00001
00048
00049 #include <stdint.h>
00050 #include <stdbool.h>
00051
00052 #include "at86rf230_registermap.h"
00053
00054 #include "compiler.h"
00055 #include "tat.h"
00056 #include "hal.h"
00057
00058 #define TAT_CCA_DONE_MASK ( 1 << 7 )
00059 #define TAT_CCA_IDLE_MASK ( 1 << 6 )
00060
00061 #define TAT_START_CCA ( 1 )
00062
00063 #define TAT_TRANSMISSION_SUCCESS ( 0 )
00064 #define TAT_BUSY_CHANNEL ( 3 )
00065 #define TAT_MIN_IEEE_FRAME_LENGTH ( 5 )
00066
00067
00075 typedef enum{
00076
00077 TIME_P_ON_TO_TRX_OFF = 510,
00078 TIME_SLEEP_TO_TRX_OFF = 880,
00079 TIME_RESET = 6,
00080 TIME_ED_MEASUREMENT = 140,
00081 TIME_CCA = 140,
00082 TIME_PLL_LOCK = 150,
00083 TIME_FTN_TUNING = 25,
00084 TIME_NOCLK_TO_WAKE = 6,
00085 TIME_CMD_FORCE_TRX_OFF = 1,
00086 TIME_TRX_OFF_TO_PLL_ACTIVE = 180,
00087 TIME_STATE_TRANSITION_PLL_ACTIVE = 1,
00088 }tat_trx_timing_t;
00089
00090
00091 static bool is_sleeping( void );
00092
00110 tat_status_t tat_init( void ){
00111
00112 tat_status_t init_status = TAT_SUCCESS;
00113
00114
00115 hal_init( );
00116 sei( );
00117
00118 tat_reset_trx( );
00119
00120
00121 hal_subregister_write( SR_TRX_CMD, CMD_FORCE_TRX_OFF );
00122 delay_us( TIME_P_ON_TO_TRX_OFF );
00123
00124 if (tat_get_trx_state( ) != TRX_OFF) {
00125 init_status = TAT_TIMED_OUT;
00126 } else {
00127
00128
00129 uint8_t version_number = hal_register_read( RG_VERSION_NUM );
00130
00131 if ((version_number != RF230_REVA ) && (version_number != RF230_REVB)) {
00132 init_status = TAT_UNSUPPORTED_DEVICE;
00133 } else {
00134
00135 if (hal_register_read( RG_MAN_ID_0 ) != SUPPORTED_MANUFACTURER_ID) {
00136 init_status = TAT_UNSUPPORTED_DEVICE;
00137 } else {
00138 hal_register_write( RG_IRQ_MASK, RF230_SUPPORTED_INTERRUPT_MASK );
00139 hal_subregister_write( SR_CLKM_CTRL, CLKM_DISABLED );
00140 }
00141 }
00142 }
00143
00144 return init_status;
00145 }
00146
00153 uint8_t tat_get_operating_channel( void ){
00154 return hal_subregister_read( SR_CHANNEL );
00155 }
00156
00169 tat_status_t tat_set_operating_channel( uint8_t channel ){
00170
00171
00172 if ((channel < RF230_MIN_CHANNEL) || (channel > RF230_MAX_CHANNEL)) {
00173 return TAT_INVALID_ARGUMENT;
00174 }
00175
00176 if (is_sleeping( ) == true) { return TAT_WRONG_STATE; }
00177
00178 if (tat_get_operating_channel( ) == channel) { return TAT_SUCCESS; }
00179
00180
00181 hal_subregister_write( SR_CHANNEL, channel );
00182
00183
00184
00185 uint8_t trx_state = tat_get_trx_state( );
00186
00187 if ((trx_state == RX_ON) || (trx_state == PLL_ON)) {
00188 delay_us( TIME_PLL_LOCK );
00189 }
00190
00191 tat_status_t channel_set_status = TAT_TIMED_OUT;
00192
00193
00194 if (tat_get_operating_channel( ) == channel) {
00195 channel_set_status = TAT_SUCCESS;
00196 }
00197
00198 return channel_set_status;
00199 }
00200
00208 uint8_t tat_get_tx_power_level( void ){
00209 return hal_subregister_read( SR_TX_PWR );
00210 }
00211
00224 tat_status_t tat_set_tx_power_level( uint8_t power_level ){
00225
00226
00227 if (power_level > TX_PWR_17_2DBM) { return TAT_INVALID_ARGUMENT; }
00228
00229 if (is_sleeping( ) == true) { return TAT_WRONG_STATE; }
00230
00231
00232 hal_subregister_write( SR_TX_PWR, power_level );
00233
00234 return TAT_SUCCESS;
00235 }
00236
00249 tat_status_t tat_do_ed_scan( uint8_t *ed_level ){
00250
00251 uint8_t current_state = tat_get_trx_state( );
00252
00253
00254 if ((current_state != RX_ON ) && (current_state != BUSY_RX)) {
00255 return TAT_WRONG_STATE;
00256 }
00257
00258
00259
00260 hal_register_write( RG_PHY_ED_LEVEL, 0 );
00261 delay_us( TIME_ED_MEASUREMENT );
00262 *ed_level = hal_register_read( RG_PHY_ED_LEVEL );
00263
00264 return TAT_SUCCESS;
00265 }
00266
00273 uint8_t tat_get_cca_mode( void ){
00274 return hal_subregister_read( SR_CCA_MODE );
00275 }
00276
00283 uint8_t tat_get_ed_threshold( void ){
00284 return hal_subregister_read( SR_CCA_ED_THRES );
00285 }
00286
00304 tat_status_t tat_set_cca_mode( uint8_t mode, uint8_t ed_threshold ){
00305
00306
00307 if ((mode != CCA_ED) && (mode != CCA_CARRIER_SENSE) &&
00308 (mode != CCA_CARRIER_SENSE_WITH_ED)) {
00309 return TAT_INVALID_ARGUMENT;
00310 }
00311
00312
00313 if (ed_threshold > RF230_MAX_ED_THRESHOLD) { return TAT_INVALID_ARGUMENT; }
00314
00315
00316 if (is_sleeping( ) == true) { return TAT_WRONG_STATE; }
00317
00318
00319 hal_subregister_write( SR_CCA_MODE, mode );
00320 hal_subregister_write( SR_CCA_ED_THRES, ed_threshold );
00321
00322 return TAT_SUCCESS;
00323 }
00324
00336 tat_status_t tat_do_cca( void ){
00337
00338
00339 if (tat_get_trx_state( ) != PLL_ON) { return TAT_WRONG_STATE; }
00340
00341
00342 if (tat_set_trx_state( RX_ON ) != TAT_SUCCESS) { return TAT_TIMED_OUT; }
00343
00344
00345 hal_subregister_write( SR_CCA_REQUEST, TAT_START_CCA );
00346
00347
00348 delay_us( TIME_CCA );
00349
00350 uint8_t status = hal_register_read( RG_TRX_STATUS );
00351 tat_status_t cca_status = TAT_CCA_BUSY;
00352
00353
00354 if ((status & TAT_CCA_DONE_MASK) != TAT_CCA_DONE_MASK) {
00355 cca_status = TAT_TIMED_OUT;
00356 } else {
00357
00358
00359 if ((status & TAT_CCA_IDLE_MASK) != TAT_CCA_IDLE_MASK) {
00360 cca_status = TAT_CCA_BUSY;
00361 } else {
00362 cca_status = TAT_CCA_IDLE;
00363 }
00364 }
00365
00366 return cca_status;
00367 }
00368
00380 tat_status_t tat_get_rssi_value( uint8_t *rssi ){
00381
00382 uint8_t current_state = tat_get_trx_state( );
00383 tat_status_t retval = TAT_WRONG_STATE;
00384
00385
00386 if ((current_state == RX_ON) || (current_state == BUSY_RX)) {
00387
00388 *rssi = hal_subregister_read( SR_RSSI );
00389 retval = TAT_SUCCESS;
00390 }
00391
00392 return retval;
00393 }
00394
00405 uint8_t tat_batmon_get_voltage_threshold( void ){
00406 return hal_subregister_read( SR_BATMON_VTH );
00407 }
00408
00419 uint8_t tat_batmon_get_voltage_range( void ){
00420 return hal_subregister_read( SR_BATMON_HR );
00421 }
00422
00434 tat_status_t tat_batmon_configure( bool range, uint8_t voltage_threshold ){
00435
00436
00437 if (voltage_threshold > BATTERY_MONITOR_HIGHEST_VOLTAGE) {
00438 return TAT_INVALID_ARGUMENT;
00439 }
00440
00441 if (is_sleeping( ) == true) { return TAT_WRONG_STATE; }
00442
00443
00444 if (range == true) {
00445 hal_subregister_write( SR_BATMON_HR, BATTERY_MONITOR_HIGH_VOLTAGE );
00446 } else {
00447 hal_subregister_write( SR_BATMON_HR, BATTERY_MONITOR_LOW_VOLTAGE );
00448 }
00449
00450 hal_subregister_write( SR_BATMON_VTH, voltage_threshold );
00451
00452 return TAT_SUCCESS;
00453 }
00454
00465 tat_status_t tat_batmon_get_status( void ){
00466
00467 tat_status_t batmon_status = TAT_BAT_LOW;
00468
00469 if (hal_subregister_read( SR_BATMON_OK ) !=
00470 BATTERY_MONITOR_VOLTAGE_UNDER_THRESHOLD) {
00471 batmon_status = TAT_BAT_OK;
00472 }
00473
00474 return batmon_status;
00475 }
00476
00488 uint8_t tat_get_clock_speed( void ){
00489 return hal_subregister_read( SR_CLKM_CTRL );
00490 }
00491
00513 tat_status_t tat_set_clock_speed( bool direct, uint8_t clock_speed ){
00514
00515
00516 if (clock_speed > CLKM_16MHZ) { return TAT_INVALID_ARGUMENT; }
00517
00518 if (tat_get_clock_speed( ) == clock_speed) { return TAT_SUCCESS; }
00519
00520
00521 if (direct == false) {
00522 hal_subregister_write( SR_CLKM_SHA_SEL, 1 );
00523 } else {
00524 hal_subregister_write( SR_CLKM_SHA_SEL, 0 );
00525 }
00526
00527 hal_subregister_write( SR_CLKM_CTRL, clock_speed );
00528
00529 return TAT_SUCCESS;
00530 }
00531
00541 tat_status_t tat_calibrate_filter( void ){
00542
00543
00544 uint8_t trx_state = tat_get_trx_state( );
00545
00546 if ((trx_state != TRX_OFF ) && (trx_state != PLL_ON)) { return TAT_WRONG_STATE; }
00547
00548
00549 hal_subregister_write( SR_FTN_START, 1 );
00550 delay_us( TIME_FTN_TUNING );
00551
00552 tat_status_t filter_calibration_status = TAT_TIMED_OUT;
00553
00554
00555 if (hal_subregister_read( SR_FTN_START ) == FTN_CALIBRATION_DONE) {
00556 filter_calibration_status = TAT_SUCCESS;
00557 }
00558
00559 return filter_calibration_status;
00560 }
00561
00570 tat_status_t tat_calibrate_pll( void ){
00571
00572
00573 if (tat_get_trx_state( ) != PLL_ON) { return TAT_WRONG_STATE; }
00574
00575
00576 hal_subregister_write( SR_PLL_DCU_START, 1 );
00577 hal_subregister_write( SR_PLL_CF_START, 1 );
00578
00579
00580 hal_clear_pll_lock_flag( );
00581 delay_us( TIME_PLL_LOCK );
00582
00583 tat_status_t pll_calibration_status = TAT_TIMED_OUT;
00584
00585 if (hal_get_pll_lock_flag( ) > 0) {
00586
00587 if (hal_subregister_read( SR_PLL_DCU_START ) == PLL_DCU_CALIBRATION_DONE) {
00588
00589 if (hal_subregister_read( SR_PLL_CF_START ) == PLL_CF_CALIBRATION_DONE) {
00590 pll_calibration_status = TAT_SUCCESS;
00591 }
00592 }
00593 }
00594
00595 return pll_calibration_status;
00596 }
00597
00642 uint8_t tat_get_trx_state( void ){
00643 return hal_subregister_read( SR_TRX_STATUS );
00644 }
00645
00654 static bool is_sleeping( void ){
00655
00656 bool sleeping = false;
00657
00658
00659
00660 if (hal_get_slptr( ) != 0) {
00661 sleeping = true;
00662 }
00663
00664 return sleeping;
00665 }
00666
00687 tat_status_t tat_set_trx_state( uint8_t new_state ){
00688
00689
00690 if (!((new_state == TRX_OFF ) || (new_state == RX_ON) || (new_state == PLL_ON) ||
00691 (new_state == RX_AACK_ON ) || (new_state == TX_ARET_ON ))) {
00692
00693 return TAT_INVALID_ARGUMENT;
00694 }
00695
00696 if (is_sleeping( ) == true) { return TAT_WRONG_STATE; }
00697
00698 uint8_t original_state = tat_get_trx_state( );
00699
00700 if ((original_state == BUSY_RX ) || (original_state == BUSY_TX) ||
00701 (original_state == BUSY_RX_AACK) || (original_state == BUSY_TX_ARET)) {
00702 return TAT_BUSY_STATE;
00703 }
00704
00705 if (new_state == original_state) { return TAT_SUCCESS; }
00706
00707
00708
00709
00710
00711
00712 if( new_state == TRX_OFF ){
00713 tat_reset_state_machine( );
00714 } else {
00715
00716
00717
00718 if ((new_state == TX_ARET_ON) && (original_state == RX_AACK_ON)) {
00719
00720
00721
00722 hal_subregister_write( SR_TRX_CMD, PLL_ON );
00723 delay_us( TIME_STATE_TRANSITION_PLL_ACTIVE );
00724 } else if ((new_state == RX_AACK_ON) && (original_state == TX_ARET_ON)) {
00725
00726
00727
00728 hal_subregister_write( SR_TRX_CMD, RX_ON );
00729 delay_us( TIME_STATE_TRANSITION_PLL_ACTIVE );
00730 }
00731
00732
00733 hal_subregister_write( SR_TRX_CMD, new_state );
00734
00735
00736
00737 if (original_state == TRX_OFF) {
00738 delay_us( TIME_TRX_OFF_TO_PLL_ACTIVE );
00739 } else {
00740 delay_us( TIME_STATE_TRANSITION_PLL_ACTIVE );
00741 }
00742 }
00743
00744
00745 tat_status_t set_state_status = TAT_TIMED_OUT;
00746
00747 if( tat_get_trx_state( ) == new_state ){ set_state_status = TAT_SUCCESS; }
00748
00749 return set_state_status;
00750 }
00751
00759 tat_status_t tat_enter_sleep_mode( void ){
00760
00761 if (is_sleeping( ) == true) { return TAT_SUCCESS; }
00762
00763 tat_reset_state_machine( );
00764
00765 tat_status_t enter_sleep_status = TAT_TIMED_OUT;
00766
00767 if (tat_get_trx_state( ) == TRX_OFF) {
00768
00769
00770 hal_set_slptr_high( );
00771 enter_sleep_status = TAT_SUCCESS;
00772 }
00773
00774 return enter_sleep_status;
00775 }
00776
00785 tat_status_t tat_leave_sleep_mode( void ){
00786
00787
00788 if (is_sleeping( ) == false) { return TAT_SUCCESS; }
00789
00790 hal_set_slptr_low( );
00791 delay_us( TIME_SLEEP_TO_TRX_OFF );
00792
00793 tat_status_t leave_sleep_status = TAT_TIMED_OUT;
00794
00795
00796 if (tat_get_trx_state( ) == TRX_OFF) {
00797 leave_sleep_status = TAT_SUCCESS;
00798 }
00799
00800 return leave_sleep_status;
00801 }
00802
00808 void tat_reset_state_machine( void ){
00809
00810 hal_set_slptr_low( );
00811 delay_us( TIME_NOCLK_TO_WAKE );
00812 hal_subregister_write( SR_TRX_CMD, CMD_FORCE_TRX_OFF );
00813 delay_us( TIME_CMD_FORCE_TRX_OFF );
00814 }
00815
00821 void tat_reset_trx( void ){
00822
00823 hal_set_rst_low( );
00824 hal_set_slptr_low( );
00825 delay_us( TIME_RESET );
00826 hal_set_rst_high( );
00827 }
00828
00839 void tat_use_auto_tx_crc( bool auto_crc_on ){
00840
00841 if (auto_crc_on == true) {
00842 hal_subregister_write( SR_TX_AUTO_CRC_ON, 1 );
00843 } else {
00844 hal_subregister_write( SR_TX_AUTO_CRC_ON, 0 );
00845 }
00846 }
00847
00863 tat_status_t tat_send_data( uint8_t *data, uint8_t data_length ){
00864
00865
00866 if (data_length > RF230_MAX_TX_FRAME_LENGTH) { return TAT_INVALID_ARGUMENT; }
00867
00868 if ((tat_get_trx_state( ) != PLL_ON)) { return TAT_WRONG_STATE; }
00869
00870
00871
00872 hal_set_slptr_high( );
00873 hal_set_slptr_low( );
00874
00875 hal_frame_write( data, data_length );
00876
00877 return TAT_SUCCESS;
00878 }
00879
00886 uint16_t tat_get_pan_id( void ){
00887
00888
00889 union{
00890
00891 uint16_t u16;
00892 uint8_t u8[ 2 ];
00893 }pan_id;
00894
00895 pan_id.u8[ 0 ] = hal_register_read( RG_PAN_ID_1 );
00896 pan_id.u8[ 1 ] = hal_register_read( RG_PAN_ID_0 );
00897
00898 return pan_id.u16;
00899 }
00900
00907 void tat_set_pan_id( uint16_t new_pan_id ){
00908
00909
00910 union{
00911
00912 uint16_t u16;
00913 uint8_t u8[ 2 ];
00914 }pan_id;
00915
00916 pan_id.u16 = new_pan_id;
00917
00918 hal_register_write( RG_PAN_ID_1, pan_id.u8[ 0 ] );
00919 hal_register_write( RG_PAN_ID_0, pan_id.u8[ 1 ] );
00920 }
00921
00929 uint16_t tat_get_short_address( void ){
00930
00931
00932 union{
00933
00934 uint16_t u16;
00935 uint8_t u8[ 2 ];
00936 }short_address;
00937
00938 short_address.u8[ 0 ] = hal_register_read( RG_SHORT_ADDR_1 );
00939 short_address.u8[ 1 ] = hal_register_read( RG_SHORT_ADDR_0 );
00940
00941 return short_address.u16;
00942 }
00943
00950 void tat_set_short_address( uint16_t new_short_address ){
00951
00952
00953 union{
00954
00955 uint16_t u16;
00956 uint8_t u8[ 2 ];
00957 }short_address;
00958
00959 short_address.u16 = new_short_address;
00960
00961 hal_register_write( RG_SHORT_ADDR_1, short_address.u8[ 0 ] );
00962 hal_register_write( RG_SHORT_ADDR_0, short_address.u8[ 1 ] );
00963 }
00964
00972 uint64_t tat_get_extended_address( void ){
00973
00974
00975 union{
00976
00977 uint64_t u64;
00978 uint8_t u8[ 8 ];
00979 }extended_address;
00980
00981 extended_address.u8[ 0 ] = hal_register_read( RG_IEEE_ADDR_7 );
00982 extended_address.u8[ 1 ] = hal_register_read( RG_IEEE_ADDR_6 );
00983 extended_address.u8[ 2 ] = hal_register_read( RG_IEEE_ADDR_5 );
00984 extended_address.u8[ 3 ] = hal_register_read( RG_IEEE_ADDR_4 );
00985 extended_address.u8[ 4 ] = hal_register_read( RG_IEEE_ADDR_3 );
00986 extended_address.u8[ 5 ] = hal_register_read( RG_IEEE_ADDR_2 );
00987 extended_address.u8[ 6 ] = hal_register_read( RG_IEEE_ADDR_1 );
00988 extended_address.u8[ 7 ] = hal_register_read( RG_IEEE_ADDR_0 );
00989
00990 return extended_address.u64;
00991 }
00992
01000 void tat_set_extended_address( uint64_t new_extended_address ){
01001
01002
01003 union{
01004
01005 uint64_t u64;
01006 uint8_t u8[ 8 ];
01007 }extended_address;
01008
01009 extended_address.u64 = new_extended_address;
01010
01011 hal_register_write( RG_IEEE_ADDR_7, extended_address.u8[ 0 ] );
01012 hal_register_write( RG_IEEE_ADDR_6, extended_address.u8[ 1 ] );
01013 hal_register_write( RG_IEEE_ADDR_5, extended_address.u8[ 2 ] );
01014 hal_register_write( RG_IEEE_ADDR_4, extended_address.u8[ 3 ] );
01015 hal_register_write( RG_IEEE_ADDR_3, extended_address.u8[ 4 ] );
01016 hal_register_write( RG_IEEE_ADDR_2, extended_address.u8[ 5 ] );
01017 hal_register_write( RG_IEEE_ADDR_1, extended_address.u8[ 6 ] );
01018 hal_register_write( RG_IEEE_ADDR_0, extended_address.u8[ 7 ] );
01019 }
01020
01042 tat_status_t tat_configure_csma( uint8_t seed0, uint8_t be_csma_seed1 ){
01043
01044
01045 if (is_sleeping( ) == true) { return TAT_WRONG_STATE; }
01046
01047
01048 uint8_t back_off_exponent = ( be_csma_seed1 & 0xC0 ) >> 6;
01049 uint8_t csma_retries = ( be_csma_seed1 & 0x38 ) >> 3;
01050 uint8_t seed1 = ( be_csma_seed1 & 0x07 );
01051
01052 hal_subregister_write( SR_MAX_FRAME_RETRIES, 0 );
01053 hal_subregister_write( SR_MAX_CSMA_RETRIES, csma_retries );
01054 hal_subregister_write( SR_MIN_BE, back_off_exponent );
01055 hal_subregister_write( SR_CSMA_SEED_0, seed0 );
01056 hal_subregister_write( SR_CSMA_SEED_1, seed1 );
01057
01058 return TAT_SUCCESS;
01059 }
01060
01081 tat_status_t tat_send_data_with_retry( uint8_t frame_length, uint8_t *frame,
01082 uint8_t retries ){
01083
01084 tat_status_t task_status = TAT_CHANNEL_ACCESS_FAILURE;
01085
01086
01087 if ((frame_length > RF230_MAX_TX_FRAME_LENGTH) ||
01088 (frame_length < TAT_MIN_IEEE_FRAME_LENGTH)) {
01089 return TAT_INVALID_ARGUMENT;
01090 }
01091
01092 if (tat_get_trx_state( ) != TX_ARET_ON) { return TAT_WRONG_STATE; }
01093
01094 hal_clear_trx_end_flag( );
01095
01096
01097 hal_set_slptr_high( );
01098 hal_set_slptr_low( );
01099 hal_frame_write( frame, frame_length );
01100
01101 bool retry = false;
01102
01103
01104 do{
01105
01106
01107 while (hal_get_trx_end_flag( ) == 0) {;}
01108
01109
01110 uint8_t transaction_status = hal_subregister_read( SR_TRAC_STATUS );
01111
01112
01113 if ((transaction_status != TAT_TRANSMISSION_SUCCESS)) {
01114
01115 if (transaction_status == TAT_BUSY_CHANNEL) {
01116 task_status = TAT_CHANNEL_ACCESS_FAILURE;
01117 } else {
01118 task_status = TAT_NO_ACK;
01119 }
01120
01121 if ((retries--) > 0) {
01122
01123 retry = true;
01124
01125
01126 while (tat_get_trx_state() != TX_ARET_ON) {;}
01127
01128 hal_clear_trx_end_flag( );
01129 hal_set_slptr_high( );
01130 hal_set_slptr_low( );
01131 } else {
01132 retry = false;
01133 }
01134 } else{
01135
01136 task_status = TAT_SUCCESS;
01137 retry = false;
01138 }
01139 } while (retry == true);
01140
01141 return task_status;
01142 }
01143