cc2430_rf.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012
00013 #include "contiki.h"
00014 #include "dev/radio.h"
00015 #include "dev/cc2430_rf.h"
00016 #include "cc2430_sfr.h"
00017 #include "sys/clock.h"
00018
00019 #include "net/packetbuf.h"
00020 #include "net/rime/rimestats.h"
00021
00022 extern void (* receiver_callback)(const struct radio_driver *);
00023 #ifndef RF_DEFAULT_POWER
00024 #define RF_DEFAULT_POWER 100
00025 #endif
00026
00027 #ifndef RF_DEFAULT_CHANNEL
00028 #define RF_DEFAULT_CHANNEL 18
00029 #endif
00030
00031 #ifndef CC2430_CONF_CHECKSUM
00032 #define CC2430_CONF_CHECKSUM 0
00033 #endif
00034
00035 #if CC2430_CONF_CHECKSUM
00036 #include "lib/crc16.h"
00037 #define CHECKSUM_LEN 2
00038 #else
00039 #define CHECKSUM_LEN 2
00040 #endif
00041 #if DEBUG_LEDS
00042
00043
00044 #include "dev/leds.h"
00045 #define RF_RX_LED_ON() leds_on(LEDS_RED);
00046 #define RF_RX_LED_OFF() leds_off(LEDS_RED);
00047 #define RF_TX_LED_ON() leds_on(LEDS_GREEN);
00048 #define RF_TX_LED_OFF() leds_off(LEDS_GREEN);
00049 #else
00050 #define RF_RX_LED_ON()
00051 #define RF_RX_LED_OFF()
00052 #define RF_TX_LED_ON()
00053 #define RF_TX_LED_OFF()
00054 #endif
00055 #define DEBUG 0
00056 #if DEBUG
00057 #define PRINTF(...) printf(__VA_ARGS__)
00058 #else
00059 #define PRINTF(...) do {} while (0)
00060 #endif
00061
00062 #define RX_ACTIVE 0x80
00063 #define TX_ACK 0x40
00064 #define TX_ON_AIR 0x20
00065 #define RX_NO_DMA
00066
00067 #ifdef HAVE_RF_ERROR
00068 uint8_t rf_error = 0;
00069 #endif
00070
00071 uint8_t rf_initialized = 0;
00072 uint8_t rf_tx_power;
00073 uint8_t rf_flags;
00074 uint8_t rf_channel = 0;
00075 rf_address_mode_t rf_addr_mode;
00076 uint16_t rf_manfid;
00077 uint8_t rf_softack;
00078 uint16_t rf_panid;
00079
00080
00081 PROCESS_NAME(cc2430_rf_process);
00082
00083
00084 const struct radio_driver cc2430_rf_driver =
00085 {
00086 cc2430_rf_send,
00087 cc2430_rf_read,
00088 cc2430_rf_set_receiver,
00089 cc2430_rf_on,
00090 cc2430_rf_off,
00091 };
00092
00093
00094 void
00095 cc2430_rf_init(void) __banked
00096 {
00097 if(rf_initialized) {
00098 return;
00099 }
00100
00101 PRINTF("cc2430_rf_init called\n");
00102
00103 RFPWR &= ~RREG_RADIO_PD;
00104 while((RFPWR & ADI_RADIO_PD) == 1);
00105 while((RFIF & IRQ_RREG_ON) == 0);
00106 SLEEP &= ~OSC_PD;
00107 while((SLEEP & XOSC_STB) == 0);
00108
00109 rf_flags = 0;
00110 rf_softack = 0;
00111
00112 FSMTC1 = 1;
00113
00114 MDMCTRL0H = 0x02;
00115 MDMCTRL0L = 0xE2;
00116
00117 MDMCTRL1H = 0x30;
00118 MDMCTRL1L = 0x0;
00119
00120 RXCTRL0H = 0x32;
00121 RXCTRL0L = 0xf5;
00122
00123
00124 rf_manfid = CHVER;
00125 rf_manfid <<= 8;
00126 rf_manfid += CHIPID;
00127 cc2430_rf_channel_set(RF_DEFAULT_CHANNEL);
00128 cc2430_rf_command(ISFLUSHTX);
00129 cc2430_rf_command(ISFLUSHRX);
00130
00131 cc2430_rf_set_addr(0xffff, 0x0000, NULL);
00132 cc2430_rf_address_decoder_mode(RF_DECODER_NONE);
00133
00134 RFIM = IRQ_FIFOP;
00135 RFIF &= ~(IRQ_FIFOP);
00136
00137 S1CON &= ~(RFIF_0 | RFIF_1);
00138 IEN2 |= RFIE;
00139
00140 RF_TX_LED_OFF();
00141 RF_RX_LED_OFF();
00142 rf_initialized = 1;
00143 process_start(&cc2430_rf_process, NULL);
00144 }
00145
00146 int
00147 cc2430_rf_send_b(void *payload, unsigned short payload_len) __banked
00148 {
00149 uint8_t i, counter;
00150
00151 if(rf_flags & TX_ACK) {
00152 return -1;
00153 }
00154 if((rf_flags & RX_ACTIVE) == 0) {
00155 cc2430_rf_rx_enable();
00156 }
00157
00158
00159
00160
00161 PRINTF("cc2430_rf: sending %ud byte payload\n", payload_len);
00162
00163 RIMESTATS_ADD(lltx);
00164
00165 cc2430_rf_command(ISFLUSHTX);
00166 PRINTF("cc2430_rf: sent = ");
00167
00168 RFD = payload_len+CHECKSUM_LEN;
00169 PRINTF("(%d)", payload_len+CHECKSUM_LEN);
00170 for(i = 0 ; i < payload_len; i++) {
00171 RFD = ((unsigned char*)(payload))[i];
00172 PRINTF("%02X", ((unsigned char*)(payload))[i]);
00173 }
00174 PRINTF("\n");
00175
00176
00177 RFD = 0;
00178 RFD = 0;
00179
00180 if(cc2430_rf_cca_check(0,0) == -1) {
00181 return -1;
00182 }
00183
00184
00185
00186 RFIF &= ~IRQ_TXDONE;
00187 cc2430_rf_command(ISTXON);
00188 counter = 0;
00189 while(!(RFSTATUS & TX_ACTIVE) && (counter++ < 3)) {
00190 clock_delay(10);
00191 }
00192
00193 if(!(RFSTATUS & TX_ACTIVE)) {
00194 PRINTF("cc2430_rf: TX never active.\n");
00195 cc2430_rf_command(ISFLUSHTX);
00196 return -1;
00197 } else {
00198 RF_RX_LED_OFF();
00199 RF_TX_LED_ON();
00200
00201 }
00202 return 1;
00203 }
00204
00205 int
00206 cc2430_rf_read_banked(void *buf, unsigned short bufsize) __banked
00207 {
00208 uint8_t i, len;
00209 #if CC2420_CONF_CHECKSUM
00210 uint16_t checksum;
00211 #endif
00212
00213
00214
00215
00216 len = RFD;
00217
00218
00219 if(len > CC2430_MAX_PACKET_LEN) {
00220
00221 PRINTF("error: bad sync\n");
00222 cc2430_rf_command(ISFLUSHRX);
00223 RIMESTATS_ADD(badsynch);
00224 return 0;
00225 }
00226
00227 if(len <= CC2430_MIN_PACKET_LEN) {
00228 PRINTF("error: too short\n");
00229 cc2430_rf_command(ISFLUSHRX);
00230 RIMESTATS_ADD(tooshort);
00231 return 0;
00232 }
00233
00234 if(len - CHECKSUM_LEN > bufsize) {
00235 PRINTF("error: too long\n");
00236 cc2430_rf_command(ISFLUSHRX);
00237 RIMESTATS_ADD(toolong);
00238 return 0;
00239 }
00240
00241
00242 PRINTF("cc2430_rf: read = ");
00243 PRINTF("(%d)", len);
00244 for(i = 0; i < (len - CHECKSUM_LEN); i++) {
00245 ((unsigned char*)(buf))[i] = RFD;
00246 PRINTF("%02X", ((unsigned char*)(buf))[i]);
00247 }
00248 PRINTF("\n");
00249
00250 #if CC2430_CONF_CHECKSUM
00251
00252 checksum = RFD * 256;
00253 checksum += RFD;
00254 #endif
00255 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, ((int8_t) RFD) - 45);
00256 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, RFD);
00257
00258 RFIF &= ~IRQ_FIFOP;
00259 RFSTATUS &= ~FIFO;
00260 cc2430_rf_command(ISFLUSHRX);
00261 cc2430_rf_command(ISFLUSHRX);
00262 RF_RX_LED_OFF();
00263
00264 RIMESTATS_ADD(llrx);
00265
00266 return (len - CHECKSUM_LEN);
00267 }
00268
00269
00270
00271
00272
00273
00274 void cc2430_rf_command(uint8_t command) __banked
00275 {
00276 if(command >= 0xE0) {
00277 uint8_t fifo_count;
00278 switch(command) {
00279 case ISRFOFF:
00280 case ISRXON:
00281 case ISTXON:
00282 fifo_count = RXFIFOCNT;
00283 RFST = command;
00284 clock_delay(2);
00285 if(fifo_count != RXFIFOCNT) {
00286 RFST = ISFLUSHRX;
00287 RFST = ISFLUSHRX;
00288 }
00289 break;
00290
00291 default:
00292 RFST = command;
00293 }
00294 } else if(command == SSTART) {
00295 RFIF &= ~IRQ_CSP_STOP;
00296 RFST = SSTOP;
00297 RFST = ISSTART;
00298 while((RFIF & IRQ_CSP_STOP) == 0);
00299 } else {
00300 RFST = command;
00301 }
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 int8_t
00318 cc2430_rf_channel_set(uint8_t channel)
00319 {
00320 uint16_t freq;
00321
00322 if((channel < 11) || (channel > 26)) {
00323 return -1;
00324 }
00325
00326 cc2430_rf_command(ISSTOP);
00327 cc2430_rf_command(ISRFOFF);
00328
00329 freq = (uint16_t) channel - 11;
00330 freq *= 5;
00331 freq += 357;
00332 freq |= 0x4000;
00333 FSCTRLH = (freq >> 8);
00334 FSCTRLL = (uint8_t)freq;
00335
00336 cc2430_rf_command(ISRXON);
00337
00338 rf_channel = channel;
00339
00340 return (int8_t) channel;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 int8_t
00362 cc2430_rf_power_set(uint8_t new_power)
00363 {
00364 uint16_t power;
00365
00366 if(new_power > 100) {
00367 return -1;
00368 }
00369
00370 power = 31 * new_power;
00371 power /= 100;
00372 power += 0xA160;
00373
00374
00375 TXCTRLH = (power >> 8);
00376 TXCTRLL = (uint8_t)power;
00377
00378 rf_tx_power = (int8_t) new_power;
00379 return rf_tx_power;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 int8_t
00390 cc2430_rf_rx_enable(void) __banked
00391 {
00392 PRINTF("cc2430_rf_rx_enable called\n");
00393 if(!(rf_flags & RX_ACTIVE)) {
00394 IOCFG0 = 0x7f;
00395 RSSIH = 0xd2;
00396 rf_flags |= RX_ACTIVE;
00397
00398 RFPWR &= ~RREG_RADIO_PD;
00399 while((RFIF & IRQ_RREG_ON) == 0);
00400 SLEEP &= ~OSC_PD;
00401 while((SLEEP & XOSC_STB) == 0);
00402
00403 cc2430_rf_command(ISRXON);
00404 cc2430_rf_command(ISFLUSHRX);
00405 }
00406 PRINTF("cc2430_rf_rx_enable done\n");
00407 return 1;
00408 }
00409
00410
00411
00412
00413
00414
00415
00416
00417 int8_t cc2430_rf_rx_disable(void) __banked
00418 {
00419 cc2430_rf_command(ISSTOP);
00420 cc2430_rf_command(ISRFOFF);
00421
00422 RFPWR |= RREG_RADIO_PD;
00423
00424 rf_flags = 0;
00425 return 1;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435 int8_t
00436 cc2430_rf_tx_enable(void)
00437 {
00438 DMAARM = 0x80 + (1 << 0);
00439
00440 return 1;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450 void
00451 cc2430_rf_set_addr(unsigned pan, unsigned addr, const uint8_t *ieee_addr)
00452 {
00453 uint8_t f;
00454 __xdata unsigned char *ptr;
00455
00456 rf_panid = pan;
00457 PANIDH = pan >> 8;
00458 PANIDL = pan & 0xff;
00459
00460 SHORTADDRH = addr >> 8;
00461 SHORTADDRL = addr & 0xff;
00462
00463 if(ieee_addr != NULL) {
00464 ptr = &IEEE_ADDR0;
00465
00466 for (f = 0; f < 8; f++) {
00467 *ptr++ = ieee_addr[f];
00468 }
00469 }
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479 int8_t
00480 cc2430_rf_address_decoder_mode(rf_address_mode_t mode)
00481 {
00482 int8_t retval = -1;
00483
00484 rf_softack = 0;
00485
00486 switch(mode) {
00487 case RF_SOFTACK_MONITOR:
00488 rf_softack = 1;
00489 case RF_MONITOR:
00490 MDMCTRL0H |= 0x10;
00491 MDMCTRL0L &= ~0x10;
00492 break;
00493
00494 case RF_DECODER_COORDINATOR:
00495 MDMCTRL0H |= 0x18;
00496 MDMCTRL0L |= 0x10;
00497 break;
00498
00499 case RF_DECODER_ON:
00500 MDMCTRL0H |= 0x08;
00501 MDMCTRL0L &= ~0x10;
00502 break;
00503
00504 default:
00505 MDMCTRL0H &= ~0x18;
00506 MDMCTRL0L &= ~0x10;
00507 break;
00508 }
00509 rf_addr_mode = mode;
00510
00511 retval = 1;
00512 return retval;
00513 }
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 int8_t
00524 cc2430_rf_analyze_rssi(void)
00525 {
00526 int8_t retval = -128;
00527
00528
00529 retval = (int8_t)RSSIL;
00530 retval -= 45;
00531 return retval;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 int8_t
00541 cc2430_rf_cca_check(uint8_t backoff_count, uint8_t slotted)
00542 {
00543 uint8_t counter, cca = 1;
00544 int8_t retval = 1;
00545 backoff_count;
00546 cc2430_rf_command(ISRXON);
00547
00548 clock_delay(64);
00549 switch(slotted) {
00550 case 1:
00551
00552 if(RFSTATUS & CCA) {
00553 counter = 0;
00554 cca = 1;
00555 while(cca != 0) {
00556 if(counter > 1) {
00557 cca = 0;
00558 }
00559 clock_delay(256);
00560 if(!(RFSTATUS & CCA)) {
00561 cca = 0;
00562 retval = -1;
00563 }
00564 counter++;
00565 }
00566 } else {
00567 retval = -1;
00568 }
00569 break;
00570
00571 case 0:
00572 if(!(RFSTATUS & CCA)) {
00573 retval = -1;
00574 } else {
00575
00576 }
00577 break;
00578 }
00579 return retval;
00580 }
00581
00582
00583
00584
00585
00586
00587 void
00588 cc2430_rf_send_ack(uint8_t pending) __banked
00589 {
00590 if(pending) {
00591 cc2430_rf_command(ISACKPEND);
00592 } else {
00593 cc2430_rf_command(ISACK);
00594 }
00595 }
00596