Refactoring of prop/ieee-mode

This commit is contained in:
Edvard Pettersen 2018-06-19 14:55:18 +02:00
parent 12a6eefa85
commit d312dd9ebb
4 changed files with 439 additions and 443 deletions

View File

@ -45,12 +45,13 @@
#define RADIO_DELAY_BEFORE_DETECT ((unsigned)US_TO_RTIMERTICKS(352))
/* Timer conversion; radio is running at 4 MHz */
#define RADIO_TIMER_SECOND 4000000u
#if (RTIMER_SECOND % 256) || (RADIO_TIMER_SECOND % 256)
#error RADIO_TO_RTIMER macro must be fixed!
#define RAT_SECOND 4000000u
#define RAT_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RAT_SECOND / 256)))
#define USEC_TO_RAT(X) ((X) * 4)
#if (RTIMER_SECOND % 256) || (RAT_SECOND % 256)
# error RAT_TO_RTIMER macro must be fixed!
#endif
#define RADIO_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RADIO_TIMER_SECOND / 256)))
#define USEC_TO_RADIO(X) ((X) * 4)
/* The PHY header (preamble + SFD, 4+1 bytes) duration is equivalent to 10 symbols */
#define RADIO_IEEE_802154_PHY_HEADER_DURATION_USEC 160

View File

@ -45,11 +45,15 @@
#define RADIO_DELAY_BEFORE_DETECT ((unsigned)US_TO_RTIMERTICKS(352))
/* Timer conversion; radio is running at 4 MHz */
#define RADIO_TIMER_SECOND 4000000u
#if (RTIMER_SECOND % 256) || (RADIO_TIMER_SECOND % 256)
#error RADIO_TO_RTIMER macro must be fixed!
/* Timer conversion; radio is running at 4 MHz */
#define RAT_SECOND 4000000u
#define RAT_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RAT_SECOND / 256)))
#define USEC_TO_RAT(X) ((X) * 4)
#if (RTIMER_SECOND % 256) || (RAT_SECOND % 256)
# error RAT_TO_RTIMER macro must be fixed!
#endif
#define RADIO_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RADIO_TIMER_SECOND / 256)))
#define USEC_TO_RADIO(X) ((X) * 4)
/* The PHY header (preamble + SFD, 4+1 bytes) duration is equivalent to 10 symbols */

File diff suppressed because it is too large Load Diff

View File

@ -100,21 +100,14 @@
# define PROP_MODE_USE_CRC16 0
#endif
/*---------------------------------------------------------------------------*/
/* Used for the return value of channel_clear */
#define RF_CCA_CLEAR 1
#define RF_CCA_BUSY 0
/* Used for checking result of CCA_REQ command */
#define CCA_STATE_IDLE 0
#define CCA_STATE_BUSY 1
#define CCA_STATE_INVALID 2
/* Used as an error return value for get_cca_info */
#define RF_GET_CCA_INFO_ERROR 0xFF
/*
* Values of the individual bits of the ccaInfo field in CMD_IEEE_CCA_REQ's
* status struct
*/
#define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 0b00 */
#define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 0b01 */
#define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 0b10 */
#ifdef PROP_MODE_CONF_RSSI_THRESHOLD
# define PROP_MODE_RSSI_THRESHOLD PROP_MODE_CONF_RSSI_THRESHOLD
#else
@ -159,12 +152,12 @@
#endif
/*---------------------------------------------------------------------------*/
/* TX power table convenience macros */
#define TX_POWER_TABLE_SIZE ((sizeof(TX_POWER_TABLE) / sizeof(TX_POWER_TABLE[0])) - 1)
#define TX_POWER_TABLE_SIZE ((sizeof(TX_POWER_TABLE) / sizeof(TX_POWER_TABLE[0])) - 1)
#define TX_POWER_MIN (TX_POWER_TABLE[0].power)
#define TX_POWER_MAX (TX_POWER_TABLE[TX_POWER_TABLE_SIZE - 1].power)
#define TX_POWER_MIN (TX_POWER_TABLE[0].power)
#define TX_POWER_MAX (TX_POWER_TABLE[TX_POWER_TABLE_SIZE - 1].power)
#define TX_POWER_IN_RANGE(dbm) (((dbm) >= TX_POWER_MIN) && ((dbm) <= TX_POWER_MAX))
#define TX_POWER_IN_RANGE(dbm) ((TX_POWER_MIN <= (dbm)) && ((dbm) <= TX_POWER_MAX))
/*---------------------------------------------------------------------------*/
/* TX buf configuration */
#define TX_BUF_HDR_LEN 2
@ -181,14 +174,10 @@
#define RX_BUF_SIZE 140
/*---------------------------------------------------------------------------*/
#define DATA_ENTRY_LENSZ_NONE 0 /* 0 bytes */
#define DATA_ENTRY_LENSZ_BYTE 1 /* 1 byte */
#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
/* Size of the Length field in Data Entry, two bytes in this case */
typedef uint16_t lensz_t;
#define DATA_ENTRY_LENSZ DATA_ENTRY_LENSZ_WORD
typedef uint16_t lensz_t;
#define FRAME_OFFSET DATA_ENTRY_LENSZ
#define FRAME_OFFSET sizeof(lensz_t)
#define FRAME_SHAVE 2 /* RSSI (1) + Status (1) */
/*---------------------------------------------------------------------------*/
#define MAC_RADIO_RECEIVER_SENSITIVITY_DBM -110
@ -199,8 +188,12 @@ typedef uint16_t lensz_t;
#define ED_RF_POWER_MIN_DBM (MAC_RADIO_RECEIVER_SENSITIVITY_DBM + MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY)
#define ED_RF_POWER_MAX_DBM MAC_RADIO_RECEIVER_SATURATION_DBM
/*---------------------------------------------------------------------------*/
/* RF Core typedefs */
typedef dataQueue_t data_queue_t;
typedef rfc_dataEntryGeneral_t data_entry_t;
typedef rfc_propRxOutput_t rx_output_t;
/* Receive buffer entries with room for 1 IEEE 802.15.4 frame in each */
typedef union {
data_entry_t data_entry;
uint8_t buf[RX_BUF_SIZE];
@ -209,13 +202,13 @@ typedef union {
typedef struct {
/* Outgoing frame buffer */
uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
/* Incoming frame buffer */
/* Incoming frame buffers */
rx_buf_t rx_bufs[RX_BUF_CNT];
/* RX Data Queue */
dataQueue_t rx_data_queue;
data_queue_t rx_data_queue;
/* RX Statistics struct */
rfc_propRxOutput_t rx_stats;
rx_output_t rx_stats;
/* Receive entry pointer to keep track of read items */
data_entry_t* rx_read_entry;
@ -300,7 +293,7 @@ stop_rx(void)
static cmd_result_t
rf_run_setup()
{
// TODO not the right way to do this.
/* TODO not the right way to do this. */
RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_radio_setup, RF_PriorityNormal, NULL, 0);
if (cmd_radio_setup.status != PROP_DONE_OK) {
return CMD_RESULT_ERROR;
@ -352,22 +345,21 @@ get_channel(void)
}
/*---------------------------------------------------------------------------*/
static cmd_result_t
set_channel(uint8_t channel)
set_channel(uint32_t channel)
{
uint32_t new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING);
uint16_t freq = (uint16_t)(new_freq / 1000);
uint16_t frac = (new_freq - (freq * 1000)) * 65536 / 1000;
const uint32_t new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING);
const uint32_t freq = new_freq / 1000;
const uint32_t frac = ((new_freq - (freq * 1000)) * 65536) / 1000;
PRINTF("set_channel: %u = 0x%04x.0x%04x (%lu)\n",
channel, freq, frac, new_freq);
(int)channel, (uint16_t)freq, (uint16_t)frac, new_freq);
cmd_radio_setup.centerFreq = freq;
cmd_fs.frequency = freq;
cmd_fs.fractFreq = frac;
cmd_fs.frequency = (uint16_t)freq;
cmd_fs.fractFreq = (uint16_t)frac;
// We don't care whether the FS command is successful because subsequent
// TX and RX commands will tell us indirectly.
/* We don't care whether the FS command is successful because subsequent */
/* TX and RX commands will tell us indirectly. */
RF_EventMask rf_events = RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_fs,
RF_PriorityNormal, NULL, 0);
if ((rf_events & (RF_EventCmdDone | RF_EventLastCmdDone)) == 0) {
@ -384,6 +376,22 @@ set_channel(uint8_t channel)
}
/*---------------------------------------------------------------------------*/
/* Returns the current TX power in dBm */
static radio_result_t
set_tx_power(const radio_value_t dBm)
{
if (!TX_POWER_IN_RANGE(dBm)) {
return RADIO_RESULT_INVALID_VALUE;
}
const RF_TxPowerTable_Value value = RF_TxPowerTable_findValue(TX_POWER_TABLE, (int8_t)dBm);
const RF_Stat stat = RF_setTxPower(prop_radio.rf_handle, value);
return (stat == RF_StatSuccess)
? RADIO_RESULT_OK
: RADIO_RESULT_ERROR;
}
/*---------------------------------------------------------------------------*/
/* Returns the current TX power in dBm */
static radio_value_t
get_tx_power(void)
{
@ -391,24 +399,6 @@ get_tx_power(void)
return (radio_value_t)RF_TxPowerTable_findPowerLevel(TX_POWER_TABLE, value);
}
/*---------------------------------------------------------------------------*/
/*
* The caller must make sure to send a new CMD_PROP_RADIO_DIV_SETUP to the
* radio after calling this function.
*/
static radio_result_t
set_tx_power(const radio_value_t power)
{
if (!TX_POWER_IN_RANGE(power)) {
return RADIO_RESULT_INVALID_VALUE;
}
const RF_TxPowerTable_Value value = RF_TxPowerTable_findValue(TX_POWER_TABLE, power);
RF_Stat stat = RF_setTxPower(prop_radio.rf_handle, value);
return (stat == RF_StatSuccess)
? RADIO_RESULT_OK
: RADIO_RESULT_ERROR;
}
/*---------------------------------------------------------------------------*/
static uint8_t
calculate_lqi(int8_t rssi)
{
@ -432,7 +422,7 @@ init_rx_buffers(void)
const data_entry_t data_entry = {
.status = DATA_ENTRY_PENDING,
.config.type = DATA_ENTRY_TYPE_GEN,
.config.lenSz = DATA_ENTRY_LENSZ,
.config.lenSz = sizeof(lensz_t),
.length = RX_BUF_SIZE - sizeof(data_entry_t), /* TODO: is this sizeof sound? */
/* Point to fist entry if this is last entry, else point to next entry */
.pNextEntry = (i == (RX_BUF_CNT - 1))
@ -493,7 +483,7 @@ transmit(unsigned short transmit_len)
ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
// watchdog_periodic();
/* watchdog_periodic(); */
/* Idle away while the command is running */
RF_EventMask rf_events = RF_pendCmd(prop_radio.rf_handle, tx_handle, RF_EventLastCmdDone);
@ -535,7 +525,7 @@ release_data_entry(void)
data_entry_t *const data_entry = prop_radio.rx_read_entry;
uint8_t *const frame_ptr = (uint8_t*)&data_entry->data;
// Clear the Length byte(s) and set status to 0: "Pending"
/* Clear the Length byte(s) and set status to 0: "Pending" */
*(lensz_t*)frame_ptr = 0;
data_entry->status = DATA_ENTRY_PENDING;
prop_radio.rx_read_entry = (data_entry_t*)data_entry->pNextEntry;
@ -547,12 +537,12 @@ read(void *buf, unsigned short buf_len)
volatile data_entry_t *data_entry = prop_radio.rx_read_entry;
const rtimer_clock_t t0 = RTIMER_NOW();
// Only wait if the Radio timer is accessing the entry
/* Only wait if the Radio timer is accessing the entry */
while ((data_entry->status == DATA_ENTRY_BUSY) &&
RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY));
if (data_entry->status != DATA_ENTRY_FINISHED) {
// No available data
/* No available data */
return 0;
}
@ -612,7 +602,7 @@ channel_clear(void)
{
if (tx_active()) {
PRINTF("channel_clear: called while in TX\n");
return RF_CCA_CLEAR;
return CCA_STATE_IDLE;
}
const bool rx_was_off = !rx_active();
@ -630,10 +620,10 @@ channel_clear(void)
}
if(rssi >= prop_radio.rssi_threshold) {
return RF_CCA_BUSY;
return CCA_STATE_BUSY;
}
return RF_CCA_CLEAR;
return CCA_STATE_IDLE;
}
/*---------------------------------------------------------------------------*/
static int
@ -643,7 +633,7 @@ receiving_packet(void)
return 0;
}
if (channel_clear() == RF_CCA_CLEAR) {
if (channel_clear() == CCA_STATE_IDLE) {
return 0;
}
@ -653,28 +643,29 @@ receiving_packet(void)
static int
pending_packet(void)
{
const rfc_dataEntry_t *const first_entry = (rfc_dataEntry_t *)prop_radio.rx_data_queue.pCurrEntry;
volatile const rfc_dataEntry_t *entry = first_entry;
const data_entry_t *const read_entry = prop_radio.rx_read_entry;
volatile const data_entry_t *curr_entry = read_entry;
int rv = 0;
int num_pending = 0;
/* Go through RX Circular buffer and check their status */
do {
const uint8_t status = entry->status;
const uint8_t status = curr_entry->status;
if ((status == DATA_ENTRY_FINISHED) ||
(status == DATA_ENTRY_BUSY)) {
rv += 1;
num_pending += 1;
}
entry = (rfc_dataEntry_t *)entry->pNextEntry;
} while (entry != first_entry);
/* Stop when we have looped the circular buffer */
curr_entry = (data_entry_t *)curr_entry->pNextEntry;
} while (curr_entry != read_entry);
if (rv > 0) {
if (num_pending > 0) {
process_poll(&rf_process);
}
/* If we didn't find an entry at status finished, no frames are pending */
return rv;
return num_pending;
}
/*---------------------------------------------------------------------------*/
static int
@ -710,18 +701,12 @@ off(void)
return CMD_RESULT_OK;
}
// Force abort of any ongoing RF operation.
/* Force abort of any ongoing RF operation */
RF_flushCmd(prop_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
// Trigger a manual power-down
/* Trigger a manual power-down */
RF_yield(prop_radio.rf_handle);
/* We pulled the plug, so we need to restore the status manually */
cmd_fs.status = IDLE;
cmd_tx.status = IDLE;
cmd_rx.status = IDLE;
// Reset RX buffers if there was an ongoing RX
/* Reset RX buffers if there was an ongoing RX */
size_t i;
for (i = 0; i < RX_BUF_CNT; ++i) {
data_entry_t *entry = &prop_radio.rx_bufs[i].data_entry;
@ -795,7 +780,7 @@ set_value(radio_param_t param, radio_value_t value)
switch(param) {
case RADIO_PARAM_POWER_MODE:
if(value == RADIO_POWER_MODE_ON) {
// Powering on happens implicitly
/* Powering on happens implicitly */
return RADIO_RESULT_OK;
}
if(value == RADIO_POWER_MODE_OFF) {
@ -836,19 +821,19 @@ set_value(radio_param_t param, radio_value_t value)
/* If we reach here we had no errors. Apply new settings */
if (rx_active()) {
stop_rx();
// TODO fix this
/* TODO fix this */
if (rf_run_setup() != CMD_RESULT_OK) {
return RADIO_RESULT_ERROR;
}
start_rx();
} else if (tx_active()) {
// Should not happen. TX is always synchronous and blocking.
// Todo: maybe remove completely here.
/* Should not happen. TX is always synchronous and blocking. */
/* Todo: maybe remove completely here. */
PRINTF("set_value: cannot apply new value while transmitting. \n");
return RADIO_RESULT_ERROR;
} else {
// was powered off. Nothing to do. New values will be
// applied automatically on next power-up.
/* was powered off. Nothing to do. New values will be */
/* applied automatically on next power-up. */
}
return RADIO_RESULT_OK;
@ -869,6 +854,11 @@ set_object(radio_param_t param, const void *src, size_t size)
static int
init(void)
{
if (prop_radio.rf_handle) {
PRINTF("init: Radio already initialized\n");
return CMD_RESULT_OK;
}
/* Zero initalize TX and RX buffers */
memset(prop_radio.tx_buf, 0x0, sizeof(prop_radio.tx_buf));
memset(prop_radio.rx_bufs, 0x0, sizeof(prop_radio.rx_bufs));
@ -894,12 +884,13 @@ init(void)
/* Init RF params and specify non-default params */
RF_Params rf_params;
RF_Params_init(&rf_params);
rf_params.nInactivityTimeout = 2000; /* 2 ms */
rf_params.nInactivityTimeout = 2000; /* 2 ms */
/* Open RF Driver */
prop_radio.rf_handle = RF_open(&prop_radio.rf_object, &rf_prop_mode,
(RF_RadioSetup*)&cmd_radio_setup, &rf_params);
if (prop_radio.rf_handle == NULL) {
PRINTF("init: unable to open RF driver\n");
return CMD_RESULT_ERROR;
}