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);
99 int cc2420_authority_level_of_sender;
101 volatile uint8_t cc2420_sfd_counter;
102 volatile uint16_t cc2420_sfd_start_time;
103 volatile uint16_t cc2420_sfd_end_time;
105 static volatile uint16_t last_packet_timestamp;
112 #define MAX_PAYLOAD_LEN (127 - CHECKSUM_LEN) 114 PROCESS(cc2420_process,
"CC2420 driver");
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) 127 int cc2420_off(
void);
129 static int cc2420_read(
void *buf,
unsigned short bufsize);
131 static int cc2420_prepare(
const void *data,
unsigned short len);
132 static int cc2420_transmit(
unsigned short len);
133 static int cc2420_send(
const void *data,
unsigned short len);
135 static int cc2420_receiving_packet(
void);
136 static int pending_packet(
void);
137 static int get_cca_threshold(
void);
138 static int cc2420_cca(
void);
139 static uint16_t getreg(
enum cc2420_register regname);
141 static void set_frame_filtering(uint8_t enable);
142 static void set_poll_mode(uint8_t enable);
143 static void set_send_on_cca(uint8_t enable);
144 static void set_auto_ack(uint8_t enable);
146 static void set_test_mode(uint8_t enable, uint8_t modulated);
148 signed char cc2420_last_rssi;
149 uint8_t cc2420_last_correlation;
151 static uint8_t receive_on;
155 static uint8_t
volatile poll_mode = 0;
157 static uint8_t send_on_cca = WITH_SEND_CCA;
159 static radio_result_t
165 return RADIO_RESULT_INVALID_VALUE;
168 case RADIO_PARAM_POWER_MODE:
169 if((getreg(CC2420_MDMCTRL1) & TX_MODE) & 0x08) {
170 *value = RADIO_POWER_MODE_CARRIER_ON;
172 *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
174 return RADIO_RESULT_OK;
175 case RADIO_PARAM_CHANNEL:
176 *value = cc2420_get_channel();
177 return RADIO_RESULT_OK;
178 case RADIO_PARAM_RX_MODE:
180 if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
183 if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
184 *value |= RADIO_RX_MODE_AUTOACK;
187 *value |= RADIO_RX_MODE_POLL_MODE;
189 return RADIO_RESULT_OK;
190 case RADIO_PARAM_TX_MODE:
195 return RADIO_RESULT_OK;
196 case RADIO_PARAM_TXPOWER:
197 v = cc2420_get_txpower();
198 *value = OUTPUT_POWER_MIN;
200 for(i = 0; i < OUTPUT_NUM; i++) {
201 if(v >= output_power[i].
config) {
202 *value = output_power[i].power;
206 return RADIO_RESULT_OK;
207 case RADIO_PARAM_CCA_THRESHOLD:
208 *value = get_cca_threshold() + RSSI_OFFSET;
209 return RADIO_RESULT_OK;
210 case RADIO_PARAM_RSSI:
212 *value = cc2420_rssi();
213 return RADIO_RESULT_OK;
214 case RADIO_PARAM_LAST_RSSI:
216 *value = cc2420_last_rssi;
217 return RADIO_RESULT_OK;
218 case RADIO_PARAM_LAST_LINK_QUALITY:
220 *value = cc2420_last_correlation;
221 return RADIO_RESULT_OK;
222 case RADIO_CONST_CHANNEL_MIN:
224 return RADIO_RESULT_OK;
225 case RADIO_CONST_CHANNEL_MAX:
227 return RADIO_RESULT_OK;
228 case RADIO_CONST_TXPOWER_MIN:
229 *value = OUTPUT_POWER_MIN;
230 return RADIO_RESULT_OK;
231 case RADIO_CONST_TXPOWER_MAX:
232 *value = OUTPUT_POWER_MAX;
233 return RADIO_RESULT_OK;
234 case RADIO_CONST_MAX_PAYLOAD_LEN:
236 return RADIO_RESULT_OK;
238 return RADIO_RESULT_NOT_SUPPORTED;
242 static radio_result_t
248 case RADIO_PARAM_POWER_MODE:
249 if(value == RADIO_POWER_MODE_ON) {
251 return RADIO_RESULT_OK;
253 if(value == RADIO_POWER_MODE_OFF) {
255 return RADIO_RESULT_OK;
257 if(value == RADIO_POWER_MODE_CARRIER_ON ||
258 value == RADIO_POWER_MODE_CARRIER_OFF) {
259 set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0);
260 return RADIO_RESULT_OK;
262 return RADIO_RESULT_INVALID_VALUE;
263 case RADIO_PARAM_CHANNEL:
264 if(value < 11 || value > 26) {
265 return RADIO_RESULT_INVALID_VALUE;
267 cc2420_set_channel(value);
268 return RADIO_RESULT_OK;
269 case RADIO_PARAM_RX_MODE:
271 RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
272 return RADIO_RESULT_INVALID_VALUE;
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;
278 case RADIO_PARAM_TX_MODE:
280 return RADIO_RESULT_INVALID_VALUE;
283 return RADIO_RESULT_OK;
284 case RADIO_PARAM_TXPOWER:
285 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
286 return RADIO_RESULT_INVALID_VALUE;
289 for(i = 1; i < OUTPUT_NUM; i++) {
290 if(value > output_power[i].power) {
295 return RADIO_RESULT_OK;
296 case RADIO_PARAM_CCA_THRESHOLD:
297 cc2420_set_cca_threshold(value - RSSI_OFFSET);
298 return RADIO_RESULT_OK;
300 return RADIO_RESULT_NOT_SUPPORTED;
304 static radio_result_t
305 get_object(radio_param_t param,
void *dest,
size_t size)
307 if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
308 #if CC2420_CONF_SFD_TIMESTAMPS 309 if(size !=
sizeof(rtimer_clock_t) || !dest) {
310 return RADIO_RESULT_INVALID_VALUE;
312 *(rtimer_clock_t*)dest = cc2420_sfd_start_time;
313 return RADIO_RESULT_OK;
315 return RADIO_RESULT_NOT_SUPPORTED;
318 return RADIO_RESULT_NOT_SUPPORTED;
321 static radio_result_t
322 set_object(radio_param_t param,
const void *src,
size_t size)
324 return RADIO_RESULT_NOT_SUPPORTED;
335 cc2420_receiving_packet,
348 strobe(
enum cc2420_register regname)
352 CC2420_SPI_DISABLE();
357 getreg(
enum cc2420_register regname)
362 SPI_WRITE(regname | 0x40);
363 value = (uint8_t)SPI_RXBUF;
366 value = SPI_RXBUF << 8;
370 CC2420_SPI_DISABLE();
381 setreg(
enum cc2420_register regname, uint16_t value)
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();
389 CC2420_SPI_DISABLE();
393 read_ram(uint8_t *buffer, uint16_t adr, uint16_t count)
398 SPI_WRITE(0x80 | ((adr) & 0x7f));
399 SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20);
401 for(i = 0; i < count; i++) {
402 SPI_READ(((uint8_t*) buffer)[i]);
404 CC2420_SPI_DISABLE();
409 write_ram(
const uint8_t *buffer,
412 enum write_ram_order order)
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]);
424 for(i = count; i > 0; i--) {
425 SPI_WRITE_FAST((buffer)[i - 1]);
428 SPI_WAITFORTx_ENDED();
429 CC2420_SPI_DISABLE();
433 write_fifo_buf(
const uint8_t *buffer, uint16_t count)
438 SPI_WRITE_FAST(CC2420_TXFIFO);
439 for(i = 0; i < count; i++) {
440 SPI_WRITE_FAST((buffer)[i]);
442 SPI_WAITFORTx_ENDED();
443 CC2420_SPI_DISABLE();
453 SPI_WRITE(CC2420_SNOP);
455 CC2420_SPI_DISABLE();
461 getrxdata(uint8_t *buffer,
int count)
466 SPI_WRITE(CC2420_RXFIFO | 0x40);
468 for(i = 0; i < count; i++) {
472 CC2420_SPI_DISABLE();
480 getrxdata(&dummy, 1);
481 strobe(CC2420_SFLUSHRX);
482 strobe(CC2420_SFLUSHRX);
489 wait_for_status(uint8_t status_bit)
493 while(!(get_status() & status_bit)
498 wait_for_transmission(
void)
502 while((get_status() & BV(CC2420_TX_ACTIVE))
510 CC2420_ENABLE_FIFOP_INT();
513 strobe(CC2420_SRXON);
515 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
526 wait_for_transmission();
528 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
529 strobe(CC2420_SRFOFF);
531 CC2420_DISABLE_FIFOP_INT();
534 if(!CC2420_FIFOP_IS_1) {
539 static uint8_t locked, lock_on, lock_off;
540 #define GET_LOCK() locked++ 541 static void RELEASE_LOCK(
void) {
559 setreg(CC2420_SECCTRL0, 0);
560 setreg(CC2420_SECCTRL1, 0);
564 set_key(
const uint8_t *key)
568 write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE);
574 encrypt(uint8_t *plaintext_and_result)
578 write_ram(plaintext_and_result,
584 while(get_status() & BV(CC2420_ENC_BUSY));
586 read_ram(plaintext_and_result, CC2420RAM_SABUF, 16);
597 set_txpower(uint8_t power)
601 reg = getreg(CC2420_TXCTRL);
602 reg = (reg & 0xffe0) | (power & 0x1f);
603 setreg(CC2420_TXCTRL, reg);
613 CC2420_DISABLE_FIFOP_INT();
614 CC2420_FIFOP_INT_INIT();
623 SET_RESET_INACTIVE();
628 strobe(CC2420_SXOSCON);
630 wait_for_status(BV(CC2420_XOSC16M_STABLE));
633 set_auto_ack(CC2420_CONF_AUTOACK);
634 set_frame_filtering(CC2420_CONF_AUTOACK);
639 reg = getreg(CC2420_MDMCTRL0);
641 setreg(CC2420_MDMCTRL0, reg);
652 setreg(CC2420_MDMCTRL1, CORR_THR(20));
653 reg = getreg(CC2420_RXCTRL1);
655 setreg(CC2420_RXCTRL1, reg);
658 setreg(CC2420_IOCFG0, FIFOP_THR(127));
662 cc2420_set_pan_addr(0xffff, 0x0000, NULL);
664 cc2420_set_cca_threshold(CC2420_CONF_CCA_THRESH);
675 cc2420_transmit(
unsigned short payload_len)
679 if(payload_len > MAX_PAYLOAD_LEN) {
692 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT 693 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!! 695 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT 699 strobe(CC2420_SRXON);
700 wait_for_status(BV(CC2420_RSSI_VALID));
701 strobe(CC2420_STXONCCA);
703 strobe(CC2420_STXON);
705 for(i = LOOP_20_SYMBOLS; i > 0; i--) {
706 if(CC2420_SFD_IS_1) {
707 if(!(get_status() & BV(CC2420_TX_ACTIVE))) {
712 return RADIO_TX_COLLISION;
715 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
717 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
720 wait_for_transmission();
722 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
724 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
738 PRINTF(
"cc2420: do_send() transmission never started\n");
741 return RADIO_TX_COLLISION;
745 cc2420_prepare(
const void *payload,
unsigned short payload_len)
749 if(payload_len > MAX_PAYLOAD_LEN) {
755 PRINTF(
"cc2420: sending %d bytes\n", payload_len);
761 strobe(CC2420_SFLUSHTX);
763 total_len = payload_len + CHECKSUM_LEN;
764 write_fifo_buf(&total_len, 1);
765 write_fifo_buf(payload, payload_len);
772 cc2420_send(
const void *payload,
unsigned short payload_len)
774 cc2420_prepare(payload, payload_len);
775 return cc2420_transmit(payload_len);
782 if(receive_on == 0) {
799 if(get_status() & BV(CC2420_TX_ACTIVE)) {
826 cc2420_get_channel(
void)
832 cc2420_set_channel(
int c)
843 f = 5 * (c - 11) + 357 + 0x4000;
846 wait_for_transmission();
848 setreg(CC2420_FSCTRL, f);
853 strobe(CC2420_SRXON);
861 cc2420_set_pan_addr(
unsigned pan,
863 const uint8_t *ieee_addr)
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);
870 if(ieee_addr != NULL) {
871 write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE);
882 CC2420_CLEAR_FIFOP_INT();
885 last_packet_timestamp = cc2420_sfd_start_time;
894 PRINTF(
"cc2420_process: started\n");
899 PRINTF(
"cc2420_process: calling receiver callback\n");
902 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
907 NETSTACK_MAC.
input();
914 cc2420_read(
void *buf,
unsigned short bufsize)
916 uint8_t footer[FOOTER_LEN];
919 if(!CC2420_FIFOP_IS_1) {
927 if(len > CC2420_MAX_PACKET_LEN) {
929 }
else if(len <= FOOTER_LEN) {
931 }
else if(len - FOOTER_LEN > bufsize) {
934 getrxdata((uint8_t *) buf, len - FOOTER_LEN);
935 getrxdata(footer, FOOTER_LEN);
937 if(footer[1] & FOOTER1_CRC_OK) {
938 cc2420_last_rssi = footer[0] + RSSI_OFFSET;
939 cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
944 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
945 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
952 if(CC2420_FIFOP_IS_1) {
953 if(!CC2420_FIFO_IS_1) {
966 return len - FOOTER_LEN;
983 cc2420_get_txpower(
void)
987 power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
996 int radio_was_off = 0;
1008 wait_for_status(BV(CC2420_RSSI_VALID));
1010 rssi = (int)((
signed char) getreg(CC2420_RSSI));
1011 rssi += RSSI_OFFSET;
1024 int radio_was_off = 0;
1049 wait_for_status(BV(CC2420_RSSI_VALID));
1051 cca = CC2420_CCA_IS_1;
1061 cc2420_receiving_packet(
void)
1063 return CC2420_SFD_IS_1;
1067 pending_packet(
void)
1069 return CC2420_FIFOP_IS_1;
1073 get_cca_threshold(
void)
1078 value = (int8_t)(getreg(CC2420_RSSI) >> 8);
1084 cc2420_set_cca_threshold(
int value)
1086 uint16_t shifted = value << 8;
1088 setreg(CC2420_RSSI, shifted);
1094 set_auto_ack(uint8_t enable)
1098 uint16_t reg = getreg(CC2420_MDMCTRL0);
1105 setreg(CC2420_MDMCTRL0, reg);
1111 set_frame_filtering(uint8_t enable)
1116 uint16_t reg = getreg(CC2420_MDMCTRL0);
1120 reg &= ~(ADR_DECODE);
1123 setreg(CC2420_MDMCTRL0, reg);
1129 set_poll_mode(uint8_t enable)
1135 CC2420_CLEAR_FIFOP_INT();
1136 CC2420_DISABLE_FIFOP_INT();
1139 CC2420_FIFOP_INT_INIT();
1140 CC2420_ENABLE_FIFOP_INT();
1141 CC2420_CLEAR_FIFOP_INT();
1148 set_send_on_cca(uint8_t enable)
1150 send_on_cca = enable;
1156 static uint16_t prev_MDMCTRL1, prev_DACTST;
1157 static uint8_t was_on;
1160 set_test_mode(uint8_t enable, uint8_t modulated)
1163 get_value(RADIO_PARAM_POWER_MODE, &mode);
1166 if(mode == RADIO_POWER_MODE_CARRIER_ON) {
1169 was_on = (mode == RADIO_POWER_MODE_ON);
1171 prev_MDMCTRL1 = getreg(CC2420_MDMCTRL1);
1172 setreg(CC2420_MDMCTRL1, 0x050C);
1174 prev_DACTST = getreg(CC2420_DACTST);
1175 setreg(CC2420_DACTST, 0x1800);
1178 strobe(CC2420_STXON);
1180 if(mode != RADIO_POWER_MODE_CARRIER_ON) {
1183 strobe(CC2420_SRFOFF);
1185 setreg(CC2420_DACTST, prev_DACTST);
1187 setreg(CC2420_MDMCTRL1, prev_MDMCTRL1);
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 RTIMER_SECOND
Number of rtimer ticks for 1 second.
#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.