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;
107 PROCESS(cc2420_process,
"CC2420 driver");
110 #define AUTOACK (1 << 4) 111 #define AUTOCRC (1 << 5) 112 #define ADR_DECODE (1 << 11) 113 #define RXFIFO_PROTECTION (1 << 9) 114 #define CORR_THR(n) (((n) & 0x1f) << 6) 115 #define FIFOP_THR(n) ((n) & 0x7f) 116 #define RXBPF_LOCUR (1 << 13); 117 #define TX_MODE (3 << 2) 120 int cc2420_off(
void);
122 static int cc2420_read(
void *buf,
unsigned short bufsize);
124 static int cc2420_prepare(
const void *data,
unsigned short len);
125 static int cc2420_transmit(
unsigned short len);
126 static int cc2420_send(
const void *data,
unsigned short len);
128 static int cc2420_receiving_packet(
void);
129 static int pending_packet(
void);
130 static int get_cca_threshold(
void);
131 static int cc2420_cca(
void);
132 static uint16_t getreg(
enum cc2420_register regname);
134 static void set_frame_filtering(uint8_t enable);
135 static void set_poll_mode(uint8_t enable);
136 static void set_send_on_cca(uint8_t enable);
137 static void set_auto_ack(uint8_t enable);
139 static void set_test_mode(uint8_t enable, uint8_t modulated);
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 if((getreg(CC2420_MDMCTRL1) & TX_MODE) & 0x08) {
163 *value = RADIO_POWER_MODE_CARRIER_ON;
165 *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
167 return RADIO_RESULT_OK;
168 case RADIO_PARAM_CHANNEL:
169 *value = cc2420_get_channel();
170 return RADIO_RESULT_OK;
171 case RADIO_PARAM_RX_MODE:
173 if(getreg(CC2420_MDMCTRL0) & ADR_DECODE) {
176 if(getreg(CC2420_MDMCTRL0) & AUTOACK) {
177 *value |= RADIO_RX_MODE_AUTOACK;
180 *value |= RADIO_RX_MODE_POLL_MODE;
182 return RADIO_RESULT_OK;
183 case RADIO_PARAM_TX_MODE:
188 return RADIO_RESULT_OK;
189 case RADIO_PARAM_TXPOWER:
190 v = cc2420_get_txpower();
191 *value = OUTPUT_POWER_MIN;
193 for(i = 0; i < OUTPUT_NUM; i++) {
194 if(v >= output_power[i].
config) {
195 *value = output_power[i].power;
199 return RADIO_RESULT_OK;
200 case RADIO_PARAM_CCA_THRESHOLD:
201 *value = get_cca_threshold() + RSSI_OFFSET;
202 return RADIO_RESULT_OK;
203 case RADIO_PARAM_RSSI:
205 *value = cc2420_rssi();
206 return RADIO_RESULT_OK;
207 case RADIO_PARAM_LAST_RSSI:
209 *value = cc2420_last_rssi;
210 return RADIO_RESULT_OK;
211 case RADIO_PARAM_LAST_LINK_QUALITY:
213 *value = cc2420_last_correlation;
214 return RADIO_RESULT_OK;
215 case RADIO_CONST_CHANNEL_MIN:
217 return RADIO_RESULT_OK;
218 case RADIO_CONST_CHANNEL_MAX:
220 return RADIO_RESULT_OK;
221 case RADIO_CONST_TXPOWER_MIN:
222 *value = OUTPUT_POWER_MIN;
223 return RADIO_RESULT_OK;
224 case RADIO_CONST_TXPOWER_MAX:
225 *value = OUTPUT_POWER_MAX;
226 return RADIO_RESULT_OK;
228 return RADIO_RESULT_NOT_SUPPORTED;
232 static radio_result_t
238 case RADIO_PARAM_POWER_MODE:
239 if(value == RADIO_POWER_MODE_ON) {
241 return RADIO_RESULT_OK;
243 if(value == RADIO_POWER_MODE_OFF) {
245 return RADIO_RESULT_OK;
247 if(value == RADIO_POWER_MODE_CARRIER_ON ||
248 value == RADIO_POWER_MODE_CARRIER_OFF) {
249 set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0);
250 return RADIO_RESULT_OK;
252 return RADIO_RESULT_INVALID_VALUE;
253 case RADIO_PARAM_CHANNEL:
254 if(value < 11 || value > 26) {
255 return RADIO_RESULT_INVALID_VALUE;
257 cc2420_set_channel(value);
258 return RADIO_RESULT_OK;
259 case RADIO_PARAM_RX_MODE:
261 RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
262 return RADIO_RESULT_INVALID_VALUE;
265 set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
266 set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
267 return RADIO_RESULT_OK;
268 case RADIO_PARAM_TX_MODE:
270 return RADIO_RESULT_INVALID_VALUE;
273 return RADIO_RESULT_OK;
274 case RADIO_PARAM_TXPOWER:
275 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
276 return RADIO_RESULT_INVALID_VALUE;
279 for(i = 1; i < OUTPUT_NUM; i++) {
280 if(value > output_power[i].power) {
285 return RADIO_RESULT_OK;
286 case RADIO_PARAM_CCA_THRESHOLD:
287 cc2420_set_cca_threshold(value - RSSI_OFFSET);
288 return RADIO_RESULT_OK;
290 return RADIO_RESULT_NOT_SUPPORTED;
294 static radio_result_t
295 get_object(radio_param_t param,
void *dest,
size_t size)
297 if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
298 #if CC2420_CONF_SFD_TIMESTAMPS 299 if(size !=
sizeof(rtimer_clock_t) || !dest) {
300 return RADIO_RESULT_INVALID_VALUE;
302 *(rtimer_clock_t*)dest = cc2420_sfd_start_time;
303 return RADIO_RESULT_OK;
305 return RADIO_RESULT_NOT_SUPPORTED;
308 return RADIO_RESULT_NOT_SUPPORTED;
311 static radio_result_t
312 set_object(radio_param_t param,
const void *src,
size_t size)
314 return RADIO_RESULT_NOT_SUPPORTED;
325 cc2420_receiving_packet,
338 strobe(
enum cc2420_register regname)
342 CC2420_SPI_DISABLE();
347 getreg(
enum cc2420_register regname)
352 SPI_WRITE(regname | 0x40);
353 value = (uint8_t)SPI_RXBUF;
356 value = SPI_RXBUF << 8;
360 CC2420_SPI_DISABLE();
371 setreg(
enum cc2420_register regname, uint16_t value)
374 SPI_WRITE_FAST(regname);
375 SPI_WRITE_FAST((uint8_t) (value >> 8));
376 SPI_WRITE_FAST((uint8_t) (value & 0xff));
377 SPI_WAITFORTx_ENDED();
379 CC2420_SPI_DISABLE();
383 read_ram(uint8_t *buffer, uint16_t adr, uint16_t count)
388 SPI_WRITE(0x80 | ((adr) & 0x7f));
389 SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20);
391 for(i = 0; i < count; i++) {
392 SPI_READ(((uint8_t*) buffer)[i]);
394 CC2420_SPI_DISABLE();
399 write_ram(
const uint8_t *buffer,
402 enum write_ram_order order)
407 SPI_WRITE_FAST(0x80 | (adr & 0x7f));
408 SPI_WRITE_FAST((adr >> 1) & 0xc0);
409 if(order == WRITE_RAM_IN_ORDER) {
410 for(i = 0; i < count; i++) {
411 SPI_WRITE_FAST((buffer)[i]);
414 for(i = count; i > 0; i--) {
415 SPI_WRITE_FAST((buffer)[i - 1]);
418 SPI_WAITFORTx_ENDED();
419 CC2420_SPI_DISABLE();
423 write_fifo_buf(
const uint8_t *buffer, uint16_t count)
428 SPI_WRITE_FAST(CC2420_TXFIFO);
429 for(i = 0; i < count; i++) {
430 SPI_WRITE_FAST((buffer)[i]);
432 SPI_WAITFORTx_ENDED();
433 CC2420_SPI_DISABLE();
443 SPI_WRITE(CC2420_SNOP);
445 CC2420_SPI_DISABLE();
451 getrxdata(uint8_t *buffer,
int count)
456 SPI_WRITE(CC2420_RXFIFO | 0x40);
458 for(i = 0; i < count; i++) {
462 CC2420_SPI_DISABLE();
470 getrxdata(&dummy, 1);
471 strobe(CC2420_SFLUSHRX);
472 strobe(CC2420_SFLUSHRX);
479 wait_for_status(uint8_t status_bit)
483 while(!(get_status() & status_bit)
484 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
488 wait_for_transmission(
void)
492 while((get_status() & BV(CC2420_TX_ACTIVE))
493 && RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + (RTIMER_SECOND / 10)));
500 CC2420_ENABLE_FIFOP_INT();
503 strobe(CC2420_SRXON);
505 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
516 wait_for_transmission();
518 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
519 strobe(CC2420_SRFOFF);
521 CC2420_DISABLE_FIFOP_INT();
524 if(!CC2420_FIFOP_IS_1) {
529 static uint8_t locked, lock_on, lock_off;
530 #define GET_LOCK() locked++ 531 static void RELEASE_LOCK(
void) {
549 setreg(CC2420_SECCTRL0, 0);
550 setreg(CC2420_SECCTRL1, 0);
554 set_key(
const uint8_t *key)
558 write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE);
564 encrypt(uint8_t *plaintext_and_result)
568 write_ram(plaintext_and_result,
574 while(get_status() & BV(CC2420_ENC_BUSY));
576 read_ram(plaintext_and_result, CC2420RAM_SABUF, 16);
587 set_txpower(uint8_t power)
591 reg = getreg(CC2420_TXCTRL);
592 reg = (reg & 0xffe0) | (power & 0x1f);
593 setreg(CC2420_TXCTRL, reg);
603 CC2420_DISABLE_FIFOP_INT();
604 CC2420_FIFOP_INT_INIT();
613 SET_RESET_INACTIVE();
618 strobe(CC2420_SXOSCON);
620 wait_for_status(BV(CC2420_XOSC16M_STABLE));
623 set_auto_ack(CC2420_CONF_AUTOACK);
624 set_frame_filtering(CC2420_CONF_AUTOACK);
629 reg = getreg(CC2420_MDMCTRL0);
631 setreg(CC2420_MDMCTRL0, reg);
642 setreg(CC2420_MDMCTRL1, CORR_THR(20));
643 reg = getreg(CC2420_RXCTRL1);
645 setreg(CC2420_RXCTRL1, reg);
648 setreg(CC2420_IOCFG0, FIFOP_THR(127));
652 cc2420_set_pan_addr(0xffff, 0x0000, NULL);
654 cc2420_set_cca_threshold(CC2420_CONF_CCA_THRESH);
665 cc2420_transmit(
unsigned short payload_len)
669 if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
682 #ifndef CC2420_CONF_SYMBOL_LOOP_COUNT 683 #error CC2420_CONF_SYMBOL_LOOP_COUNT needs to be set!!! 685 #define LOOP_20_SYMBOLS CC2420_CONF_SYMBOL_LOOP_COUNT 689 strobe(CC2420_SRXON);
690 wait_for_status(BV(CC2420_RSSI_VALID));
691 strobe(CC2420_STXONCCA);
693 strobe(CC2420_STXON);
695 for(i = LOOP_20_SYMBOLS; i > 0; i--) {
696 if(CC2420_SFD_IS_1) {
697 if(!(get_status() & BV(CC2420_TX_ACTIVE))) {
702 return RADIO_TX_COLLISION;
705 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
707 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
710 wait_for_transmission();
712 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
714 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
728 PRINTF(
"cc2420: do_send() transmission never started\n");
731 return RADIO_TX_COLLISION;
735 cc2420_prepare(
const void *payload,
unsigned short payload_len)
739 if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
745 PRINTF(
"cc2420: sending %d bytes\n", payload_len);
751 strobe(CC2420_SFLUSHTX);
753 total_len = payload_len + CHECKSUM_LEN;
754 write_fifo_buf(&total_len, 1);
755 write_fifo_buf(payload, payload_len);
762 cc2420_send(
const void *payload,
unsigned short payload_len)
764 cc2420_prepare(payload, payload_len);
765 return cc2420_transmit(payload_len);
772 if(receive_on == 0) {
789 if(get_status() & BV(CC2420_TX_ACTIVE)) {
816 cc2420_get_channel(
void)
822 cc2420_set_channel(
int c)
833 f = 5 * (c - 11) + 357 + 0x4000;
836 wait_for_transmission();
838 setreg(CC2420_FSCTRL, f);
843 strobe(CC2420_SRXON);
851 cc2420_set_pan_addr(
unsigned pan,
853 const uint8_t *ieee_addr)
857 write_ram((uint8_t *) &pan, CC2420RAM_PANID, 2, WRITE_RAM_IN_ORDER);
858 write_ram((uint8_t *) &addr, CC2420RAM_SHORTADDR, 2, WRITE_RAM_IN_ORDER);
860 if(ieee_addr != NULL) {
861 write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE);
872 CC2420_CLEAR_FIFOP_INT();
875 last_packet_timestamp = cc2420_sfd_start_time;
884 PRINTF(
"cc2420_process: started\n");
889 PRINTF(
"cc2420_process: calling receiver callback\n");
892 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, last_packet_timestamp);
897 NETSTACK_MAC.
input();
904 cc2420_read(
void *buf,
unsigned short bufsize)
906 uint8_t footer[FOOTER_LEN];
909 if(!CC2420_FIFOP_IS_1) {
917 if(len > CC2420_MAX_PACKET_LEN) {
919 }
else if(len <= FOOTER_LEN) {
921 }
else if(len - FOOTER_LEN > bufsize) {
924 getrxdata((uint8_t *) buf, len - FOOTER_LEN);
925 getrxdata(footer, FOOTER_LEN);
927 if(footer[1] & FOOTER1_CRC_OK) {
928 cc2420_last_rssi = footer[0] + RSSI_OFFSET;
929 cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION;
934 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi);
935 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation);
942 if(CC2420_FIFOP_IS_1) {
943 if(!CC2420_FIFO_IS_1) {
956 return len - FOOTER_LEN;
973 cc2420_get_txpower(
void)
977 power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
986 int radio_was_off = 0;
998 wait_for_status(BV(CC2420_RSSI_VALID));
1000 rssi = (int)((
signed char) getreg(CC2420_RSSI));
1001 rssi += RSSI_OFFSET;
1014 int radio_was_off = 0;
1039 wait_for_status(BV(CC2420_RSSI_VALID));
1041 cca = CC2420_CCA_IS_1;
1051 cc2420_receiving_packet(
void)
1053 return CC2420_SFD_IS_1;
1057 pending_packet(
void)
1059 return CC2420_FIFOP_IS_1;
1063 get_cca_threshold(
void)
1068 value = (int8_t)(getreg(CC2420_RSSI) >> 8);
1074 cc2420_set_cca_threshold(
int value)
1076 uint16_t shifted = value << 8;
1078 setreg(CC2420_RSSI, shifted);
1084 set_auto_ack(uint8_t enable)
1088 uint16_t reg = getreg(CC2420_MDMCTRL0);
1095 setreg(CC2420_MDMCTRL0, reg);
1101 set_frame_filtering(uint8_t enable)
1106 uint16_t reg = getreg(CC2420_MDMCTRL0);
1110 reg &= ~(ADR_DECODE);
1113 setreg(CC2420_MDMCTRL0, reg);
1119 set_poll_mode(uint8_t enable)
1125 CC2420_CLEAR_FIFOP_INT();
1126 CC2420_DISABLE_FIFOP_INT();
1129 CC2420_FIFOP_INT_INIT();
1130 CC2420_ENABLE_FIFOP_INT();
1131 CC2420_CLEAR_FIFOP_INT();
1138 set_send_on_cca(uint8_t enable)
1140 send_on_cca = enable;
1146 static uint16_t prev_MDMCTRL1, prev_DACTST;
1147 static uint8_t was_on;
1150 set_test_mode(uint8_t enable, uint8_t modulated)
1153 get_value(RADIO_PARAM_POWER_MODE, &mode);
1156 if(mode == RADIO_POWER_MODE_CARRIER_ON) {
1159 was_on = (mode == RADIO_POWER_MODE_ON);
1161 prev_MDMCTRL1 = getreg(CC2420_MDMCTRL1);
1162 setreg(CC2420_MDMCTRL1, 0x050C);
1164 prev_DACTST = getreg(CC2420_DACTST);
1165 setreg(CC2420_DACTST, 0x1800);
1168 strobe(CC2420_STXON);
1170 if(mode != RADIO_POWER_MODE_CARRIER_ON) {
1173 strobe(CC2420_SRFOFF);
1175 setreg(CC2420_DACTST, prev_DACTST);
1177 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 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.