From d312dd9ebb2bd7fd33781aa3d8b7084dcd200012 Mon Sep 17 00:00:00 2001 From: Edvard Pettersen Date: Tue, 19 Jun 2018 14:55:18 +0200 Subject: [PATCH] Refactoring of prop/ieee-mode --- .../cc13x0-cc26x0/cc13xx-cc26xx-def.h | 11 +- .../cc13x2-cc26x2/cc13xx-cc26xx-def.h | 12 +- arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c | 692 +++++++++--------- arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c | 167 ++--- 4 files changed, 439 insertions(+), 443 deletions(-) diff --git a/arch/cpu/cc13xx-cc26xx/cc13x0-cc26x0/cc13xx-cc26xx-def.h b/arch/cpu/cc13xx-cc26xx/cc13x0-cc26x0/cc13xx-cc26xx-def.h index 563bbff56..41eee3d87 100644 --- a/arch/cpu/cc13xx-cc26xx/cc13x0-cc26x0/cc13xx-cc26xx-def.h +++ b/arch/cpu/cc13xx-cc26xx/cc13x0-cc26x0/cc13xx-cc26xx-def.h @@ -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 diff --git a/arch/cpu/cc13xx-cc26xx/cc13x2-cc26x2/cc13xx-cc26xx-def.h b/arch/cpu/cc13xx-cc26xx/cc13x2-cc26x2/cc13xx-cc26xx-def.h index 7d54aa45a..507db4470 100644 --- a/arch/cpu/cc13xx-cc26xx/cc13x2-cc26x2/cc13xx-cc26xx-def.h +++ b/arch/cpu/cc13xx-cc26xx/cc13x2-cc26x2/cc13xx-cc26xx-def.h @@ -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 */ diff --git a/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c b/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c index e9443a68e..dfe3a0d3c 100644 --- a/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c +++ b/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c @@ -55,11 +55,11 @@ #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h) #include DeviceFamily_constructPath(driverlib/rf_data_entry.h) #include DeviceFamily_constructPath(driverlib/rf_mailbox.h) -// rf_ieee_cmd and rf_ieee_mailbox included by RF settings because of the -// discrepancy between CC13x0 and CC13x2 IEEE support. CC13x0 doesn't provide -// RFCore definitions of IEEE commandos, and are therefore included locally -// from the Contiki build system. CC13x2 includes these normally from driverlib. -// This is taken care of RF settings. +/* rf_ieee_cmd and rf_ieee_mailbox included by RF settings because of the + * discrepancy between CC13x0 and CC13x2 IEEE support. CC13x0 doesn't provide + * RFCore definitions of IEEE commandos, and are therefore included locally + * from the Contiki build system. CC13x2 includes these normally from driverlib. + * This is taken care of RF settings. */ #include /*---------------------------------------------------------------------------*/ @@ -81,7 +81,6 @@ #include #include #include -#include /*---------------------------------------------------------------------------*/ /* Log configuration */ #include "sys/log.h" @@ -138,8 +137,8 @@ #endif /*---------------------------------------------------------------------------*/ /* TX power table convenience macros */ -#define TX_POWER_MIN (TX_POWER_TABLE[0]) -#define TX_POWER_MAX (TX_POWER_TABLE[TX_POWER_TABLE_SIZE - 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_IN_RANGE(dbm) (((dbm) >= TX_POWER_MIN) && ((dbm) <= TX_POWER_MAX)) /*---------------------------------------------------------------------------*/ @@ -161,65 +160,26 @@ /*---------------------------------------------------------------------------*/ /* Timeout constants */ -/* How long to wait for an ongoing ACK TX to finish before starting frame TX */ -#define TIMEOUT_TX_WAIT (RTIMER_SECOND >> 11) - -/* How long to wait for the RF to enter RX in cmd_rx */ -#define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10) - -/* How long to wait for the RF to react on CMD_ABORT: around 1 msec */ -#define TIMEOUT_RF_TURN_OFF_WAIT (RTIMER_SECOND >> 10) - -/* How long to wait for the RF to finish TX of a packet or an ACK */ -#define TIMEOUT_TX_FINISH_WAIT (RTIMER_SECOND >> 7) - /* How long to wait for the rx read entry to become ready */ #define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250) /*---------------------------------------------------------------------------*/ -#define CCA_STATE_IDLE 0 -#define CCA_STATE_BUSY 1 -#define CCA_STATE_INVALID 2 +#define RAT_RANGE (~(uint32_t)0) +#define RAT_ONE_QUARTER (RAT_RANGE / (uint32_t)4) +#define RAT_THREE_QUARTERS ((RAT_RANGE * (uint32_t)3) / (uint32_t)4) + +/* XXX: don't know what exactly is this, looks like the time to TX 3 octets */ +#define RAT_TIMESTAMP_OFFSET -(USEC_TO_RADIO(32 * 3) - 1) /* -95.75 usec */ /*---------------------------------------------------------------------------*/ -/* TI-RTOS RF driver object */ -static RF_Object g_rfObj; -static RF_Handle g_rfHandle; - -/* RF Core command pointers */ -#define cmd_radio_setup (*(volatile rfc_CMD_RADIO_SETUP_t*)&rf_cmd_ieee_radio_setup) -#define cmd_fs (*(volatile rfc_CMD_FS_t*) &rf_cmd_ieee_fs) -#define cmd_tx (*(volatile rfc_CMD_IEEE_TX_t*) &rf_cmd_ieee_tx) -#define cmd_rx (*(volatile rfc_CMD_IEEE_RX_t*) &rf_cmd_ieee_rx) - -/* RF command handles */ -static RF_CmdHandle g_cmdTxHandle; -static RF_CmdHandle g_cmdRxHandle; - -/* Global RF Core commands */ -static rfc_CMD_IEEE_MOD_FILT_t g_cmdModFilt; - -/* RF stats data structure */ -static rfc_ieeeRxOutput_t g_rxStats; +#define STATUS_CORRELATION 0x3f /* bits 0-5 */ +#define STATUS_REJECT_FRAME 0x40 /* bit 6 */ +#define STATUS_CRC_FAIL 0x80 /* bit 7 */ /*---------------------------------------------------------------------------*/ -/* The outgoing frame buffer */ -#define TX_BUF_PAYLOAD_LEN 180 +/* TX buf configuration */ #define TX_BUF_HDR_LEN 2 +#define TX_BUF_PAYLOAD_LEN 180 -static uint8_t g_txBuf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4); -/*---------------------------------------------------------------------------*/ -/* RX Data Queue */ -static dataQueue_t g_rxDataQueue; -/*---------------------------------------------------------------------------*/ -/* Constants for receive buffers */ -#define DATA_ENTRY_LENSZ_NONE 0 -#define DATA_ENTRY_LENSZ_BYTE 1 -#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */ +#define TX_BUF_SIZE (TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN) -#define DATA_ENTRY_LENSZ DATA_ENTRY_LENSZ_BYTE -typedef uint8_t lensz_t; - -#define FRAME_OFFSET DATA_ENTRY_LENSZ -#define FRAME_SHAVE 8 /* FCS (2) + RSSI (1) + Status (1) + Timestamp (4) */ -/*---------------------------------------------------------------------------*/ /* RX buf configuration */ #ifdef IEEE_MODE_CONF_RX_BUF_CNT # define RX_BUF_CNT IEEE_MODE_CONF_RX_BUF_CNT @@ -228,48 +188,19 @@ typedef uint8_t lensz_t; #endif #define RX_BUF_SIZE 144 - -/* Receive buffer entries with room for 1 IEEE 802.15.4 frame in each */ -typedef rfc_dataEntryGeneral_t data_entry_t; - -typedef union { - data_entry_t data_entry; - uint8_t buf[RX_BUF_SIZE]; -} rx_buf_t CC_ALIGN(4); - -static rx_buf_t rx_bufs[RX_BUF_CNT]; - -/* Receive entry pointer to keep track of read items */ -static data_entry_t *rx_read_entry; /*---------------------------------------------------------------------------*/ -/* RAT overflow upkeep */ -static struct ctimer g_ratOverflowTimer; -static rtimer_clock_t g_ratLastOverflow; -static volatile uint32_t g_ratOverflowCount; +/* Size of the Length representation in Data Entry, one byte in this case */ +typedef uint8_t lensz_t; -#define RAT_RANGE (~(uint32_t)0) -#define RAT_OVERFLOW_PERIOD_SECONDS (RAT_RANGE / (uint32_t)RADIO_TIMER_SECOND) -/* XXX: don't know what exactly is this, looks like the time to TX 3 octets */ -#define RAT_TIMESTAMP_OFFSET -(USEC_TO_RADIO(32 * 3) - 1) /* -95.75 usec */ +#define FRAME_OFFSET sizeof(lensz_t) +#define FRAME_SHAVE 8 /* FCS (2) + RSSI (1) + Status (1) + Timestamp (4) */ /*---------------------------------------------------------------------------*/ -#define STATUS_CORRELATION 0x3f // bits 0-5 -#define STATUS_REJECT_FRAME 0x40 // bit 6 -#define STATUS_CRC_FAIL 0x80 // bit 7 -/*---------------------------------------------------------------------------*/ -#define CHANNEL_CLEAR_ERROR -1 -/*---------------------------------------------------------------------------*/ -/* Global state */ - -/* Are we currently in poll mode? */ -static volatile bool g_bPollMode = false; - -/* Enable/disable CCA before sending */ -static volatile bool g_bSendOnCca = false; - -/* Last RX operation stats */ -static volatile int8_t g_lastRssi; -static volatile uint8_t g_lastCorrLqi; -static volatile uint32_t g_lastTimestamp; +/* Used for checking result of CCA_REQ command */ +typedef enum { + CCA_STATE_IDLE = 0, + CCA_STATE_BUSY = 1, + CCA_STATE_INVALID = 2 +} cca_state_t; /*---------------------------------------------------------------------------*/ typedef enum { POWER_STATE_ON = (1 << 0), @@ -277,10 +208,75 @@ typedef enum { POWER_STATE_RESTART = POWER_STATE_ON | POWER_STATE_OFF, } PowerState; /*---------------------------------------------------------------------------*/ +/* RF Core typedefs */ +typedef dataQueue_t data_queue_t; +typedef rfc_dataEntryGeneral_t data_entry_t; +typedef rfc_ieeeRxOutput_t rx_output_t; +typedef rfc_CMD_IEEE_MOD_FILT_t cmd_mod_filt_t; +typedef rfc_CMD_IEEE_CCA_REQ_t cmd_cca_req_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]; +} rx_buf_t CC_ALIGN(4); + +typedef struct { + /* Outgoing frame buffer */ + uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4); + /* Ingoing frame buffers */ + rx_buf_t rx_bufs[RX_BUF_CNT]; + + /* RX Data Queue */ + data_queue_t rx_data_queue; + /* RF Statistics struct */ + rx_output_t rx_stats; + /* Receive entry pointer to keep track of read items */ + data_entry_t* rx_read_entry; + + /* Indicates RF is supposed to be on or off */ + bool rf_is_on; + /* Enable/disable CCA before sending */ + bool send_on_cca; + /* Are we currently in poll mode? */ + bool poll_mode; + + /* Last RX operation stats */ + struct { + int8_t rssi; + uint8_t corr_lqi; + uint32_t timestamp; + } last; + + /* RAT Overflow Upkeep */ + struct { + struct ctimer overflow_timer; + rtimer_clock_t last_overflow; + volatile uint32_t overflow_count; + } rat; + + /* RF driver */ + RF_Object rf_object; + RF_Handle rf_handle; +} ieee_radio_t; + +static ieee_radio_t ieee_radio; + +/* Global RF Core commands */ +static cmd_mod_filt_t cmd_mod_filt; +/*---------------------------------------------------------------------------*/ +/* RF Command volatile objects */ +#define cmd_radio_setup (*(volatile rfc_CMD_RADIO_SETUP_t*)&rf_cmd_ieee_radio_setup) +#define cmd_fs (*(volatile rfc_CMD_FS_t*) &rf_cmd_ieee_fs) +#define cmd_tx (*(volatile rfc_CMD_IEEE_TX_t*) &rf_cmd_ieee_tx) +#define cmd_rx (*(volatile rfc_CMD_IEEE_RX_t*) &rf_cmd_ieee_rx) +/*---------------------------------------------------------------------------*/ +static CC_INLINE bool tx_active(void) { return cmd_tx.status == ACTIVE; } +static CC_INLINE bool rx_active(void) { return cmd_rx.status == ACTIVE; } +/*---------------------------------------------------------------------------*/ /* Forward declarations of static functions */ static int set_rx(const PowerState); static void check_rat_overflow(void); -static bool rf_is_on(void); static uint32_t rat_to_timestamp(const uint32_t); /*---------------------------------------------------------------------------*/ /* Forward declarations of Radio driver functions */ @@ -318,43 +314,34 @@ const struct radio_driver ieee_mode_driver = { }; /*---------------------------------------------------------------------------*/ static void -rx_cb(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) +rx_cb(RF_Handle client, RF_CmdHandle command, RF_EventMask events) { - if (e & RF_EventRxOk) { + /* Unused arguments */ + (void)client; + (void)command; + + if (events & RF_EventRxOk) { process_poll(&rf_process); } } /*---------------------------------------------------------------------------*/ static void -rf_error_cb(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) -{ - // See SWRZ062B: Synth failed to calibrate, CMD_FS must be repeated - if ((ch == RF_ERROR_CMDFS_SYNTH_PROG) && - (cmd_fs.status == ERROR_SYNTH_PROG)) { - // Call CMD_FS async, a synth error will trigger rf_error_cb once more - const uint8_t stop_gracefully = 1; - RF_flushCmd(g_rfHandle, RF_CMDHANDLE_FLUSH_ALL, stop_gracefully); - RF_postCmd(g_rfHandle, (RF_Op*)&cmd_fs, RF_PriorityNormal, NULL, 0); - } -} -/*---------------------------------------------------------------------------*/ -static void rat_overflow_cb(void *arg) { check_rat_overflow(); - // Check next time after half of the RAT interval - ctimer_set(&g_ratOverflowTimer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, - rat_overflow_cb, NULL); + /* Check next time after half of the RAT interval */ + const clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND; + ctimer_set(&ieee_radio.rat.overflow_timer, two_quarters, rat_overflow_cb, NULL); } /*---------------------------------------------------------------------------*/ static void init_data_queue(void) { - // Initialize RF core data queue, circular buffer - g_rxDataQueue.pCurrEntry = rx_bufs[0].buf; - g_rxDataQueue.pLastEntry = NULL; - // Set current read pointer to first element - rx_read_entry = &rx_bufs[0].data_entry; + /* Initialize RF core data queue, circular buffer */ + ieee_radio.rx_data_queue.pCurrEntry = ieee_radio.rx_bufs[0].buf; + ieee_radio.rx_data_queue.pLastEntry = NULL; + /* Set current read pointer to first element */ + ieee_radio.rx_read_entry = &ieee_radio.rx_bufs[0].data_entry; } /*---------------------------------------------------------------------------*/ static void @@ -362,8 +349,8 @@ init_rf_params(void) { cmd_rx.channel = IEEE_MODE_CHANNEL; - cmd_rx.pRxQ = &g_rxDataQueue; - cmd_rx.pOutput = &g_rxStats; + cmd_rx.pRxQ = &ieee_radio.rx_data_queue; + cmd_rx.pOutput = &ieee_radio.rx_stats; #if IEEE_MODE_PROMISCOUS cmd_rx.frameFiltOpt.frameFiltEn = 0; @@ -379,10 +366,10 @@ init_rf_params(void) cmd_rx.ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD; - // Initialize address filter command - g_cmdModFilt.commandNo = CMD_IEEE_MOD_FILT; - memcpy(&(g_cmdModFilt.newFrameFiltOpt), &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt)); - memcpy(&(g_cmdModFilt.newFrameTypes), &(rf_cmd_ieee_rx.frameTypes), sizeof(rf_cmd_ieee_rx.frameTypes)); + /* Initialize address filter command */ + cmd_mod_filt.commandNo = CMD_IEEE_MOD_FILT; + memcpy(&(cmd_mod_filt.newFrameFiltOpt), &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt)); + memcpy(&(cmd_mod_filt.newFrameTypes), &(rf_cmd_ieee_rx.frameTypes), sizeof(rf_cmd_ieee_rx.frameTypes)); } /*---------------------------------------------------------------------------*/ static void @@ -393,56 +380,55 @@ 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, - .length = RX_BUF_SIZE - sizeof(data_entry_t), /* TODO: is this sizeof sound? */ + .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)) - ? rx_bufs[0].buf - : rx_bufs[i].buf + ? ieee_radio.rx_bufs[0].buf + : ieee_radio.rx_bufs[i].buf }; - rx_bufs[i].data_entry = data_entry; + ieee_radio.rx_bufs[i].data_entry = data_entry; } } /*---------------------------------------------------------------------------*/ -static bool -set_channel(uint8_t channel) +static cmd_result_t +set_channel(uint32_t channel) { if (!IEEE_MODE_CHAN_IN_RANGE(channel)) { PRINTF("set_channel: illegal channel %d, defaults to %d\n", - channel, IEEE_MODE_CHANNEL); + (int)channel, IEEE_MODE_CHANNEL); channel = IEEE_MODE_CHANNEL; } if (channel == cmd_rx.channel) { - // We are already calibrated to this channel + /* We are already calibrated to this channel */ return true; } cmd_rx.channel = 0; - // freq = freq_base + freq_spacing * (channel - channel_min) - const uint32_t newFreq = (uint32_t)(IEEE_MODE_FREQ_BASE + IEEE_MODE_FREQ_SPACING * ((uint32_t)channel - IEEE_MODE_CHAN_MIN)); - const uint32_t freq = newFreq / 1000; - const uint32_t frac = (newFreq - (freq * 1000)) * 65536 / 1000; + /* freq = freq_base + freq_spacing * (channel - channel_min) */ + const uint32_t new_freq = IEEE_MODE_FREQ_BASE + IEEE_MODE_FREQ_SPACING * (channel - IEEE_MODE_CHAN_MIN); + const uint32_t freq = new_freq / 1000; + const uint32_t frac = ((new_freq - (freq * 1000)) * 65536) / 1000; PRINTF("set_channel: %d = 0x%04X.0x%04X (%lu)\n", - channel, (uint16_t)freq, (uint16_t)frac, newFreq); + (int)channel, (uint16_t)freq, (uint16_t)frac, new_freq); cmd_fs.frequency = (uint16_t)freq; cmd_fs.fractFreq = (uint16_t)frac; - const bool rx_active = (cmd_rx.status == ACTIVE); + const bool was_on = rx_active(); - if (rx_active) { - const uint8_t stop_gracefully = 1; - RF_flushCmd(g_rfHandle, RF_CMDHANDLE_FLUSH_ALL, stop_gracefully); + if (was_on) { + RF_flushCmd(ieee_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY); } - // Start FS command asynchronously. We don't care when it is finished + /* Start FS command asynchronously. We don't care when it is finished */ RF_EventMask events = 0; uint8_t tries = 0; bool cmd_ok = false; do { - events = RF_runCmd(g_rfHandle, (RF_Op*)&cmd_fs, RF_PriorityNormal, NULL, 0); + events = RF_runCmd(ieee_radio.rf_handle, (RF_Op*)&cmd_fs, RF_PriorityNormal, NULL, 0); cmd_ok = ((events & RF_EventLastCmdDone) != 0) && (cmd_fs.status == DONE_OK); } while (!cmd_ok && (tries++ < 3)); @@ -453,120 +439,133 @@ set_channel(uint8_t channel) cmd_rx.channel = channel; - if (rx_active) { + if (was_on) { set_rx(POWER_STATE_ON); } return true; } /*---------------------------------------------------------------------------*/ -static int -set_tx_power(const radio_value_t dbm) +static radio_result_t +set_tx_power(const radio_value_t dBm) { - const RF_TxPowerTable_Value tx_power_table_value = RF_TxPowerTable_findValue(TX_POWER_TABLE, (int8_t)dbm); - const RF_Stat stat = RF_setTxPower(g_rfHandle, tx_power_table_value); - - if (stat != RF_StatSuccess) { - PRINTF("set_tx_power: stat=0x%02X\n", stat); - return CMD_RESULT_ERROR; + if (!TX_POWER_IN_RANGE(dBm)) { + return RADIO_RESULT_INVALID_VALUE; } - return CMD_RESULT_OK; + + const RF_TxPowerTable_Value tx_power_table_value = RF_TxPowerTable_findValue(TX_POWER_TABLE, (int8_t)dBm); + const RF_Stat stat = RF_setTxPower(ieee_radio.rf_handle, tx_power_table_value); + + return (stat == RF_StatSuccess) + ? RADIO_RESULT_OK + : RADIO_RESULT_ERROR; } /*---------------------------------------------------------------------------*/ static radio_value_t get_tx_power(void) { - const RF_TxPowerTable_Value tx_power_table_value = RF_getTxPower(g_rfHandle); - const int8_t dbm = RF_TxPowerTable_findPowerLevel(TX_POWER_TABLE, tx_power_table_value); - - if (dbm == RF_TxPowerTable_INVALID_DBM) { - PRINTF("get_tx_power: invalid dbm received=%d\n", dbm); - } - - return (radio_value_t)dbm; + const RF_TxPowerTable_Value value = RF_getTxPower(ieee_radio.rf_handle); + return (radio_value_t)RF_TxPowerTable_findPowerLevel(TX_POWER_TABLE, value); } /*---------------------------------------------------------------------------*/ static void set_send_on_cca(bool enable) { - g_bSendOnCca = enable; + ieee_radio.send_on_cca = enable; } /*---------------------------------------------------------------------------*/ static void check_rat_overflow(void) { - const bool was_off = !rf_is_on(); - if (was_off) { - RF_runDirectCmd(g_rfHandle, CMD_NOP); - } - const uint32_t currentValue = RF_getCurrentTime(); + const bool was_off = !rx_active(); - static uint32_t lastValue; - static bool bFirstTime = true; - if (bFirstTime) { - // First time checking overflow will only store the current value - bFirstTime = false; + if (was_off) { + RF_runDirectCmd(ieee_radio.rf_handle, CMD_NOP); + } + + const uint32_t current_value = RF_getCurrentTime(); + + static bool initial_iteration = true; + static uint32_t last_value; + + if (initial_iteration) { + /* First time checking overflow will only store the current value */ + initial_iteration = false; } else { - // Overflow happens in the last quarter of the RAT range - if (currentValue + RAT_RANGE / 4 < lastValue) { - // Overflow detected - g_ratLastOverflow = RTIMER_NOW(); - g_ratOverflowCount += 1; + /* Overflow happens in the last quarter of the RAT range */ + if ((current_value + RAT_ONE_QUARTER) < last_value) { + /* Overflow detected */ + ieee_radio.rat.last_overflow = RTIMER_NOW(); + ieee_radio.rat.overflow_count += 1; } } - lastValue = currentValue; + last_value = current_value; if (was_off) { - off(); + RF_yield(ieee_radio.rf_handle); } } /*---------------------------------------------------------------------------*/ static uint32_t -rat_to_timestamp(const uint32_t ratTimestamp) +rat_to_timestamp(const uint32_t rat_ticks) { check_rat_overflow(); - uint64_t adjustedOverflowCount = g_ratOverflowCount; + uint64_t adjusted_overflow_count = ieee_radio.rat.overflow_count; - // If the timestamp is in the 4th quarter and the last overflow was recently, - // assume that the timestamp refers to the time before the overflow - if(ratTimestamp > (uint32_t)(RAT_RANGE * 3 / 4)) { - if(RTIMER_CLOCK_LT(RTIMER_NOW(), - g_ratLastOverflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) { - adjustedOverflowCount -= 1; + /* If the timestamp is in the 4th quarter and the last overflow was recently, + * assume that the timestamp refers to the time before the overflow */ + if (rat_ticks > RAT_THREE_QUARTERS) { + const rtimer_clock_t one_quarter = (RAT_ONE_QUARTER * RTIMER_SECOND) / RAT_SECOND; + if (RTIMER_CLOCK_LT(RTIMER_NOW(), ieee_radio.rat.last_overflow + one_quarter)) { + adjusted_overflow_count -= 1; } } - // Add the overflowed time to the timestamp - const uint64_t ratTimestamp64 = (uint64_t)ratTimestamp + (uint64_t)RAT_RANGE * adjustedOverflowCount; + /* Add the overflowed time to the timestamp */ + const uint64_t rat_ticks_adjusted = (uint64_t)rat_ticks + (uint64_t)RAT_RANGE * adjusted_overflow_count; - // Correct timestamp so that it refers to the end of the SFD and convert to RTIMER - return RADIO_TO_RTIMER(ratTimestamp64 + RAT_TIMESTAMP_OFFSET); + /* Correct timestamp so that it refers to the end of the SFD and convert to RTIMER */ + return RAT_TO_RTIMER(rat_ticks_adjusted + RAT_TIMESTAMP_OFFSET); } /*---------------------------------------------------------------------------*/ static int init(void) { - RF_Params params; - RF_Params_init(¶ms); - params.pErrCb = rf_error_cb; + if (ieee_radio.rf_handle) { + PRINTF("init: Radio already initialized\n"); + return CMD_RESULT_OK; + } + + /* RX is off */ + ieee_radio.rf_is_on = false; init_rf_params(); init_data_queue(); - g_rfHandle = RF_open(&g_rfObj, &rf_ieee_mode, (RF_RadioSetup*)&cmd_radio_setup, ¶ms); - assert(g_rfHandle != NULL); + /* Init RF params and specify non-default params */ + RF_Params rf_params; + RF_Params_init(&rf_params); + rf_params.nInactivityTimeout = 2000; /* 2 ms */ + + ieee_radio.rf_handle = RF_open(&ieee_radio.rf_object, &rf_ieee_mode, + (RF_RadioSetup*)&cmd_radio_setup, &rf_params); + if (ieee_radio.rf_handle == NULL) { + PRINTF("init: unable to open RF driver\n"); + return CMD_RESULT_ERROR; + } set_channel(IEEE_MODE_CHANNEL); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - // Start RAT overflow upkeep + /* Start RAT overflow upkeep */ check_rat_overflow(); - ctimer_set(&g_ratOverflowTimer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, - rat_overflow_cb, NULL); + clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND; + ctimer_set(&ieee_radio.rat.overflow_timer, two_quarters, rat_overflow_cb, NULL); + /* Start RF process */ process_start(&rf_process, NULL); return CMD_RESULT_OK; @@ -577,28 +576,16 @@ prepare(const void *payload, unsigned short payload_len) { const size_t len = MIN((size_t)payload_len, (size_t)TX_BUF_PAYLOAD_LEN); - memcpy(&g_txBuf[TX_BUF_HDR_LEN], payload, len); + memcpy(&ieee_radio.tx_buf[TX_BUF_HDR_LEN], payload, len); return 0; } /*---------------------------------------------------------------------------*/ -static bool -rf_is_on(void) -{ - RF_InfoVal infoVal; - memset(&infoVal, 0x0, sizeof(RF_InfoVal)); - const RF_Stat stat = RF_getInfo(g_rfHandle, RF_GET_RADIO_STATE, &infoVal); - return (stat == RF_StatSuccess) - ? infoVal.bRadioState // 0: Radio OFF, 1: Radio ON - : false; -} -/*---------------------------------------------------------------------------*/ static int set_rx(const PowerState state) { if (state & POWER_STATE_OFF) { - // Stop RX gracefully, don't care about the result - const uint8_t stop_gracefully = 1; - RF_cancelCmd(g_rfHandle, g_cmdRxHandle, stop_gracefully); + /* Stop RX gracefully, don't care about the result */ + RF_cancelCmd(ieee_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY); } if (state & POWER_STATE_ON) { @@ -607,14 +594,14 @@ set_rx(const PowerState state) return CMD_RESULT_OK; } - RF_ScheduleCmdParams schedParams; - RF_ScheduleCmdParams_init(&schedParams); + RF_ScheduleCmdParams sched_params; + RF_ScheduleCmdParams_init(&sched_params); cmd_rx.status = IDLE; - g_cmdRxHandle = RF_scheduleCmd(g_rfHandle, (RF_Op*)&cmd_rx, &schedParams, rx_cb, - RF_EventRxOk | RF_EventRxBufFull | RF_EventRxEntryDone); - if ((g_cmdRxHandle == RF_ALLOC_ERROR) || (g_cmdRxHandle == RF_SCHEDULE_CMD_ERROR)) { - PRINTF("transmit: unable to allocate RX command\n"); + RF_CmdHandle rx_handle = RF_scheduleCmd(ieee_radio.rf_handle, (RF_Op*)&cmd_rx, &sched_params, rx_cb, + RF_EventRxOk | RF_EventRxBufFull | RF_EventRxEntryDone); + if ((rx_handle == RF_ALLOC_ERROR) || (rx_handle == RF_SCHEDULE_CMD_ERROR)) { + PRINTF("transmit: unable to schedule RX command cmd_handle=%d\n", rx_handle); return CMD_RESULT_ERROR; } } @@ -625,31 +612,32 @@ set_rx(const PowerState state) static int transmit_aux(unsigned short transmit_len) { - // Configure TX command + /* Configure TX command */ cmd_tx.payloadLen = (uint8_t)transmit_len; - cmd_tx.pPayload = &g_txBuf[TX_BUF_HDR_LEN]; + cmd_tx.pPayload = &ieee_radio.tx_buf[TX_BUF_HDR_LEN]; - RF_ScheduleCmdParams schedParams; - RF_ScheduleCmdParams_init(&schedParams); + RF_ScheduleCmdParams sched_params; + RF_ScheduleCmdParams_init(&sched_params); - // As IEEE_TX is a FG command, the TX operation will be executed - // either way if RX is running or not + /* As IEEE_TX is a FG command, the TX operation will be executed + * either way if RX is running or not */ cmd_tx.status = IDLE; - g_cmdTxHandle = RF_scheduleCmd(g_rfHandle, (RF_Op*)&cmd_tx, &schedParams, NULL, 0); - if ((g_cmdTxHandle == RF_ALLOC_ERROR) || (g_cmdTxHandle == RF_SCHEDULE_CMD_ERROR)) { - // Failure sending the CMD_IEEE_TX command - PRINTF("transmit: failed to allocate TX command cmdHandle=%d, status=%04x\n", - g_cmdTxHandle, cmd_tx.status); + RF_CmdHandle tx_handle = RF_scheduleCmd(ieee_radio.rf_handle, (RF_Op*)&cmd_tx, &sched_params, + NULL, 0); + if ((tx_handle == RF_ALLOC_ERROR) || (tx_handle == RF_SCHEDULE_CMD_ERROR)) { + /* Failure sending the CMD_IEEE_TX command */ + PRINTF("transmit: unable to schedule TX command cmd_handle=%d, status=%04x\n", + tx_handle, cmd_tx.status); return RADIO_TX_ERR; } ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT); - // Wait until TX operation finishes - RF_EventMask events = RF_pendCmd(g_rfHandle, g_cmdTxHandle, 0); - if ((events & (RF_EventFGCmdDone | RF_EventLastFGCmdDone)) == 0) { - PRINTF("transmit: TX command error events=0x%08llx, status=0x%04x\n", - events, cmd_tx.status); + /* Wait until TX operation finishes */ + RF_EventMask tx_events = RF_pendCmd(ieee_radio.rf_handle, tx_handle, 0); + if ((tx_events & (RF_EventFGCmdDone | RF_EventLastFGCmdDone)) == 0) { + PRINTF("transmit: TX command pend error events=0x%08llx, status=0x%04x\n", + tx_events, cmd_tx.status); return RADIO_TX_ERR; } @@ -659,9 +647,7 @@ transmit_aux(unsigned short transmit_len) static int transmit(unsigned short transmit_len) { - const bool was_rx = (cmd_rx.status == ACTIVE); - - if (g_bSendOnCca && channel_clear() != 1) { + if (ieee_radio.send_on_cca && channel_clear() != 1) { PRINTF("transmit: channel wasn't clear\n"); return RADIO_TX_COLLISION; } @@ -669,9 +655,6 @@ transmit(unsigned short transmit_len) const int rv = transmit_aux(transmit_len); ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN); - if (!was_rx) { - off(); - } return rv; } /*---------------------------------------------------------------------------*/ @@ -685,28 +668,27 @@ send(const void *payload, unsigned short payload_len) static void release_data_entry(void) { - data_entry_t *const data_entry = rx_read_entry; + data_entry_t *const data_entry = ieee_radio.rx_read_entry; uint8_t *const frame_ptr = (uint8_t*)&data_entry->data; - - // Clear the length byte and set status to 0: "Pending" + /* Clear the length byte and set status to 0: "Pending" */ *(lensz_t*)frame_ptr = 0; data_entry->status = DATA_ENTRY_PENDING; - rx_read_entry = (data_entry_t*)data_entry->pNextEntry; + ieee_radio.rx_read_entry = (data_entry_t*)data_entry->pNextEntry; } /*---------------------------------------------------------------------------*/ static int read(void *buf, unsigned short buf_len) { - volatile data_entry_t *data_entry = rx_read_entry; + volatile data_entry_t *data_entry = ieee_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; } @@ -746,143 +728,166 @@ read(void *buf, unsigned short buf_len) return 0; } - memcpy(buf, payload_ptr, payload_len); /* RSSI stored FCS (2) bytes after payload */ - g_lastRssi = (int8_t)payload_ptr[payload_len + 2]; + ieee_radio.last.rssi = (int8_t)payload_ptr[payload_len + 2]; /* LQI retrieved from Status byte, FCS (2) + RSSI (1) bytes after payload */ - g_lastCorrLqi = ((uint8_t)payload_ptr[payload_len + 3]) & STATUS_CORRELATION; + ieee_radio.last.corr_lqi = ((uint8_t)payload_ptr[payload_len + 3]) & STATUS_CORRELATION; /* Timestamp stored FCS (2) + RSSI (1) + Status (1) bytes after payload */ - const uint32_t ratTimestamp = *(uint32_t*)(payload_ptr + payload_len + 4); - g_lastTimestamp = rat_to_timestamp(ratTimestamp); + const uint32_t rat_ticks = *(uint32_t*)(payload_ptr + payload_len + 4); + ieee_radio.last.timestamp = rat_to_timestamp(rat_ticks); - if (!g_bPollMode) { - // Not in poll mode: packetbuf should not be accessed in interrupt context. - // In poll mode, the last packet RSSI and link quality can be obtained through - // RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)g_lastRssi); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)g_lastCorrLqi); + if (!ieee_radio.poll_mode) { + /* Not in poll mode: packetbuf should not be accessed in interrupt context. */ + /* In poll mode, the last packet RSSI and link quality can be obtained through */ + /* RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */ + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)ieee_radio.last.rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)ieee_radio.last.corr_lqi); } release_data_entry(); return (int)payload_len; } /*---------------------------------------------------------------------------*/ -static int -channel_clear_aux(void) +static cmd_result_t +cca_request(cmd_cca_req_t *cmd_cca_req) { - rfc_CMD_IEEE_CCA_REQ_t RF_cmdIeeeCaaReq; - memset(&RF_cmdIeeeCaaReq, 0x0, sizeof(rfc_CMD_IEEE_CCA_REQ_t)); - RF_cmdIeeeCaaReq.commandNo = CMD_IEEE_CCA_REQ; + const bool rx_is_off = !rx_active(); - const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&RF_cmdIeeeCaaReq); - if (stat != RF_StatCmdDoneSuccess) { - PRINTF("channel_clear: CCA request failed stat=0x%02X\n", stat); + if (rx_is_off && set_rx(POWER_STATE_ON) != CMD_RESULT_OK) { return CMD_RESULT_ERROR; } - // Channel is clear if CCA state is idle (0) or invalid (2), i.e. not busy (1) - return (RF_cmdIeeeCaaReq.ccaInfo.ccaState != 1); + const RF_Stat stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t*)&cmd_cca_req); + + if (rx_is_off) { + set_rx(POWER_STATE_OFF); + } + + return (stat == RF_StatCmdDoneSuccess) + ? CMD_RESULT_OK + : CMD_RESULT_ERROR; } /*---------------------------------------------------------------------------*/ static int channel_clear(void) { - const bool was_rx = (cmd_rx.status == ACTIVE); - if (!was_rx && set_rx(POWER_STATE_ON) != CMD_RESULT_OK) { - PRINTF("channel_clear: unable to start RX\n"); - return CHANNEL_CLEAR_ERROR; + cmd_cca_req_t cmd_cca_req; + memset(&cmd_cca_req, 0x0, sizeof(cmd_cca_req_t)); + cmd_cca_req.commandNo = CMD_IEEE_CCA_REQ; + + if (cca_request(&cmd_cca_req) != CMD_RESULT_OK) { + return 0; } - const int rv = channel_clear_aux(); - - if (!was_rx) { - set_rx(POWER_STATE_OFF); - } - return rv; + /* Channel is clear if CCA state is IDLE */ + return (cmd_cca_req.ccaInfo.ccaState == CCA_STATE_IDLE); } /*---------------------------------------------------------------------------*/ static int receiving_packet(void) { - // If we are not in RX, we are not receiving - if (cmd_rx.status != ACTIVE) { - PRINTF("receiving_packet: not in RX\n"); + cmd_cca_req_t cmd_cca_req; + memset(&cmd_cca_req, 0x0, sizeof(cmd_cca_req_t)); + cmd_cca_req.commandNo = CMD_IEEE_CCA_REQ; + + if (cca_request(&cmd_cca_req) != CMD_RESULT_OK) { return 0; } - rfc_CMD_IEEE_CCA_REQ_t cca_req; - memset(&cca_req, 0x0, sizeof(rfc_CMD_IEEE_CCA_REQ_t)); - cca_req.commandNo = CMD_IEEE_CCA_REQ; - - const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&cca_req); - if (stat != RF_StatCmdDoneSuccess) { - PRINTF("receiving_packet: CCA request failed stat=0x%02X\n", stat); + /* If we are transmitting (can only be an ACK here), we are not receiving */ + if ((cmd_cca_req.ccaInfo.ccaEnergy == CCA_STATE_BUSY) && + (cmd_cca_req.ccaInfo.ccaCorr == CCA_STATE_BUSY) && + (cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY)) { + PRINTF("receiving_packet: we were TXing ACK\n"); return 0; } - // We are in RX if a CCA sync has been seen, i.e. ccaSync is busy (1) - return (cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY); + /* We are receiving a packet if a CCA sync has been seen, i.e. ccaSync is busy (1) */ + return (cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY); } /*---------------------------------------------------------------------------*/ static int pending_packet(void) { - const rfc_dataEntry_t *const pStartEntry = (rfc_dataEntry_t *)g_rxDataQueue.pCurrEntry; - volatile const rfc_dataEntry_t *pCurrEntry = pStartEntry; + const data_entry_t *const read_entry = ieee_radio.rx_read_entry; + volatile const data_entry_t *curr_entry = read_entry; - int rv = 0; + int num_pending = 0; - // Check all RX buffers and check their statuses, stopping when looping the circular buffer + /* Go through RX Circular buffer and check their status */ do { - const uint8_t status = pCurrEntry->status; + const uint8_t status = curr_entry->status; if ((status == DATA_ENTRY_FINISHED) || (status == DATA_ENTRY_BUSY)) { - rv += 1; + num_pending += 1; } - pCurrEntry = (rfc_dataEntry_t *)pCurrEntry->pNextEntry; - } while (pCurrEntry != pStartEntry); + /* Stop when we have looped the circular buffer */ + curr_entry = (data_entry_t *)curr_entry->pNextEntry; + } while (curr_entry != read_entry); - if ((rv > 0) && !g_bPollMode) { + if ((num_pending > 0) && !ieee_radio.poll_mode) { process_poll(&rf_process); } - // If we didn't find an entry at status finished or busy, no frames are pending - return rv; + /* If we didn't find an entry at status finished or busy, no frames are pending */ + return num_pending; } /*---------------------------------------------------------------------------*/ static int on(void) { + if (ieee_radio.rf_is_on) { + PRINTF("on: Radio already on\n"); + return CMD_RESULT_OK; + } + + /* Reset all RF command statuses */ + cmd_fs.status = IDLE; + cmd_tx.status = IDLE; + cmd_rx.status = IDLE; + init_rx_buffers(); - const int rv = set_rx(POWER_STATE_ON); + const int rx_ok = set_rx(POWER_STATE_ON); + if (!rx_ok) { + off(); + return CMD_RESULT_ERROR; + } ENERGEST_ON(ENERGEST_TYPE_LISTEN); - return rv; + ieee_radio.rf_is_on = true; + return rx_ok; } /*---------------------------------------------------------------------------*/ static int off(void) { - const uint8_t stopGracefully = 1; - RF_flushCmd(g_rfHandle, RF_CMDHANDLE_FLUSH_ALL, stopGracefully); - RF_yield(g_rfHandle); + if (!ieee_radio.rf_is_on) { + PRINTF("off: Radio already off\n"); + return CMD_RESULT_OK; + } + + /* Force abort of any ongoing RF operation */ + RF_flushCmd(ieee_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY); + /* Trigger a manual power-down */ + RF_yield(ieee_radio.rf_handle); ENERGEST_OFF(ENERGEST_TYPE_LISTEN); - // 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 = &rx_bufs[i].data_entry; + data_entry_t *entry = &ieee_radio.rx_bufs[i].data_entry; if (entry->status == DATA_ENTRY_BUSY) { entry->status = DATA_ENTRY_PENDING; } } + ieee_radio.rf_is_on = false; return CMD_RESULT_OK; } /*---------------------------------------------------------------------------*/ @@ -895,7 +900,7 @@ get_value(radio_param_t param, radio_value_t *value) switch (param) { case RADIO_PARAM_POWER_MODE: - *value = rf_is_on() + *value = (ieee_radio.rf_is_on) ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; return RADIO_RESULT_OK; @@ -920,7 +925,7 @@ get_value(radio_param_t param, radio_value_t *value) if (cmd_rx.frameFiltOpt.autoAckEn) { *value |= (radio_value_t)RADIO_RX_MODE_AUTOACK; } - if (g_bPollMode) { + if (ieee_radio.poll_mode) { *value |= (radio_value_t)RADIO_RX_MODE_POLL_MODE; } return RADIO_RESULT_OK; @@ -940,7 +945,7 @@ get_value(radio_param_t param, radio_value_t *value) return RADIO_RESULT_OK; case RADIO_PARAM_RSSI: - *value = RF_getRssi(g_rfHandle); + *value = RF_getRssi(ieee_radio.rf_handle); return (*value == RF_GET_RSSI_ERROR_VAL) ? RADIO_RESULT_ERROR : RADIO_RESULT_OK; @@ -954,19 +959,19 @@ get_value(radio_param_t param, radio_value_t *value) return RADIO_RESULT_OK; case RADIO_CONST_TXPOWER_MIN: - *value = (radio_value_t)(TX_POWER_MIN.power); + *value = (radio_value_t)TX_POWER_MIN; return RADIO_RESULT_OK; case RADIO_CONST_TXPOWER_MAX: - *value = (radio_value_t)(TX_POWER_MAX.power); + *value = (radio_value_t)TX_POWER_MAX; return RADIO_RESULT_OK; case RADIO_PARAM_LAST_RSSI: - *value = (radio_value_t)g_lastRssi; + *value = (radio_value_t)ieee_radio.last.rssi; return RADIO_RESULT_OK; case RADIO_PARAM_LAST_LINK_QUALITY: - *value = (radio_value_t)g_lastCorrLqi; + *value = (radio_value_t)ieee_radio.last.corr_lqi; return RADIO_RESULT_OK; default: @@ -1001,7 +1006,7 @@ set_value(radio_param_t param, radio_value_t value) case RADIO_PARAM_PAN_ID: cmd_rx.localPanID = (uint16_t)value; - if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { + if (ieee_radio.rf_is_on && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { PRINTF("failed to restart RX"); return RADIO_RESULT_ERROR; } @@ -1009,7 +1014,7 @@ set_value(radio_param_t param, radio_value_t value) case RADIO_PARAM_16BIT_ADDR: cmd_rx.localShortAddr = (uint16_t)value; - if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { + if (ieee_radio.rf_is_on && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { PRINTF("failed to restart RX"); return RADIO_RESULT_ERROR; } @@ -1021,29 +1026,29 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_INVALID_VALUE; } - cmd_rx.frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0; - cmd_rx.frameFiltOpt.frameFiltStop = 1; - cmd_rx.frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0; - cmd_rx.frameFiltOpt.slottedAckEn = 0; - cmd_rx.frameFiltOpt.autoPendEn = 0; - cmd_rx.frameFiltOpt.defaultPend = 0; + cmd_rx.frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0; + cmd_rx.frameFiltOpt.frameFiltStop = 1; + cmd_rx.frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0; + cmd_rx.frameFiltOpt.slottedAckEn = 0; + cmd_rx.frameFiltOpt.autoPendEn = 0; + cmd_rx.frameFiltOpt.defaultPend = 0; cmd_rx.frameFiltOpt.bPendDataReqOnly = 0; - cmd_rx.frameFiltOpt.bPanCoord = 0; + cmd_rx.frameFiltOpt.bPanCoord = 0; cmd_rx.frameFiltOpt.bStrictLenFilter = 0; - const bool bOldPollMode = g_bPollMode; - g_bPollMode = (value & RADIO_RX_MODE_POLL_MODE) != 0; - if (g_bPollMode == bOldPollMode) { - // Do not turn the radio off and on, just send an update command - memcpy(&g_cmdModFilt.newFrameFiltOpt, &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt)); - const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&g_cmdModFilt); + const bool old_poll_mode = ieee_radio.poll_mode; + ieee_radio.poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0; + if (old_poll_mode == ieee_radio.poll_mode) { + /* Do not turn the radio off and on, just send an update command */ + memcpy(&cmd_mod_filt.newFrameFiltOpt, &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt)); + const RF_Stat stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t*)&cmd_mod_filt); if (stat != RF_StatCmdDoneSuccess) { PRINTF("setting address filter failed: stat=0x%02X\n", stat); return RADIO_RESULT_ERROR; } return RADIO_RESULT_OK; } - if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { + if (ieee_radio.rf_is_on && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { PRINTF("failed to restart RX"); return RADIO_RESULT_ERROR; } @@ -1058,16 +1063,11 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: - if(value < TX_POWER_MIN.power || value > TX_POWER_MAX.power) { - return RADIO_RESULT_INVALID_VALUE; - } - return (set_tx_power(value) != CMD_RESULT_OK) - ? RADIO_RESULT_ERROR - : RADIO_RESULT_OK; + return set_tx_power(value); case RADIO_PARAM_CCA_THRESHOLD: cmd_rx.ccaRssiThr = (int8_t)value; - if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { + if (ieee_radio.rf_is_on && set_rx(POWER_STATE_RESTART) != CMD_RESULT_OK) { PRINTF("failed to restart RX"); return RADIO_RESULT_ERROR; } @@ -1105,7 +1105,7 @@ get_object(radio_param_t param, void *dest, size_t size) return RADIO_RESULT_INVALID_VALUE; } - *(rtimer_clock_t *)dest = g_lastTimestamp; + *(rtimer_clock_t *)dest = ieee_radio.last.timestamp; return RADIO_RESULT_OK; diff --git a/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c b/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c index 0eb08470f..b7d2c58f6 100644 --- a/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c +++ b/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c @@ -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; }