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