Contiki-NG
prop-mode.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, 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  * \addtogroup cc13xx-cc26xx-rf
32  * @{
33  *
34  * \defgroup cc13xx-cc26xx-rf-prop Prop-mode driver for CC13xx/CC26xx
35  *
36  * @{
37  *
38  * \file
39  * Implementation of the CC13xx/CC26xx prop-mode NETSTACK_RADIO driver.
40  * \author
41  * Edvard Pettersen <e.pettersen@ti.com>
42  */
43 /*---------------------------------------------------------------------------*/
44 #include "contiki.h"
45 #include "net/packetbuf.h"
46 #include "net/netstack.h"
47 #include "sys/energest.h"
48 #include "sys/clock.h"
49 #include "sys/rtimer.h"
50 #include "sys/cc.h"
51 #include "dev/watchdog.h"
52 /*---------------------------------------------------------------------------*/
53 /* RF Core Mailbox API */
54 #include <ti/devices/DeviceFamily.h>
55 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
56 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
57 #include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
58 #include DeviceFamily_constructPath(driverlib/rf_prop_cmd.h)
59 #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
60 
61 #include <ti/drivers/rf/RF.h>
62 #include DeviceFamily_constructPath(inc/hw_rfc_dbell.h)
63 #include DeviceFamily_constructPath(driverlib/rfc.h)
64 /*---------------------------------------------------------------------------*/
65 /* Platform RF dev */
66 #include "rf/rf.h"
67 #include "rf/dot-15-4g.h"
68 #include "rf/sched.h"
69 #include "rf/data-queue.h"
70 #include "rf/tx-power.h"
71 #include "rf/settings.h"
72 #include "rf/rat.h"
73 #include "rf/radio-mode.h"
74 /*---------------------------------------------------------------------------*/
75 #include <stdint.h>
76 #include <string.h>
77 #include <stdio.h>
78 #include <stdbool.h>
79 #include <assert.h>
80 /*---------------------------------------------------------------------------*/
81 /* Log configuration */
82 #include "sys/log.h"
83 #define LOG_MODULE "Radio"
84 #define LOG_LEVEL LOG_LEVEL_NONE
85 /*---------------------------------------------------------------------------*/
86 #undef CLAMP
87 #define CLAMP(v, vmin, vmax) (MAX(MIN(v, vmax), vmin))
88 /*---------------------------------------------------------------------------*/
89 /* Configuration parameters */
90 #define PROP_MODE_DYN_WHITENER PROP_MODE_CONF_DW
91 #define PROP_MODE_USE_CRC16 PROP_MODE_CONF_USE_CRC16
92 #define PROP_MODE_CENTER_FREQ PROP_MODE_CONF_CENTER_FREQ
93 #define PROP_MODE_LO_DIVIDER PROP_MODE_CONF_LO_DIVIDER
94 #define PROP_MODE_CCA_RSSI_THRESHOLD PROP_MODE_CONF_CCA_RSSI_THRESHOLD
95 /*---------------------------------------------------------------------------*/
96 /* Used for checking result of CCA_REQ command */
97 typedef enum {
98  CCA_STATE_IDLE = 0,
99  CCA_STATE_BUSY = 1,
100  CCA_STATE_INVALID = 2
101 } cca_state_t;
102 /*---------------------------------------------------------------------------*/
103 #if MAC_CONF_WITH_TSCH
104 static volatile uint8_t is_receiving_packet;
105 #endif
106 /*---------------------------------------------------------------------------*/
107 /* Defines and variables related to the .15.4g PHY HDR */
108 #define DOT_4G_PHR_NUM_BYTES 2
109 #define DOT_4G_LEN_OFFSET 0xFC
110 #define DOT_4G_SYNCWORD 0x0055904E
111 
112 /* PHY HDR bits */
113 #define DOT_4G_PHR_CRC16 0x10
114 #define DOT_4G_PHR_DW 0x08
115 
116 #if PROP_MODE_USE_CRC16
117 /* CRC16 */
118 #define DOT_4G_PHR_CRC_BIT DOT_4G_PHR_CRC16
119 #define CRC_LEN 2
120 #else
121 /* CRC32 */
122 #define DOT_4G_PHR_CRC_BIT 0
123 #define CRC_LEN 4
124 #endif /* PROP_MODE_USE_CRC16 */
125 
126 #if PROP_MODE_DYN_WHITENER
127 #define DOT_4G_PHR_DW_BIT DOT_4G_PHR_DW
128 #else
129 #define DOT_4G_PHR_DW_BIT 0
130 #endif
131 /*---------------------------------------------------------------------------*/
132 /*
133  * The maximum number of bytes this driver can accept from the MAC layer for
134  * transmission or will deliver to the MAC layer after reception. Includes
135  * the MAC header and payload, but not the CRC.
136  *
137  * Unlike typical 2.4GHz radio drivers, this driver supports the .15.4g
138  * 32-bit CRC option.
139  *
140  * This radio hardware is perfectly happy to transmit frames longer than 127
141  * bytes, which is why it's OK to end up transmitting 125 payload bytes plus
142  * a 4-byte CRC.
143  *
144  * In the future we can change this to support transmission of long frames,
145  * for example as per .15.4g, which defines 2047 as the maximum frame size.
146  * The size of the TX and RX buffers would need to be adjusted accordingly.
147  */
148 #define MAX_PAYLOAD_LEN 125
149 /*---------------------------------------------------------------------------*/
150 /* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */
151 #define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10)
152 
153 /*---------------------------------------------------------------------------*/
154 /*
155  * Offset of the end of SFD when compared to the radio HW-generated timestamp.
156  */
157 #define RAT_TIMESTAMP_OFFSET USEC_TO_RAT(RADIO_PHY_HEADER_LEN * RADIO_BYTE_AIR_TIME - 270)
158 /*---------------------------------------------------------------------------*/
159 /* TX buf configuration */
160 #define TX_BUF_HDR_LEN 2
161 #define TX_BUF_PAYLOAD_LEN 180
162 
163 #define TX_BUF_SIZE (TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN)
164 /*---------------------------------------------------------------------------*/
165 /* Size of the Length field in Data Entry, two bytes in this case */
166 typedef uint16_t lensz_t;
167 
168 #define FRAME_OFFSET sizeof(lensz_t)
169 #define FRAME_SHAVE 6 /**< RSSI (1) + Timestamp (4) + Status (1) */
170 /*---------------------------------------------------------------------------*/
171 /* Constants used when calculating the LQI from the RSSI */
172 #define RX_SENSITIVITY_DBM -110
173 #define RX_SATURATION_DBM 10
174 #define ED_MIN_DBM_ABOVE_RX_SENSITIVITY 10
175 #define ED_MAX 0xFF
176 
177 #define ED_RF_POWER_MIN_DBM (RX_SENSITIVITY_DBM + ED_MIN_DBM_ABOVE_RX_SENSITIVITY)
178 #define ED_RF_POWER_MAX_DBM RX_SATURATION_DBM
179 /*---------------------------------------------------------------------------*/
180 /* RF Core typedefs */
181 typedef rfc_propRxOutput_t rx_output_t;
182 
183 typedef struct {
184  /* RF driver */
185  RF_Handle rf_handle;
186 
187  /* Are we currently in poll mode? */
188  bool poll_mode;
189 
190  /* RAT Overflow Upkeep */
191  struct {
192  struct ctimer overflow_timer;
193  rtimer_clock_t last_overflow;
194  volatile uint32_t overflow_count;
195  } rat;
196 
197  bool (* rx_is_active)(void);
198 
199  /* Outgoing frame buffer */
200  uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
201 
202  /* RX Statistics struct */
203  rx_output_t rx_stats;
204 
205  /* RSSI Threshold */
206  int8_t rssi_threshold;
207  uint16_t channel;
208 
209  /* Indicates RF is supposed to be on or off */
210  uint8_t rf_is_on;
211  /* Enable/disable CCA before sending */
212  bool send_on_cca;
213 
214  /* Last RX operation stats */
215  struct {
216  int8_t rssi;
217  uint8_t corr_lqi;
218  uint32_t timestamp;
219  } last;
220 } prop_radio_t;
221 
222 static prop_radio_t prop_radio;
223 
224 /*---------------------------------------------------------------------------*/
225 /* Convenience macros for more succinct access of RF commands */
226 #define cmd_radio_setup rf_cmd_prop_radio_div_setup
227 #define cmd_fs rf_cmd_prop_fs
228 #define cmd_tx rf_cmd_prop_tx_adv
229 #define cmd_rx rf_cmd_prop_rx_adv
230 
231 /* Convenience macros for volatile access with the RF commands */
232 #define v_cmd_radio_setup CC_ACCESS_NOW(rfc_CMD_PROP_RADIO_DIV_SETUP_t, rf_cmd_prop_radio_div_setup)
233 #define v_cmd_fs CC_ACCESS_NOW(rfc_CMD_FS_t, rf_cmd_prop_fs)
234 #define v_cmd_tx CC_ACCESS_NOW(rfc_CMD_PROP_TX_ADV_t, rf_cmd_prop_tx_adv)
235 #define v_cmd_rx CC_ACCESS_NOW(rfc_CMD_PROP_RX_ADV_t, rf_cmd_prop_rx_adv)
236 /*---------------------------------------------------------------------------*/
237 static inline bool
238 tx_is_active(void)
239 {
240  return v_cmd_tx.status == ACTIVE;
241 }
242 /*---------------------------------------------------------------------------*/
243 static inline bool
244 rx_is_active(void)
245 {
246  return v_cmd_rx.status == ACTIVE;
247 }
248 /*---------------------------------------------------------------------------*/
249 static int channel_clear(void);
250 static int on(void);
251 static int off(void);
252 static rf_result_t set_channel_force(uint16_t channel);
253 /*---------------------------------------------------------------------------*/
254 static void
255 init_rf_params(void)
256 {
257  cmd_radio_setup.config.frontEndMode = RF_SUB_1_GHZ_FRONT_END_MODE;
258  cmd_radio_setup.config.biasMode = RF_SUB_1_GHZ_BIAS_MODE;
259  cmd_radio_setup.centerFreq = PROP_MODE_CENTER_FREQ;
260  cmd_radio_setup.loDivider = PROP_MODE_LO_DIVIDER;
261 
262  cmd_tx.numHdrBits = DOT_4G_PHR_NUM_BYTES * 8;
263  cmd_tx.syncWord = DOT_4G_SYNCWORD;
264 
265  cmd_rx.syncWord0 = DOT_4G_SYNCWORD;
266  cmd_rx.syncWord1 = 0x00000000;
267  cmd_rx.maxPktLen = RADIO_PHY_OVERHEAD + MAX_PAYLOAD_LEN;
268  cmd_rx.hdrConf.numHdrBits = DOT_4G_PHR_NUM_BYTES * 8;
269  cmd_rx.lenOffset = DOT_4G_LEN_OFFSET;
270  cmd_rx.pQueue = data_queue_init(sizeof(lensz_t));
271  cmd_rx.pOutput = (uint8_t *)&prop_radio.rx_stats;
272 }
273 /*---------------------------------------------------------------------------*/
274 static int8_t
275 get_rssi(void)
276 {
277  rf_result_t res;
278  bool stop_rx = false;
279  int8_t rssi = RF_GET_RSSI_ERROR_VAL;
280 
281  /* RX is required to be running in order to do a RSSI measurement */
282  if(!rx_is_active()) {
283  /* If RX is not pending, i.e. soon to be running, schedule the RX command */
284  if(v_cmd_rx.status != PENDING) {
285  res = netstack_sched_rx(false);
286  if(res != RF_RESULT_OK) {
287  LOG_ERR("RSSI measurement failed to schedule RX\n");
288  return res;
289  }
290 
291  /* We only stop RX if we had to schedule it */
292  stop_rx = true;
293  }
294 
295  /* Make sure RX is running before we continue, unless we timeout and fail */
296  RTIMER_BUSYWAIT_UNTIL(rx_is_active(), TIMEOUT_ENTER_RX_WAIT);
297 
298  if(!rx_is_active()) {
299  LOG_ERR("RSSI measurement failed to turn on RX, RX status=0x%04X\n", v_cmd_rx.status);
300  return RF_RESULT_ERROR;
301  }
302  }
303 
304  /* Perform the RSSI measurement */
305  rssi = RF_getRssi(prop_radio.rf_handle);
306 
307  if(stop_rx) {
308  netstack_stop_rx();
309  }
310 
311  return rssi;
312 }
313 /*---------------------------------------------------------------------------*/
314 static uint8_t
315 get_channel(void)
316 {
317  uint32_t freq_khz = v_cmd_fs.frequency * 1000;
318 
319  /*
320  * For some channels, fractFreq * 1000 / 65536 will return 324.99xx.
321  * Casting the result to uint32_t will truncate decimals resulting in the
322  * function returning channel - 1 instead of channel. Thus, we do a quick
323  * positive integer round up.
324  */
325  freq_khz += (((v_cmd_fs.fractFreq * 1000) + 65535) / 65536);
326 
327  return (uint8_t)((freq_khz - DOT_15_4G_CHAN0_FREQ) / DOT_15_4G_FREQ_SPACING);
328 }
329 /*---------------------------------------------------------------------------*/
330 static rf_result_t
331 set_channel(uint16_t channel)
332 {
333  if(!dot_15_4g_chan_in_range(channel)) {
334  LOG_WARN("Supplied hannel %d is illegal, defaults to %d\n",
335  (int)channel, DOT_15_4G_DEFAULT_CHAN);
336  channel = DOT_15_4G_DEFAULT_CHAN;
337  }
338 
339  if(channel == prop_radio.channel) {
340  /* We are already calibrated to this channel */
341  return RF_RESULT_OK;
342  }
343 
344  return set_channel_force(channel);
345 }
346 /*---------------------------------------------------------------------------*/
347 /* Sets the given channel without checking if it is a valid channel number. */
348 static rf_result_t
349 set_channel_force(uint16_t channel)
350 {
351  rf_result_t res;
352 
353  if(prop_radio.rf_is_on) {
354  /* Force RAT and RTC resync */
355  rf_restart_rat();
356  }
357 
358  const uint32_t new_freq = dot_15_4g_freq(channel);
359  const uint16_t freq = (uint16_t)(new_freq / 1000);
360  const uint16_t frac = (uint16_t)(((new_freq - (freq * 1000)) * 0x10000) / 1000);
361 
362  LOG_DBG("Set channel to %d, frequency 0x%04X.0x%04X (%lu)\n",
363  (int)channel, freq, frac, new_freq);
364 
365  v_cmd_fs.frequency = freq;
366  v_cmd_fs.fractFreq = frac;
367 
368  res = netstack_sched_fs();
369 
370  if(res != RF_RESULT_OK) {
371  return res;
372  }
373 
374  prop_radio.channel = channel;
375  return RF_RESULT_OK;
376 }
377 /*---------------------------------------------------------------------------*/
378 static uint8_t
379 calculate_lqi(int8_t rssi)
380 {
381  /*
382  * Note : Currently the LQI value is simply the energy detect measurement.
383  * A more accurate value could be derived by using the correlation
384  * value along with the RSSI value.
385  */
386  rssi = CLAMP(rssi, ED_RF_POWER_MIN_DBM, ED_RF_POWER_MAX_DBM);
387 
388  /*
389  * Create energy detect measurement by normalizing and scaling RF power level.
390  * Note : The division operation below is designed for maximum accuracy and
391  * best granularity. This is done by grouping the math operations to
392  * compute the entire numerator before doing any division.
393  */
394  return (ED_MAX * (rssi - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);
395 }
396 /*---------------------------------------------------------------------------*/
397 static void
398 set_send_on_cca(bool enable)
399 {
400  prop_radio.send_on_cca = enable;
401 }
402 /*---------------------------------------------------------------------------*/
403 static int
404 prepare(const void *payload, unsigned short payload_len)
405 {
406  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > MAX_PAYLOAD_LEN) {
407  return RADIO_TX_ERR;
408  }
409 
410  memcpy(prop_radio.tx_buf + TX_BUF_HDR_LEN, payload, payload_len);
411  return 0;
412 }
413 /*---------------------------------------------------------------------------*/
414 static int
415 transmit(unsigned short transmit_len)
416 {
417  rf_result_t res;
418 
419  if(transmit_len > MAX_PAYLOAD_LEN) {
420  LOG_ERR("Too long\n");
421  return RADIO_TX_ERR;
422  }
423 
424  if(tx_is_active()) {
425  LOG_ERR("A transmission is already active\n");
426  return RADIO_TX_ERR;
427  }
428 
429  if(prop_radio.send_on_cca && !channel_clear()) {
430  LOG_WARN("Channel is not clear for transmission\n");
431  return RADIO_TX_COLLISION;
432  }
433 
434  /* Length in .15.4g PHY HDR. Includes the CRC but not the HDR itself */
435  const uint16_t total_length = transmit_len + CRC_LEN;
436  /*
437  * Prepare the .15.4g PHY header
438  * MS=0, Length MSBits=0, DW and CRC configurable
439  * Total length = transmit_len (payload) + CRC length
440  *
441  * The Radio will flip the bits around, so tx_buf[0] must have the length
442  * LSBs (PHR[15:8] and tx_buf[1] will have PHR[7:0]
443  */
444  prop_radio.tx_buf[0] = ((total_length >> 0) & 0xFF);
445  prop_radio.tx_buf[1] = ((total_length >> 8) & 0xFF) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT;
446 
447  /* pktLen: Total number of bytes in the TX buffer, including the header if
448  * one exists, but not including the CRC (which is not present in the buffer) */
449  v_cmd_tx.pktLen = transmit_len + DOT_4G_PHR_NUM_BYTES;
450  v_cmd_tx.pPkt = prop_radio.tx_buf;
451 
452  res = netstack_sched_prop_tx(transmit_len);
453 
454  if(res != RF_RESULT_OK) {
455  LOG_WARN("Channel is not clear for transmission\n");
456  return RADIO_TX_ERR;
457  }
458 
459  return (res == RF_RESULT_OK)
460  ? RADIO_TX_OK
461  : RADIO_TX_ERR;
462 }
463 /*---------------------------------------------------------------------------*/
464 static int
465 send(const void *payload, unsigned short payload_len)
466 {
467  prepare(payload, payload_len);
468  return transmit(payload_len);
469 }
470 /*---------------------------------------------------------------------------*/
471 static int
472 read(void *buf, unsigned short buf_len)
473 {
474  volatile data_entry_t *data_entry = data_queue_current_entry();
475 
476  /* Only wait if the Radio is accessing the entry */
477  const rtimer_clock_t t0 = RTIMER_NOW();
478  while((data_entry->status == DATA_ENTRY_BUSY) &&
479  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + RADIO_FRAME_DURATION(MAX_PAYLOAD_LEN)));
480 
481 #if MAC_CONF_WITH_TSCH
482  /* Make sure the flag is reset */
483  is_receiving_packet = 0;
484 #endif
485 
486  if(data_entry->status != DATA_ENTRY_FINISHED) {
487  /* No available data */
488  return 0;
489  }
490 
491  /*
492  * lensz bytes (2) in the data entry are the length of the received frame.
493  * Data frame is on the following format:
494  * Length (2) + Payload (N) + RSSI (1) + Timestamp (4) + Status (1)
495  * Data frame DOES NOT contain the following:
496  * no Header/PHY bytes
497  * no appended Received CRC bytes
498  * Visual representation of frame format:
499  *
500  * +---------+---------+--------+-----------+--------+
501  * | 2 bytes | N bytes | 1 byte | 4 bytes | 1 byte |
502  * +---------+---------+--------+-----------+--------+
503  * | Length | Payload | RSSI | Timestamp | Status |
504  * +---------+---------+--------+-----------+--------+
505  *
506  * Length bytes equal total length of entire frame excluding itself,
507  * Length = N + RSSI (1) + Timestamp (4) + Status (1)
508  * = N + 6
509  * N = Length - 6
510  */
511  uint8_t *const frame_ptr = (uint8_t *)&data_entry->data;
512  const lensz_t frame_len = *(lensz_t *)frame_ptr;
513 
514  /* Sanity check that Frame is at least Frame Shave bytes long */
515  if(frame_len < FRAME_SHAVE) {
516  LOG_ERR("Received frame is too short, len=%d\n", frame_len);
517 
518  data_queue_release_entry();
519  return 0;
520  }
521 
522  const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t);
523  const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE);
524 
525  /* Sanity check that Payload fits in Buffer */
526  if(payload_len > buf_len) {
527  LOG_ERR("Payload of received frame is too large for local buffer, len=%d buf_len=%d\n",
528  payload_len, buf_len);
529 
530  data_queue_release_entry();
531  return 0;
532  }
533 
534  memcpy(buf, payload_ptr, payload_len);
535 
536  /* RSSI stored after payload */
537  prop_radio.last.rssi = (int8_t)payload_ptr[payload_len];
538  /* LQI calculated from RSSI */
539  prop_radio.last.corr_lqi = calculate_lqi(prop_radio.last.rssi);
540  /* Timestamp stored RSSI (1) bytes after payload. */
541  uint32_t rat_ticks;
542  memcpy(&rat_ticks, payload_ptr + payload_len + 1, 4);
543 
544  /* Correct timestamp so that it refers to the end of the SFD */
545  prop_radio.last.timestamp = rat_to_timestamp(rat_ticks, RAT_TIMESTAMP_OFFSET);
546 
547  if(!prop_radio.poll_mode) {
548  /* Not in poll mode: packetbuf should not be accessed in interrupt context. */
549  /* In poll mode, the last packet RSSI and link quality can be obtained through */
550  /* RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
551  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)prop_radio.last.rssi);
552  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)prop_radio.last.corr_lqi);
553  }
554 
555  data_queue_release_entry();
556  return (int)payload_len;
557 }
558 /*---------------------------------------------------------------------------*/
559 static uint8_t
560 cca_request(void)
561 {
562  const int8_t rssi = get_rssi();
563 
564  if(rssi == RF_GET_RSSI_ERROR_VAL) {
565  return CCA_STATE_INVALID;
566  }
567 
568  return (rssi < prop_radio.rssi_threshold)
569  ? CCA_STATE_IDLE
570  : CCA_STATE_BUSY;
571 }
572 /*---------------------------------------------------------------------------*/
573 static int
574 channel_clear(void)
575 {
576  if(tx_is_active()) {
577  LOG_ERR("Channel clear called while in TX\n");
578  return 0;
579  }
580 
581  const uint8_t cca_state = cca_request();
582 
583  /* Channel is clear if CCA state is IDLE */
584  return cca_state == CCA_STATE_IDLE;
585 }
586 /*---------------------------------------------------------------------------*/
587 static int
588 receiving_packet(void)
589 {
590  if(!prop_radio.rf_is_on) {
591  return 0;
592  }
593 
594 #if MAC_CONF_WITH_TSCH
595  /*
596  * Under TSCH operation, we rely on "hints" from the MDMSOFT interrupt
597  * flag. This flag is set by the radio upon sync word detection, but it is
598  * not cleared automatically by hardware. We store state in a variable after
599  * first call. The assumption is that the TSCH code will keep calling us
600  * until frame reception has completed, at which point we can clear MDMSOFT.
601  */
602  if(!is_receiving_packet) {
603  /* Look for the modem synchronization word detection interrupt flag.
604  * This flag is raised when the synchronization word is received.
605  */
606  if(HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFHWIFG) & RFC_DBELL_RFHWIFG_MDMSOFT) {
607  is_receiving_packet = 1;
608  }
609  } else {
610  /* After the start of the packet: reset the Rx flag once the channel gets clear */
611  is_receiving_packet = (cca_request() == CCA_STATE_BUSY);
612  if(!is_receiving_packet) {
613  /* Clear the modem sync flag */
614  RFCHwIntClear(RFC_DBELL_RFHWIFG_MDMSOFT);
615  }
616  }
617 
618  return is_receiving_packet;
619 #else
620  /*
621  * Under CSMA operation, there is no immediately straightforward logic as to
622  * when it's OK to clear the MDMSOFT interrupt flag:
623  *
624  * - We cannot re-use the same logic as above, since CSMA may bail out of
625  * frame TX immediately after a single call this function here. In this
626  * scenario, is_receiving_packet would remain equal to one and we would
627  * therefore erroneously signal ongoing RX in subsequent calls to this
628  * function here, even _after_ reception has completed.
629  * - We can neither clear inside read_frame() nor inside the RX frame
630  * interrupt handler (remember, we are not in poll mode under CSMA),
631  * since we risk clearing MDMSOFT after we have seen a sync word for the
632  * _next_ frame. If this happens, this function here would incorrectly
633  * return 0 during RX of this next frame.
634  *
635  * So to avoid a very convoluted logic of how to handle MDMSOFT, we simply
636  * perform a clear channel assessment here: We interpret channel activity
637  * as frame reception.
638  */
639 
640  if(cca_request() == CCA_STATE_BUSY) {
641  return 1;
642  }
643 
644  return 0;
645 
646 #endif
647 }
648 /*---------------------------------------------------------------------------*/
649 static int
650 pending_packet(void)
651 {
652  const data_entry_t *const read_entry = data_queue_current_entry();
653  volatile const data_entry_t *curr_entry = read_entry;
654 
655  int num_pending = 0;
656 
657  /* Go through RX Circular buffer and check their status */
658  do {
659  const uint8_t status = curr_entry->status;
660  if((status == DATA_ENTRY_FINISHED) ||
661  (status == DATA_ENTRY_BUSY)) {
662  num_pending += 1;
663  }
664 
665  /* Stop when we have looped the circular buffer */
666  curr_entry = (data_entry_t *)curr_entry->pNextEntry;
667  } while(curr_entry != read_entry);
668 
669  if(num_pending > 0 && !prop_radio.poll_mode) {
670  process_poll(&rf_sched_process);
671  }
672 
673  /* If we didn't find an entry at status finished, no frames are pending */
674  return num_pending;
675 }
676 /*---------------------------------------------------------------------------*/
677 static int
678 on(void)
679 {
680  rf_result_t res;
681 
682  if(prop_radio.rf_is_on) {
683  LOG_WARN("Radio is already on\n");
684  return RF_RESULT_OK;
685  }
686 
687  data_queue_reset();
688 
689  res = netstack_sched_rx(true);
690 
691  if(res != RF_RESULT_OK) {
692  return RF_RESULT_ERROR;
693  }
694 
695  prop_radio.rf_is_on = true;
696  return RF_RESULT_OK;
697 }
698 /*---------------------------------------------------------------------------*/
699 static int
700 off(void)
701 {
702  if(!prop_radio.rf_is_on) {
703  LOG_WARN("Radio is already off\n");
704  return RF_RESULT_OK;
705  }
706 
707  rf_yield();
708 
709  prop_radio.rf_is_on = false;
710  return RF_RESULT_OK;
711 }
712 /*---------------------------------------------------------------------------*/
713 static radio_result_t
714 get_value(radio_param_t param, radio_value_t *value)
715 {
716  rf_result_t res;
717 
718  if(!value) {
720  }
721 
722  switch(param) {
724  /* On / off */
725  *value = (prop_radio.rf_is_on)
728 
729  return RADIO_RESULT_OK;
730 
731  case RADIO_PARAM_CHANNEL:
732  *value = (radio_value_t)get_channel();
733  return RADIO_RESULT_OK;
734 
735  /* RX mode */
736  case RADIO_PARAM_RX_MODE:
737  *value = 0;
738  if(prop_radio.poll_mode) {
740  }
741  return RADIO_RESULT_OK;
742 
743  /* TX mode */
744  case RADIO_PARAM_TX_MODE:
745  *value = 0;
746  return RADIO_RESULT_OK;
747 
748  case RADIO_PARAM_TXPOWER:
749  res = rf_get_tx_power(prop_radio.rf_handle, rf_tx_power_table, (int8_t *)&value);
750  return ((res == RF_RESULT_OK) &&
751  (*value != RF_TxPowerTable_INVALID_DBM))
754 
756  *value = prop_radio.rssi_threshold;
757  return RADIO_RESULT_OK;
758 
759  case RADIO_PARAM_RSSI:
760  *value = get_rssi();
761  return (*value == RF_GET_RSSI_ERROR_VAL)
763  : RADIO_RESULT_OK;
764 
766  *value = prop_radio.last.rssi;
767  return RADIO_RESULT_OK;
768 
770  *value = prop_radio.last.corr_lqi;
771  return RADIO_RESULT_OK;
772 
774  *value = DOT_15_4G_CHAN_MIN;
775  return RADIO_RESULT_OK;
776 
778  *value = DOT_15_4G_CHAN_MAX;
779  return RADIO_RESULT_OK;
780 
782  *value = (radio_value_t)tx_power_min(rf_tx_power_table);
783  return RADIO_RESULT_OK;
784 
786  *value = (radio_value_t)tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
787  return RADIO_RESULT_OK;
788 
789  case RADIO_CONST_MAX_PAYLOAD_LEN:
790  *value = (radio_value_t)MAX_PAYLOAD_LEN;
791  return RADIO_RESULT_OK;
792 
793  default:
795  }
796 }
797 /*---------------------------------------------------------------------------*/
798 static radio_result_t
799 set_value(radio_param_t param, radio_value_t value)
800 {
801  rf_result_t res;
802 
803  switch(param) {
805 
806  if(value == RADIO_POWER_MODE_ON) {
807  return (on() == RF_RESULT_OK)
810  } else if(value == RADIO_POWER_MODE_OFF) {
811  off();
812  return RADIO_RESULT_OK;
813  }
814 
816 
817  case RADIO_PARAM_CHANNEL:
818  res = set_channel((uint16_t)value);
819  return (res == RF_RESULT_OK)
822 
823  case RADIO_PARAM_TXPOWER:
824  if(!tx_power_in_range((int8_t)value, rf_tx_power_table, rf_tx_power_table_size)) {
826  }
827  res = rf_set_tx_power(prop_radio.rf_handle, rf_tx_power_table, (int8_t)value);
828  return (res == RF_RESULT_OK)
831 
832  /* RX Mode */
833  case RADIO_PARAM_RX_MODE:
834  if(value & ~(RADIO_RX_MODE_POLL_MODE)) {
836  }
837 
838  const bool old_poll_mode = prop_radio.poll_mode;
839  prop_radio.poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
840  if(old_poll_mode == prop_radio.poll_mode) {
841  return RADIO_RESULT_OK;
842  }
843  if(!prop_radio.rf_is_on) {
844  return RADIO_RESULT_OK;
845  }
846 
847  netstack_stop_rx();
848  res = netstack_sched_rx(false);
849  return (res == RF_RESULT_OK)
852 
853  /* TX Mode */
854  case RADIO_PARAM_TX_MODE:
855  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
857  }
858  set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
859  return RADIO_RESULT_OK;
860 
862  prop_radio.rssi_threshold = (int8_t)value;
863  return RADIO_RESULT_OK;
864 
865  default:
867  }
868 }
869 /*---------------------------------------------------------------------------*/
870 static radio_result_t
871 get_object(radio_param_t param, void *dest, size_t size)
872 {
873  if(!dest) {
875  }
876 
877  switch(param) {
878  /* Last packet timestamp */
880  if(size != sizeof(rtimer_clock_t)) {
882  }
883 
884  *(rtimer_clock_t *)dest = prop_radio.last.timestamp;
885 
886  return RADIO_RESULT_OK;
887 
888  default:
890  }
891 }
892 /*---------------------------------------------------------------------------*/
893 static radio_result_t
894 set_object(radio_param_t param, const void *src, size_t size)
895 {
897 }
898 /*---------------------------------------------------------------------------*/
899 static int
900 init(void)
901 {
902  RF_Params rf_params;
903  RF_TxPowerTable_Value tx_power_value;
904  RF_Stat rf_stat;
905 
906  prop_radio.rx_is_active = rx_is_active;
907 
908  radio_mode = (simplelink_radio_mode_t *)&prop_radio;
909 
910  if(prop_radio.rf_handle) {
911  LOG_WARN("Radio is already initialized\n");
912  return RF_RESULT_OK;
913  }
914 
915  /* RX is off */
916  prop_radio.rf_is_on = false;
917 
918  /* Set configured RSSI threshold */
919  prop_radio.rssi_threshold = PROP_MODE_CCA_RSSI_THRESHOLD;
920 
921  init_rf_params();
922 
923  /* Init RF params and specify non-default params */
924  RF_Params_init(&rf_params);
925  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
926 
927  /* Open RF Driver */
928  prop_radio.rf_handle = netstack_open(&rf_params);
929 
930  if(prop_radio.rf_handle == NULL) {
931  LOG_ERR("Unable to open RF driver during initialization\n");
932  return RF_RESULT_ERROR;
933  }
934 
935  set_channel_force(IEEE802154_DEFAULT_CHANNEL);
936 
937  tx_power_value = RF_TxPowerTable_findValue(rf_tx_power_table, RF_TXPOWER_DBM);
938  if(tx_power_value.rawValue != RF_TxPowerTable_INVALID_VALUE) {
939  rf_stat = RF_setTxPower(prop_radio.rf_handle, tx_power_value);
940  if(rf_stat == RF_StatSuccess) {
941  LOG_INFO("TX power configured to %d dBm\n", RF_TXPOWER_DBM);
942  } else {
943  LOG_WARN("Setting TX power to %d dBm failed, stat=0x%02X", RF_TXPOWER_DBM, rf_stat);
944  }
945  } else {
946  LOG_WARN("Unable to find TX power %d dBm in the TX power table\n", RF_TXPOWER_DBM);
947  }
948 
949  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
950 
951  /* Start RAT overflow upkeep */
952  rat_init();
953 
954  /* Start RF process */
955  process_start(&rf_sched_process, NULL);
956 
957  return RF_RESULT_OK;
958 }
959 /*---------------------------------------------------------------------------*/
960 const struct radio_driver prop_mode_driver = {
961  init,
962  prepare,
963  transmit,
964  send,
965  read,
969  on,
970  off,
971  get_value,
972  set_value,
973  get_object,
974  set_object,
975 };
976 /*---------------------------------------------------------------------------*/
977 /**
978  * @}
979  * @}
980  */
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:762
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:572
Header file of TX power functionality of CC13xx/CC26xx.
The parameter is not supported.
Definition: radio.h:473
static uint8_t rf_is_on(void)
Checks whether the RFC domain is accessible and the RFC is in IEEE RX.
Definition: ieee-mode.c:267
#define FRAME_SHAVE
RSSI (1) + Timestamp (4) + Status (1)
Definition: prop-mode.c:169
Header file for the energy estimation mechanism
TX failed due to a collision.
Definition: radio.h:503
The maximum transmission power in dBm.
Definition: radio.h:318
Received signal strength indicator in dBm.
Definition: radio.h:218
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:676
Header file of the generic radio mode API.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:748
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver&#39;s buffers.
Definition: radio.h:689
The structure of a Contiki-NG radio device driver.
Definition: radio.h:526
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:175
Channel used for radio communication.
Definition: radio.h:134
The value argument was incorrect.
Definition: radio.h:474
The parameter was set/read successfully.
Definition: radio.h:472
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Definition: radio.h:664
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
An error occurred when getting/setting the parameter, but the arguments were otherwise correct...
Definition: radio.h:480
Header file of the CC13xx/CC26xx RAT timer handler.
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition: radio.h:180
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
The RSSI value of the last received packet.
Definition: radio.h:226
Clear channel assessment threshold in dBm.
Definition: radio.h:205
Header file of the CC13xx/CC26xx RF scheduler.
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:623
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:611
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
int(* off)(void)
Turn the radio off.
Definition: radio.h:721
#define RF_CONF_INACTIVITY_TIMEOUT
2 ms
The lowest radio channel number.
Definition: radio.h:303
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
Header file for the real-time timer module.
The highest radio channel number.
Definition: radio.h:308
Header file of the CC13xx/CC26xx RF data queue.
When getting the value of this parameter, the radio driver should indicate whether the radio is on or...
Definition: radio.h:119
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:466
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:547
Header file of RF settings for CC13xx/CC26xx.
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:453
Link quality indicator of the last received packet.
Definition: radio.h:236
The minimum transmission power in dBm.
Definition: radio.h:313
Radio powered on and able to receive frames.
Definition: radio.h:392
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:647
Transmission power in dBm.
Definition: radio.h:192
Header file of common CC13xx/CC26xx RF functionality.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:733
Default definitions of C compiler quirk work-arounds.
Last packet timestamp, of type rtimer_clock_t.
Definition: radio.h:278
An error occurred during transmission.
Definition: radio.h:498
Header file for the logging system
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:779
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:387
TX was successful and where an ACK was requested one was received.
Definition: radio.h:490
int(* on)(void)
Turn the radio on.
Definition: radio.h:703
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
static uint8_t get_channel()
Get the current operating channel.
Definition: cc2538-rf.c:165