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 #include <stdio.h>
00039 #include <string.h>
00040
00041 #include "contiki.h"
00042
00043 #if defined(__AVR__)
00044 #include <avr/io.h>
00045
00046
00047
00048
00049
00050 #include <util/delay_basic.h>
00051 #define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) )
00052
00053 #include <avr/pgmspace.h>
00054 #elif defined(__MSP430__)
00055 #include <io.h>
00056 #endif
00057
00058 #include "dev/leds.h"
00059 #include "dev/spi.h"
00060 #include "rf230bb.h"
00061
00062 #include "net/packetbuf.h"
00063 #include "net/rime/rimestats.h"
00064 #include "net/netstack.h"
00065
00066 #include "sys/timetable.h"
00067
00068 #define WITH_SEND_CCA 0
00069
00070
00071 #if RF230_CONF_TIMESTAMPS
00072 #include "net/rime/timesynch.h"
00073 #define TIMESTAMP_LEN 3
00074 #else
00075 #define TIMESTAMP_LEN 0
00076 #endif
00077
00078 #define FOOTER_LEN 0
00079
00080
00081 #ifndef RF230_CONF_CHECKSUM
00082 #define RF230_CONF_CHECKSUM 0
00083 #endif
00084
00085 #ifndef RF230_CONF_AUTOACK
00086 #define RF230_CONF_AUTOACK 1
00087 #endif
00088
00089 #if RF230_CONF_AUTOACK
00090 static bool is_promiscuous;
00091 #endif
00092
00093 #ifndef RF230_CONF_AUTORETRIES
00094 #define RF230_CONF_AUTORETRIES 2
00095 #endif
00096
00097
00098 #if RF230_CONF_CHECKSUM || defined(RF230BB_HOOK_TX_PACKET)
00099 #include "lib/crc16.h"
00100 #endif
00101 #define CHECKSUM_LEN 2
00102
00103
00104 #define AUX_LEN (CHECKSUM_LEN + TIMESTAMP_LEN + FOOTER_LEN)
00105 #if AUX_LEN != CHECKSUM_LEN
00106 #warning RF230 Untested Configuration!
00107 #endif
00108
00109 struct timestamp {
00110 uint16_t time;
00111 uint8_t authority_level;
00112 };
00113
00114 #define FOOTER1_CRC_OK 0x80
00115 #define FOOTER1_CORRELATION 0x7f
00116
00117
00118 #if JACKDAW
00119 #define RADIOALWAYSON 1
00120 #else
00121 #define RADIOALWAYSON 0
00122 #define RADIOSLEEPSWHENOFF 1
00123 #endif
00124
00125
00126 #define DEBUG 0
00127 #if DEBUG
00128 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00129 #define PRINTSHORT(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00130 #else
00131 #define PRINTF(...)
00132 #define PRINTSHORT(...)
00133 #endif
00134 #if DEBUG>1
00135
00136
00137
00138
00139
00140
00141
00142 #endif
00143
00144
00145 #if WEBSERVER
00146 #define RADIOSTATS 1
00147 #endif
00148 #if RADIOSTATS
00149 uint16_t RF230_sendpackets,RF230_receivepackets,RF230_sendfail,RF230_receivefail;
00150 #endif
00151
00152 #if RADIOCALIBRATE
00153
00154 uint8_t rf230_calibrate;
00155 uint8_t rf230_calibrated;
00156 #endif
00157
00158
00159
00160 #if DEBUGFLOWSIZE
00161 uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE];
00162 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c
00163 #else
00164 #define DEBUGFLOW(c)
00165 #endif
00166
00167
00168 rtimer_clock_t rf230_time_of_arrival, rf230_time_of_departure;
00169
00170 int rf230_authority_level_of_sender;
00171
00172 #if RF230_CONF_TIMESTAMPS
00173 static rtimer_clock_t setup_time_for_transmission;
00174 static unsigned long total_time_for_transmission, total_transmission_len;
00175 static int num_transmissions;
00176 #endif
00177
00178 static uint8_t volatile pending;
00179
00180
00181 typedef enum{
00182 TIME_TO_ENTER_P_ON = 510,
00183 TIME_P_ON_TO_TRX_OFF = 510,
00184 TIME_SLEEP_TO_TRX_OFF = 880,
00185 TIME_RESET = 6,
00186 TIME_ED_MEASUREMENT = 140,
00187 TIME_CCA = 140,
00188 TIME_PLL_LOCK = 150,
00189 TIME_FTN_TUNING = 25,
00190 TIME_NOCLK_TO_WAKE = 6,
00191 TIME_CMD_FORCE_TRX_OFF = 1,
00192 TIME_TRX_OFF_TO_PLL_ACTIVE = 180,
00193 TIME_STATE_TRANSITION_PLL_ACTIVE = 1,
00194 }radio_trx_timing_t;
00195
00196 PROCESS(rf230_process, "RF230 driver");
00197
00198
00199 int rf230_on(void);
00200 int rf230_off(void);
00201
00202 static int rf230_read(void *buf, unsigned short bufsize);
00203
00204 static int rf230_prepare(const void *data, unsigned short len);
00205 static int rf230_transmit(unsigned short len);
00206 static int rf230_send(const void *data, unsigned short len);
00207
00208 static int rf230_receiving_packet(void);
00209 static int pending_packet(void);
00210 static int rf230_cca(void);
00211
00212 uint8_t rf230_last_correlation,rf230_last_rssi,rf230_smallest_rssi;
00213
00214 const struct radio_driver rf230_driver =
00215 {
00216 rf230_init,
00217 rf230_prepare,
00218 rf230_transmit,
00219 rf230_send,
00220 rf230_read,
00221 rf230_cca,
00222 rf230_receiving_packet,
00223 pending_packet,
00224 rf230_on,
00225 rf230_off
00226 };
00227
00228 uint8_t RF230_receive_on,RF230_sleeping;
00229 static uint8_t channel;
00230
00231
00232 uint8_t rxframe_head,rxframe_tail;
00233 hal_rx_frame_t rxframe[RF230_CONF_RX_BUFFERS];
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 static uint8_t
00279 radio_get_trx_state(void)
00280 {
00281 return hal_subregister_read(SR_TRX_STATUS);
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291 static bool radio_is_sleeping(void)
00292 {
00293 bool sleeping = false;
00294
00295
00296
00297 if (hal_get_slptr() != 0){
00298 sleeping = true;
00299 }
00300
00301 return sleeping;
00302 }
00303
00304
00305
00306
00307
00308 static void
00309 radio_reset_state_machine(void)
00310 {
00311 hal_set_slptr_low();
00312 delay_us(TIME_NOCLK_TO_WAKE);
00313 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00314 delay_us(TIME_CMD_FORCE_TRX_OFF);
00315 }
00316
00317 static char
00318 rf230_isidle(void)
00319 {
00320 uint8_t radio_state;
00321 radio_state = hal_subregister_read(SR_TRX_STATUS);
00322 if (radio_state != BUSY_TX_ARET &&
00323 radio_state != BUSY_RX_AACK &&
00324 radio_state != STATE_TRANSITION &&
00325 radio_state != BUSY_RX &&
00326 radio_state != BUSY_TX) {
00327 return(1);
00328 } else {
00329
00330 return(0);
00331 }
00332 }
00333
00334 static void
00335 rf230_waitidle(void)
00336 {
00337 while (1) {
00338 if (rf230_isidle()) break;
00339 }
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 static radio_status_t
00362 radio_set_trx_state(uint8_t new_state)
00363 {
00364 uint8_t original_state;
00365
00366
00367 if (!((new_state == TRX_OFF) ||
00368 (new_state == RX_ON) ||
00369 (new_state == PLL_ON) ||
00370 (new_state == RX_AACK_ON) ||
00371 (new_state == TX_ARET_ON))){
00372 return RADIO_INVALID_ARGUMENT;
00373 }
00374
00375 if (radio_is_sleeping() == true){
00376 return RADIO_WRONG_STATE;
00377 }
00378
00379
00380 rf230_waitidle();
00381
00382
00383 original_state = radio_get_trx_state();
00384
00385
00386
00387
00388
00389
00390
00391 if (new_state == original_state){
00392 return RADIO_SUCCESS;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401 if(new_state == TRX_OFF){
00402 radio_reset_state_machine();
00403 } else {
00404
00405
00406 if ((new_state == TX_ARET_ON) &&
00407 (original_state == RX_AACK_ON)){
00408
00409
00410 hal_subregister_write(SR_TRX_CMD, PLL_ON);
00411 delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
00412 } else if ((new_state == RX_AACK_ON) &&
00413 (original_state == TX_ARET_ON)){
00414
00415
00416 hal_subregister_write(SR_TRX_CMD, RX_ON);
00417 delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
00418 }
00419
00420
00421 hal_subregister_write(SR_TRX_CMD, new_state);
00422
00423
00424
00425 if (original_state == TRX_OFF){
00426 delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
00427 } else {
00428 delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE);
00429 }
00430 }
00431
00432
00433 radio_status_t set_state_status = RADIO_TIMED_OUT;
00434
00435 if (radio_get_trx_state() == new_state){
00436 set_state_status = RADIO_SUCCESS;
00437 }
00438
00439 return set_state_status;
00440 }
00441
00442 void
00443 rf230_set_promiscuous_mode(bool isPromiscuous) {
00444 #if RF230_CONF_AUTOACK
00445 is_promiscuous = isPromiscuous;
00446
00447
00448 #endif
00449 }
00450
00451 bool
00452 rf230_is_ready_to_send() {
00453 switch(radio_get_trx_state()) {
00454 case BUSY_TX:
00455 case BUSY_TX_ARET:
00456 return false;
00457 }
00458
00459 return true;
00460 }
00461
00462
00463 static void
00464 flushrx(void)
00465 {
00466 rxframe[rxframe_head].length=0;
00467 }
00468
00469 static uint8_t locked, lock_on, lock_off;
00470
00471 static void
00472 on(void)
00473 {
00474 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00475
00476 #ifdef RF230BB_HOOK_RADIO_ON
00477 RF230BB_HOOK_RADIO_ON();
00478 #endif
00479
00480 if (RF230_sleeping) {
00481 hal_set_slptr_low();
00482 delay_us(TIME_SLEEP_TO_TRX_OFF);
00483
00484 RF230_sleeping=0;
00485 }
00486 rf230_waitidle();
00487
00488 #if RF230_CONF_AUTOACK
00489
00490 radio_set_trx_state(RX_AACK_ON);
00491 #else
00492 radio_set_trx_state(RX_ON);
00493 #endif
00494
00495
00496
00497 RF230_receive_on = 1;
00498 }
00499 static void
00500 off(void)
00501 {
00502
00503 RF230_receive_on = 0;
00504
00505 #ifdef RF230BB_HOOK_RADIO_OFF
00506 RF230BB_HOOK_RADIO_OFF();
00507 #endif
00508
00509
00510 #if !RADIOALWAYSON
00511
00512
00513 rf230_waitidle();
00514
00515
00516 radio_reset_state_machine();
00517
00518 #if RADIOSLEEPSWHENOFF
00519
00520 hal_set_slptr_high();
00521 RF230_sleeping = 1;
00522 #endif
00523
00524 #endif
00525
00526 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00527 }
00528
00529 #define GET_LOCK() locked = 1
00530 static void RELEASE_LOCK(void) {
00531 if(lock_on) {
00532 on();
00533 lock_on = 0;
00534 }
00535 if(lock_off) {
00536 off();
00537 lock_off = 0;
00538 }
00539 locked = 0;
00540 }
00541
00542 static void
00543 set_txpower(uint8_t power)
00544 {
00545 if (power > TX_PWR_17_2DBM){
00546 power=TX_PWR_17_2DBM;
00547 }
00548 if (radio_is_sleeping() ==true) {
00549 PRINTF("rf230_set_txpower:Sleeping");
00550 } else {
00551 hal_subregister_write(SR_TX_PWR, power);
00552 }
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 #define AVR_ENTER_CRITICAL_REGION( ) {uint8_t volatile saved_sreg = SREG; cli( )
00564 #define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg;}
00565 uint8_t osccal_original,osccal_calibrated;
00566 void
00567 calibrate_rc_osc_32k(void)
00568 {
00569 #if 1
00570
00571
00572
00573
00574
00575
00576
00577
00578 uint8_t osccal_original = OSCCAL;
00579 volatile uint16_t temp;
00580
00581
00582
00583
00584
00585 TIMSK2 = 0x00;
00586 TIMSK1 = 0x00;
00587
00588
00589
00590
00591 ASSR |= (1 << AS2);
00592
00593 TCCR2B = 1 << CS20;
00594
00595 delay_us(50000UL);
00596 AVR_ENTER_CRITICAL_REGION();
00597
00598 uint8_t counter = 128;
00599 bool cal_ok = false;
00600 do{
00601
00602 TCCR1B = 1 << CS10;
00603
00604 while (ASSR & ((1 << TCN2UB)|(1 << OCR2AUB)|(1 << TCR2AUB)|(1 << TCR2BUB))) { ; }
00605
00606 TCNT2 = 0x80;
00607 TCNT1 = 0;
00608
00609 TIFR2 = 0xFF;
00610
00611
00612
00613
00614
00615 while (!(TIFR2 & (1 << TOV2))){
00616 ;
00617 }
00618 temp = TCNT1;
00619
00620 TCCR1B = 0;
00621
00622
00623 #define cal_upper 32812 //(31250*1.05) // 32812 = 0x802c
00624 #define cal_lower 29687 //(31250*0.95) // 29687 = 0x73f7
00625
00626 if (temp < cal_lower) {
00627
00628 if (OSCCAL==0x7e) break;
00629 if (OSCCAL==0xff) break;
00630 OSCCAL++;
00631 } else if (temp > cal_upper) {
00632
00633 if (OSCCAL==0x81) break;
00634 if (OSCCAL==0x00) break;
00635 OSCCAL--;
00636 } else {
00637
00638 cal_ok = true;
00639 }
00640
00641 counter--;
00642 } while ((counter != 0) && (false == cal_ok));
00643
00644 osccal_calibrated=OSCCAL;
00645 if (true != cal_ok) {
00646
00647 OSCCAL = osccal_original;
00648 }
00649
00650 OSCCAL = osccal_original;
00651 TCCR2B = 0;
00652
00653 ASSR &= ~(1 << AS2);
00654
00655
00656
00657
00658 AVR_LEAVE_CRITICAL_REGION();
00659 #endif
00660 }
00661
00662 int
00663 rf230_init(void)
00664 {
00665 uint8_t i;
00666 DEBUGFLOW('I');
00667
00668
00669 delay_us(TIME_TO_ENTER_P_ON);
00670
00671
00672
00673
00674
00675
00676
00677 hal_init();
00678
00679
00680 for (i=0;i<RF230_CONF_RX_BUFFERS;i++) rxframe[i].length=0;
00681 rxframe_head=0;rxframe_tail=0;
00682
00683
00684 hal_set_rst_low();
00685 hal_set_slptr_low();
00686 delay_us(TIME_RESET);
00687 hal_set_rst_high();
00688
00689
00690 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00691 delay_us(TIME_P_ON_TO_TRX_OFF);
00692
00693
00694
00695
00696 uint8_t tvers = hal_register_read(RG_VERSION_NUM);
00697 uint8_t tmanu = hal_register_read(RG_MAN_ID_0);
00698
00699 if ((tvers != RF230_REVA) && (tvers != RF230_REVB))
00700 PRINTF("rf230: Unsupported version %u\n",tvers);
00701 if (tmanu != SUPPORTED_MANUFACTURER_ID)
00702 PRINTF("rf230: Unsupported manufacturer ID %u\n",tmanu);
00703
00704 PRINTF("rf230: Version %u, ID %u\n",tvers,tmanu);
00705
00706 rf230_warm_reset();
00707
00708
00709 process_start(&rf230_process, NULL);
00710
00711
00712 on();
00713
00714 return 1;
00715 }
00716
00717
00718 void rf230_warm_reset(void) {
00719 #if RF230_CONF_SNEEZER && JACKDAW
00720
00721 #warning Manipulating PORTB pins for RF230 Sneezer mode!
00722 PORTB &= ~(1<<7);
00723 DDRB &= ~(1<<7);
00724 #endif
00725
00726 hal_register_write(RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK);
00727
00728
00729 hal_subregister_write(SR_MAX_FRAME_RETRIES, RF230_CONF_AUTORETRIES );
00730
00731
00732 hal_subregister_write(SR_MAX_CSMA_RETRIES, 5 );
00733 hal_register_write(RG_CSMA_BE, 0x80);
00734 hal_register_write(RG_CSMA_SEED_0,hal_register_read(RG_PHY_RSSI) );
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 #if RF230_CONF_CCA_THRES < -91
00746 #warning RF230_CONF_CCA_THRES below hardware limit, setting to -91dBm
00747 hal_subregister_write(SR_CCA_ED_THRES,0);
00748 #elif RF230_CONF_CCA_THRES > -61
00749 #warning RF230_CONF_CCA_THRES above hardware limit, setting to -61dBm
00750 hal_subregister_write(SR_CCA_ED_THRES,15);
00751 #else
00752 hal_subregister_write(SR_CCA_ED_THRES,(RF230_CONF_CCA_THRES+91)/2);
00753 #endif
00754
00755
00756 #if RF230_CONF_CHECKSUM
00757 hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
00758 #else
00759 hal_subregister_write(SR_TX_AUTO_CRC_ON, 1);
00760 #endif
00761
00762
00763 #ifdef RF230_MAX_TX_POWER
00764 set_txpower(RF230_MAX_TX_POWER);
00765 #endif
00766 }
00767
00768 static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH+AUX_LEN];
00769 static int
00770 rf230_transmit(unsigned short payload_len)
00771 {
00772 int txpower;
00773 uint8_t total_len;
00774 uint8_t radiowason;
00775 uint8_t tx_result;
00776 #if RF230_CONF_TIMESTAMPS
00777 struct timestamp timestamp;
00778 #endif
00779
00780 GET_LOCK();
00781
00782
00783
00784 radiowason=RF230_receive_on;
00785
00786
00787
00788 if (RF230_sleeping) {
00789 hal_set_slptr_low();
00790
00791 RF230_sleeping=0;
00792 } else {
00793 #if RADIOCALIBRATE
00794
00795 if (rf230_calibrate) {
00796 hal_subregister_write(SR_PLL_CF_START,1);
00797 hal_subregister_write(SR_PLL_DCU_START,1);
00798 rf230_calibrate=0;
00799 rf230_calibrated=1;
00800 delay_us(80);
00801 }
00802 #endif
00803 }
00804
00805
00806 rf230_waitidle();
00807
00808
00809 #if RF230_CONF_AUTORETRIES
00810 radio_set_trx_state(TX_ARET_ON);
00811 #else
00812 radio_set_trx_state(PLL_ON);
00813 #endif
00814
00815 txpower = 0;
00816
00817 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00818
00819 txpower = rf230_get_txpower();
00820
00821 set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
00822 }
00823
00824 total_len = payload_len + AUX_LEN;
00825
00826 #if RF230_CONF_TIMESTAMPS
00827 rtimer_clock_t txtime = timesynch_time();
00828 #endif
00829 #if defined(__AVR_ATmega128RFA1__)
00830
00831 cli();
00832
00833
00834 #endif
00835
00836 hal_set_slptr_high();
00837 hal_set_slptr_low();
00838 hal_frame_write(buffer, total_len);
00839 #if defined(__AVR_ATmega128RFA1__)
00840 sei();
00841 #endif
00842 PRINTF("rf230_transmit:\n");
00843 #if DEBUG>1
00844
00845
00846
00847 {
00848 uint8_t i;
00849 PRINTF("0000");
00850 for (i=0;i<total_len;i++) PRINTF(" %02x",buffer[i]);
00851 PRINTF("\n");
00852 }
00853 #endif
00854
00855 if(RF230_receive_on) {
00856 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00857 }
00858 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00859
00860 #if RADIOSTATS
00861 RF230_sendpackets++;
00862 #endif
00863
00864
00865
00866 rf230_waitidle();
00867
00868
00869 #if RF230_CONF_AUTORETRIES
00870 tx_result = hal_subregister_read(SR_TRAC_STATUS);
00871 #else
00872 tx_result=0;
00873 #endif
00874
00875 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
00876 ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
00877 #endif
00878
00879
00880 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00881 set_txpower(txpower & 0xff);
00882 }
00883
00884
00885 if(radiowason) {
00886
00887 on();
00888 }
00889
00890 #if RF230_CONF_TIMESTAMPS
00891 setup_time_for_transmission = txtime - timestamp.time;
00892
00893 if(num_transmissions < 10000) {
00894 total_time_for_transmission += timesynch_time() - txtime;
00895 total_transmission_len += total_len;
00896 num_transmissions++;
00897 }
00898
00899 #endif
00900
00901 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00902 if(RF230_receive_on) {
00903 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00904 } else {
00905 #if RADIOALWAYSON
00906
00907 on();
00908 #else
00909
00910 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00911 #endif
00912 }
00913
00914 RELEASE_LOCK();
00915 if (tx_result==1) {
00916 tx_result=0;
00917 } else if (tx_result==3) {
00918 RIMESTATS_ADD(contentiondrop);
00919 PRINTF("rf230_transmit: Transmission never started\n");
00920
00921
00922 }
00923
00924 return tx_result;
00925 }
00926
00927 static int
00928 rf230_prepare(const void *payload, unsigned short payload_len)
00929 {
00930 int ret = 0;
00931 uint8_t total_len,*pbuf;
00932 #if RF230_CONF_TIMESTAMPS
00933 struct timestamp timestamp;
00934 #endif
00935 #if RF230_CONF_CHECKSUM
00936 uint16_t checksum;
00937 #endif
00938
00939 GET_LOCK();
00940
00941
00942
00943
00944
00945 RIMESTATS_ADD(lltx);
00946
00947 #if RF230_CONF_CHECKSUM
00948 checksum = crc16_data(payload, payload_len, 0);
00949 #endif
00950
00951
00952 total_len = payload_len + AUX_LEN;
00953 if (total_len > RF230_MAX_TX_FRAME_LENGTH){
00954 #if RADIOSTATS
00955 RF230_sendfail++;
00956 #endif
00957 #if DEBUG
00958 printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH);
00959 #endif
00960 ret = -1;
00961 goto bail;
00962 }
00963 pbuf=&buffer[0];
00964 memcpy(pbuf,payload,payload_len);
00965 pbuf+=payload_len;
00966
00967 #if RF230_CONF_CHECKSUM
00968 memcpy(pbuf,&checksum,CHECKSUM_LEN);
00969 pbuf+=CHECKSUM_LEN;
00970 #endif
00971
00972 #if RF230_CONF_TIMESTAMPS
00973 timestamp.authority_level = timesynch_authority_level();
00974 timestamp.time = timesynch_time();
00975 memcpy(pbuf,×tamp,TIMESTAMP_LEN);
00976 pbuf+=TIMESTAMP_LEN;
00977 #endif
00978
00979
00980 #ifdef RF230BB_HOOK_TX_PACKET
00981 #if !RF230_CONF_CHECKSUM
00982 {
00983 uint16_t checksum;
00984 checksum = crc16_data(payload, payload_len, 0);
00985 memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN);
00986 }
00987 #endif
00988 RF230BB_HOOK_TX_PACKET(buffer,total_len);
00989 #endif
00990
00991
00992 bail:
00993 RELEASE_LOCK();
00994 return ret;
00995 }
00996
00997 static int
00998 rf230_send(const void *payload, unsigned short payload_len)
00999 {
01000 int ret = 0;
01001
01002 #ifdef RF230BB_HOOK_IS_SEND_ENABLED
01003 if(!RF230BB_HOOK_IS_SEND_ENABLED()) {
01004 goto bail;
01005 }
01006 #endif
01007
01008 if((ret=rf230_prepare(payload, payload_len))) {
01009 #if DEBUG
01010 printf_P(PSTR("rf230_send: Unable to send, prep failed (%d)\n"),ret);
01011 #endif
01012 goto bail;
01013 }
01014
01015 ret = rf230_transmit(payload_len);
01016
01017 bail:
01018 #if RADIOSTATS
01019 if (ret) RF230_sendfail++;
01020 #endif
01021 return ret;
01022 }
01023
01024 int
01025 rf230_off(void)
01026 {
01027
01028 if(RF230_receive_on == 0) {
01029 return 1;
01030 }
01031
01032
01033
01034 if(locked) {
01035 lock_off = 1;
01036 return 1;
01037 }
01038
01039
01040
01041
01042
01043 if (!rf230_isidle()) {
01044
01045 lock_off = 1;
01046 return 1;
01047 }
01048
01049 off();
01050 return 1;
01051 }
01052
01053 int
01054 rf230_on(void)
01055 {
01056 if(RF230_receive_on) {
01057 return 1;
01058 }
01059 if(locked) {
01060 DEBUGFLOW('L');
01061 lock_on = 1;
01062 return 1;
01063 }
01064
01065 on();
01066 return 1;
01067 }
01068
01069 uint8_t
01070 rf230_get_channel(void)
01071 {
01072
01073
01074 return channel;
01075 }
01076
01077 void
01078 rf230_set_channel(uint8_t c)
01079 {
01080
01081 PRINTF("rf230: Set Channel %u\n",c);
01082 rf230_waitidle();
01083 channel=c;
01084 hal_subregister_write(SR_CHANNEL, c);
01085 }
01086
01087 void
01088 rf230_listen_channel(uint8_t c)
01089 {
01090
01091
01092 rf230_set_channel(c);
01093 radio_set_trx_state(RX_ON);
01094 }
01095
01096 void
01097 rf230_set_pan_addr(unsigned pan,
01098 unsigned addr,
01099 const uint8_t ieee_addr[8])
01100
01101 {
01102 PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
01103
01104 uint8_t abyte;
01105 abyte = pan & 0xFF;
01106 hal_register_write(RG_PAN_ID_0,abyte);
01107 abyte = (pan >> 8*1) & 0xFF;
01108 hal_register_write(RG_PAN_ID_1, abyte);
01109
01110 abyte = addr & 0xFF;
01111 hal_register_write(RG_SHORT_ADDR_0, abyte);
01112 abyte = (addr >> 8*1) & 0xFF;
01113 hal_register_write(RG_SHORT_ADDR_1, abyte);
01114
01115 if (ieee_addr != NULL) {
01116 PRINTF("MAC=%x",*ieee_addr);
01117 hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++);
01118 PRINTF(":%x",*ieee_addr);
01119 hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++);
01120 PRINTF(":%x",*ieee_addr);
01121 hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++);
01122 PRINTF(":%x",*ieee_addr);
01123 hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++);
01124 PRINTF(":%x",*ieee_addr);
01125 hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++);
01126 PRINTF(":%x",*ieee_addr);
01127 hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++);
01128 PRINTF(":%x",*ieee_addr);
01129 hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++);
01130 PRINTF(":%x",*ieee_addr);
01131 hal_register_write(RG_IEEE_ADDR_0, *ieee_addr);
01132 PRINTF("\n");
01133 }
01134 }
01135
01136
01137
01138
01139 #if RF230_CONF_TIMESTAMPS
01140 static volatile rtimer_clock_t interrupt_time;
01141 static volatile int interrupt_time_set;
01142 #endif
01143 #if RF230_TIMETABLE_PROFILING
01144 #define rf230_timetable_size 16
01145 TIMETABLE(rf230_timetable);
01146 TIMETABLE_AGGREGATE(aggregate_time, 10);
01147 #endif
01148 int
01149 rf230_interrupt(void)
01150 {
01151
01152 #if RADIOALWAYSON
01153 if (RF230_receive_on) {
01154 DEBUGFLOW('+');
01155 #endif
01156 #if RF230_CONF_TIMESTAMPS
01157 interrupt_time = timesynch_time();
01158 interrupt_time_set = 1;
01159 #endif
01160
01161 process_poll(&rf230_process);
01162
01163 #if RF230_TIMETABLE_PROFILING
01164 timetable_clear(&rf230_timetable);
01165 TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt");
01166 #endif
01167
01168 pending = 1;
01169
01170 #if RADIOSTATS //TODO:This will double count buffered packets
01171 RF230_receivepackets++;
01172 #endif
01173
01174 #if RADIOALWAYSON
01175 } else {
01176 DEBUGFLOW('-');
01177 rxframe[rxframe_head].length=0;
01178 }
01179 #endif
01180 return 1;
01181 }
01182
01183
01184
01185
01186
01187
01188 #if 0
01189 uint8_t rf230processflag;
01190 #define RF230PROCESSFLAG(arg) rf230processflag=arg
01191 #else
01192 #define RF230PROCESSFLAG(arg)
01193 #endif
01194
01195 PROCESS_THREAD(rf230_process, ev, data)
01196 {
01197 int len;
01198 PROCESS_BEGIN();
01199 RF230PROCESSFLAG(99);
01200
01201 while(1) {
01202 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
01203 RF230PROCESSFLAG(42);
01204 #if RF230_TIMETABLE_PROFILING
01205 TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
01206 #endif
01207
01208 pending = 0;
01209
01210 packetbuf_clear();
01211 len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
01212 RF230PROCESSFLAG(1);
01213 if(len > 0) {
01214 packetbuf_set_datalen(len);
01215 RF230PROCESSFLAG(2);
01216 NETSTACK_RDC.input();
01217 #if RF230_TIMETABLE_PROFILING
01218 TIMETABLE_TIMESTAMP(rf230_timetable, "end");
01219 timetable_aggregate_compute_detailed(&aggregate_time,
01220 &rf230_timetable);
01221 timetable_clear(&rf230_timetable);
01222 #endif
01223 } else {
01224 #if RADIOSTATS
01225 RF230_receivefail++;
01226 #endif
01227 }
01228 }
01229
01230 PROCESS_END();
01231 }
01232
01233
01234
01235
01236
01237
01238 static int
01239 rf230_read(void *buf, unsigned short bufsize)
01240 {
01241 uint8_t len,*framep;
01242 #if FOOTER_LEN
01243 uint8_t footer[FOOTER_LEN];
01244 #endif
01245 #if RF230_CONF_CHECKSUM
01246 uint16_t checksum;
01247 #endif
01248 #if RF230_CONF_TIMESTAMPS
01249 struct timestamp t;
01250 #endif
01251
01252 len=rxframe[rxframe_head].length;
01253 if (len==0) {
01254 #if RADIOALWAYSON && DEBUGFLOWSIZE
01255 if (RF230_receive_on==0) {if (debugflow[debugflowsize-1]!='z') DEBUGFLOW('z');}
01256 #endif
01257 return 0;
01258 }
01259
01260 #if RADIOALWAYSON
01261 if (RF230_receive_on) {
01262 #endif
01263
01264 #if RF230_CONF_TIMESTAMPS
01265 if(interrupt_time_set) {
01266 rf230_time_of_arrival = interrupt_time;
01267 interrupt_time_set = 0;
01268 } else {
01269 rf230_time_of_arrival = 0;
01270 }
01271 rf230_time_of_departure = 0;
01272 #endif
01273
01274
01275 PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe[rxframe_head].length,rxframe[rxframe_head].lqi,rxframe[rxframe_head].crc);
01276 #if DEBUG>1
01277 {
01278 uint8_t i;
01279 PRINTF("0000");
01280 for (i=0;i<rxframe[rxframe_head].length;i++) PRINTF(" %02x",rxframe[rxframe_head].data[i]);
01281 PRINTF("\n");
01282 }
01283 #endif
01284
01285
01286
01287
01288 if(len > RF230_MAX_TX_FRAME_LENGTH) {
01289
01290 DEBUGFLOW('y');
01291 flushrx();
01292 RIMESTATS_ADD(badsynch);
01293
01294 return 0;
01295 }
01296
01297 if(len <= AUX_LEN) {
01298 DEBUGFLOW('s');
01299 PRINTF("len <= AUX_LEN\n");
01300 flushrx();
01301 RIMESTATS_ADD(tooshort);
01302
01303 return 0;
01304 }
01305
01306 if(len - AUX_LEN > bufsize) {
01307 DEBUGFLOW('b');
01308 PRINTF("len - AUX_LEN > bufsize\n");
01309 flushrx();
01310 RIMESTATS_ADD(toolong);
01311
01312 return 0;
01313 }
01314
01315 framep=&(rxframe[rxframe_head].data[0]);
01316 memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
01317 rf230_last_correlation = rxframe[rxframe_head].lqi;
01318
01319
01320 rxframe[rxframe_head].length=0;
01321 rxframe_head++;if (rxframe_head >= RF230_CONF_RX_BUFFERS) rxframe_head=0;
01322
01323 if (rxframe[rxframe_head].length) rf230_interrupt();
01324
01325
01326 framep+=len-AUX_LEN;
01327 #if RF230_CONF_CHECKSUM
01328 memcpy(&checksum,framep,CHECKSUM_LEN);
01329 #endif
01330 framep+=CHECKSUM_LEN;
01331 #if RF230_CONF_TIMESTAMPS
01332 memcpy(&t,framep,TIMESTAMP_LEN);
01333 #endif
01334 framep+=TIMESTAMP_LEN;
01335 #if FOOTER_LEN
01336 memcpy(footer,framep,FOOTER_LEN);
01337 #endif
01338 #if RF230_CONF_CHECKSUM
01339 if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
01340 DEBUGFLOW('K');
01341 PRINTF("checksum failed 0x%04x != 0x%04x\n",
01342 checksum, crc16_data(buf, len - AUX_LEN, 0));
01343 }
01344 #if FOOTER_LEN
01345 if(footer[1] & FOOTER1_CRC_OK &&
01346 checksum == crc16_data(buf, len - AUX_LEN, 0)) {
01347 #endif
01348 #endif
01349
01350
01351 #if 0 //more general
01352 rf230_last_rssi = rf230_get_raw_rssi();
01353 #else //faster
01354 #if RF230_CONF_AUTOACK
01355
01356 rf230_last_rssi = hal_register_read(RG_PHY_ED_LEVEL);
01357 #else
01358
01359
01360 #endif
01361 #endif
01362
01363
01364 if ((rf230_smallest_rssi==0) || (rf230_last_rssi<rf230_smallest_rssi))
01365 rf230_smallest_rssi=rf230_last_rssi;
01366
01367
01368 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
01369 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
01370
01371 RIMESTATS_ADD(llrx);
01372
01373 #if RF230_CONF_TIMESTAMPS
01374 rf230_time_of_departure =
01375 t.time +
01376 setup_time_for_transmission +
01377 (total_time_for_transmission * (len - 2)) / total_transmission_len;
01378
01379 rf230_authority_level_of_sender = t.authority_level;
01380
01381 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
01382 #endif
01383
01384 #if RF230_CONF_CHECKSUM
01385 #if FOOTER_LEN
01386 } else {
01387 DEBUGFLOW('X');
01388 PRINTF("bad crc");
01389 RIMESTATS_ADD(badcrc);
01390 len = AUX_LEN;
01391 }
01392 #endif
01393 #endif
01394
01395 #ifdef RF230BB_HOOK_RX_PACKET
01396 RF230BB_HOOK_RX_PACKET(buf,len);
01397 #endif
01398
01399
01400 return len - AUX_LEN;
01401
01402 #if RADIOALWAYSON
01403 } else {
01404 DEBUGFLOW('R');
01405 return 0;
01406 }
01407 #endif
01408 }
01409
01410 void
01411 rf230_set_txpower(uint8_t power)
01412 {
01413 GET_LOCK();
01414 set_txpower(power);
01415 RELEASE_LOCK();
01416 }
01417
01418 uint8_t
01419 rf230_get_txpower(void)
01420 {
01421 uint8_t power = TX_PWR_UNDEFINED;
01422 if (radio_is_sleeping()) {
01423 PRINTF("rf230_get_txpower:Sleeping");
01424 } else {
01425 power = hal_subregister_read(SR_TX_PWR);
01426 }
01427 return power;
01428 }
01429
01430
01431 uint8_t
01432 rf230_get_raw_rssi(void)
01433 {
01434 uint8_t rssi,state;
01435 bool radio_was_off = 0;
01436
01437
01438 if(!RF230_receive_on) {
01439 radio_was_off = 1;
01440 rf230_on();
01441 }
01442
01443
01444
01445 state=radio_get_trx_state();
01446 if ((state==RX_AACK_ON) || (state==BUSY_RX_AACK)) {
01447
01448 rssi = hal_register_read(RG_PHY_ED_LEVEL);
01449 } else {
01450 #if 0 // 3-clock shift and add is faster on machines with no hardware multiply
01451
01452 rssi = hal_subregister_read(SR_RSSI);
01453 rssi = (rssi << 1) + rssi;
01454 #else // 1 or 2 clock multiply, or compiler with correct optimization
01455 rssi = 3 * hal_subregister_read(SR_RSSI);
01456 #endif
01457
01458 }
01459
01460 if(radio_was_off) {
01461 rf230_off();
01462 }
01463 return rssi;
01464 }
01465
01466
01467 static int
01468 rf230_cca(void)
01469 {
01470 int cca;
01471 int radio_was_off = 0;
01472
01473
01474
01475
01476
01477 if(locked) {
01478 return 1;
01479 }
01480
01481 if(!RF230_receive_on) {
01482 radio_was_off = 1;
01483 rf230_on();
01484 }
01485
01486 DEBUGFLOW('c');
01487
01488
01489
01490
01491
01492 hal_subregister_write(SR_CCA_REQUEST,1);
01493 delay_us(TIME_CCA);
01494
01495 while (!hal_subregister_read(SR_CCA_DONE)) {continue;}
01496 cca=hal_subregister_read(SR_CCA_STATUS);
01497
01498 if(radio_was_off) {
01499 rf230_off();
01500 }
01501 return cca;
01502 }
01503
01504 int
01505 rf230_receiving_packet(void)
01506 {
01507 uint8_t radio_state;
01508 radio_state = hal_subregister_read(SR_TRX_STATUS);
01509 if ((radio_state==BUSY_RX) || (radio_state==BUSY_RX_AACK)) {
01510 DEBUGFLOW('B');
01511 return 1;
01512 } else {
01513 return 0;
01514 }
01515 }
01516
01517 static int
01518 pending_packet(void)
01519 {
01520 if (pending) DEBUGFLOW('p');
01521 return pending;
01522 }
01523
01524 #if RF230_CONF_SNEEZER && JACKDAW
01525
01526
01527
01528
01529
01530 void rf230_start_sneeze(void) {
01531
01532
01533
01534
01535
01536
01537
01538 hal_register_write(0x0E, 0x01);
01539 hal_register_write(0x02, 0x03);
01540 hal_register_write(0x03, 0x10);
01541
01542 hal_subregister_write(SR_CCA_MODE,1);
01543
01544
01545 hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
01546
01547 hal_register_read(0x01);
01548 hal_frame_write(buffer, 127);
01549
01550 hal_register_write(0x36,0x0F);
01551 hal_register_write(0x3D,0x00);
01552
01553
01554
01555
01556 DDRB |= 1<<7;
01557 PORTB |= 1<<7;
01558
01559 hal_register_write(0x02,0x09);
01560 delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
01561 delay_us(TIME_PLL_LOCK);
01562 delay_us(TIME_PLL_LOCK);
01563
01564 hal_register_write(0x02,0x02);
01565 }
01566 #endif