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 #define DATA_ENTRY_LENSZ_NONE 0
185 #define DATA_ENTRY_LENSZ_BYTE 1
186 #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
187 
188 /* The size of the metadata (excluding the packet length field) */
189 #define RX_BUF_METADATA_SIZE \
190  (2 * RF_CORE_RX_BUF_INCLUDE_CRC \
191  + RF_CORE_RX_BUF_INCLUDE_RSSI \
192  + RF_CORE_RX_BUF_INCLUDE_CORR \
193  + 4 * RF_CORE_RX_BUF_INCLUDE_TIMESTAMP)
194 
195 /* The offset of the packet length in a rx buffer */
196 #define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t)
197 /* The offset of the packet data in a rx buffer */
198 #define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + 1)
199 
200 #define RX_BUF_SIZE (RX_BUF_DATA_OFFSET \
201  + NETSTACK_RADIO_MAX_PAYLOAD_LEN \
202  + RX_BUF_METADATA_SIZE)
203 
204 /* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */
205 static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
206 static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
207 static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN(4);
208 static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN(4);
209 
210 /* The RX Data Queue */
211 static dataQueue_t rx_data_queue = { 0 };
212 
213 /* Receive entry pointer to keep track of read items */
214 volatile static uint8_t *rx_read_entry;
215 /*---------------------------------------------------------------------------*/
216 /* The outgoing frame buffer */
217 #define TX_BUF_PAYLOAD_LEN 180
218 #define TX_BUF_HDR_LEN 2
219 
220 static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
221 /*---------------------------------------------------------------------------*/
222 #ifdef IEEE_MODE_CONF_BOARD_OVERRIDES
223 #define IEEE_MODE_BOARD_OVERRIDES IEEE_MODE_CONF_BOARD_OVERRIDES
224 #else
225 #define IEEE_MODE_BOARD_OVERRIDES
226 #endif
227 /*---------------------------------------------------------------------------*/
228 /* Overrides for IEEE 802.15.4, differential mode */
229 static uint32_t ieee_overrides[] = {
230  0x00354038, /* Synth: Set RTRIM (POTAILRESTRIM) to 5 */
231  0x4001402D, /* Synth: Correct CKVD latency setting (address) */
232  0x00608402, /* Synth: Correct CKVD latency setting (value) */
233 // 0x4001405D, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (address) */
234 // 0x1801F800, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (value) */
235  0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */
236  0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */
237  0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */
238  0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */
239  0x002B50DC, /* Adjust AGC DC filter */
240  0x05000243, /* Increase synth programming timeout */
241  0x002082C3, /* Increase synth programming timeout */
242  IEEE_MODE_BOARD_OVERRIDES
243  0xFFFFFFFF, /* End of override list */
244 };
245 /*---------------------------------------------------------------------------*/
246 static int on(void);
247 static int off(void);
248 /*---------------------------------------------------------------------------*/
249 /**
250  * \brief Checks whether the RFC domain is accessible and the RFC is in IEEE RX
251  * \return 1: RFC in RX mode (and therefore accessible too). 0 otherwise
252  */
253 static uint8_t
254 rf_is_on(void)
255 {
256  if(!rf_core_is_accessible()) {
257  return 0;
258  }
259 
260  return RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE;
261 }
262 /*---------------------------------------------------------------------------*/
263 /**
264  * \brief Check the RF's TX status
265  * \return 1 RF is transmitting
266  * \return 0 RF is not transmitting
267  *
268  * TX mode may be triggered either by a CMD_IEEE_TX or by the automatic
269  * transmission of an ACK frame.
270  */
271 static uint8_t
273 {
274  uint32_t cmd_status;
275  rfc_CMD_IEEE_CCA_REQ_t cmd;
276 
277  /* If we are off, we are not in TX */
278  if(!rf_core_is_accessible()) {
279  return 0;
280  }
281 
282  memset(&cmd, 0x00, sizeof(cmd));
283 
284  cmd.commandNo = CMD_IEEE_CCA_REQ;
285 
286  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
287  PRINTF("transmitting: CMDSTA=0x%08lx\n", cmd_status);
288  return 0;
289  }
290 
291  if((cmd.currentRssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) &&
292  (cmd.ccaInfo.ccaEnergy == RF_CORE_CMD_CCA_REQ_CCA_STATE_BUSY)) {
293  return 1;
294  }
295 
296  return 0;
297 }
298 /*---------------------------------------------------------------------------*/
299 /**
300  * \brief Returns CCA information
301  * \return RF_CORE_GET_CCA_INFO_ERROR if the RF was not on
302  * \return On success, the return value is formatted as per the ccaInfo field
303  * of CMD_IEEE_CCA_REQ
304  *
305  * It is the caller's responsibility to make sure the RF is on. This function
306  * will return RF_CORE_GET_CCA_INFO_ERROR if the RF is off
307  *
308  * This function will in fact wait for a valid CCA state
309  */
310 static uint8_t
312 {
313  uint32_t cmd_status;
314  rfc_CMD_IEEE_CCA_REQ_t cmd;
315 
316  if(!rf_is_on()) {
317  PRINTF("get_cca_info: Not on\n");
318  return RF_CORE_GET_CCA_INFO_ERROR;
319  }
320 
321  memset(&cmd, 0x00, sizeof(cmd));
322  cmd.ccaInfo.ccaState = RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID;
323 
324  while(cmd.ccaInfo.ccaState == RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID) {
325  memset(&cmd, 0x00, sizeof(cmd));
326  cmd.commandNo = CMD_IEEE_CCA_REQ;
327 
328  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
329  PRINTF("get_cca_info: CMDSTA=0x%08lx\n", cmd_status);
330 
331  return RF_CORE_GET_CCA_INFO_ERROR;
332  }
333  }
334 
335  /* We have a valid CCA state. Return the CCA Info */
336  return *((uint8_t *)&cmd.ccaInfo);
337 }
338 /*---------------------------------------------------------------------------*/
339 /**
340  * \brief Reads the current signal strength (RSSI)
341  * \return The current RSSI in dBm or CMD_GET_RSSI_UNKNOWN
342  *
343  * This function reads the current RSSI on the currently configured
344  * channel.
345  */
346 static radio_value_t
347 get_rssi(void)
348 {
349  uint32_t cmd_status;
350  uint8_t was_off = 0;
351  rfc_CMD_IEEE_CCA_REQ_t cmd;
352 
353  /* If we are off, turn on first */
354  if(!rf_is_on()) {
355  was_off = 1;
356  if(on() != RF_CORE_CMD_OK) {
357  PRINTF("get_rssi: on() failed\n");
358  return RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
359  }
360  }
361 
362  memset(&cmd, 0x00, sizeof(cmd));
363  cmd.ccaInfo.ccaEnergy = RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID;
364 
365  while(cmd.ccaInfo.ccaEnergy == RF_CORE_CMD_CCA_REQ_CCA_STATE_INVALID) {
366  memset(&cmd, 0x00, sizeof(cmd));
367  cmd.commandNo = CMD_IEEE_CCA_REQ;
368 
369  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
370  PRINTF("get_rssi: CMDSTA=0x%08lx\n", cmd_status);
371 
372  /* Make sure to return RSSI unknown */
373  cmd.currentRssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
374  break;
375  }
376  }
377 
378  /* If we were off, turn back off */
379  if(was_off) {
380  off();
381  }
382 
383  return cmd.currentRssi;
384 }
385 /*---------------------------------------------------------------------------*/
386 /* Returns the current TX power in dBm */
387 static radio_value_t
388 get_tx_power(void)
389 {
390  return tx_power_current->dbm;
391 }
392 /*---------------------------------------------------------------------------*/
393 /*
394  * Set TX power to 'at least' power dBm
395  * This works with a lookup table. If the value of 'power' does not exist in
396  * the lookup table, TXPOWER will be set to the immediately higher available
397  * value
398  */
399 static void
400 set_tx_power(radio_value_t power)
401 {
402  uint32_t cmd_status;
403  int i;
404  rfc_CMD_SET_TX_POWER_t cmd;
405 
406  /* First, find the correct setting and save it */
407  for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
408  if(power <= output_power[i].dbm) {
409  tx_power_current = &output_power[i];
410  break;
411  }
412  }
413 
414  /*
415  * If the core is not accessible, the new setting will be applied next
416  * time we send CMD_RADIO_SETUP, so we don't need to do anything further.
417  * If the core is accessible, we can apply the new setting immediately with
418  * CMD_SET_TX_POWER
419  */
420  if(rf_core_is_accessible() == RF_CORE_NOT_ACCESSIBLE) {
421  return;
422  }
423 
424  memset(&cmd, 0x00, sizeof(cmd));
425  cmd.commandNo = CMD_SET_TX_POWER;
426  cmd.txPower = output_power[i].tx_power;
427 
428  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
429  PRINTF("set_tx_power: CMDSTA=0x%08lx\n", cmd_status);
430  }
431 }
432 /*---------------------------------------------------------------------------*/
433 static uint8_t
434 rf_radio_setup()
435 {
436  uint32_t cmd_status;
437  rfc_CMD_RADIO_SETUP_t cmd;
438 
439  rf_switch_select_path(RF_SWITCH_PATH_2_4GHZ);
440 
441  /* Create radio setup command */
442  rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_RADIO_SETUP);
443 
444  cmd.txPower = tx_power_current->tx_power;
445  cmd.pRegOverride = ieee_overrides;
446  cmd.config.frontEndMode = RF_CORE_RADIO_SETUP_FRONT_END_MODE;
447  cmd.config.biasMode = RF_CORE_RADIO_SETUP_BIAS_MODE;
448  cmd.mode = 1;
449 
450  /* Send Radio setup to RF Core */
451  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
452  PRINTF("rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
453  cmd_status, cmd.status);
454  return RF_CORE_CMD_ERROR;
455  }
456 
457  /* Wait until radio setup is done */
458  if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
459  PRINTF("rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n",
460  cmd_status, cmd.status);
461  return RF_CORE_CMD_ERROR;
462  }
463 
464  return RF_CORE_CMD_OK;
465 }
466 /*---------------------------------------------------------------------------*/
467 /**
468  * \brief Set up radio in IEEE802.15.4 RX mode
469  *
470  * \return RF_CORE_CMD_OK Succeeded
471  * \return RF_CORE_CMD_ERROR Failed
472  *
473  * This function assumes that cmd_ieee_rx_buf has been previously populated
474  * with correct values. This can be done through init_rf_params (sets defaults)
475  * or through Contiki's extended RF API (set_value, set_object)
476  */
477 static uint8_t
479 {
480  uint32_t cmd_status;
481  int ret;
482 
483  ret = rf_core_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status);
484 
485  if(ret != RF_CORE_CMD_OK) {
486  PRINTF("rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
487  ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
488  return RF_CORE_CMD_ERROR;
489  }
490 
491  RTIMER_BUSYWAIT_UNTIL(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_CORE_RADIO_OP_STATUS_ACTIVE,
492  RF_CORE_ENTER_RX_TIMEOUT);
493 
494  /* Wait to enter RX */
495  if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
496  PRINTF("rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n",
497  cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
498  return RF_CORE_CMD_ERROR;
499  }
500 
501  return ret;
502 }
503 /*---------------------------------------------------------------------------*/
504 static void
505 init_rx_buffers(void)
506 {
507  rfc_dataEntry_t *entry;
508 
509  entry = (rfc_dataEntry_t *)rx_buf_0;
510  entry->pNextEntry = rx_buf_1;
511  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
512  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
513 
514  entry = (rfc_dataEntry_t *)rx_buf_1;
515  entry->pNextEntry = rx_buf_2;
516  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
517  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
518 
519  entry = (rfc_dataEntry_t *)rx_buf_2;
520  entry->pNextEntry = rx_buf_3;
521  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
522  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
523 
524  entry = (rfc_dataEntry_t *)rx_buf_3;
525  entry->pNextEntry = rx_buf_0;
526  entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE;
527  entry->length = sizeof(rx_buf_0) - sizeof(*entry);
528 }
529 /*---------------------------------------------------------------------------*/
530 static void
531 init_rf_params(void)
532 {
533  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
534 
535  memset(cmd_ieee_rx_buf, 0x00, RF_CMD_BUFFER_SIZE);
536 
537  cmd->commandNo = CMD_IEEE_RX;
538  cmd->status = RF_CORE_RADIO_OP_STATUS_IDLE;
539  cmd->pNextOp = NULL;
540  cmd->startTime = 0x00000000;
541  cmd->startTrigger.triggerType = TRIG_NOW;
542  cmd->condition.rule = COND_NEVER;
543  cmd->channel = IEEE802154_DEFAULT_CHANNEL;
544 
545  cmd->rxConfig.bAutoFlushCrc = 1;
546  cmd->rxConfig.bAutoFlushIgn = 0;
547  cmd->rxConfig.bIncludePhyHdr = 0;
548  cmd->rxConfig.bIncludeCrc = RF_CORE_RX_BUF_INCLUDE_CRC;
549  cmd->rxConfig.bAppendRssi = RF_CORE_RX_BUF_INCLUDE_RSSI;
550  cmd->rxConfig.bAppendCorrCrc = RF_CORE_RX_BUF_INCLUDE_CORR;
551  cmd->rxConfig.bAppendSrcInd = 0;
552  cmd->rxConfig.bAppendTimestamp = RF_CORE_RX_BUF_INCLUDE_TIMESTAMP;
553 
554  cmd->pRxQ = &rx_data_queue;
555  cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
556 
557 #if IEEE_MODE_PROMISCOUS
558  cmd->frameFiltOpt.frameFiltEn = 0;
559 #else
560  cmd->frameFiltOpt.frameFiltEn = 1;
561 #endif
562 
563  cmd->frameFiltOpt.frameFiltStop = 1;
564 
565 #if IEEE_MODE_AUTOACK
566  cmd->frameFiltOpt.autoAckEn = 1;
567 #else
568  cmd->frameFiltOpt.autoAckEn = 0;
569 #endif
570 
571  cmd->frameFiltOpt.slottedAckEn = 0;
572  cmd->frameFiltOpt.autoPendEn = 0;
573  cmd->frameFiltOpt.defaultPend = 0;
574  cmd->frameFiltOpt.bPendDataReqOnly = 0;
575  cmd->frameFiltOpt.bPanCoord = 0;
576  cmd->frameFiltOpt.maxFrameVersion = 2;
577  cmd->frameFiltOpt.bStrictLenFilter = 0;
578 
579  /* Receive all frame types */
580  cmd->frameTypes.bAcceptFt0Beacon = 1;
581  cmd->frameTypes.bAcceptFt1Data = 1;
582  cmd->frameTypes.bAcceptFt2Ack = 1;
583  cmd->frameTypes.bAcceptFt3MacCmd = 1;
584  cmd->frameTypes.bAcceptFt4Reserved = 1;
585  cmd->frameTypes.bAcceptFt5Reserved = 1;
586  cmd->frameTypes.bAcceptFt6Reserved = 1;
587  cmd->frameTypes.bAcceptFt7Reserved = 1;
588 
589  /* Configure CCA settings */
590  cmd->ccaOpt.ccaEnEnergy = 1;
591  cmd->ccaOpt.ccaEnCorr = 1;
592  cmd->ccaOpt.ccaEnSync = 1;
593  cmd->ccaOpt.ccaCorrOp = 1;
594  cmd->ccaOpt.ccaSyncOp = 0;
595  cmd->ccaOpt.ccaCorrThr = 3;
596 
597  cmd->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD;
598 
599  cmd->numExtEntries = 0x00;
600  cmd->numShortEntries = 0x00;
601  cmd->pExtEntryList = 0;
602  cmd->pShortEntryList = 0;
603 
604  cmd->endTrigger.triggerType = TRIG_NEVER;
605  cmd->endTime = 0x00000000;
606 
607  /* set address filter command */
608  filter_cmd.commandNo = CMD_IEEE_MOD_FILT;
609  memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt));
610  memcpy(&filter_cmd.newFrameTypes, &cmd->frameTypes, sizeof(cmd->frameTypes));
611 }
612 /*---------------------------------------------------------------------------*/
613 static int
614 rx_on(void)
615 {
616  int ret;
617 
618  /* Get status of running IEEE_RX (if any) */
619  if(rf_is_on()) {
620  PRINTF("rx_on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
621  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
622  return RF_CORE_CMD_OK;
623  }
624 
625  /* Put CPE in RX using the currently configured parameters */
626  ret = rf_cmd_ieee_rx();
627 
628  if(ret) {
629  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
630  }
631 
632  return ret;
633 }
634 /*---------------------------------------------------------------------------*/
635 static int
636 rx_off(void)
637 {
638  uint32_t cmd_status;
639  int ret;
640 
641  /* If we are off, do nothing */
642  if(!rf_is_on()) {
643  return RF_CORE_CMD_OK;
644  }
645 
646  /* Wait for ongoing ACK TX to finish */
647  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
648 
649  /* Send a CMD_ABORT command to RF Core */
650  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
651  PRINTF("RX off: CMD_ABORT status=0x%08lx\n", cmd_status);
652  /* Continue nonetheless */
653  }
654 
655  RTIMER_BUSYWAIT_UNTIL(!rf_is_on(), RF_CORE_TURN_OFF_TIMEOUT);
656 
657  if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED ||
658  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) {
659  /* Stopped gracefully */
660  ret = RF_CORE_CMD_OK;
661  } else {
662  PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
663  ret = RF_CORE_CMD_ERROR;
664  }
665 
666  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
667 
668  return ret;
669 }
670 /*---------------------------------------------------------------------------*/
671 static uint8_t
672 request(void)
673 {
674  /*
675  * We rely on the RDC layer to turn us on and off. Thus, if we are on we
676  * will only allow sleep, standby otherwise
677  */
678  if(rf_is_on()) {
679  return LPM_MODE_SLEEP;
680  }
681 
682  return LPM_MODE_MAX_SUPPORTED;
683 }
684 /*---------------------------------------------------------------------------*/
685 LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
686 /*---------------------------------------------------------------------------*/
687 static void
688 soft_off(void)
689 {
690  uint32_t cmd_status;
691  volatile rfc_radioOp_t *cmd = rf_core_get_last_radio_op();
692 
693  if(!rf_core_is_accessible()) {
694  return;
695  }
696 
697  PRINTF("soft_off: Aborting 0x%04x, Status=0x%04x\n", cmd->commandNo,
698  cmd->status);
699 
700  /* Send a CMD_ABORT command to RF Core */
701  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
702  PRINTF("soft_off: CMD_ABORT status=0x%08lx\n", cmd_status);
703  return;
704  }
705 
706  RTIMER_BUSYWAIT_UNTIL((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) !=
707  RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_CORE_TURN_OFF_TIMEOUT);
708 }
709 /*---------------------------------------------------------------------------*/
710 static uint8_t
711 soft_on(void)
712 {
713  if(rf_radio_setup() != RF_CORE_CMD_OK) {
714  PRINTF("on: radio_setup() failed\n");
715  return RF_CORE_CMD_ERROR;
716  }
717 
718  return rx_on();
719 }
720 /*---------------------------------------------------------------------------*/
721 static const rf_core_primary_mode_t mode_ieee = {
722  soft_off,
723  soft_on,
724  rf_is_on,
725  RAT_TIMESTAMP_OFFSET_2_4_GHZ
726 };
727 /*---------------------------------------------------------------------------*/
728 static int
729 init(void)
730 {
731  lpm_register_module(&cc26xx_rf_lpm_module);
732 
734 
735  /* Initialise RX buffers */
736  memset(rx_buf_0, 0, RX_BUF_SIZE);
737  memset(rx_buf_1, 0, RX_BUF_SIZE);
738  memset(rx_buf_2, 0, RX_BUF_SIZE);
739  memset(rx_buf_3, 0, RX_BUF_SIZE);
740 
741  /* Set of RF Core data queue. Circular buffer, no last entry */
742  rx_data_queue.pCurrEntry = rx_buf_0;
743 
744  rx_data_queue.pLastEntry = NULL;
745 
746  /* Initialize current read pointer to first element (used in ISR) */
747  rx_read_entry = rx_buf_0;
748 
749  /* Populate the RF parameters data structure with default values */
750  init_rf_params();
751 
752  if(on() != RF_CORE_CMD_OK) {
753  PRINTF("init: on() failed\n");
754  return RF_CORE_CMD_ERROR;
755  }
756 
757  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
758 
759  rf_core_primary_mode_register(&mode_ieee);
760 
762 
763  process_start(&rf_core_process, NULL);
764  return 1;
765 }
766 /*---------------------------------------------------------------------------*/
767 static int
768 prepare(const void *payload, unsigned short payload_len)
769 {
770  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
771  return RADIO_TX_ERR;
772  }
773 
774  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
775  return 0;
776 }
777 /*---------------------------------------------------------------------------*/
778 static int
779 transmit(unsigned short transmit_len)
780 {
781  int ret;
782  uint8_t was_off = 0;
783  uint32_t cmd_status;
784  uint16_t stat;
785  uint8_t tx_active = 0;
786  rtimer_clock_t t0;
787  volatile rfc_CMD_IEEE_TX_t cmd;
788 
789  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
790  PRINTF("transmit: too long\n");
791  return RADIO_TX_ERR;
792  }
793 
794  if(!rf_is_on()) {
795  was_off = 1;
796  if(on() != RF_CORE_CMD_OK) {
797  PRINTF("transmit: on() failed\n");
798  return RADIO_TX_ERR;
799  }
800  }
801 
802  /*
803  * We are certainly not TXing a frame as a result of CMD_IEEE_TX, but we may
804  * be in the process of TXing an ACK. In that case, wait for the TX to finish
805  * or return after approx TX_WAIT_TIMEOUT
806  */
807  t0 = RTIMER_NOW();
808 
809  do {
810  tx_active = transmitting();
811  } while(tx_active == 1 &&
812  (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + RF_CORE_TX_TIMEOUT)));
813 
814  if(tx_active) {
815  PRINTF("transmit: Already TXing and wait timed out\n");
816 
817  if(was_off) {
818  off();
819  }
820 
821  return RADIO_TX_COLLISION;
822  }
823 
824  /* Send the CMD_IEEE_TX command */
825  rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_IEEE_TX);
826 
827  cmd.payloadLen = transmit_len;
828  cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
829 
830  cmd.startTime = 0;
831  cmd.startTrigger.triggerType = TRIG_NOW;
832 
833  /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
834  rf_core_cmd_done_en(true);
835 
836  ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
837 
838  if(ret) {
839  /* If we enter here, TX actually started */
840  ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
841 
842  /* Idle away while the command is running */
843  while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
844  == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
845  /* Note: for now sleeping while Tx'ing in polling mode is disabled.
846  * To enable it:
847  * 1) make the `lpm_sleep()` call here unconditional;
848  * 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR.
849  */
850  if(!rf_core_poll_mode) {
851  lpm_sleep();
852  }
853  }
854 
855  stat = cmd.status;
856 
857  if(stat == RF_CORE_RADIO_OP_STATUS_IEEE_DONE_OK) {
858  /* Sent OK */
859  ret = RADIO_TX_OK;
860  } else {
861  /* Operation completed, but frame was not sent */
862  PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret,
863  cmd_status, stat);
864  ret = RADIO_TX_ERR;
865  }
866  } else {
867  /* Failure sending the CMD_IEEE_TX command */
868  PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
869  ret, cmd_status, cmd.status);
870 
871  ret = RADIO_TX_ERR;
872  }
873 
874  /*
875  * Update ENERGEST state here, before a potential call to off(), which
876  * will correctly update it if required.
877  */
878  ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
879 
880  /*
881  * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
882  * except when we are transmitting
883  */
885 
886  if(was_off) {
887  off();
888  }
889 
890  return ret;
891 }
892 /*---------------------------------------------------------------------------*/
893 static int
894 send(const void *payload, unsigned short payload_len)
895 {
896  prepare(payload, payload_len);
897  return transmit(payload_len);
898 }
899 /*---------------------------------------------------------------------------*/
900 static void
901 release_data_entry(void)
902 {
903  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
904 
905  /* Clear the length byte */
906  rx_read_entry[8] = 0;
907 
908  /* Set status to 0 "Pending" in element */
909  entry->status = DATA_ENTRY_STATUS_PENDING;
910  rx_read_entry = entry->pNextEntry;
911 }
912 /*---------------------------------------------------------------------------*/
913 static int
914 read_frame(void *buf, unsigned short buf_len)
915 {
916  int len = 0;
917  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
918  uint32_t rat_timestamp;
919 
920  /* wait for entry to become finished */
921  rtimer_clock_t t0 = RTIMER_NOW();
922  while(entry->status == DATA_ENTRY_STATUS_BUSY
923  && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 250)));
924 
925  if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
926  /* No available data */
927  return 0;
928  }
929 
930  len = rx_read_entry[RX_BUF_LENGTH_OFFSET];
931  if(len <= RX_BUF_METADATA_SIZE) {
932  PRINTF("RF: too short!");
933 
934  release_data_entry();
935  return 0;
936  }
937 
938  len -= RX_BUF_METADATA_SIZE;
939  if(len > buf_len) {
940  PRINTF("RF: too long\n");
941 
942  release_data_entry();
943  return 0;
944  }
945 
946  memcpy(buf, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET, len);
947 
948  rf_core_last_rssi = (int8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len];
949  rf_core_last_corr_lqi = (uint8_t)rx_read_entry[RX_BUF_DATA_OFFSET + len + 1] & STATUS_CORRELATION;
950 
951  /* get the timestamp */
952  memcpy(&rat_timestamp, (uint8_t *)rx_read_entry + RX_BUF_DATA_OFFSET + len + 2, 4);
953 
954  rf_core_last_packet_timestamp = rf_core_convert_rat_to_rtimer(rat_timestamp);
955 
956  if(!rf_core_poll_mode) {
957  /* Not in poll mode: packetbuf should not be accessed in interrupt context.
958  * In poll mode, the last packet RSSI and link quality can be obtained through
959  * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
960  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf_core_last_rssi);
961  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf_core_last_corr_lqi);
962  }
963 
964  release_data_entry();
965 
966  return len;
967 }
968 /*---------------------------------------------------------------------------*/
969 static int
970 channel_clear(void)
971 {
972  uint8_t was_off = 0;
973  uint8_t cca_info;
974  int ret = RF_CORE_CCA_CLEAR;
975 
976  /*
977  * If we are in the middle of a BLE operation, we got called by ContikiMAC
978  * from within an interrupt context. Indicate a clear channel
979  */
980  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
981  PRINTF("channel_clear: Interrupt context but BLE in progress\n");
982  return RF_CORE_CCA_CLEAR;
983  }
984 
985  if(rf_is_on()) {
986  /*
987  * Wait for potential leftover ACK still being sent.
988  * Strictly speaking, if we are TXing an ACK then the channel is not clear.
989  * However, channel_clear is only ever called to determine whether there is
990  * someone else's packet in the air, not ours.
991  *
992  * We could probably even simply return that the channel is clear
993  */
994  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
995  } else {
996  was_off = 1;
997  if(on() != RF_CORE_CMD_OK) {
998  PRINTF("channel_clear: on() failed\n");
999  if(was_off) {
1000  off();
1001  }
1002  return RF_CORE_CCA_CLEAR;
1003  }
1004  }
1005 
1006  cca_info = get_cca_info();
1007 
1008  if(cca_info == RF_CORE_GET_CCA_INFO_ERROR) {
1009  PRINTF("channel_clear: CCA error\n");
1010  ret = RF_CORE_CCA_CLEAR;
1011  } else {
1012  /*
1013  * cca_info bits 1:0 - ccaStatus
1014  * Return 1 (clear) if idle or invalid.
1015  */
1016  ret = (cca_info & 0x03) != RF_CORE_CMD_CCA_REQ_CCA_STATE_BUSY;
1017  }
1018 
1019  if(was_off) {
1020  off();
1021  }
1022 
1023  return ret;
1024 }
1025 /*---------------------------------------------------------------------------*/
1026 static int
1027 receiving_packet(void)
1028 {
1029  uint8_t cca_info;
1030 
1031  /*
1032  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1033  * from within an interrupt context. We are not receiving
1034  */
1035  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1036  PRINTF("receiving_packet: Interrupt context but BLE in progress\n");
1037  return 0;
1038  }
1039 
1040  /* If we are off, we are not receiving */
1041  if(!rf_is_on()) {
1042  PRINTF("receiving_packet: We were off\n");
1043  return 0;
1044  }
1045 
1046  /* If we are transmitting (can only be an ACK here), we are not receiving */
1047  if(transmitting()) {
1048  PRINTF("receiving_packet: We were TXing\n");
1049  return 0;
1050  }
1051 
1052  cca_info = get_cca_info();
1053 
1054  /* If we can't read CCA info, return "not receiving" */
1055  if(cca_info == RF_CORE_GET_CCA_INFO_ERROR) {
1056  return 0;
1057  }
1058 
1059  /* If sync has been seen, return 1 (receiving) */
1060  if(cca_info & RF_CORE_CMD_CCA_REQ_CCA_SYNC_BUSY) {
1061  return 1;
1062  }
1063 
1064  return 0;
1065 }
1066 /*---------------------------------------------------------------------------*/
1067 static int
1068 pending_packet(void)
1069 {
1070  volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1071  int rv = 0;
1072 
1073  /* Go through all RX buffers and check their status */
1074  do {
1075  if(entry->status == DATA_ENTRY_STATUS_FINISHED
1076  || entry->status == DATA_ENTRY_STATUS_BUSY) {
1077  rv = 1;
1078  if(!rf_core_poll_mode) {
1079  process_poll(&rf_core_process);
1080  }
1081  }
1082 
1083  entry = (rfc_dataEntry_t *)entry->pNextEntry;
1084  } while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1085 
1086  /* If we didn't find an entry at status finished, no frames are pending */
1087  return rv;
1088 }
1089 /*---------------------------------------------------------------------------*/
1090 static int
1091 on(void)
1092 {
1093  /*
1094  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1095  * from within an interrupt context. Abort, but pretend everything is OK.
1096  */
1097  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1098  PRINTF("on: Interrupt context but BLE in progress\n");
1099  return RF_CORE_CMD_OK;
1100  }
1101 
1102  /*
1103  * Request the HF XOSC as the source for the HF clock. Needed before we can
1104  * use the FS. This will only request, it will _not_ perform the switch.
1105  */
1107 
1108  if(rf_is_on()) {
1109  PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
1110  RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
1111  return RF_CORE_CMD_OK;
1112  }
1113 
1114  init_rx_buffers();
1115 
1116  /*
1117  * Trigger a switch to the XOSC, so that we can subsequently use the RF FS
1118  * This will block until the XOSC is actually ready, but give how we
1119  * requested it early on, this won't be too long a wait.
1120  * This should be done before starting the RAT.
1121  */
1123 
1124  if(rf_core_boot() != RF_CORE_CMD_OK) {
1125  PRINTF("on: rf_core_boot() failed\n");
1126  return RF_CORE_CMD_ERROR;
1127  }
1128 
1130 
1131  if(rf_radio_setup() != RF_CORE_CMD_OK) {
1132  PRINTF("on: radio_setup() failed\n");
1133  return RF_CORE_CMD_ERROR;
1134  }
1135 
1136  return rx_on();
1137 }
1138 /*---------------------------------------------------------------------------*/
1139 static int
1140 off(void)
1141 {
1142  /*
1143  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1144  * from within an interrupt context. Abort, but pretend everything is OK.
1145  */
1146  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1147  PRINTF("off: Interrupt context but BLE in progress\n");
1148  return RF_CORE_CMD_OK;
1149  }
1150 
1151  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
1152 
1153  /* stopping the rx explicitly results in lower sleep-mode power usage */
1154  rx_off();
1156 
1157  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1158 
1159 #if !CC2650_FAST_RADIO_STARTUP
1160  /* Switch HF clock source to the RCOSC to preserve power.
1161  * This must be done after stopping RAT.
1162  */
1164 #endif
1165 
1166  /* We pulled the plug, so we need to restore the status manually */
1167  ((rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
1168 
1169  /*
1170  * Just in case there was an ongoing RX (which started after we begun the
1171  * shutdown sequence), we don't want to leave the buffer in state == ongoing
1172  */
1173  if(((rfc_dataEntry_t *)rx_buf_0)->status == DATA_ENTRY_STATUS_BUSY) {
1174  ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING;
1175  }
1176  if(((rfc_dataEntry_t *)rx_buf_1)->status == DATA_ENTRY_STATUS_BUSY) {
1177  ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING;
1178  }
1179  if(((rfc_dataEntry_t *)rx_buf_2)->status == DATA_ENTRY_STATUS_BUSY) {
1180  ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING;
1181  }
1182  if(((rfc_dataEntry_t *)rx_buf_3)->status == DATA_ENTRY_STATUS_BUSY) {
1183  ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING;
1184  }
1185 
1186  return RF_CORE_CMD_OK;
1187 }
1188 /*---------------------------------------------------------------------------*/
1189 /* Enable or disable CCA before sending */
1190 static radio_result_t
1191 set_send_on_cca(uint8_t enable)
1192 {
1193  if(enable) {
1194  /* this driver does not have support for CCA on Tx */
1195  return RADIO_RESULT_NOT_SUPPORTED;
1196  }
1197  return RADIO_RESULT_OK;
1198 }
1199 /*---------------------------------------------------------------------------*/
1200 static radio_result_t
1201 get_value(radio_param_t param, radio_value_t *value)
1202 {
1203  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1204 
1205  if(!value) {
1206  return RADIO_RESULT_INVALID_VALUE;
1207  }
1208 
1209  switch(param) {
1210  case RADIO_PARAM_POWER_MODE:
1211  /* On / off */
1212  *value = rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
1213  return RADIO_RESULT_OK;
1214  case RADIO_PARAM_CHANNEL:
1215  *value = (radio_value_t)cmd->channel;
1216  return RADIO_RESULT_OK;
1217  case RADIO_PARAM_PAN_ID:
1218  *value = (radio_value_t)cmd->localPanID;
1219  return RADIO_RESULT_OK;
1220  case RADIO_PARAM_16BIT_ADDR:
1221  *value = (radio_value_t)cmd->localShortAddr;
1222  return RADIO_RESULT_OK;
1223  case RADIO_PARAM_RX_MODE:
1224  *value = 0;
1225  if(cmd->frameFiltOpt.frameFiltEn) {
1226  *value |= RADIO_RX_MODE_ADDRESS_FILTER;
1227  }
1228  if(cmd->frameFiltOpt.autoAckEn) {
1229  *value |= RADIO_RX_MODE_AUTOACK;
1230  }
1231  if(rf_core_poll_mode) {
1232  *value |= RADIO_RX_MODE_POLL_MODE;
1233  }
1234 
1235  return RADIO_RESULT_OK;
1236  case RADIO_PARAM_TX_MODE:
1237  *value = 0;
1238  return RADIO_RESULT_OK;
1239  case RADIO_PARAM_TXPOWER:
1240  *value = get_tx_power();
1241  return RADIO_RESULT_OK;
1242  case RADIO_PARAM_CCA_THRESHOLD:
1243  *value = cmd->ccaRssiThr;
1244  return RADIO_RESULT_OK;
1245  case RADIO_PARAM_RSSI:
1246  *value = get_rssi();
1247 
1248  if(*value == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) {
1249  return RADIO_RESULT_ERROR;
1250  } else {
1251  return RADIO_RESULT_OK;
1252  }
1253  case RADIO_CONST_CHANNEL_MIN:
1254  *value = IEEE_MODE_CHANNEL_MIN;
1255  return RADIO_RESULT_OK;
1256  case RADIO_CONST_CHANNEL_MAX:
1257  *value = IEEE_MODE_CHANNEL_MAX;
1258  return RADIO_RESULT_OK;
1259  case RADIO_CONST_TXPOWER_MIN:
1260  *value = OUTPUT_POWER_MIN;
1261  return RADIO_RESULT_OK;
1262  case RADIO_CONST_TXPOWER_MAX:
1263  *value = OUTPUT_POWER_MAX;
1264  return RADIO_RESULT_OK;
1265  case RADIO_PARAM_LAST_RSSI:
1266  *value = rf_core_last_rssi;
1267  return RADIO_RESULT_OK;
1268  case RADIO_PARAM_LAST_LINK_QUALITY:
1269  *value = rf_core_last_corr_lqi;
1270  return RADIO_RESULT_OK;
1271  case RADIO_CONST_PHY_OVERHEAD:
1272  *value = (radio_value_t)RADIO_PHY_OVERHEAD;
1273  return RADIO_RESULT_OK;
1274  case RADIO_CONST_BYTE_AIR_TIME:
1275  *value = (radio_value_t)RADIO_BYTE_AIR_TIME;
1276  return RADIO_RESULT_OK;
1277  case RADIO_CONST_DELAY_BEFORE_TX:
1278  *value = (radio_value_t)RADIO_DELAY_BEFORE_TX;
1279  return RADIO_RESULT_OK;
1280  case RADIO_CONST_DELAY_BEFORE_RX:
1281  *value = (radio_value_t)RADIO_DELAY_BEFORE_RX;
1282  return RADIO_RESULT_OK;
1283  case RADIO_CONST_DELAY_BEFORE_DETECT:
1284  *value = (radio_value_t)RADIO_DELAY_BEFORE_DETECT;
1285  return RADIO_RESULT_OK;
1286  default:
1287  return RADIO_RESULT_NOT_SUPPORTED;
1288  }
1289 }
1290 /*---------------------------------------------------------------------------*/
1291 static radio_result_t
1292 set_value(radio_param_t param, radio_value_t value)
1293 {
1294  radio_result_t rv = RADIO_RESULT_OK;
1295  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1296  uint8_t old_poll_mode;
1297 
1298  switch(param) {
1299  case RADIO_PARAM_POWER_MODE:
1300  if(value == RADIO_POWER_MODE_ON) {
1301  if(on() != RF_CORE_CMD_OK) {
1302  PRINTF("set_value: on() failed (1)\n");
1303  return RADIO_RESULT_ERROR;
1304  }
1305  return RADIO_RESULT_OK;
1306  }
1307  if(value == RADIO_POWER_MODE_OFF) {
1308  off();
1309  return RADIO_RESULT_OK;
1310  }
1311  return RADIO_RESULT_INVALID_VALUE;
1312  case RADIO_PARAM_CHANNEL:
1313  if(value < IEEE_MODE_CHANNEL_MIN ||
1314  value > IEEE_MODE_CHANNEL_MAX) {
1315  return RADIO_RESULT_INVALID_VALUE;
1316  }
1317 
1318  /* Note: this return may lead to long periods when RAT and RTC are not resynchronized */
1319  if(cmd->channel == (uint8_t)value) {
1320  /* We already have that very same channel configured.
1321  * Nothing to do here. */
1322  return RADIO_RESULT_OK;
1323  }
1324 
1325  cmd->channel = (uint8_t)value;
1326  break;
1327  case RADIO_PARAM_PAN_ID:
1328  cmd->localPanID = (uint16_t)value;
1329  break;
1330  case RADIO_PARAM_16BIT_ADDR:
1331  cmd->localShortAddr = (uint16_t)value;
1332  break;
1333  case RADIO_PARAM_RX_MODE:
1334  {
1335  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
1336  RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
1337  return RADIO_RESULT_INVALID_VALUE;
1338  }
1339 
1340  cmd->frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
1341  cmd->frameFiltOpt.frameFiltStop = 1;
1342  cmd->frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
1343  cmd->frameFiltOpt.slottedAckEn = 0;
1344  cmd->frameFiltOpt.autoPendEn = 0;
1345  cmd->frameFiltOpt.defaultPend = 0;
1346  cmd->frameFiltOpt.bPendDataReqOnly = 0;
1347  cmd->frameFiltOpt.bPanCoord = 0;
1348  cmd->frameFiltOpt.bStrictLenFilter = 0;
1349 
1350  old_poll_mode = rf_core_poll_mode;
1351  rf_core_poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
1352  if(rf_core_poll_mode == old_poll_mode) {
1353  uint32_t cmd_status;
1354 
1355  /* do not turn the radio on and off, just send an update command */
1356  memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt));
1357 
1358  if(rf_core_send_cmd((uint32_t)&filter_cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
1359  PRINTF("setting address filter failed: CMDSTA=0x%08lx\n", cmd_status);
1360  return RADIO_RESULT_ERROR;
1361  }
1362  return RADIO_RESULT_OK;
1363  }
1364  break;
1365  }
1366 
1367  case RADIO_PARAM_TX_MODE:
1368  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1369  return RADIO_RESULT_INVALID_VALUE;
1370  }
1371  return set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1372 
1373  case RADIO_PARAM_TXPOWER:
1374  if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1375  return RADIO_RESULT_INVALID_VALUE;
1376  }
1377 
1378  set_tx_power(value);
1379 
1380  return RADIO_RESULT_OK;
1381 
1382  case RADIO_PARAM_CCA_THRESHOLD:
1383  cmd->ccaRssiThr = (int8_t)value;
1384  break;
1385 
1386  default:
1387  return RADIO_RESULT_NOT_SUPPORTED;
1388  }
1389 
1390  /* If off, the new configuration will be applied the next time radio is started */
1391  if(!rf_is_on()) {
1392  return RADIO_RESULT_OK;
1393  }
1394 
1395  /* If we reach here we had no errors. Apply new settings */
1396  if(rx_off() != RF_CORE_CMD_OK) {
1397  PRINTF("set_value: rx_off() failed\n");
1398  rv = RADIO_RESULT_ERROR;
1399  }
1400 
1401  /* Restart the radio timer (RAT).
1402  This causes resynchronization between RAT and RTC: useful for TSCH. */
1403  if(rf_core_restart_rat() == RF_CORE_CMD_OK) {
1405  }
1406 
1407  if(rx_on() != RF_CORE_CMD_OK) {
1408  PRINTF("set_value: rx_on() failed\n");
1409  rv = RADIO_RESULT_ERROR;
1410  }
1411 
1412  return rv;
1413 }
1414 /*---------------------------------------------------------------------------*/
1415 static radio_result_t
1416 get_object(radio_param_t param, void *dest, size_t size)
1417 {
1418  uint8_t *target;
1419  uint8_t *src;
1420  int i;
1421  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1422 
1423  if(param == RADIO_PARAM_64BIT_ADDR) {
1424  if(size != 8 || !dest) {
1425  return RADIO_RESULT_INVALID_VALUE;
1426  }
1427 
1428  target = dest;
1429  src = (uint8_t *)(&cmd->localExtAddr);
1430 
1431  for(i = 0; i < 8; i++) {
1432  target[i] = src[7 - i];
1433  }
1434 
1435  return RADIO_RESULT_OK;
1436  }
1437 
1438  if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
1439  if(size != sizeof(rtimer_clock_t) || !dest) {
1440  return RADIO_RESULT_INVALID_VALUE;
1441  }
1442  *(rtimer_clock_t *)dest = rf_core_last_packet_timestamp;
1443 
1444  return RADIO_RESULT_OK;
1445  }
1446 
1447  return RADIO_RESULT_NOT_SUPPORTED;
1448 }
1449 /*---------------------------------------------------------------------------*/
1450 static radio_result_t
1451 set_object(radio_param_t param, const void *src, size_t size)
1452 {
1453  radio_result_t rv = RADIO_RESULT_OK;
1454  int i;
1455  uint8_t *dst;
1456  rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf;
1457 
1458  if(param == RADIO_PARAM_64BIT_ADDR) {
1459  if(size != 8 || !src) {
1460  return RADIO_RESULT_INVALID_VALUE;
1461  }
1462 
1463  dst = (uint8_t *)(&cmd->localExtAddr);
1464 
1465  for(i = 0; i < 8; i++) {
1466  dst[i] = ((uint8_t *)src)[7 - i];
1467  }
1468 
1469  /* If off, the new configuration will be applied the next time radio is started */
1470  if(!rf_is_on()) {
1471  return RADIO_RESULT_OK;
1472  }
1473 
1474  if(rx_off() != RF_CORE_CMD_OK) {
1475  PRINTF("set_object: rx_off() failed\n");
1476  rv = RADIO_RESULT_ERROR;
1477  }
1478 
1479  if(rx_on() != RF_CORE_CMD_OK) {
1480  PRINTF("set_object: rx_on() failed\n");
1481  rv = RADIO_RESULT_ERROR;
1482  }
1483 
1484  return rv;
1485  }
1486  return RADIO_RESULT_NOT_SUPPORTED;
1487 }
1488 /*---------------------------------------------------------------------------*/
1489 const struct radio_driver ieee_mode_driver = {
1490  init,
1491  prepare,
1492  transmit,
1493  send,
1494  read_frame,
1495  channel_clear,
1498  on,
1499  off,
1500  get_value,
1501  set_value,
1502  get_object,
1503  set_object,
1504 };
1505 /*---------------------------------------------------------------------------*/
1506 /**
1507  * @}
1508  * @}
1509  */
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:307
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:272
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:269
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
Definition: ieee-mode.c:478
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:254
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.
Definition: rf-core.c:534
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.
Definition: rf-core.c:372
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:285
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:300
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:288
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition: rf-core.c:410
The structure of a device driver for a radio in Contiki.
Definition: radio.h:264
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:202
void lpm_sleep(void)
Enter sleep mode.
Definition: lpm.c:376
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:282
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
#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:160
Header file for the CC13xx/CC26xx oscillator control.
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
Definition: rf-core.c:652
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:275
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:272
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:294
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:347
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
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:231
uint8_t rf_ble_is_active()
Check whether the BLE beacond is currently active.
Definition: rf-ble.c:262
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...
Definition: radio.h:243
static uint8_t get_cca_info(void)
Returns CCA information.
Definition: ieee-mode.c:311
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.
void oscillators_switch_to_hf_xosc(void)
Performs the switch to the XOSC.
Definition: oscillators.c:116
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:92
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:297
Default definitions of C compiler quirk work-arounds.
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:313
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition: rf-core.c:513
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:291
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:539
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