Contiki 2.6
|
00001 /* 00002 * Copyright 2006, Freie Universitaet Berlin. All rights reserved. 00003 * 00004 * These sources were developed at the Freie Universitaet Berlin, Computer 00005 * Systems and Telematics group. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * - Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * - Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in the 00015 * documentation and/or other materials provided with the distribution. 00016 * 00017 * - Neither the name of Freie Universitaet Berlin (FUB) nor the names of its 00018 * contributors may be used to endorse or promote products derived from 00019 * this software without specific prior written permission. 00020 * 00021 * This software is provided by FUB and the contributors on an "as is" 00022 * basis, without any representations or warranties of any kind, express 00023 * or implied including, but not limited to, representations or 00024 * warranties of non-infringement, merchantability or fitness for a 00025 * particular purpose. In no event shall FUB or contributors be liable 00026 * for any direct, indirect, incidental, special, exemplary, or 00027 * consequential damages (including, but not limited to, procurement of 00028 * substitute goods or services; loss of use, data, or profits; or 00029 * business interruption) however caused and on any theory of liability, 00030 * whether in contract, strict liability, or tort (including negligence 00031 * or otherwise) arising in any way out of the use of this software, 00032 * even if advised of the possibility of such damage. 00033 * 00034 * This implementation was originally developed by the CST group at the FUB. 00035 */ 00036 00037 /** 00038 * \file cc1020.c 00039 * \author FUB ScatterWeb Developers, Michael Baar, Nicolas Tsiftes 00040 **/ 00041 00042 #include <stdio.h> 00043 #include <string.h> 00044 00045 #include "contiki.h" 00046 #include "contiki-msb430.h" 00047 #include "cc1020-internal.h" 00048 #include "cc1020.h" 00049 #include "lib/random.h" 00050 #include "lib/crc16.h" 00051 #include "net/rime/rimestats.h" 00052 #include "dev/dma.h" 00053 #include "sys/energest.h" 00054 #include "isr_compat.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 /* current mode of cc1020 chip */ 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 /* number of bytes in receive and transmit buffers respectively. */ 00086 static uint8_t cc1020_rxlen; 00087 static uint8_t cc1020_txlen; 00088 00089 /* received signal strength indicator reading for last received packet */ 00090 static volatile uint8_t rssi; 00091 00092 /* callback when a packet has been received */ 00093 static uint8_t cc1020_pa_power = PA_POWER; 00094 00095 static volatile char dma_done; 00096 00097 /* Radio driver AAPI functions. */ 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 /* reset receiver */ 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 /* init tx buffer with preamble + syncword */ 00156 memset(cc1020_txbuf, PREAMBLE, PREAMBLE_SIZE); 00157 cc1020_txbuf[PREAMBLE_SIZE] = syncword[0]; 00158 cc1020_txbuf[PREAMBLE_SIZE + 1] = syncword[1]; 00159 00160 /* calibrate receiver */ 00161 cc1020_wakeupRX(RX_CURRENT); 00162 if(!cc1020_calibrate()) { 00163 PRINTF("cc1020: rx calibration failed\n"); 00164 return -1; 00165 } 00166 00167 /* calibrate transmitter */ 00168 cc1020_wakeupTX(TX_CURRENT); 00169 if(!cc1020_calibrate()) { 00170 PRINTF("cc1020: tx calibration failed\n"); 00171 return -1; 00172 } 00173 00174 /* power down */ 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 /* Reset SEL for P3[1-3] (CC DIO, DIO, DCLK) and P3[4-5] (Camera Rx+Tx) */ 00191 P3SEL &= ~0x3E; 00192 IFG1 &= ~(UTXIE0 | URXIE0); /* Clear interrupt flags */ 00193 ME1 &= ~(UTXE0 | URXE0); /* Disable Uart0 Tx + Rx */ 00194 UCTL0 = SWRST; /* U0 into reset state. */ 00195 UCTL0 |= CHAR | SYNC; /* 8-bit character, SPI, Slave mode */ 00196 00197 /* CKPH works also, but not CKPH+CKPL or none of them!! */ 00198 UTCTL0 = CKPL | STC; 00199 URCTL0 = 0x00; 00200 UBR00 = 0x00; /* No baudrate divider */ 00201 UBR10 = 0x00; /* settings for a spi */ 00202 UMCTL0 = 0x00; /* slave. */ 00203 ME1 |= URXE0; /* Enable USART0 RXD, disabling does not yield any powersavings */ 00204 P3SEL |= 0x0A; /* Select rx line and clk */ 00205 UCTL0 &= ~SWRST; /* Clear reset bit */ 00206 splx(s); 00207 00208 /* configure driver */ 00209 cc1020_rxlen = 0; /* receive buffer position to start */ 00210 CC1020_SET_OPSTATE(CC1020_RX | CC1020_RX_SEARCHING); /* driver state to receive mode */ 00211 00212 /* configure radio */ 00213 ENERGEST_ON(ENERGEST_TYPE_LISTEN); 00214 cc1020_wakeupRX(RX_CURRENT); 00215 cc1020_setupRX(RX_CURRENT); 00216 LNA_POWER_ON(); /* enable amplifier */ 00217 00218 /* activate */ 00219 IE1 |= URXIE0; /* enable interrupt */ 00220 } 00221 00222 void 00223 cc1020_set_tx(void) 00224 { 00225 int s; 00226 00227 /* configure radio rx */ 00228 ENERGEST_OFF(ENERGEST_TYPE_LISTEN); 00229 LNA_POWER_OFF(); /* power down LNA */ 00230 s = splhigh(); 00231 DISABLE_RX_IRQ(); 00232 P3SEL &= ~0x02; /* Ensure Rx line is off */ 00233 splx(s); 00234 00235 /* configure radio tx */ 00236 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); 00237 cc1020_wakeupTX(TX_CURRENT); 00238 cc1020_setupTX(TX_CURRENT); 00239 P3SEL |= 0x0C; /* select Tx line and clk */ 00240 U0CTL |= SWRST; /* UART to reset mode */ 00241 IFG1 &= ~UTXIFG0; /* Reset IFG. */ 00242 00243 /* configure driver */ 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; /* For checksum purposes */ 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 /* The preamble and the sync word are already in buffer. */ 00289 cc1020_txlen = PREAMBLE_SIZE + SYNCWORD_SIZE; 00290 00291 /* header */ 00292 cc1020_txbuf[cc1020_txlen++] = 0x00; 00293 cc1020_txbuf[cc1020_txlen++] = normal_header + CRC_SIZE; 00294 00295 /* Adding the checksum on header and data */ 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 /* data to send */ 00302 memcpy((char *)cc1020_txbuf + cc1020_txlen, buf, len); 00303 cc1020_txlen += len; 00304 00305 /* Send checksum */ 00306 cc1020_txbuf[cc1020_txlen++] = rxcrc >> 8; 00307 cc1020_txbuf[cc1020_txlen++] = rxcrc & 0xff; 00308 00309 /* suffix */ 00310 cc1020_txbuf[cc1020_txlen++] = TAIL; 00311 cc1020_txbuf[cc1020_txlen++] = TAIL; 00312 00313 /* Switch to transceive mode. */ 00314 cc1020_set_tx(); 00315 00316 /* Initiate radio transfer. */ 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 /* clean up */ 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 /* Discard the current read buffer when the radio is shutting down. */ 00396 cc1020_rxlen = 0; 00397 00398 LNA_POWER_OFF(); /* power down lna */ 00399 s = splhigh(); 00400 DISABLE_RX_IRQ(); 00401 cc1020_state = CC1020_OFF; 00402 splx(s); 00403 cc1020_setupPD(); /* power down radio */ 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 /* Verify the checksum. */ 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 ISR(UART0RX, cc1020_rxhandler) 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 /* 0 AA D3 91 00 | FF 00 | */ 00485 syncbs = 0; 00486 cc1020_rxbuf[cc1020_rxlen++] = shiftbuf.b4; 00487 } else if(shiftbuf.i1 == 0x5569 && shiftbuf.i2 == 0xC880) { 00488 /* 1 55 69 C8 80 | 7F 80 | */ 00489 syncbs = -1; 00490 } else if(shiftbuf.i1 == 0xAAB4 && shiftbuf.i2 == 0xE440) { 00491 /* 2 AA B4 E4 40 | 3F C0 | */ 00492 syncbs = -2; 00493 } else if(shiftbuf.i1 == 0x555A && shiftbuf.i2 == 0x7220) { 00494 /* 3 55 5A 72 20 | 1F E0 | */ 00495 syncbs = -3; 00496 } else if(shiftbuf.i1 == 0xAAAD && shiftbuf.i2 == 0x3910) { 00497 /* 4 AA AD 39 10 | 0F F0 | */ 00498 syncbs = -4; 00499 } else if(shiftbuf.i1 == 0x5556 && shiftbuf.i2 == 0x9C88) { 00500 /* 5 55 56 9C 88 | 07 F8 | */ 00501 syncbs = +3; 00502 } else if(shiftbuf.i1 == 0xAAAB && shiftbuf.i2 == 0x4E44) { 00503 /* 6 AA AB 4E 44 | 03 FC | */ 00504 syncbs = +2; 00505 } else if(shiftbuf.i1 == 0x5555 && shiftbuf.i2 == 0xA722) { 00506 /* 7 55 55 A7 22 | 01 FE | */ 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 /* Disable interrupts while processing the packet. */ 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 /* Send address bits */ 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 /* Send read/write bit */ 00571 /* Ignore bit in data, always use 1 */ 00572 PCLK_LOW; 00573 PDI_HIGH; 00574 PCLK_HIGH; 00575 nop(); 00576 data = adata; 00577 00578 /* Send data bits */ 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 /* Send address bits */ 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 /* Send read/write bit */ 00618 /* Ignore bit in data, always use 0 */ 00619 PCLK_LOW; 00620 PDI_LOW; 00621 PCLK_HIGH; 00622 nop(); 00623 PCLK_LOW; 00624 00625 /* Receive data bits */ 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 /* Reset CC1020 */ 00655 cc1020_write_reg(CC1020_MAIN, 0x0FU & ~0x01U); 00656 00657 /* Bring CC1020 out of reset */ 00658 cc1020_write_reg(CC1020_MAIN, 0x1F); 00659 } 00660 00661 static int 00662 cc1020_calibrate(void) 00663 { 00664 unsigned int timeout_cnt; 00665 00666 /* Turn off PA to avoid spurs during calibration in TX mode */ 00667 cc1020_write_reg(CC1020_PA_POWER, 0x00); 00668 00669 /* Start calibration */ 00670 cc1020_write_reg(CC1020_CALIBRATE, 0xB5); 00671 while((cc1020_read_reg(CC1020_STATUS) & CAL_COMPLETE) == 0); 00672 00673 /* Monitor lock */ 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 /* Restore PA_POWER */ 00681 cc1020_write_reg(CC1020_PA_POWER, cc1020_pa_power); 00682 00683 /* Return state of LOCK_CONTINUOUS bit */ 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 /* Monitor LOCK, lasts 420 - 510 cycles @ 4505600 = 93 us - 113 us */ 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 /* Switch into RX, switch to freq. reg A */ 00714 cc1020_write_reg(CC1020_MAIN, 0x01); 00715 lock_status = cc1020_lock(); 00716 00717 /* Switch RX part of CC1020 on */ 00718 cc1020_write_reg(CC1020_INTERFACE, 0x02); 00719 00720 /* Return LOCK status to application */ 00721 return lock_status; 00722 } 00723 00724 static int 00725 cc1020_setupTX(int analog) 00726 { 00727 char lock_status; 00728 00729 /* Switch into TX, switch to freq. reg B */ 00730 cc1020_write_reg(CC1020_MAIN, 0xC1); 00731 lock_status = cc1020_lock(); 00732 00733 /* Restore PA_POWER */ 00734 cc1020_write_reg(CC1020_PA_POWER, cc1020_pa_power); 00735 00736 /* Turn OFF DCLK squelch in TX */ 00737 cc1020_write_reg(CC1020_INTERFACE, 0x01); 00738 00739 /* Return LOCK status to application */ 00740 return lock_status; 00741 } 00742 00743 static void 00744 cc1020_setupPD(void) 00745 { 00746 /* 00747 * Power down components and reset all registers except MAIN 00748 * to their default values. 00749 */ 00750 cc1020_write_reg(CC1020_MAIN, 00751 RESET_N | BIAS_PD | FS_PD | XOSC_PD | PD_MODE_1); 00752 00753 /* Turn off the power amplifier. */ 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 /* Turn on crystal oscillator core. */ 00763 cc1020_write_reg(CC1020_MAIN, 0x1B); 00764 00765 /* Setup bias current adjustment. */ 00766 cc1020_write_reg(CC1020_ANALOG, analog); 00767 00768 /* 00769 * Wait for the crystal oscillator to stabilize. 00770 * This typically takes 2-5 ms. 00771 */ 00772 MS_DELAY(5); 00773 00774 /* Turn on bias generator. */ 00775 cc1020_write_reg(CC1020_MAIN, 0x19); 00776 00777 /* Turn on frequency synthesizer. */ 00778 cc1020_write_reg(CC1020_MAIN, 0x11); 00779 } 00780 00781 static void 00782 cc1020_wakeupTX(int analog) 00783 { 00784 /* Turn on crystal oscillator core. */ 00785 cc1020_write_reg(CC1020_MAIN, 0xDB); 00786 00787 /* Setup bias current adjustment. */ 00788 cc1020_write_reg(CC1020_ANALOG, analog); 00789 00790 /* 00791 * Wait for the crystal oscillator to stabilize. 00792 * This typically takes 2-5 ms. 00793 */ 00794 MS_DELAY(5); 00795 00796 /* Turn on bias generator. */ 00797 cc1020_write_reg(CC1020_MAIN, 0xD9); 00798 00799 /* Turn on frequency synthesizer. */ 00800 MS_DELAY(1); 00801 cc1020_write_reg(CC1020_MAIN, 0xD1); 00802 } 00803