Contiki-NG
micromac-radio.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, NXP and SICS Swedish ICT.
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 Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Contiki driver for NXP JN516X using MMAC interface
36  * \authors
37  * Beshr Al Nahas <beshr@sics.se>
38  * Simon Duquennot <simonduq@sics.se>
39  * Atis Elsts <atis.elsts@sics.se>
40  *
41  */
42 
43 #include <string.h>
44 #include "contiki.h"
45 #include "dev/leds.h"
46 #include "sys/rtimer.h"
47 #include "sys/energest.h"
48 #include "net/packetbuf.h"
49 #include "net/netstack.h"
51 #include "lib/crc16.h"
52 #include "lib/ringbufindex.h"
53 
54 #include "AppHardwareApi.h"
55 #include "MMAC.h"
56 #include "micromac-radio.h"
57 #include "JPT.h"
58 #include "PeripheralRegs.h"
59 
60 /* This driver configures the radio in PHY mode and does address decoding
61  * and acknowledging in software. */
62 
63 #define DEBUG DEBUG_NONE
64 #include "net/ipv6/uip-debug.h"
65 
66 #ifdef MICROMAC_CONF_RADIO_MAC
67 #define MICROMAC_RADIO_MAC MICROMAC_CONF_RADIO_MAC
68 #else
69 #define MICROMAC_RADIO_MAC 0
70 #endif
71 
72 #if MICROMAC_RADIO_MAC
73 #define MICROMAC_FRAME tsMacFrame
74 #else
75 #define MICROMAC_FRAME tsPhyFrame
76 #endif
77 
78 /* Perform CRC check for received packets in SW,
79  * since we use PHY mode which does not calculate CRC in HW */
80 #define CRC_SW 1
81 
82 #define CHECKSUM_LEN 2
83 
84 /*
85  * The maximum number of bytes this driver can accept from the MAC layer for
86  * transmission or will deliver to the MAC layer after reception. Includes
87  * the MAC header and payload, but not the FCS.
88  */
89 #define MAX_PAYLOAD_LEN (127 - CHECKSUM_LEN)
90 
91 /* Max packet duration: 5 + 127 + 2 bytes, 32us per byte */
92 #define MAX_PACKET_DURATION US_TO_RTIMERTICKS((127 + 2) * 32 + RADIO_DELAY_BEFORE_TX)
93 /* Max ACK duration: 5 + 3 + 2 bytes */
94 #define MAX_ACK_DURATION US_TO_RTIMERTICKS((3 + 2) * 32 + RADIO_DELAY_BEFORE_TX)
95 
96 /* Test-mode pins output on dev-kit */
97 #define RADIO_TEST_MODE_HIGH_PWR 1
98 #define RADIO_TEST_MODE_ADVANCED 2
99 #define RADIO_TEST_MODE_DISABLED 0
100 
101 #ifndef RADIO_TEST_MODE
102 #define RADIO_TEST_MODE RADIO_TEST_MODE_DISABLED
103 #endif /* RADIO_TEST_MODE */
104 
105 /* The number of input buffers */
106 #ifndef MIRCOMAC_CONF_BUF_NUM
107 #define MIRCOMAC_CONF_BUF_NUM 2
108 #endif /* MIRCOMAC_CONF_BUF_NUM */
109 
110 /* Default energy level threshold for clear channel detection */
111 #ifndef MICROMAC_CONF_CCA_THR
112 #define MICROMAC_CONF_CCA_THR 39 /* approximately -85 dBm */
113 #endif /* MICROMAC_CONF_CCA_THR */
114 
115 #if (JENNIC_CHIP == JN5169)
116 #define OUTPUT_POWER_MAX 10
117 #define OUTPUT_POWER_MIN (-32)
118 #define ABS_OUTPUT_POWER_MIN (32)
119 #else
120 #define OUTPUT_POWER_MAX 0
121 #define OUTPUT_POWER_MIN (-32)
122 #endif
123 
124 /* Default Tx power [dBm] (between OUTPUT_POWER_MIN and OUTPUT_POWER_MAX) */
125 #ifndef MICROMAC_CONF_TX_POWER
126 #define MICROMAC_CONF_TX_POWER 0
127 #endif
128 
129 /* Autoack */
130 #ifndef MICROMAC_CONF_AUTOACK
131 #define MICROMAC_CONF_AUTOACK 1
132 #endif /* MICROMAC_CONF_AUTOACK */
133 
134 /* Set radio always on for now because this is what Contiki MAC layers
135  * expect. */
136 #ifndef MICROMAC_CONF_ALWAYS_ON
137 #define MICROMAC_CONF_ALWAYS_ON 1
138 #endif /* MICROMAC_CONF_ALWAYS_ON */
139 
140 /* Local variables */
141 static volatile signed char radio_last_rssi;
142 static volatile uint8_t radio_last_correlation; /* LQI */
143 
144 /* Did we miss a request to turn the radio on due to overflow? */
145 static volatile uint8_t missed_radio_on_request = 0;
146 
147 /* Poll mode disabled by default */
148 static uint8_t poll_mode = 0;
149 /* (Software) frame filtering enabled by default */
150 static uint8_t frame_filtering = 1;
151 /* (Software) autoack */
152 static uint8_t autoack_enabled = MICROMAC_CONF_AUTOACK;
153 /* CCA before sending? Disabled by default. */
154 static uint8_t send_on_cca = 0;
155 
156 /* Current radio channel */
157 static int current_channel = IEEE802154_DEFAULT_CHANNEL;
158 
159 /* Current set point tx power
160  Actual tx power may be different. Use get_txpower() for actual power */
161 static int current_tx_power = MICROMAC_CONF_TX_POWER;
162 
163 /* an integer between 0 and 255, used only with cca() */
164 static uint8_t cca_thershold = MICROMAC_CONF_CCA_THR;
165 
166 /* Tx in progress? */
167 static volatile uint8_t tx_in_progress = 0;
168 /* Are we currently listening? */
169 static volatile uint8_t listen_on = 0;
170 
171 /* Is the driver currently transmitting a software ACK? */
172 static uint8_t in_ack_transmission = 0;
173 
174 /* TX frame buffer */
175 static MICROMAC_FRAME tx_frame_buffer;
176 
177 /* RX frame buffer */
178 static MICROMAC_FRAME *rx_frame_buffer;
179 
180 /* Frame buffer pointer to read from */
181 static MICROMAC_FRAME *input_frame_buffer = NULL;
182 
183 /* Ringbuffer for received packets in interrupt enabled mode */
184 static struct ringbufindex input_ringbuf;
185 static MICROMAC_FRAME input_array[MIRCOMAC_CONF_BUF_NUM];
186 
187 /* SFD timestamp in RTIMER ticks */
188 static volatile uint32_t last_packet_timestamp = 0;
189 
190 /* Local functions prototypes */
191 static int on(void);
192 static int off(void);
193 #if !MICROMAC_RADIO_MAC
194 static int is_packet_for_us(uint8_t *buf, int len, int do_send_ack);
195 #endif
196 static void set_frame_filtering(uint8_t enable);
197 static rtimer_clock_t get_packet_timestamp(void);
198 static void set_txpower(int8_t power);
199 void set_channel(int c);
200 static void radio_interrupt_handler(uint32 mac_event);
201 static int get_detected_energy(void);
202 static int get_rssi(void);
203 static void read_last_rssi(void);
204 
205 /*---------------------------------------------------------------------------*/
206 PROCESS(micromac_radio_process, "micromac_radio_driver");
207 /*---------------------------------------------------------------------------*/
208 
209 /* Custom Radio parameters */
210 #ifndef RADIO_RX_MODE_POLL_MODE
211 #define RADIO_PARAM_LAST_RSSI 0x80
212 #define RADIO_PARAM_LAST_PACKET_TIMESTAMP 0x81
213 #define RADIO_RX_MODE_POLL_MODE (1 << 2)
214 #endif /* RADIO_RX_MODE_POLL_MODE */
215 
216 /*---------------------------------------------------------------------------*/
217 static rtimer_clock_t
218 get_packet_timestamp(void)
219 {
220  /* Wait for an edge */
221  uint32_t t = u32MMAC_GetTime();
222  while(u32MMAC_GetTime() == t);
223  /* Save SFD timestamp, converted from radio timer to RTIMER */
224  last_packet_timestamp = RTIMER_NOW() -
225  RADIO_TO_RTIMER((uint32_t)(u32MMAC_GetTime() - (u32MMAC_GetRxTime() - 1)));
226  /* The remaining measured error is typically in range 0..16 usec.
227  * Center it around zero, in the -8..+8 usec range. */
228  last_packet_timestamp -= US_TO_RTIMERTICKS(8);
229  return last_packet_timestamp;
230 }
231 /*---------------------------------------------------------------------------*/
232 static int
233 init_software(void)
234 {
235  int put_index;
236  /* Initialize ring buffer and first input packet pointer */
237  ringbufindex_init(&input_ringbuf, MIRCOMAC_CONF_BUF_NUM);
238  /* get pointer to next input slot */
239  put_index = ringbufindex_peek_put(&input_ringbuf);
240  if(put_index == -1) {
241  rx_frame_buffer = NULL;
242  printf("micromac_radio init:! no buffer available. Abort init.\n");
243  off();
244  return 0;
245  } else {
246  rx_frame_buffer = &input_array[put_index];
247  }
248  input_frame_buffer = rx_frame_buffer;
249 
250  process_start(&micromac_radio_process, NULL);
251 
252  return 1;
253 }
254 /*---------------------------------------------------------------------------*/
255 static int
256 init(void)
257 {
258  int ret = 1;
259  tsExtAddr node_long_address;
260  uint16_t node_short_address;
261  static uint8_t is_initialized;
262 
263  tx_in_progress = 0;
264 
265  u32JPT_Init();
266  vMMAC_Enable();
267 
268  /* Enable/disable interrupts */
269  if(poll_mode) {
270  vMMAC_EnableInterrupts(NULL);
271  vMMAC_ConfigureInterruptSources(0);
272  } else {
273  vMMAC_EnableInterrupts(&radio_interrupt_handler);
274  }
275  vMMAC_ConfigureRadio();
276  set_txpower(current_tx_power); /* it sets also the current_channel */
277 
278  vMMAC_GetMacAddress(&node_long_address);
279  /* Short addresses are disabled by default */
280  node_short_address = (uint16_t)node_long_address.u32L;
281  vMMAC_SetRxAddress(frame802154_get_pan_id(), node_short_address, &node_long_address);
282 
283  /* Disable hardware backoff */
284  vMMAC_SetTxParameters(1, 0, 0, 0);
285  vMMAC_SetCutOffTimer(0, FALSE);
286 
287 #if RADIO_TEST_MODE == RADIO_TEST_MODE_HIGH_PWR
288  /* Enable high power mode.
289  * In this mode DIO2 goes high during RX
290  * and DIO3 goes high during TX
291  **/
292  vREG_SysWrite(REG_SYS_PWR_CTRL,
293  u32REG_SysRead(REG_SYS_PWR_CTRL)
294  | REG_SYSCTRL_PWRCTRL_RFRXEN_MASK
295  | REG_SYSCTRL_PWRCTRL_RFTXEN_MASK);
296 #elif RADIO_TEST_MODE == RADIO_TEST_MODE_ADVANCED
297  /* output internal radio status on IO pins.
298  * See Chris@NXP email */
299  vREG_SysWrite(REG_SYS_PWR_CTRL,
300  u32REG_SysRead(REG_SYS_PWR_CTRL) | (1UL << 26UL));
301 #endif /* TEST_MODE */
302 
303  if(!is_initialized) {
304  is_initialized = 1;
305  ret = init_software();
306  }
307 
308  return ret;
309 }
310 /*---------------------------------------------------------------------------*/
311 static int
312 on(void)
313 {
314  /* No address matching or frame decoding */
315  if(rx_frame_buffer != NULL) {
316 #if MICROMAC_RADIO_MAC
317  vMMAC_StartMacReceive(rx_frame_buffer,
318  (uint16_t)(E_MMAC_RX_START_NOW
319  | E_MMAC_RX_USE_AUTO_ACK
320  | E_MMAC_RX_NO_MALFORMED
321  | E_MMAC_RX_NO_FCS_ERROR
322  | E_MMAC_RX_ADDRESS_MATCH
323  | E_MMAC_RX_ALIGN_NORMAL)
324  );
325 #else
326  vMMAC_StartPhyReceive(rx_frame_buffer,
327  (uint16_t)(E_MMAC_RX_START_NOW
328  | E_MMAC_RX_NO_FCS_ERROR) /* means: reject FCS errors */
329  );
330 #endif
331  } else {
332  missed_radio_on_request = 1;
333  }
334  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
335  listen_on = 1;
336  return 1;
337 }
338 /*---------------------------------------------------------------------------*/
339 static int
340 off(void)
341 {
342  listen_on = 0;
343  tx_in_progress = 0;
344 
345  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
346 
347  /* The following would be needed with delayed Tx/Rx functions
348  * vMMAC_SetCutOffTimer(0, FALSE);*/
349  vMMAC_RadioOff();
350 
351  return 1;
352 }
353 /*---------------------------------------------------------------------------*/
354 static int
355 transmit(unsigned short payload_len)
356 {
357  if(tx_in_progress) {
358  return RADIO_TX_COLLISION;
359  }
360  if(payload_len > MAX_PAYLOAD_LEN) {
361  return RADIO_TX_ERR;
362  }
363 
364  tx_in_progress = 1;
365 
366  /* Energest */
367  if(listen_on) {
368  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
369  }
370  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
371 
372  /* Transmit and wait */
373 #if MICROMAC_RADIO_MAC
374  vMMAC_StartMacTransmit(&tx_frame_buffer,
375  E_MMAC_TX_START_NOW |
376  E_MMAC_TX_USE_AUTO_ACK |
377  (send_on_cca ? E_MMAC_TX_USE_CCA : E_MMAC_TX_NO_CCA));
378 #else
379  vMMAC_StartPhyTransmit(&tx_frame_buffer,
380  E_MMAC_TX_START_NOW |
381  (send_on_cca ? E_MMAC_TX_USE_CCA : E_MMAC_TX_NO_CCA));
382 #endif
383  if(poll_mode) {
384  RTIMER_BUSYWAIT_UNTIL(u32MMAC_PollInterruptSource(E_MMAC_INT_TX_COMPLETE), MAX_PACKET_DURATION);
385  } else {
386  if(in_ack_transmission) {
387  /* as nested interupts are not possible, the tx flag will never be cleared */
388  RTIMER_BUSYWAIT_UNTIL(FALSE, MAX_ACK_DURATION);
389  } else {
390  /* wait until the tx flag is cleared */
391  RTIMER_BUSYWAIT_UNTIL(!tx_in_progress, MAX_PACKET_DURATION);
392  }
393  }
394 
395  /* Energest */
396  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
397  if(listen_on) {
398  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
399  }
400  tx_in_progress = 0;
401 
402  /* Check error code */
403  int ret;
404  uint32_t tx_error = u32MMAC_GetTxErrors();
405  if(tx_error == 0) {
406  ret = RADIO_TX_OK;
407  } else if(tx_error & E_MMAC_TXSTAT_ABORTED) {
408  ret = RADIO_TX_ERR;
409  } else if(tx_error & E_MMAC_TXSTAT_CCA_BUSY) {
410  ret = RADIO_TX_COLLISION;
411  } else if(tx_error & E_MMAC_TXSTAT_NO_ACK) {
412  ret = RADIO_TX_NOACK;
413  } else {
414  ret = RADIO_TX_ERR;
415  }
416  return ret;
417 }
418 /*---------------------------------------------------------------------------*/
419 static int
420 prepare(const void *payload, unsigned short payload_len)
421 {
422 #if !MICROMAC_RADIO_MAC
423  uint8_t i;
424  uint16_t checksum;
425 #endif
426 
427  if(tx_in_progress) {
428  return 1;
429  }
430  if(payload_len > MAX_PAYLOAD_LEN || payload == NULL) {
431  return 1;
432  }
433 #if MICROMAC_RADIO_MAC
434  frame802154_t info154;
435  int hdr_len = frame802154_parse((unsigned char *)payload, payload_len, &info154);
436  //TODO: hdr_len contains security header, which are not managed by micromac
437  tx_frame_buffer.u8PayloadLength = payload_len - hdr_len;
438  tx_frame_buffer.u8SequenceNum = info154.seq;
439  tx_frame_buffer.u16FCF = ((uint8_t*)payload)[0] | (((uint8_t*)payload)[1] << 8);
440  tx_frame_buffer.u16DestPAN = info154.dest_pid;
441  tx_frame_buffer.u16SrcPAN = info154.src_pid;
442  if(info154.fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
443  tx_frame_buffer.uDestAddr.u16Short = info154.dest_addr[0] | (info154.dest_addr[0] << 8);
444  } else if(info154.fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
445  tx_frame_buffer.uDestAddr.sExt.u32L = *(uint32_t*)(&info154.dest_addr[4]);
446  tx_frame_buffer.uDestAddr.sExt.u32H = *(uint32_t*)(&info154.dest_addr[0]);
447  }
448  if(info154.fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
449  tx_frame_buffer.uSrcAddr.u16Short = info154.src_addr[0] | (info154.src_addr[0] << 8);
450  } else if(info154.fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
451  tx_frame_buffer.uSrcAddr.sExt.u32L = *(uint32_t*)(&info154.src_addr[4]);
452  tx_frame_buffer.uSrcAddr.sExt.u32H = *(uint32_t*)(&info154.src_addr[0]);
453  }
454  tx_frame_buffer.u16FCS = crc16_data(payload, payload_len, 0);
455  memcpy(tx_frame_buffer.uPayload.au8Byte, info154.payload, info154.payload_len);
456 #else
457  /* Copy payload to (soft) Ttx buffer */
458  memcpy(tx_frame_buffer.uPayload.au8Byte, payload, payload_len);
459  i = payload_len;
460 #if CRC_SW
461  /* Compute CRC */
462  checksum = crc16_data(payload, payload_len, 0);
463  tx_frame_buffer.uPayload.au8Byte[i++] = checksum;
464  tx_frame_buffer.uPayload.au8Byte[i++] = (checksum >> 8) & 0xff;
465  tx_frame_buffer.u8PayloadLength = payload_len + CHECKSUM_LEN;
466 #else
467  tx_frame_buffer.u8PayloadLength = payload_len;
468 #endif
469 #endif
470 
471  return 0;
472 }
473 /*---------------------------------------------------------------------------*/
474 static int
475 send(const void *payload, unsigned short payload_len)
476 {
477  if(prepare(payload, payload_len) == 0) {
478  return transmit(payload_len);
479  } else {
480  return RADIO_TX_ERR;
481  }
482 }
483 /*---------------------------------------------------------------------------*/
484 int
485 get_channel(void)
486 {
487  return current_channel;
488 }
489 /*---------------------------------------------------------------------------*/
490 void
491 set_channel(int c)
492 {
493  current_channel = c;
494  vMMAC_SetChannelAndPower(current_channel, current_tx_power);
495 }
496 /*---------------------------------------------------------------------------*/
497 #if !MICROMAC_RADIO_MAC
498 static int
499 is_broadcast_addr(uint8_t mode, uint8_t *addr)
500 {
501  int i = ((mode == FRAME802154_SHORTADDRMODE) ? 2 : 8);
502  while(i-- > 0) {
503  if(addr[i] != 0xff) {
504  return 0;
505  }
506  }
507  return 1;
508 }
509 /*---------------------------------------------------------------------------*/
510 /* Send an ACK */
511 static void
512 send_ack(const frame802154_t *frame)
513 {
514  uint8_t buffer[3];
515  /* FCF: 2 octets */
516  buffer[0] = FRAME802154_ACKFRAME;
517  buffer[1] = 0;
518  /* Seqnum: 1 octets */
519  buffer[2] = frame->seq;
520  in_ack_transmission = 1;
521  send(&buffer, sizeof(buffer));
522  in_ack_transmission = 0;
523 }
524 /*---------------------------------------------------------------------------*/
525 /* Check if a packet is for us */
526 static int
527 is_packet_for_us(uint8_t *buf, int len, int do_send_ack)
528 {
529  frame802154_t frame;
530  int result;
531  uint8_t parsed = frame802154_parse(buf, len, &frame);
532  if(parsed) {
533  if(frame.fcf.dest_addr_mode) {
534  int has_dest_panid;
535  frame802154_has_panid(&frame.fcf, NULL, &has_dest_panid);
536  if(has_dest_panid
537  && frame802154_get_pan_id() != FRAME802154_BROADCASTPANDID
538  && frame.dest_pid != frame802154_get_pan_id()
539  && frame.dest_pid != FRAME802154_BROADCASTPANDID) {
540  /* Packet to another PAN */
541  return 0;
542  }
543  if(!is_broadcast_addr(frame.fcf.dest_addr_mode, frame.dest_addr)) {
544  result = linkaddr_cmp((linkaddr_t *)frame.dest_addr, &linkaddr_node_addr);
545  if(autoack_enabled && result && do_send_ack) {
546  /* this is a unicast frame and sending ACKs is enabled */
547  send_ack(&frame);
548  }
549  return result;
550  }
551  }
552  return 1;
553  } else {
554  return 0;
555  }
556 }
557 #endif
558 /*---------------------------------------------------------------------------*/
559 static int
560 read(void *buf, unsigned short bufsize)
561 {
562  int len = 0;
563 #if MICROMAC_RADIO_MAC
564  frame802154_fcf_t fcf;
565  uint8_t *p = (uint8_t*)buf;
566  int has_src_panid;
567  int has_dest_panid;
568  int c;
569 
570  p[len++] = input_frame_buffer->u16FCF & 0xff;
571  p[len++] = (input_frame_buffer->u16FCF >> 8) & 0xff;
572  frame802154_parse_fcf(p, &fcf);
573  p[len++] = input_frame_buffer->u8SequenceNum;
574  frame802154_has_panid(&fcf, &has_src_panid, &has_dest_panid);
575  if(has_dest_panid) {
576  p[len++] = input_frame_buffer->u16DestPAN & 0xff;
577  p[len++] = (input_frame_buffer->u16DestPAN >> 8) & 0xff;
578  }
579  if(fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
580  p[len++] = input_frame_buffer->uDestAddr.u16Short & 0xff;
581  p[len++] = (input_frame_buffer->uDestAddr.u16Short >> 8) & 0xff;
582  } else if(fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
583  for(c = 0; c < 4; c++) {
584  p[len + c] = ((uint8_t*)(&input_frame_buffer->uDestAddr.sExt.u32L))[3 - c];
585  }
586  for(c = 0; c < 4; c++) {
587  p[len + c + 4] = ((uint8_t*)(&input_frame_buffer->uDestAddr.sExt.u32H))[3 - c];
588  }
589  len += 8;
590  }
591  if(has_src_panid) {
592  p[len++] = input_frame_buffer->u16SrcPAN & 0xff;
593  p[len++] = (input_frame_buffer->u16SrcPAN >> 8) & 0xff;
594  }
595  if(fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
596  p[len++] = input_frame_buffer->uSrcAddr.u16Short & 0xff;
597  p[len++] = (input_frame_buffer->uSrcAddr.u16Short >> 8) & 0xff;
598  } else if(fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
599  for(c = 0; c < 4; c++) {
600  p[len + c] = ((uint8_t*)(&input_frame_buffer->uSrcAddr.sExt.u32L))[3 - c];
601  }
602  for(c = 0; c < 4; c++) {
603  p[len + c + 4] = ((uint8_t*)(&input_frame_buffer->uSrcAddr.sExt.u32H))[3 - c];
604  }
605  len += 8;
606  }
607  memcpy(&p[len], input_frame_buffer->uPayload.au8Byte, input_frame_buffer->u8PayloadLength);
608  len += input_frame_buffer->u8PayloadLength;
609 #else
610  uint16_t radio_last_rx_crc;
611  uint8_t radio_last_rx_crc_ok = 1;
612 
613  len = input_frame_buffer->u8PayloadLength;
614 
615  if(len <= CHECKSUM_LEN) {
616  input_frame_buffer->u8PayloadLength = 0;
617  return 0;
618  } else {
619  len -= CHECKSUM_LEN;
620  /* Check CRC */
621 #if CRC_SW
622  uint16_t checksum = crc16_data(input_frame_buffer->uPayload.au8Byte, len, 0);
623  radio_last_rx_crc =
624  (uint16_t)(input_frame_buffer->uPayload.au8Byte[len + 1] << (uint16_t)8)
625  | input_frame_buffer->uPayload.au8Byte[len];
626  radio_last_rx_crc_ok = (checksum == radio_last_rx_crc);
627  if(!radio_last_rx_crc_ok) {
628  }
629 #endif /* CRC_SW */
630  if(radio_last_rx_crc_ok) {
631  /* If we are in poll mode we need to check the frame here */
632  if(poll_mode) {
633  if(frame_filtering &&
634  !is_packet_for_us(input_frame_buffer->uPayload.au8Byte, len, 0)) {
635  len = 0;
636  } else {
637  read_last_rssi();
638  }
639  }
640  if(len != 0) {
641  bufsize = MIN(len, bufsize);
642  memcpy(buf, input_frame_buffer->uPayload.au8Byte, bufsize);
643  if(!poll_mode) {
644  /* Not in poll mode: packetbuf should not be accessed in interrupt context */
645  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, radio_last_rssi);
646  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, radio_last_correlation);
647  }
648  }
649  } else {
650  len = 0;
651  }
652  /* Disable further read attempts */
653  input_frame_buffer->u8PayloadLength = 0;
654  }
655 #endif
656  return len;
657 }
658 /*---------------------------------------------------------------------------*/
659 static void
660 set_txpower(int8_t power)
661 {
662  if(power > OUTPUT_POWER_MAX) {
663  current_tx_power = OUTPUT_POWER_MAX;
664  } else {
665  if(power < OUTPUT_POWER_MIN) {
666  current_tx_power = OUTPUT_POWER_MIN;
667  } else {
668  current_tx_power = power;
669  }
670  }
671  vMMAC_SetChannelAndPower(current_channel, current_tx_power);
672 }
673 /*--------------------------------------------------------------------------*/
674 static int
675 get_txpower(void)
676 {
677  int actual_tx_power;
678 #if (JENNIC_CHIP == JN5169)
679  /* Actual tx power value rounded to nearest integer number */
680  const static int8 power_table [] = {
681  -32, -30, -29, -29, /* -32 .. -29 */
682  -28, -28, -28, -28, /* -28 .. -25 */
683  -21, -21, -21, -2, /* -24 .. -21 */
684  -20, -19, -18, -17, /* -20 .. -17 */
685  -17, -17, -17, -10, /* -16 .. -13 */
686  -10, -10, -10, -9, /* -12 .. -09 */
687  -8, -7, -6, -6, /* -08 .. -05 */
688  -6, -6, 1, 1, /* -04 .. -01 */
689  1, 1, 2, 3, /* 00 .. 03 */
690  4, 5, 6, 7, /* 04 .. 07 */
691  9, 9, 10 }; /* 08 .. 10 */
692  if(current_tx_power > OUTPUT_POWER_MAX) {
693  actual_tx_power = OUTPUT_POWER_MAX;
694  } else if(current_tx_power < OUTPUT_POWER_MIN) {
695  actual_tx_power = OUTPUT_POWER_MIN;
696  } else {
697  actual_tx_power = power_table[current_tx_power + ABS_OUTPUT_POWER_MIN];
698  }
699 #else
700  /* Other JN516x chips */
701  if(current_tx_power < (-24)) {
702  actual_tx_power = OUTPUT_POWER_MIN;
703  } else if(current_tx_power < (-12)) {
704  actual_tx_power = (-20);
705  } else if(current_tx_power < 0) {
706  actual_tx_power = (-9);
707  } else {
708  actual_tx_power = OUTPUT_POWER_MAX;
709  }
710 #endif
711  return (int)actual_tx_power;
712 }
713 /*---------------------------------------------------------------------------*/
714 static int
715 get_detected_energy(void)
716 {
717  const uint32 u32Samples = 8;
718  return u8JPT_EnergyDetect(current_channel, u32Samples);
719 }
720 /*---------------------------------------------------------------------------*/
721 static int
722 get_rssi(void)
723 {
724  /* this approximate formula for RSSI is taken from NXP internal docs */
725  return (7 * get_detected_energy() - 1970) / 20;
726 }
727 /*---------------------------------------------------------------------------*/
728 static void
729 read_last_rssi(void)
730 {
731  uint8_t radio_last_rx_energy;
732  radio_last_rx_energy = u8MMAC_GetRxLqi((uint8_t *)&radio_last_correlation);
733  radio_last_rssi = i16JPT_ConvertEnergyTodBm(radio_last_rx_energy);
734 }
735 /*---------------------------------------------------------------------------*/
736 int
737 receiving_packet(void)
738 {
739  return bMMAC_RxDetected();
740 }
741 /*---------------------------------------------------------------------------*/
742 static int
743 pending_packet(void)
744 {
745  if(!poll_mode) {
746  return ringbufindex_peek_get(&input_ringbuf) != -1;
747  } else {
748  return u32MMAC_PollInterruptSource(
749  E_MMAC_INT_RX_COMPLETE | E_MMAC_INT_RX_HEADER);
750  }
751 }
752 /*---------------------------------------------------------------------------*/
753 static int
754 cca(void)
755 {
756  bool_t is_channel_busy = bJPT_CCA(current_channel,
757  E_JPT_CCA_MODE_CARRIER_OR_ENERGY,
758  cca_thershold);
759  return is_channel_busy == FALSE;
760 }
761 /*---------------------------------------------------------------------------*/
762 static void
763 radio_interrupt_handler(uint32 mac_event)
764 {
765  uint32_t rx_status;
766  uint8_t overflow = 0;
767  int get_index;
768  int put_index;
769 #if !MICROMAC_RADIO_MAC
770  int packet_for_me = 0;
771 #endif
772 
773  if(mac_event & E_MMAC_INT_TX_COMPLETE) {
774  /* Transmission attempt has finished */
775  tx_in_progress = 0;
776  } else if(mac_event & E_MMAC_INT_RX_COMPLETE) {
777  rx_status = u32MMAC_GetRxErrors();
778  /* If rx is successful */
779  if(rx_status == 0) {
780  /* Save SFD timestamp */
781  last_packet_timestamp = get_packet_timestamp();
782 
783  if(!poll_mode && (mac_event & E_MMAC_INT_RX_COMPLETE)) {
784 #if MICROMAC_RADIO_MAC
785  /* read and cache RSSI and LQI values */
786  read_last_rssi();
787  /* Put received frame in queue */
788  ringbufindex_put(&input_ringbuf);
789 
790  if((get_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
791  input_frame_buffer = &input_array[get_index];
792  }
793  process_poll(&micromac_radio_process);
794 
795  /* get pointer to next input slot */
796  put_index = ringbufindex_peek_put(&input_ringbuf);
797  /* is there space? */
798  if(put_index != -1) {
799  /* move rx_frame_buffer to next empty slot */
800  rx_frame_buffer = &input_array[put_index];
801  } else {
802  overflow = 1;
803  rx_frame_buffer = NULL;
804  }
805 #else
806  if(rx_frame_buffer->u8PayloadLength > CHECKSUM_LEN) {
807  if(frame_filtering) {
808  /* Check RX address */
809  packet_for_me = is_packet_for_us(rx_frame_buffer->uPayload.au8Byte, rx_frame_buffer->u8PayloadLength - CHECKSUM_LEN, 1);
810  } else if(!frame_filtering) {
811  packet_for_me = 1;
812  }
813  }
814  if(!packet_for_me) {
815  /* Prevent reading */
816  rx_frame_buffer->u8PayloadLength = 0;
817  } else {
818  /* read and cache RSSI and LQI values */
819  read_last_rssi();
820  /* Put received frame in queue */
821  ringbufindex_put(&input_ringbuf);
822 
823  if((get_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
824  input_frame_buffer = &input_array[get_index];
825  }
826  process_poll(&micromac_radio_process);
827 
828  /* get pointer to next input slot */
829  put_index = ringbufindex_peek_put(&input_ringbuf);
830  /* is there space? */
831  if(put_index != -1) {
832  /* move rx_frame_buffer to next empty slot */
833  rx_frame_buffer = &input_array[put_index];
834  } else {
835  overflow = 1;
836  rx_frame_buffer = NULL;
837  }
838  }
839 #endif
840  }
841  }
842  }
843  if(overflow) {
844  off();
845  } else if(MICROMAC_CONF_ALWAYS_ON
846  && (mac_event & (E_MMAC_INT_TX_COMPLETE | E_MMAC_INT_RX_COMPLETE))) {
847  on();
848  }
849 }
850 /*---------------------------------------------------------------------------*/
851 PROCESS_THREAD(micromac_radio_process, ev, data)
852 {
853  PROCESS_BEGIN();
854 
855  while(1) {
856  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
857 
858  /* Pass received packets to upper layer */
859  int16_t read_index;
860  /* Loop on accessing (without removing) a pending input packet */
861  while((read_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
862  input_frame_buffer = &input_array[read_index];
863  /* Put packet into packetbuf for input callback */
864  packetbuf_clear();
865  int len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
866  /* is packet valid? */
867  if(len > 0) {
869  NETSTACK_MAC.input();
870  }
871  /* Remove packet from ringbuf */
872  ringbufindex_get(&input_ringbuf);
873  /* Disable further read attempts */
874  input_frame_buffer->u8PayloadLength = 0;
875  }
876 
877  /* Are we recovering from overflow? */
878  if(rx_frame_buffer == NULL) {
879  /* get pointer to next input slot */
880  int put_index = ringbufindex_peek_put(&input_ringbuf);
881  /* is there space? */
882  if(put_index != -1) {
883  /* move rx_frame_buffer to next empty slot */
884  rx_frame_buffer = &input_array[put_index];
885  /* do we need to turn radio on? */
886  if(MICROMAC_CONF_ALWAYS_ON || missed_radio_on_request) {
887  missed_radio_on_request = 0;
888  on();
889  }
890  } else {
891  rx_frame_buffer = NULL;
892  }
893  }
894  }
895  PROCESS_END();
896 }
897 /*---------------------------------------------------------------------------*/
898 static void
899 set_frame_filtering(uint8_t enable)
900 {
901  frame_filtering = enable;
902 }
903 /*---------------------------------------------------------------------------*/
904 static void
905 set_autoack(uint8_t enable)
906 {
907  autoack_enabled = enable;
908 }
909 /*---------------------------------------------------------------------------*/
910 static void
911 set_poll_mode(uint8_t enable)
912 {
913  poll_mode = enable;
914  if(poll_mode) {
915  /* Disable interrupts */
916  vMMAC_EnableInterrupts(NULL);
917  vMMAC_ConfigureInterruptSources(0);
918  } else {
919  /* Initialize and enable interrupts */
920  /* TODO: enable E_MMAC_INT_RX_HEADER & filter out frames after header rx */
921  vMMAC_ConfigureInterruptSources(
922  E_MMAC_INT_RX_COMPLETE | E_MMAC_INT_TX_COMPLETE);
923  vMMAC_EnableInterrupts(&radio_interrupt_handler);
924  }
925 }
926 /* Enable or disable CCA before sending */
927 static void
928 set_send_on_cca(uint8_t enable)
929 {
930  send_on_cca = enable;
931 }
932 /*---------------------------------------------------------------------------*/
933 static radio_result_t
934 get_value(radio_param_t param, radio_value_t *value)
935 {
936  if(!value) {
937  return RADIO_RESULT_INVALID_VALUE;
938  }
939  switch(param) {
940  case RADIO_PARAM_POWER_MODE:
941  *value = listen_on || tx_in_progress ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
942  return RADIO_RESULT_OK;
943  case RADIO_PARAM_CHANNEL:
944  *value = get_channel();
945  return RADIO_RESULT_OK;
946  case RADIO_PARAM_RX_MODE:
947  *value = 0;
948  if(frame_filtering) {
950  }
951  if(autoack_enabled) {
952  *value |= RADIO_RX_MODE_AUTOACK;
953  }
954  if(poll_mode) {
955  *value |= RADIO_RX_MODE_POLL_MODE;
956  }
957  return RADIO_RESULT_OK;
958  case RADIO_PARAM_TX_MODE:
959  *value = 0;
960  if(send_on_cca) {
961  *value |= RADIO_TX_MODE_SEND_ON_CCA;
962  }
963  return RADIO_RESULT_OK;
964  case RADIO_PARAM_TXPOWER:
965  *value = get_txpower();
966  return RADIO_RESULT_OK;
967  case RADIO_PARAM_RSSI:
968  *value = get_rssi();
969  return RADIO_RESULT_OK;
970  case RADIO_PARAM_LAST_RSSI:
971  *value = radio_last_rssi;
972  return RADIO_RESULT_OK;
973  case RADIO_PARAM_CCA_THRESHOLD:
974  *value = cca_thershold;
975  return RADIO_RESULT_OK;
976  case RADIO_CONST_CHANNEL_MIN:
977  *value = 11;
978  return RADIO_RESULT_OK;
979  case RADIO_CONST_CHANNEL_MAX:
980  *value = 26;
981  return RADIO_RESULT_OK;
982  case RADIO_CONST_TXPOWER_MIN:
983  *value = OUTPUT_POWER_MIN;
984  return RADIO_RESULT_OK;
985  case RADIO_CONST_TXPOWER_MAX:
986  *value = OUTPUT_POWER_MAX;
987  return RADIO_RESULT_OK;
988  case RADIO_CONST_MAX_PAYLOAD_LEN:
989  *value = (radio_value_t)MAX_PAYLOAD_LEN;
990  return RADIO_RESULT_OK;
991  default:
992  return RADIO_RESULT_NOT_SUPPORTED;
993  }
994 }
995 /*---------------------------------------------------------------------------*/
996 static radio_result_t
997 set_value(radio_param_t param, radio_value_t value)
998 {
999  switch(param) {
1000  case RADIO_PARAM_POWER_MODE:
1001  if(value == RADIO_POWER_MODE_ON) {
1002  on();
1003  return RADIO_RESULT_OK;
1004  }
1005  if(value == RADIO_POWER_MODE_OFF) {
1006  off();
1007  return RADIO_RESULT_OK;
1008  }
1009  return RADIO_RESULT_INVALID_VALUE;
1010  case RADIO_PARAM_CHANNEL:
1011  if(value < 11 || value > 26) {
1012  return RADIO_RESULT_INVALID_VALUE;
1013  }
1014  set_channel(value);
1015  return RADIO_RESULT_OK;
1016  case RADIO_PARAM_RX_MODE:
1017  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
1018  RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
1019  return RADIO_RESULT_INVALID_VALUE;
1020  }
1021  set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
1022  set_autoack((value & RADIO_RX_MODE_AUTOACK) != 0);
1023  set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
1024  return RADIO_RESULT_OK;
1025  case RADIO_PARAM_TX_MODE:
1026  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1027  return RADIO_RESULT_INVALID_VALUE;
1028  }
1029  set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1030  return RADIO_RESULT_OK;
1031  case RADIO_PARAM_TXPOWER:
1032  if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1033  return RADIO_RESULT_INVALID_VALUE;
1034  /* Find the closest higher PA_LEVEL for the desired output power */
1035  }
1036  set_txpower(value);
1037  return RADIO_RESULT_OK;
1038  case RADIO_PARAM_CCA_THRESHOLD:
1039  cca_thershold = value;
1040  return RADIO_RESULT_OK;
1041  default:
1042  return RADIO_RESULT_NOT_SUPPORTED;
1043  }
1044 }
1045 /*---------------------------------------------------------------------------*/
1046 static radio_result_t
1047 get_object(radio_param_t param, void *dest, size_t size)
1048 {
1049  if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
1050  if(size != sizeof(rtimer_clock_t) || !dest) {
1051  return RADIO_RESULT_INVALID_VALUE;
1052  }
1053  *(rtimer_clock_t *)dest = get_packet_timestamp();
1054 
1055  return RADIO_RESULT_OK;
1056  }
1057  return RADIO_RESULT_NOT_SUPPORTED;
1058 }
1059 /*---------------------------------------------------------------------------*/
1060 static radio_result_t
1061 set_object(radio_param_t param, const void *src, size_t size)
1062 {
1063  return RADIO_RESULT_NOT_SUPPORTED;
1064 }
1065 /*---------------------------------------------------------------------------*/
1066 const struct radio_driver micromac_radio_driver = {
1067  init,
1068  prepare,
1069  transmit,
1070  send,
1071  read,
1072  cca,
1075  on,
1076  off,
1077  get_value,
1078  set_value,
1079  get_object,
1080  set_object
1081 };
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:328
uint16_t src_pid
Source PAN ID.
Definition: frame802154.h:207
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
uint8_t dest_addr_mode
2 bit.
Definition: frame802154.h:161
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:290
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void ringbufindex_init(struct ringbufindex *r, uint8_t size)
Initialize a ring buffer.
Definition: ringbufindex.c:50
Header file for the ringbufindex library
frame802154_fcf_t fcf
Frame control field.
Definition: frame802154.h:204
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
Header file for the energy estimation mechanism
int ringbufindex_peek_get(const struct ringbufindex *r)
Return the index of the first element which will be removed if calling ringbufindex_get.
Definition: ringbufindex.c:115
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
int frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
Parses an input frame.
Definition: frame802154.c:500
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:306
Header file for the CRC16 calculcation
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:321
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:309
The structure of a device driver for a radio in Contiki.
Definition: radio.h:285
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
int payload_len
Length of payload field.
Definition: frame802154.h:210
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:175
A set of debugging macros for the IP stack
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
uint8_t src_addr[8]
Source address.
Definition: frame802154.h:203
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
#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
void(* input)(void)
Callback for getting notified of incoming packet.
Definition: mac.h:72
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:296
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:293
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:315
The IEEE 802.15.4 frame has a number of constant/fixed fields that can be counted to make frame const...
Definition: frame802154.h:152
Header file for the real-time timer module.
unsigned short crc16_data(const unsigned char *data, int len, unsigned short acc)
Calculate the CRC16 over a data area.
Definition: crc16.c:66
uint8_t src_addr_mode
2 bit.
Definition: frame802154.h:163
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:67
MICROMAC_RADIO driver header file
802.15.4 frame creation and parsing functions
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:252
uint16_t dest_pid
Destination PAN ID.
Definition: frame802154.h:206
Parameters used by the frame802154_create() function.
Definition: frame802154.h:198
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
Definition: radio.h:264
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
uint8_t seq
Sequence number.
Definition: frame802154.h:205
int ringbufindex_get(struct ringbufindex *r)
Remove the first element and return its index.
Definition: ringbufindex.c:90
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:299
int ringbufindex_peek_put(const struct ringbufindex *r)
Check if there is space to put an element.
Definition: ringbufindex.c:78
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:318
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1107
uint8_t * payload
Pointer to 802.15.4 payload.
Definition: frame802154.h:209
uint8_t dest_addr[8]
Destination address.
Definition: frame802154.h:202
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:334
Header file for the LED HAL.
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
Definition: ringbufindex.c:58
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
int(* on)(void)
Turn the radio on.
Definition: radio.h:312
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