47 #include "contiki-msb430.h"
48 #include "cc1020-internal.h"
50 #include "lib/random.h"
59 #define PRINTF(...) printf(__VA_ARGS__)
64 #define SEND_TIMEOUT 10
66 static int cc1020_calibrate(
void);
67 static int cc1020_setupTX(
int);
68 static int cc1020_setupRX(
int);
69 static void cc1020_setupPD(
void);
70 static void cc1020_wakeupTX(
int);
71 static void cc1020_wakeupRX(
int);
72 static uint8_t cc1020_read_reg(uint8_t addr);
73 static void cc1020_write_reg(uint8_t addr, uint8_t adata);
74 static void cc1020_load_config(
const uint8_t *);
75 static void cc1020_reset(
void);
77 static const uint8_t syncword[SYNCWORD_SIZE] = {0xD3, 0x91};
80 static volatile enum cc1020_state cc1020_state = CC1020_OFF;
81 static volatile uint8_t cc1020_rxbuf[HDR_SIZE + CC1020_BUFFERSIZE];
82 static uint8_t cc1020_txbuf[PREAMBLE_SIZE + SYNCWORD_SIZE + HDR_SIZE +
83 CC1020_BUFFERSIZE + TAIL_SIZE];
86 static uint8_t cc1020_rxlen;
87 static uint8_t cc1020_txlen;
90 static volatile uint8_t rssi;
93 static uint8_t cc1020_pa_power = PA_POWER;
95 static volatile char dma_done;
98 static int cc1020_init(
void);
99 static int cc1020_prepare(
const void *payload,
unsigned short payload_len);
100 static int cc1020_transmit(
unsigned short transmit_len);
101 static int cc1020_send(
const void *payload,
unsigned short payload_len);
102 static int cc1020_read(
void *buf,
unsigned short buf_len);
103 static int cc1020_channel_clear(
void);
104 static int cc1020_receiving_packet(
void);
105 static int cc1020_pending_packet(
void);
106 static int cc1020_on(
void);
107 static int cc1020_off(
void);
116 cc1020_channel_clear,
117 cc1020_receiving_packet,
118 cc1020_pending_packet,
123 #define MS_DELAY(x) clock_delay(354 * (x))
125 PROCESS(cc1020_receiver_process,
"CC1020 receiver");
139 if((cc1020_state & CC1020_TURN_OFF) && (cc1020_txlen == 0)) {
142 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
153 cc1020_load_config(cc1020_config_19200);
156 memset(cc1020_txbuf, PREAMBLE, PREAMBLE_SIZE);
157 cc1020_txbuf[PREAMBLE_SIZE] = syncword[0];
158 cc1020_txbuf[PREAMBLE_SIZE + 1] = syncword[1];
161 cc1020_wakeupRX(RX_CURRENT);
162 if(!cc1020_calibrate()) {
163 PRINTF(
"cc1020: rx calibration failed\n");
168 cc1020_wakeupTX(TX_CURRENT);
169 if(!cc1020_calibrate()) {
170 PRINTF(
"cc1020: tx calibration failed\n");
178 dma_subscribe(0, dma_callback);
192 IFG1 &= ~(UTXIE0 | URXIE0);
193 ME1 &= ~(UTXE0 | URXE0);
195 UCTL0 |= CHAR | SYNC;
210 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
213 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
214 cc1020_wakeupRX(RX_CURRENT);
215 cc1020_setupRX(RX_CURRENT);
228 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
236 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
237 cc1020_wakeupTX(TX_CURRENT);
238 cc1020_setupTX(TX_CURRENT);
244 CC1020_SET_OPSTATE(CC1020_TX);
248 cc1020_set_power(uint8_t pa_power)
250 cc1020_pa_power = pa_power;
254 cc1020_prepare(
const void *payload,
unsigned short payload_len)
260 cc1020_transmit(
unsigned short transmit_len)
266 cc1020_send(
const void *buf,
unsigned short len)
268 int normal_header = HDR_SIZE + len;
269 uint16_t rxcrc = 0xffff;
270 rtimer_clock_t timeout_time;
272 timeout_time =
RTIMER_NOW() + RTIMER_SECOND / 1000 * SEND_TIMEOUT;
273 while(cc1020_state & CC1020_RX_RECEIVING) {
274 if(RTIMER_CLOCK_LT(timeout_time,
RTIMER_NOW())) {
275 PRINTF(
"cc1020: transmission blocked by reception in progress\n");
280 if(cc1020_state == CC1020_OFF) {
284 if(len > CC1020_BUFFERSIZE) {
289 cc1020_txlen = PREAMBLE_SIZE + SYNCWORD_SIZE;
292 cc1020_txbuf[cc1020_txlen++] = 0x00;
293 cc1020_txbuf[cc1020_txlen++] = normal_header + CRC_SIZE;
296 rxcrc =
crc16_add(normal_header & 0xff, rxcrc);
297 rxcrc =
crc16_add((normal_header >> 8) & 0xff, rxcrc);
302 memcpy((
char *)cc1020_txbuf + cc1020_txlen, buf, len);
306 cc1020_txbuf[cc1020_txlen++] = rxcrc >> 8;
307 cc1020_txbuf[cc1020_txlen++] = rxcrc & 0xff;
310 cc1020_txbuf[cc1020_txlen++] = TAIL;
311 cc1020_txbuf[cc1020_txlen++] = TAIL;
318 dma_transfer((
unsigned char *)&TXBUF0, cc1020_txbuf, cc1020_txlen);
321 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
326 if(cc1020_state & CC1020_TURN_OFF) {
336 cc1020_read(
void *buf,
unsigned short size)
340 if(cc1020_rxlen <= HDR_SIZE) {
344 len = cc1020_rxlen - HDR_SIZE;
346 RIMESTATS_ADD(toolong);
350 memcpy(buf, (
char *)cc1020_rxbuf + HDR_SIZE, len);
358 cc1020_channel_clear(
void)
360 return (cc1020_read_reg(CC1020_STATUS) & CARRIER_SENSE);
364 cc1020_receiving_packet(
void)
366 return cc1020_state & CC1020_RX_RECEIVING;
370 cc1020_pending_packet(
void)
372 return cc1020_state & CC1020_RX_PROCESSING;
378 if(cc1020_state == CC1020_OFF) {
380 }
else if(cc1020_state & CC1020_TURN_OFF) {
381 cc1020_state &= ~CC1020_TURN_OFF;
393 if(cc1020_state != CC1020_OFF) {
394 if(cc1020_state & CC1020_RX_SEARCHING) {
401 cc1020_state = CC1020_OFF;
404 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
405 cc1020_state = CC1020_OFF;
407 cc1020_state |= CC1020_TURN_OFF;
414 cc1020_get_rssi(
void)
416 return (cc1020_read_reg(CC1020_RSS) & 0x7F);
420 cc1020_get_packet_rssi(
void)
432 ev = PROCESS_EVENT_NONE;
436 uint16_t expected_crc = 0xffff;
439 actual_crc = (cc1020_rxbuf[cc1020_rxlen - CRC_SIZE] << 8) |
440 cc1020_rxbuf[cc1020_rxlen - CRC_SIZE + 1];
441 cc1020_rxlen -= CRC_SIZE;
443 expected_crc =
crc16_add(cc1020_rxlen & 0xff, expected_crc);
444 expected_crc =
crc16_add((cc1020_rxlen >> 8) & 0xff, expected_crc);
445 expected_crc =
crc16_data((
char *)&cc1020_rxbuf[HDR_SIZE],
446 cc1020_rxlen - HDR_SIZE, expected_crc);
448 if(expected_crc == actual_crc) {
451 NETSTACK_RDC.input();
453 RIMESTATS_ADD(badcrc);
461 interrupt(UART0RX_VECTOR) cc1020_rxhandler(
void)
463 static signed char syncbs;
476 static unsigned char pktlen;
478 if(cc1020_state & CC1020_RX_SEARCHING) {
479 shiftbuf.b1 = shiftbuf.b2;
480 shiftbuf.b2 = shiftbuf.b3;
481 shiftbuf.b3 = shiftbuf.b4;
482 shiftbuf.b4 = RXBUF0;
483 if(shiftbuf.i1 == 0xAAD3 && shiftbuf.b3 == 0x91) {
486 cc1020_rxbuf[cc1020_rxlen++] = shiftbuf.b4;
487 }
else if(shiftbuf.i1 == 0x5569 && shiftbuf.i2 == 0xC880) {
490 }
else if(shiftbuf.i1 == 0xAAB4 && shiftbuf.i2 == 0xE440) {
493 }
else if(shiftbuf.i1 == 0x555A && shiftbuf.i2 == 0x7220) {
496 }
else if(shiftbuf.i1 == 0xAAAD && shiftbuf.i2 == 0x3910) {
499 }
else if(shiftbuf.i1 == 0x5556 && shiftbuf.i2 == 0x9C88) {
502 }
else if(shiftbuf.i1 == 0xAAAB && shiftbuf.i2 == 0x4E44) {
505 }
else if(shiftbuf.i1 == 0x5555 && shiftbuf.i2 == 0xA722) {
511 rssi = cc1020_get_rssi();
512 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_RECEIVING);
513 }
else if(cc1020_state & CC1020_RX_RECEIVING) {
515 cc1020_rxbuf[cc1020_rxlen] = RXBUF0;
517 shiftbuf.b3 = shiftbuf.b4;
518 shiftbuf.b4 = RXBUF0;
520 shiftbuf.i1 = shiftbuf.i2 << -syncbs;
521 cc1020_rxbuf[cc1020_rxlen] = shiftbuf.b1;
523 shiftbuf.i1 = shiftbuf.i2 >> syncbs;
524 cc1020_rxbuf[cc1020_rxlen] = shiftbuf.b2;
530 if(cc1020_rxlen == HDR_SIZE) {
531 pktlen = ((
struct cc1020_header *)cc1020_rxbuf)->length;
532 if(pktlen == 0 || pktlen >
sizeof (cc1020_rxbuf)) {
534 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
536 }
else if(cc1020_rxlen > HDR_SIZE) {
537 if(cc1020_rxlen == pktlen) {
540 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_PROCESSING);
541 _BIC_SR_IRQ(LPM3_bits);
549 cc1020_write_reg(uint8_t addr, uint8_t adata)
558 for(i = 0; i < 7; i++) {
579 for(i = 0; i < 8; i++) {
596 cc1020_read_reg(uint8_t addr)
605 for(i = 0; i < 7; i++) {
626 for(i = 0; i < 8; i++) {
643 cc1020_load_config(
const uint8_t * config)
647 for(i = 0; i < 0x28; i++)
648 cc1020_write_reg(i, config[i]);
655 cc1020_write_reg(CC1020_MAIN, 0x0FU & ~0x01U);
658 cc1020_write_reg(CC1020_MAIN, 0x1F);
662 cc1020_calibrate(
void)
664 unsigned int timeout_cnt;
667 cc1020_write_reg(CC1020_PA_POWER, 0x00);
670 cc1020_write_reg(CC1020_CALIBRATE, 0xB5);
671 while((cc1020_read_reg(CC1020_STATUS) & CAL_COMPLETE) == 0);
674 for(timeout_cnt = LOCK_TIMEOUT; timeout_cnt > 0; timeout_cnt--) {
675 if(cc1020_read_reg(CC1020_STATUS) & LOCK_CONTINUOUS) {
681 cc1020_write_reg(CC1020_PA_POWER, cc1020_pa_power);
684 return (cc1020_read_reg(CC1020_STATUS) & LOCK_CONTINUOUS) == LOCK_CONTINUOUS;
694 for(i = LOCK_TIMEOUT; i > 0; i--) {
695 lock_status = cc1020_read_reg(CC1020_STATUS) & LOCK_CONTINUOUS;
701 if(lock_status == LOCK_CONTINUOUS) {
705 return cc1020_calibrate() ? LOCK_RECAL_OK : LOCK_NOK;
709 cc1020_setupRX(
int analog)
714 cc1020_write_reg(CC1020_MAIN, 0x01);
715 lock_status = cc1020_lock();
718 cc1020_write_reg(CC1020_INTERFACE, 0x02);
725 cc1020_setupTX(
int analog)
730 cc1020_write_reg(CC1020_MAIN, 0xC1);
731 lock_status = cc1020_lock();
734 cc1020_write_reg(CC1020_PA_POWER, cc1020_pa_power);
737 cc1020_write_reg(CC1020_INTERFACE, 0x01);
750 cc1020_write_reg(CC1020_MAIN,
751 RESET_N | BIAS_PD | FS_PD | XOSC_PD | PD_MODE_1);
754 cc1020_write_reg(CC1020_PA_POWER, 0x00);
756 cc1020_write_reg(CC1020_POWERDOWN, 0x1F);
760 cc1020_wakeupRX(
int analog)
763 cc1020_write_reg(CC1020_MAIN, 0x1B);
766 cc1020_write_reg(CC1020_ANALOG, analog);
775 cc1020_write_reg(CC1020_MAIN, 0x19);
778 cc1020_write_reg(CC1020_MAIN, 0x11);
782 cc1020_wakeupTX(
int analog)
785 cc1020_write_reg(CC1020_MAIN, 0xDB);
788 cc1020_write_reg(CC1020_ANALOG, analog);
797 cc1020_write_reg(CC1020_MAIN, 0xD9);
801 cc1020_write_reg(CC1020_MAIN, 0xD1);