Contiki-NG
cc2420.c
1/*
2 * Copyright (c) 2007, Swedish Institute of Computer Science
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 * This code is almost device independent and should be easy to port.
34 */
35
36#include <string.h>
37
38#include "contiki.h"
39#include "sys/energest.h"
40
41#include "dev/leds.h"
42#include "dev/spi-legacy.h"
44#include "dev/radio/cc2420/cc2420_const.h"
45
46#include "net/packetbuf.h"
47#include "net/netstack.h"
48
49enum write_ram_order {
50 /* Begin with writing the first given byte */
51 WRITE_RAM_IN_ORDER,
52 /* Begin with writing the last given byte */
53 WRITE_RAM_REVERSE
54};
55
56#define DEBUG 0
57#if DEBUG
58#include <stdio.h>
59#define PRINTF(...) printf(__VA_ARGS__)
60#else
61#define PRINTF(...) do {} while (0)
62#endif
63
64#define DEBUG_LEDS DEBUG
65#undef LEDS_ON
66#undef LEDS_OFF
67#if DEBUG_LEDS
68#define LEDS_ON(x) leds_on(x)
69#define LEDS_OFF(x) leds_off(x)
70#else
71#define LEDS_ON(x)
72#define LEDS_OFF(x)
73#endif
74
75/* Conversion map between PA_LEVEL and output power in dBm
76 (from table 9 in CC2420 specification).
77*/
78struct output_config {
79 int8_t power;
80 uint8_t config;
81};
82
83static const struct output_config output_power[] = {
84 { 0, 31 }, /* 0xff */
85 { -1, 27 }, /* 0xfb */
86 { -3, 23 }, /* 0xf7 */
87 { -5, 19 }, /* 0xf3 */
88 { -7, 15 }, /* 0xef */
89 {-10, 11 }, /* 0xeb */
90 {-15, 7 }, /* 0xe7 */
91 {-25, 3 }, /* 0xe3 */
92};
93#define OUTPUT_NUM (sizeof(output_power) / sizeof(struct output_config))
94#define OUTPUT_POWER_MAX 0
95#define OUTPUT_POWER_MIN -25
96
97void cc2420_arch_init(void);
98
99int cc2420_authority_level_of_sender;
100
101volatile uint8_t cc2420_sfd_counter;
102volatile uint16_t cc2420_sfd_start_time;
103volatile uint16_t cc2420_sfd_end_time;
104
105static volatile uint16_t last_packet_timestamp;
106
107/*
108 * The maximum number of bytes this driver can accept from the MAC layer for
109 * transmission or will deliver to the MAC layer after reception. Includes
110 * the MAC header and payload, but not the FCS.
111 */
112#define MAX_PAYLOAD_LEN (127 - CHECKSUM_LEN)
113/*---------------------------------------------------------------------------*/
114PROCESS(cc2420_process, "CC2420 driver");
115/*---------------------------------------------------------------------------*/
116
117#define AUTOACK (1 << 4)
118#define AUTOCRC (1 << 5)
119#define ADR_DECODE (1 << 11)
120#define RXFIFO_PROTECTION (1 << 9)
121#define CORR_THR(n) (((n) & 0x1f) << 6)
122#define FIFOP_THR(n) ((n) & 0x7f)
123#define RXBPF_LOCUR (1 << 13);
124#define TX_MODE (3 << 2)
125
126int cc2420_on(void);
127int cc2420_off(void);
128
129static int cc2420_read(void *buf, unsigned short bufsize);
130
131static int cc2420_prepare(const void *data, unsigned short len);
132static int cc2420_transmit(unsigned short len);
133static int cc2420_send(const void *data, unsigned short len);
134
135static int cc2420_receiving_packet(void);
136static int pending_packet(void);
137static int get_cca_threshold(void);
138static int cc2420_cca(void);
139static uint16_t getreg(enum cc2420_register regname);
140
141static void set_frame_filtering(uint8_t enable);
142static void set_poll_mode(uint8_t enable);
143static void set_send_on_cca(uint8_t enable);
144static void set_auto_ack(uint8_t enable);
145
146static void set_test_mode(uint8_t enable, uint8_t modulated);
147
148signed char cc2420_last_rssi;
149uint8_t cc2420_last_correlation;
150
151static uint8_t receive_on;
152static int channel;
153
154/* Are we currently in poll mode? */
155static uint8_t volatile poll_mode = 0;
156/* Do we perform a CCA before sending? */
157static uint8_t send_on_cca = WITH_SEND_CCA;
158
159static radio_result_t
160get_value(radio_param_t param, radio_value_t *value)
161{
162 int i, v;
163
164 if(!value) {
166 }
167 switch(param) {
169 if((getreg(CC2420_MDMCTRL1) & TX_MODE) & 0x08) {
171 } else {
172 *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
173 }
174 return RADIO_RESULT_OK;
176 *value = cc2420_get_channel();
177 return RADIO_RESULT_OK;
179 *value = 0;
180 if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
182 }
183 if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
184 *value |= RADIO_RX_MODE_AUTOACK;
185 }
186 if(poll_mode) {
187 *value |= RADIO_RX_MODE_POLL_MODE;
188 }
189 return RADIO_RESULT_OK;
191 *value = 0;
192 if(send_on_cca) {
194 }
195 return RADIO_RESULT_OK;
197 v = cc2420_get_txpower();
198 *value = OUTPUT_POWER_MIN;
199 /* Find the actual estimated output power in conversion table */
200 for(i = 0; i < OUTPUT_NUM; i++) {
201 if(v >= output_power[i].config) {
202 *value = output_power[i].power;
203 break;
204 }
205 }
206 return RADIO_RESULT_OK;
208 *value = get_cca_threshold() + RSSI_OFFSET;
209 return RADIO_RESULT_OK;
210 case RADIO_PARAM_RSSI:
211 /* Return the RSSI value in dBm */
212 *value = cc2420_rssi();
213 return RADIO_RESULT_OK;
215 /* RSSI of the last packet received */
216 *value = cc2420_last_rssi;
217 return RADIO_RESULT_OK;
219 /* LQI of the last packet received */
220 *value = cc2420_last_correlation;
221 return RADIO_RESULT_OK;
223 *value = 11;
224 return RADIO_RESULT_OK;
226 *value = 26;
227 return RADIO_RESULT_OK;
229 *value = OUTPUT_POWER_MIN;
230 return RADIO_RESULT_OK;
232 *value = OUTPUT_POWER_MAX;
233 return RADIO_RESULT_OK;
234 case RADIO_CONST_MAX_PAYLOAD_LEN:
235 *value = (radio_value_t)MAX_PAYLOAD_LEN;
236 return RADIO_RESULT_OK;
237 default:
239 }
240}
241
242static radio_result_t
243set_value(radio_param_t param, radio_value_t value)
244{
245 int i;
246
247 switch(param) {
249 if(value == RADIO_POWER_MODE_ON) {
250 cc2420_on();
251 return RADIO_RESULT_OK;
252 }
253 if(value == RADIO_POWER_MODE_OFF) {
254 cc2420_off();
255 return RADIO_RESULT_OK;
256 }
257 if(value == RADIO_POWER_MODE_CARRIER_ON ||
259 set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0);
260 return RADIO_RESULT_OK;
261 }
264 if(value < 11 || value > 26) {
266 }
267 cc2420_set_channel(value);
268 return RADIO_RESULT_OK;
270 if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
273 }
274 set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
275 set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
276 set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
277 return RADIO_RESULT_OK;
279 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
281 }
282 set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
283 return RADIO_RESULT_OK;
285 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
287 }
288 /* Find the closest higher PA_LEVEL for the desired output power */
289 for(i = 1; i < OUTPUT_NUM; i++) {
290 if(value > output_power[i].power) {
291 break;
292 }
293 }
294 cc2420_set_txpower(output_power[i - 1].config);
295 return RADIO_RESULT_OK;
297 cc2420_set_cca_threshold(value - RSSI_OFFSET);
298 return RADIO_RESULT_OK;
299 default:
301 }
302}
303
304static radio_result_t
305get_object(radio_param_t param, void *dest, size_t size)
306{
308#if CC2420_CONF_SFD_TIMESTAMPS
309 if(size != sizeof(rtimer_clock_t) || !dest) {
311 }
312 *(rtimer_clock_t*)dest = cc2420_sfd_start_time;
313 return RADIO_RESULT_OK;
314#else
316#endif
317 }
319}
320
321static radio_result_t
322set_object(radio_param_t param, const void *src, size_t size)
323{
325}
326
327const struct radio_driver cc2420_driver =
328 {
329 cc2420_init,
330 cc2420_prepare,
331 cc2420_transmit,
332 cc2420_send,
333 cc2420_read,
334 cc2420_cca,
335 cc2420_receiving_packet,
337 cc2420_on,
338 cc2420_off,
339 get_value,
340 set_value,
343 };
344
345/*---------------------------------------------------------------------------*/
346/* Sends a strobe */
347static void
348strobe(enum cc2420_register regname)
349{
350 CC2420_SPI_ENABLE();
351 SPI_WRITE(regname);
352 CC2420_SPI_DISABLE();
353}
354/*---------------------------------------------------------------------------*/
355/* Reads a register */
356static uint16_t
357getreg(enum cc2420_register regname)
358{
359 uint16_t value;
360
361 CC2420_SPI_ENABLE();
362 SPI_WRITE(regname | 0x40);
363 value = (uint8_t)SPI_RXBUF;
364 SPI_TXBUF = 0;
365 SPI_WAITFOREORx();
366 value = SPI_RXBUF << 8;
367 SPI_TXBUF = 0;
368 SPI_WAITFOREORx();
369 value |= SPI_RXBUF;
370 CC2420_SPI_DISABLE();
371
372 return value;
373}
374/*---------------------------------------------------------------------------*/
375/**
376 * Writes to a register.
377 * Note: the SPI_WRITE(0) seems to be needed for getting the
378 * write reg working on the Z1 / MSP430X platform
379 */
380static void
381setreg(enum cc2420_register regname, uint16_t value)
382{
383 CC2420_SPI_ENABLE();
384 SPI_WRITE_FAST(regname);
385 SPI_WRITE_FAST((uint8_t) (value >> 8));
386 SPI_WRITE_FAST((uint8_t) (value & 0xff));
387 SPI_WAITFORTx_ENDED();
388 SPI_WRITE(0);
389 CC2420_SPI_DISABLE();
390}
391/*---------------------------------------------------------------------------*/
392static void
393read_ram(uint8_t *buffer, uint16_t adr, uint16_t count)
394{
395 uint8_t i;
396
397 CC2420_SPI_ENABLE();
398 SPI_WRITE(0x80 | ((adr) & 0x7f));
399 SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20);
400 SPI_RXBUF;
401 for(i = 0; i < count; i++) {
402 SPI_READ(((uint8_t*) buffer)[i]);
403 }
404 CC2420_SPI_DISABLE();
405}
406/*---------------------------------------------------------------------------*/
407/* Write to RAM in the CC2420 */
408static void
409write_ram(const uint8_t *buffer,
410 uint16_t adr,
411 uint16_t count,
412 enum write_ram_order order)
413{
414 uint8_t i;
415
416 CC2420_SPI_ENABLE();
417 SPI_WRITE_FAST(0x80 | (adr & 0x7f));
418 SPI_WRITE_FAST((adr >> 1) & 0xc0);
419 if(order == WRITE_RAM_IN_ORDER) {
420 for(i = 0; i < count; i++) {
421 SPI_WRITE_FAST((buffer)[i]);
422 }
423 } else {
424 for(i = count; i > 0; i--) {
425 SPI_WRITE_FAST((buffer)[i - 1]);
426 }
427 }
428 SPI_WAITFORTx_ENDED();
429 CC2420_SPI_DISABLE();
430}
431/*---------------------------------------------------------------------------*/
432static void
433write_fifo_buf(const uint8_t *buffer, uint16_t count)
434{
435 uint8_t i;
436
437 CC2420_SPI_ENABLE();
438 SPI_WRITE_FAST(CC2420_TXFIFO);
439 for(i = 0; i < count; i++) {
440 SPI_WRITE_FAST((buffer)[i]);
441 }
442 SPI_WAITFORTx_ENDED();
443 CC2420_SPI_DISABLE();
444}
445/*---------------------------------------------------------------------------*/
446/* Returns the current status */
447static uint8_t
448get_status(void)
449{
450 uint8_t status;
451
452 CC2420_SPI_ENABLE();
453 SPI_WRITE(CC2420_SNOP);
454 status = SPI_RXBUF;
455 CC2420_SPI_DISABLE();
456
457 return status;
458}
459/*---------------------------------------------------------------------------*/
460static void
461getrxdata(uint8_t *buffer, int count)
462{
463 uint8_t i;
464
465 CC2420_SPI_ENABLE();
466 SPI_WRITE(CC2420_RXFIFO | 0x40);
467 (void) SPI_RXBUF;
468 for(i = 0; i < count; i++) {
469 SPI_READ(buffer[i]);
470 }
471 clock_delay(1);
472 CC2420_SPI_DISABLE();
473}
474/*---------------------------------------------------------------------------*/
475static void
476flushrx(void)
477{
478 uint8_t dummy;
479
480 getrxdata(&dummy, 1);
481 strobe(CC2420_SFLUSHRX);
482 strobe(CC2420_SFLUSHRX);
483 if(dummy) {
484 /* avoid unused variable compiler warning */
485 }
486}
487/*---------------------------------------------------------------------------*/
488static void
489wait_for_status(uint8_t status_bit)
490{
491 rtimer_clock_t t0;
492 t0 = RTIMER_NOW();
493 while(!(get_status() & status_bit)
494 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
495}
496/*---------------------------------------------------------------------------*/
497static void
498wait_for_transmission(void)
499{
500 rtimer_clock_t t0;
501 t0 = RTIMER_NOW();
502 while((get_status() & BV(CC2420_TX_ACTIVE))
503 && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
504}
505/*---------------------------------------------------------------------------*/
506static void
507on(void)
508{
509 if(!poll_mode) {
510 CC2420_ENABLE_FIFOP_INT();
511 }
512
513 strobe(CC2420_SRXON);
514
515 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
516 receive_on = 1;
517}
518/*---------------------------------------------------------------------------*/
519static void
520off(void)
521{
522 /* PRINTF("off\n");*/
523 receive_on = 0;
524
525 /* Wait for transmission to end before turning radio off. */
526 wait_for_transmission();
527
528 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
529 strobe(CC2420_SRFOFF);
530 if(!poll_mode) {
531 CC2420_DISABLE_FIFOP_INT();
532 }
533
534 if(!CC2420_FIFOP_IS_1) {
535 flushrx();
536 }
537}
538/*---------------------------------------------------------------------------*/
539static uint8_t locked, lock_on, lock_off;
540#define GET_LOCK() locked++
541static void RELEASE_LOCK(void) {
542 if(locked == 1) {
543 if(lock_on) {
544 on();
545 lock_on = 0;
546 }
547 if(lock_off) {
548 off();
549 lock_off = 0;
550 }
551 }
552 locked--;
553}
554/*---------------------------------------------------------------------------*/
555static void
556init_security(void)
557{
558 /* only use key 0 */
559 setreg(CC2420_SECCTRL0, 0);
560 setreg(CC2420_SECCTRL1, 0);
561}
562/*---------------------------------------------------------------------------*/
563static void
564set_key(const uint8_t *key)
565{
566 GET_LOCK();
567
568 write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE);
569
570 RELEASE_LOCK();
571}
572/*---------------------------------------------------------------------------*/
573static void
574encrypt(uint8_t *plaintext_and_result)
575{
576 GET_LOCK();
577
578 write_ram(plaintext_and_result,
579 CC2420RAM_SABUF,
580 16,
581 WRITE_RAM_IN_ORDER);
582
583 strobe(CC2420_SAES);
584 while(get_status() & BV(CC2420_ENC_BUSY));
585
586 read_ram(plaintext_and_result, CC2420RAM_SABUF, 16);
587
588 RELEASE_LOCK();
589}
590/*---------------------------------------------------------------------------*/
591const struct aes_128_driver cc2420_aes_128_driver = {
592 set_key,
593 encrypt
594};
595/*---------------------------------------------------------------------------*/
596static void
597set_txpower(uint8_t power)
598{
599 uint16_t reg;
600
601 reg = getreg(CC2420_TXCTRL);
602 reg = (reg & 0xffe0) | (power & 0x1f);
603 setreg(CC2420_TXCTRL, reg);
604}
605/*---------------------------------------------------------------------------*/
606int
607cc2420_init(void)
608{
609 uint16_t reg;
610 {
611 int s = splhigh();
612 cc2420_arch_init(); /* Initalize ports and SPI. */
613 CC2420_DISABLE_FIFOP_INT();
614 CC2420_FIFOP_INT_INIT();
615 splx(s);
616 }
617
618 /* Turn on voltage regulator and reset. */
619 SET_VREG_ACTIVE();
620 clock_delay(250);
621 SET_RESET_ACTIVE();
622 clock_delay(127);
623 SET_RESET_INACTIVE();
624 clock_delay(125);
625
626
627 /* Turn on the crystal oscillator. */
628 strobe(CC2420_SXOSCON);
629 /* And wait until it stabilizes */
630 wait_for_status(BV(CC2420_XOSC16M_STABLE));
631
632 /* Set auto-ack and frame filtering */
633 set_auto_ack(CC2420_CONF_AUTOACK);
634 set_frame_filtering(CC2420_CONF_AUTOACK);
635
636 /* Enabling CRC in hardware; this is required by AUTOACK anyway
637 and provides us with RSSI and link quality indication (LQI)
638 information. */
639 reg = getreg(CC2420_MDMCTRL0);
640 reg |= AUTOCRC;
641 setreg(CC2420_MDMCTRL0, reg);
642
643 /* Set transmission turnaround time to the lower setting (8 symbols
644 = 0.128 ms) instead of the default (12 symbols = 0.192 ms). */
645 /* reg = getreg(CC2420_TXCTRL);
646 reg &= ~(1 << 13);
647 setreg(CC2420_TXCTRL, reg);*/
648
649
650 /* Change default values as recomended in the data sheet, */
651 /* correlation threshold = 20, RX bandpass filter = 1.3uA. */
652 setreg(CC2420_MDMCTRL1, CORR_THR(20));
653 reg = getreg(CC2420_RXCTRL1);
654 reg |= RXBPF_LOCUR;
655 setreg(CC2420_RXCTRL1, reg);
656
657 /* Set the FIFOP threshold to maximum. */
658 setreg(CC2420_IOCFG0, FIFOP_THR(127));
659
660 init_security();
661
662 cc2420_set_pan_addr(0xffff, 0x0000, NULL);
663 cc2420_set_channel(IEEE802154_DEFAULT_CHANNEL);
664 cc2420_set_cca_threshold(CC2420_CONF_CCA_THRESH);
665
666 flushrx();
667
668 set_poll_mode(0);
669
670 process_start(&cc2420_process, NULL);
671 return 1;
672}
673/*---------------------------------------------------------------------------*/
674static int
675cc2420_transmit(unsigned short payload_len)
676{
677 int i;
678
679 if(payload_len > MAX_PAYLOAD_LEN) {
680 return RADIO_TX_ERR;
681 }
682
683 GET_LOCK();
684
685 /* The TX FIFO can only hold one packet. Make sure to not overrun
686 * FIFO by waiting for transmission to start here and synchronizing
687 * with the CC2420_TX_ACTIVE check in cc2420_send.
688 *
689 * Note that we may have to wait up to 320 us (20 symbols) before
690 * transmission starts.
691 */
692#ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
693#error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
694#else
695#define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
696#endif
697
698 if(send_on_cca) {
699 strobe(CC2420_SRXON);
700 wait_for_status(BV(CC2420_RSSI_VALID));
701 strobe(CC2420_STXONCCA);
702 } else {
703 strobe(CC2420_STXON);
704 }
705 for(i = LOOP_20_SYMBOLS; i > 0; i--) {
706 if(CC2420_SFD_IS_1) {
707 if(!(get_status() & BV(CC2420_TX_ACTIVE))) {
708 /* SFD went high but we are not transmitting. This means that
709 we just started receiving a packet, so we drop the
710 transmission. */
711 RELEASE_LOCK();
712 return RADIO_TX_COLLISION;
713 }
714 if(receive_on) {
715 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
716 }
717 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
718 /* We wait until transmission has ended so that we get an
719 accurate measurement of the transmission time.*/
720 wait_for_transmission();
721
722 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
723 if(receive_on) {
724 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
725 } else {
726 /* We need to explicitly turn off the radio,
727 * since STXON[CCA] -> TX_ACTIVE -> RX_ACTIVE */
728 off();
729 }
730
731 RELEASE_LOCK();
732 return RADIO_TX_OK;
733 }
734 }
735
736 /* If we send with cca (cca_on_send), we get here if the packet wasn't
737 transmitted because of other channel activity. */
738 PRINTF("cc2420: do_send() transmission never started\n");
739
740 RELEASE_LOCK();
741 return RADIO_TX_COLLISION;
742}
743/*---------------------------------------------------------------------------*/
744static int
745cc2420_prepare(const void *payload, unsigned short payload_len)
746{
747 uint8_t total_len;
748
749 if(payload_len > MAX_PAYLOAD_LEN) {
750 return RADIO_TX_ERR;
751 }
752
753 GET_LOCK();
754
755 PRINTF("cc2420: sending %d bytes\n", payload_len);
756
757 /* Wait for any previous transmission to finish. */
758 /* while(status() & BV(CC2420_TX_ACTIVE));*/
759
760 /* Write packet to TX FIFO. */
761 strobe(CC2420_SFLUSHTX);
762
763 total_len = payload_len + CHECKSUM_LEN;
764 write_fifo_buf(&total_len, 1);
765 write_fifo_buf(payload, payload_len);
766
767 RELEASE_LOCK();
768 return 0;
769}
770/*---------------------------------------------------------------------------*/
771static int
772cc2420_send(const void *payload, unsigned short payload_len)
773{
774 cc2420_prepare(payload, payload_len);
775 return cc2420_transmit(payload_len);
776}
777/*---------------------------------------------------------------------------*/
778int
779cc2420_off(void)
780{
781 /* Don't do anything if we are already turned off. */
782 if(receive_on == 0) {
783 return 1;
784 }
785
786 /* If we are called when the driver is locked, we indicate that the
787 radio should be turned off when the lock is unlocked. */
788 if(locked) {
789 /* printf("Off when locked (%d)\n", locked);*/
790 lock_off = 1;
791 return 1;
792 }
793
794 GET_LOCK();
795 /* If we are currently receiving a packet (indicated by SFD == 1),
796 we don't actually switch the radio off now, but signal that the
797 driver should switch off the radio once the packet has been
798 received and processed, by setting the 'lock_off' variable. */
799 if(get_status() & BV(CC2420_TX_ACTIVE)) {
800 lock_off = 1;
801 } else {
802 off();
803 }
804 RELEASE_LOCK();
805 return 1;
806}
807/*---------------------------------------------------------------------------*/
808int
809cc2420_on(void)
810{
811 if(receive_on) {
812 return 1;
813 }
814 if(locked) {
815 lock_on = 1;
816 return 1;
817 }
818
819 GET_LOCK();
820 on();
821 RELEASE_LOCK();
822 return 1;
823}
824/*---------------------------------------------------------------------------*/
825int
826cc2420_get_channel(void)
827{
828 return channel;
829}
830/*---------------------------------------------------------------------------*/
831int
832cc2420_set_channel(int c)
833{
834 uint16_t f;
835
836 GET_LOCK();
837 /*
838 * Subtract the base channel (11), multiply by 5, which is the
839 * channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
840 */
841 channel = c;
842
843 f = 5 * (c - 11) + 357 + 0x4000;
844
845 /* Wait for any transmission to end. */
846 wait_for_transmission();
847
848 setreg(CC2420_FSCTRL, f);
849
850 /* If we are in receive mode, we issue an SRXON command to ensure
851 that the VCO is calibrated. */
852 if(receive_on) {
853 strobe(CC2420_SRXON);
854 }
855
856 RELEASE_LOCK();
857 return 1;
858}
859/*---------------------------------------------------------------------------*/
860void
861cc2420_set_pan_addr(unsigned pan,
862 unsigned addr,
863 const uint8_t *ieee_addr)
864{
865 GET_LOCK();
866
867 write_ram((uint8_t *) &pan, CC2420RAM_PANID, 2, WRITE_RAM_IN_ORDER);
868 write_ram((uint8_t *) &addr, CC2420RAM_SHORTADDR, 2, WRITE_RAM_IN_ORDER);
869
870 if(ieee_addr != NULL) {
871 write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE);
872 }
873 RELEASE_LOCK();
874}
875/*---------------------------------------------------------------------------*/
876/*
877 * Interrupt leaves frame intact in FIFO.
878 */
879int
881{
882 CC2420_CLEAR_FIFOP_INT();
883 process_poll(&cc2420_process);
884
885 last_packet_timestamp = cc2420_sfd_start_time;
886 return 1;
887}
888/*---------------------------------------------------------------------------*/
889PROCESS_THREAD(cc2420_process, ev, data)
890{
891 int len;
893
894 PRINTF("cc2420_process: started\n");
895
896 while(1) {
897 PROCESS_YIELD_UNTIL(!poll_mode && ev == PROCESS_EVENT_POLL);
898
899 PRINTF("cc2420_process: calling receiver callback\n");
900
902 len = cc2420_read(packetbuf_dataptr(), PACKETBUF_SIZE);
903
905
906 NETSTACK_MAC.input();
907 }
908
909 PROCESS_END();
910}
911/*---------------------------------------------------------------------------*/
912static int
913cc2420_read(void *buf, unsigned short bufsize)
914{
915 uint8_t footer[FOOTER_LEN];
916 uint8_t len;
917
918 if(!CC2420_FIFOP_IS_1) {
919 return 0;
920 }
921
922 GET_LOCK();
923
924 getrxdata(&len, 1);
925
926 if(len > CC2420_MAX_PACKET_LEN) {
927 /* Oops, we must be out of sync. */
928 } else if(len <= FOOTER_LEN) {
929 /* Packet too short */
930 } else if(len - FOOTER_LEN > bufsize) {
931 /* Packet too long */
932 } else {
933 getrxdata((uint8_t *) buf, len - FOOTER_LEN);
934 getrxdata(footer, FOOTER_LEN);
935
936 if(footer[1] & FOOTER1_CRC_OK) {
937 cc2420_last_rssi = footer[0] + RSSI_OFFSET;
938 cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
939 if(!poll_mode) {
940 /* Not in poll mode: packetbuf should not be accessed in interrupt context.
941 * In poll mode, the last packet RSSI and link quality can be obtained through
942 * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
943 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
944 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
945 }
946 } else {
947 len = FOOTER_LEN;
948 }
949
950 if(!poll_mode) {
951 if(CC2420_FIFOP_IS_1) {
952 if(!CC2420_FIFO_IS_1) {
953 /* Clean up in case of FIFO overflow! This happens for every
954 * full length frame and is signaled by FIFOP = 1 and FIFO =
955 * 0. */
956 flushrx();
957 } else {
958 /* Another packet has been received and needs attention. */
959 process_poll(&cc2420_process);
960 }
961 }
962 }
963
964 RELEASE_LOCK();
965 return len - FOOTER_LEN;
966 }
967
968 flushrx();
969 RELEASE_LOCK();
970 return 0;
971}
972/*---------------------------------------------------------------------------*/
973void
974cc2420_set_txpower(uint8_t power)
975{
976 GET_LOCK();
977 set_txpower(power);
978 RELEASE_LOCK();
979}
980/*---------------------------------------------------------------------------*/
981int
982cc2420_get_txpower(void)
983{
984 int power;
985 GET_LOCK();
986 power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
987 RELEASE_LOCK();
988 return power;
989}
990/*---------------------------------------------------------------------------*/
991int
992cc2420_rssi(void)
993{
994 int rssi;
995 int radio_was_off = 0;
996
997 if(locked) {
998 return 0;
999 }
1000
1001 GET_LOCK();
1002
1003 if(!receive_on) {
1004 radio_was_off = 1;
1005 cc2420_on();
1006 }
1007 wait_for_status(BV(CC2420_RSSI_VALID));
1008
1009 rssi = (int)((signed char) getreg(CC2420_RSSI));
1010 rssi += RSSI_OFFSET;
1011
1012 if(radio_was_off) {
1013 cc2420_off();
1014 }
1015 RELEASE_LOCK();
1016 return rssi;
1017}
1018/*---------------------------------------------------------------------------*/
1019static int
1020cc2420_cca(void)
1021{
1022 int cca;
1023 int radio_was_off = 0;
1024
1025 /* If the radio is locked by an underlying thread (because we are
1026 being invoked through an interrupt), we preted that the coast is
1027 clear (i.e., no packet is currently being transmitted by a
1028 neighbor). */
1029 if(locked) {
1030 return 1;
1031 }
1032
1033 GET_LOCK();
1034 if(!receive_on) {
1035 radio_was_off = 1;
1036 cc2420_on();
1037 }
1038
1039 /* Make sure that the radio really got turned on. */
1040 if(!receive_on) {
1041 RELEASE_LOCK();
1042 if(radio_was_off) {
1043 cc2420_off();
1044 }
1045 return 1;
1046 }
1047
1048 wait_for_status(BV(CC2420_RSSI_VALID));
1049
1050 cca = CC2420_CCA_IS_1;
1051
1052 if(radio_was_off) {
1053 cc2420_off();
1054 }
1055 RELEASE_LOCK();
1056 return cca;
1057}
1058/*---------------------------------------------------------------------------*/
1059int
1060cc2420_receiving_packet(void)
1061{
1062 return CC2420_SFD_IS_1;
1063}
1064/*---------------------------------------------------------------------------*/
1065static int
1066pending_packet(void)
1067{
1068 return CC2420_FIFOP_IS_1;
1069}
1070/*---------------------------------------------------------------------------*/
1071static int
1072get_cca_threshold(void)
1073{
1074 int value;
1075
1076 GET_LOCK();
1077 value = (int8_t)(getreg(CC2420_RSSI) >> 8);
1078 RELEASE_LOCK();
1079 return value;
1080}
1081/*---------------------------------------------------------------------------*/
1082void
1083cc2420_set_cca_threshold(int value)
1084{
1085 uint16_t shifted = value << 8;
1086 GET_LOCK();
1087 setreg(CC2420_RSSI, shifted);
1088 RELEASE_LOCK();
1089}
1090/*---------------------------------------------------------------------------*/
1091/* Set or unset frame autoack */
1092static void
1093set_auto_ack(uint8_t enable)
1094{
1095 GET_LOCK();
1096
1097 uint16_t reg = getreg(CC2420_MDMCTRL0);
1098 if(enable) {
1099 reg |= AUTOACK;
1100 } else {
1101 reg &= ~(AUTOACK);
1102 }
1103
1104 setreg(CC2420_MDMCTRL0, reg);
1105 RELEASE_LOCK();
1106}
1107/*---------------------------------------------------------------------------*/
1108/* Set or unset frame filtering */
1109static void
1110set_frame_filtering(uint8_t enable)
1111{
1112 GET_LOCK();
1113
1114 /* Turn on/off address decoding. */
1115 uint16_t reg = getreg(CC2420_MDMCTRL0);
1116 if(enable) {
1117 reg |= ADR_DECODE;
1118 } else {
1119 reg &= ~(ADR_DECODE);
1120 }
1121
1122 setreg(CC2420_MDMCTRL0, reg);
1123 RELEASE_LOCK();
1124}
1125/*---------------------------------------------------------------------------*/
1126/* Enable or disable radio interrupts (both FIFOP and SFD timer capture) */
1127static void
1128set_poll_mode(uint8_t enable)
1129{
1130 GET_LOCK();
1131 poll_mode = enable;
1132 if(enable) {
1133 /* Disable FIFOP interrupt */
1134 CC2420_CLEAR_FIFOP_INT();
1135 CC2420_DISABLE_FIFOP_INT();
1136 } else {
1137 /* Initialize and enable FIFOP interrupt */
1138 CC2420_FIFOP_INT_INIT();
1139 CC2420_ENABLE_FIFOP_INT();
1140 CC2420_CLEAR_FIFOP_INT();
1141 }
1142 RELEASE_LOCK();
1143}
1144/*---------------------------------------------------------------------------*/
1145/* Enable or disable CCA before sending */
1146static void
1147set_send_on_cca(uint8_t enable)
1148{
1149 send_on_cca = enable;
1150}
1151/*---------------------------------------------------------------------------*/
1152/* Enable or disable radio test mode emmiting modulated or unmodulated
1153 * (carrier) signal. See datasheet page 55.
1154 */
1155static uint16_t prev_MDMCTRL1, prev_DACTST;
1156static uint8_t was_on;
1157
1158static void
1159set_test_mode(uint8_t enable, uint8_t modulated)
1160{
1161 radio_value_t mode;
1162 get_value(RADIO_PARAM_POWER_MODE, &mode);
1163
1164 if(enable) {
1165 if(mode == RADIO_POWER_MODE_CARRIER_ON) {
1166 return;
1167 }
1168 was_on = (mode == RADIO_POWER_MODE_ON);
1169 off();
1170 prev_MDMCTRL1 = getreg(CC2420_MDMCTRL1);
1171 setreg(CC2420_MDMCTRL1, 0x050C);
1172 if(!modulated) {
1173 prev_DACTST = getreg(CC2420_DACTST);
1174 setreg(CC2420_DACTST, 0x1800);
1175 }
1176 /* actually starts the test mode */
1177 strobe(CC2420_STXON);
1178 } else {
1179 if(mode != RADIO_POWER_MODE_CARRIER_ON) {
1180 return;
1181 }
1182 strobe(CC2420_SRFOFF);
1183 if(!modulated) {
1184 setreg(CC2420_DACTST, prev_DACTST);
1185 }
1186 setreg(CC2420_MDMCTRL1, prev_MDMCTRL1);
1187 /* actually stops the carrier */
1188 if(was_on) {
1189 on();
1190 }
1191 }
1192}
1193/*---------------------------------------------------------------------------*/
CC2420 driver header file.
void cc2420_set_txpower(uint8_t power)
Definition: cc2420.c:974
int cc2420_interrupt(void)
Interrupt function, called from the simple-cc2420-arch driver.
Definition: cc2420.c:880
Header file for the energy estimation mechanism.
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
Definition: clock.c:164
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1154
static volatile uint64_t count
Num.
Definition: clock.c:50
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:451
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:461
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:474
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:456
@ RADIO_RESULT_NOT_SUPPORTED
The parameter is not supported.
Definition: radio.h:481
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
Definition: radio.h:482
@ RADIO_RESULT_OK
The parameter was set/read successfully.
Definition: radio.h:480
@ 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:286
@ 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_LAST_LINK_QUALITY
Link quality indicator of the last received packet.
Definition: radio.h:244
@ RADIO_PARAM_TXPOWER
Transmission power in dBm.
Definition: radio.h:192
@ RADIO_CONST_CHANNEL_MAX
The highest radio channel number.
Definition: radio.h:316
@ 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:321
@ RADIO_CONST_CHANNEL_MIN
The lowest radio channel number.
Definition: radio.h:311
@ RADIO_CONST_TXPOWER_MAX
The maximum transmission power in dBm.
Definition: radio.h:326
@ 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_CARRIER_OFF
Radio powered on, but not emitting unmodulated carriers.
Definition: radio.h:410
@ RADIO_POWER_MODE_OFF
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:395
@ RADIO_POWER_MODE_ON
Radio powered on and able to receive frames.
Definition: radio.h:400
@ RADIO_POWER_MODE_CARRIER_ON
Radio powered on and emitting unmodulated carriers.
Definition: radio.h:405
@ RADIO_TX_COLLISION
TX failed due to a collision.
Definition: radio.h:511
@ RADIO_TX_ERR
An error occurred during transmission.
Definition: radio.h:506
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition: radio.h:498
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
#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
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Basic SPI macros.
Structure of AES drivers.
Definition: aes-128.h:57
void(* set_key)(const uint8_t *key)
Sets the current key.
Definition: aes-128.h:62
void(* encrypt)(uint8_t *plaintext_and_result)
Encrypts.
Definition: aes-128.h:67
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:534
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:770
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:756
int(* off)(void)
Turn the radio off.
Definition: radio.h:729
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:787
int(* on)(void)
Turn the radio on.
Definition: radio.h:711
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver's buffers.
Definition: radio.h:697
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:741
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107