Contiki-NG
prop-mode.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 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-prop
33  * @{
34  *
35  * \file
36  * Implementation of the CC13xx prop mode NETSTACK_RADIO driver
37  */
38 /*---------------------------------------------------------------------------*/
39 #include "contiki.h"
40 #include "dev/radio.h"
41 #include "dev/cc26xx-uart.h"
42 #include "dev/oscillators.h"
43 #include "dev/watchdog.h"
44 #include "net/packetbuf.h"
45 #include "net/netstack.h"
46 #include "sys/energest.h"
47 #include "sys/clock.h"
48 #include "sys/critical.h"
49 #include "sys/rtimer.h"
50 #include "sys/cc.h"
51 #include "lpm.h"
52 #include "ti-lib.h"
53 #include "rf-core/rf-core.h"
54 #include "rf-core/rf-switch.h"
55 #include "rf-core/rf-ble.h"
56 #include "rf-core/prop-mode.h"
57 #include "rf-core/dot-15-4g.h"
58 /*---------------------------------------------------------------------------*/
59 /* RF core and RF HAL API */
60 #include "hw_rfc_dbell.h"
61 #include "hw_rfc_pwr.h"
62 /*---------------------------------------------------------------------------*/
63 /* RF Core Mailbox API */
64 #include "driverlib/rf_mailbox.h"
65 #include "driverlib/rf_common_cmd.h"
66 #include "driverlib/rf_data_entry.h"
67 #include "driverlib/rf_prop_mailbox.h"
68 #include "driverlib/rf_prop_cmd.h"
69 /*---------------------------------------------------------------------------*/
70 /* CC13xxware patches */
71 #include "rf_patches/rf_patch_cpe_genfsk.h"
72 #include "rf_patches/rf_patch_rfe_genfsk.h"
73 /*---------------------------------------------------------------------------*/
74 #include "rf-core/smartrf-settings.h"
75 /*---------------------------------------------------------------------------*/
76 #include <stdint.h>
77 #include <string.h>
78 #include <stdio.h>
79 #include <stdbool.h>
80 /*---------------------------------------------------------------------------*/
81 #define DEBUG 0
82 #if DEBUG
83 #define PRINTF(...) printf(__VA_ARGS__)
84 #else
85 #define PRINTF(...)
86 #endif
87 /*---------------------------------------------------------------------------*/
88 /* Data entry status field constants */
89 #define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
90 #define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
91 #define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */
92 #define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */
93 #define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */
94 /*---------------------------------------------------------------------------*/
95 /* Data whitener. 1: Whitener, 0: No whitener */
96 #ifdef PROP_MODE_CONF_DW
97 #define PROP_MODE_DW PROP_MODE_CONF_DW
98 #else
99 #define PROP_MODE_DW 0
100 #endif
101 
102 #ifdef PROP_MODE_CONF_USE_CRC16
103 #define PROP_MODE_USE_CRC16 PROP_MODE_CONF_USE_CRC16
104 #else
105 #define PROP_MODE_USE_CRC16 0
106 #endif
107 /*---------------------------------------------------------------------------*/
108 /**
109  * \brief Returns the current status of a running Radio Op command
110  * \param a A pointer with the buffer used to initiate the command
111  * \return The value of the Radio Op buffer's status field
112  *
113  * This macro can be used to e.g. return the status of a previously
114  * initiated background operation, or of an immediate command
115  */
116 #define RF_RADIO_OP_GET_STATUS(a) GET_FIELD_V(a, radioOp, status)
117 /*---------------------------------------------------------------------------*/
118 #ifdef PROP_MODE_CONF_RSSI_THRESHOLD
119 #define PROP_MODE_RSSI_THRESHOLD PROP_MODE_CONF_RSSI_THRESHOLD
120 #else
121 #define PROP_MODE_RSSI_THRESHOLD 0xA6
122 #endif
123 
124 static int8_t rssi_threshold = PROP_MODE_RSSI_THRESHOLD;
125 /*---------------------------------------------------------------------------*/
126 #if MAC_CONF_WITH_TSCH
127 static volatile uint8_t is_receiving_packet;
128 #endif
129 /*---------------------------------------------------------------------------*/
130 static int on(void);
131 static int off(void);
132 
133 static rfc_propRxOutput_t rx_stats;
134 /*---------------------------------------------------------------------------*/
135 /* Defines and variables related to the .15.4g PHY HDR */
136 #define DOT_4G_MAX_FRAME_LEN 2047
137 #define DOT_4G_PHR_LEN 2
138 
139 /* PHY HDR bits */
140 #define DOT_4G_PHR_CRC16 0x10
141 #define DOT_4G_PHR_DW 0x08
142 
143 #if PROP_MODE_USE_CRC16
144 /* CRC16 */
145 #define DOT_4G_PHR_CRC_BIT DOT_4G_PHR_CRC16
146 #define CRC_LEN 2
147 #else
148 /* CRC32 */
149 #define DOT_4G_PHR_CRC_BIT 0
150 #define CRC_LEN 4
151 #endif
152 
153 #if PROP_MODE_DW
154 #define DOT_4G_PHR_DW_BIT DOT_4G_PHR_DW
155 #else
156 #define DOT_4G_PHR_DW_BIT 0
157 #endif
158 /*---------------------------------------------------------------------------*/
159 /*
160  * The maximum number of bytes this driver can accept from the MAC layer for
161  * transmission or will deliver to the MAC layer after reception. Includes
162  * the MAC header and payload, but not the CRC.
163  *
164  * Unlike typical 2.4GHz radio drivers, this driver supports the .15.4g
165  * 32-bit CRC option.
166  *
167  * This radio hardware is perfectly happy to transmit frames longer than 127
168  * bytes, which is why it's OK to end up transmitting 125 payload bytes plus
169  * a 4-byte CRC.
170  *
171  * In the future we can change this to support transmission of long frames,
172  * for example as per .15.4g. the size of the TX and RX buffers would need
173  * adjusted accordingly.
174  */
175 #define MAX_PAYLOAD_LEN 125
176 /*---------------------------------------------------------------------------*/
177 /* TX power table for the 431-527MHz band */
178 #ifdef PROP_MODE_CONF_TX_POWER_431_527
179 #define PROP_MODE_TX_POWER_431_527 PROP_MODE_CONF_TX_POWER_431_527
180 #else
181 #define PROP_MODE_TX_POWER_431_527 prop_mode_tx_power_431_527
182 #endif
183 /*---------------------------------------------------------------------------*/
184 /* TX power table for the 779-930MHz band */
185 #ifdef PROP_MODE_CONF_TX_POWER_779_930
186 #define PROP_MODE_TX_POWER_779_930 PROP_MODE_CONF_TX_POWER_779_930
187 #else
188 #define PROP_MODE_TX_POWER_779_930 prop_mode_tx_power_779_930
189 #endif
190 /*---------------------------------------------------------------------------*/
191 /* Select power table based on the frequency band */
192 #if DOT_15_4G_FREQUENCY_BAND_ID==DOT_15_4G_FREQUENCY_BAND_470
193 #define TX_POWER_DRIVER PROP_MODE_TX_POWER_431_527
194 #else
195 #define TX_POWER_DRIVER PROP_MODE_TX_POWER_779_930
196 #endif
197 /*---------------------------------------------------------------------------*/
198 extern const prop_mode_tx_power_config_t TX_POWER_DRIVER[];
199 
200 /* Max and Min Output Power in dBm */
201 #define OUTPUT_POWER_MAX (TX_POWER_DRIVER[0].dbm)
202 #define OUTPUT_POWER_UNKNOWN 0xFFFF
203 
204 /* Default TX Power - position in output_power[] */
205 static const prop_mode_tx_power_config_t *tx_power_current = &TX_POWER_DRIVER[1];
206 /*---------------------------------------------------------------------------*/
207 #ifdef PROP_MODE_CONF_LO_DIVIDER
208 #define PROP_MODE_LO_DIVIDER PROP_MODE_CONF_LO_DIVIDER
209 #else
210 #define PROP_MODE_LO_DIVIDER 0x05
211 #endif
212 /*---------------------------------------------------------------------------*/
213 #ifdef PROP_MODE_CONF_RX_BUF_CNT
214 #define PROP_MODE_RX_BUF_CNT PROP_MODE_CONF_RX_BUF_CNT
215 #else
216 #define PROP_MODE_RX_BUF_CNT 4
217 #endif
218 /*---------------------------------------------------------------------------*/
219 #define DATA_ENTRY_LENSZ_NONE 0
220 #define DATA_ENTRY_LENSZ_BYTE 1
221 #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
222 
223 /* The size of the metadata (excluding the packet length field) */
224 #define RX_BUF_METADATA_SIZE \
225  (CRC_LEN * RF_CORE_RX_BUF_INCLUDE_CRC \
226  + RF_CORE_RX_BUF_INCLUDE_RSSI \
227  + RF_CORE_RX_BUF_INCLUDE_CORR \
228  + 4 * RF_CORE_RX_BUF_INCLUDE_TIMESTAMP)
229 
230 /* The offset of the packet length in a rx buffer */
231 #define RX_BUF_LENGTH_OFFSET sizeof(rfc_dataEntry_t)
232 /* The offset of the packet data in a rx buffer */
233 #define RX_BUF_DATA_OFFSET (RX_BUF_LENGTH_OFFSET + DOT_4G_PHR_LEN)
234 
235 #define ALIGN_TO_4(size) (((size) + 3) & ~3)
236 
237 #define RX_BUF_SIZE ALIGN_TO_4(RX_BUF_DATA_OFFSET \
238  + MAX_PAYLOAD_LEN \
239  + RX_BUF_METADATA_SIZE)
240 
241 /*
242  * RX buffers.
243  * PROP_MODE_RX_BUF_CNT buffers of RX_BUF_SIZE bytes each. The start of each
244  * buffer must be 4-byte aligned, therefore RX_BUF_SIZE must divide by 4
245  */
246 static uint8_t rx_buf[PROP_MODE_RX_BUF_CNT][RX_BUF_SIZE] CC_ALIGN(4);
247 
248 /* The RX Data Queue */
249 static dataQueue_t rx_data_queue = { 0 };
250 
251 /* Receive entry pointer to keep track of read items */
252 volatile static uint8_t *rx_read_entry;
253 /*---------------------------------------------------------------------------*/
254 /*
255  * Increasing this number causes unicast Tx immediately after broadcast Rx to have
256  * negative synchronization errors ("dr" in TSCH logs); decreasing it: the opposite.
257  */
258 #define RAT_TIMESTAMP_OFFSET_SUB_GHZ USEC_TO_RADIO(160 * 6 - 240)
259 /*---------------------------------------------------------------------------*/
260 /* The outgoing frame buffer */
261 #define TX_BUF_PAYLOAD_LEN 180
262 #define TX_BUF_HDR_LEN 2
263 
264 static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4);
265 /*---------------------------------------------------------------------------*/
266 static uint8_t
267 rf_is_on(void)
268 {
269  if(!rf_core_is_accessible()) {
270  return 0;
271  }
272 
273  return smartrf_settings_cmd_prop_rx_adv.status == RF_CORE_RADIO_OP_STATUS_ACTIVE;
274 }
275 /*---------------------------------------------------------------------------*/
276 static uint8_t
277 transmitting(void)
278 {
279  return smartrf_settings_cmd_prop_tx_adv.status == RF_CORE_RADIO_OP_STATUS_ACTIVE;
280 }
281 /*---------------------------------------------------------------------------*/
282 static radio_value_t
283 get_rssi(void)
284 {
285  uint32_t cmd_status;
286  int8_t rssi;
287  uint8_t attempts = 0;
288  uint8_t was_off = 0;
289  rfc_CMD_GET_RSSI_t cmd;
290 
291  /* If we are off, turn on first */
292  if(!rf_is_on()) {
293  was_off = 1;
294  if(on() != RF_CORE_CMD_OK) {
295  PRINTF("get_rssi: on() failed\n");
296  return RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
297  }
298  }
299 
300  rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
301 
302  while((rssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) && ++attempts < 10) {
303  memset(&cmd, 0x00, sizeof(cmd));
304  cmd.commandNo = CMD_GET_RSSI;
305 
306  if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) == RF_CORE_CMD_ERROR) {
307  PRINTF("get_rssi: CMDSTA=0x%08lx\n", cmd_status);
308  break;
309  } else {
310  /* Current RSSI in bits 23:16 of cmd_status */
311  rssi = (cmd_status >> 16) & 0xFF;
312  }
313  }
314 
315  /* If we were off, turn back off */
316  if(was_off) {
317  off();
318  }
319 
320  return rssi;
321 }
322 /*---------------------------------------------------------------------------*/
323 static uint8_t
324 get_channel(void)
325 {
326  uint32_t freq_khz;
327 
328  freq_khz = smartrf_settings_cmd_fs.frequency * 1000;
329 
330  /*
331  * For some channels, fractFreq * 1000 / 65536 will return 324.99xx.
332  * Casting the result to uint32_t will truncate decimals resulting in the
333  * function returning channel - 1 instead of channel. Thus, we do a quick
334  * positive integer round up.
335  */
336  freq_khz += (((smartrf_settings_cmd_fs.fractFreq * 1000) + 65535) / 65536);
337 
338  return (freq_khz - DOT_15_4G_CHAN0_FREQUENCY) / DOT_15_4G_CHANNEL_SPACING;
339 }
340 /*---------------------------------------------------------------------------*/
341 static void
342 set_channel(uint8_t channel)
343 {
344  uint32_t new_freq;
345  uint16_t freq, frac;
346 
347  new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING);
348 
349  freq = (uint16_t)(new_freq / 1000);
350  frac = (new_freq - (freq * 1000)) * 65536 / 1000;
351 
352  PRINTF("set_channel: %u = 0x%04x.0x%04x (%lu)\n", channel, freq, frac,
353  new_freq);
354 
355  smartrf_settings_cmd_prop_radio_div_setup.centerFreq = freq;
356  smartrf_settings_cmd_fs.frequency = freq;
357  smartrf_settings_cmd_fs.fractFreq = frac;
358 }
359 /*---------------------------------------------------------------------------*/
360 static uint8_t
361 get_tx_power_array_last_element(void)
362 {
363  const prop_mode_tx_power_config_t *array = TX_POWER_DRIVER;
364  uint8_t count = 0;
365 
366  while(array->tx_power != OUTPUT_POWER_UNKNOWN) {
367  count++;
368  array++;
369  }
370  return count - 1;
371 }
372 /*---------------------------------------------------------------------------*/
373 /* Returns the current TX power in dBm */
374 static radio_value_t
375 get_tx_power(void)
376 {
377  return tx_power_current->dbm;
378 }
379 /*---------------------------------------------------------------------------*/
380 /*
381  * The caller must make sure to send a new CMD_PROP_RADIO_DIV_SETUP to the
382  * radio after calling this function.
383  */
384 static void
385 set_tx_power(radio_value_t power)
386 {
387  int i;
388 
389  for(i = get_tx_power_array_last_element(); i >= 0; --i) {
390  if(power <= TX_POWER_DRIVER[i].dbm) {
391  /*
392  * Merely save the value. It will be used in all subsequent usages of
393  * CMD_PROP_RADIO_DIV_SETP, including one immediately after this function
394  * has returned
395  */
396  tx_power_current = &TX_POWER_DRIVER[i];
397 
398  return;
399  }
400  }
401 }
402 /*---------------------------------------------------------------------------*/
403 static int
404 prop_div_radio_setup(void)
405 {
406  uint32_t cmd_status;
407  rfc_radioOp_t *cmd = (rfc_radioOp_t *)&smartrf_settings_cmd_prop_radio_div_setup;
408 
409  rf_switch_select_path(RF_SWITCH_PATH_SUBGHZ);
410 
411  /* Adjust loDivider depending on the selected band */
412  smartrf_settings_cmd_prop_radio_div_setup.loDivider = PROP_MODE_LO_DIVIDER;
413 
414  /* Update to the correct TX power setting */
415  smartrf_settings_cmd_prop_radio_div_setup.txPower = tx_power_current->tx_power;
416 
417  /* Adjust RF Front End and Bias based on the board */
418  smartrf_settings_cmd_prop_radio_div_setup.config.frontEndMode =
419  RF_CORE_PROP_FRONT_END_MODE;
420  smartrf_settings_cmd_prop_radio_div_setup.config.biasMode =
421  RF_CORE_PROP_BIAS_MODE;
422 
423  /* Send Radio setup to RF Core */
424  if(rf_core_send_cmd((uint32_t)cmd, &cmd_status) != RF_CORE_CMD_OK) {
425  PRINTF("prop_div_radio_setup: DIV_SETUP, CMDSTA=0x%08lx, status=0x%04x\n",
426  cmd_status, cmd->status);
427  return RF_CORE_CMD_ERROR;
428  }
429 
430  /* Wait until radio setup is done */
431  if(rf_core_wait_cmd_done(cmd) != RF_CORE_CMD_OK) {
432  PRINTF("prop_div_radio_setup: DIV_SETUP wait, CMDSTA=0x%08lx,"
433  "status=0x%04x\n", cmd_status, cmd->status);
434  return RF_CORE_CMD_ERROR;
435  }
436 
437  return RF_CORE_CMD_OK;
438 }
439 /*---------------------------------------------------------------------------*/
440 static uint8_t
441 rf_cmd_prop_rx()
442 {
443  uint32_t cmd_status;
444  volatile rfc_CMD_PROP_RX_ADV_t *cmd_rx_adv;
445  int ret;
446 
447  cmd_rx_adv = (rfc_CMD_PROP_RX_ADV_t *)&smartrf_settings_cmd_prop_rx_adv;
448  cmd_rx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE;
449 
450  cmd_rx_adv->rxConf.bIncludeCrc = RF_CORE_RX_BUF_INCLUDE_CRC;
451  cmd_rx_adv->rxConf.bAppendRssi = RF_CORE_RX_BUF_INCLUDE_RSSI;
452  cmd_rx_adv->rxConf.bAppendTimestamp = RF_CORE_RX_BUF_INCLUDE_TIMESTAMP;
453  cmd_rx_adv->rxConf.bAppendStatus = RF_CORE_RX_BUF_INCLUDE_CORR;
454 
455  /*
456  * Set the max Packet length. This is for the payload only, therefore
457  * 2047 - length offset
458  */
459  cmd_rx_adv->maxPktLen = DOT_4G_MAX_FRAME_LEN - cmd_rx_adv->lenOffset;
460 
461  ret = rf_core_send_cmd((uint32_t)cmd_rx_adv, &cmd_status);
462 
463  if(ret != RF_CORE_CMD_OK) {
464  PRINTF("rf_cmd_prop_rx: send_cmd ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
465  ret, cmd_status, cmd_rx_adv->status);
466  return RF_CORE_CMD_ERROR;
467  }
468 
469  RTIMER_BUSYWAIT_UNTIL(cmd_rx_adv->status == RF_CORE_RADIO_OP_STATUS_ACTIVE,
470  RF_CORE_ENTER_RX_TIMEOUT);
471 
472  /* Wait to enter RX */
473  if(cmd_rx_adv->status != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
474  PRINTF("rf_cmd_prop_rx: CMDSTA=0x%08lx, status=0x%04x\n",
475  cmd_status, cmd_rx_adv->status);
476  return RF_CORE_CMD_ERROR;
477  }
478 
479  return ret;
480 }
481 /*---------------------------------------------------------------------------*/
482 static void
483 init_rx_buffers(void)
484 {
485  rfc_dataEntry_t *entry;
486  int i;
487 
488  for(i = 0; i < PROP_MODE_RX_BUF_CNT; i++) {
489  entry = (rfc_dataEntry_t *)rx_buf[i];
490  entry->status = DATA_ENTRY_STATUS_PENDING;
491  entry->config.type = DATA_ENTRY_TYPE_GEN;
492  entry->config.lenSz = DATA_ENTRY_LENSZ_WORD;
493  entry->length = RX_BUF_SIZE - 8;
494  entry->pNextEntry = rx_buf[i + 1];
495  }
496 
497  ((rfc_dataEntry_t *)rx_buf[PROP_MODE_RX_BUF_CNT - 1])->pNextEntry = rx_buf[0];
498 }
499 /*---------------------------------------------------------------------------*/
500 static int
501 rx_on_prop(void)
502 {
503  int ret;
504 
505  if(rf_is_on()) {
506  PRINTF("rx_on_prop: We were on. PD=%u, RX=0x%04x\n",
507  rf_core_is_accessible(), smartrf_settings_cmd_prop_rx_adv.status);
508  return RF_CORE_CMD_OK;
509  }
510 
511  /* Put CPE in RX using the currently configured parameters */
512  ret = rf_cmd_prop_rx();
513 
514  if(ret) {
515  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
516  }
517 
518  return ret;
519 }
520 /*---------------------------------------------------------------------------*/
521 static int
522 rx_off_prop(void)
523 {
524  uint32_t cmd_status;
525  int ret;
526 
527  /* If we are off, do nothing */
528  if(!rf_is_on()) {
529  return RF_CORE_CMD_OK;
530  }
531 
532  /* Wait for ongoing ACK TX to finish */
533  RTIMER_BUSYWAIT_UNTIL(!transmitting(), RF_CORE_TX_FINISH_TIMEOUT);
534 
535  /* Send a CMD_ABORT command to RF Core */
536  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
537  PRINTF("rx_off_prop: CMD_ABORT status=0x%08lx\n", cmd_status);
538  /* Continue nonetheless */
539  }
540 
541  RTIMER_BUSYWAIT_UNTIL(!rf_is_on(), RF_CORE_TURN_OFF_TIMEOUT);
542 
543  if(smartrf_settings_cmd_prop_rx_adv.status == PROP_DONE_STOPPED ||
544  smartrf_settings_cmd_prop_rx_adv.status == PROP_DONE_ABORT) {
545  /* Stopped gracefully */
546  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
547  ret = RF_CORE_CMD_OK;
548  } else {
549  PRINTF("rx_off_prop: status=0x%04x\n",
550  smartrf_settings_cmd_prop_rx_adv.status);
551  ret = RF_CORE_CMD_ERROR;
552  }
553 
554  return ret;
555 }
556 /*---------------------------------------------------------------------------*/
557 static uint8_t
558 request(void)
559 {
560  /*
561  * We rely on the RDC layer to turn us on and off. Thus, if we are on we
562  * will only allow sleep, standby otherwise
563  */
564  if(rf_is_on()) {
565  return LPM_MODE_SLEEP;
566  }
567 
568  return LPM_MODE_MAX_SUPPORTED;
569 }
570 /*---------------------------------------------------------------------------*/
571 LPM_MODULE(prop_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE);
572 /*---------------------------------------------------------------------------*/
573 static int
574 prop_fs(void)
575 {
576  uint32_t cmd_status;
577  rfc_radioOp_t *cmd = (rfc_radioOp_t *)&smartrf_settings_cmd_fs;
578 
579  /* Send the command to the RF Core */
580  if(rf_core_send_cmd((uint32_t)cmd, &cmd_status) != RF_CORE_CMD_OK) {
581  PRINTF("prop_fs: CMD_FS, CMDSTA=0x%08lx, status=0x%04x\n",
582  cmd_status, cmd->status);
583  return RF_CORE_CMD_ERROR;
584  }
585 
586  /* Wait until the command is done */
587  if(rf_core_wait_cmd_done(cmd) != RF_CORE_CMD_OK) {
588  PRINTF("prop_fs: CMD_FS wait, CMDSTA=0x%08lx, status=0x%04x\n",
589  cmd_status, cmd->status);
590  return RF_CORE_CMD_ERROR;
591  }
592 
593  return RF_CORE_CMD_OK;
594 }
595 /*---------------------------------------------------------------------------*/
596 static void
597 soft_off_prop(void)
598 {
599  uint32_t cmd_status;
600  volatile rfc_radioOp_t *cmd = rf_core_get_last_radio_op();
601 
602  if(!rf_core_is_accessible()) {
603  return;
604  }
605 
606  /* Send a CMD_ABORT command to RF Core */
607  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CORE_CMD_OK) {
608  PRINTF("soft_off_prop: CMD_ABORT status=0x%08lx\n", cmd_status);
609  return;
610  }
611 
612  RTIMER_BUSYWAIT_UNTIL((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) !=
613  RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_CORE_TURN_OFF_TIMEOUT);
614 }
615 /*---------------------------------------------------------------------------*/
616 static uint8_t
617 soft_on_prop(void)
618 {
619  if(prop_div_radio_setup() != RF_CORE_CMD_OK) {
620  PRINTF("soft_on_prop: prop_div_radio_setup() failed\n");
621  return RF_CORE_CMD_ERROR;
622  }
623 
624  if(prop_fs() != RF_CORE_CMD_OK) {
625  PRINTF("soft_on_prop: prop_fs() failed\n");
626  return RF_CORE_CMD_ERROR;
627  }
628 
629  return rx_on_prop();
630 }
631 /*---------------------------------------------------------------------------*/
632 static const rf_core_primary_mode_t mode_prop = {
633  soft_off_prop,
634  soft_on_prop,
635  rf_is_on,
636  RAT_TIMESTAMP_OFFSET_SUB_GHZ
637 };
638 /*---------------------------------------------------------------------------*/
639 static int
640 init(void)
641 {
642  lpm_register_module(&prop_lpm_module);
643 
644  if(ti_lib_chipinfo_chip_family_is_cc13xx() == false) {
645  return RF_CORE_CMD_ERROR;
646  }
647 
648  /* Initialise RX buffers */
649  memset(rx_buf, 0, sizeof(rx_buf));
650 
651  /* Set of RF Core data queue. Circular buffer, no last entry */
652  rx_data_queue.pCurrEntry = rx_buf[0];
653  rx_data_queue.pLastEntry = NULL;
654 
655  /* Initialize current read pointer to first element (used in ISR) */
656  rx_read_entry = rx_buf[0];
657 
658  smartrf_settings_cmd_prop_rx_adv.pQueue = &rx_data_queue;
659  smartrf_settings_cmd_prop_rx_adv.pOutput = (uint8_t *)&rx_stats;
660 
662 
663  if(on() != RF_CORE_CMD_OK) {
664  PRINTF("init: on() failed\n");
665  return RF_CORE_CMD_ERROR;
666  }
667 
668  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
669 
670  rf_core_primary_mode_register(&mode_prop);
671 
673 
674  process_start(&rf_core_process, NULL);
675 
676  return 1;
677 }
678 /*---------------------------------------------------------------------------*/
679 static int
680 prepare(const void *payload, unsigned short payload_len)
681 {
682  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > MAX_PAYLOAD_LEN) {
683  return RADIO_TX_ERR;
684  }
685 
686  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
687  return 0;
688 }
689 /*---------------------------------------------------------------------------*/
690 static int
691 transmit(unsigned short transmit_len)
692 {
693  int ret;
694  uint8_t was_off = 0;
695  uint32_t cmd_status;
696  volatile rfc_CMD_PROP_TX_ADV_t *cmd_tx_adv;
697 
698  /* Length in .15.4g PHY HDR. Includes the CRC but not the HDR itself */
699  uint16_t total_length;
700 
701  if(transmit_len > MAX_PAYLOAD_LEN) {
702  PRINTF("transmit: too long\n");
703  return RADIO_TX_ERR;
704  }
705 
706  if(!rf_is_on()) {
707  was_off = 1;
708  if(on() != RF_CORE_CMD_OK) {
709  PRINTF("transmit: on() failed\n");
710  return RADIO_TX_ERR;
711  }
712  }
713 
714  /*
715  * Prepare the .15.4g PHY header
716  * MS=0, Length MSBits=0, DW and CRC configurable
717  * Total length = transmit_len (payload) + CRC length
718  *
719  * The Radio will flip the bits around, so tx_buf[0] must have the length
720  * LSBs (PHR[15:8] and tx_buf[1] will have PHR[7:0]
721  */
722  total_length = transmit_len + CRC_LEN;
723 
724  tx_buf[0] = total_length & 0xFF;
725  tx_buf[1] = (total_length >> 8) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT;
726 
727  /* Prepare the CMD_PROP_TX_ADV command */
728  cmd_tx_adv = (rfc_CMD_PROP_TX_ADV_t *)&smartrf_settings_cmd_prop_tx_adv;
729 
730  /*
731  * pktLen: Total number of bytes in the TX buffer, including the header if
732  * one exists, but not including the CRC (which is not present in the buffer)
733  */
734  cmd_tx_adv->pktLen = transmit_len + DOT_4G_PHR_LEN;
735  cmd_tx_adv->pPkt = tx_buf;
736 
737  /* Abort RX */
738  rx_off_prop();
739 
740  /* Enable the LAST_COMMAND_DONE interrupt to wake us up */
741  rf_core_cmd_done_en(false);
742 
743  ret = rf_core_send_cmd((uint32_t)cmd_tx_adv, &cmd_status);
744 
745  if(ret) {
746  /* If we enter here, TX actually started */
747  ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
748 
749  /* Idle away while the command is running */
750  while((cmd_tx_adv->status & RF_CORE_RADIO_OP_MASKED_STATUS)
751  == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
752  /* Note: for now sleeping while Tx'ing in polling mode is disabled.
753  * To enable it:
754  * 1) make the `lpm_sleep()` call here unconditional;
755  * 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR.
756  */
757  if(!rf_core_poll_mode) {
758  lpm_sleep();
759  }
760  }
761 
762  if(cmd_tx_adv->status == RF_CORE_RADIO_OP_STATUS_PROP_DONE_OK) {
763  /* Sent OK */
764  ret = RADIO_TX_OK;
765  } else {
766  /* Operation completed, but frame was not sent */
767  PRINTF("transmit: Not Sent OK status=0x%04x\n",
768  cmd_tx_adv->status);
769  ret = RADIO_TX_ERR;
770  }
771  } else {
772  /* Failure sending the CMD_PROP_TX command */
773  PRINTF("transmit: PROP_TX_ERR ret=%d, CMDSTA=0x%08lx, status=0x%04x\n",
774  ret, cmd_status, cmd_tx_adv->status);
775  ret = RADIO_TX_ERR;
776  }
777 
778  /*
779  * Update ENERGEST state here, before a potential call to off(), which
780  * will correctly update it if required.
781  */
782  ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
783 
784  /*
785  * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
786  * except when we are transmitting
787  */
789 
790  /* Workaround. Set status to IDLE */
791  cmd_tx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE;
792 
793  rx_on_prop();
794 
795  if(was_off) {
796  off();
797  }
798 
799  return ret;
800 }
801 /*---------------------------------------------------------------------------*/
802 static int
803 send(const void *payload, unsigned short payload_len)
804 {
805  prepare(payload, payload_len);
806  return transmit(payload_len);
807 }
808 /*---------------------------------------------------------------------------*/
809 static void
810 release_data_entry(void)
811 {
812  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
813  uint8_t *data_ptr = &entry->data;
814  int_master_status_t interrupt_status;
815 
816  /* Clear the length field (2 bytes) */
817  data_ptr[0] = 0;
818  data_ptr[1] = 0;
819 
820  /* Set status to 0 "Pending" in element */
821  entry->status = DATA_ENTRY_STATUS_PENDING;
822  rx_read_entry = entry->pNextEntry;
823 
824  interrupt_status = critical_enter();
825  if(rf_core_rx_is_full) {
826  rf_core_rx_is_full = false;
827  PRINTF("RXQ was full, re-enabling radio!\n");
828  rx_on_prop();
829  }
830  critical_exit(interrupt_status);
831 
832 }
833 /*---------------------------------------------------------------------------*/
834 static int
835 read_frame(void *buf, unsigned short buf_len)
836 {
837  rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
838  uint8_t *data_ptr;
839  int len = 0;
840  uint32_t rat_timestamp;
841 
842  int is_found = 0;
843  /* Go through all RX buffers and check their status */
844  do {
845  if(entry->status == DATA_ENTRY_STATUS_FINISHED
846  || entry->status == DATA_ENTRY_STATUS_BUSY) {
847  is_found = 1;
848  break;
849  }
850 
851  entry = (rfc_dataEntryGeneral_t *)entry->pNextEntry;
852  } while(entry != (rfc_dataEntryGeneral_t *)rx_read_entry);
853 
854  if(is_found == 0) {
855  /* No available data */
856  return 0;
857  }
858 
859  rx_read_entry = (volatile uint8_t *)entry;
860 
861  /* wait for entry to become finished */
862  rtimer_clock_t t0 = RTIMER_NOW();
863  while(entry->status == DATA_ENTRY_STATUS_BUSY
864  && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 50)));
865 
866 #if MAC_CONF_WITH_TSCH
867  /* Make sure the flag is reset */
868  is_receiving_packet = 0;
869 #endif
870 
871  if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
872  /* No available data */
873  return 0;
874  }
875 
876  /*
877  * First 2 bytes in the data entry are the length.
878  * Our data entry consists of:
879  * Payload + RSSI (1 byte) + Timestamp (4 bytes) + Status (1 byte)
880  * This length includes all of those.
881  */
882  data_ptr = &entry->data;
883  len = (*(uint16_t *)data_ptr);
884 
885  if(len <= RX_BUF_METADATA_SIZE) {
886  PRINTF("RF: too short!");
887 
888  release_data_entry();
889  return 0;
890  }
891 
892  data_ptr += 2;
893  len -= RX_BUF_METADATA_SIZE;
894 
895  if(len > buf_len) {
896  PRINTF("RF: too long\n");
897 
898  release_data_entry();
899  return 0;
900  }
901 
902  memcpy(buf, data_ptr, len);
903 
904  /* get the RSSI and status */
905  rf_core_last_rssi = (int8_t)data_ptr[len];
906  rf_core_last_corr_lqi = data_ptr[len + 5];
907 
908  /* get the timestamp */
909  memcpy(&rat_timestamp, data_ptr + len + 1, 4);
910 
911  rf_core_last_packet_timestamp = rf_core_convert_rat_to_rtimer(rat_timestamp);
912 
913  if(!rf_core_poll_mode) {
914  /* Not in poll mode: packetbuf should not be accessed in interrupt context.
915  * In poll mode, the last packet RSSI and link quality can be obtained through
916  * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
917  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf_core_last_rssi);
918  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf_core_last_corr_lqi);
919  }
920 
921  release_data_entry();
922 
923  return len;
924 }
925 /*---------------------------------------------------------------------------*/
926 static int
927 channel_clear(void)
928 {
929  uint8_t was_off = 0;
930  uint32_t cmd_status;
931  int8_t rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
932 
933  /*
934  * If we are in the middle of a BLE operation, we got called by ContikiMAC
935  * from within an interrupt context. Indicate a clear channel
936  */
937  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
938  return RF_CORE_CCA_CLEAR;
939  }
940 
941  if(!rf_core_is_accessible()) {
942  was_off = 1;
943  if(on() != RF_CORE_CMD_OK) {
944  PRINTF("channel_clear: on() failed\n");
945  if(was_off) {
946  off();
947  }
948  return RF_CORE_CCA_CLEAR;
949  }
950  } else {
951  if(transmitting()) {
952  PRINTF("channel_clear: called while in TX\n");
953  return RF_CORE_CCA_CLEAR;
954  }
955  }
956 
957  while(rssi == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) {
958  if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_GET_RSSI), &cmd_status)
959  != RF_CORE_CMD_OK) {
960  break;
961  }
962  /* Current RSSI in bits 23:16 of cmd_status */
963  rssi = (cmd_status >> 16) & 0xFF;
964  }
965 
966  if(was_off) {
967  off();
968  }
969 
970  if(rssi >= rssi_threshold) {
971  return RF_CORE_CCA_BUSY;
972  }
973 
974  return RF_CORE_CCA_CLEAR;
975 }
976 /*---------------------------------------------------------------------------*/
977 static int
978 receiving_packet(void)
979 {
980  if(!rf_is_on()) {
981  return 0;
982  }
983 
984 #if MAC_CONF_WITH_TSCH
985  /*
986  * Under TSCH operation, we rely on "hints" from the MDMSOFT interrupt
987  * flag. This flag is set by the radio upon sync word detection, but it is
988  * not cleared automatically by hardware. We store state in a variable after
989  * first call. The assumption is that the TSCH code will keep calling us
990  * until frame reception has completed, at which point we can clear MDMSOFT.
991  */
992  if(!is_receiving_packet) {
993  /* Look for the modem synchronization word detection interrupt flag.
994  * This flag is raised when the synchronization word is received.
995  */
996  if(HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFHWIFG) & RFC_DBELL_RFHWIFG_MDMSOFT) {
997  is_receiving_packet = 1;
998  }
999  } else {
1000  /* After the start of the packet: reset the Rx flag once the channel gets clear */
1001  is_receiving_packet = (channel_clear() == RF_CORE_CCA_BUSY);
1002  if(!is_receiving_packet) {
1003  /* Clear the modem sync flag */
1004  ti_lib_rfc_hw_int_clear(RFC_DBELL_RFHWIFG_MDMSOFT);
1005  }
1006  }
1007 
1008  return is_receiving_packet;
1009 #else
1010  /*
1011  * Under CSMA operation, there is no immediately straightforward logic as to
1012  * when it's OK to clear the MDMSOFT interrupt flag:
1013  *
1014  * - We cannot re-use the same logic as above, since CSMA may bail out of
1015  * frame TX immediately after a single call this function here. In this
1016  * scenario, is_receiving_packet would remain equal to one and we would
1017  * therefore erroneously signal ongoing RX in subsequent calls to this
1018  * function here, even _after_ reception has completed.
1019  * - We can neither clear inside read_frame() nor inside the RX frame
1020  * interrupt handler (remember, we are not in poll mode under CSMA),
1021  * since we risk clearing MDMSOFT after we have seen a sync word for the
1022  * _next_ frame. If this happens, this function here would incorrectly
1023  * return 0 during RX of this next frame.
1024  *
1025  * So to avoid a very convoluted logic of how to handle MDMSOFT, we simply
1026  * perform a clear channel assessment here: We interpret channel activity
1027  * as frame reception.
1028  */
1029 
1030  if(channel_clear() == RF_CORE_CCA_CLEAR) {
1031  return 0;
1032  }
1033 
1034  return 1;
1035 
1036 #endif
1037 }
1038 /*---------------------------------------------------------------------------*/
1039 static int
1040 pending_packet(void)
1041 {
1042  int rv = 0;
1043  volatile rfc_dataEntry_t *entry = (rfc_dataEntry_t *)rx_data_queue.pCurrEntry;
1044 
1045  /* Go through all RX buffers and check their status */
1046  do {
1047  if(entry->status == DATA_ENTRY_STATUS_FINISHED
1048  || entry->status == DATA_ENTRY_STATUS_BUSY) {
1049  rv = 1;
1050  if(!rf_core_poll_mode) {
1051  process_poll(&rf_core_process);
1052  }
1053  }
1054 
1055  entry = (rfc_dataEntry_t *)entry->pNextEntry;
1056  } while(entry != (rfc_dataEntry_t *)rx_data_queue.pCurrEntry);
1057 
1058  /* If we didn't find an entry at status finished, no frames are pending */
1059  return rv;
1060 }
1061 /*---------------------------------------------------------------------------*/
1062 static int
1063 on(void)
1064 {
1065  /*
1066  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1067  * from within an interrupt context. Abort, but pretend everything is OK.
1068  */
1069  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1070  return RF_CORE_CMD_OK;
1071  }
1072 
1073  if(rf_is_on()) {
1074  PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(),
1075  smartrf_settings_cmd_prop_rx_adv.status);
1076  return RF_CORE_CMD_OK;
1077  }
1078 
1079  /*
1080  * Request the HF XOSC as the source for the HF clock. Needed before we can
1081  * use the FS. This will only request, it will _not_ perform the switch.
1082  */
1084 
1085  if(!rf_core_is_accessible()) {
1086  if(rf_core_power_up() != RF_CORE_CMD_OK) {
1087  PRINTF("on: rf_core_power_up() failed\n");
1088 
1090 
1091  return RF_CORE_CMD_ERROR;
1092  }
1093 
1094  /* Keep track of RF Core mode */
1096 
1097  /* Apply patches to radio core */
1098  rf_patch_cpe_genfsk();
1099  while(!HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG));
1100  HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
1101  rf_patch_rfe_genfsk();
1102 
1103  /* Initialize bus request */
1104  HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
1105  HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) =
1106  CMDR_DIR_CMD_1BYTE(CMD_BUS_REQUEST, 1);
1107 
1108  /* set VCOLDO reference */
1109  ti_lib_rfc_adi3vco_ldo_voltage_mode(true);
1110 
1111  /* Let CC13xxware automatically set a correct value for RTRIM for us */
1112  ti_lib_rfc_rtrim((rfc_radioOp_t *)&smartrf_settings_cmd_prop_radio_div_setup);
1113 
1114  /* Make sure BUS_REQUEST is done */
1115  while(!HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG));
1116  HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
1117 
1118  if(rf_core_start_rat() != RF_CORE_CMD_OK) {
1119  PRINTF("on: rf_core_start_rat() failed\n");
1120 
1122 
1123  return RF_CORE_CMD_ERROR;
1124  }
1125  }
1126 
1128 
1129  init_rx_buffers();
1130 
1131  /*
1132  * Trigger a switch to the XOSC, so that we can subsequently use the RF FS
1133  * This will block until the XOSC is actually ready, but give how we
1134  * requested it early on, this won't be too long a wait/
1135  */
1137 
1138  if(prop_div_radio_setup() != RF_CORE_CMD_OK) {
1139  PRINTF("on: prop_div_radio_setup() failed\n");
1140  return RF_CORE_CMD_ERROR;
1141  }
1142 
1143  if(prop_fs() != RF_CORE_CMD_OK) {
1144  PRINTF("on: prop_fs() failed\n");
1145  return RF_CORE_CMD_ERROR;
1146  }
1147 
1148  return rx_on_prop();
1149 }
1150 /*---------------------------------------------------------------------------*/
1151 static int
1152 off(void)
1153 {
1154  int i;
1155  rfc_dataEntry_t *entry;
1156 
1157  /*
1158  * If we are in the middle of a BLE operation, we got called by ContikiMAC
1159  * from within an interrupt context. Abort, but pretend everything is OK.
1160  */
1161  if(rf_ble_is_active() == RF_BLE_ACTIVE) {
1162  return RF_CORE_CMD_OK;
1163  }
1164 
1165  rx_off_prop();
1167 
1168  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
1169 
1170 #if !CC2650_FAST_RADIO_STARTUP
1171  /* Switch HF clock source to the RCOSC to preserve power */
1173 #endif
1174 
1175  /* We pulled the plug, so we need to restore the status manually */
1176  smartrf_settings_cmd_prop_rx_adv.status = RF_CORE_RADIO_OP_STATUS_IDLE;
1177 
1178  /*
1179  * Just in case there was an ongoing RX (which started after we begun the
1180  * shutdown sequence), we don't want to leave the buffer in state == ongoing
1181  */
1182  for(i = 0; i < PROP_MODE_RX_BUF_CNT; i++) {
1183  entry = (rfc_dataEntry_t *)rx_buf[i];
1184  if(entry->status == DATA_ENTRY_STATUS_BUSY) {
1185  entry->status = DATA_ENTRY_STATUS_PENDING;
1186  }
1187  }
1188 
1189  return RF_CORE_CMD_OK;
1190 }
1191 /*---------------------------------------------------------------------------*/
1192 /* Enable or disable CCA before sending */
1193 static radio_result_t
1194 set_send_on_cca(uint8_t enable)
1195 {
1196  if(enable) {
1197  /* this driver does not have support for CCA on Tx */
1199  }
1200  return RADIO_RESULT_OK;
1201 }
1202 /*---------------------------------------------------------------------------*/
1203 static radio_result_t
1204 get_value(radio_param_t param, radio_value_t *value)
1205 {
1206  if(!value) {
1208  }
1209 
1210  switch(param) {
1212  /* On / off */
1214  return RADIO_RESULT_OK;
1215  case RADIO_PARAM_CHANNEL:
1216  *value = (radio_value_t)get_channel();
1217  return RADIO_RESULT_OK;
1218  case RADIO_PARAM_RX_MODE:
1219  *value = 0;
1220  if(rf_core_poll_mode) {
1221  *value |= RADIO_RX_MODE_POLL_MODE;
1222  }
1223  return RADIO_RESULT_OK;
1224  case RADIO_PARAM_TX_MODE:
1225  *value = 0;
1226  return RADIO_RESULT_OK;
1227  case RADIO_PARAM_TXPOWER:
1228  *value = get_tx_power();
1229  return RADIO_RESULT_OK;
1231  *value = rssi_threshold;
1232  return RADIO_RESULT_OK;
1233  case RADIO_PARAM_RSSI:
1234  *value = get_rssi();
1235 
1236  if(*value == RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN) {
1237  return RADIO_RESULT_ERROR;
1238  } else {
1239  return RADIO_RESULT_OK;
1240  }
1242  *value = 0;
1243  return RADIO_RESULT_OK;
1245  *value = DOT_15_4G_CHANNEL_MAX;
1246  return RADIO_RESULT_OK;
1248  *value = TX_POWER_DRIVER[get_tx_power_array_last_element()].dbm;
1249  return RADIO_RESULT_OK;
1251  *value = OUTPUT_POWER_MAX;
1252  return RADIO_RESULT_OK;
1253  case RADIO_PARAM_LAST_RSSI:
1254  *value = rf_core_last_rssi;
1255  return RADIO_RESULT_OK;
1257  *value = rf_core_last_corr_lqi;
1258  return RADIO_RESULT_OK;
1260  /* 2 header bytes, 2 or 4 bytes CRC */
1261  *value = (radio_value_t)(DOT_4G_PHR_LEN + CRC_LEN);
1262  return RADIO_RESULT_OK;
1264  *value = (radio_value_t)RADIO_BYTE_AIR_TIME;
1265  return RADIO_RESULT_OK;
1267  *value = (radio_value_t)RADIO_DELAY_BEFORE_TX;
1268  return RADIO_RESULT_OK;
1270  *value = (radio_value_t)RADIO_DELAY_BEFORE_RX;
1271  return RADIO_RESULT_OK;
1273  *value = (radio_value_t)RADIO_DELAY_BEFORE_DETECT;
1274  return RADIO_RESULT_OK;
1275  case RADIO_CONST_MAX_PAYLOAD_LEN:
1276  *value = (radio_value_t)MAX_PAYLOAD_LEN;
1277  return RADIO_RESULT_OK;
1278  default:
1280  }
1281 }
1282 /*---------------------------------------------------------------------------*/
1283 static radio_result_t
1284 set_value(radio_param_t param, radio_value_t value)
1285 {
1287  uint8_t old_poll_mode;
1288 
1289  switch(param) {
1291  if(value == RADIO_POWER_MODE_ON) {
1292  if(on() != RF_CORE_CMD_OK) {
1293  PRINTF("set_value: on() failed (1)\n");
1294  return RADIO_RESULT_ERROR;
1295  }
1296  return RADIO_RESULT_OK;
1297  }
1298  if(value == RADIO_POWER_MODE_OFF) {
1299  off();
1300  return RADIO_RESULT_OK;
1301  }
1303  case RADIO_PARAM_CHANNEL:
1304  if(value < 0 ||
1305  value > DOT_15_4G_CHANNEL_MAX) {
1307  }
1308 
1309  if(get_channel() == (uint8_t)value) {
1310  /* We already have that very same channel configured.
1311  * Nothing to do here. */
1312  return RADIO_RESULT_OK;
1313  }
1314 
1315  set_channel((uint8_t)value);
1316  break;
1317 
1318  case RADIO_PARAM_RX_MODE:
1319  if(value & ~(RADIO_RX_MODE_POLL_MODE)) {
1321  }
1322 
1323  old_poll_mode = rf_core_poll_mode;
1324  rf_core_poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
1325  if(rf_core_poll_mode == old_poll_mode) {
1326  return RADIO_RESULT_OK;
1327  }
1328  break;
1329 
1330  case RADIO_PARAM_TX_MODE:
1331  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1333  }
1334  return set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1335 
1336  case RADIO_PARAM_TXPOWER:
1337  if(value < TX_POWER_DRIVER[get_tx_power_array_last_element()].dbm ||
1338  value > OUTPUT_POWER_MAX) {
1340  }
1341 
1342  soft_off_prop();
1343 
1344  set_tx_power(value);
1345 
1346  if(soft_on_prop() != RF_CORE_CMD_OK) {
1347  PRINTF("set_value: soft_on_prop() failed\n");
1348  rv = RADIO_RESULT_ERROR;
1349  }
1350 
1351  return RADIO_RESULT_OK;
1352 
1354  rssi_threshold = (int8_t)value;
1355  break;
1356  default:
1358  }
1359 
1360  /* If off, the new configuration will be applied the next time radio is started */
1361  if(!rf_is_on()) {
1362  return RADIO_RESULT_OK;
1363  }
1364 
1365  /* If we reach here we had no errors. Apply new settings */
1366  if(rx_off_prop() != RF_CORE_CMD_OK) {
1367  PRINTF("set_value: rx_off_prop() failed\n");
1368  rv = RADIO_RESULT_ERROR;
1369  }
1370 
1371  /* Restart the radio timer (RAT).
1372  This causes resynchronization between RAT and RTC: useful for TSCH. */
1373  if(rf_core_restart_rat() != RF_CORE_CMD_OK) {
1374  PRINTF("set_value: rf_core_restart_rat() failed\n");
1375  /* do not set the error */
1376  } else {
1378  }
1379 
1380  if(soft_on_prop() != RF_CORE_CMD_OK) {
1381  PRINTF("set_value: soft_on_prop() failed\n");
1382  rv = RADIO_RESULT_ERROR;
1383  }
1384 
1385  return rv;
1386 }
1387 /*---------------------------------------------------------------------------*/
1388 static radio_result_t
1389 get_object(radio_param_t param, void *dest, size_t size)
1390 {
1391  if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
1392  if(size != sizeof(rtimer_clock_t) || !dest) {
1394  }
1395  *(rtimer_clock_t *)dest = rf_core_last_packet_timestamp;
1396 
1397  return RADIO_RESULT_OK;
1398  }
1399 
1401 }
1402 /*---------------------------------------------------------------------------*/
1403 static radio_result_t
1404 set_object(radio_param_t param, const void *src, size_t size)
1405 {
1407 }
1408 /*---------------------------------------------------------------------------*/
1409 const struct radio_driver prop_mode_driver = {
1410  init,
1411  prepare,
1412  transmit,
1413  send,
1414  read_frame,
1415  channel_clear,
1418  on,
1419  off,
1420  get_value,
1421  set_value,
1422  get_object,
1423  set_object,
1424 };
1425 /*---------------------------------------------------------------------------*/
1426 /**
1427  * @}
1428  */
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
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
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
static void critical_exit(int_master_status_t status)
Exit a critical section and restore the master interrupt.
Definition: critical.h:81
int rf_core_power_up()
Turn on power to the RFC and boot it.
Definition: rf-core.c:263
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
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
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:175
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
static int_master_status_t critical_enter()
Enter a critical section.
Definition: critical.h:65
#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
Header file with descriptors for the various modes of operation defined in IEEE 802.15.4g.
void oscillators_switch_to_hf_rc(void)
Switches MF and HF clock source to be the HF RC OSC.
Definition: oscillators.c:134
INT_MASTER_STATUS_DATATYPE int_master_status_t
Master interrupt state representation data type.
Definition: int-master.h:62
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
Header file for the CC13xx prop mode NETSTACK_RADIO driver.
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 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
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
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
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.
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
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_start_rat(void)
Start the CM0 RAT.
Definition: rf-core.c:312
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
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
static uint8_t get_channel()
Get the current operating channel.
Definition: cc2538-rf.c:165