Contiki-NG
ieee-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-ieee IEEE-mode driver for CC13xx/CC26xx
35  *
36  * @{
37  *
38  * \file
39  * Implementation of the CC13xx/CC26xx IEEE-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/linkaddr.h"
47 #include "net/netstack.h"
48 #include "sys/energest.h"
49 #include "sys/clock.h"
50 #include "sys/rtimer.h"
51 #include "sys/ctimer.h"
52 #include "sys/cc.h"
53 /*---------------------------------------------------------------------------*/
54 /* RF driver and RF Core API */
55 #include <ti/devices/DeviceFamily.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_mailbox.h)
59 /*
60  * rf_ieee_cmd.h and rf_ieee_mailbox.h are included by RF settings because a
61  * discrepancy between CC13x0 and CC13x2 IEEE support. CC13x0 doesn't provide
62  * RFCore definitions of IEEE commands, and are therefore included locally
63  * from the Contiki build system. CC13x2 includes these normally from driverlib.
64  * This is taken care of RF settings.
65  */
66 
67 #include <ti/drivers/rf/RF.h>
68 /*---------------------------------------------------------------------------*/
69 /* SimpleLink Platform RF dev */
70 #include "rf/rf.h"
71 #include "rf/data-queue.h"
72 #include "rf/dot-15-4g.h"
73 #include "rf/sched.h"
74 #include "rf/settings.h"
75 #include "rf/tx-power.h"
76 /*---------------------------------------------------------------------------*/
77 #include <stdint.h>
78 #include <stddef.h>
79 #include <string.h>
80 #include <stdio.h>
81 #include <stdbool.h>
82 /*---------------------------------------------------------------------------*/
83 /* Log configuration */
84 #include "sys/log.h"
85 #define LOG_MODULE "Radio"
86 #define LOG_LEVEL LOG_LEVEL_NONE
87 /*---------------------------------------------------------------------------*/
88 /* Configuration parameters */
89 #define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK
90 #define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS
91 #define IEEE_MODE_CCA_RSSI_THRESHOLD IEEE_MODE_CONF_CCA_RSSI_THRESHOLD
92 /*---------------------------------------------------------------------------*/
93 /* Timeout constants */
94 
95 /* How long to wait for the rx read entry to become ready */
96 #define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250)
97 
98 /* How long to wait for RX to become active after scheduled */
99 #define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10)
100 /*---------------------------------------------------------------------------*/
101 #define RAT_RANGE (~(uint32_t)0)
102 #define RAT_ONE_QUARTER (RAT_RANGE / (uint32_t)4)
103 #define RAT_THREE_QUARTERS ((RAT_RANGE * (uint32_t)3) / (uint32_t)4)
104 
105 /* XXX: don't know what exactly is this, looks like the time to TX 3 octets */
106 #define RAT_TIMESTAMP_OFFSET -(USEC_TO_RAT(32 * 3) - 1) /* -95.75 usec */
107 /*---------------------------------------------------------------------------*/
108 #define STATUS_CORRELATION 0x3f /* bits 0-5 */
109 #define STATUS_REJECT_FRAME 0x40 /* bit 6 */
110 #define STATUS_CRC_FAIL 0x80 /* bit 7 */
111 /*---------------------------------------------------------------------------*/
112 #define FRAME_FCF_OFFSET 0
113 #define FRAME_SEQNUM_OFFSET 2
114 
115 #define FRAME_ACK_REQUEST 0x20 /* bit 5 */
116 
117 /* TX buf configuration */
118 #define TX_BUF_SIZE 180
119 /*---------------------------------------------------------------------------*/
120 /* Size of the Length representation in Data Entry, one byte in this case */
121 typedef uint8_t lensz_t;
122 
123 #define FRAME_OFFSET sizeof(lensz_t)
124 #define FRAME_SHAVE 8 /* FCS (2) + RSSI (1) + Status (1) + Timestamp (4) */
125 /*---------------------------------------------------------------------------*/
126 /* Used for checking result of CCA_REQ command */
127 typedef enum {
128  CCA_STATE_IDLE = 0,
129  CCA_STATE_BUSY = 1,
130  CCA_STATE_INVALID = 2
131 } cca_state_t;
132 /*---------------------------------------------------------------------------*/
133 /* RF Core typedefs */
134 typedef rfc_ieeeRxOutput_t rx_output_t;
135 typedef rfc_CMD_IEEE_MOD_FILT_t cmd_mod_filt_t;
136 typedef rfc_CMD_IEEE_CCA_REQ_t cmd_cca_req_t;
137 
138 typedef struct {
139  /* Outgoing frame buffer */
140  uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
141 
142  /* RF Statistics struct */
143  rx_output_t rx_stats;
144 
145  /* Indicates RF is supposed to be on or off */
146  bool rf_is_on;
147  /* Enable/disable CCA before sending */
148  bool send_on_cca;
149  /* Are we currently in poll mode? */
150  bool poll_mode;
151 
152  /* Last RX operation stats */
153  struct {
154  int8_t rssi;
155  uint8_t corr_lqi;
156  uint32_t timestamp;
157  } last;
158 
159  /* RAT Overflow Upkeep */
160  struct {
161  struct ctimer overflow_timer;
162  rtimer_clock_t last_overflow;
163  volatile uint32_t overflow_count;
164  } rat;
165 
166  /* RF driver */
167  RF_Handle rf_handle;
168 } ieee_radio_t;
169 
170 static ieee_radio_t ieee_radio;
171 
172 /* Global RF Core commands */
173 static cmd_mod_filt_t cmd_mod_filt;
174 /*---------------------------------------------------------------------------*/
175 /* RF Command volatile objects */
176 #define cmd_radio_setup (*(volatile rfc_CMD_RADIO_SETUP_t *)&rf_cmd_ieee_radio_setup)
177 #define cmd_fs (*(volatile rfc_CMD_FS_t *) &rf_cmd_ieee_fs)
178 #define cmd_tx (*(volatile rfc_CMD_IEEE_TX_t *) &rf_cmd_ieee_tx)
179 #define cmd_rx (*(volatile rfc_CMD_IEEE_RX_t *) &rf_cmd_ieee_rx)
180 #define cmd_rx_ack (*(volatile rfc_CMD_IEEE_RX_ACK_t *)&rf_cmd_ieee_rx_ack)
181 /*---------------------------------------------------------------------------*/
182 static inline bool
183 rx_is_active(void)
184 {
185  return cmd_rx.status == ACTIVE;
186 }
187 /*---------------------------------------------------------------------------*/
188 /* Forward declarations of local functions */
189 static void check_rat_overflow(void);
190 static uint32_t rat_to_timestamp(const uint32_t);
191 /*---------------------------------------------------------------------------*/
192 /* Forward declarations of Radio driver functions */
193 static int init(void);
194 static int prepare(const void *, unsigned short);
195 static int transmit(unsigned short);
196 static int send(const void *, unsigned short);
197 static int read(void *, unsigned short);
198 static int channel_clear(void);
199 static int receiving_packet(void);
200 static int pending_packet(void);
201 static int on(void);
202 static int off(void);
203 static radio_result_t get_value(radio_param_t, radio_value_t *);
204 static radio_result_t set_value(radio_param_t, radio_value_t);
205 static radio_result_t get_object(radio_param_t, void *, size_t);
206 static radio_result_t set_object(radio_param_t, const void *, size_t);
207 /*---------------------------------------------------------------------------*/
208 static void
209 rat_overflow_cb(void *arg)
210 {
211  check_rat_overflow();
212  /* Check next time after half of the RAT interval */
213  const clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND;
214  ctimer_set(&ieee_radio.rat.overflow_timer, two_quarters, rat_overflow_cb, NULL);
215 }
216 /*---------------------------------------------------------------------------*/
217 static void
218 init_rf_params(void)
219 {
220  data_queue_t *rx_q = data_queue_init(sizeof(lensz_t));
221 
222  cmd_rx.pRxQ = rx_q;
223  cmd_rx.pOutput = &ieee_radio.rx_stats;
224 
225 #if IEEE_MODE_PROMISCOUS
226  cmd_rx.frameFiltOpt.frameFiltEn = 0;
227 #else
228  cmd_rx.frameFiltOpt.frameFiltEn = 1;
229 #endif
230 
231 #if IEEE_MODE_AUTOACK
232  cmd_rx.frameFiltOpt.autoAckEn = 1;
233 #else
234  cmd_rx.frameFiltOpt.autoAckEn = 0;
235 #endif
236 
237  cmd_rx.ccaRssiThr = IEEE_MODE_CCA_RSSI_THRESHOLD;
238 
239  cmd_tx.pNextOp = (RF_Op *)&cmd_rx_ack;
240  cmd_tx.condition.rule = COND_NEVER; /* Initially ACK turned off */
241 
242  /*
243  * ACK packet is transmitted 192 us after the end of the received packet,
244  * takes 352 us for ACK transmission, total of 546 us of expected time to
245  * recieve ACK in ideal conditions. 700 us endTime for CMD_IEEE_RX_ACK
246  * should give some margins.
247  * The ACK frame consists of 6 bytes of SHR/PDR and 5 bytes of PSDU, total
248  * of 11 bytes. 11 bytes x 32 us/byte equals 352 us of ACK transmission time.
249  */
250  cmd_rx_ack.startTrigger.triggerType = TRIG_NOW;
251  cmd_rx_ack.endTrigger.triggerType = TRIG_REL_START;
252  cmd_rx_ack.endTime = RF_convertUsToRatTicks(700);
253 
254  /* Initialize address filter command */
255  cmd_mod_filt.commandNo = CMD_IEEE_MOD_FILT;
256  memcpy(&(cmd_mod_filt.newFrameFiltOpt), &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt));
257  memcpy(&(cmd_mod_filt.newFrameTypes), &(rf_cmd_ieee_rx.frameTypes), sizeof(rf_cmd_ieee_rx.frameTypes));
258 }
259 /*---------------------------------------------------------------------------*/
260 static rf_result_t
261 set_channel(uint8_t channel)
262 {
263  if(!dot_15_4g_chan_in_range(channel)) {
264  LOG_WARN("Supplied hannel %d is illegal, defaults to %d\n",
265  (int)channel, DOT_15_4G_DEFAULT_CHAN);
266  channel = DOT_15_4G_DEFAULT_CHAN;
267  }
268 
269  /*
270  * cmd_rx.channel is initialized to 0, causing any initial call to
271  * set_channel() to cause a synth calibration, since channel must be in
272  * range 11-26.
273  */
274  if(channel == cmd_rx.channel) {
275  /* We are already calibrated to this channel */
276  return true;
277  }
278 
279  cmd_rx.channel = channel;
280 
281  const uint32_t new_freq = dot_15_4g_freq(channel);
282  const uint16_t freq = (uint16_t)(new_freq / 1000);
283  const uint16_t frac = (uint16_t)(((new_freq - (freq * 1000)) * 0x10000) / 1000);
284 
285  LOG_DBG("Set channel to %d, frequency 0x%04X.0x%04X (%lu)\n",
286  (int)channel, freq, frac, new_freq);
287 
288  cmd_fs.frequency = freq;
289  cmd_fs.fractFreq = frac;
290 
291  return netstack_sched_fs();
292 }
293 /*---------------------------------------------------------------------------*/
294 static void
295 set_send_on_cca(bool enable)
296 {
297  ieee_radio.send_on_cca = enable;
298 }
299 /*---------------------------------------------------------------------------*/
300 static void
301 check_rat_overflow(void)
302 {
303  const bool was_off = !rx_is_active();
304 
305  if(was_off) {
306  RF_runDirectCmd(ieee_radio.rf_handle, CMD_NOP);
307  }
308 
309  const uint32_t current_value = RF_getCurrentTime();
310 
311  static bool initial_iteration = true;
312  static uint32_t last_value;
313 
314  if(initial_iteration) {
315  /* First time checking overflow will only store the current value */
316  initial_iteration = false;
317  } else {
318  /* Overflow happens in the last quarter of the RAT range */
319  if((current_value + RAT_ONE_QUARTER) < last_value) {
320  /* Overflow detected */
321  ieee_radio.rat.last_overflow = RTIMER_NOW();
322  ieee_radio.rat.overflow_count += 1;
323  }
324  }
325 
326  last_value = current_value;
327 
328  if(was_off) {
329  RF_yield(ieee_radio.rf_handle);
330  }
331 }
332 /*---------------------------------------------------------------------------*/
333 static uint32_t
334 rat_to_timestamp(const uint32_t rat_ticks)
335 {
336  check_rat_overflow();
337 
338  uint64_t adjusted_overflow_count = ieee_radio.rat.overflow_count;
339 
340  /* If the timestamp is in the 4th quarter and the last overflow was recently,
341  * assume that the timestamp refers to the time before the overflow */
342  if(rat_ticks > RAT_THREE_QUARTERS) {
343  const rtimer_clock_t one_quarter = (RAT_ONE_QUARTER * RTIMER_SECOND) / RAT_SECOND;
344  if(RTIMER_CLOCK_LT(RTIMER_NOW(), ieee_radio.rat.last_overflow + one_quarter)) {
345  adjusted_overflow_count -= 1;
346  }
347  }
348 
349  /* Add the overflowed time to the timestamp */
350  const uint64_t rat_ticks_adjusted = (uint64_t)rat_ticks + (uint64_t)RAT_RANGE * adjusted_overflow_count;
351 
352  /* Correct timestamp so that it refers to the end of the SFD and convert to RTIMER */
353  return RAT_TO_RTIMER(rat_ticks_adjusted + RAT_TIMESTAMP_OFFSET);
354 }
355 /*---------------------------------------------------------------------------*/
356 static int
357 init(void)
358 {
359  if(ieee_radio.rf_handle) {
360  LOG_WARN("Radio already initialized\n");
361  return RF_RESULT_OK;
362  }
363 
364  /* RX is off */
365  ieee_radio.rf_is_on = false;
366 
367  init_rf_params();
368 
369  /* Init RF params and specify non-default params */
370  RF_Params rf_params;
371  RF_Params_init(&rf_params);
372  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
373 
374  ieee_radio.rf_handle = netstack_open(&rf_params);
375 
376  if(ieee_radio.rf_handle == NULL) {
377  LOG_ERR("Unable to open RF driver\n");
378  return RF_RESULT_ERROR;
379  }
380 
381  set_channel(DOT_15_4G_DEFAULT_CHAN);
382 
383  int8_t max_tx_power = tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
384  rf_set_tx_power(ieee_radio.rf_handle, rf_tx_power_table, max_tx_power);
385 
386  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
387 
388  /* Start RAT overflow upkeep */
389  check_rat_overflow();
390  clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND;
391  ctimer_set(&ieee_radio.rat.overflow_timer, two_quarters, rat_overflow_cb, NULL);
392 
393  /* Start RF process */
394  process_start(&rf_sched_process, NULL);
395 
396  return RF_RESULT_OK;
397 }
398 /*---------------------------------------------------------------------------*/
399 static int
400 prepare(const void *payload, unsigned short payload_len)
401 {
402  const size_t len = MIN((size_t)payload_len,
403  (size_t)TX_BUF_SIZE);
404 
405  memcpy(ieee_radio.tx_buf, payload, len);
406  return 0;
407 }
408 /*---------------------------------------------------------------------------*/
409 static int
410 transmit(unsigned short transmit_len)
411 {
412  rf_result_t res;
413 
414  if(ieee_radio.send_on_cca && channel_clear() != 1) {
415  LOG_WARN("Channel is not clear for transmission\n");
416  return RADIO_TX_COLLISION;
417  }
418 
419  /*
420  * Are we expecting ACK? The ACK Request flag is in the first Frame
421  * Control Field byte, that is the first byte in the frame.
422  */
423  const bool ack_request = (bool)(ieee_radio.tx_buf[FRAME_FCF_OFFSET] & FRAME_ACK_REQUEST);
424  if(ack_request) {
425  /* Yes, turn on chaining */
426  cmd_tx.condition.rule = COND_STOP_ON_FALSE;
427 
428  /* Reset CMD_IEEE_RX_ACK command */
429  cmd_rx_ack.status = IDLE;
430  /* Sequence number is the third byte in the frame */
431  cmd_rx_ack.seqNo = ieee_radio.tx_buf[FRAME_SEQNUM_OFFSET];
432  } else {
433  /* No, turn off chaining */
434  cmd_tx.condition.rule = COND_NEVER;
435  }
436 
437  /* Configure TX command */
438  cmd_tx.payloadLen = (uint8_t)transmit_len;
439  cmd_tx.pPayload = ieee_radio.tx_buf;
440 
441  res = netstack_sched_ieee_tx(ack_request);
442 
443  if(res != RF_RESULT_OK) {
444  return RADIO_TX_ERR;
445  }
446 
447  if(ack_request) {
448  switch(cmd_rx_ack.status) {
449  /* CMD_IEEE_RX_ACK timed out, i.e. never received ACK */
450  case IEEE_DONE_TIMEOUT: return RADIO_TX_NOACK;
451  /* An ACK was received with either pending data bit set or cleared */
452  case IEEE_DONE_ACK: /* fallthrough */
453  case IEEE_DONE_ACKPEND: return RADIO_TX_OK;
454  /* Any other statuses are errors */
455  default: return RADIO_TX_ERR;
456  }
457  }
458 
459  /* No ACK expected, TX OK */
460  return RADIO_TX_OK;
461 }
462 /*---------------------------------------------------------------------------*/
463 static int
464 send(const void *payload, unsigned short payload_len)
465 {
466  prepare(payload, payload_len);
467  return transmit(payload_len);
468 }
469 /*---------------------------------------------------------------------------*/
470 static int
471 read(void *buf, unsigned short buf_len)
472 {
473  volatile data_entry_t *data_entry = data_queue_current_entry();
474 
475  const rtimer_clock_t t0 = RTIMER_NOW();
476  /* Only wait if the Radio timer is accessing the entry */
477  while((data_entry->status == DATA_ENTRY_BUSY) &&
478  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)) ;
479 
480  if(data_entry->status != DATA_ENTRY_FINISHED) {
481  /* No available data */
482  return -1;
483  }
484 
485  /*
486  * lensz bytes (1) in the data entry are the length of the received frame.
487  * Data frame is on the following format:
488  * Length (1) + Payload (N) + FCS (2) + RSSI (1) + Status (1) + Timestamp (4)
489  * Data frame DOES NOT contain the following:
490  * no PHY Header bytes
491  * no Source Index bytes
492  * Visual representation of frame format:
493  *
494  * +--------+---------+---------+--------+--------+-----------+
495  * | 1 byte | N bytes | 2 bytes | 1 byte | 1 byte | 4 bytes |
496  * +--------+---------+---------+--------+--------+-----------+
497  * | Length | Payload | FCS | RSSI | Status | Timestamp |
498  * +--------+---------+---------+--------+--------+-----------+
499  *
500  * Length bytes equal total length of entire frame excluding itself,
501  * Length = N + FCS (2) + RSSI (1) + Status (1) + Timestamp (4)
502  * Length = N + 8
503  * N = Length - 8
504  */
505  uint8_t *const frame_ptr = (uint8_t *)&data_entry->data;
506  const lensz_t frame_len = *(lensz_t *)frame_ptr;
507 
508  /* Sanity check that Frame is at least Frame Shave bytes long */
509  if(frame_len < FRAME_SHAVE) {
510  LOG_ERR("Received frame too short, len=%d\n", frame_len);
511 
512  data_queue_release_entry();
513  return 0;
514  }
515 
516  const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t);
517  const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE);
518 
519  /* Sanity check that Payload fits in buffer. */
520  if(payload_len > buf_len) {
521  LOG_ERR("MAC payload too large for buffer, len=%d buf_len=%d\n",
522  payload_len, buf_len);
523 
524  data_queue_release_entry();
525  return 0;
526  }
527 
528  memcpy(buf, payload_ptr, payload_len);
529 
530  /* RSSI stored FCS (2) bytes after payload. */
531  ieee_radio.last.rssi = (int8_t)payload_ptr[payload_len + 2];
532  /* LQI retrieved from Status byte, FCS (2) + RSSI (1) bytes after payload. */
533  ieee_radio.last.corr_lqi = (uint8_t)(payload_ptr[payload_len + 3] & STATUS_CORRELATION);
534  /* Timestamp stored FCS (2) + RSSI (1) + Status (1) bytes after payload. */
535  const uint32_t rat_ticks = *(uint32_t *)(payload_ptr + payload_len + 4);
536  ieee_radio.last.timestamp = rat_to_timestamp(rat_ticks);
537 
538  if(!ieee_radio.poll_mode) {
539  /* Not in poll mode: packetbuf should not be accessed in interrupt context. */
540  /* In poll mode, the last packet RSSI and link quality can be obtained through */
541  /* RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
542  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)ieee_radio.last.rssi);
543  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)ieee_radio.last.corr_lqi);
544  }
545 
546  data_queue_release_entry();
547  return (int)payload_len;
548 }
549 /*---------------------------------------------------------------------------*/
550 static rf_result_t
551 cca_request(cmd_cca_req_t *cmd_cca_req)
552 {
553  rf_result_t res;
554 
555  const bool rx_is_idle = !rx_is_active();
556 
557  if(rx_is_idle) {
558  res = netstack_sched_rx(false);
559  if(res != RF_RESULT_OK) {
560  return RF_RESULT_ERROR;
561  }
562  }
563 
564  const rtimer_clock_t t0 = RTIMER_NOW();
565  while((cmd_rx.status != ACTIVE) &&
566  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_ENTER_RX_WAIT)) ;
567 
568  RF_Stat stat = RF_StatRadioInactiveError;
569  if(rx_is_active()) {
570  stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)&cmd_cca_req);
571  }
572 
573  if(rx_is_idle) {
574  netstack_stop_rx();
575  }
576 
577  if(stat != RF_StatCmdDoneSuccess) {
578  LOG_ERR("CCA request failed, stat=0x%02X\n", stat);
579  return RF_RESULT_ERROR;
580  }
581 
582  return RF_RESULT_OK;
583 }
584 /*---------------------------------------------------------------------------*/
585 static int
586 channel_clear(void)
587 {
588  cmd_cca_req_t cmd_cca_req;
589  memset(&cmd_cca_req, 0x0, sizeof(cmd_cca_req_t));
590  cmd_cca_req.commandNo = CMD_IEEE_CCA_REQ;
591 
592  if(cca_request(&cmd_cca_req) != RF_RESULT_OK) {
593  return 0;
594  }
595 
596  /* Channel is clear if CCA state is IDLE */
597  return cmd_cca_req.ccaInfo.ccaState == CCA_STATE_IDLE;
598 }
599 /*---------------------------------------------------------------------------*/
600 static int
601 receiving_packet(void)
602 {
603  cmd_cca_req_t cmd_cca_req;
604  memset(&cmd_cca_req, 0x0, sizeof(cmd_cca_req_t));
605  cmd_cca_req.commandNo = CMD_IEEE_CCA_REQ;
606 
607  if(cca_request(&cmd_cca_req) != RF_RESULT_OK) {
608  return 0;
609  }
610 
611  /* If we are transmitting (can only be an ACK here), we are not receiving */
612  if((cmd_cca_req.ccaInfo.ccaEnergy == CCA_STATE_BUSY) &&
613  (cmd_cca_req.ccaInfo.ccaCorr == CCA_STATE_BUSY) &&
614  (cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY)) {
615  LOG_WARN("We are TXing ACK, therefore not receiving packets\n");
616  return 0;
617  }
618 
619  /* We are receiving a packet if a CCA sync has been seen, i.e. ccaSync is busy (1) */
620  return cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY;
621 }
622 /*---------------------------------------------------------------------------*/
623 static int
624 pending_packet(void)
625 {
626  const data_entry_t *const read_entry = data_queue_current_entry();
627  volatile const data_entry_t *curr_entry = read_entry;
628 
629  int num_pending = 0;
630 
631  /* Go through RX Circular buffer and check each data entry status */
632  do {
633  const uint8_t status = curr_entry->status;
634  if((status == DATA_ENTRY_FINISHED) ||
635  (status == DATA_ENTRY_BUSY)) {
636  num_pending += 1;
637  }
638 
639  /* Stop when we have looped the circular buffer */
640  curr_entry = (data_entry_t *)curr_entry->pNextEntry;
641  } while(curr_entry != read_entry);
642 
643  if((num_pending > 0) && !ieee_radio.poll_mode) {
644  process_poll(&rf_sched_process);
645  }
646 
647  /* If we didn't find an entry at status finished or busy, no frames are pending */
648  return num_pending;
649 }
650 /*---------------------------------------------------------------------------*/
651 static int
652 on(void)
653 {
654  rf_result_t res;
655 
656  if(ieee_radio.rf_is_on) {
657  LOG_WARN("Radio is already on\n");
658  return RF_RESULT_OK;
659  }
660 
661  data_queue_reset();
662 
663  res = netstack_sched_rx(true);
664 
665  if(res != RF_RESULT_OK) {
666  return RF_RESULT_ERROR;
667  }
668 
669  ieee_radio.rf_is_on = true;
670  return RF_RESULT_OK;
671 }
672 /*---------------------------------------------------------------------------*/
673 static int
674 off(void)
675 {
676  if(!ieee_radio.rf_is_on) {
677  LOG_WARN("Radio is already off\n");
678  return RF_RESULT_OK;
679  }
680 
681  rf_yield();
682 
683  ieee_radio.rf_is_on = false;
684  return RF_RESULT_OK;
685 }
686 /*---------------------------------------------------------------------------*/
687 static radio_result_t
688 get_value(radio_param_t param, radio_value_t *value)
689 {
690  rf_result_t res;
691 
692  if(!value) {
693  return RADIO_RESULT_INVALID_VALUE;
694  }
695 
696  switch(param) {
697 
698  /* Power Mode */
699  case RADIO_PARAM_POWER_MODE:
700  *value = (ieee_radio.rf_is_on)
701  ? RADIO_POWER_MODE_ON
702  : RADIO_POWER_MODE_OFF;
703  return RADIO_RESULT_OK;
704 
705  /* Channel */
706  case RADIO_PARAM_CHANNEL:
707  *value = (radio_value_t)cmd_rx.channel;
708  return RADIO_RESULT_OK;
709 
710  /* PAN ID */
711  case RADIO_PARAM_PAN_ID:
712  *value = (radio_value_t)cmd_rx.localPanID;
713  return RADIO_RESULT_OK;
714 
715  /* 16-bit address */
716  case RADIO_PARAM_16BIT_ADDR:
717  *value = (radio_value_t)cmd_rx.localShortAddr;
718  return RADIO_RESULT_OK;
719 
720  /* RX mode */
721  case RADIO_PARAM_RX_MODE:
722  *value = 0;
723  if(cmd_rx.frameFiltOpt.frameFiltEn) {
725  }
726  if(cmd_rx.frameFiltOpt.autoAckEn) {
727  *value |= (radio_value_t)RADIO_RX_MODE_AUTOACK;
728  }
729  if(ieee_radio.poll_mode) {
730  *value |= (radio_value_t)RADIO_RX_MODE_POLL_MODE;
731  }
732  return RADIO_RESULT_OK;
733 
734  /* TX mode */
735  case RADIO_PARAM_TX_MODE:
736  *value = 0;
737  return RADIO_RESULT_OK;
738 
739  /* TX power */
740  case RADIO_PARAM_TXPOWER:
741  res = rf_get_tx_power(ieee_radio.rf_handle, rf_tx_power_table, (int8_t *)&value);
742  return ((res == RF_RESULT_OK) &&
743  (*value != RF_TxPowerTable_INVALID_DBM))
744  ? RADIO_RESULT_OK
745  : RADIO_RESULT_ERROR;
746 
747  /* CCA threshold */
748  case RADIO_PARAM_CCA_THRESHOLD:
749  *value = cmd_rx.ccaRssiThr;
750  return RADIO_RESULT_OK;
751 
752  /* RSSI */
753  case RADIO_PARAM_RSSI:
754  *value = RF_getRssi(ieee_radio.rf_handle);
755  return (*value == RF_GET_RSSI_ERROR_VAL)
756  ? RADIO_RESULT_ERROR
757  : RADIO_RESULT_OK;
758 
759  /* Channel min */
760  case RADIO_CONST_CHANNEL_MIN:
761  *value = (radio_value_t)DOT_15_4G_CHAN_MIN;
762  return RADIO_RESULT_OK;
763 
764  /* Channel max */
765  case RADIO_CONST_CHANNEL_MAX:
766  *value = (radio_value_t)DOT_15_4G_CHAN_MAX;
767  return RADIO_RESULT_OK;
768 
769  case RADIO_CONST_TXPOWER_MIN:
770  *value = (radio_value_t)tx_power_min(rf_tx_power_table);
771  return RADIO_RESULT_OK;
772 
773  /* TX power max */
774  case RADIO_CONST_TXPOWER_MAX:
775  *value = (radio_value_t)tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
776  return RADIO_RESULT_OK;
777 
778  /* Last RSSI */
779  case RADIO_PARAM_LAST_RSSI:
780  *value = (radio_value_t)ieee_radio.last.rssi;
781  return RADIO_RESULT_OK;
782 
783  /* Last link quality */
784  case RADIO_PARAM_LAST_LINK_QUALITY:
785  *value = (radio_value_t)ieee_radio.last.corr_lqi;
786  return RADIO_RESULT_OK;
787 
788  default:
789  return RADIO_RESULT_NOT_SUPPORTED;
790  }
791 }
792 /*---------------------------------------------------------------------------*/
793 static radio_result_t
794 set_value(radio_param_t param, radio_value_t value)
795 {
796  rf_result_t res;
797 
798  switch(param) {
799 
800  /* Power Mode */
801  case RADIO_PARAM_POWER_MODE:
802 
803  if(value == RADIO_POWER_MODE_ON) {
804  return (on() == RF_RESULT_OK)
805  ? RADIO_RESULT_OK
806  : RADIO_RESULT_ERROR;
807  } else if(value == RADIO_POWER_MODE_OFF) {
808  off();
809  return RADIO_RESULT_OK;
810  }
811 
812  return RADIO_RESULT_INVALID_VALUE;
813 
814  /* Channel */
815  case RADIO_PARAM_CHANNEL:
816  if(!dot_15_4g_chan_in_range(value)) {
817  return RADIO_RESULT_INVALID_VALUE;
818  }
819  set_channel((uint8_t)value);
820  return RADIO_RESULT_OK;
821 
822  /* PAN ID */
823  case RADIO_PARAM_PAN_ID:
824  cmd_rx.localPanID = (uint16_t)value;
825  if(!ieee_radio.rf_is_on) {
826  return RADIO_RESULT_OK;
827  }
828 
829  netstack_stop_rx();
830  res = netstack_sched_rx(false);
831  return (res == RF_RESULT_OK)
832  ? RADIO_RESULT_OK
833  : RADIO_RESULT_ERROR;
834 
835  /* 16bit address */
836  case RADIO_PARAM_16BIT_ADDR:
837  cmd_rx.localShortAddr = (uint16_t)value;
838  if(!ieee_radio.rf_is_on) {
839  return RADIO_RESULT_OK;
840  }
841 
842  netstack_stop_rx();
843  res = netstack_sched_rx(false);
844  return (res == RF_RESULT_OK)
845  ? RADIO_RESULT_OK
846  : RADIO_RESULT_ERROR;
847 
848  /* RX Mode */
849  case RADIO_PARAM_RX_MODE: {
850  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
851  RADIO_RX_MODE_AUTOACK |
852  RADIO_RX_MODE_POLL_MODE)) {
853  return RADIO_RESULT_INVALID_VALUE;
854  }
855 
856  cmd_rx.frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
857  cmd_rx.frameFiltOpt.frameFiltStop = 1;
858  cmd_rx.frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
859  cmd_rx.frameFiltOpt.slottedAckEn = 0;
860  cmd_rx.frameFiltOpt.autoPendEn = 0;
861  cmd_rx.frameFiltOpt.defaultPend = 0;
862  cmd_rx.frameFiltOpt.bPendDataReqOnly = 0;
863  cmd_rx.frameFiltOpt.bPanCoord = 0;
864  cmd_rx.frameFiltOpt.bStrictLenFilter = 0;
865 
866  const bool old_poll_mode = ieee_radio.poll_mode;
867  ieee_radio.poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
868  if(old_poll_mode == ieee_radio.poll_mode) {
869  /* Do not turn the radio off and on, just send an update command */
870  memcpy(&cmd_mod_filt.newFrameFiltOpt, &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt));
871  const RF_Stat stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)&cmd_mod_filt);
872  if(stat != RF_StatCmdDoneSuccess) {
873  LOG_ERR("Setting address filter failed, stat=0x%02X\n", stat);
874  return RADIO_RESULT_ERROR;
875  }
876  return RADIO_RESULT_OK;
877  }
878  if(!ieee_radio.rf_is_on) {
879  return RADIO_RESULT_OK;
880  }
881 
882  netstack_stop_rx();
883  res = netstack_sched_rx(false);
884  return (res == RF_RESULT_OK)
885  ? RADIO_RESULT_OK
886  : RADIO_RESULT_ERROR;
887  }
888 
889  /* TX Mode */
890  case RADIO_PARAM_TX_MODE:
891  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
892  return RADIO_RESULT_INVALID_VALUE;
893  }
894  set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
895  return RADIO_RESULT_OK;
896 
897  /* TX Power */
898  case RADIO_PARAM_TXPOWER:
899  if(!tx_power_in_range((int8_t)value, rf_tx_power_table, rf_tx_power_table_size)) {
900  return RADIO_RESULT_INVALID_VALUE;
901  }
902  res = rf_set_tx_power(ieee_radio.rf_handle, rf_tx_power_table, (int8_t)value);
903  return (res == RF_RESULT_OK)
904  ? RADIO_RESULT_OK
905  : RADIO_RESULT_ERROR;
906 
907  /* CCA Threshold */
908  case RADIO_PARAM_CCA_THRESHOLD:
909  cmd_rx.ccaRssiThr = (int8_t)value;
910  if(!ieee_radio.rf_is_on) {
911  return RADIO_RESULT_OK;
912  }
913 
914  netstack_stop_rx();
915  res = netstack_sched_rx(false);
916  return (res == RF_RESULT_OK)
917  ? RADIO_RESULT_OK
918  : RADIO_RESULT_ERROR;
919 
920  default:
921  return RADIO_RESULT_NOT_SUPPORTED;
922  }
923 }
924 /*---------------------------------------------------------------------------*/
925 static radio_result_t
926 get_object(radio_param_t param, void *dest, size_t size)
927 {
928  if(!dest) {
929  return RADIO_RESULT_INVALID_VALUE;
930  }
931 
932  switch(param) {
933  /* 64bit address */
934  case RADIO_PARAM_64BIT_ADDR: {
935  const size_t srcSize = sizeof(cmd_rx.localExtAddr);
936  if(size != srcSize) {
937  return RADIO_RESULT_INVALID_VALUE;
938  }
939 
940  const uint8_t *pSrc = (uint8_t *)&(cmd_rx.localExtAddr);
941  uint8_t *pDest = dest;
942  for(size_t i = 0; i < srcSize; ++i) {
943  pDest[i] = pSrc[srcSize - 1 - i];
944  }
945 
946  return RADIO_RESULT_OK;
947  }
948  /* Last packet timestamp */
949  case RADIO_PARAM_LAST_PACKET_TIMESTAMP:
950  if(size != sizeof(rtimer_clock_t)) {
951  return RADIO_RESULT_INVALID_VALUE;
952  }
953 
954  *(rtimer_clock_t *)dest = ieee_radio.last.timestamp;
955 
956  return RADIO_RESULT_OK;
957 
958  default:
959  return RADIO_RESULT_NOT_SUPPORTED;
960  }
961 }
962 /*---------------------------------------------------------------------------*/
963 static radio_result_t
964 set_object(radio_param_t param, const void *src, size_t size)
965 {
966  rf_result_t res;
967 
968  if(!src) {
969  return RADIO_RESULT_INVALID_VALUE;
970  }
971 
972  switch(param) {
973  /* 64-bit address */
974  case RADIO_PARAM_64BIT_ADDR: {
975  const size_t destSize = sizeof(cmd_rx.localExtAddr);
976  if(size != destSize) {
977  return RADIO_RESULT_INVALID_VALUE;
978  }
979 
980  const uint8_t *pSrc = (const uint8_t *)src;
981  volatile uint8_t *pDest = (uint8_t *)&(cmd_rx.localExtAddr);
982  for(size_t i = 0; i < destSize; ++i) {
983  pDest[i] = pSrc[destSize - 1 - i];
984  }
985 
986  if(!rx_is_active()) {
987  return RADIO_RESULT_OK;
988  }
989 
990  netstack_stop_rx();
991  res = netstack_sched_rx(false);
992  return (res == RF_RESULT_OK)
993  ? RADIO_RESULT_OK
994  : RADIO_RESULT_ERROR;
995  }
996  default:
997  return RADIO_RESULT_NOT_SUPPORTED;
998  }
999 }
1000 /*---------------------------------------------------------------------------*/
1001 const struct radio_driver ieee_mode_driver = {
1002  init,
1003  prepare,
1004  transmit,
1005  send,
1006  read,
1007  channel_clear,
1010  on,
1011  off,
1012  get_value,
1013  set_value,
1014  get_object,
1015  set_object,
1016 };
1017 /*---------------------------------------------------------------------------*/
1018 /**
1019  * @}
1020  * @}
1021  */
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
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
Definition: ieee-mode.c:478
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
Header file for the link-layer address representation
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 RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:160
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
Header file of the CC13xx/CC26xx RF scheduler.
Header file for the callback timer
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.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:214
Header file of the CC13xx/CC26xx RF data queue.
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
Definition: radio.h:226
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 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: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