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 */
141static volatile signed char radio_last_rssi;
142static volatile uint8_t radio_last_correlation; /* LQI */
143
144/* Did we miss a request to turn the radio on due to overflow? */
145static volatile uint8_t missed_radio_on_request = 0;
146
147/* Poll mode disabled by default */
148static uint8_t poll_mode = 0;
149/* (Software) frame filtering enabled by default */
150static uint8_t frame_filtering = 1;
151/* (Software) autoack */
152static uint8_t autoack_enabled = MICROMAC_CONF_AUTOACK;
153/* CCA before sending? Disabled by default. */
154static uint8_t send_on_cca = 0;
155
156/* Current radio channel */
157static 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 */
161static int current_tx_power = MICROMAC_CONF_TX_POWER;
162
163/* an integer between 0 and 255, used only with cca() */
164static uint8_t cca_thershold = MICROMAC_CONF_CCA_THR;
165
166/* Tx in progress? */
167static volatile uint8_t tx_in_progress = 0;
168/* Are we currently listening? */
169static volatile uint8_t listen_on = 0;
170
171/* Is the driver currently transmitting a software ACK? */
172static uint8_t in_ack_transmission = 0;
173
174/* TX frame buffer */
175static MICROMAC_FRAME tx_frame_buffer;
176
177/* RX frame buffer */
178static MICROMAC_FRAME *rx_frame_buffer;
179
180/* Frame buffer pointer to read from */
181static MICROMAC_FRAME *input_frame_buffer = NULL;
182
183/* Ringbuffer for received packets in interrupt enabled mode */
184static struct ringbufindex input_ringbuf;
185static MICROMAC_FRAME input_array[MIRCOMAC_CONF_BUF_NUM];
186
187/* SFD timestamp in RTIMER ticks */
188static volatile uint32_t last_packet_timestamp = 0;
189
190/* Local functions prototypes */
191static int on(void);
192static int off(void);
193#if !MICROMAC_RADIO_MAC
194static int is_packet_for_us(uint8_t *buf, int len, int do_send_ack);
195#endif
196static void set_frame_filtering(uint8_t enable);
197static rtimer_clock_t get_packet_timestamp(void);
198static void set_txpower(int8_t power);
199void set_channel(int c);
200static void radio_interrupt_handler(uint32 mac_event);
201static int get_detected_energy(void);
202static int get_rssi(void);
203static void read_last_rssi(void);
204
205/*---------------------------------------------------------------------------*/
206PROCESS(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/*---------------------------------------------------------------------------*/
217static rtimer_clock_t
218get_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/*---------------------------------------------------------------------------*/
232static int
233init_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/*---------------------------------------------------------------------------*/
255static int
256init(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/*---------------------------------------------------------------------------*/
311static int
312on(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/*---------------------------------------------------------------------------*/
339static int
340off(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/*---------------------------------------------------------------------------*/
354static int
355transmit(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/*---------------------------------------------------------------------------*/
419static int
420prepare(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/*---------------------------------------------------------------------------*/
474static int
475send(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/*---------------------------------------------------------------------------*/
484int
485get_channel(void)
486{
487 return current_channel;
488}
489/*---------------------------------------------------------------------------*/
490void
491set_channel(int c)
492{
493 current_channel = c;
494 vMMAC_SetChannelAndPower(current_channel, current_tx_power);
495}
496/*---------------------------------------------------------------------------*/
497#if !MICROMAC_RADIO_MAC
498static int
499is_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 */
511static void
512send_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 */
526static int
527is_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/*---------------------------------------------------------------------------*/
559static int
560read(void *buf, unsigned short bufsize)
561{
562 int len = 0;
563#if MICROMAC_RADIO_MAC
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/*---------------------------------------------------------------------------*/
659static void
660set_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/*--------------------------------------------------------------------------*/
674static int
675get_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/*---------------------------------------------------------------------------*/
714static int
715get_detected_energy(void)
716{
717 const uint32 u32Samples = 8;
718 return u8JPT_EnergyDetect(current_channel, u32Samples);
719}
720/*---------------------------------------------------------------------------*/
721static int
722get_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/*---------------------------------------------------------------------------*/
728static void
729read_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/*---------------------------------------------------------------------------*/
736int
737receiving_packet(void)
738{
739 return bMMAC_RxDetected();
740}
741/*---------------------------------------------------------------------------*/
742static int
743pending_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/*---------------------------------------------------------------------------*/
753static int
754cca(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/*---------------------------------------------------------------------------*/
762static void
763radio_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/*---------------------------------------------------------------------------*/
851PROCESS_THREAD(micromac_radio_process, ev, data)
852{
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 */
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/*---------------------------------------------------------------------------*/
898static void
899set_frame_filtering(uint8_t enable)
900{
901 frame_filtering = enable;
902}
903/*---------------------------------------------------------------------------*/
904static void
905set_autoack(uint8_t enable)
906{
907 autoack_enabled = enable;
908}
909/*---------------------------------------------------------------------------*/
910static void
911set_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 */
927static void
928set_send_on_cca(uint8_t enable)
929{
930 send_on_cca = enable;
931}
932/*---------------------------------------------------------------------------*/
933static radio_result_t
934get_value(radio_param_t param, radio_value_t *value)
935{
936 if(!value) {
938 }
939 switch(param) {
941 *value = listen_on || tx_in_progress ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
942 return RADIO_RESULT_OK;
944 *value = get_channel();
945 return RADIO_RESULT_OK;
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;
959 *value = 0;
960 if(send_on_cca) {
962 }
963 return RADIO_RESULT_OK;
965 *value = get_txpower();
966 return RADIO_RESULT_OK;
967 case RADIO_PARAM_RSSI:
968 *value = get_rssi();
969 return RADIO_RESULT_OK;
971 *value = radio_last_rssi;
972 return RADIO_RESULT_OK;
974 *value = cca_thershold;
975 return RADIO_RESULT_OK;
977 *value = 11;
978 return RADIO_RESULT_OK;
980 *value = 26;
981 return RADIO_RESULT_OK;
983 *value = OUTPUT_POWER_MIN;
984 return RADIO_RESULT_OK;
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:
993 }
994}
995/*---------------------------------------------------------------------------*/
996static radio_result_t
997set_value(radio_param_t param, radio_value_t value)
998{
999 switch(param) {
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 }
1011 if(value < 11 || value > 26) {
1013 }
1014 set_channel(value);
1015 return RADIO_RESULT_OK;
1017 if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
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;
1026 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
1028 }
1029 set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
1030 return RADIO_RESULT_OK;
1032 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
1034 /* Find the closest higher PA_LEVEL for the desired output power */
1035 }
1036 set_txpower(value);
1037 return RADIO_RESULT_OK;
1039 cca_thershold = value;
1040 return RADIO_RESULT_OK;
1041 default:
1043 }
1044}
1045/*---------------------------------------------------------------------------*/
1046static radio_result_t
1047get_object(radio_param_t param, void *dest, size_t size)
1048{
1050 if(size != sizeof(rtimer_clock_t) || !dest) {
1052 }
1053 *(rtimer_clock_t *)dest = get_packet_timestamp();
1054
1055 return RADIO_RESULT_OK;
1056 }
1058}
1059/*---------------------------------------------------------------------------*/
1060static radio_result_t
1061set_object(radio_param_t param, const void *src, size_t size)
1062{
1064}
1065/*---------------------------------------------------------------------------*/
1066const 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,
1081};
Header file for the CRC16 calculcation.
Header file for the energy estimation mechanism.
802.15.4 frame creation and parsing functions
static uint8_t get_channel()
Get the current operating channel.
Definition: cc2538-rf.c:165
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:175
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1110
unsigned short crc16_data(const unsigned char *data, int len, unsigned short acc)
Calculate the CRC16 over a data area.
Definition: crc16.c:66
int frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
Parses an input frame.
Definition: frame802154.c:500
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:67
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#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
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition: radio.h:443
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:453
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:466
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
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 RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition: radio.h:448
@ RADIO_RESULT_NOT_SUPPORTED
The parameter is not supported.
Definition: radio.h:473
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
Definition: radio.h:474
@ RADIO_RESULT_OK
The parameter was set/read successfully.
Definition: radio.h:472
@ RADIO_PARAM_POWER_MODE
When getting the value of this parameter, the radio driver should indicate whether the radio is on or...
Definition: radio.h:119
@ RADIO_PARAM_RSSI
Received signal strength indicator in dBm.
Definition: radio.h:218
@ RADIO_PARAM_LAST_PACKET_TIMESTAMP
Last packet timestamp, of type rtimer_clock_t.
Definition: radio.h:278
@ RADIO_PARAM_LAST_RSSI
The RSSI value of the last received packet.
Definition: radio.h:226
@ RADIO_PARAM_RX_MODE
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
@ RADIO_PARAM_CHANNEL
Channel used for radio communication.
Definition: radio.h:134
@ RADIO_PARAM_TXPOWER
Transmission power in dBm.
Definition: radio.h:192
@ RADIO_CONST_CHANNEL_MAX
The highest radio channel number.
Definition: radio.h:308
@ RADIO_PARAM_CCA_THRESHOLD
Clear channel assessment threshold in dBm.
Definition: radio.h:205
@ RADIO_CONST_TXPOWER_MIN
The minimum transmission power in dBm.
Definition: radio.h:313
@ RADIO_CONST_CHANNEL_MIN
The lowest radio channel number.
Definition: radio.h:303
@ RADIO_CONST_TXPOWER_MAX
The maximum transmission power in dBm.
Definition: radio.h:318
@ RADIO_PARAM_TX_MODE
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition: radio.h:180
@ RADIO_POWER_MODE_OFF
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:387
@ RADIO_POWER_MODE_ON
Radio powered on and able to receive frames.
Definition: radio.h:392
@ RADIO_TX_NOACK
A unicast frame was sent OK but an ACK was not received.
Definition: radio.h:508
@ RADIO_TX_COLLISION
TX failed due to a collision.
Definition: radio.h:503
@ RADIO_TX_ERR
An error occurred during transmission.
Definition: radio.h:498
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition: radio.h:490
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
Header file for the LED HAL.
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
MICROMAC_RADIO driver header file.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
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
void ringbufindex_init(struct ringbufindex *r, uint8_t size)
Initialize a ring buffer.
Definition: ringbufindex.c:50
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
Definition: ringbufindex.c:58
int ringbufindex_get(struct ringbufindex *r)
Remove the first element and return its index.
Definition: ringbufindex.c:90
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 ringbufindex library.
Header file for the real-time timer module.
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
uint8_t src_addr_mode
2 bit.
Definition: frame802154.h:163
uint8_t dest_addr_mode
2 bit.
Definition: frame802154.h:161
Parameters used by the frame802154_create() function.
Definition: frame802154.h:198
uint8_t seq
Sequence number.
Definition: frame802154.h:205
uint8_t dest_addr[8]
Destination address.
Definition: frame802154.h:202
uint8_t * payload
Pointer to 802.15.4 payload.
Definition: frame802154.h:209
uint8_t src_addr[8]
Source address.
Definition: frame802154.h:203
uint16_t src_pid
Source PAN ID.
Definition: frame802154.h:207
frame802154_fcf_t fcf
Frame control field
Definition: frame802154.h:204
uint16_t dest_pid
Destination PAN ID.
Definition: frame802154.h:206
int payload_len
Length of payload field.
Definition: frame802154.h:210
void(* input)(void)
Callback for getting notified of incoming packet.
Definition: mac.h:72
The structure of a Contiki-NG radio device driver.
Definition: radio.h:526
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:762
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:647
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:572
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:748
int(* off)(void)
Turn the radio off.
Definition: radio.h:721
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:547
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:623
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:676
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:779
int(* on)(void)
Turn the radio on.
Definition: radio.h:703
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:611
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver's buffers.
Definition: radio.h:689
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:733
A set of debugging macros for the IP stack.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107