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