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 /*---------------------------------------------------------------------------*/
63 /* Platform RF dev */
64 #include "rf/dot-15-4g.h"
65 #include "rf/sched.h"
66 #include "rf/data-queue.h"
67 #include "rf/tx-power.h"
68 #include "rf/settings.h"
69 /*---------------------------------------------------------------------------*/
70 #include <stdint.h>
71 #include <string.h>
72 #include <stdio.h>
73 #include <stdbool.h>
74 #include <assert.h>
75 /*---------------------------------------------------------------------------*/
76 /* Log configuration */
77 #include "sys/log.h"
78 #define LOG_MODULE "Radio"
79 #define LOG_LEVEL LOG_LEVEL_NONE
80 /*---------------------------------------------------------------------------*/
81 #undef CLAMP
82 #define CLAMP(v, vmin, vmax) (MAX(MIN(v, vmax), vmin))
83 /*---------------------------------------------------------------------------*/
84 /* Configuration parameters */
85 #define PROP_MODE_DYN_WHITENER PROP_MODE_CONF_DW
86 #define PROP_MODE_USE_CRC16 PROP_MODE_CONF_USE_CRC16
87 #define PROP_MODE_CENTER_FREQ PROP_MODE_CONF_CENTER_FREQ
88 #define PROP_MODE_LO_DIVIDER PROP_MODE_CONF_LO_DIVIDER
89 #define PROP_MODE_CCA_RSSI_THRESHOLD PROP_MODE_CONF_CCA_RSSI_THRESHOLD
90 /*---------------------------------------------------------------------------*/
91 /* Used for checking result of CCA_REQ command */
92 typedef enum {
93  CCA_STATE_IDLE = 0,
94  CCA_STATE_BUSY = 1,
95  CCA_STATE_INVALID = 2
96 } cca_state_t;
97 /*---------------------------------------------------------------------------*/
98 /* Defines and variables related to the .15.4g PHY HDR */
99 #define DOT_4G_MAX_FRAME_LEN 2047
100 #define DOT_4G_PHR_LEN 2
101 
102 /* PHY HDR bits */
103 #define DOT_4G_PHR_CRC16 0x10
104 #define DOT_4G_PHR_DW 0x08
105 
106 #if PROP_MODE_USE_CRC16
107 /* CRC16 */
108 #define DOT_4G_PHR_CRC_BIT DOT_4G_PHR_CRC16
109 #define CRC_LEN 2
110 #else
111 /* CRC32 */
112 #define DOT_4G_PHR_CRC_BIT 0
113 #define CRC_LEN 4
114 #endif /* PROP_MODE_USE_CRC16 */
115 
116 #if PROP_MODE_DYN_WHITENER
117 #define DOT_4G_PHR_DW_BIT DOT_4G_PHR_DW
118 #else
119 #define DOT_4G_PHR_DW_BIT 0
120 #endif
121 /*---------------------------------------------------------------------------*/
122 /* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */
123 #define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10)
124 
125 /* How long to wait for the rx read entry to become ready */
126 #define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250)
127 /*---------------------------------------------------------------------------*/
128 /* TX buf configuration */
129 #define TX_BUF_HDR_LEN 2
130 #define TX_BUF_PAYLOAD_LEN 180
131 
132 #define TX_BUF_SIZE (TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN)
133 /*---------------------------------------------------------------------------*/
134 /* Size of the Length field in Data Entry, two bytes in this case */
135 typedef uint16_t lensz_t;
136 
137 #define FRAME_OFFSET sizeof(lensz_t)
138 #define FRAME_SHAVE 2 /**< RSSI (1) + Status (1) */
139 /*---------------------------------------------------------------------------*/
140 /* Constants used when calculating the LQI from the RSSI */
141 #define RX_SENSITIVITY_DBM -110
142 #define RX_SATURATION_DBM 10
143 #define ED_MIN_DBM_ABOVE_RX_SENSITIVITY 10
144 #define ED_MAX 0xFF
145 
146 #define ED_RF_POWER_MIN_DBM (RX_SENSITIVITY_DBM + ED_MIN_DBM_ABOVE_RX_SENSITIVITY)
147 #define ED_RF_POWER_MAX_DBM RX_SATURATION_DBM
148 /*---------------------------------------------------------------------------*/
149 /* RF Core typedefs */
150 typedef rfc_propRxOutput_t rx_output_t;
151 
152 typedef struct {
153  /* Outgoing frame buffer */
154  uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
155 
156  /* RX Statistics struct */
157  rx_output_t rx_stats;
158 
159  /* RSSI Threshold */
160  int8_t rssi_threshold;
161  uint16_t channel;
162 
163  /* Indicates RF is supposed to be on or off */
164  uint8_t rf_is_on;
165 
166  /* RF driver */
167  RF_Handle rf_handle;
168 } prop_radio_t;
169 
170 static prop_radio_t prop_radio;
171 /*---------------------------------------------------------------------------*/
172 /* Convenience macros for volatile access with the RF commands */
173 #define cmd_radio_setup (*(volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t *)&rf_cmd_prop_radio_div_setup)
174 #define cmd_fs (*(volatile rfc_CMD_FS_t *) &rf_cmd_prop_fs)
175 #define cmd_tx (*(volatile rfc_CMD_PROP_TX_ADV_t *) &rf_cmd_prop_tx_adv)
176 #define cmd_rx (*(volatile rfc_CMD_PROP_RX_ADV_t *) &rf_cmd_prop_rx_adv)
177 /*---------------------------------------------------------------------------*/
178 static inline bool
179 tx_is_active(void)
180 {
181  return cmd_tx.status == ACTIVE;
182 }
183 /*---------------------------------------------------------------------------*/
184 static inline bool
185 rx_is_active(void)
186 {
187  return cmd_rx.status == ACTIVE;
188 }
189 /*---------------------------------------------------------------------------*/
190 static int on(void);
191 static int off(void);
192 /*---------------------------------------------------------------------------*/
193 static void
194 init_rf_params(void)
195 {
196  cmd_radio_setup.centerFreq = PROP_MODE_CENTER_FREQ;
197  cmd_radio_setup.loDivider = PROP_MODE_LO_DIVIDER;
198 
199  data_queue_t *data_queue = data_queue_init(sizeof(lensz_t));
200 
201  cmd_rx.maxPktLen = DOT_4G_MAX_FRAME_LEN - cmd_rx.lenOffset;
202  cmd_rx.pQueue = data_queue;
203  cmd_rx.pOutput = (uint8_t *)&prop_radio.rx_stats;
204 }
205 /*---------------------------------------------------------------------------*/
206 static int8_t
207 get_rssi(void)
208 {
209  rf_result_t res;
210 
211  const bool rx_is_idle = !rx_is_active();
212 
213  if(rx_is_idle) {
214  res = netstack_sched_rx(false);
215  if(res != RF_RESULT_OK) {
216  return RF_GET_RSSI_ERROR_VAL;
217  }
218  }
219 
220  const rtimer_clock_t t0 = RTIMER_NOW();
221  while((cmd_rx.status != ACTIVE) &&
222  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_ENTER_RX_WAIT)) ;
223 
224  int8_t rssi = RF_GET_RSSI_ERROR_VAL;
225  if(rx_is_active()) {
226  rssi = RF_getRssi(prop_radio.rf_handle);
227  }
228 
229  if(rx_is_idle) {
230  netstack_stop_rx();
231  }
232 
233  return rssi;
234 }
235 /*---------------------------------------------------------------------------*/
236 static uint8_t
237 get_channel(void)
238 {
239  uint32_t freq_khz = cmd_fs.frequency * 1000;
240 
241  /*
242  * For some channels, fractFreq * 1000 / 65536 will return 324.99xx.
243  * Casting the result to uint32_t will truncate decimals resulting in the
244  * function returning channel - 1 instead of channel. Thus, we do a quick
245  * positive integer round up.
246  */
247  freq_khz += (((cmd_fs.fractFreq * 1000) + 65535) / 65536);
248 
249  return (uint8_t)((freq_khz - DOT_15_4G_CHAN0_FREQ) / DOT_15_4G_FREQ_SPACING);
250 }
251 /*---------------------------------------------------------------------------*/
252 static rf_result_t
253 set_channel(uint16_t channel)
254 {
255  rf_result_t res;
256 
257  if(!dot_15_4g_chan_in_range(channel)) {
258  LOG_WARN("Supplied hannel %d is illegal, defaults to %d\n",
259  (int)channel, DOT_15_4G_DEFAULT_CHAN);
260  channel = DOT_15_4G_DEFAULT_CHAN;
261  }
262 
263  if(channel == prop_radio.channel) {
264  /* We are already calibrated to this channel */
265  return RF_RESULT_OK;
266  }
267 
268  const uint32_t new_freq = dot_15_4g_freq(channel);
269  const uint16_t freq = (uint16_t)(new_freq / 1000);
270  const uint16_t frac = (uint16_t)(((new_freq - (freq * 1000)) * 0x10000) / 1000);
271 
272  LOG_DBG("Set channel to %d, frequency 0x%04X.0x%04X (%lu)\n",
273  (int)channel, freq, frac, new_freq);
274 
275  cmd_fs.frequency = freq;
276  cmd_fs.fractFreq = frac;
277 
278  res = netstack_sched_fs();
279 
280  if(res != RF_RESULT_OK) {
281  return res;
282  }
283 
284  prop_radio.channel = channel;
285  return RF_RESULT_OK;
286 }
287 /*---------------------------------------------------------------------------*/
288 static uint8_t
289 calculate_lqi(int8_t rssi)
290 {
291  /*
292  * Note : Currently the LQI value is simply the energy detect measurement.
293  * A more accurate value could be derived by using the correlation
294  * value along with the RSSI value.
295  */
296  rssi = CLAMP(rssi, ED_RF_POWER_MIN_DBM, ED_RF_POWER_MAX_DBM);
297 
298  /*
299  * Create energy detect measurement by normalizing and scaling RF power level.
300  * Note : The division operation below is designed for maximum accuracy and
301  * best granularity. This is done by grouping the math operations to
302  * compute the entire numerator before doing any division.
303  */
304  return (ED_MAX * (rssi - ED_RF_POWER_MIN_DBM)) / (ED_RF_POWER_MAX_DBM - ED_RF_POWER_MIN_DBM);
305 }
306 /*---------------------------------------------------------------------------*/
307 static int
308 prepare(const void *payload, unsigned short payload_len)
309 {
310  const size_t len = MIN((size_t)payload_len,
311  (size_t)TX_BUF_PAYLOAD_LEN);
312 
313  memcpy(prop_radio.tx_buf + TX_BUF_HDR_LEN, payload, len);
314  return 0;
315 }
316 /*---------------------------------------------------------------------------*/
317 static int
318 transmit(unsigned short transmit_len)
319 {
320  rf_result_t res;
321 
322  if(tx_is_active()) {
323  LOG_ERR("A transmission is already active\n");
324  return RADIO_TX_ERR;
325  }
326 
327  /* Length in .15.4g PHY HDR. Includes the CRC but not the HDR itself */
328  const uint16_t total_length = transmit_len + CRC_LEN;
329  /*
330  * Prepare the .15.4g PHY header
331  * MS=0, Length MSBits=0, DW and CRC configurable
332  * Total length = transmit_len (payload) + CRC length
333  *
334  * The Radio will flip the bits around, so tx_buf[0] must have the length
335  * LSBs (PHR[15:8] and tx_buf[1] will have PHR[7:0]
336  */
337  prop_radio.tx_buf[0] = ((total_length >> 0) & 0xFF);
338  prop_radio.tx_buf[1] = ((total_length >> 8) & 0xFF) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT;
339 
340  /* pktLen: Total number of bytes in the TX buffer, including the header if
341  * one exists, but not including the CRC (which is not present in the buffer) */
342  cmd_tx.pktLen = transmit_len + DOT_4G_PHR_LEN;
343  cmd_tx.pPkt = prop_radio.tx_buf;
344 
345  res = netstack_sched_prop_tx();
346 
347  return (res == RF_RESULT_OK)
348  ? RADIO_TX_OK
349  : RADIO_TX_ERR;
350 }
351 /*---------------------------------------------------------------------------*/
352 static int
353 send(const void *payload, unsigned short payload_len)
354 {
355  prepare(payload, payload_len);
356  return transmit(payload_len);
357 }
358 /*---------------------------------------------------------------------------*/
359 static int
360 read(void *buf, unsigned short buf_len)
361 {
362  volatile data_entry_t *data_entry = data_queue_current_entry();
363 
364  const rtimer_clock_t t0 = RTIMER_NOW();
365  /* Only wait if the Radio is accessing the entry */
366  while((data_entry->status == DATA_ENTRY_BUSY) &&
367  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)) ;
368 
369  if(data_entry->status != DATA_ENTRY_FINISHED) {
370  /* No available data */
371  return -1;
372  }
373 
374  /*
375  * lensz bytes (2) in the data entry are the length of the received frame.
376  * Data frame is on the following format:
377  * Length (2) + Payload (N) + RSSI (1) + Status (1)
378  * Data frame DOES NOT contain the following:
379  * no Header/PHY bytes
380  * no appended Received CRC bytes
381  * no Timestamp bytes
382  * Visual representation of frame format:
383  *
384  * +---------+---------+--------+--------+
385  * | 2 bytes | N bytes | 1 byte | 1 byte |
386  * +---------+---------+--------+--------+
387  * | Length | Payload | RSSI | Status |
388  * +---------+---------+--------+--------+
389  *
390  * Length bytes equal total length of entire frame excluding itself,
391  * Length = N + RSSI (1) + Status (1)
392  * = N + 2
393  * N = Length - 2
394  */
395  uint8_t *const frame_ptr = (uint8_t *)&data_entry->data;
396  const lensz_t frame_len = *(lensz_t *)frame_ptr;
397 
398  /* Sanity check that Frame is at least Frame Shave bytes long */
399  if(frame_len < FRAME_SHAVE) {
400  LOG_ERR("Received rame is too short, len=%d\n", frame_len);
401 
402  data_queue_release_entry();
403  return 0;
404  }
405 
406  const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t);
407  const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE);
408 
409  /* Sanity check that Payload fits in Buffer */
410  if(payload_len > buf_len) {
411  LOG_ERR("Payload of received frame is too large for local buffer, len=%d buf_len=%d\n",
412  payload_len, buf_len);
413 
414  data_queue_release_entry();
415  return 0;
416  }
417 
418  memcpy(buf, payload_ptr, payload_len);
419 
420  /* RSSI stored after payload */
421  const int8_t rssi = (int8_t)payload_ptr[payload_len];
422  /* LQI calculated from RSSI */
423  const uint8_t lqi = calculate_lqi(rssi);
424 
425  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)rssi);
426  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)lqi);
427 
428  data_queue_release_entry();
429  return (int)payload_len;
430 }
431 /*---------------------------------------------------------------------------*/
432 static uint8_t
433 cca_request(void)
434 {
435  const int8_t rssi = get_rssi();
436 
437  if(rssi == RF_GET_RSSI_ERROR_VAL) {
438  return CCA_STATE_INVALID;
439  }
440 
441  return (rssi < prop_radio.rssi_threshold)
442  ? CCA_STATE_IDLE
443  : CCA_STATE_BUSY;
444 }
445 /*---------------------------------------------------------------------------*/
446 static int
447 channel_clear(void)
448 {
449  if(tx_is_active()) {
450  LOG_ERR("Channel clear called while in TX\n");
451  return 0;
452  }
453 
454  const uint8_t cca_state = cca_request();
455 
456  /* Channel is clear if CCA state is IDLE */
457  return cca_state == CCA_STATE_IDLE;
458 }
459 /*---------------------------------------------------------------------------*/
460 static int
461 receiving_packet(void)
462 {
463  if(!rx_is_active()) {
464  return 0;
465  }
466 
467  const uint8_t cca_state = cca_request();
468 
469  return cca_state == CCA_STATE_BUSY;
470 }
471 /*---------------------------------------------------------------------------*/
472 static int
473 pending_packet(void)
474 {
475  const data_entry_t *const read_entry = data_queue_current_entry();
476  volatile const data_entry_t *curr_entry = read_entry;
477 
478  int num_pending = 0;
479 
480  /* Go through RX Circular buffer and check their status */
481  do {
482  const uint8_t status = curr_entry->status;
483  if((status == DATA_ENTRY_FINISHED) ||
484  (status == DATA_ENTRY_BUSY)) {
485  num_pending += 1;
486  }
487 
488  /* Stop when we have looped the circular buffer */
489  curr_entry = (data_entry_t *)curr_entry->pNextEntry;
490  } while(curr_entry != read_entry);
491 
492  if(num_pending > 0) {
493  process_poll(&rf_sched_process);
494  }
495 
496  /* If we didn't find an entry at status finished, no frames are pending */
497  return num_pending;
498 }
499 /*---------------------------------------------------------------------------*/
500 static int
501 on(void)
502 {
503  rf_result_t res;
504 
505  if(prop_radio.rf_is_on) {
506  LOG_WARN("Radio is already on\n");
507  return RF_RESULT_OK;
508  }
509 
510  data_queue_reset();
511 
512  res = netstack_sched_rx(true);
513 
514  if(res != RF_RESULT_OK) {
515  return RF_RESULT_ERROR;
516  }
517 
518  prop_radio.rf_is_on = true;
519  return RF_RESULT_OK;
520 }
521 /*---------------------------------------------------------------------------*/
522 static int
523 off(void)
524 {
525  if(!prop_radio.rf_is_on) {
526  LOG_WARN("Radio is already off\n");
527  return RF_RESULT_OK;
528  }
529 
530  rf_yield();
531 
532  prop_radio.rf_is_on = false;
533  return RF_RESULT_OK;
534 }
535 /*---------------------------------------------------------------------------*/
536 static radio_result_t
537 get_value(radio_param_t param, radio_value_t *value)
538 {
539  rf_result_t res;
540 
541  if(!value) {
542  return RADIO_RESULT_INVALID_VALUE;
543  }
544 
545  switch(param) {
546  case RADIO_PARAM_POWER_MODE:
547  /* On / off */
548  *value = (prop_radio.rf_is_on)
549  ? RADIO_POWER_MODE_ON
550  : RADIO_POWER_MODE_OFF;
551 
552  return RADIO_RESULT_OK;
553 
554  case RADIO_PARAM_CHANNEL:
555  *value = (radio_value_t)get_channel();
556  return RADIO_RESULT_OK;
557 
558  case RADIO_PARAM_TXPOWER:
559  res = rf_get_tx_power(prop_radio.rf_handle, rf_tx_power_table, (int8_t *)&value);
560  return ((res == RF_RESULT_OK) &&
561  (*value != RF_TxPowerTable_INVALID_DBM))
562  ? RADIO_RESULT_OK
563  : RADIO_RESULT_ERROR;
564 
565  case RADIO_PARAM_CCA_THRESHOLD:
566  *value = prop_radio.rssi_threshold;
567  return RADIO_RESULT_OK;
568 
569  case RADIO_PARAM_RSSI:
570  *value = get_rssi();
571  return (*value == RF_GET_RSSI_ERROR_VAL)
572  ? RADIO_RESULT_ERROR
573  : RADIO_RESULT_OK;
574 
575  case RADIO_CONST_CHANNEL_MIN:
576  *value = DOT_15_4G_CHAN_MIN;
577  return RADIO_RESULT_OK;
578 
579  case RADIO_CONST_CHANNEL_MAX:
580  *value = DOT_15_4G_CHAN_MAX;
581  return RADIO_RESULT_OK;
582 
583  case RADIO_CONST_TXPOWER_MIN:
584  *value = (radio_value_t)tx_power_min(rf_tx_power_table);
585  return RADIO_RESULT_OK;
586 
587  case RADIO_CONST_TXPOWER_MAX:
588  *value = (radio_value_t)tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
589  return RADIO_RESULT_OK;
590 
591  default:
592  return RADIO_RESULT_NOT_SUPPORTED;
593  }
594 }
595 /*---------------------------------------------------------------------------*/
596 static radio_result_t
597 set_value(radio_param_t param, radio_value_t value)
598 {
599  rf_result_t res;
600 
601  switch(param) {
602  case RADIO_PARAM_POWER_MODE:
603 
604  if(value == RADIO_POWER_MODE_ON) {
605  return (on() == RF_RESULT_OK)
606  ? RADIO_RESULT_OK
607  : RADIO_RESULT_ERROR;
608  } else if(value == RADIO_POWER_MODE_OFF) {
609  off();
610  return RADIO_RESULT_OK;
611  }
612 
613  return RADIO_RESULT_INVALID_VALUE;
614 
615  case RADIO_PARAM_CHANNEL:
616  res = set_channel((uint16_t)value);
617  return (res == RF_RESULT_OK)
618  ? RADIO_RESULT_OK
619  : RADIO_RESULT_ERROR;
620 
621  case RADIO_PARAM_TXPOWER:
622  if(!tx_power_in_range((int8_t)value, rf_tx_power_table, rf_tx_power_table_size)) {
623  return RADIO_RESULT_INVALID_VALUE;
624  }
625  res = rf_set_tx_power(prop_radio.rf_handle, rf_tx_power_table, (int8_t)value);
626  return (res == RF_RESULT_OK)
627  ? RADIO_RESULT_OK
628  : RADIO_RESULT_ERROR;
629 
630  case RADIO_PARAM_RX_MODE:
631  return RADIO_RESULT_OK;
632 
633  case RADIO_PARAM_CCA_THRESHOLD:
634  prop_radio.rssi_threshold = (int8_t)value;
635  return RADIO_RESULT_OK;
636 
637  default:
638  return RADIO_RESULT_NOT_SUPPORTED;
639  }
640 }
641 /*---------------------------------------------------------------------------*/
642 static radio_result_t
643 get_object(radio_param_t param, void *dest, size_t size)
644 {
645  return RADIO_RESULT_NOT_SUPPORTED;
646 }
647 /*---------------------------------------------------------------------------*/
648 static radio_result_t
649 set_object(radio_param_t param, const void *src, size_t size)
650 {
651  return RADIO_RESULT_NOT_SUPPORTED;
652 }
653 /*---------------------------------------------------------------------------*/
654 static int
655 init(void)
656 {
657  if(prop_radio.rf_handle) {
658  LOG_WARN("Radio is already initialized\n");
659  return RF_RESULT_OK;
660  }
661 
662  /* RX is off */
663  prop_radio.rf_is_on = false;
664 
665  /* Set configured RSSI threshold */
666  prop_radio.rssi_threshold = PROP_MODE_CCA_RSSI_THRESHOLD;
667 
668  init_rf_params();
669 
670  /* Init RF params and specify non-default params */
671  RF_Params rf_params;
672  RF_Params_init(&rf_params);
673  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
674 
675  /* Open RF Driver */
676  prop_radio.rf_handle = netstack_open(&rf_params);
677 
678  if(prop_radio.rf_handle == NULL) {
679  LOG_ERR("Unable to open RF driver during initialization\n");
680  return RF_RESULT_ERROR;
681  }
682 
684 
685  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
686 
687  /* Start RF process */
688  process_start(&rf_sched_process, NULL);
689 
690  return RF_RESULT_OK;
691 }
692 /*---------------------------------------------------------------------------*/
693 const struct radio_driver prop_mode_driver = {
694  init,
695  prepare,
696  transmit,
697  send,
698  read,
702  on,
703  off,
704  get_value,
705  set_value,
706  get_object,
707  set_object,
708 };
709 /*---------------------------------------------------------------------------*/
710 /**
711  * @}
712  * @}
713  */
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:290
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:252
Header file of TX power functionality of CC13xx/CC26xx.
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
#define FRAME_SHAVE
RSSI (1) + Status (1)
Definition: prop-mode.c:138
Header file for the energy estimation mechanism
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
The structure of a device driver for a radio in Contiki.
Definition: radio.h:247
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:166
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
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
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:160
Header file of the CC13xx/CC26xx RF scheduler.
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:258
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
#define RF_CONF_INACTIVITY_TIMEOUT
2 ms
Header file for the real-time timer module.
Header file of the CC13xx/CC26xx RF data queue.
Header file of RF settings for CC13xx/CC26xx.
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:261
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:280
Default definitions of C compiler quirk work-arounds.
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:296
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
static uint8_t get_channel()
Get the current operating channel.
Definition: cc2538-rf.c:156