00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <stdio.h>
00043 #include <string.h>
00044 #include <signal.h>
00045
00046 #include "contiki.h"
00047 #include "contiki-msb430.h"
00048 #include "cc1020-internal.h"
00049 #include "cc1020.h"
00050 #include "lib/random.h"
00051 #include "lib/crc16.h"
00052 #include "net/rime/rimestats.h"
00053 #include "dev/dma.h"
00054 #include "sys/energest.h"
00055
00056 #define DEBUG 0
00057 #if DEBUG
00058 #include <stdio.h>
00059 #define PRINTF(...) printf(__VA_ARGS__)
00060 #else
00061 #define PRINTF(...)
00062 #endif
00063
00064 #define SEND_TIMEOUT 10
00065
00066 static int cc1020_calibrate(void);
00067 static int cc1020_setupTX(int);
00068 static int cc1020_setupRX(int);
00069 static void cc1020_setupPD(void);
00070 static void cc1020_wakeupTX(int);
00071 static void cc1020_wakeupRX(int);
00072 static uint8_t cc1020_read_reg(uint8_t addr);
00073 static void cc1020_write_reg(uint8_t addr, uint8_t adata);
00074 static void cc1020_load_config(const uint8_t *);
00075 static void cc1020_reset(void);
00076
00077 static const uint8_t syncword[SYNCWORD_SIZE] = {0xD3, 0x91};
00078
00079
00080 static volatile enum cc1020_state cc1020_state = CC1020_OFF;
00081 static volatile uint8_t cc1020_rxbuf[HDR_SIZE + CC1020_BUFFERSIZE];
00082 static uint8_t cc1020_txbuf[PREAMBLE_SIZE + SYNCWORD_SIZE + HDR_SIZE +
00083 CC1020_BUFFERSIZE + TAIL_SIZE];
00084
00085
00086 static uint8_t cc1020_rxlen;
00087 static uint8_t cc1020_txlen;
00088
00089
00090 static volatile uint8_t rssi;
00091
00092
00093 static uint8_t cc1020_pa_power = PA_POWER;
00094
00095 static volatile char dma_done;
00096
00097
00098 static int cc1020_init(void);
00099 static int cc1020_prepare(const void *payload, unsigned short payload_len);
00100 static int cc1020_transmit(unsigned short transmit_len);
00101 static int cc1020_send(const void *payload, unsigned short payload_len);
00102 static int cc1020_read(void *buf, unsigned short buf_len);
00103 static int cc1020_channel_clear(void);
00104 static int cc1020_receiving_packet(void);
00105 static int cc1020_pending_packet(void);
00106 static int cc1020_on(void);
00107 static int cc1020_off(void);
00108
00109 const struct radio_driver cc1020_driver =
00110 {
00111 cc1020_init,
00112 cc1020_prepare,
00113 cc1020_transmit,
00114 cc1020_send,
00115 cc1020_read,
00116 cc1020_channel_clear,
00117 cc1020_receiving_packet,
00118 cc1020_pending_packet,
00119 cc1020_on,
00120 cc1020_off
00121 };
00122
00123 #define MS_DELAY(x) clock_delay(354 * (x))
00124
00125 PROCESS(cc1020_receiver_process, "CC1020 receiver");
00126
00127 static void
00128 dma_callback(void)
00129 {
00130 dma_done = 1;
00131 }
00132
00133 static void
00134 reset_receiver(void)
00135 {
00136
00137 cc1020_rxlen = 0;
00138
00139 if((cc1020_state & CC1020_TURN_OFF) && (cc1020_txlen == 0)) {
00140 cc1020_off();
00141 } else {
00142 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
00143 cc1020_set_rx();
00144 ENABLE_RX_IRQ();
00145 }
00146 }
00147
00148 static int
00149 cc1020_init(void)
00150 {
00151 cc1020_setupPD();
00152 cc1020_reset();
00153 cc1020_load_config(cc1020_config_19200);
00154
00155
00156 memset(cc1020_txbuf, PREAMBLE, PREAMBLE_SIZE);
00157 cc1020_txbuf[PREAMBLE_SIZE] = syncword[0];
00158 cc1020_txbuf[PREAMBLE_SIZE + 1] = syncword[1];
00159
00160
00161 cc1020_wakeupRX(RX_CURRENT);
00162 if(!cc1020_calibrate()) {
00163 PRINTF("cc1020: rx calibration failed\n");
00164 return -1;
00165 }
00166
00167
00168 cc1020_wakeupTX(TX_CURRENT);
00169 if(!cc1020_calibrate()) {
00170 PRINTF("cc1020: tx calibration failed\n");
00171 return -1;
00172 }
00173
00174
00175 cc1020_setupPD();
00176
00177 process_start(&cc1020_receiver_process, NULL);
00178 dma_subscribe(0, dma_callback);
00179
00180 return 0;
00181 }
00182
00183 void
00184 cc1020_set_rx(void)
00185 {
00186 int s;
00187
00188 s = splhigh();
00189
00190
00191 P3SEL &= ~0x3E;
00192 IFG1 &= ~(UTXIE0 | URXIE0);
00193 ME1 &= ~(UTXE0 | URXE0);
00194 UCTL0 = SWRST;
00195 UCTL0 |= CHAR | SYNC;
00196
00197
00198 UTCTL0 = CKPL | STC;
00199 URCTL0 = 0x00;
00200 UBR00 = 0x00;
00201 UBR10 = 0x00;
00202 UMCTL0 = 0x00;
00203 ME1 |= URXE0;
00204 P3SEL |= 0x0A;
00205 UCTL0 &= ~SWRST;
00206 splx(s);
00207
00208
00209 cc1020_rxlen = 0;
00210 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
00211
00212
00213 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00214 cc1020_wakeupRX(RX_CURRENT);
00215 cc1020_setupRX(RX_CURRENT);
00216 LNA_POWER_ON();
00217
00218
00219 IE1 |= URXIE0;
00220 }
00221
00222 void
00223 cc1020_set_tx(void)
00224 {
00225 int s;
00226
00227
00228 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00229 LNA_POWER_OFF();
00230 s = splhigh();
00231 DISABLE_RX_IRQ();
00232 P3SEL &= ~0x02;
00233 splx(s);
00234
00235
00236 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00237 cc1020_wakeupTX(TX_CURRENT);
00238 cc1020_setupTX(TX_CURRENT);
00239 P3SEL |= 0x0C;
00240 U0CTL |= SWRST;
00241 IFG1 &= ~UTXIFG0;
00242
00243
00244 CC1020_SET_OPSTATE(CC1020_TX);
00245 }
00246
00247 void
00248 cc1020_set_power(uint8_t pa_power)
00249 {
00250 cc1020_pa_power = pa_power;
00251 }
00252
00253 static int
00254 cc1020_prepare(const void *payload, unsigned short payload_len)
00255 {
00256 return -1;
00257 }
00258
00259 static int
00260 cc1020_transmit(unsigned short transmit_len)
00261 {
00262 return 0;
00263 }
00264
00265 static int
00266 cc1020_send(const void *buf, unsigned short len)
00267 {
00268 int normal_header = HDR_SIZE + len;
00269 uint16_t rxcrc = 0xffff;
00270 rtimer_clock_t timeout_time;
00271
00272 timeout_time = RTIMER_NOW() + RTIMER_SECOND / 1000 * SEND_TIMEOUT;
00273 while(cc1020_state & CC1020_RX_RECEIVING) {
00274 if(RTIMER_CLOCK_LT(timeout_time, RTIMER_NOW())) {
00275 PRINTF("cc1020: transmission blocked by reception in progress\n");
00276 return RADIO_TX_ERR;
00277 }
00278 }
00279
00280 if(cc1020_state == CC1020_OFF) {
00281 return RADIO_TX_ERR;
00282 }
00283
00284 if(len > CC1020_BUFFERSIZE) {
00285 return RADIO_TX_ERR;
00286 }
00287
00288
00289 cc1020_txlen = PREAMBLE_SIZE + SYNCWORD_SIZE;
00290
00291
00292 cc1020_txbuf[cc1020_txlen++] = 0x00;
00293 cc1020_txbuf[cc1020_txlen++] = normal_header + CRC_SIZE;
00294
00295
00296 rxcrc = crc16_add(normal_header & 0xff, rxcrc);
00297 rxcrc = crc16_add((normal_header >> 8) & 0xff, rxcrc);
00298
00299 rxcrc = crc16_data(buf, len, rxcrc);
00300
00301
00302 memcpy((char *)cc1020_txbuf + cc1020_txlen, buf, len);
00303 cc1020_txlen += len;
00304
00305
00306 cc1020_txbuf[cc1020_txlen++] = rxcrc >> 8;
00307 cc1020_txbuf[cc1020_txlen++] = rxcrc & 0xff;
00308
00309
00310 cc1020_txbuf[cc1020_txlen++] = TAIL;
00311 cc1020_txbuf[cc1020_txlen++] = TAIL;
00312
00313
00314 cc1020_set_tx();
00315
00316
00317 dma_done = 0;
00318 dma_transfer((unsigned char *)&TXBUF0, cc1020_txbuf, cc1020_txlen);
00319 while(!dma_done);
00320
00321 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00322 RIMESTATS_ADD(lltx);
00323
00324
00325 cc1020_txlen = 0;
00326 if(cc1020_state & CC1020_TURN_OFF) {
00327 cc1020_off();
00328 } else {
00329 cc1020_set_rx();
00330 }
00331
00332 return RADIO_TX_OK;
00333 }
00334
00335 static int
00336 cc1020_read(void *buf, unsigned short size)
00337 {
00338 unsigned len;
00339
00340 if(cc1020_rxlen <= HDR_SIZE) {
00341 return 0;
00342 }
00343
00344 len = cc1020_rxlen - HDR_SIZE;
00345 if(len > size) {
00346 RIMESTATS_ADD(toolong);
00347 return -1;
00348 }
00349
00350 memcpy(buf, (char *)cc1020_rxbuf + HDR_SIZE, len);
00351 RIMESTATS_ADD(llrx);
00352 reset_receiver();
00353
00354 return len;
00355 }
00356
00357 static int
00358 cc1020_channel_clear(void)
00359 {
00360 return (cc1020_read_reg(CC1020_STATUS) & CARRIER_SENSE);
00361 }
00362
00363 static int
00364 cc1020_receiving_packet(void)
00365 {
00366 return cc1020_state & CC1020_RX_RECEIVING;
00367 }
00368
00369 static int
00370 cc1020_pending_packet(void)
00371 {
00372 return cc1020_state & CC1020_RX_PROCESSING;
00373 }
00374
00375 int
00376 cc1020_on(void)
00377 {
00378 if(cc1020_state == CC1020_OFF) {
00379 cc1020_set_rx();
00380 } else if(cc1020_state & CC1020_TURN_OFF) {
00381 cc1020_state &= ~CC1020_TURN_OFF;
00382 cc1020_set_rx();
00383 }
00384
00385 return 1;
00386 }
00387
00388 int
00389 cc1020_off(void)
00390 {
00391 int s;
00392
00393 if(cc1020_state != CC1020_OFF) {
00394 if(cc1020_state & CC1020_RX_SEARCHING) {
00395
00396 cc1020_rxlen = 0;
00397
00398 LNA_POWER_OFF();
00399 s = splhigh();
00400 DISABLE_RX_IRQ();
00401 cc1020_state = CC1020_OFF;
00402 splx(s);
00403 cc1020_setupPD();
00404 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00405 cc1020_state = CC1020_OFF;
00406 } else {
00407 cc1020_state |= CC1020_TURN_OFF;
00408 }
00409 }
00410 return 1;
00411 }
00412
00413 uint8_t
00414 cc1020_get_rssi(void)
00415 {
00416 return (cc1020_read_reg(CC1020_RSS) & 0x7F);
00417 }
00418
00419 uint8_t
00420 cc1020_get_packet_rssi(void)
00421 {
00422 return rssi;
00423 }
00424
00425 PROCESS_THREAD(cc1020_receiver_process, ev, data)
00426 {
00427 int len;
00428
00429 PROCESS_BEGIN();
00430
00431 while(1) {
00432 ev = PROCESS_EVENT_NONE;
00433 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
00434
00435
00436 uint16_t expected_crc = 0xffff;
00437 uint16_t actual_crc;
00438
00439 actual_crc = (cc1020_rxbuf[cc1020_rxlen - CRC_SIZE] << 8) |
00440 cc1020_rxbuf[cc1020_rxlen - CRC_SIZE + 1];
00441 cc1020_rxlen -= CRC_SIZE;
00442
00443 expected_crc = crc16_add(cc1020_rxlen & 0xff, expected_crc);
00444 expected_crc = crc16_add((cc1020_rxlen >> 8) & 0xff, expected_crc);
00445 expected_crc = crc16_data((char *)&cc1020_rxbuf[HDR_SIZE],
00446 cc1020_rxlen - HDR_SIZE, expected_crc);
00447
00448 if(expected_crc == actual_crc) {
00449 len = cc1020_read(packetbuf_dataptr(), PACKETBUF_SIZE);
00450 packetbuf_set_datalen(len);
00451 NETSTACK_RDC.input();
00452 } else {
00453 RIMESTATS_ADD(badcrc);
00454 reset_receiver();
00455 }
00456 }
00457
00458 PROCESS_END();
00459 }
00460
00461 interrupt(UART0RX_VECTOR) cc1020_rxhandler(void)
00462 {
00463 static signed char syncbs;
00464 static union {
00465 struct {
00466 uint8_t b2;
00467 uint8_t b1;
00468 uint8_t b4;
00469 uint8_t b3;
00470 };
00471 struct {
00472 uint16_t i1;
00473 uint16_t i2;
00474 };
00475 } shiftbuf;
00476 static unsigned char pktlen;
00477
00478 if(cc1020_state & CC1020_RX_SEARCHING) {
00479 shiftbuf.b1 = shiftbuf.b2;
00480 shiftbuf.b2 = shiftbuf.b3;
00481 shiftbuf.b3 = shiftbuf.b4;
00482 shiftbuf.b4 = RXBUF0;
00483 if(shiftbuf.i1 == 0xAAD3 && shiftbuf.b3 == 0x91) {
00484
00485 syncbs = 0;
00486 cc1020_rxbuf[cc1020_rxlen++] = shiftbuf.b4;
00487 } else if(shiftbuf.i1 == 0x5569 && shiftbuf.i2 == 0xC880) {
00488
00489 syncbs = -1;
00490 } else if(shiftbuf.i1 == 0xAAB4 && shiftbuf.i2 == 0xE440) {
00491
00492 syncbs = -2;
00493 } else if(shiftbuf.i1 == 0x555A && shiftbuf.i2 == 0x7220) {
00494
00495 syncbs = -3;
00496 } else if(shiftbuf.i1 == 0xAAAD && shiftbuf.i2 == 0x3910) {
00497
00498 syncbs = -4;
00499 } else if(shiftbuf.i1 == 0x5556 && shiftbuf.i2 == 0x9C88) {
00500
00501 syncbs = +3;
00502 } else if(shiftbuf.i1 == 0xAAAB && shiftbuf.i2 == 0x4E44) {
00503
00504 syncbs = +2;
00505 } else if(shiftbuf.i1 == 0x5555 && shiftbuf.i2 == 0xA722) {
00506
00507 syncbs = +1;
00508 } else {
00509 return;
00510 }
00511 rssi = cc1020_get_rssi();
00512 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_RECEIVING);
00513 } else if(cc1020_state & CC1020_RX_RECEIVING) {
00514 if(syncbs == 0) {
00515 cc1020_rxbuf[cc1020_rxlen] = RXBUF0;
00516 } else {
00517 shiftbuf.b3 = shiftbuf.b4;
00518 shiftbuf.b4 = RXBUF0;
00519 if(syncbs < 0) {
00520 shiftbuf.i1 = shiftbuf.i2 << -syncbs;
00521 cc1020_rxbuf[cc1020_rxlen] = shiftbuf.b1;
00522 } else {
00523 shiftbuf.i1 = shiftbuf.i2 >> syncbs;
00524 cc1020_rxbuf[cc1020_rxlen] = shiftbuf.b2;
00525 }
00526 }
00527
00528 cc1020_rxlen++;
00529
00530 if(cc1020_rxlen == HDR_SIZE) {
00531 pktlen = ((struct cc1020_header *)cc1020_rxbuf)->length;
00532 if(pktlen == 0 || pktlen > sizeof (cc1020_rxbuf)) {
00533 cc1020_rxlen = 0;
00534 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING);
00535 }
00536 } else if(cc1020_rxlen > HDR_SIZE) {
00537 if(cc1020_rxlen == pktlen) {
00538
00539 DISABLE_RX_IRQ();
00540 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_PROCESSING);
00541 _BIC_SR_IRQ(LPM3_bits);
00542 process_poll(&cc1020_receiver_process);
00543 }
00544 }
00545 }
00546 }
00547
00548 static void
00549 cc1020_write_reg(uint8_t addr, uint8_t adata)
00550 {
00551 unsigned int i;
00552 uint8_t data;
00553
00554 data = addr << 1;
00555 PSEL_ON;
00556
00557
00558 for(i = 0; i < 7; i++) {
00559 PCLK_LOW;
00560 if(data & 0x80) {
00561 PDI_HIGH;
00562 } else {
00563 PDI_LOW;
00564 }
00565 data = data << 1;
00566 PCLK_HIGH;
00567 nop();
00568 }
00569
00570
00571
00572 PCLK_LOW;
00573 PDI_HIGH;
00574 PCLK_HIGH;
00575 nop();
00576 data = adata;
00577
00578
00579 for(i = 0; i < 8; i++) {
00580 PCLK_LOW;
00581 if(data & 0x80) {
00582 PDI_HIGH;
00583 } else {
00584 PDI_LOW;
00585 }
00586 data = data << 1;
00587 PCLK_HIGH;
00588 nop();
00589 }
00590
00591 PCLK_LOW;
00592 PSEL_OFF;
00593 }
00594
00595 static uint8_t
00596 cc1020_read_reg(uint8_t addr)
00597 {
00598 unsigned int i;
00599 uint8_t data;
00600
00601 data = addr << 1;
00602 PSEL_ON;
00603
00604
00605 for(i = 0; i < 7; i++) {
00606 PCLK_LOW;
00607 if(data & 0x80) {
00608 PDI_HIGH;
00609 } else {
00610 PDI_LOW;
00611 }
00612 data = data << 1;
00613 PCLK_HIGH;
00614 nop();
00615 }
00616
00617
00618
00619 PCLK_LOW;
00620 PDI_LOW;
00621 PCLK_HIGH;
00622 nop();
00623 PCLK_LOW;
00624
00625
00626 for(i = 0; i < 8; i++) {
00627 nop();
00628 PCLK_HIGH;
00629 nop();
00630 data = data << 1;
00631 if(PDO) {
00632 data++;
00633 }
00634 PCLK_LOW;
00635 }
00636
00637 PSEL_OFF;
00638
00639 return data;
00640 }
00641
00642 static void
00643 cc1020_load_config(const uint8_t * config)
00644 {
00645 int i;
00646
00647 for(i = 0; i < 0x28; i++)
00648 cc1020_write_reg(i, config[i]);
00649 }
00650
00651 static void
00652 cc1020_reset(void)
00653 {
00654
00655 cc1020_write_reg(CC1020_MAIN, 0x0FU & ~0x01U);
00656
00657
00658 cc1020_write_reg(CC1020_MAIN, 0x1F);
00659 }
00660
00661 static int
00662 cc1020_calibrate(void)
00663 {
00664 unsigned int timeout_cnt;
00665
00666
00667 cc1020_write_reg(CC1020_PA_POWER, 0x00);
00668
00669
00670 cc1020_write_reg(CC1020_CALIBRATE, 0xB5);
00671 while((cc1020_read_reg(CC1020_STATUS) & CAL_COMPLETE) == 0);
00672
00673
00674 for(timeout_cnt = LOCK_TIMEOUT; timeout_cnt > 0; timeout_cnt--) {
00675 if(cc1020_read_reg(CC1020_STATUS) & LOCK_CONTINUOUS) {
00676 break;
00677 }
00678 }
00679
00680
00681 cc1020_write_reg(CC1020_PA_POWER, cc1020_pa_power);
00682
00683
00684 return (cc1020_read_reg(CC1020_STATUS) & LOCK_CONTINUOUS) == LOCK_CONTINUOUS;
00685 }
00686
00687 static int
00688 cc1020_lock(void)
00689 {
00690 char lock_status;
00691 int i;
00692
00693
00694 for(i = LOCK_TIMEOUT; i > 0; i--) {
00695 lock_status = cc1020_read_reg(CC1020_STATUS) & LOCK_CONTINUOUS;
00696 if(lock_status) {
00697 break;
00698 }
00699 }
00700
00701 if(lock_status == LOCK_CONTINUOUS) {
00702 return LOCK_OK;
00703 }
00704
00705 return cc1020_calibrate() ? LOCK_RECAL_OK : LOCK_NOK;
00706 }
00707
00708 static int
00709 cc1020_setupRX(int analog)
00710 {
00711 char lock_status;
00712
00713
00714 cc1020_write_reg(CC1020_MAIN, 0x01);
00715 lock_status = cc1020_lock();
00716
00717
00718 cc1020_write_reg(CC1020_INTERFACE, 0x02);
00719
00720
00721 return lock_status;
00722 }
00723
00724 static int
00725 cc1020_setupTX(int analog)
00726 {
00727 char lock_status;
00728
00729
00730 cc1020_write_reg(CC1020_MAIN, 0xC1);
00731 lock_status = cc1020_lock();
00732
00733
00734 cc1020_write_reg(CC1020_PA_POWER, cc1020_pa_power);
00735
00736
00737 cc1020_write_reg(CC1020_INTERFACE, 0x01);
00738
00739
00740 return lock_status;
00741 }
00742
00743 static void
00744 cc1020_setupPD(void)
00745 {
00746
00747
00748
00749
00750 cc1020_write_reg(CC1020_MAIN,
00751 RESET_N | BIAS_PD | FS_PD | XOSC_PD | PD_MODE_1);
00752
00753
00754 cc1020_write_reg(CC1020_PA_POWER, 0x00);
00755
00756 cc1020_write_reg(CC1020_POWERDOWN, 0x1F);
00757 }
00758
00759 static void
00760 cc1020_wakeupRX(int analog)
00761 {
00762
00763 cc1020_write_reg(CC1020_MAIN, 0x1B);
00764
00765
00766 cc1020_write_reg(CC1020_ANALOG, analog);
00767
00768
00769
00770
00771
00772 MS_DELAY(5);
00773
00774
00775 cc1020_write_reg(CC1020_MAIN, 0x19);
00776
00777
00778 cc1020_write_reg(CC1020_MAIN, 0x11);
00779 }
00780
00781 static void
00782 cc1020_wakeupTX(int analog)
00783 {
00784
00785 cc1020_write_reg(CC1020_MAIN, 0xDB);
00786
00787
00788 cc1020_write_reg(CC1020_ANALOG, analog);
00789
00790
00791
00792
00793
00794 MS_DELAY(5);
00795
00796
00797 cc1020_write_reg(CC1020_MAIN, 0xD9);
00798
00799
00800 MS_DELAY(1);
00801 cc1020_write_reg(CC1020_MAIN, 0xD1);
00802 }
00803