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 #ifdef RF230_CONF_CCA_THRES
00746 #if RF230_CONF_CCA_THRES < -91
00747 #warning
00748 #warning RF230_CONF_CCA_THRES below hardware limit, setting to -91dBm
00749 #warning
00750 hal_subregister_write(SR_CCA_ED_THRES,0);
00751 #elif RF230_CONF_CCA_THRES > -61
00752 #warning
00753 #warning RF230_CONF_CCA_THRES above hardware limit, setting to -61dBm
00754 #warning
00755 hal_subregister_write(SR_CCA_ED_THRES,15);
00756 #else
00757 hal_subregister_write(SR_CCA_ED_THRES,(RF230_CONF_CCA_THRES+91)/2);
00758 #endif
00759 #endif
00760
00761
00762 #if RF230_CONF_CHECKSUM
00763 hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
00764 #else
00765 hal_subregister_write(SR_TX_AUTO_CRC_ON, 1);
00766 #endif
00767
00768
00769 #ifdef RF230_MAX_TX_POWER
00770 set_txpower(RF230_MAX_TX_POWER);
00771 #endif
00772 }
00773
00774 static uint8_t buffer[RF230_MAX_TX_FRAME_LENGTH+AUX_LEN];
00775 static int
00776 rf230_transmit(unsigned short payload_len)
00777 {
00778 int txpower;
00779 uint8_t total_len;
00780 uint8_t radiowason;
00781 uint8_t tx_result;
00782 #if RF230_CONF_TIMESTAMPS
00783 struct timestamp timestamp;
00784 #endif
00785
00786 GET_LOCK();
00787
00788
00789
00790 radiowason=RF230_receive_on;
00791
00792
00793
00794 if (RF230_sleeping) {
00795 hal_set_slptr_low();
00796
00797 RF230_sleeping=0;
00798 } else {
00799 #if RADIOCALIBRATE
00800
00801 if (rf230_calibrate) {
00802 hal_subregister_write(SR_PLL_CF_START,1);
00803 hal_subregister_write(SR_PLL_DCU_START,1);
00804 rf230_calibrate=0;
00805 rf230_calibrated=1;
00806 delay_us(80);
00807 }
00808 #endif
00809 }
00810
00811
00812 rf230_waitidle();
00813
00814
00815 #if RF230_CONF_AUTORETRIES
00816 radio_set_trx_state(TX_ARET_ON);
00817 #else
00818 radio_set_trx_state(PLL_ON);
00819 #endif
00820
00821 txpower = 0;
00822
00823 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00824
00825 txpower = rf230_get_txpower();
00826
00827 set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
00828 }
00829
00830 total_len = payload_len + AUX_LEN;
00831
00832 #if RF230_CONF_TIMESTAMPS
00833 rtimer_clock_t txtime = timesynch_time();
00834 #endif
00835 #if defined(__AVR_ATmega128RFA1__)
00836
00837 cli();
00838
00839
00840 #endif
00841
00842 hal_set_slptr_high();
00843 hal_set_slptr_low();
00844 hal_frame_write(buffer, total_len);
00845 #if defined(__AVR_ATmega128RFA1__)
00846 sei();
00847 #endif
00848 PRINTF("rf230_transmit:\n");
00849 #if DEBUG>1
00850
00851
00852
00853 {
00854 uint8_t i;
00855 PRINTF("0000");
00856 for (i=0;i<total_len;i++) PRINTF(" %02x",buffer[i]);
00857 PRINTF("\n");
00858 }
00859 #endif
00860
00861 if(RF230_receive_on) {
00862 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00863 }
00864 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00865
00866 #if RADIOSTATS
00867 RF230_sendpackets++;
00868 #endif
00869
00870
00871
00872 rf230_waitidle();
00873
00874
00875 #if RF230_CONF_AUTORETRIES
00876 tx_result = hal_subregister_read(SR_TRAC_STATUS);
00877 #else
00878 tx_result=0;
00879 #endif
00880
00881 #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS
00882 ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,rf230_get_txpower());
00883 #endif
00884
00885
00886 if(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) > 0) {
00887 set_txpower(txpower & 0xff);
00888 }
00889
00890
00891 if(radiowason) {
00892
00893 on();
00894 }
00895
00896 #if RF230_CONF_TIMESTAMPS
00897 setup_time_for_transmission = txtime - timestamp.time;
00898
00899 if(num_transmissions < 10000) {
00900 total_time_for_transmission += timesynch_time() - txtime;
00901 total_transmission_len += total_len;
00902 num_transmissions++;
00903 }
00904
00905 #endif
00906
00907 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00908 if(RF230_receive_on) {
00909 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00910 } else {
00911 #if RADIOALWAYSON
00912
00913 on();
00914 #else
00915
00916 hal_subregister_write(SR_TRX_CMD, CMD_FORCE_TRX_OFF);
00917 #endif
00918 }
00919
00920 RELEASE_LOCK();
00921 if (tx_result==1) {
00922 tx_result=0;
00923 } else if (tx_result==3) {
00924 RIMESTATS_ADD(contentiondrop);
00925 PRINTF("rf230_transmit: Transmission never started\n");
00926
00927
00928 }
00929
00930 return tx_result;
00931 }
00932
00933 static int
00934 rf230_prepare(const void *payload, unsigned short payload_len)
00935 {
00936 int ret = 0;
00937 uint8_t total_len,*pbuf;
00938 #if RF230_CONF_TIMESTAMPS
00939 struct timestamp timestamp;
00940 #endif
00941 #if RF230_CONF_CHECKSUM
00942 uint16_t checksum;
00943 #endif
00944
00945 GET_LOCK();
00946
00947
00948
00949
00950
00951 RIMESTATS_ADD(lltx);
00952
00953 #if RF230_CONF_CHECKSUM
00954 checksum = crc16_data(payload, payload_len, 0);
00955 #endif
00956
00957
00958 total_len = payload_len + AUX_LEN;
00959 if (total_len > RF230_MAX_TX_FRAME_LENGTH){
00960 #if RADIOSTATS
00961 RF230_sendfail++;
00962 #endif
00963 #if DEBUG
00964 printf_P(PSTR("rf230_prepare: packet too large (%d, max: %d)\n"),total_len,RF230_MAX_TX_FRAME_LENGTH);
00965 #endif
00966 ret = -1;
00967 goto bail;
00968 }
00969 pbuf=&buffer[0];
00970 memcpy(pbuf,payload,payload_len);
00971 pbuf+=payload_len;
00972
00973 #if RF230_CONF_CHECKSUM
00974 memcpy(pbuf,&checksum,CHECKSUM_LEN);
00975 pbuf+=CHECKSUM_LEN;
00976 #endif
00977
00978 #if RF230_CONF_TIMESTAMPS
00979 timestamp.authority_level = timesynch_authority_level();
00980 timestamp.time = timesynch_time();
00981 memcpy(pbuf,×tamp,TIMESTAMP_LEN);
00982 pbuf+=TIMESTAMP_LEN;
00983 #endif
00984
00985
00986 #ifdef RF230BB_HOOK_TX_PACKET
00987 #if !RF230_CONF_CHECKSUM
00988 {
00989 uint16_t checksum;
00990 checksum = crc16_data(payload, payload_len, 0);
00991 memcpy(buffer+total_len-CHECKSUM_LEN,&checksum,CHECKSUM_LEN);
00992 }
00993 #endif
00994 RF230BB_HOOK_TX_PACKET(buffer,total_len);
00995 #endif
00996
00997
00998 bail:
00999 RELEASE_LOCK();
01000 return ret;
01001 }
01002
01003 static int
01004 rf230_send(const void *payload, unsigned short payload_len)
01005 {
01006 int ret = 0;
01007
01008 #ifdef RF230BB_HOOK_IS_SEND_ENABLED
01009 if(!RF230BB_HOOK_IS_SEND_ENABLED()) {
01010 goto bail;
01011 }
01012 #endif
01013
01014 if((ret=rf230_prepare(payload, payload_len))) {
01015 #if DEBUG
01016 printf_P(PSTR("rf230_send: Unable to send, prep failed (%d)\n"),ret);
01017 #endif
01018 goto bail;
01019 }
01020
01021 ret = rf230_transmit(payload_len);
01022
01023 bail:
01024 #if RADIOSTATS
01025 if (ret) RF230_sendfail++;
01026 #endif
01027 return ret;
01028 }
01029
01030 int
01031 rf230_off(void)
01032 {
01033
01034 if(RF230_receive_on == 0) {
01035 return 1;
01036 }
01037
01038
01039
01040 if(locked) {
01041 lock_off = 1;
01042 return 1;
01043 }
01044
01045
01046
01047
01048
01049 if (!rf230_isidle()) {
01050
01051 lock_off = 1;
01052 return 1;
01053 }
01054
01055 off();
01056 return 1;
01057 }
01058
01059 int
01060 rf230_on(void)
01061 {
01062 if(RF230_receive_on) {
01063 return 1;
01064 }
01065 if(locked) {
01066 DEBUGFLOW('L');
01067 lock_on = 1;
01068 return 1;
01069 }
01070
01071 on();
01072 return 1;
01073 }
01074
01075 uint8_t
01076 rf230_get_channel(void)
01077 {
01078
01079
01080 return channel;
01081 }
01082
01083 void
01084 rf230_set_channel(uint8_t c)
01085 {
01086
01087 PRINTF("rf230: Set Channel %u\n",c);
01088 rf230_waitidle();
01089 channel=c;
01090 hal_subregister_write(SR_CHANNEL, c);
01091 }
01092
01093 void
01094 rf230_listen_channel(uint8_t c)
01095 {
01096
01097
01098 rf230_set_channel(c);
01099 radio_set_trx_state(RX_ON);
01100 }
01101
01102 void
01103 rf230_set_pan_addr(unsigned pan,
01104 unsigned addr,
01105 const uint8_t ieee_addr[8])
01106
01107 {
01108 PRINTF("rf230: PAN=%x Short Addr=%x\n",pan,addr);
01109
01110 uint8_t abyte;
01111 abyte = pan & 0xFF;
01112 hal_register_write(RG_PAN_ID_0,abyte);
01113 abyte = (pan >> 8*1) & 0xFF;
01114 hal_register_write(RG_PAN_ID_1, abyte);
01115
01116 abyte = addr & 0xFF;
01117 hal_register_write(RG_SHORT_ADDR_0, abyte);
01118 abyte = (addr >> 8*1) & 0xFF;
01119 hal_register_write(RG_SHORT_ADDR_1, abyte);
01120
01121 if (ieee_addr != NULL) {
01122 PRINTF("MAC=%x",*ieee_addr);
01123 hal_register_write(RG_IEEE_ADDR_7, *ieee_addr++);
01124 PRINTF(":%x",*ieee_addr);
01125 hal_register_write(RG_IEEE_ADDR_6, *ieee_addr++);
01126 PRINTF(":%x",*ieee_addr);
01127 hal_register_write(RG_IEEE_ADDR_5, *ieee_addr++);
01128 PRINTF(":%x",*ieee_addr);
01129 hal_register_write(RG_IEEE_ADDR_4, *ieee_addr++);
01130 PRINTF(":%x",*ieee_addr);
01131 hal_register_write(RG_IEEE_ADDR_3, *ieee_addr++);
01132 PRINTF(":%x",*ieee_addr);
01133 hal_register_write(RG_IEEE_ADDR_2, *ieee_addr++);
01134 PRINTF(":%x",*ieee_addr);
01135 hal_register_write(RG_IEEE_ADDR_1, *ieee_addr++);
01136 PRINTF(":%x",*ieee_addr);
01137 hal_register_write(RG_IEEE_ADDR_0, *ieee_addr);
01138 PRINTF("\n");
01139 }
01140 }
01141
01142
01143
01144
01145 #if RF230_CONF_TIMESTAMPS
01146 static volatile rtimer_clock_t interrupt_time;
01147 static volatile int interrupt_time_set;
01148 #endif
01149 #if RF230_TIMETABLE_PROFILING
01150 #define rf230_timetable_size 16
01151 TIMETABLE(rf230_timetable);
01152 TIMETABLE_AGGREGATE(aggregate_time, 10);
01153 #endif
01154 int
01155 rf230_interrupt(void)
01156 {
01157
01158 #if RADIOALWAYSON
01159 if (RF230_receive_on) {
01160 DEBUGFLOW('+');
01161 #endif
01162 #if RF230_CONF_TIMESTAMPS
01163 interrupt_time = timesynch_time();
01164 interrupt_time_set = 1;
01165 #endif
01166
01167 process_poll(&rf230_process);
01168
01169 #if RF230_TIMETABLE_PROFILING
01170 timetable_clear(&rf230_timetable);
01171 TIMETABLE_TIMESTAMP(rf230_timetable, "interrupt");
01172 #endif
01173
01174 pending = 1;
01175
01176 #if RADIOSTATS //TODO:This will double count buffered packets
01177 RF230_receivepackets++;
01178 #endif
01179
01180 #if RADIOALWAYSON
01181 } else {
01182 DEBUGFLOW('-');
01183 rxframe[rxframe_head].length=0;
01184 }
01185 #endif
01186 return 1;
01187 }
01188
01189
01190
01191
01192
01193
01194 #if 0
01195 uint8_t rf230processflag;
01196 #define RF230PROCESSFLAG(arg) rf230processflag=arg
01197 #else
01198 #define RF230PROCESSFLAG(arg)
01199 #endif
01200
01201 PROCESS_THREAD(rf230_process, ev, data)
01202 {
01203 int len;
01204 PROCESS_BEGIN();
01205 RF230PROCESSFLAG(99);
01206
01207 while(1) {
01208 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
01209 RF230PROCESSFLAG(42);
01210 #if RF230_TIMETABLE_PROFILING
01211 TIMETABLE_TIMESTAMP(rf230_timetable, "poll");
01212 #endif
01213
01214 pending = 0;
01215
01216 packetbuf_clear();
01217 len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
01218 RF230PROCESSFLAG(1);
01219 if(len > 0) {
01220 packetbuf_set_datalen(len);
01221 RF230PROCESSFLAG(2);
01222 NETSTACK_RDC.input();
01223 #if RF230_TIMETABLE_PROFILING
01224 TIMETABLE_TIMESTAMP(rf230_timetable, "end");
01225 timetable_aggregate_compute_detailed(&aggregate_time,
01226 &rf230_timetable);
01227 timetable_clear(&rf230_timetable);
01228 #endif
01229 } else {
01230 #if RADIOSTATS
01231 RF230_receivefail++;
01232 #endif
01233 }
01234 }
01235
01236 PROCESS_END();
01237 }
01238
01239
01240
01241
01242
01243
01244 static int
01245 rf230_read(void *buf, unsigned short bufsize)
01246 {
01247 uint8_t len,*framep;
01248 #if FOOTER_LEN
01249 uint8_t footer[FOOTER_LEN];
01250 #endif
01251 #if RF230_CONF_CHECKSUM
01252 uint16_t checksum;
01253 #endif
01254 #if RF230_CONF_TIMESTAMPS
01255 struct timestamp t;
01256 #endif
01257
01258 len=rxframe[rxframe_head].length;
01259 if (len==0) {
01260 #if RADIOALWAYSON && DEBUGFLOWSIZE
01261 if (RF230_receive_on==0) {if (debugflow[debugflowsize-1]!='z') DEBUGFLOW('z');}
01262 #endif
01263 return 0;
01264 }
01265
01266 #if RADIOALWAYSON
01267 if (RF230_receive_on) {
01268 #endif
01269
01270 #if RF230_CONF_TIMESTAMPS
01271 if(interrupt_time_set) {
01272 rf230_time_of_arrival = interrupt_time;
01273 interrupt_time_set = 0;
01274 } else {
01275 rf230_time_of_arrival = 0;
01276 }
01277 rf230_time_of_departure = 0;
01278 #endif
01279
01280
01281 PRINTF("rf230_read: %u bytes lqi %u crc %u\n",rxframe[rxframe_head].length,rxframe[rxframe_head].lqi,rxframe[rxframe_head].crc);
01282 #if DEBUG>1
01283 {
01284 uint8_t i;
01285 PRINTF("0000");
01286 for (i=0;i<rxframe[rxframe_head].length;i++) PRINTF(" %02x",rxframe[rxframe_head].data[i]);
01287 PRINTF("\n");
01288 }
01289 #endif
01290
01291
01292
01293
01294 if(len > RF230_MAX_TX_FRAME_LENGTH) {
01295
01296 DEBUGFLOW('y');
01297 flushrx();
01298 RIMESTATS_ADD(badsynch);
01299
01300 return 0;
01301 }
01302
01303 if(len <= AUX_LEN) {
01304 DEBUGFLOW('s');
01305 PRINTF("len <= AUX_LEN\n");
01306 flushrx();
01307 RIMESTATS_ADD(tooshort);
01308
01309 return 0;
01310 }
01311
01312 if(len - AUX_LEN > bufsize) {
01313 DEBUGFLOW('b');
01314 PRINTF("len - AUX_LEN > bufsize\n");
01315 flushrx();
01316 RIMESTATS_ADD(toolong);
01317
01318 return 0;
01319 }
01320
01321 framep=&(rxframe[rxframe_head].data[0]);
01322 memcpy(buf,framep,len-AUX_LEN+CHECKSUM_LEN);
01323 rf230_last_correlation = rxframe[rxframe_head].lqi;
01324
01325
01326 rxframe[rxframe_head].length=0;
01327 rxframe_head++;if (rxframe_head >= RF230_CONF_RX_BUFFERS) rxframe_head=0;
01328
01329 if (rxframe[rxframe_head].length) rf230_interrupt();
01330
01331
01332 framep+=len-AUX_LEN;
01333 #if RF230_CONF_CHECKSUM
01334 memcpy(&checksum,framep,CHECKSUM_LEN);
01335 #endif
01336 framep+=CHECKSUM_LEN;
01337 #if RF230_CONF_TIMESTAMPS
01338 memcpy(&t,framep,TIMESTAMP_LEN);
01339 #endif
01340 framep+=TIMESTAMP_LEN;
01341 #if FOOTER_LEN
01342 memcpy(footer,framep,FOOTER_LEN);
01343 #endif
01344 #if RF230_CONF_CHECKSUM
01345 if(checksum != crc16_data(buf, len - AUX_LEN, 0)) {
01346 DEBUGFLOW('K');
01347 PRINTF("checksum failed 0x%04x != 0x%04x\n",
01348 checksum, crc16_data(buf, len - AUX_LEN, 0));
01349 }
01350 #if FOOTER_LEN
01351 if(footer[1] & FOOTER1_CRC_OK &&
01352 checksum == crc16_data(buf, len - AUX_LEN, 0)) {
01353 #endif
01354 #endif
01355
01356
01357 #if 0 //more general
01358 rf230_last_rssi = rf230_get_raw_rssi();
01359 #else //faster
01360 #if RF230_CONF_AUTOACK
01361
01362 rf230_last_rssi = hal_register_read(RG_PHY_ED_LEVEL);
01363 #else
01364
01365
01366 #endif
01367 #endif
01368
01369
01370 if ((rf230_smallest_rssi==0) || (rf230_last_rssi<rf230_smallest_rssi))
01371 rf230_smallest_rssi=rf230_last_rssi;
01372
01373
01374 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rf230_last_rssi);
01375 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rf230_last_correlation);
01376
01377 RIMESTATS_ADD(llrx);
01378
01379 #if RF230_CONF_TIMESTAMPS
01380 rf230_time_of_departure =
01381 t.time +
01382 setup_time_for_transmission +
01383 (total_time_for_transmission * (len - 2)) / total_transmission_len;
01384
01385 rf230_authority_level_of_sender = t.authority_level;
01386
01387 packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
01388 #endif
01389
01390 #if RF230_CONF_CHECKSUM
01391 #if FOOTER_LEN
01392 } else {
01393 DEBUGFLOW('X');
01394 PRINTF("bad crc");
01395 RIMESTATS_ADD(badcrc);
01396 len = AUX_LEN;
01397 }
01398 #endif
01399 #endif
01400
01401 #ifdef RF230BB_HOOK_RX_PACKET
01402 RF230BB_HOOK_RX_PACKET(buf,len);
01403 #endif
01404
01405
01406 return len - AUX_LEN;
01407
01408 #if RADIOALWAYSON
01409 } else {
01410 DEBUGFLOW('R');
01411 return 0;
01412 }
01413 #endif
01414 }
01415
01416 void
01417 rf230_set_txpower(uint8_t power)
01418 {
01419 GET_LOCK();
01420 set_txpower(power);
01421 RELEASE_LOCK();
01422 }
01423
01424 uint8_t
01425 rf230_get_txpower(void)
01426 {
01427 uint8_t power = TX_PWR_UNDEFINED;
01428 if (radio_is_sleeping()) {
01429 PRINTF("rf230_get_txpower:Sleeping");
01430 } else {
01431 power = hal_subregister_read(SR_TX_PWR);
01432 }
01433 return power;
01434 }
01435
01436
01437 uint8_t
01438 rf230_get_raw_rssi(void)
01439 {
01440 uint8_t rssi,state;
01441 bool radio_was_off = 0;
01442
01443
01444 if(!RF230_receive_on) {
01445 radio_was_off = 1;
01446 rf230_on();
01447 }
01448
01449
01450
01451 state=radio_get_trx_state();
01452 if ((state==RX_AACK_ON) || (state==BUSY_RX_AACK)) {
01453
01454 rssi = hal_register_read(RG_PHY_ED_LEVEL);
01455 } else {
01456 #if 0 // 3-clock shift and add is faster on machines with no hardware multiply
01457
01458 rssi = hal_subregister_read(SR_RSSI);
01459 rssi = (rssi << 1) + rssi;
01460 #else // 1 or 2 clock multiply, or compiler with correct optimization
01461 rssi = 3 * hal_subregister_read(SR_RSSI);
01462 #endif
01463
01464 }
01465
01466 if(radio_was_off) {
01467 rf230_off();
01468 }
01469 return rssi;
01470 }
01471
01472
01473 static int
01474 rf230_cca(void)
01475 {
01476 int cca;
01477 int radio_was_off = 0;
01478
01479
01480
01481
01482
01483 if(locked) {
01484 return 1;
01485 }
01486
01487 if(!RF230_receive_on) {
01488 radio_was_off = 1;
01489 rf230_on();
01490 }
01491
01492 DEBUGFLOW('c');
01493
01494
01495
01496
01497
01498 hal_subregister_write(SR_CCA_REQUEST,1);
01499 delay_us(TIME_CCA);
01500
01501 while (!hal_subregister_read(SR_CCA_DONE)) {continue;}
01502 cca=hal_subregister_read(SR_CCA_STATUS);
01503
01504 if(radio_was_off) {
01505 rf230_off();
01506 }
01507 return cca;
01508 }
01509
01510 int
01511 rf230_receiving_packet(void)
01512 {
01513 uint8_t radio_state;
01514 radio_state = hal_subregister_read(SR_TRX_STATUS);
01515 if ((radio_state==BUSY_RX) || (radio_state==BUSY_RX_AACK)) {
01516 DEBUGFLOW('B');
01517 return 1;
01518 } else {
01519 return 0;
01520 }
01521 }
01522
01523 static int
01524 pending_packet(void)
01525 {
01526 if (pending) DEBUGFLOW('p');
01527 return pending;
01528 }
01529
01530 #if RF230_CONF_SNEEZER && JACKDAW
01531
01532
01533
01534
01535
01536 void rf230_start_sneeze(void) {
01537
01538
01539
01540
01541
01542
01543
01544 hal_register_write(0x0E, 0x01);
01545 hal_register_write(0x02, 0x03);
01546 hal_register_write(0x03, 0x10);
01547
01548 hal_subregister_write(SR_CCA_MODE,1);
01549
01550
01551 hal_subregister_write(SR_TX_AUTO_CRC_ON, 0);
01552
01553 hal_register_read(0x01);
01554 hal_frame_write(buffer, 127);
01555
01556 hal_register_write(0x36,0x0F);
01557 hal_register_write(0x3D,0x00);
01558
01559
01560
01561
01562 DDRB |= 1<<7;
01563 PORTB |= 1<<7;
01564
01565 hal_register_write(0x02,0x09);
01566 delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE);
01567 delay_us(TIME_PLL_LOCK);
01568 delay_us(TIME_PLL_LOCK);
01569
01570 hal_register_write(0x02,0x02);
01571 }
01572 #endif