44 #include "cc2420_const.h" 49 enum write_ram_order {
59 #define PRINTF(...) printf(__VA_ARGS__) 61 #define PRINTF(...) do {} while (0) 64 #define DEBUG_LEDS DEBUG 68 #define LEDS_ON(x) leds_on(x) 69 #define LEDS_OFF(x) leds_off(x) 78 struct output_config {
83 static const struct output_config output_power[] = {
93 #define OUTPUT_NUM (sizeof(output_power) / sizeof(struct output_config)) 94 #define OUTPUT_POWER_MAX 0 95 #define OUTPUT_POWER_MIN -25 97 void cc2420_arch_init(
void);
100 rtimer_clock_t cc2420_time_of_arrival, cc2420_time_of_departure;
102 int cc2420_authority_level_of_sender;
104 volatile uint8_t cc2420_sfd_counter;
105 volatile uint16_t cc2420_sfd_start_time;
106 volatile uint16_t cc2420_sfd_end_time;
108 static volatile uint16_t last_packet_timestamp;
110 PROCESS(cc2420_process,
"CC2420 driver");
113 #define AUTOACK (1 << 4) 114 #define AUTOCRC (1 << 5) 115 #define ADR_DECODE (1 << 11) 116 #define RXFIFO_PROTECTION (1 << 9) 117 #define CORR_THR(n) (((n) & 0x1f) << 6) 118 #define FIFOP_THR(n) ((n) & 0x7f) 119 #define RXBPF_LOCUR (1 << 13); 122 int cc2420_off(
void);
124 static int cc2420_read(
void *buf,
unsigned short bufsize);
126 static int cc2420_prepare(
const void *data,
unsigned short len);
127 static int cc2420_transmit(
unsigned short len);
128 static int cc2420_send(
const void *data,
unsigned short len);
130 static int cc2420_receiving_packet(
void);
131 static int pending_packet(
void);
132 static int get_cca_threshold(
void);
133 static int cc2420_cca(
void);
134 static uint16_t getreg(
enum cc2420_register regname);
136 static void set_frame_filtering(uint8_t enable);
137 static void set_poll_mode(uint8_t enable);
138 static void set_send_on_cca(uint8_t enable);
139 static void set_auto_ack(uint8_t enable);
141 signed char cc2420_last_rssi;
142 uint8_t cc2420_last_correlation;
144 static uint8_t receive_on;
148 static uint8_t
volatile poll_mode = 0;
150 static uint8_t send_on_cca = WITH_SEND_CCA;
152 static radio_result_t
158 return RADIO_RESULT_INVALID_VALUE;
161 case RADIO_PARAM_POWER_MODE:
162 *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
163 return RADIO_RESULT_OK;
164 case RADIO_PARAM_CHANNEL:
165 *value = cc2420_get_channel();
166 return RADIO_RESULT_OK;
167 case RADIO_PARAM_RX_MODE:
169 if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
172 if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
173 *value |= RADIO_RX_MODE_AUTOACK;
176 *value |= RADIO_RX_MODE_POLL_MODE;
178 return RADIO_RESULT_OK;
179 case RADIO_PARAM_TX_MODE:
184 return RADIO_RESULT_OK;
185 case RADIO_PARAM_TXPOWER:
186 v = cc2420_get_txpower();
187 *value = OUTPUT_POWER_MIN;
189 for(i = 0; i < OUTPUT_NUM; i++) {
190 if(v >= output_power[i].
config) {
191 *value = output_power[i].power;
195 return RADIO_RESULT_OK;
196 case RADIO_PARAM_CCA_THRESHOLD:
197 *value = get_cca_threshold() + RSSI_OFFSET;
198 return RADIO_RESULT_OK;
199 case RADIO_PARAM_RSSI:
201 *value = cc2420_rssi();
202 return RADIO_RESULT_OK;
203 case RADIO_PARAM_LAST_RSSI:
205 *value = cc2420_last_rssi;
206 return RADIO_RESULT_OK;
207 case RADIO_PARAM_LAST_LINK_QUALITY:
209 *value = cc2420_last_correlation;
210 return RADIO_RESULT_OK;
211 case RADIO_CONST_CHANNEL_MIN:
213 return RADIO_RESULT_OK;
214 case RADIO_CONST_CHANNEL_MAX:
216 return RADIO_RESULT_OK;
217 case RADIO_CONST_TXPOWER_MIN:
218 *value = OUTPUT_POWER_MIN;
219 return RADIO_RESULT_OK;
220 case RADIO_CONST_TXPOWER_MAX:
221 *value = OUTPUT_POWER_MAX;
222 return RADIO_RESULT_OK;
224 return RADIO_RESULT_NOT_SUPPORTED;
228 static radio_result_t
234 case RADIO_PARAM_POWER_MODE:
235 if(value == RADIO_POWER_MODE_ON) {
237 return RADIO_RESULT_OK;
239 if(value == RADIO_POWER_MODE_OFF) {
241 return RADIO_RESULT_OK;
243 return RADIO_RESULT_INVALID_VALUE;
244 case RADIO_PARAM_CHANNEL:
245 if(value < 11 || value > 26) {
246 return RADIO_RESULT_INVALID_VALUE;
248 cc2420_set_channel(value);
249 return RADIO_RESULT_OK;
250 case RADIO_PARAM_RX_MODE:
252 RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
253 return RADIO_RESULT_INVALID_VALUE;
256 set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
257 set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
258 return RADIO_RESULT_OK;
259 case RADIO_PARAM_TX_MODE:
261 return RADIO_RESULT_INVALID_VALUE;
264 return RADIO_RESULT_OK;
265 case RADIO_PARAM_TXPOWER:
266 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
267 return RADIO_RESULT_INVALID_VALUE;
270 for(i = 1; i < OUTPUT_NUM; i++) {
271 if(value > output_power[i].power) {
276 return RADIO_RESULT_OK;
277 case RADIO_PARAM_CCA_THRESHOLD:
278 cc2420_set_cca_threshold(value - RSSI_OFFSET);
279 return RADIO_RESULT_OK;
281 return RADIO_RESULT_NOT_SUPPORTED;
285 static radio_result_t
286 get_object(radio_param_t param,
void *dest,
size_t size)
288 if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
289 #if CC2420_CONF_SFD_TIMESTAMPS 290 if(size !=
sizeof(rtimer_clock_t) || !dest) {
291 return RADIO_RESULT_INVALID_VALUE;
293 *(rtimer_clock_t*)dest = cc2420_sfd_start_time;
294 return RADIO_RESULT_OK;
296 return RADIO_RESULT_NOT_SUPPORTED;
299 return RADIO_RESULT_NOT_SUPPORTED;
302 static radio_result_t
303 set_object(radio_param_t param,
const void *src,
size_t size)
305 return RADIO_RESULT_NOT_SUPPORTED;
316 cc2420_receiving_packet,
329 strobe(
enum cc2420_register regname)
333 CC2420_SPI_DISABLE();
338 getreg(
enum cc2420_register regname)
343 SPI_WRITE(regname | 0x40);
344 value = (uint8_t)SPI_RXBUF;
347 value = SPI_RXBUF << 8;
351 CC2420_SPI_DISABLE();
362 setreg(
enum cc2420_register regname, uint16_t value)
365 SPI_WRITE_FAST(regname);
366 SPI_WRITE_FAST((uint8_t) (value >> 8));
367 SPI_WRITE_FAST((uint8_t) (value & 0xff));
368 SPI_WAITFORTx_ENDED();
370 CC2420_SPI_DISABLE();
374 read_ram(uint8_t *buffer, uint16_t adr, uint16_t count)
379 SPI_WRITE(0x80 | ((adr) & 0x7f));
380 SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20);
382 for(i = 0; i < count; i++) {
383 SPI_READ(((uint8_t*) buffer)[i]);
385 CC2420_SPI_DISABLE();
390 write_ram(
const uint8_t *buffer,
393 enum write_ram_order order)
398 SPI_WRITE_FAST(0x80 | (adr & 0x7f));
399 SPI_WRITE_FAST((adr >> 1) & 0xc0);
400 if(order == WRITE_RAM_IN_ORDER) {
401 for(i = 0; i < count; i++) {
402 SPI_WRITE_FAST((buffer)[i]);
405 for(i = count; i > 0; i--) {
406 SPI_WRITE_FAST((buffer)[i - 1]);
409 SPI_WAITFORTx_ENDED();
410 CC2420_SPI_DISABLE();
414 write_fifo_buf(
const uint8_t *buffer, uint16_t count)
419 SPI_WRITE_FAST(CC2420_TXFIFO);
420 for(i = 0; i < count; i++) {
421 SPI_WRITE_FAST((buffer)[i]);
423 SPI_WAITFORTx_ENDED();
424 CC2420_SPI_DISABLE();
434 SPI_WRITE(CC2420_SNOP);
436 CC2420_SPI_DISABLE();
442 getrxdata(uint8_t *buffer,
int count)
447 SPI_WRITE(CC2420_RXFIFO | 0x40);
449 for(i = 0; i < count; i++) {
453 CC2420_SPI_DISABLE();
461 getrxdata(&dummy, 1);
462 strobe(CC2420_SFLUSHRX);
463 strobe(CC2420_SFLUSHRX);
470 wait_for_status(uint8_t status_bit)
474 while(!(get_status() & status_bit)
475 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
479 wait_for_transmission(
void)
483 while((get_status() & BV(CC2420_TX_ACTIVE))
484 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
491 CC2420_ENABLE_FIFOP_INT();
494 strobe(CC2420_SRXON);
496 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
507 wait_for_transmission();
509 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
510 strobe(CC2420_SRFOFF);
512 CC2420_DISABLE_FIFOP_INT();
515 if(!CC2420_FIFOP_IS_1) {
520 static uint8_t locked, lock_on, lock_off;
521 #define GET_LOCK() locked++ 522 static void RELEASE_LOCK(
void) {
540 setreg(CC2420_SECCTRL0, 0);
541 setreg(CC2420_SECCTRL1, 0);
545 set_key(
const uint8_t *key)
549 write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE);
555 encrypt(uint8_t *plaintext_and_result)
559 write_ram(plaintext_and_result,
565 while(get_status() & BV(CC2420_ENC_BUSY));
567 read_ram(plaintext_and_result, CC2420RAM_SABUF, 16);
578 set_txpower(uint8_t power)
582 reg = getreg(CC2420_TXCTRL);
583 reg = (reg & 0xffe0) | (power & 0x1f);
584 setreg(CC2420_TXCTRL, reg);
594 CC2420_DISABLE_FIFOP_INT();
595 CC2420_FIFOP_INT_INIT();
604 SET_RESET_INACTIVE();
609 strobe(CC2420_SXOSCON);
611 wait_for_status(BV(CC2420_XOSC16M_STABLE));
614 set_auto_ack(CC2420_CONF_AUTOACK);
615 set_frame_filtering(CC2420_CONF_AUTOACK);
620 reg = getreg(CC2420_MDMCTRL0);
622 setreg(CC2420_MDMCTRL0, reg);
633 setreg(CC2420_MDMCTRL1, CORR_THR(20));
634 reg = getreg(CC2420_RXCTRL1);
636 setreg(CC2420_RXCTRL1, reg);
639 setreg(CC2420_IOCFG0, FIFOP_THR(127));
643 cc2420_set_pan_addr(0xffff, 0x0000, NULL);
645 cc2420_set_cca_threshold(CC2420_CONF_CCA_THRESH);
656 cc2420_transmit(
unsigned short payload_len)
669 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT 670 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!! 672 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT 676 strobe(CC2420_SRXON);
677 wait_for_status(BV(CC2420_RSSI_VALID));
678 strobe(CC2420_STXONCCA);
680 strobe(CC2420_STXON);
682 for(i = LOOP_20_SYMBOLS; i > 0; i--) {
683 if(CC2420_SFD_IS_1) {
684 if(!(get_status() & BV(CC2420_TX_ACTIVE))) {
689 return RADIO_TX_COLLISION;
692 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
694 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
697 wait_for_transmission();
699 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
701 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
715 PRINTF(
"cc2420: do_send() transmission never started\n");
718 return RADIO_TX_COLLISION;
722 cc2420_prepare(
const void *payload,
unsigned short payload_len)
728 PRINTF(
"cc2420: sending %d bytes\n", payload_len);
734 strobe(CC2420_SFLUSHTX);
736 total_len = payload_len + CHECKSUM_LEN;
737 write_fifo_buf(&total_len, 1);
738 write_fifo_buf(payload, payload_len);
745 cc2420_send(
const void *payload,
unsigned short payload_len)
747 cc2420_prepare(payload, payload_len);
748 return cc2420_transmit(payload_len);
755 if(receive_on == 0) {
772 if(get_status() & BV(CC2420_TX_ACTIVE)) {
799 cc2420_get_channel(
void)
805 cc2420_set_channel(
int c)
816 f = 5 * (c - 11) + 357 + 0x4000;
819 wait_for_transmission();
821 setreg(CC2420_FSCTRL, f);
826 strobe(CC2420_SRXON);
834 cc2420_set_pan_addr(
unsigned pan,
836 const uint8_t *ieee_addr)
840 write_ram((uint8_t *) &pan, CC2420RAM_PANID, 2, WRITE_RAM_IN_ORDER);
841 write_ram((uint8_t *) &addr, CC2420RAM_SHORTADDR, 2, WRITE_RAM_IN_ORDER);
843 if(ieee_addr != NULL) {
844 write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE);
855 CC2420_CLEAR_FIFOP_INT();
858 last_packet_timestamp = cc2420_sfd_start_time;
867 PRINTF(
"cc2420_process: started\n");
872 PRINTF(
"cc2420_process: calling receiver callback\n");
875 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
880 NETSTACK_MAC.
input();
887 cc2420_read(
void *buf,
unsigned short bufsize)
889 uint8_t footer[FOOTER_LEN];
892 if(!CC2420_FIFOP_IS_1) {
900 if(len > CC2420_MAX_PACKET_LEN) {
902 }
else if(len <= FOOTER_LEN) {
904 }
else if(len - FOOTER_LEN > bufsize) {
907 getrxdata((uint8_t *) buf, len - FOOTER_LEN);
908 getrxdata(footer, FOOTER_LEN);
910 if(footer[1] & FOOTER1_CRC_OK) {
911 cc2420_last_rssi = footer[0] + RSSI_OFFSET;
912 cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
917 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
918 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
925 if(CC2420_FIFOP_IS_1) {
926 if(!CC2420_FIFO_IS_1) {
939 return len - FOOTER_LEN;
956 cc2420_get_txpower(
void)
960 power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
969 int radio_was_off = 0;
981 wait_for_status(BV(CC2420_RSSI_VALID));
983 rssi = (int)((
signed char) getreg(CC2420_RSSI));
997 int radio_was_off = 0;
1022 wait_for_status(BV(CC2420_RSSI_VALID));
1024 cca = CC2420_CCA_IS_1;
1034 cc2420_receiving_packet(
void)
1036 return CC2420_SFD_IS_1;
1040 pending_packet(
void)
1042 return CC2420_FIFOP_IS_1;
1046 get_cca_threshold(
void)
1051 value = (int8_t)(getreg(CC2420_RSSI) >> 8);
1057 cc2420_set_cca_threshold(
int value)
1059 uint16_t shifted = value << 8;
1061 setreg(CC2420_RSSI, shifted);
1067 set_auto_ack(uint8_t enable)
1071 uint16_t reg = getreg(CC2420_MDMCTRL0);
1078 setreg(CC2420_MDMCTRL0, reg);
1084 set_frame_filtering(uint8_t enable)
1089 uint16_t reg = getreg(CC2420_MDMCTRL0);
1093 reg &= ~(ADR_DECODE);
1096 setreg(CC2420_MDMCTRL0, reg);
1102 set_poll_mode(uint8_t enable)
1108 CC2420_CLEAR_FIFOP_INT();
1109 CC2420_DISABLE_FIFOP_INT();
1112 CC2420_FIFOP_INT_INIT();
1113 CC2420_ENABLE_FIFOP_INT();
1114 CC2420_CLEAR_FIFOP_INT();
1121 set_send_on_cca(uint8_t enable)
1123 send_on_cca = enable;
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
CC2420 driver header file
#define PROCESS(name, strname)
Declare a process.
void packetbuf_clear(void)
Clear and reset the packetbuf.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Header file for the energy estimation mechanism
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
int cc2420_interrupt(void)
Interrupt function, called from the simple-cc2420-arch driver.
Structure of AES drivers.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
void(* encrypt)(uint8_t *plaintext_and_result)
Encrypts.
The structure of a device driver for a radio in Contiki.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
#define RTIMER_NOW()
Get the current clock time.
void cc2420_set_txpower(uint8_t power)
void(* input)(void)
Callback for getting notified of incoming packet.
void process_poll(struct process *p)
Request a process to be polled.
int(* off)(void)
Turn the radio off.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
void clock_delay(unsigned int i)
Obsolete delay function but we implement it here since some code still uses it.
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
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.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Header file for the LED HAL.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
int(* on)(void)
Turn the radio on.
void process_start(struct process *p, process_data_t data)
Start a process.
void(* set_key)(const uint8_t *key)
Sets the current key.