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