48 #include "dev/cc2420_const.h"
56 #define WITH_SEND_CCA 1
60 #ifndef CC2420_CONF_CHECKSUM
61 #define CC2420_CONF_CHECKSUM 0
64 #ifndef CC2420_CONF_AUTOACK
65 #define CC2420_CONF_AUTOACK 0
68 #if CC2420_CONF_CHECKSUM
70 #define CHECKSUM_LEN 2
72 #define CHECKSUM_LEN 0
75 #define AUX_LEN (CHECKSUM_LEN + FOOTER_LEN)
78 #define FOOTER1_CRC_OK 0x80
79 #define FOOTER1_CORRELATION 0x7f
84 #define PRINTF(...) printf(__VA_ARGS__)
86 #define PRINTF(...) do {} while (0)
89 #define DEBUG_LEDS DEBUG
93 #define LEDS_ON(x) leds_on(x)
94 #define LEDS_OFF(x) leds_off(x)
100 void cc2420_arch_init(
void);
103 rtimer_clock_t cc2420_time_of_arrival, cc2420_time_of_departure;
105 int cc2420_authority_level_of_sender;
107 int cc2420_packets_seen, cc2420_packets_read;
109 static uint8_t
volatile pending;
111 #define BUSYWAIT_UNTIL(cond, max_time) \
115 while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
118 volatile uint8_t cc2420_sfd_counter;
119 volatile uint16_t cc2420_sfd_start_time;
120 volatile uint16_t cc2420_sfd_end_time;
122 static volatile uint16_t last_packet_timestamp;
124 PROCESS(cc2420_process,
"CC2420 driver");
129 int cc2420_off(
void);
131 static int cc2420_read(
void *buf,
unsigned short bufsize);
133 static int cc2420_prepare(
const void *data,
unsigned short len);
134 static int cc2420_transmit(
unsigned short len);
135 static int cc2420_send(
const void *data,
unsigned short len);
137 static int cc2420_receiving_packet(
void);
138 static int pending_packet(
void);
139 static int cc2420_cca(
void);
142 signed char cc2420_last_rssi;
143 uint8_t cc2420_last_correlation;
155 cc2420_receiving_packet,
161 static uint8_t receive_on;
168 getrxdata(
void *buf,
int len)
170 CC2420_READ_FIFO_BUF(buf, len);
173 getrxbyte(uint8_t *byte)
175 CC2420_READ_FIFO_BYTE(*byte);
182 CC2420_READ_FIFO_BYTE(dummy);
183 CC2420_STROBE(CC2420_SFLUSHRX);
184 CC2420_STROBE(CC2420_SFLUSHRX);
188 strobe(
enum cc2420_register regname)
190 CC2420_STROBE(regname);
197 CC2420_GET_STATUS(status);
201 static uint8_t locked, lock_on, lock_off;
206 CC2420_ENABLE_FIFOP_INT();
207 strobe(CC2420_SRXON);
209 BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 100);
211 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
221 BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
223 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
224 strobe(CC2420_SRFOFF);
225 CC2420_DISABLE_FIFOP_INT();
227 if(!CC2420_FIFOP_IS_1) {
232 #define GET_LOCK() locked++
233 static void RELEASE_LOCK(
void) {
248 getreg(
enum cc2420_register regname)
251 CC2420_READ_REG(regname, reg);
256 setreg(
enum cc2420_register regname,
unsigned value)
258 CC2420_WRITE_REG(regname, value);
262 set_txpower(uint8_t power)
266 reg = getreg(CC2420_TXCTRL);
267 reg = (reg & 0xffe0) | (power & 0x1f);
268 setreg(CC2420_TXCTRL, reg);
271 #define AUTOACK (1 << 4)
272 #define ADR_DECODE (1 << 11)
273 #define RXFIFO_PROTECTION (1 << 9)
274 #define CORR_THR(n) (((n) & 0x1f) << 6)
275 #define FIFOP_THR(n) ((n) & 0x7f)
276 #define RXBPF_LOCUR (1 << 13);
281 PRINTF(
"CC2420: init\n");
286 CC2420_DISABLE_FIFOP_INT();
287 CC2420_FIFOP_INT_INIT();
296 SET_RESET_INACTIVE();
301 strobe(CC2420_SXOSCON);
304 reg = getreg(CC2420_MDMCTRL0);
306 #if CC2420_CONF_AUTOACK
307 reg |= AUTOACK | ADR_DECODE;
309 reg &= ~(AUTOACK | ADR_DECODE);
311 setreg(CC2420_MDMCTRL0, reg);
322 setreg(CC2420_MDMCTRL1, CORR_THR(20));
323 reg = getreg(CC2420_RXCTRL1);
325 setreg(CC2420_RXCTRL1, reg);
328 setreg(CC2420_IOCFG0, FIFOP_THR(127));
331 reg = getreg(CC2420_SECCTRL0);
332 reg &= ~RXFIFO_PROTECTION;
333 setreg(CC2420_SECCTRL0, reg);
335 cc2420_set_pan_addr(0xffff, 0x0000,
NULL);
336 cc2420_set_channel(26);
345 cc2420_transmit(
unsigned short payload_len)
349 #if CC2420_CONF_CHECKSUM
356 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
358 txpower = cc2420_get_txpower();
360 set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
363 total_len = payload_len + AUX_LEN;
372 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT
373 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!!
375 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT
379 strobe(CC2420_SRXON);
380 BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 10);
381 strobe(CC2420_STXONCCA);
383 strobe(CC2420_STXON);
385 for(i = LOOP_20_SYMBOLS; i > 0; i--) {
386 if(CC2420_SFD_IS_1) {
388 rtimer_clock_t sfd_timestamp;
389 sfd_timestamp = cc2420_sfd_start_time;
390 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
391 PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) {
393 CC2420_WRITE_RAM(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2);
397 if(!(status() & BV(CC2420_TX_ACTIVE))) {
402 return RADIO_TX_COLLISION;
405 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
407 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
410 BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
412 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
413 ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower());
415 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
417 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
424 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
426 set_txpower(txpower & 0xff);
436 RIMESTATS_ADD(contentiondrop);
437 PRINTF(
"cc2420: do_send() transmission never started\n");
439 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
441 set_txpower(txpower & 0xff);
445 return RADIO_TX_COLLISION;
449 cc2420_prepare(
const void *payload,
unsigned short payload_len)
452 #if CC2420_CONF_CHECKSUM
457 PRINTF(
"cc2420: sending %d bytes\n", payload_len);
465 strobe(CC2420_SFLUSHTX);
467 #if CC2420_CONF_CHECKSUM
468 checksum =
crc16_data(payload, payload_len, 0);
470 total_len = payload_len + AUX_LEN;
471 CC2420_WRITE_FIFO_BUF(&total_len, 1);
472 CC2420_WRITE_FIFO_BUF(payload, payload_len);
473 #if CC2420_CONF_CHECKSUM
474 CC2420_WRITE_FIFO_BUF(&checksum, CHECKSUM_LEN);
482 cc2420_send(
const void *payload,
unsigned short payload_len)
484 cc2420_prepare(payload, payload_len);
485 return cc2420_transmit(payload_len);
494 if(receive_on == 0) {
511 if(status() & BV(CC2420_TX_ACTIVE)) {
538 cc2420_get_channel(
void)
544 cc2420_set_channel(
int c)
555 f = 5 * (c - 11) + 357 + 0x4000;
559 BUSYWAIT_UNTIL((status() & (BV(CC2420_XOSC16M_STABLE))), RTIMER_SECOND / 10);
562 BUSYWAIT_UNTIL(!(status() & BV(CC2420_TX_ACTIVE)), RTIMER_SECOND / 10);
564 setreg(CC2420_FSCTRL, f);
569 strobe(CC2420_SRXON);
577 cc2420_set_pan_addr(
unsigned pan,
579 const uint8_t *ieee_addr)
589 BUSYWAIT_UNTIL(status() & (BV(CC2420_XOSC16M_STABLE)), RTIMER_SECOND / 10);
593 CC2420_WRITE_RAM(&tmp, CC2420RAM_PANID, 2);
595 tmp[0] = addr & 0xff;
597 CC2420_WRITE_RAM(&tmp, CC2420RAM_SHORTADDR, 2);
598 if(ieee_addr !=
NULL) {
601 for (f = 0; f < 8; f++) {
602 tmp_addr[7 - f] = ieee_addr[f];
604 CC2420_WRITE_RAM(tmp_addr, CC2420RAM_IEEEADDR, 8);
612 #if CC2420_TIMETABLE_PROFILING
613 #define cc2420_timetable_size 16
614 TIMETABLE(cc2420_timetable);
615 TIMETABLE_AGGREGATE(aggregate_time, 10);
618 cc2420_interrupt(
void)
620 PRINTF(
"got packet\n");
621 CC2420_CLEAR_FIFOP_INT();
623 #if CC2420_TIMETABLE_PROFILING
624 timetable_clear(&cc2420_timetable);
625 TIMETABLE_TIMESTAMP(cc2420_timetable,
"interrupt");
628 last_packet_timestamp = cc2420_sfd_start_time;
630 cc2420_packets_seen++;
639 PRINTF(
"cc2420_process: started\n");
643 #if CC2420_TIMETABLE_PROFILING
644 TIMETABLE_TIMESTAMP(cc2420_timetable,
"poll");
647 PRINTF(
"cc2420_process: calling receiver callback\n");
650 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
654 CC2420_GET_STATUS(i);
656 regi= getreg(CC2420_IOCFG0);
657 PRINTF(
"cc2420_process: fifo threshold: %u, got %u bytes, CC2420 satus:%u \n",regi,len,i);
663 NETSTACK_RDC.input();
664 #if CC2420_TIMETABLE_PROFILING
665 TIMETABLE_TIMESTAMP(cc2420_timetable,
"end");
666 timetable_aggregate_compute_detailed(&aggregate_time,
668 timetable_clear(&cc2420_timetable);
676 cc2420_read(
void *buf,
unsigned short bufsize)
680 #if CC2420_CONF_CHECKSUM
684 if(!CC2420_FIFOP_IS_1) {
695 cc2420_packets_read++;
699 if(len > CC2420_MAX_PACKET_LEN) {
702 RIMESTATS_ADD(badsynch);
709 RIMESTATS_ADD(tooshort);
714 if(len - AUX_LEN > bufsize) {
716 RIMESTATS_ADD(toolong);
721 getrxdata(buf, len - AUX_LEN);
722 #if CC2420_CONF_CHECKSUM
723 getrxdata(&checksum, CHECKSUM_LEN);
725 getrxdata(footer, FOOTER_LEN);
727 #if CC2420_CONF_CHECKSUM
728 if(checksum !=
crc16_data(buf, len - AUX_LEN, 0)) {
729 PRINTF(
"checksum failed 0x%04x != 0x%04x\n",
733 if(footer[1] & FOOTER1_CRC_OK &&
734 checksum ==
crc16_data(buf, len - AUX_LEN, 0)) {
736 if(footer[1] & FOOTER1_CRC_OK) {
738 cc2420_last_rssi = footer[0];
739 cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
742 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
743 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
748 RIMESTATS_ADD(badcrc);
752 if(CC2420_FIFOP_IS_1) {
753 if(!CC2420_FIFO_IS_1) {
770 return len - AUX_LEN;
774 cc2420_set_txpower(uint8_t power)
782 cc2420_get_txpower(
void)
786 power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
795 int radio_was_off = 0;
807 BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
809 rssi = (int)((
signed char)getreg(CC2420_RSSI));
827 cc2420_cca_valid(
void)
834 valid = !!(status() & BV(CC2420_RSSI_VALID));
843 int radio_was_off = 0;
868 BUSYWAIT_UNTIL(status() & BV(CC2420_RSSI_VALID), RTIMER_SECOND / 100);
870 cca = CC2420_CCA_IS_1;
880 cc2420_receiving_packet(
void)
882 return CC2420_SFD_IS_1;
888 return CC2420_FIFOP_IS_1;
892 cc2420_set_cca_threshold(
int value)
894 uint16_t shifted = value << 8;
896 setreg(CC2420_RSSI, shifted);