Contiki-NG
ieee-mode.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /*---------------------------------------------------------------------------*/
31 /**
32  * \addtogroup rf-core
33  * @{
34  *
35  * \defgroup rf-core-ieee CC13xx/CC26xx IEEE mode driver
36  *
37  * @{
38  *
39  * \file
40  * Implementation of the CC13xx/CC26xx IEEE mode NETSTACK_RADIO driver
41  */
42 /*---------------------------------------------------------------------------*/
43 #include "contiki.h"
44 #include "dev/radio.h"
45 #include "dev/cc26xx-uart.h"
46 #include "dev/oscillators.h"
47 #include "net/packetbuf.h"
48 #include "net/linkaddr.h"
49 #include "net/netstack.h"
50 #include "sys/energest.h"
51 #include "sys/clock.h"
52 #include "sys/rtimer.h"
53 #include "sys/ctimer.h"
54 #include "sys/cc.h"
55 #include "lpm.h"
56 #include "ti-lib.h"
57 #include "rf-core/rf-core.h"
58 #include "rf-core/rf-switch.h"
59 #include "rf-core/rf-ble.h"
60 /*---------------------------------------------------------------------------*/
61 /* RF core and RF HAL API */
62 #include "hw_rfc_dbell.h"
63 #include "hw_rfc_pwr.h"
64 /*---------------------------------------------------------------------------*/
65 /* RF Core Mailbox API */
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"
71 /*---------------------------------------------------------------------------*/
72 #include "smartrf-settings.h"
73 /*---------------------------------------------------------------------------*/
74 #include <stdint.h>
75 #include <string.h>
76 #include <stdio.h>
77 #include <stdbool.h>
78 /*---------------------------------------------------------------------------*/
79 #define DEBUG 0
80 #if DEBUG
81 #define PRINTF(...) printf(__VA_ARGS__)
82 #else
83 #define PRINTF(...)
84 #endif
85 
86 /* Configuration to enable/disable auto ACKs in IEEE mode */
87 #ifdef IEEE_MODE_CONF_AUTOACK
88 #define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK
89 #else
90 #define IEEE_MODE_AUTOACK 1
91 #endif /* IEEE_MODE_CONF_AUTOACK */
92 
93 /* Configuration to enable/disable frame filtering in IEEE mode */
94 #ifdef IEEE_MODE_CONF_PROMISCOUS
95 #define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS
96 #else
97 #define IEEE_MODE_PROMISCOUS 0
98 #endif /* IEEE_MODE_CONF_PROMISCOUS */
99 
100 #ifdef IEEE_MODE_CONF_RSSI_THRESHOLD
101 #define IEEE_MODE_RSSI_THRESHOLD IEEE_MODE_CONF_RSSI_THRESHOLD
102 #else
103 #define IEEE_MODE_RSSI_THRESHOLD 0xA6
104 #endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */
105 /*---------------------------------------------------------------------------*/
106 #define STATUS_CRC_FAIL 0x80 /* bit 7 */
107 #define STATUS_REJECT_FRAME 0x40 /* bit 6 */
108 #define STATUS_CORRELATION 0x3f /* bits 0-5 */
109 /*---------------------------------------------------------------------------*/
110 /* Data entry status field constants */
111 #define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
112 #define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
113 #define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */
114 #define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */
115 #define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */
116 /*---------------------------------------------------------------------------*/
117 /* RF stats data structure */
118 static uint8_t rf_stats[16] = { 0 };
119 /*---------------------------------------------------------------------------*/
120 /* The size of the RF commands buffer */
121 #define RF_CMD_BUFFER_SIZE 128
122 /*---------------------------------------------------------------------------*/
123 #define RAT_TIMESTAMP_OFFSET_2_4_GHZ 0
124 /*---------------------------------------------------------------------------*/
125 /**
126  * \brief Returns the current status of a running Radio Op command
127  * \param a A pointer with the buffer used to initiate the command
128  * \return The value of the Radio Op buffer's status field
129  *
130  * This macro can be used to e.g. return the status of a previously
131  * initiated background operation, or of an immediate command
132  */
133 #define RF_RADIO_OP_GET_STATUS(a) (((rfc_radioOp_t *)a)->status)
134 /*---------------------------------------------------------------------------*/
135 #define IEEE_MODE_CHANNEL_MIN 11
136 #define IEEE_MODE_CHANNEL_MAX 26
137 /*---------------------------------------------------------------------------*/
138 /* TX Power dBm lookup table - values from SmartRF Studio */
139 typedef struct output_config {
140  radio_value_t dbm;
141  uint16_t tx_power; /* Value for the CMD_RADIO_SETUP.txPower field */
142 } output_config_t;
143 
144 static const output_config_t output_power[] = {
145  { 5, 0x9330 },
146  { 4, 0x9324 },
147  { 3, 0x5a1c },
148  { 2, 0x4e18 },
149  { 1, 0x4214 },
150  { 0, 0x3161 },
151  { -3, 0x2558 },
152  { -6, 0x1d52 },
153  { -9, 0x194e },
154  {-12, 0x144b },
155  {-15, 0x0ccb },
156  {-18, 0x0cc9 },
157  {-21, 0x0cc7 },
158 };
159 
160 #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t))
161 
162 /* Max and Min Output Power in dBm */
163 #define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm)
164 #define OUTPUT_POWER_MAX (output_power[0].dbm)
165 #define OUTPUT_POWER_UNKNOWN 0xFFFF
166 
167 /* Default TX Power - position in output_power[] */
168 static const output_config_t *tx_power_current = &output_power[0];
169 /*---------------------------------------------------------------------------*/
170 static rfc_CMD_IEEE_MOD_FILT_t filter_cmd;
171 /*---------------------------------------------------------------------------*/
172 /*
173  * Buffers used to send commands to the RF core (generic and IEEE commands).
174  * Some of those buffers are re-usable, some are not.
175  *
176  * If you are uncertain, declare a new buffer.
177  */
178 /*
179  * A buffer to send a CMD_IEEE_RX and to subsequently monitor its status
180  * Do not use this buffer for any commands other than CMD_IEEE_RX
181  */
182 static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN(4);
183 /*---------------------------------------------------------------------------*/
184 /*
185  * The number of bytes appended at the end of an outgoing frame as a footer
186  * Currently fixed at 2 bytes for IEEE 802.15.4 compliance.
187  */
188 #define CHECKSUM_LEN 2
189 
190 /*
191  * The maximum number of bytes this driver can accept from the MAC layer for
192  * transmission or will deliver to the MAC layer after reception. Includes
193  * the MAC header and payload, but not the FCS.
194  */
195 #define MAX_PAYLOAD_LEN (127 - CHECKSUM_LEN)
196 /*---------------------------------------------------------------------------*/
197 #define DATA_ENTRY_LENSZ_NONE 0
198 #define DATA_ENTRY_LENSZ_BYTE 1
199 #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
200 
201 /* The size of the metadata (excluding the packet length field) */
202 #define RX_BUF_METADATA_SIZE \
203  (2 * RF_CORE_RX_BUF_INCLUDE_CRC \
204  + RF_CORE_RX_BUF_INCLUDE_RSSI \
205  + RF_CORE_RX_BUF_INCLUDE_CORR \
206  + 4 * RF_CORE_RX_BUF_INCLUDE_TIMESTAMP)
207 
208 /* The offset of the packet length in a rx buffer */
209 #define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t)
210 /* The offset of the packet data in a rx buffer */
211 #define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + 1)
212 
213 #define RX_BUF_SIZE (RX_BUF_DATA_OFFSET \
214  + MAX_PAYLOAD_LEN \
215  + RX_BUF_METADATA_SIZE)
216 
217 /* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */
218 static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
219 static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
220 static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4);
221 static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4);
222 
223 /* The RX Data Queue */
224 static dataQueue_t rx_data_queue = { 0 };
225 
226 /* Receive entry pointer to keep track of read items */
227 volatile static uint8_t *rx_read_entry;
228 /*---------------------------------------------------------------------------*/
229 /* The outgoing frame buffer */
230 #define TX_BUF_PAYLOAD_LEN 180
231 #define TX_BUF_HDR_LEN 2
232 
233 static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
234 /*---------------------------------------------------------------------------*/
235 #ifdef IEEE_MODE_CONF_BOARD_OVERRIDES
236 #define IEEE_MODE_BOARD_OVERRIDES IEEE_MODE_CONF_BOARD_OVERRIDES
237 #else
238 #define IEEE_MODE_BOARD_OVERRIDES
239 #endif
240 /*---------------------------------------------------------------------------*/
241 /* Overrides for IEEE 802.15.4, differential mode */
242 static uint32_t ieee_overrides[] = {
243  0x00354038, /* Synth: Set RTRIM (POTAILRESTRIM) to 5 */
244  0x4001402D, /* Synth: Correct CKVD latency setting (address) */
245  0x00608402, /* Synth: Correct CKVD latency setting (value) */
246 // 0x4001405D, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (address) */
247 // 0x1801F800, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (value) */
248  0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */
249  0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */
250  0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */
251  0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */
252  0x002B50DC, /* Adjust AGC DC filter */
253  0x05000243, /* Increase synth programming timeout */
254  0x002082C3, /* Increase synth programming timeout */
255  IEEE_MODE_BOARD_OVERRIDES
256  0xFFFFFFFF, /* End of override list */
257 };
258 /*---------------------------------------------------------------------------*/
259 static int on(void);
260 static int off(void);
261 /*---------------------------------------------------------------------------*/
262 /**
263  * \brief Checks whether the RFC domain is accessible and the RFC is in IEEE RX
264  * \return 1: RFC in RX mode (and therefore accessible too). 0 otherwise
265  */
266 static uint8_t
267 rf_is_on(void)
268 {
269  if(!rf_core_is_accessible()) {
270  return 0;
271  }
272 
273  return RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE;
274 }
275 /*---------------------------------------------------------------------------*/
276 /**
277  * \brief Check the RF's TX status
278  * \return 1 RF is transmitting
279  * \return 0 RF is not transmitting
280  *
281  * TX mode may be triggered either by a CMD_IEEE_TX or by the automatic
282  * transmission of an ACK frame.
283  */
284 static uint8_t
286 {
287  uint32_t cmd_status;
288  rfc_CMD_IEEE_CCA_REQ_t cmd;
289 
290  /* If we are off, we are not in TX */
291  if(!rf_core_is_accessible()) {
292  return 0;
293  }
294 
295  memset(&cmd, 0x00, sizeof(cmd));
296 
297  cmd.commandNo = CMD_IEEE_CCA_REQ;
298 
299  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
300  PRINTF("transmitting: CMDSTA=0x%08lx\n", cmd_status);
301  return 0;
302  }
303 
304  if((cmd.currentRssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) &&
305  (cmd.ccaInfo.ccaEnergy == RF_CORE_CMD_CCA_REQ_CCA_STATE_BUSY)) {
306  return 1;
307  }
308 
309  return 0;
310 }
311 /*---------------------------------------------------------------------------*/
312 /**
313  * \brief Returns CCA information
314  * \return RF_CORE_GET_CCA_INFO_ERROR if the RF was not on
315  * \return On success, the return value is formatted as per the ccaInfo field
316  * of CMD_IEEE_CCA_REQ
317  *
318  * It is the caller's responsibility to make sure the RF is on. This function
319  * will return RF_CORE_GET_CCA_INFO_ERROR if the RF is off
320  *
321  * This function will in fact wait for a valid CCA state
322  */
323 static uint8_t
325 {
326  uint32_t cmd_status;
327  rfc_CMD_IEEE_CCA_REQ_t cmd;
328 
329  if(!rf_is_on()) {
330  PRINTF("get_cca_info: Not on\n");
331  return RF_CORE_GET_CCA_INFO_ERROR;
332  }
333 
334  memset(&cmd, 0x00, sizeof(cmd));
335  cmd.ccaInfo.ccaState = RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID;
336 
337  while(cmd.ccaInfo.ccaState == RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID) {
338  memset(&cmd, 0x00, sizeof(cmd));
339  cmd.commandNo = CMD_IEEE_CCA_REQ;
340 
341  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
342  PRINTF("get_cca_info: CMDSTA=0x%08lx\n", cmd_status);
343 
344  return RF_CORE_GET_CCA_INFO_ERROR;
345  }
346  }
347 
348  /* We have a valid CCA state. Return the CCA Info */
349  return *((uint8_t *)&cmd.ccaInfo);
350 }
351 /*---------------------------------------------------------------------------*/
352 /**
353  * \brief Reads the current signal strength (RSSI)
354  * \return The current RSSI in dBm or CMD_GET_RSSI_UNKNOWN
355  *
356  * This function reads the current RSSI on the currently configured
357  * channel.
358  */
359 static radio_value_t
360 get_rssi(void)
361 {
362  uint32_t cmd_status;
363  uint8_t was_off = 0;
364  rfc_CMD_IEEE_CCA_REQ_t cmd;
365 
366  /* If we are off, turn on first */
367  if(!rf_is_on()) {
368  was_off = 1;
369  if(on() != RF_CORE_CMD_OK) {
370  PRINTF("get_rssi: on() failed\n");
371  return RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
372  }
373  }
374 
375  memset(&cmd, 0x00, sizeof(cmd));
376  cmd.ccaInfo.ccaEnergy = RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID;
377 
378  while(cmd.ccaInfo.ccaEnergy == RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID) {
379  memset(&cmd, 0x00, sizeof(cmd));
380  cmd.commandNo = CMD_IEEE_CCA_REQ;
381 
382  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
383  PRINTF("get_rssi: CMDSTA=0x%08lx\n", cmd_status);
384 
385  /* Make sure to return RSSI unknown */
386  cmd.currentRssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
387  break;
388  }
389  }
390 
391  /* If we were off, turn back off */
392  if(was_off) {
393  off();
394  }
395 
396  return cmd.currentRssi;
397 }
398 /*---------------------------------------------------------------------------*/
399 /* Returns the current TX power in dBm */
400 static radio_value_t
401 get_tx_power(void)
402 {
403  return tx_power_current->dbm;
404 }
405 /*---------------------------------------------------------------------------*/
406 /*
407  * Set TX power to 'at least' power dBm
408  * This works with a lookup table. If the value of 'power' does not exist in
409  * the lookup table, TXPOWER will be set to the immediately higher available
410  * value
411  */
412 static void
413 set_tx_power(radio_value_t power)
414 {
415  uint32_t cmd_status;
416  int i;
417  rfc_CMD_SET_TX_POWER_t cmd;
418 
419  /* First, find the correct setting and save it */
420  for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
421  if(power <= output_power[i].dbm) {
422  tx_power_current = &output_power[i];
423  break;
424  }
425  }
426 
427  /*
428  * If the core is not accessible, the new setting will be applied next
429  * time we send CMD_RADIO_SETUP, so we don't need to do anything further.
430  * If the core is accessible, we can apply the new setting immediately with
431  * CMD_SET_TX_POWER
432  */
433  if(rf_core_is_accessible() == RF_CORE_NOT_ACCESSIBLE) {
434  return;
435  }
436 
437  memset(&cmd, 0x00, sizeof(cmd));
438  cmd.commandNo = CMD_SET_TX_POWER;
439  cmd.txPower = output_power[i].tx_power;
440 
441  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
442  PRINTF("set_tx_power: CMDSTA=0x%08lx\n", cmd_status);
443  }
444 }
445 /*---------------------------------------------------------------------------*/
446 static uint8_t
447 rf_radio_setup()
448 {
449  uint32_t cmd_status;
450  rfc_CMD_RADIO_SETUP_t cmd;
451 
452  rf_switch_select_path(RF_SWITCH_PATH_2_4GHZ);
453 
454  /* Create radio setup command */
455  rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP);
456 
457  cmd.txPower = tx_power_current->tx_power;
458  cmd.pRegOverride = ieee_overrides;
459  cmd.config.frontEndMode = RF_CORE_RADIO_SETUP_FRONT_END_MODE;
460  cmd.config.biasMode = RF_CORE_RADIO_SETUP_BIAS_MODE;
461  cmd.mode = 1;
462 
463  /* Send Radio setup to RF Core */
464  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
465  PRINTF("rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
466  cmd_status, cmd.status);
467  return RF_CORE_CMD_ERROR;
468  }
469 
470  /* Wait until radio setup is done */
471  if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
472  PRINTF("rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n",
473  cmd_status, cmd.status);
474  return RF_CORE_CMD_ERROR;
475  }
476 
477  return RF_CORE_CMD_OK;
478 }
479 /*---------------------------------------------------------------------------*/
480 /**
481  * \brief Set up radio in IEEE802.15.4 RX mode
482  *
483  * \return RF_CORE_CMD_OK Succeeded
484  * \return RF_CORE_CMD_ERROR Failed
485  *
486  * This function assumes that cmd_ieee_rx_buf has been previously populated
487  * with correct values. This can be done through init_rf_params (sets defaults)
488  * or through Contiki's extended RF API (set_value, set_object)
489  */
490 static uint8_t
492 {
493  uint32_t cmd_status;
494  int ret;
495 
496  ret = rf_core_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status);
497 
498  if(ret != RF_CORE_CMD_OK) {
499  PRINTF("rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
500  ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
501  return RF_CORE_CMD_ERROR;
502  }
503 
504  RTIMER_BUSYWAIT_UNTIL(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE,
505  RF_CORE_ENTER_RX_TIMEOUT);
506 
507  /* Wait to enter RX */
508  if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
509  PRINTF("rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n",
510  cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
511  return RF_CORE_CMD_ERROR;
512  }
513 
514  return ret;
515 }
516 /*---------------------------------------------------------------------------*/
517 static void
518 init_rx_buffers(void)
519 {
520  rfc_dataEntry_t *entry;
521 
522  entry = (rfc_dataEntry_t *)rx_buf_0;
523  entry->pNextEntry = rx_buf_1;
524  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
525  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
526 
527  entry = (rfc_dataEntry_t *)rx_buf_1;
528  entry->pNextEntry = rx_buf_2;
529  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
530  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
531 
532  entry = (rfc_dataEntry_t *)rx_buf_2;
533  entry->pNextEntry = rx_buf_3;
534  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
535  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
536 
537  entry = (rfc_dataEntry_t *)rx_buf_3;
538  entry->pNextEntry = rx_buf_0;
539  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
540  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
541 }
542 /*---------------------------------------------------------------------------*/
543 static void
544 init_rf_params(void)
545 {
546  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
547 
548  memset(cmd_ieee_rx_buf, 0x00, RF_CMD_BUFFER_SIZE);
549 
550  cmd->commandNo = CMD_IEEE_RX;
551  cmd->status = RF_CORE_RADIO_OP_STATUS_IDLE;
552  cmd->pNextOp = NULL;
553  cmd->startTime = 0x00000000;
554  cmd->startTrigger.triggerType = TRIG_NOW;
555  cmd->condition.rule = COND_NEVER;
556  cmd->channel = IEEE802154_DEFAULT_CHANNEL;
557 
558  cmd->rxConfig.bAutoFlushCrc = 1;
559  cmd->rxConfig.bAutoFlushIgn = 0;
560  cmd->rxConfig.bIncludePhyHdr = 0;
561  cmd->rxConfig.bIncludeCrc = RF_CORE_RX_BUF_INCLUDE_CRC;
562  cmd->rxConfig.bAppendRssi = RF_CORE_RX_BUF_INCLUDE_RSSI;
563  cmd->rxConfig.bAppendCorrCrc = RF_CORE_RX_BUF_INCLUDE_CORR;
564  cmd->rxConfig.bAppendSrcInd = 0;
565  cmd->rxConfig.bAppendTimestamp = RF_CORE_RX_BUF_INCLUDE_TIMESTAMP;
566 
567  cmd->pRxQ = &rx_data_queue;
568  cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
569 
570 #if IEEE_MODE_PROMISCOUS
571  cmd->frameFiltOpt.frameFiltEn = 0;
572 #else
573  cmd->frameFiltOpt.frameFiltEn = 1;
574 #endif
575 
576  cmd->frameFiltOpt.frameFiltStop = 1;
577 
578 #if IEEE_MODE_AUTOACK
579  cmd->frameFiltOpt.autoAckEn = 1;
580 #else
581  cmd->frameFiltOpt.autoAckEn = 0;
582 #endif
583 
584  cmd->frameFiltOpt.slottedAckEn = 0;
585  cmd->frameFiltOpt.autoPendEn = 0;
586  cmd->frameFiltOpt.defaultPend = 0;
587  cmd->frameFiltOpt.bPendDataReqOnly = 0;
588  cmd->frameFiltOpt.bPanCoord = 0;
589  cmd->frameFiltOpt.maxFrameVersion = 2;
590  cmd->frameFiltOpt.bStrictLenFilter = 0;
591 
592  /* Receive all frame types */
593  cmd->frameTypes.bAcceptFt0Beacon = 1;
594  cmd->frameTypes.bAcceptFt1Data = 1;
595  cmd->frameTypes.bAcceptFt2Ack = 1;
596  cmd->frameTypes.bAcceptFt3MacCmd = 1;
597  cmd->frameTypes.bAcceptFt4Reserved = 1;
598  cmd->frameTypes.bAcceptFt5Reserved = 1;
599  cmd->frameTypes.bAcceptFt6Reserved = 1;
600  cmd->frameTypes.bAcceptFt7Reserved = 1;
601 
602  /* Configure CCA settings */
603  cmd->ccaOpt.ccaEnEnergy = 1;
604  cmd->ccaOpt.ccaEnCorr = 1;
605  cmd->ccaOpt.ccaEnSync = 1;
606  cmd->ccaOpt.ccaCorrOp = 1;
607  cmd->ccaOpt.ccaSyncOp = 0;
608  cmd->ccaOpt.ccaCorrThr = 3;
609 
610  cmd->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD;
611 
612  cmd->numExtEntries = 0x00;
613  cmd->numShortEntries = 0x00;
614  cmd->pExtEntryList = 0;
615  cmd->pShortEntryList = 0;
616 
617  cmd->endTrigger.triggerType = TRIG_NEVER;
618  cmd->endTime = 0x00000000;
619 
620  /* set address filter command */
621  filter_cmd.commandNo = CMD_IEEE_MOD_FILT;
622  memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt));
623  memcpy(&filter_cmd.newFrameTypes, &cmd->frameTypes, sizeof(cmd->frameTypes));
624 }
625 /*---------------------------------------------------------------------------*/
626 static int
627 rx_on(void)
628 {
629  int ret;
630 
631  /* Get status of running IEEE_RX (if any) */
632  if(rf_is_on()) {
633  PRINTF("rx_on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
634  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
635  return RF_CORE_CMD_OK;
636  }
637 
638  /* Put CPE in RX using the currently configured parameters */
639  ret = rf_cmd_ieee_rx();
640 
641  if(ret) {
642  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
643  }
644 
645  return ret;
646 }
647 /*---------------------------------------------------------------------------*/
648 static int
649 rx_off(void)
650 {
651  uint32_t cmd_status;
652  int ret;
653 
654  /* If we are off, do nothing */
655  if(!rf_is_on()) {
656  return RF_CORE_CMD_OK;
657  }
658 
659  /* Wait for ongoing ACK TX to finish */
660  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
661 
662  /* Send a CMD_ABORT command to RF Core */
663  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
664  PRINTF("RX off: CMD_ABORT status=0x%08lx\n", cmd_status);
665  /* Continue nonetheless */
666  }
667 
668  RTIMER_BUSYWAIT_UNTIL(!rf_is_on(), RF_CORE_TURN_OFF_TIMEOUT);
669 
670  if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED ||
671  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) {
672  /* Stopped gracefully */
673  ret = RF_CORE_CMD_OK;
674  } else {
675  PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
676  ret = RF_CORE_CMD_ERROR;
677  }
678 
679  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
680 
681  return ret;
682 }
683 /*---------------------------------------------------------------------------*/
684 static uint8_t
685 request(void)
686 {
687  /*
688  * We rely on the RDC layer to turn us on and off. Thus, if we are on we
689  * will only allow sleep, standby otherwise
690  */
691  if(rf_is_on()) {
692  return LPM_MODE_SLEEP;
693  }
694 
695  return LPM_MODE_MAX_SUPPORTED;
696 }
697 /*---------------------------------------------------------------------------*/
698 LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
699 /*---------------------------------------------------------------------------*/
700 static void
701 soft_off(void)
702 {
703  uint32_t cmd_status;
704  volatile rfc_radioOp_t *cmd = rf_core_get_last_radio_op();
705 
706  if(!rf_core_is_accessible()) {
707  return;
708  }
709 
710  PRINTF("soft_off: Aborting 0x%04x, Status=0x%04x\n", cmd->commandNo,
711  cmd->status);
712 
713  /* Send a CMD_ABORT command to RF Core */
714  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
715  PRINTF("soft_off: CMD_ABORT status=0x%08lx\n", cmd_status);
716  return;
717  }
718 
719  RTIMER_BUSYWAIT_UNTIL((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) !=
720  RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_CORE_TURN_OFF_TIMEOUT);
721 }
722 /*---------------------------------------------------------------------------*/
723 static uint8_t
724 soft_on(void)
725 {
726  if(rf_radio_setup() != RF_CORE_CMD_OK) {
727  PRINTF("on: radio_setup() failed\n");
728  return RF_CORE_CMD_ERROR;
729  }
730 
731  return rx_on();
732 }
733 /*---------------------------------------------------------------------------*/
734 static const rf_core_primary_mode_t mode_ieee = {
735  soft_off,
736  soft_on,
737  rf_is_on,
738  RAT_TIMESTAMP_OFFSET_2_4_GHZ
739 };
740 /*---------------------------------------------------------------------------*/
741 static int
742 init(void)
743 {
744  lpm_register_module(&cc26xx_rf_lpm_module);
745 
747 
748  /* Initialise RX buffers */
749  memset(rx_buf_0, 0, RX_BUF_SIZE);
750  memset(rx_buf_1, 0, RX_BUF_SIZE);
751  memset(rx_buf_2, 0, RX_BUF_SIZE);
752  memset(rx_buf_3, 0, RX_BUF_SIZE);
753 
754  /* Set of RF Core data queue. Circular buffer, no last entry */
755  rx_data_queue.pCurrEntry = rx_buf_0;
756 
757  rx_data_queue.pLastEntry = NULL;
758 
759  /* Initialize current read pointer to first element (used in ISR) */
760  rx_read_entry = rx_buf_0;
761 
762  /* Populate the RF parameters data structure with default values */
763  init_rf_params();
764 
765  if(on() != RF_CORE_CMD_OK) {
766  PRINTF("init: on() failed\n");
767  return RF_CORE_CMD_ERROR;
768  }
769 
770  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
771 
772  rf_core_primary_mode_register(&mode_ieee);
773 
775 
776  process_start(&rf_core_process, NULL);
777  return 1;
778 }
779 /*---------------------------------------------------------------------------*/
780 static int
781 prepare(const void *payload, unsigned short payload_len)
782 {
783  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > MAX_PAYLOAD_LEN) {
784  return RADIO_TX_ERR;
785  }
786 
787  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
788  return 0;
789 }
790 /*---------------------------------------------------------------------------*/
791 static int
792 transmit(unsigned short transmit_len)
793 {
794  int ret;
795  uint8_t was_off = 0;
796  uint32_t cmd_status;
797  uint16_t stat;
798  uint8_t tx_active = 0;
799  rtimer_clock_t t0;
800  volatile rfc_CMD_IEEE_TX_t cmd;
801 
802  if(transmit_len > MAX_PAYLOAD_LEN) {
803  PRINTF("transmit: too long\n");
804  return RADIO_TX_ERR;
805  }
806 
807  if(!rf_is_on()) {
808  was_off = 1;
809  if(on() != RF_CORE_CMD_OK) {
810  PRINTF("transmit: on() failed\n");
811  return RADIO_TX_ERR;
812  }
813  }
814 
815  /*
816  * We are certainly not TXing a frame as a result of CMD_IEEE_TX, but we may
817  * be in the process of TXing an ACK. In that case, wait for the TX to finish
818  * or return after approx TX_WAIT_TIMEOUT
819  */
820  t0 = RTIMER_NOW();
821 
822  do {
823  tx_active = transmitting();
824  } while(tx_active == 1 &&
825  (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + RF_CORE_TX_TIMEOUT)));
826 
827  if(tx_active) {
828  PRINTF("transmit: Already TXing and wait timed out\n");
829 
830  if(was_off) {
831  off();
832  }
833 
834  return RADIO_TX_COLLISION;
835  }
836 
837  /* Send the CMD_IEEE_TX command */
838  rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_IEEE_TX);
839 
840  cmd.payloadLen = transmit_len;
841  cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
842 
843  cmd.startTime = 0;
844  cmd.startTrigger.triggerType = TRIG_NOW;
845 
846  /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
847  rf_core_cmd_done_en(true);
848 
849  ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
850 
851  if(ret) {
852  /* If we enter here, TX actually started */
853  ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
854 
855  /* Idle away while the command is running */
856  while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
857  == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
858  /* Note: for now sleeping while Tx'ing in polling mode is disabled.
859  * To enable it:
860  * 1) make the `lpm_sleep()` call here unconditional;
861  * 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR.
862  */
863  if(!rf_core_poll_mode) {
864  lpm_sleep();
865  }
866  }
867 
868  stat = cmd.status;
869 
870  if(stat == RF_CORE_RADIO_OP_STATUS_IEEE_DONE_OK) {
871  /* Sent OK */
872  ret = RADIO_TX_OK;
873  } else {
874  /* Operation completed, but frame was not sent */
875  PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret,
876  cmd_status, stat);
877  ret = RADIO_TX_ERR;
878  }
879  } else {
880  /* Failure sending the CMD_IEEE_TX command */
881  PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
882  ret, cmd_status, cmd.status);
883 
884  ret = RADIO_TX_ERR;
885  }
886 
887  /*
888  * Update ENERGEST state here, before a potential call to off(), which
889  * will correctly update it if required.
890  */
891  ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
892 
893  /*
894  * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
895  * except when we are transmitting
896  */
898 
899  if(was_off) {
900  off();
901  }
902 
903  return ret;
904 }
905 /*---------------------------------------------------------------------------*/
906 static int
907 send(const void *payload, unsigned short payload_len)
908 {
909  prepare(payload, payload_len);
910  return transmit(payload_len);
911 }
912 /*---------------------------------------------------------------------------*/
913 static void
914 release_data_entry(void)
915 {
916  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
917 
918  /* Clear the length byte */
919  rx_read_entry[8] = 0;
920 
921  /* Set status to 0 "Pending" in element */
922  entry->status = DATA_ENTRY_STATUS_PENDING;
923  rx_read_entry = entry->pNextEntry;
924 }
925 /*---------------------------------------------------------------------------*/
926 static int
927 read_frame(void *buf, unsigned short buf_len)
928 {
929  int len = 0;
930  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
931  uint32_t rat_timestamp;
932 
933  /* wait for entry to become finished */
934  rtimer_clock_t t0 = RTIMER_NOW();
935  while(entry->status == DATA_ENTRY_STATUS_BUSY
936  && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 250)));
937 
938  if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
939  /* No available data */
940  return 0;
941  }
942 
943  len = rx_read_entry[RX_BUF_LENGTH_OFFSET];
944  if(len <= RX_BUF_METADATA_SIZE) {
945  PRINTF("RF: too short!");
946 
947  release_data_entry();
948  return 0;
949  }
950 
951  len -= RX_BUF_METADATA_SIZE;
952  if(len > buf_len) {
953  PRINTF("RF: too long\n");
954 
955  release_data_entry();
956  return 0;
957  }
958 
959  memcpy(buf, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET, len);
960 
961  rf_core_last_rssi = (int8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len];
962  rf_core_last_corr_lqi = (uint8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 1] & STATUS_CORRELATION;
963 
964  /* get the timestamp */
965  memcpy(&rat_timestamp, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET + len + 2, 4);
966 
967  rf_core_last_packet_timestamp = rf_core_convert_rat_to_rtimer(rat_timestamp);
968 
969  if(!rf_core_poll_mode) {
970  /* Not in poll mode: packetbuf should not be accessed in interrupt context.
971  * In poll mode, the last packet RSSI and link quality can be obtained through
972  * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
973  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf_core_last_rssi);
974  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf_core_last_corr_lqi);
975  }
976 
977  release_data_entry();
978 
979  return len;
980 }
981 /*---------------------------------------------------------------------------*/
982 static int
983 channel_clear(void)
984 {
985  uint8_t was_off = 0;
986  uint8_t cca_info;
987  int ret = RF_CORE_CCA_CLEAR;
988 
989  /*
990  * If we are in the middle of a BLE operation, we got called by ContikiMAC
991  * from within an interrupt context. Indicate a clear channel
992  */
993  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
994  PRINTF("channel_clear: Interrupt context but BLE in progress\n");
995  return RF_CORE_CCA_CLEAR;
996  }
997 
998  if(rf_is_on()) {
999  /*
1000  * Wait for potential leftover ACK still being sent.
1001  * Strictly speaking, if we are TXing an ACK then the channel is not clear.
1002  * However, channel_clear is only ever called to determine whether there is
1003  * someone else's packet in the air, not ours.
1004  *
1005  * We could probably even simply return that the channel is clear
1006  */
1007  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
1008  } else {
1009  was_off = 1;
1010  if(on() != RF_CORE_CMD_OK) {
1011  PRINTF("channel_clear: on() failed\n");
1012  if(was_off) {
1013  off();
1014  }
1015  return RF_CORE_CCA_CLEAR;
1016  }
1017  }
1018 
1019  cca_info = get_cca_info();
1020 
1021  if(cca_info == RF_CORE_GET_CCA_INFO_ERROR) {
1022  PRINTF("channel_clear: CCA error\n");
1023  ret = RF_CORE_CCA_CLEAR;
1024  } else {
1025  /*
1026  * cca_info bits 1:0 - ccaStatus
1027  * Return 1 (clear) if idle or invalid.
1028  */
1029  ret = (cca_info & 0x03) != RF_CORE_CMD_CCA_REQ_CCA_STATE_BUSY;
1030  }
1031 
1032  if(was_off) {
1033  off();
1034  }
1035 
1036  return ret;
1037 }
1038 /*---------------------------------------------------------------------------*/
1039 static int
1040 receiving_packet(void)
1041 {
1042  uint8_t cca_info;
1043 
1044  /*
1045  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1046  * from within an interrupt context. We are not receiving
1047  */
1048  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1049  PRINTF("receiving_packet: Interrupt context but BLE in progress\n");
1050  return 0;
1051  }
1052 
1053  /* If we are off, we are not receiving */
1054  if(!rf_is_on()) {
1055  PRINTF("receiving_packet: We were off\n");
1056  return 0;
1057  }
1058 
1059  /* If we are transmitting (can only be an ACK here), we are not receiving */
1060  if(transmitting()) {
1061  PRINTF("receiving_packet: We were TXing\n");
1062  return 0;
1063  }
1064 
1065  cca_info = get_cca_info();
1066 
1067  /* If we can't read CCA info, return "not receiving" */
1068  if(cca_info == RF_CORE_GET_CCA_INFO_ERROR) {
1069  return 0;
1070  }
1071 
1072  /* If sync has been seen, return 1 (receiving) */
1073  if(cca_info & RF_CORE_CMD_CCA_REQ_CCA_SYNC_BUSY) {
1074  return 1;
1075  }
1076 
1077  return 0;
1078 }
1079 /*---------------------------------------------------------------------------*/
1080 static int
1081 pending_packet(void)
1082 {
1083  volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1084  int rv = 0;
1085 
1086  /* Go through all RX buffers and check their status */
1087  do {
1088  if(entry->status == DATA_ENTRY_STATUS_FINISHED
1089  || entry->status == DATA_ENTRY_STATUS_BUSY) {
1090  rv = 1;
1091  if(!rf_core_poll_mode) {
1092  process_poll(&rf_core_process);
1093  }
1094  }
1095 
1096  entry = (rfc_dataEntry_t *)entry->pNextEntry;
1097  } while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1098 
1099  /* If we didn't find an entry at status finished, no frames are pending */
1100  return rv;
1101 }
1102 /*---------------------------------------------------------------------------*/
1103 static int
1104 on(void)
1105 {
1106  /*
1107  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1108  * from within an interrupt context. Abort, but pretend everything is OK.
1109  */
1110  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1111  PRINTF("on: Interrupt context but BLE in progress\n");
1112  return RF_CORE_CMD_OK;
1113  }
1114 
1115  /*
1116  * Request the HF XOSC as the source for the HF clock. Needed before we can
1117  * use the FS. This will only request, it will _not_ perform the switch.
1118  */
1120 
1121  if(rf_is_on()) {
1122  PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
1123  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
1124  return RF_CORE_CMD_OK;
1125  }
1126 
1127  init_rx_buffers();
1128 
1129  /*
1130  * Trigger a switch to the XOSC, so that we can subsequently use the RF FS
1131  * This will block until the XOSC is actually ready, but give how we
1132  * requested it early on, this won't be too long a wait.
1133  * This should be done before starting the RAT.
1134  */
1136 
1137  if(rf_core_boot() != RF_CORE_CMD_OK) {
1138  PRINTF("on: rf_core_boot() failed\n");
1139  return RF_CORE_CMD_ERROR;
1140  }
1141 
1143 
1144  if(rf_radio_setup() != RF_CORE_CMD_OK) {
1145  PRINTF("on: radio_setup() failed\n");
1146  return RF_CORE_CMD_ERROR;
1147  }
1148 
1149  return rx_on();
1150 }
1151 /*---------------------------------------------------------------------------*/
1152 static int
1153 off(void)
1154 {
1155  /*
1156  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1157  * from within an interrupt context. Abort, but pretend everything is OK.
1158  */
1159  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1160  PRINTF("off: Interrupt context but BLE in progress\n");
1161  return RF_CORE_CMD_OK;
1162  }
1163 
1164  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
1165 
1166  /* stopping the rx explicitly results in lower sleep-mode power usage */
1167  rx_off();
1169 
1170  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1171 
1172 #if !CC2650_FAST_RADIO_STARTUP
1173  /* Switch HF clock source to the RCOSC to preserve power.
1174  * This must be done after stopping RAT.
1175  */
1177 #endif
1178 
1179  /* We pulled the plug, so we need to restore the status manually */
1180  ((rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
1181 
1182  /*
1183  * Just in case there was an ongoing RX (which started after we begun the
1184  * shutdown sequence), we don't want to leave the buffer in state == ongoing
1185  */
1186  if(((rfc_dataEntry_t *)rx_buf_0)->status == DATA_ENTRY_STATUS_BUSY) {
1187  ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING;
1188  }
1189  if(((rfc_dataEntry_t *)rx_buf_1)->status == DATA_ENTRY_STATUS_BUSY) {
1190  ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING;
1191  }
1192  if(((rfc_dataEntry_t *)rx_buf_2)->status == DATA_ENTRY_STATUS_BUSY) {
1193  ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING;
1194  }
1195  if(((rfc_dataEntry_t *)rx_buf_3)->status == DATA_ENTRY_STATUS_BUSY) {
1196  ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING;
1197  }
1198 
1199  return RF_CORE_CMD_OK;
1200 }
1201 /*---------------------------------------------------------------------------*/
1202 /* Enable or disable CCA before sending */
1203 static radio_result_t
1204 set_send_on_cca(uint8_t enable)
1205 {
1206  if(enable) {
1207  /* this driver does not have support for CCA on Tx */
1209  }
1210  return RADIO_RESULT_OK;
1211 }
1212 /*---------------------------------------------------------------------------*/
1213 static radio_result_t
1214 get_value(radio_param_t param, radio_value_t *value)
1215 {
1216  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1217 
1218  if(!value) {
1220  }
1221 
1222  switch(param) {
1224  /* On / off */
1226  return RADIO_RESULT_OK;
1227  case RADIO_PARAM_CHANNEL:
1228  *value = (radio_value_t)cmd->channel;
1229  return RADIO_RESULT_OK;
1230  case RADIO_PARAM_PAN_ID:
1231  *value = (radio_value_t)cmd->localPanID;
1232  return RADIO_RESULT_OK;
1234  *value = (radio_value_t)cmd->localShortAddr;
1235  return RADIO_RESULT_OK;
1236  case RADIO_PARAM_RX_MODE:
1237  *value = 0;
1238  if(cmd->frameFiltOpt.frameFiltEn) {
1239  *value |= RADIO_RX_MODE_ADDRESS_FILTER;
1240  }
1241  if(cmd->frameFiltOpt.autoAckEn) {
1242  *value |= RADIO_RX_MODE_AUTOACK;
1243  }
1244  if(rf_core_poll_mode) {
1245  *value |= RADIO_RX_MODE_POLL_MODE;
1246  }
1247 
1248  return RADIO_RESULT_OK;
1249  case RADIO_PARAM_TX_MODE:
1250  *value = 0;
1251  return RADIO_RESULT_OK;
1252  case RADIO_PARAM_TXPOWER:
1253  *value = get_tx_power();
1254  return RADIO_RESULT_OK;
1256  *value = cmd->ccaRssiThr;
1257  return RADIO_RESULT_OK;
1258  case RADIO_PARAM_RSSI:
1259  *value = get_rssi();
1260 
1261  if(*value == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) {
1262  return RADIO_RESULT_ERROR;
1263  } else {
1264  return RADIO_RESULT_OK;
1265  }
1267  *value = IEEE_MODE_CHANNEL_MIN;
1268  return RADIO_RESULT_OK;
1270  *value = IEEE_MODE_CHANNEL_MAX;
1271  return RADIO_RESULT_OK;
1273  *value = OUTPUT_POWER_MIN;
1274  return RADIO_RESULT_OK;
1276  *value = OUTPUT_POWER_MAX;
1277  return RADIO_RESULT_OK;
1278  case RADIO_PARAM_LAST_RSSI:
1279  *value = rf_core_last_rssi;
1280  return RADIO_RESULT_OK;
1282  *value = rf_core_last_corr_lqi;
1283  return RADIO_RESULT_OK;
1285  *value = (radio_value_t)RADIO_PHY_OVERHEAD;
1286  return RADIO_RESULT_OK;
1288  *value = (radio_value_t)RADIO_BYTE_AIR_TIME;
1289  return RADIO_RESULT_OK;
1291  *value = (radio_value_t)RADIO_DELAY_BEFORE_TX;
1292  return RADIO_RESULT_OK;
1294  *value = (radio_value_t)RADIO_DELAY_BEFORE_RX;
1295  return RADIO_RESULT_OK;
1297  *value = (radio_value_t)RADIO_DELAY_BEFORE_DETECT;
1298  return RADIO_RESULT_OK;
1299  case RADIO_CONST_MAX_PAYLOAD_LEN:
1300  *value = (radio_value_t)MAX_PAYLOAD_LEN;
1301  return RADIO_RESULT_OK;
1302  default:
1304  }
1305 }
1306 /*---------------------------------------------------------------------------*/
1307 static radio_result_t
1308 set_value(radio_param_t param, radio_value_t value)
1309 {
1311  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1312  uint8_t old_poll_mode;
1313 
1314  switch(param) {
1316  if(value == RADIO_POWER_MODE_ON) {
1317  if(on() != RF_CORE_CMD_OK) {
1318  PRINTF("set_value: on() failed (1)\n");
1319  return RADIO_RESULT_ERROR;
1320  }
1321  return RADIO_RESULT_OK;
1322  }
1323  if(value == RADIO_POWER_MODE_OFF) {
1324  off();
1325  return RADIO_RESULT_OK;
1326  }
1328  case RADIO_PARAM_CHANNEL:
1329  if(value < IEEE_MODE_CHANNEL_MIN ||
1330  value > IEEE_MODE_CHANNEL_MAX) {
1332  }
1333 
1334  /* Note: this return may lead to long periods when RAT and RTC are not resynchronized */
1335  if(cmd->channel == (uint8_t)value) {
1336  /* We already have that very same channel configured.
1337  * Nothing to do here. */
1338  return RADIO_RESULT_OK;
1339  }
1340 
1341  cmd->channel = (uint8_t)value;
1342  break;
1343  case RADIO_PARAM_PAN_ID:
1344  cmd->localPanID = (uint16_t)value;
1345  break;
1347  cmd->localShortAddr = (uint16_t)value;
1348  break;
1349  case RADIO_PARAM_RX_MODE:
1350  {
1351  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
1354  }
1355 
1356  cmd->frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
1357  cmd->frameFiltOpt.frameFiltStop = 1;
1358  cmd->frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
1359  cmd->frameFiltOpt.slottedAckEn = 0;
1360  cmd->frameFiltOpt.autoPendEn = 0;
1361  cmd->frameFiltOpt.defaultPend = 0;
1362  cmd->frameFiltOpt.bPendDataReqOnly = 0;
1363  cmd->frameFiltOpt.bPanCoord = 0;
1364  cmd->frameFiltOpt.bStrictLenFilter = 0;
1365 
1366  old_poll_mode = rf_core_poll_mode;
1367  rf_core_poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
1368  if(rf_core_poll_mode == old_poll_mode) {
1369  uint32_t cmd_status;
1370 
1371  /* do not turn the radio on and off, just send an update command */
1372  memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt));
1373 
1374  if(rf_core_send_cmd((uint32_t)&filter_cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
1375  PRINTF("setting address filter failed: CMDSTA=0x%08lx\n", cmd_status);
1376  return RADIO_RESULT_ERROR;
1377  }
1378  return RADIO_RESULT_OK;
1379  }
1380  break;
1381  }
1382 
1383  case RADIO_PARAM_TX_MODE:
1384  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1386  }
1387  return set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1388 
1389  case RADIO_PARAM_TXPOWER:
1390  if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1392  }
1393 
1394  set_tx_power(value);
1395 
1396  return RADIO_RESULT_OK;
1397 
1399  cmd->ccaRssiThr = (int8_t)value;
1400  break;
1401 
1402  default:
1404  }
1405 
1406  /* If off, the new configuration will be applied the next time radio is started */
1407  if(!rf_is_on()) {
1408  return RADIO_RESULT_OK;
1409  }
1410 
1411  /* If we reach here we had no errors. Apply new settings */
1412  if(rx_off() != RF_CORE_CMD_OK) {
1413  PRINTF("set_value: rx_off() failed\n");
1414  rv = RADIO_RESULT_ERROR;
1415  }
1416 
1417  /* Restart the radio timer (RAT).
1418  This causes resynchronization between RAT and RTC: useful for TSCH. */
1419  if(rf_core_restart_rat() == RF_CORE_CMD_OK) {
1421  }
1422 
1423  if(rx_on() != RF_CORE_CMD_OK) {
1424  PRINTF("set_value: rx_on() failed\n");
1425  rv = RADIO_RESULT_ERROR;
1426  }
1427 
1428  return rv;
1429 }
1430 /*---------------------------------------------------------------------------*/
1431 static radio_result_t
1432 get_object(radio_param_t param, void *dest, size_t size)
1433 {
1434  uint8_t *target;
1435  uint8_t *src;
1436  int i;
1437  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1438 
1439  if(param == RADIO_PARAM_64BIT_ADDR) {
1440  if(size != 8 || !dest) {
1442  }
1443 
1444  target = dest;
1445  src = (uint8_t *)(&cmd->localExtAddr);
1446 
1447  for(i = 0; i < 8; i++) {
1448  target[i] = src[7 - i];
1449  }
1450 
1451  return RADIO_RESULT_OK;
1452  }
1453 
1454  if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
1455  if(size != sizeof(rtimer_clock_t) || !dest) {
1457  }
1458  *(rtimer_clock_t *)dest = rf_core_last_packet_timestamp;
1459 
1460  return RADIO_RESULT_OK;
1461  }
1462 
1464 }
1465 /*---------------------------------------------------------------------------*/
1466 static radio_result_t
1467 set_object(radio_param_t param, const void *src, size_t size)
1468 {
1470  int i;
1471  uint8_t *dst;
1472  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1473 
1474  if(param == RADIO_PARAM_64BIT_ADDR) {
1475  if(size != 8 || !src) {
1477  }
1478 
1479  dst = (uint8_t *)(&cmd->localExtAddr);
1480 
1481  for(i = 0; i < 8; i++) {
1482  dst[i] = ((uint8_t *)src)[7 - i];
1483  }
1484 
1485  /* If off, the new configuration will be applied the next time radio is started */
1486  if(!rf_is_on()) {
1487  return RADIO_RESULT_OK;
1488  }
1489 
1490  if(rx_off() != RF_CORE_CMD_OK) {
1491  PRINTF("set_object: rx_off() failed\n");
1492  rv = RADIO_RESULT_ERROR;
1493  }
1494 
1495  if(rx_on() != RF_CORE_CMD_OK) {
1496  PRINTF("set_object: rx_on() failed\n");
1497  rv = RADIO_RESULT_ERROR;
1498  }
1499 
1500  return rv;
1501  }
1503 }
1504 /*---------------------------------------------------------------------------*/
1505 const struct radio_driver ieee_mode_driver = {
1506  init,
1507  prepare,
1508  transmit,
1509  send,
1510  read_frame,
1511  channel_clear,
1514  on,
1515  off,
1516  get_value,
1517  set_value,
1518  get_object,
1519  set_object,
1520 };
1521 /*---------------------------------------------------------------------------*/
1522 /**
1523  * @}
1524  * @}
1525  */
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:762
void oscillators_request_hf_xosc(void)
Requests the HF XOSC as the source for the HF clock, but does not perform the actual switch...
Definition: oscillators.c:94
static uint8_t transmitting(void)
Check the RF&#39;s TX status.
Definition: ieee-mode.c:285
The delay in usec between turning on the radio and it being actually listening (able to hear a preamb...
Definition: radio.h:347
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:572
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
Definition: ieee-mode.c:491
The parameter is not supported.
Definition: radio.h:473
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.
Definition: ieee-mode.c:267
Header file for the energy estimation mechanism
TX failed due to a collision.
Definition: radio.h:503
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Definition: rf-core.c:534
Header file for the radio API
The delay in usec between a call to the radio API&#39;s transmit function and the end of SFD transmission...
Definition: radio.h:341
The maximum transmission power in dBm.
Definition: radio.h:318
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.
Definition: rf-core.c:372
Received signal strength indicator in dBm.
Definition: radio.h:218
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:676
The short address (16 bits) for the radio, which is used by the h/w filter.
Definition: radio.h:166
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:748
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver&#39;s buffers.
Definition: radio.h:689
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition: rf-core.c:410
The structure of a Contiki-NG radio device driver.
Definition: radio.h:526
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
Channel used for radio communication.
Definition: radio.h:134
The value argument was incorrect.
Definition: radio.h:474
The parameter was set/read successfully.
Definition: radio.h:472
void lpm_sleep(void)
Enter sleep mode.
Definition: lpm.c:379
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Definition: radio.h:664
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...
Definition: radio.h:88
An error occurred when getting/setting the parameter, but the arguments were otherwise correct...
Definition: radio.h:480
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition: radio.h:180
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
Header file for the CC13xx/CC26xx oscillator control.
The RSSI value of the last received packet.
Definition: radio.h:226
The physical layer header (PHR) + MAC layer footer (MFR) overhead in bytes.
Definition: radio.h:330
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
Definition: rf-core.c:652
Clear channel assessment threshold in dBm.
Definition: radio.h:205
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
Definition: oscillators.c:134
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.
Definition: rf-core.c:549
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:623
A data strcuture representing the radio&#39;s primary mode of operation.
Definition: rf-core.h:125
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:611
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
int(* off)(void)
Turn the radio off.
Definition: radio.h:721
The personal area network identifier (PAN ID), which is used by the h/w frame filtering functionality...
Definition: radio.h:150
The lowest radio channel number.
Definition: radio.h:303
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
Header file for the real-time timer module.
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
Definition: rf-core.c:577
static radio_value_t get_rssi(void)
Reads the current signal strength (RSSI)
Definition: ieee-mode.c:360
The highest radio channel number.
Definition: radio.h:308
The air time of one byte in usec, e.g.
Definition: radio.h:335
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Definition: rf-core.c:527
void rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
Prepare a buffer to host a Radio Op.
Definition: rf-core.c:540
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition: radio.h:443
uint8_t rf_ble_is_active()
Check whether the BLE beacond is currently active.
Definition: rf-ble.c:262
When getting the value of this parameter, the radio driver should indicate whether the radio is on or...
Definition: radio.h:119
Header file for the CC13xx/CC26xx BLE driver.
Header file with definitions related to RF switch support.
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:466
static uint8_t get_cca_info(void)
Returns CCA information.
Definition: ieee-mode.c:324
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Definition: rf-core.c:145
Header file for the CC13xx/CC26xx UART driver.
#define RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition: radio.h:448
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:547
The delay in usec between the end of SFD reception for an incoming frame and the radio API starting t...
Definition: radio.h:353
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:453
Link quality indicator of the last received packet.
Definition: radio.h:236
void oscillators_switch_to_hf_xosc(void)
Performs the switch to the XOSC.
Definition: oscillators.c:116
Long (64 bits) address for the radio, which is used by the address filter.
Definition: radio.h:255
The minimum transmission power in dBm.
Definition: radio.h:313
Radio powered on and able to receive frames.
Definition: radio.h:392
Transmission power in dBm.
Definition: radio.h:192
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Definition: rf-core.c:154
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.
Definition: lpm.h:96
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
Definition: rf-core.c:479
Include file for the Contiki low-layer network stack (NETSTACK)
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
Definition: rf-core.c:460
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:733
Default definitions of C compiler quirk work-arounds.
Last packet timestamp, of type rtimer_clock_t.
Definition: radio.h:278
An error occurred during transmission.
Definition: radio.h:498
uint8_t rf_core_boot()
Boot the RF Core.
Definition: rf-core.c:438
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:779
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:387
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition: rf-core.c:513
TX was successful and where an ACK was requested one was received.
Definition: radio.h:490
uint8_t rf_core_check_rat_overflow(void)
Check if RAT overflow has occured and increment the overflow counter if so.
Definition: rf-core.c:588
int(* on)(void)
Turn the radio on.
Definition: radio.h:703
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void lpm_register_module(lpm_registered_module_t *module)
Register a module for LPM notifications.
Definition: lpm.c:545
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
Definition: rf-core.c:220
#define RF_RADIO_OP_GET_STATUS(a)
Returns the current status of a running Radio Op command.
Definition: ieee-mode.c:133