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