51 #include "sys/clock.h" 62 #include "hw_rfc_dbell.h" 63 #include "hw_rfc_pwr.h" 66 #include "rf-core/api/ieee_cmd.h" 67 #include "rf-core/api/ieee_mailbox.h" 68 #include "driverlib/rf_mailbox.h" 69 #include "driverlib/rf_common_cmd.h" 70 #include "driverlib/rf_data_entry.h" 72 #include "smartrf-settings.h" 81 #define PRINTF(...) printf(__VA_ARGS__) 87 #ifdef IEEE_MODE_CONF_AUTOACK 88 #define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK 90 #define IEEE_MODE_AUTOACK 1 94 #ifdef IEEE_MODE_CONF_PROMISCOUS 95 #define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS 97 #define IEEE_MODE_PROMISCOUS 0 100 #ifdef IEEE_MODE_CONF_RSSI_THRESHOLD 101 #define IEEE_MODE_RSSI_THRESHOLD IEEE_MODE_CONF_RSSI_THRESHOLD 103 #define IEEE_MODE_RSSI_THRESHOLD 0xA6 106 #define STATUS_CRC_FAIL 0x80 107 #define STATUS_REJECT_FRAME 0x40 108 #define STATUS_CORRELATION 0x3f 111 #define DATA_ENTRY_STATUS_PENDING 0x00 112 #define DATA_ENTRY_STATUS_ACTIVE 0x01 113 #define DATA_ENTRY_STATUS_BUSY 0x02 114 #define DATA_ENTRY_STATUS_FINISHED 0x03 115 #define DATA_ENTRY_STATUS_UNFINISHED 0x04 118 static uint8_t rf_stats[16] = { 0 };
121 #define RF_CMD_BUFFER_SIZE 128 131 #define RF_RADIO_OP_GET_STATUS(a) (((rfc_radioOp_t *)a)->status) 134 #define RF_CMD_CCA_REQ_RSSI_UNKNOWN -128 137 #define RF_CCA_CLEAR 1 138 #define RF_CCA_BUSY 0 141 #define RF_GET_CCA_INFO_ERROR 0xFF 147 #define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 148 #define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 149 #define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 151 #define RF_CMD_CCA_REQ_CCA_CORR_IDLE (0 << 4) 152 #define RF_CMD_CCA_REQ_CCA_CORR_BUSY (1 << 4) 153 #define RF_CMD_CCA_REQ_CCA_CORR_INVALID (3 << 4) 154 #define RF_CMD_CCA_REQ_CCA_CORR_MASK (3 << 4) 156 #define RF_CMD_CCA_REQ_CCA_SYNC_BUSY (1 << 6) 158 #define IEEE_MODE_CHANNEL_MIN 11 159 #define IEEE_MODE_CHANNEL_MAX 26 162 #define TX_WAIT_TIMEOUT (RTIMER_SECOND >> 11) 165 #define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10) 168 #define RF_TURN_OFF_WAIT_TIMEOUT (RTIMER_SECOND >> 10) 171 #define TX_FINISH_WAIT_TIMEOUT (RTIMER_SECOND >> 7) 173 #define LIMITED_BUSYWAIT(cond, timeout) do { \ 174 rtimer_clock_t end_time = RTIMER_NOW() + timeout; \ 176 if(!RTIMER_CLOCK_LT(RTIMER_NOW(), end_time)) { \ 183 typedef struct output_config {
188 static const output_config_t output_power[] = {
204 #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) 207 #define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm) 208 #define OUTPUT_POWER_MAX (output_power[0].dbm) 209 #define OUTPUT_POWER_UNKNOWN 0xFFFF 212 static const output_config_t *tx_power_current = &output_power[0];
214 static volatile int8_t last_rssi = 0;
215 static volatile uint8_t last_corr_lqi = 0;
217 extern int32_t rat_offset;
221 static volatile uint32_t last_packet_timestamp = 0;
223 static uint64_t last_rat_timestamp64 = 0;
226 static struct ctimer rat_overflow_timer;
227 static volatile uint32_t rat_overflow_counter = 0;
228 static rtimer_clock_t last_rat_overflow = 0;
231 #define RAT_RANGE 4294967296ull 233 #define RAT_OVERFLOW_PERIOD_SECONDS (60 * 18) 236 #define TIMESTAMP_OFFSET -(USEC_TO_RADIO(32 * 3) - 1) 239 static uint8_t poll_mode = 0;
241 static rfc_CMD_IEEE_MOD_FILT_t filter_cmd;
253 static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN(4);
255 #define DATA_ENTRY_LENSZ_NONE 0 256 #define DATA_ENTRY_LENSZ_BYTE 1 257 #define DATA_ENTRY_LENSZ_WORD 2 259 #define RX_BUF_SIZE 144 261 static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
262 static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
263 static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4);
264 static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4);
266 #define RX_BUF_INCLUDE_CRC 1 267 #define RX_BUF_INCLUDE_RSSI 1 268 #define RX_BUF_INCLUDE_CORR 1 269 #define RX_BUF_INCLUDE_TIMESTAMP 1 272 #define RX_BUF_METADATA_SIZE \ 273 (2 * RX_BUF_INCLUDE_CRC + RX_BUF_INCLUDE_RSSI + RX_BUF_INCLUDE_CORR + 4 * RX_BUF_INCLUDE_TIMESTAMP) 276 #define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t) 278 #define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + 1) 281 static dataQueue_t rx_data_queue = { 0 };
284 volatile static uint8_t *rx_read_entry;
287 #define TX_BUF_PAYLOAD_LEN 180 288 #define TX_BUF_HDR_LEN 2 290 static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
292 #ifdef IEEE_MODE_CONF_BOARD_OVERRIDES 293 #define IEEE_MODE_BOARD_OVERRIDES IEEE_MODE_CONF_BOARD_OVERRIDES 295 #define IEEE_MODE_BOARD_OVERRIDES 299 static uint32_t ieee_overrides[] = {
312 IEEE_MODE_BOARD_OVERRIDES
317 static int off(
void);
345 rfc_CMD_IEEE_CCA_REQ_t cmd;
352 memset(&cmd, 0x00,
sizeof(cmd));
354 cmd.commandNo = CMD_IEEE_CCA_REQ;
357 PRINTF(
"transmitting: CMDSTA=0x%08lx\n", cmd_status);
361 if((cmd.currentRssi == RF_CMD_CCA_REQ_RSSI_UNKNOWN) &&
362 (cmd.ccaInfo.ccaEnergy == RF_CMD_CCA_REQ_CCA_STATE_BUSY)) {
384 rfc_CMD_IEEE_CCA_REQ_t cmd;
387 PRINTF(
"get_cca_info: Not on\n");
388 return RF_GET_CCA_INFO_ERROR;
391 memset(&cmd, 0x00,
sizeof(cmd));
392 cmd.ccaInfo.ccaState = RF_CMD_CCA_REQ_CCA_STATE_INVALID;
394 while(cmd.ccaInfo.ccaState == RF_CMD_CCA_REQ_CCA_STATE_INVALID) {
395 memset(&cmd, 0x00,
sizeof(cmd));
396 cmd.commandNo = CMD_IEEE_CCA_REQ;
399 PRINTF(
"get_cca_info: CMDSTA=0x%08lx\n", cmd_status);
401 return RF_GET_CCA_INFO_ERROR;
406 return *((uint8_t *)&cmd.ccaInfo);
421 rfc_CMD_IEEE_CCA_REQ_t cmd;
426 if(on() != RF_CORE_CMD_OK) {
427 PRINTF(
"get_rssi: on() failed\n");
428 return RF_CMD_CCA_REQ_RSSI_UNKNOWN;
432 memset(&cmd, 0x00,
sizeof(cmd));
433 cmd.ccaInfo.ccaEnergy = RF_CMD_CCA_REQ_CCA_STATE_INVALID;
435 while(cmd.ccaInfo.ccaEnergy == RF_CMD_CCA_REQ_CCA_STATE_INVALID) {
436 memset(&cmd, 0x00,
sizeof(cmd));
437 cmd.commandNo = CMD_IEEE_CCA_REQ;
440 PRINTF(
"get_rssi: CMDSTA=0x%08lx\n", cmd_status);
443 cmd.currentRssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN;
453 return cmd.currentRssi;
460 return tx_power_current->dbm;
474 rfc_CMD_SET_TX_POWER_t cmd;
477 for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
478 if(power <= output_power[i].dbm) {
479 tx_power_current = &output_power[i];
494 memset(&cmd, 0x00,
sizeof(cmd));
495 cmd.commandNo = CMD_SET_TX_POWER;
496 cmd.txPower = output_power[i].tx_power;
499 PRINTF(
"set_tx_power: CMDSTA=0x%08lx\n", cmd_status);
507 rfc_CMD_RADIO_SETUP_t cmd;
509 rf_switch_select_path(RF_SWITCH_PATH_2_4GHZ);
514 cmd.txPower = tx_power_current->tx_power;
515 cmd.pRegOverride = ieee_overrides;
516 cmd.config.frontEndMode = RF_CORE_RADIO_SETUP_FRONT_END_MODE;
517 cmd.config.biasMode = RF_CORE_RADIO_SETUP_BIAS_MODE;
522 PRINTF(
"rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
523 cmd_status, cmd.status);
524 return RF_CORE_CMD_ERROR;
529 PRINTF(
"rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n",
530 cmd_status, cmd.status);
531 return RF_CORE_CMD_ERROR;
534 return RF_CORE_CMD_OK;
555 if(ret != RF_CORE_CMD_OK) {
556 PRINTF(
"rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
558 return RF_CORE_CMD_ERROR;
562 ENTER_RX_WAIT_TIMEOUT);
566 PRINTF(
"rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n",
568 return RF_CORE_CMD_ERROR;
575 init_rx_buffers(
void)
577 rfc_dataEntry_t *entry;
579 entry = (rfc_dataEntry_t *)rx_buf_0;
580 entry->pNextEntry = rx_buf_1;
581 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
582 entry->length =
sizeof(rx_buf_0) -
sizeof(*entry);
584 entry = (rfc_dataEntry_t *)rx_buf_1;
585 entry->pNextEntry = rx_buf_2;
586 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
587 entry->length =
sizeof(rx_buf_0) -
sizeof(*entry);
589 entry = (rfc_dataEntry_t *)rx_buf_2;
590 entry->pNextEntry = rx_buf_3;
591 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
592 entry->length =
sizeof(rx_buf_0) -
sizeof(*entry);
594 entry = (rfc_dataEntry_t *)rx_buf_3;
595 entry->pNextEntry = rx_buf_0;
596 entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
597 entry->length =
sizeof(rx_buf_0) -
sizeof(*entry);
603 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
605 memset(cmd_ieee_rx_buf, 0x00, RF_CMD_BUFFER_SIZE);
607 cmd->commandNo = CMD_IEEE_RX;
608 cmd->status = RF_CORE_RADIO_OP_STATUS_IDLE;
610 cmd->startTime = 0x00000000;
611 cmd->startTrigger.triggerType = TRIG_NOW;
612 cmd->condition.rule = COND_NEVER;
615 cmd->rxConfig.bAutoFlushCrc = 1;
616 cmd->rxConfig.bAutoFlushIgn = 0;
617 cmd->rxConfig.bIncludePhyHdr = 0;
618 cmd->rxConfig.bIncludeCrc = RX_BUF_INCLUDE_CRC;
619 cmd->rxConfig.bAppendRssi = RX_BUF_INCLUDE_RSSI;
620 cmd->rxConfig.bAppendCorrCrc = RX_BUF_INCLUDE_CORR;
621 cmd->rxConfig.bAppendSrcInd = 0;
622 cmd->rxConfig.bAppendTimestamp = RX_BUF_INCLUDE_TIMESTAMP;
624 cmd->pRxQ = &rx_data_queue;
625 cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
627 #if IEEE_MODE_PROMISCOUS 628 cmd->frameFiltOpt.frameFiltEn = 0;
630 cmd->frameFiltOpt.frameFiltEn = 1;
633 cmd->frameFiltOpt.frameFiltStop = 1;
635 #if IEEE_MODE_AUTOACK 636 cmd->frameFiltOpt.autoAckEn = 1;
638 cmd->frameFiltOpt.autoAckEn = 0;
641 cmd->frameFiltOpt.slottedAckEn = 0;
642 cmd->frameFiltOpt.autoPendEn = 0;
643 cmd->frameFiltOpt.defaultPend = 0;
644 cmd->frameFiltOpt.bPendDataReqOnly = 0;
645 cmd->frameFiltOpt.bPanCoord = 0;
646 cmd->frameFiltOpt.maxFrameVersion = 2;
647 cmd->frameFiltOpt.bStrictLenFilter = 0;
650 cmd->frameTypes.bAcceptFt0Beacon = 1;
651 cmd->frameTypes.bAcceptFt1Data = 1;
652 cmd->frameTypes.bAcceptFt2Ack = 1;
653 cmd->frameTypes.bAcceptFt3MacCmd = 1;
654 cmd->frameTypes.bAcceptFt4Reserved = 1;
655 cmd->frameTypes.bAcceptFt5Reserved = 1;
656 cmd->frameTypes.bAcceptFt6Reserved = 1;
657 cmd->frameTypes.bAcceptFt7Reserved = 1;
660 cmd->ccaOpt.ccaEnEnergy = 1;
661 cmd->ccaOpt.ccaEnCorr = 1;
662 cmd->ccaOpt.ccaEnSync = 1;
663 cmd->ccaOpt.ccaCorrOp = 1;
664 cmd->ccaOpt.ccaSyncOp = 0;
665 cmd->ccaOpt.ccaCorrThr = 3;
667 cmd->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD;
669 cmd->numExtEntries = 0x00;
670 cmd->numShortEntries = 0x00;
671 cmd->pExtEntryList = 0;
672 cmd->pShortEntryList = 0;
674 cmd->endTrigger.triggerType = TRIG_NEVER;
675 cmd->endTime = 0x00000000;
678 filter_cmd.commandNo = CMD_IEEE_MOD_FILT;
679 memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt,
sizeof(cmd->frameFiltOpt));
680 memcpy(&filter_cmd.newFrameTypes, &cmd->frameTypes,
sizeof(cmd->frameTypes));
692 return RF_CORE_CMD_OK;
699 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
713 return RF_CORE_CMD_OK;
717 LIMITED_BUSYWAIT(
transmitting(), TX_FINISH_WAIT_TIMEOUT);
720 if(
rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
721 PRINTF(
"RX off: CMD_ABORT status=0x%08lx\n", cmd_status);
725 LIMITED_BUSYWAIT(
rf_is_on(), RF_TURN_OFF_WAIT_TIMEOUT);
730 ret = RF_CORE_CMD_OK;
733 ret = RF_CORE_CMD_ERROR;
736 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
749 return LPM_MODE_SLEEP;
752 return LPM_MODE_MAX_SUPPORTED;
755 LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
767 PRINTF(
"soft_off: Aborting 0x%04x, Status=0x%04x\n", cmd->commandNo,
771 if(
rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
772 PRINTF(
"soft_off: CMD_ABORT status=0x%08lx\n", cmd_status);
776 LIMITED_BUSYWAIT((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) ==
777 RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_TURN_OFF_WAIT_TIMEOUT);
783 if(rf_radio_setup() != RF_CORE_CMD_OK) {
784 PRINTF(
"on: radio_setup() failed\n");
785 return RF_CORE_CMD_ERROR;
797 check_rat_overflow(
bool first_time)
799 static uint32_t last_value;
800 uint32_t current_value;
801 uint8_t interrupts_disabled;
808 interrupts_disabled = ti_lib_int_master_disable();
810 last_value = HWREG(RFC_RAT_BASE + RATCNT);
812 current_value = HWREG(RFC_RAT_BASE + RATCNT);
813 if(current_value + RAT_RANGE / 4 < last_value) {
816 rat_overflow_counter++;
818 last_value = current_value;
820 if(!interrupts_disabled) {
821 ti_lib_int_master_enable();
827 handle_rat_overflow(
void *unused)
834 if(on() != RF_CORE_CMD_OK) {
835 PRINTF(
"overflow: on() failed\n");
837 handle_rat_overflow, NULL);
842 success = check_rat_overflow(
false);
851 handle_rat_overflow, NULL);
855 handle_rat_overflow, NULL);
867 memset(rx_buf_0, 0, RX_BUF_SIZE);
868 memset(rx_buf_1, 0, RX_BUF_SIZE);
869 memset(rx_buf_2, 0, RX_BUF_SIZE);
870 memset(rx_buf_3, 0, RX_BUF_SIZE);
873 rx_data_queue.pCurrEntry = rx_buf_0;
875 rx_data_queue.pLastEntry = NULL;
878 rx_read_entry = rx_buf_0;
883 if(on() != RF_CORE_CMD_OK) {
884 PRINTF(
"init: on() failed\n");
885 return RF_CORE_CMD_ERROR;
888 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
892 check_rat_overflow(
true);
894 handle_rat_overflow, NULL);
901 prepare(
const void *payload,
unsigned short payload_len)
903 int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN);
905 memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len);
910 transmit(
unsigned short transmit_len)
916 uint8_t tx_active = 0;
918 volatile rfc_CMD_IEEE_TX_t cmd;
922 if(on() != RF_CORE_CMD_OK) {
923 PRINTF(
"transmit: on() failed\n");
937 }
while(tx_active == 1 &&
938 (RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + TX_WAIT_TIMEOUT)));
941 PRINTF(
"transmit: Already TXing and wait timed out\n");
947 return RADIO_TX_COLLISION;
953 cmd.payloadLen = transmit_len;
954 cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
957 cmd.startTrigger.triggerType = TRIG_NOW;
966 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
969 while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
970 == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
983 if(stat == RF_CORE_RADIO_OP_STATUS_IEEE_DONE_OK) {
988 PRINTF(
"transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret,
994 PRINTF(
"transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
995 ret, cmd_status, cmd.status);
1004 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
1020 send(
const void *payload,
unsigned short payload_len)
1022 prepare(payload, payload_len);
1023 return transmit(payload_len);
1027 release_data_entry(
void)
1029 rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
1032 rx_read_entry[8] = 0;
1035 entry->status = DATA_ENTRY_STATUS_PENDING;
1036 rx_read_entry = entry->pNextEntry;
1040 calc_last_packet_timestamp(uint32_t rat_timestamp)
1042 uint64_t rat_timestamp64;
1043 uint32_t adjusted_overflow_counter;
1044 uint8_t was_off = 0;
1052 check_rat_overflow(
false);
1058 adjusted_overflow_counter = rat_overflow_counter;
1062 if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) {
1064 last_rat_overflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) {
1065 adjusted_overflow_counter--;
1070 rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter;
1072 rat_timestamp64 += TIMESTAMP_OFFSET;
1074 last_rat_timestamp64 = rat_timestamp64 - rat_offset;
1076 return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset);
1080 read_frame(
void *buf,
unsigned short buf_len)
1083 rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
1084 uint32_t rat_timestamp;
1088 while(entry->status == DATA_ENTRY_STATUS_BUSY
1089 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 250)));
1091 if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
1096 len = rx_read_entry[RX_BUF_LENGTH_OFFSET];
1097 if(len <= RX_BUF_METADATA_SIZE) {
1098 PRINTF(
"RF: too short!");
1100 release_data_entry();
1104 len -= RX_BUF_METADATA_SIZE;
1106 PRINTF(
"RF: too long\n");
1108 release_data_entry();
1112 memcpy(buf, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET, len);
1114 last_rssi = (int8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 2];
1115 last_corr_lqi = (uint8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 3] & STATUS_CORRELATION;
1118 memcpy(&rat_timestamp, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET + len + 4, 4);
1120 last_packet_timestamp = calc_last_packet_timestamp(rat_timestamp);
1126 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
1127 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, last_corr_lqi);
1130 release_data_entry();
1138 uint8_t was_off = 0;
1140 int ret = RF_CCA_CLEAR;
1147 PRINTF(
"channel_clear: Interrupt context but BLE in progress\n");
1148 return RF_CCA_CLEAR;
1160 LIMITED_BUSYWAIT(
transmitting(), TX_FINISH_WAIT_TIMEOUT);
1163 if(on() != RF_CORE_CMD_OK) {
1164 PRINTF(
"channel_clear: on() failed\n");
1168 return RF_CCA_CLEAR;
1174 if(cca_info == RF_GET_CCA_INFO_ERROR) {
1175 PRINTF(
"channel_clear: CCA error\n");
1182 ret = (cca_info & 0x03) != RF_CMD_CCA_REQ_CCA_STATE_BUSY;
1193 receiving_packet(
void)
1202 PRINTF(
"receiving_packet: Interrupt context but BLE in progress\n");
1208 PRINTF(
"receiving_packet: We were off\n");
1214 PRINTF(
"receiving_packet: We were TXing\n");
1221 if(cca_info == RF_GET_CCA_INFO_ERROR) {
1226 if(cca_info & RF_CMD_CCA_REQ_CCA_SYNC_BUSY) {
1234 pending_packet(
void)
1236 volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1241 if(entry->status == DATA_ENTRY_STATUS_FINISHED
1242 || entry->status == DATA_ENTRY_STATUS_BUSY) {
1249 entry = (rfc_dataEntry_t *)entry->pNextEntry;
1250 }
while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1264 PRINTF(
"on: Interrupt context but BLE in progress\n");
1265 return RF_CORE_CMD_OK;
1277 return RF_CORE_CMD_OK;
1291 PRINTF(
"on: rf_core_boot() failed\n");
1292 return RF_CORE_CMD_ERROR;
1297 if(rf_radio_setup() != RF_CORE_CMD_OK) {
1298 PRINTF(
"on: radio_setup() failed\n");
1299 return RF_CORE_CMD_ERROR;
1313 PRINTF(
"off: Interrupt context but BLE in progress\n");
1314 return RF_CORE_CMD_OK;
1317 LIMITED_BUSYWAIT(
transmitting(), TX_FINISH_WAIT_TIMEOUT);
1323 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1325 #if !CC2650_FAST_RADIO_STARTUP 1333 ((rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
1339 if(((rfc_dataEntry_t *)rx_buf_0)->status == DATA_ENTRY_STATUS_BUSY) {
1340 ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING;
1342 if(((rfc_dataEntry_t *)rx_buf_1)->status == DATA_ENTRY_STATUS_BUSY) {
1343 ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING;
1345 if(((rfc_dataEntry_t *)rx_buf_2)->status == DATA_ENTRY_STATUS_BUSY) {
1346 ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING;
1348 if(((rfc_dataEntry_t *)rx_buf_3)->status == DATA_ENTRY_STATUS_BUSY) {
1349 ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING;
1352 return RF_CORE_CMD_OK;
1356 static radio_result_t
1357 set_send_on_cca(uint8_t enable)
1361 return RADIO_RESULT_NOT_SUPPORTED;
1363 return RADIO_RESULT_OK;
1366 static radio_result_t
1369 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1372 return RADIO_RESULT_INVALID_VALUE;
1376 case RADIO_PARAM_POWER_MODE:
1378 *value =
rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
1379 return RADIO_RESULT_OK;
1380 case RADIO_PARAM_CHANNEL:
1382 return RADIO_RESULT_OK;
1383 case RADIO_PARAM_PAN_ID:
1385 return RADIO_RESULT_OK;
1386 case RADIO_PARAM_16BIT_ADDR:
1388 return RADIO_RESULT_OK;
1389 case RADIO_PARAM_RX_MODE:
1391 if(cmd->frameFiltOpt.frameFiltEn) {
1394 if(cmd->frameFiltOpt.autoAckEn) {
1395 *value |= RADIO_RX_MODE_AUTOACK;
1398 *value |= RADIO_RX_MODE_POLL_MODE;
1401 return RADIO_RESULT_OK;
1402 case RADIO_PARAM_TX_MODE:
1404 return RADIO_RESULT_OK;
1405 case RADIO_PARAM_TXPOWER:
1406 *value = get_tx_power();
1407 return RADIO_RESULT_OK;
1408 case RADIO_PARAM_CCA_THRESHOLD:
1409 *value = cmd->ccaRssiThr;
1410 return RADIO_RESULT_OK;
1411 case RADIO_PARAM_RSSI:
1414 if(*value == RF_CMD_CCA_REQ_RSSI_UNKNOWN) {
1415 return RADIO_RESULT_ERROR;
1417 return RADIO_RESULT_OK;
1419 case RADIO_CONST_CHANNEL_MIN:
1420 *value = IEEE_MODE_CHANNEL_MIN;
1421 return RADIO_RESULT_OK;
1422 case RADIO_CONST_CHANNEL_MAX:
1423 *value = IEEE_MODE_CHANNEL_MAX;
1424 return RADIO_RESULT_OK;
1425 case RADIO_CONST_TXPOWER_MIN:
1426 *value = OUTPUT_POWER_MIN;
1427 return RADIO_RESULT_OK;
1428 case RADIO_CONST_TXPOWER_MAX:
1429 *value = OUTPUT_POWER_MAX;
1430 return RADIO_RESULT_OK;
1431 case RADIO_PARAM_LAST_RSSI:
1433 return RADIO_RESULT_OK;
1434 case RADIO_PARAM_LAST_LINK_QUALITY:
1435 *value = last_corr_lqi;
1436 return RADIO_RESULT_OK;
1438 return RADIO_RESULT_NOT_SUPPORTED;
1442 static radio_result_t
1445 radio_result_t rv = RADIO_RESULT_OK;
1446 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1447 uint8_t old_poll_mode;
1450 case RADIO_PARAM_POWER_MODE:
1451 if(value == RADIO_POWER_MODE_ON) {
1452 if(on() != RF_CORE_CMD_OK) {
1453 PRINTF(
"set_value: on() failed (1)\n");
1454 return RADIO_RESULT_ERROR;
1456 return RADIO_RESULT_OK;
1458 if(value == RADIO_POWER_MODE_OFF) {
1460 return RADIO_RESULT_OK;
1462 return RADIO_RESULT_INVALID_VALUE;
1463 case RADIO_PARAM_CHANNEL:
1464 if(value < IEEE_MODE_CHANNEL_MIN ||
1465 value > IEEE_MODE_CHANNEL_MAX) {
1466 return RADIO_RESULT_INVALID_VALUE;
1470 if(cmd->channel == (uint8_t)value) {
1473 return RADIO_RESULT_OK;
1476 cmd->channel = (uint8_t)value;
1478 case RADIO_PARAM_PAN_ID:
1479 cmd->localPanID = (uint16_t)value;
1481 case RADIO_PARAM_16BIT_ADDR:
1482 cmd->localShortAddr = (uint16_t)value;
1484 case RADIO_PARAM_RX_MODE:
1487 RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
1488 return RADIO_RESULT_INVALID_VALUE;
1492 cmd->frameFiltOpt.frameFiltStop = 1;
1493 cmd->frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
1494 cmd->frameFiltOpt.slottedAckEn = 0;
1495 cmd->frameFiltOpt.autoPendEn = 0;
1496 cmd->frameFiltOpt.defaultPend = 0;
1497 cmd->frameFiltOpt.bPendDataReqOnly = 0;
1498 cmd->frameFiltOpt.bPanCoord = 0;
1499 cmd->frameFiltOpt.bStrictLenFilter = 0;
1501 old_poll_mode = poll_mode;
1502 poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
1503 if(poll_mode == old_poll_mode) {
1504 uint32_t cmd_status;
1507 memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt,
sizeof(cmd->frameFiltOpt));
1509 if(
rf_core_send_cmd((uint32_t)&filter_cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
1510 PRINTF(
"setting address filter failed: CMDSTA=0x%08lx\n", cmd_status);
1511 return RADIO_RESULT_ERROR;
1513 return RADIO_RESULT_OK;
1518 case RADIO_PARAM_TX_MODE:
1520 return RADIO_RESULT_INVALID_VALUE;
1524 case RADIO_PARAM_TXPOWER:
1525 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1526 return RADIO_RESULT_INVALID_VALUE;
1529 set_tx_power(value);
1531 return RADIO_RESULT_OK;
1533 case RADIO_PARAM_CCA_THRESHOLD:
1534 cmd->ccaRssiThr = (int8_t)value;
1538 return RADIO_RESULT_NOT_SUPPORTED;
1543 return RADIO_RESULT_OK;
1547 if(rx_off() != RF_CORE_CMD_OK) {
1548 PRINTF(
"set_value: rx_off() failed\n");
1549 rv = RADIO_RESULT_ERROR;
1555 check_rat_overflow(
false);
1558 if(rx_on() != RF_CORE_CMD_OK) {
1559 PRINTF(
"set_value: rx_on() failed\n");
1560 rv = RADIO_RESULT_ERROR;
1566 static radio_result_t
1567 get_object(radio_param_t param,
void *dest,
size_t size)
1572 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1574 if(param == RADIO_PARAM_64BIT_ADDR) {
1575 if(size != 8 || !dest) {
1576 return RADIO_RESULT_INVALID_VALUE;
1580 src = (uint8_t *)(&cmd->localExtAddr);
1582 for(i = 0; i < 8; i++) {
1583 target[i] = src[7 - i];
1586 return RADIO_RESULT_OK;
1589 if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
1590 if(size !=
sizeof(rtimer_clock_t) || !dest) {
1591 return RADIO_RESULT_INVALID_VALUE;
1593 *(rtimer_clock_t *)dest = last_packet_timestamp;
1595 return RADIO_RESULT_OK;
1598 return RADIO_RESULT_NOT_SUPPORTED;
1601 static radio_result_t
1602 set_object(radio_param_t param,
const void *src,
size_t size)
1604 radio_result_t rv = RADIO_RESULT_OK;
1607 rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1609 if(param == RADIO_PARAM_64BIT_ADDR) {
1610 if(size != 8 || !src) {
1611 return RADIO_RESULT_INVALID_VALUE;
1614 dst = (uint8_t *)(&cmd->localExtAddr);
1616 for(i = 0; i < 8; i++) {
1617 dst[i] = ((uint8_t *)src)[7 - i];
1622 return RADIO_RESULT_OK;
1625 if(rx_off() != RF_CORE_CMD_OK) {
1626 PRINTF(
"set_object: rx_off() failed\n");
1627 rv = RADIO_RESULT_ERROR;
1630 if(rx_on() != RF_CORE_CMD_OK) {
1631 PRINTF(
"set_object: rx_on() failed\n");
1632 rv = RADIO_RESULT_ERROR;
1637 return RADIO_RESULT_NOT_SUPPORTED;
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
void oscillators_request_hf_xosc(void)
Requests the HF XOSC as the source for the HF clock, but does not perform the actual switch...
static uint8_t transmitting(void)
Check the RF's TX status.
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
void rf_core_setup_interrupts(bool poll_mode)
Setup RF core interrupts.
Header file with macros which rename TI CC26xxware functions.
static uint8_t rf_is_on(void)
Checks whether the RFC domain is accessible and the RFC is in IEEE RX.
Header file for the energy estimation mechanism
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Header file for the radio API
Header file for the link-layer address representation
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
The structure of a device driver for a radio in Contiki.
void lpm_sleep(void)
Enter sleep mode.
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Header file for the CC13xx/CC26xx RF core driver.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
#define RTIMER_NOW()
Get the current clock time.
Header file for the CC13xx/CC26xx oscillator control.
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
#define CLOCK_SECOND
A second, measured in system clock time.
uint8_t rf_ble_is_active()
Check whether the BLE beacond is currently active.
Header file for the callback timer
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
void rf_core_cmd_done_dis(bool poll_mode)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
A data strcuture representing the radio's primary mode of operation.
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
void process_poll(struct process *p)
Request a process to be polled.
int(* off)(void)
Turn the radio off.
Header file for the real-time timer module.
static radio_value_t get_rssi(void)
Reads the current signal strength (RSSI)
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
Prepare a buffer to host a Radio Op.
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Header file for the CC13xx/CC26xx BLE driver.
Header file with definitions related to RF switch support.
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
static uint8_t get_cca_info(void)
Returns CCA information.
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Header file for the CC13xx/CC26xx UART driver.
void oscillators_switch_to_hf_xosc(void)
Performs the switch to the XOSC.
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
void rf_core_cmd_done_en(bool fg, bool poll_mode)
Enable interrupt on command done.
Header file for the Packet buffer (packetbuf) management
#define LPM_MODULE(n, m, s, w, l)
Declare a variable to be used in order to get notifications from LPM.
Include file for the Contiki low-layer network stack (NETSTACK)
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Default definitions of C compiler quirk work-arounds.
uint8_t rf_core_boot()
Boot the RF Core.
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
int(* on)(void)
Turn the radio on.
void process_start(struct process *p, process_data_t data)
Start a process.
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
#define RF_RADIO_OP_GET_STATUS(a)
Returns the current status of a running Radio Op command.