• Main Page
  • Modules
  • Index
  • File List
  • Globals

gazell/common/gzll.c

Go to the documentation of this file.
00001 /* Copyright (c) 2009 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is confidential property of Nordic
00004  * Semiconductor ASA.Terms and conditions of usage are described in detail
00005  * in NORDIC SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRENTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *
00011  * $LastChangedRevision: 2368 $
00012  */
00013 
00018 #include "gzll.h"
00019 #include <string.h>
00020 
00021 #ifdef __C51__
00022 #include <intrins.h>
00023 #elif __ICC8051__
00024 #include <intrinsics.h>
00025 #endif
00026 
00027 #include "hal_delay.h"
00028 
00029 #define GZLL_PULSE_FIX
00030 
00031 /*-----------------------------------------------------------------------------
00032   Misc. Internal function prototypes
00033 -----------------------------------------------------------------------------*/
00034 
00048 static uint8_t gzll_lfsr_get(uint8_t seed, uint8_t max_limit);
00049 
00053 void gzll_delay_50us(uint8_t n);
00054 
00059 typedef enum
00060 {
00061   GZLL_CHANNEL_PREVIOUS_SUCCESS,
00062   GZLL_CHANNEL_RANDOM,
00063   GZLL_CHANNEL_ESTIMATED,
00064   GZLL_CHANNEL_NEXT_INDEX
00065 } gzll_new_tx_ch_t;
00066 
00076 static void gzll_start_new_tx(gzll_new_tx_ch_t channel_select);
00077 
00082 static void gzll_reload_tries_pr_channel_counter(void);
00083 
00089 static void gzll_set_radio_auto_retries(void);
00090 
00094 static void gzll_set_system_idle(void);
00095 
00100 static void gzll_interupts_disable_rfck_enable(void);
00101 
00106 static void gzll_interupts_enable_rfck_disable(void);
00107 
00108 /*-----------------------------------------------------------------------------
00109   Channel Manager (CHM) function prototypes
00110 -----------------------------------------------------------------------------*/
00111 
00116 static void gzll_chm_reset_rx_channel_index(void);
00117 
00124 static uint8_t gzll_chm_get_current_rx_channel(void);
00125 
00131 static uint8_t gzll_chm_get_next_rx_channel(void);
00132 
00138 static void gzll_chm_hold_rx_channel(void);
00139 
00144 static void gzll_chm_execute(void);
00145 
00153 static uint16_t gzll_chm_get_rx_ce_offset(void);
00154 
00163 static uint16_t gzll_chm_get_tx_ce_offset(void);
00164 
00165 /*-----------------------------------------------------------------------------
00166   Radio power manager (PM) function prototypes
00167 -----------------------------------------------------------------------------*/
00168 
00174 static void gzll_set_radio_power_on(bool on);
00175 
00176 /*-----------------------------------------------------------------------------
00177   Function prototypes for assembling / disassembling encrypted packages
00178 -----------------------------------------------------------------------------*/
00179 
00194 static void gzll_crypt_payload_assemble(uint8_t *dst, uint8_t *src, uint8_t length_src, uint8_t *aes_key);
00195 
00211 static void gzll_crypt_payload_disassemble(uint8_t *dst, uint8_t *src, uint8_t length_src, uint8_t *aes_key);
00212 
00213 /*-----------------------------------------------------------------------------
00214   Global variables
00215 -----------------------------------------------------------------------------*/
00216 
00217 /*
00218   Dynamic parameters.
00219 */
00220 static uint16_t xdata gzll_dyn_params[GZLL_DYN_PARAM_SIZE];
00221 
00222 /*
00223   Channel subset array.
00224 */
00225 static uint8_t xdata gzll_channel_tab[GZLL_MAX_CHANNEL_TAB_SIZE] = GZLL_DEFAULT_CHANNEL_TAB;
00226 
00227 /*
00228   Pipe 0 address shadow register.
00229 */
00230 static uint8_t xdata gzll_p0_adr[GZLL_ADDRESS_WIDTH] = GZLL_DEFAULT_ADDRESS_PIPE0;
00231 
00232 #ifdef __C51__
00233 static uint16_t bdata gzll_bit_storage;
00234 #define GZLL_BIT(_var, _bitnum) sbit _var = gzll_bit_storage ^ _bitnum
00235 #else
00236 #define GZLL_BIT(_var, _bitnum) static xdata bool volatile _var
00237 #endif
00238 
00239 /*
00240   Status variables.
00241 */
00242 GZLL_BIT(gzll_tx_success_f, 0);       // Result of previous transmission
00243 GZLL_BIT(gzll_tx_setup_modified, 1);  // TX setup modified since previous transmission
00244 GZLL_BIT(gzll_rx_setup_modified, 2);  // RX setup modified since previous receive session
00245 GZLL_BIT(gzll_sync_on, 3);            // Sync on
00246 GZLL_BIT(gzll_rx_dr, 4);              // Received data ready
00247 GZLL_BIT(gzll_rx_power_high_f, 5);    // Receive signal strength high
00248 GZLL_BIT(gzll_radio_active_f, 6);     // For assisting power management in application
00249 GZLL_BIT(gzll_power_on, 7);
00250 
00251 static xdata uint8_t volatile gzll_current_tx_pipe;            // Current TX pipe setup
00252 static xdata uint8_t volatile gzll_current_tx_payload_length;  // Current TX payload length
00253 static xdata uint8_t volatile gzll_channel_tab_size;           // Channel subset size
00254 static xdata uint8_t volatile gzll_channel_tab_index;          // Channel subset index
00255 static xdata gzll_states_t volatile gzll_state_var;            // State variable
00256 
00257 /*
00258   Variables for signaling to timer and radio ISR.
00259 */
00260 GZLL_BIT(gzll_pending_tx_start, 8);       // Transmission should be started in next timer ISR
00261 GZLL_BIT(gzll_pending_goto_idle, 9);      // Goto idle when current radio events completed
00262 GZLL_BIT(gzll_timer_period_modified, 10);  // Timer period temporarily modified
00263 GZLL_BIT(gzll_claim_rfck_en, 11);
00264 GZLL_BIT(b_rfce, 12);
00265 
00266 /*
00267   FIFO holding receive pipes for ACK payloads
00268   residing in radio HW RX FIFO.
00269 */
00270 static xdata uint8_t gzll_ack_rx_pipe_fifo[3];        // FIFO holding pipe for received ACK payload
00271 static xdata uint8_t gzll_ack_rx_pipe_fifo_cnt;       // FIFO index
00272 
00273 /*
00274   Counters.
00275 */
00276 static xdata uint8_t gzll_tries_pr_channel_counter;   // Counter used for counting transmit attempts before channel switch
00277 static xdata uint16_t gzll_sync_period;               // Counter for counting duration since previous successfull TX
00278 static xdata uint16_t gzll_timeout_counter;            // Counter used for TX/RX timeout
00279 
00280 /*
00281   Transmission statistics.
00282 */
00283 static xdata uint16_t gzll_channel_switch_counter;    // Channel switches for previous transmission
00284 static xdata uint16_t gzll_try_counter;               // Transmit attempts for previous transmission
00285 
00286 /*
00287   Macros / functions for disabling/enabling Gazell interrupts and
00288   the radio enable (RFEN) and radio clk enable (RFCKEN).
00289 
00290   The logical relation between RFCKEN and RFEN expresses as:
00291 
00292   RFCKEN = GZLL_RFCK_ENABLE() || GZLL_RFCE_HIGH()
00293 
00294 */
00295 
00296 #define GZLL_INTERRUPTS_DISABLE() do{ \
00297   RFEN = 0;                           \
00298   TIMEREN = 0;                        \
00299 }while(0)
00300 
00301 #define GZLL_INTERRUPTS_ENABLE() do{  \
00302   RFEN = 1;                           \
00303   TIMEREN = 1;                        \
00304 }while(0)
00305 
00306 #ifdef GZLL_PULSE_FIX
00307 #define GZLL_RFCK_ENABLE() do{ \
00308   gzll_claim_rfck_en = 1;      \
00309   RFCKEN = 1;                  \
00310 } while(0)
00311 
00312 #define GZLL_RFCK_DISABLE() do{ \
00313   gzll_claim_rfck_en = 0;       \
00314   RFCKEN = b_rfce; \
00315 } while(0)
00316 
00317 #define GZLL_RFCE_PULSE() do{ \
00318   RFCKEN = 1;                \
00319   RFCE = 1;                  \
00320   b_rfce = true; \
00321   delay_us(10); \
00322   RFCE = 0; \
00323 } while(false)
00324 
00325 #define GZLL_RFCE_HIGH() do{ \
00326   RFCKEN = 1;                \
00327   RFCE = 1;                  \
00328   b_rfce = true; \
00329 } while(false)
00330 
00331 #define GZLL_RFCE_LOW() do{ \
00332   RFCE = 0;                       \
00333   RFCKEN = gzll_claim_rfck_en;    \
00334   b_rfce = false; \
00335 } while(0)
00336 
00337 #else
00338 
00339 #define GZLL_RFCK_ENABLE() do{ \
00340   gzll_claim_rfck_en = 1;      \
00341   RFCKEN = 1;                  \
00342 } while(0)
00343 
00344 #define GZLL_RFCK_DISABLE() do{ \
00345   gzll_claim_rfck_en = 0;       \
00346   RFCKEN = RFCE; \
00347 } while(0)
00348 
00349 
00350 #define GZLL_RFCE_HIGH() do{ \
00351   RFCKEN = 1;                \
00352   RFCE = 1;                  \
00353 } while(false)
00354 
00355 #define GZLL_RFCE_PULSE() GZLL_RFCE_HIGH()
00356 
00357 #define GZLL_RFCE_LOW() do{ \
00358   RFCE = 0;                       \
00359   RFCKEN = gzll_claim_rfck_en;    \
00360 } while(0)
00361 
00362 #endif
00363 
00364 static void gzll_interupts_disable_rfck_enable()
00365 {
00366   uint8_t t_ea;
00367   t_ea = EA;
00368   EA = 0;
00369   GZLL_INTERRUPTS_DISABLE();
00370   GZLL_RFCK_ENABLE();
00371   EA = t_ea;
00372 }
00373 
00374 static void gzll_interupts_enable_rfck_disable()
00375 {
00376   GZLL_INTERRUPTS_ENABLE();
00377   GZLL_RFCK_DISABLE();
00378 }
00379 
00380 /*-----------------------------------------------------------------------------
00381   Implementation: Application interface (user functions)
00382 -----------------------------------------------------------------------------*/
00383 
00384 void gzll_init(void)
00385 {
00386   uint8_t temp_adr[GZLL_ADDRESS_WIDTH] = GZLL_DEFAULT_ADDRESS_PIPE1;
00387 
00388   gzll_interupts_disable_rfck_enable();
00389   GZLL_RFCE_LOW();
00390 
00391   hal_nrf_enable_ack_payload(true);
00392   hal_nrf_enable_dynamic_payload(true);
00393   hal_nrf_setup_dynamic_payload(0xff);
00394 
00395   /*
00396   Initialize status variables.
00397   */
00398   gzll_channel_tab_index = 0;
00399   gzll_channel_tab_size = GZLL_DEFAULT_CHANNEL_TAB_SIZE;
00400 
00401   gzll_pending_goto_idle = false;
00402   gzll_timer_period_modified = false;
00403 
00404   gzll_current_tx_pipe = 0;
00405   gzll_pending_tx_start = false;
00406   gzll_tx_setup_modified = true;
00407   gzll_rx_setup_modified = true;
00408   gzll_radio_active_f = false;
00409   gzll_tx_success_f = true;
00410 
00411   gzll_sync_period = 0;
00412   gzll_sync_on = false;
00413 
00414   gzll_rx_dr = false;
00415   gzll_rx_power_high_f = false;
00416   gzll_ack_rx_pipe_fifo_cnt = 0;
00417 
00418   /*
00419   Set up default addresses.
00420   */
00421   hal_nrf_set_address(HAL_NRF_PIPE0, gzll_p0_adr);
00422   hal_nrf_set_address(HAL_NRF_PIPE1, temp_adr);
00423 
00424   temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE2;
00425   hal_nrf_set_address(HAL_NRF_PIPE2, temp_adr);
00426 
00427   temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE3;
00428   hal_nrf_set_address(HAL_NRF_PIPE3, temp_adr);
00429 
00430   temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE4;
00431   hal_nrf_set_address(HAL_NRF_PIPE4, temp_adr);
00432 
00433   temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE5;
00434   hal_nrf_set_address(HAL_NRF_PIPE5, temp_adr);
00435 
00436   /*
00437   Set up default channel.
00438   */
00439   hal_nrf_set_rf_channel(gzll_channel_tab[gzll_channel_tab_index]);
00440 
00441   /*
00442   Initialize dynamic parameters using default values.
00443   */
00444   gzll_dyn_params[GZLL_PARAM_DEVICE_MODE] = GZLL_DEFAULT_PARAM_DEVICE_MODE;
00445   gzll_dyn_params[GZLL_PARAM_TX_TIMEOUT] = GZLL_DEFAULT_PARAM_TX_TIMEOUT;
00446   gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_ON] = GZLL_DEFAULT_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_ON;
00447   gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_OFF] = GZLL_DEFAULT_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_OFF;
00448   gzll_dyn_params[GZLL_PARAM_HOST_MODE] = GZLL_DEFAULT_PARAM_HOST_MODE;
00449   gzll_dyn_params[GZLL_PARAM_RX_PIPES] = GZLL_DEFAULT_PARAM_RX_PIPES;
00450   gzll_dyn_params[GZLL_PARAM_CRYPT_PIPES] = GZLL_DEFAULT_PARAM_CRYPT_PIPES;
00451   gzll_dyn_params[GZLL_PARAM_RX_TIMEOUT] = GZLL_DEFAULT_PARAM_RX_TIMEOUT;
00452   gzll_dyn_params[GZLL_PARAM_HOST_MODE_1_CYCLE_PERIOD] = GZLL_DEFAULT_PARAM_HOST_MODE_1_CYCLE_PERIOD;
00453   gzll_dyn_params[GZLL_PARAM_RX_PERIOD] = GZLL_DEFAULT_PARAM_RX_PERIOD;
00454   gzll_dyn_params[GZLL_PARAM_RX_PERIOD_MODIFIER] = GZLL_DEFAULT_PARAM_RX_PERIOD_MODIFIER;
00455   gzll_dyn_params[GZLL_PARAM_RX_CHANNEL_HOLD_PERIODS] = GZLL_DEFAULT_PARAM_RX_CHANNEL_HOLD_PERIODS;
00456   gzll_dyn_params[GZLL_PARAM_OUTPUT_POWER] = GZLL_DEFAULT_PARAM_OUTPUT_POWER;
00457   gzll_dyn_params[GZLL_PARAM_POWER_DOWN_IDLE_ENABLE] = GZLL_DEFAULT_PARAM_POWER_DOWN_IDLE_ENABLE;
00458   gzll_dyn_params[GZLL_PARAM_MAX_SYNC_PERIOD] = GZLL_DEFAULT_PARAM_MAX_SYNC_PERIOD;
00459   gzll_dyn_params[GZLL_PARAM_COLLISION_CHANNEL_SWITCH_LIMIT] = GZLL_DEFAULT_PARAM_COLLISION_CHANNEL_SWITCH_LIMIT;
00460 
00461   /*
00462   Set up default output power.
00463   */
00464   hal_nrf_set_output_power((hal_nrf_output_power_t) gzll_dyn_params[GZLL_PARAM_OUTPUT_POWER]);
00465 
00466   /*
00467   Static radio setup.
00468   */
00469   hal_nrf_set_datarate(GZLL_HAL_DATARATE);
00470   hal_nrf_set_crc_mode(GZLL_CRC);
00471   hal_nrf_set_address_width(GZLL_ADDRESS_WIDTH);
00472 
00473   /*
00474   Clear radio IRQ flags.
00475   */
00476   //lint -esym(534, hal_nrf_get_clear_irq_flags) "return value ignored"
00477   hal_nrf_get_clear_irq_flags();
00478 
00479   hal_nrf_flush_rx();
00480   hal_nrf_flush_tx();
00481 
00482   gzll_set_timer_period(GZLL_DEFAULT_PARAM_RX_PERIOD);
00483   gzll_set_system_idle();
00484   gzll_interupts_enable_rfck_disable();
00485 }
00486 
00487 void gzll_set_param(gzll_dyn_params_t param, uint16_t val)
00488 {
00489   ASSERT((gzll_state_var == GZLL_IDLE));
00490   ASSERT((param < GZLL_DYN_PARAM_SIZE));
00491   ASSERT(!(param == GZLL_PARAM_DEVICE_MODE && val > GZLL_DEVICE_MODE_4));
00492   ASSERT(!(param == GZLL_PARAM_HOST_MODE && val > GZLL_HOST_MODE_1));
00493   ASSERT(!(param == GZLL_PARAM_RX_PIPES && val > 0x3f));
00494   ASSERT(!(param == GZLL_PARAM_CRYPT_PIPES && val > GZLL_MAX_CRYPT_PIPES_VAL));
00495   ASSERT(!(param == GZLL_PARAM_OUTPUT_POWER && val > 3));
00496 
00497   gzll_interupts_disable_rfck_enable();
00498 
00499   if(param < GZLL_DYN_PARAM_SIZE)
00500   {
00501     gzll_dyn_params[param] = val;
00502 
00503     switch(param)
00504     {
00505       case GZLL_PARAM_DEVICE_MODE:
00506         if((val == GZLL_DEVICE_MODE_0 || val == GZLL_DEVICE_MODE_1))
00507         {
00508           gzll_sync_on = false;
00509         }
00510         break;
00511       case GZLL_PARAM_POWER_DOWN_IDLE_ENABLE:
00512         if(val == 1)
00513         {
00514           gzll_set_radio_power_on(false);
00515         }
00516         break;
00517       case GZLL_PARAM_RX_PERIOD:
00518         gzll_timer_period_modified = 1;
00519         break;
00520       case GZLL_PARAM_OUTPUT_POWER:
00521         hal_nrf_set_output_power((hal_nrf_output_power_t)gzll_dyn_params[GZLL_PARAM_OUTPUT_POWER]);
00522         break;
00523       case GZLL_PARAM_RX_PIPES:
00524         gzll_rx_setup_modified = true;
00525         break;
00526     }
00527   }
00528 
00529   gzll_interupts_enable_rfck_disable();
00530 }
00531 
00532 uint16_t gzll_get_param_max(gzll_dyn_params_t param)
00533 {
00534   uint16_t param_max[GZLL_DYN_PARAM_SIZE] = GZLL_PARAMS_MAX;
00535 
00536   return param_max[param];
00537 }
00538 
00539 uint16_t gzll_get_param(gzll_dyn_params_t param)
00540 {
00541   ASSERT((param < GZLL_DYN_PARAM_SIZE));
00542 
00543   gzll_interupts_disable_rfck_enable();
00544 
00545   if(param < GZLL_DYN_PARAM_SIZE)
00546   {
00547     gzll_interupts_enable_rfck_disable();
00548     return gzll_dyn_params[param];
00549   }
00550   else
00551   {
00552     gzll_interupts_enable_rfck_disable();
00553     return 0;
00554   }
00555 }
00556 
00557 uint8_t gzll_get_channel_tab_size()
00558 {
00559   return gzll_channel_tab_size;
00560 }
00561 
00562 void gzll_get_channels(uint8_t *channels)
00563 {
00564   memcpy(channels, gzll_channel_tab, gzll_channel_tab_size);
00565 }
00566 
00567 void gzll_set_channels(uint8_t *channels, uint8_t channel_tab_size)
00568 {
00569   gzll_interupts_disable_rfck_enable();
00570 
00571   ASSERT((gzll_state_var == GZLL_IDLE));
00572   ASSERT((channel_tab_size <= GZLL_MAX_CHANNEL_TAB_SIZE));
00573 
00574   gzll_channel_tab_index = 0;
00575   gzll_channel_tab_size = channel_tab_size;
00576   memcpy(gzll_channel_tab, channels, gzll_channel_tab_size);
00577 
00578   hal_nrf_set_rf_channel(gzll_channel_tab[gzll_channel_tab_index]);
00579 
00580   gzll_interupts_enable_rfck_disable();
00581 }
00582 
00583 void gzll_set_address(hal_nrf_address_t pipe, const uint8_t *address)
00584 {
00585   ASSERT((gzll_state_var == GZLL_IDLE));
00586   ASSERT((pipe <= 5));
00587 
00588   gzll_interupts_disable_rfck_enable();
00589 
00590   gzll_tx_setup_modified = true;
00591   gzll_rx_setup_modified = true;
00592 
00593   if(pipe == HAL_NRF_PIPE0)
00594   {
00595     memcpy(gzll_p0_adr, (uint8_t*)address, GZLL_ADDRESS_WIDTH);
00596   }
00597 
00598   hal_nrf_set_address(pipe, address);
00599 
00600   gzll_interupts_enable_rfck_disable();
00601 }
00602 
00603 void gzll_get_address(uint8_t pipe, uint8_t* address)
00604 {
00605   ASSERT((pipe <= 5));
00606   ASSERT(address != NULL);
00607 
00608   gzll_interupts_disable_rfck_enable();
00609 
00610   hal_nrf_get_address(pipe, address); //lint !e534 "return value ignored"
00611 
00612   gzll_interupts_enable_rfck_disable();
00613 }
00614 
00615 #ifndef GZLL_DEVICE_ONLY
00616 
00617 
00618 void gzll_rx_start()
00619 {
00620   uint8_t i;
00621 
00622   gzll_goto_idle();
00623 
00624   if(gzll_rx_setup_modified)
00625   {
00626     gzll_interupts_disable_rfck_enable();
00627 
00628     gzll_rx_setup_modified = false;
00629     gzll_tx_setup_modified = true;
00630 
00631     /*
00632     Restore pipe 0 address (this may have been altered during transmission)
00633     */
00634     hal_nrf_set_address(HAL_NRF_PIPE0, gzll_p0_adr);
00635 
00636     /*
00637     Enable the receive pipes selected by gzll_set_param()
00638     */
00639     hal_nrf_close_pipe(HAL_NRF_ALL);
00640     for(i = 0; i < 6; i++)
00641     {
00642       if(gzll_dyn_params[GZLL_PARAM_RX_PIPES] & (1 << i))
00643       {
00644         hal_nrf_open_pipe((hal_nrf_address_t)i, EN_AA);
00645       }
00646     }
00647     hal_nrf_set_operation_mode(HAL_NRF_PRX);
00648   }
00649 
00650   gzll_set_radio_power_on(true);
00651   gzll_timeout_counter = 0;
00652   gzll_state_var = GZLL_HOST_ACTIVE;
00653 
00654   GZLL_RFCE_HIGH();
00655   gzll_interupts_enable_rfck_disable();
00656 }
00657 
00658 bool gzll_ack_payload_write(const uint8_t *src, uint8_t length, uint8_t pipe)
00659 {
00660   ASSERT(length <= GZLL_MAX_ACK_PAYLOAD_LENGTH && length > 0);
00661   ASSERT(pipe <= 5);
00662 
00663   gzll_interupts_disable_rfck_enable();
00664 
00665   if(length == 0 || (length > GZLL_MAX_ACK_PAYLOAD_LENGTH) || hal_nrf_tx_fifo_full())
00666   {
00667     gzll_interupts_enable_rfck_disable();
00668     return false;                             // ACK payload not written
00669   }
00670   hal_nrf_write_ack_payload(pipe, src, length);
00671   gzll_interupts_enable_rfck_disable();
00672   return true;                                // ACK payload successfully written
00673 }
00674 
00675 #endif
00676 
00677 #define GZLL_UPLOAD_PAYLOAD_TO_RADIO() hal_nrf_write_tx_payload(src, length)
00678 
00679 #ifndef GZLL_HOST_ONLY
00680 
00681 bool gzll_tx_data(const uint8_t *src, uint8_t length, uint8_t pipe)
00682 {
00683   uint8_t temp_address[GZLL_ADDRESS_WIDTH];
00684   uint16_t temp;
00685 
00686   ASSERT(length <= GZLL_MAX_FW_PAYLOAD_LENGTH && length > 0);
00687   ASSERT(pipe <= 5);
00688 
00689   /*
00690   Length check to prevent memory corruption. (Note, assertion
00691   will capture this as well).
00692   */
00693   if(length == 0 || length > GZLL_MAX_FW_PAYLOAD_LENGTH)
00694   {
00695     return false;
00696   }
00697 
00698   gzll_current_tx_payload_length = length;
00699 
00700   if(gzll_state_var == GZLL_HOST_ACTIVE)
00701   {
00702     gzll_goto_idle();
00703   }
00704 
00705   gzll_interupts_disable_rfck_enable();
00706 
00707   /*
00708   If the specified pipe is different from the previous TX pipe,
00709   the TX setup must be updated
00710   */
00711   if(pipe != gzll_current_tx_pipe)
00712   {
00713     gzll_current_tx_pipe = pipe;
00714     gzll_tx_setup_modified = true;
00715   }
00716 
00717   /*
00718   Here, state can be GZLL_IDLE or GZLL_DEVICE_ACTIVE
00719   */
00720   if(gzll_state_var == GZLL_IDLE)
00721   {
00722     if(gzll_tx_setup_modified)       // TX setup has to be restored?
00723     {
00724       gzll_tx_setup_modified = false;
00725       gzll_rx_setup_modified = true;
00726 
00727       hal_nrf_set_operation_mode(HAL_NRF_PTX);
00728       hal_nrf_open_pipe(HAL_NRF_PIPE0, EN_AA);
00729 
00730        //Read out the full RX address for pipe number "pipe"
00731       if(pipe == HAL_NRF_PIPE0)
00732       {
00733         hal_nrf_set_address(HAL_NRF_TX, gzll_p0_adr);
00734         hal_nrf_set_address(HAL_NRF_PIPE0, gzll_p0_adr);
00735       }
00736       else
00737       {
00738         //lint -esym(550,bytes_in_buffer) "variable not accessed"
00739         //lint -esym(438,bytes_in_buffer) "last assigned value not used"
00740         uint8_t bytes_in_buffer;
00741         bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE1, temp_address);
00742         if(pipe != HAL_NRF_PIPE1)
00743         {
00744           switch(pipe)
00745           {
00746             default:
00747             case HAL_NRF_PIPE2:
00748               bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE2, temp_address);
00749               break;
00750             case HAL_NRF_PIPE3:
00751               bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE3, temp_address);
00752               break;
00753             case HAL_NRF_PIPE4:
00754               bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE4, temp_address);
00755               break;
00756             case HAL_NRF_PIPE5:
00757               bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE5, temp_address);
00758               break;
00759           }
00760         }
00761 
00762         //Here, temp_address will contain the full TX address
00763         hal_nrf_set_address(HAL_NRF_PIPE0, temp_address);
00764         hal_nrf_set_address(HAL_NRF_TX, temp_address);
00765 
00766         /*
00767         Change seed for random generator. Will prevent different devices
00768         transmitting to the same host from using the same channel hopping
00769         sequence.
00770         */
00771         //lint -esym(534, gzll_lfsr_get) "return value ignored"
00772         gzll_lfsr_get(pipe, 1);
00773       }
00774     }
00775 
00776     // Prepare for new transmission
00777     gzll_timeout_counter = 0;
00778     gzll_channel_switch_counter = 0;
00779     gzll_try_counter = 0;
00780     hal_nrf_flush_tx();
00781 
00782     GZLL_UPLOAD_PAYLOAD_TO_RADIO();
00783 
00784     gzll_tx_success_f = false;                // Transmission by default "failure"
00785 
00786     temp = gzll_dyn_params[GZLL_PARAM_DEVICE_MODE];
00787 
00788     gzll_set_radio_power_on(true);
00789     if(gzll_sync_on)
00790     {
00791       switch(temp)
00792       {
00793         case GZLL_DEVICE_MODE_2:
00794         default:
00795           gzll_start_new_tx(GZLL_CHANNEL_PREVIOUS_SUCCESS);
00796           break;
00797         case GZLL_DEVICE_MODE_3:
00798           gzll_start_new_tx(GZLL_CHANNEL_RANDOM);
00799           break;
00800         case GZLL_DEVICE_MODE_4:
00801           gzll_start_new_tx(GZLL_CHANNEL_ESTIMATED);
00802           break;
00803       }
00804     }
00805     else
00806     {
00807       switch(temp)
00808       {
00809         case GZLL_DEVICE_MODE_0:
00810         case GZLL_DEVICE_MODE_2:
00811           gzll_start_new_tx(GZLL_CHANNEL_PREVIOUS_SUCCESS);
00812           break;
00813         default:
00814           gzll_start_new_tx(GZLL_CHANNEL_RANDOM);
00815           break;
00816       }
00817     }
00818 
00819     gzll_state_var = GZLL_DEVICE_ACTIVE;
00820     gzll_interupts_enable_rfck_disable();
00821     return true;                              // Payload successfully written to TX FIFO
00822   }
00823   else                                        // Else TRANSMIT state
00824   {
00825     /*
00826     Check if criteria for starting new transmission when already transmitting
00827     is fulfilled
00828     */
00829     if(!gzll_tx_setup_modified &&
00830        !hal_nrf_tx_fifo_full()
00831     )
00832     {
00833       GZLL_UPLOAD_PAYLOAD_TO_RADIO();
00834       gzll_interupts_enable_rfck_disable();
00835       return true;                            // Payload successfully written to TX FIFO
00836     }
00837     else
00838     {
00839       gzll_interupts_enable_rfck_disable();
00840       return false;                           // Payload not written to TX FIFO
00841     }
00842   }
00843 }
00844 
00845 bool gzll_dev_mode2_rx_channel_match()
00846 {
00847   if(gzll_sync_on)
00848   {
00849     if(gzll_channel_tab_index == gzll_chm_get_next_rx_channel())
00850     {
00851       if((gzll_dyn_params[GZLL_PARAM_HOST_MODE] == GZLL_HOST_MODE_0) ||
00852          gzll_chm_get_tx_ce_offset() == 1)
00853       {
00854         return true;
00855       }
00856     }
00857     return false;
00858   }
00859   else
00860   {
00861     return true;
00862   }
00863 }
00864 
00865 bool gzll_tx_success(void)
00866 {
00867   ASSERT(gzll_state_var != GZLL_DEVICE_ACTIVE);
00868 
00869   return gzll_tx_success_f;
00870 }
00871 
00872 uint16_t gzll_get_tx_attempts(void)
00873 {
00874   ASSERT(gzll_state_var != GZLL_DEVICE_ACTIVE);
00875 
00876   return gzll_try_counter;
00877 }
00878 
00879 uint16_t gzll_get_tx_channel_switches(void)
00880 {
00881   ASSERT(gzll_state_var != GZLL_DEVICE_ACTIVE)
00882   return  gzll_channel_switch_counter;
00883 }
00884 
00885 #endif
00886 
00887 void gzll_tx_fifo_flush(void)
00888 {
00889   gzll_interupts_disable_rfck_enable();
00890 
00891   hal_nrf_flush_tx();
00892 
00893   gzll_interupts_enable_rfck_disable();
00894 }
00895 
00896 
00897 gzll_states_t gzll_get_state(void)
00898 {
00899   return gzll_state_var;
00900 }
00901 
00902 bool gzll_radio_active()
00903 {
00904   return gzll_radio_active_f;
00905 }
00906 
00907 uint8_t gzll_get_rx_data_ready_pipe_number()
00908 {
00909   uint8_t dr_rx_pipe;
00910 
00911   gzll_interupts_disable_rfck_enable();
00912 
00913   if(gzll_rx_dr)
00914   {
00915     if(gzll_ack_rx_pipe_fifo_cnt > 0)
00916     {
00917       dr_rx_pipe = gzll_ack_rx_pipe_fifo[gzll_ack_rx_pipe_fifo_cnt - 1];
00918     }
00919     else
00920     {
00921       dr_rx_pipe = hal_nrf_get_rx_data_source();
00922     }
00923   }
00924   else
00925   {
00926     dr_rx_pipe = 0xff;
00927   }
00928 
00929   gzll_interupts_enable_rfck_disable();
00930   return dr_rx_pipe;
00931 }
00932 
00933 bool gzll_rx_data_ready(uint8_t pipe)
00934 {
00935   uint8_t available_rx_data_pipe;
00936 
00937   available_rx_data_pipe = gzll_get_rx_data_ready_pipe_number();
00938 
00939   return (available_rx_data_pipe <= 5 && (pipe == 0xff || pipe == available_rx_data_pipe));
00940 }
00941 
00942 bool gzll_rx_fifo_read(uint8_t *dst, uint8_t *length, uint8_t *pipe)
00943 {
00944   uint8_t temp_pipe;
00945   uint8_t temp_length;
00946   uint16_t pipe_and_length;
00947 
00948   ASSERT(dst != NULL);
00949 
00950   gzll_interupts_disable_rfck_enable();
00951 
00952   if(gzll_rx_dr)
00953   {
00954     temp_length = hal_nrf_read_rx_payload_width();
00955     if(temp_length <= 32) //TODO: Remove or comment hardcoded value
00956     {
00957       pipe_and_length = hal_nrf_read_rx_payload(dst);
00958       if(gzll_ack_rx_pipe_fifo_cnt > 0)
00959       {
00960         gzll_ack_rx_pipe_fifo_cnt--;
00961         temp_pipe = gzll_ack_rx_pipe_fifo[gzll_ack_rx_pipe_fifo_cnt];
00962       }
00963       else
00964       {
00965         temp_pipe = (pipe_and_length >> 8);
00966       }
00967 
00968       /*
00969       Handles if two or more payloads were received while only one interrupt
00970       request serviced.
00971       */
00972 
00973       if(hal_nrf_rx_fifo_empty())
00974       {
00975         gzll_rx_dr = false;
00976       }
00977 
00978       if(pipe != NULL)
00979       {
00980         *pipe = temp_pipe;
00981       }
00982 
00983       if(length != NULL)
00984       {
00985         *length = temp_length;
00986       }
00987 
00988       gzll_interupts_enable_rfck_disable();
00989       return true;
00990     }
00991     else
00992     {
00993       gzll_rx_fifo_flush();
00994     }
00995   }
00996 
00997   gzll_interupts_enable_rfck_disable();
00998   return false;
00999 }
01000 
01001 bool gzll_rx_power_high()
01002 {
01003   return gzll_rx_power_high_f;
01004 }
01005 
01006 void gzll_rx_fifo_flush(void)
01007 {
01008   gzll_interupts_disable_rfck_enable();
01009 
01010   hal_nrf_flush_rx();
01011   gzll_ack_rx_pipe_fifo_cnt = 0;
01012   gzll_rx_dr = false;
01013 
01014   gzll_interupts_enable_rfck_disable();
01015 }
01016 
01017 void gzll_goto_idle()
01018 {
01019   if(gzll_state_var == GZLL_DEVICE_ACTIVE)
01020   {
01021     gzll_pending_goto_idle = true;
01022 
01023     while(gzll_state_var != GZLL_IDLE)
01024     ;
01025   }
01026   else
01027   {
01028     if(gzll_state_var == GZLL_HOST_ACTIVE)
01029     {
01030       gzll_interupts_disable_rfck_enable();
01031       gzll_set_system_idle();
01032       gzll_interupts_enable_rfck_disable();
01033     }
01034   }
01035 }
01036 
01037 /*-----------------------------------------------------------------------------
01038   Implementation: Misc. internal functions
01039 -----------------------------------------------------------------------------*/
01040 
01041 static uint8_t gzll_lfsr_get(uint8_t seed, uint8_t max_limit)
01042 {
01043   static xdata uint8_t pseudoreg = 0xff; // Can never be zero
01044   uint8_t shiftbit;
01045 
01046   if(seed > 0)
01047   {
01048     pseudoreg = seed;
01049   }
01050 
01051   shiftbit = (pseudoreg << 7) & 0x80;
01052   shiftbit ^= (pseudoreg << 6) & 0x80;
01053   shiftbit ^= (pseudoreg << 5) & 0x80;
01054   shiftbit ^= (pseudoreg & 0x80);
01055 
01056   pseudoreg = (shiftbit | (pseudoreg >> 1));
01057 
01058   return pseudoreg % max_limit;
01059 }
01060 
01061 void gzll_delay_50us(uint8_t n)
01062 {
01063   uint16_t c;
01064 
01065   while(n-- > 0)
01066   {
01067       c = 45;
01068       while(c-- > 0)
01069       ;
01070   }
01071 }
01072 
01073 static void gzll_start_new_tx(gzll_new_tx_ch_t channel_select)
01074 {
01075   uint8_t temp;
01076 
01077   gzll_reload_tries_pr_channel_counter();
01078   gzll_set_radio_auto_retries();
01079 
01080   // If new random channel should be picked
01081   switch(channel_select)
01082   {
01083     case GZLL_CHANNEL_PREVIOUS_SUCCESS:
01084     default:
01085       temp = gzll_channel_tab_index;
01086       break;
01087     case GZLL_CHANNEL_RANDOM:
01088       temp = gzll_lfsr_get(0, gzll_channel_tab_size);
01089       break;
01090     case GZLL_CHANNEL_ESTIMATED:
01091       temp = gzll_chm_get_next_rx_channel();
01092       break;
01093     case GZLL_CHANNEL_NEXT_INDEX:
01094       temp = gzll_channel_tab_index + 1;
01095       temp = temp % gzll_channel_tab_size;
01096       break;
01097   }
01098   // Update RF channel if new is different from current
01099 
01100   if(temp != gzll_channel_tab_index)
01101   {
01102     gzll_channel_tab_index = temp;
01103     hal_nrf_set_rf_channel(gzll_channel_tab[gzll_channel_tab_index]);
01104     gzll_channel_switch_counter++;
01105   }
01106 
01107   if(gzll_sync_on)
01108   {
01109     // Signal to timer ISR for starting a new transmission
01110     gzll_pending_tx_start = true;
01111   }
01112   else
01113   {
01114     gzll_radio_active_f = true;
01115     GZLL_RFCE_PULSE();
01116   }
01117 
01118 }
01119 
01120 static void gzll_reload_tries_pr_channel_counter()
01121 {
01122   if(gzll_sync_on)
01123   {
01124     gzll_tries_pr_channel_counter = gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_ON];
01125   }
01126   else
01127   {
01128     gzll_tries_pr_channel_counter = gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_OFF];
01129   }
01130 }
01131 
01132 static void gzll_set_radio_auto_retries()
01133 {
01134   if(gzll_tries_pr_channel_counter > 15)
01135   {
01136     hal_nrf_set_auto_retr(15, GZLL_AUTO_RETR_DELAY);
01137   }
01138   else
01139   {
01140     hal_nrf_set_auto_retr((uint8_t)(gzll_tries_pr_channel_counter - 1), GZLL_AUTO_RETR_DELAY);
01141   }
01142 }
01143 
01144 static void gzll_set_system_idle(void)
01145 {
01146   GZLL_RFCE_LOW();
01147 
01148   if(gzll_state_var == GZLL_HOST_ACTIVE)
01149   {
01150     // Add delay to ensure that any ongoing ACK transmission is completed.
01151     gzll_delay_50us(GZLL_HOST_CE_LOW_IDLE_DELAY);
01152   }
01153 
01154   if(gzll_dyn_params[GZLL_PARAM_POWER_DOWN_IDLE_ENABLE] == 1)
01155   {
01156     gzll_set_radio_power_on(false);
01157   }
01158   else
01159   {
01160     gzll_set_radio_power_on(true);
01161   }
01162 
01163   gzll_radio_active_f = false;
01164   gzll_pending_goto_idle = false;
01165   gzll_state_var = GZLL_IDLE;
01166 }
01167 
01168 /*-----------------------------------------------------------------------------
01169   Implementation: Interrupt Service Routines (ISR)
01170 -----------------------------------------------------------------------------*/
01171 void gzll_radio_isr_function(void)
01172 {
01173   #ifndef GZLL_HOST_ONLY
01174   //lint -esym(644,tries) "Variable may not have been initialized"
01175   uint8_t tries;
01176   uint16_t timer_mod_period, temp;
01177   #endif
01178   uint8_t status;
01179 
01180   GZLL_INTERRUPTS_DISABLE();
01181   GZLL_RFCK_ENABLE();
01182 
01183   status = hal_nrf_clear_irq_flags_get_status();
01184 
01185   //If "received data ready" interrupt from radio
01186   if(status & ((1<<RX_DR)))
01187   {
01188     gzll_rx_dr = true;
01189     gzll_rx_power_high_f = hal_nrf_get_carrier_detect();
01190     gzll_chm_hold_rx_channel();
01191 
01192     #ifndef GZLL_HOST_ONLY
01193     /*
01194     If ACK payload has been received . Here, the actual RX pipe is always 0, so
01195     rx_pipe_fifo[] needs to store the current tx pipe.
01196     */
01197     if(gzll_state_var == GZLL_DEVICE_ACTIVE)
01198     {
01199       gzll_ack_rx_pipe_fifo[gzll_ack_rx_pipe_fifo_cnt] = gzll_current_tx_pipe;
01200       if(gzll_ack_rx_pipe_fifo_cnt < 2)
01201       {
01202         gzll_ack_rx_pipe_fifo_cnt++;
01203       }
01204     }
01205     #endif
01206   }
01207 
01208   //Read radio retransmit attempt counter and update affected variables.
01209   #ifndef GZLL_HOST_ONLY
01210   if((status & (1<<MAX_RT)) || (status & ((1<<TX_DS))))
01211   {
01212     tries = hal_nrf_get_transmit_attempts() + 1;
01213     gzll_tries_pr_channel_counter -= tries;
01214     gzll_try_counter += tries;
01215   }
01216   #endif
01217 
01218   //If "data sent" interrupt from radio
01219   if(status & (1<<TX_DS))
01220   {
01221     #ifndef GZLL_HOST_ONLY
01222     if(gzll_state_var == GZLL_DEVICE_ACTIVE)
01223     {
01224       gzll_timer_period_modified = 1;
01225 
01226       timer_mod_period = gzll_dyn_params[GZLL_PARAM_RX_PERIOD] - (gzll_dyn_params[GZLL_PARAM_RX_PERIOD_MODIFIER] + ((uint16_t)((GZLL_CONST_BYTES_PR_PACKET * 2) + gzll_current_tx_payload_length) * GZLL_US_PR_BYTE));
01227       if(status & ((1<<RX_DR)))
01228       {
01229         timer_mod_period -= (GZLL_US_PR_BYTE * GZLL_INTERNAL_ACK_PAYLOAD_LENGTH);
01230       }
01231 
01232       gzll_set_timer_period(timer_mod_period);
01233 
01234       gzll_chm_reset_rx_channel_index();
01235       gzll_chm_hold_rx_channel();
01236 
01237       temp = gzll_dyn_params[GZLL_PARAM_DEVICE_MODE];
01238 
01239       gzll_sync_period = gzll_dyn_params[GZLL_PARAM_MAX_SYNC_PERIOD];
01240 
01241       if(temp == GZLL_DEVICE_MODE_2 || temp == GZLL_DEVICE_MODE_3 || temp == GZLL_DEVICE_MODE_4)
01242       {
01243         gzll_sync_on = true;
01244       }
01245 
01246       /*
01247       Goto IDLE state if TX FIFO empty.
01248       */
01249       if(hal_nrf_tx_fifo_empty())
01250       {
01251         gzll_tx_success_f = true;
01252         gzll_set_system_idle();
01253       }
01254       else
01255       {
01256         gzll_reload_tries_pr_channel_counter();
01257         gzll_timeout_counter = 0;
01258         gzll_try_counter = 0;
01259         GZLL_RFCE_PULSE();
01260       }
01261     }
01262     #endif
01263   }
01264 
01265   /*
01266   If "max retransmit" interrupt from radio
01267   */
01268   #ifndef GZLL_HOST_ONLY
01269   if(status & (1<<MAX_RT))
01270   {
01271     GZLL_RFCE_LOW();
01272 
01273     gzll_timeout_counter += tries;
01274     temp = gzll_dyn_params[GZLL_PARAM_TX_TIMEOUT];
01275 
01276     // If TX has timed out, or user has called gzll_goto_idle()
01277     if((temp != 0 && gzll_timeout_counter >= temp) ||
01278       gzll_pending_goto_idle)
01279     {
01280       gzll_set_system_idle();
01281     }
01282     else
01283     {
01284       // If tries per channel has elapsed
01285       if(gzll_tries_pr_channel_counter == 0)
01286       {
01287         // If possible unintended sync to another device
01288         if(gzll_channel_switch_counter > gzll_dyn_params[GZLL_PARAM_COLLISION_CHANNEL_SWITCH_LIMIT])
01289         {
01290           gzll_sync_period = 0;
01291           gzll_sync_on = false;
01292           gzll_start_new_tx(GZLL_CHANNEL_RANDOM);
01293         }
01294         else
01295         {
01296           if(gzll_sync_on)
01297           {
01298             // If < 1 timer period until radio active -> state shall not go to !radio_active
01299             if(gzll_chm_get_tx_ce_offset() > 1)
01300             {
01301               gzll_radio_active_f = false;
01302             }
01303             gzll_start_new_tx(GZLL_CHANNEL_ESTIMATED);
01304           }
01305           else
01306           {
01307             gzll_start_new_tx(GZLL_CHANNEL_NEXT_INDEX);
01308           }
01309         }
01310       }
01311       else
01312       {
01313         gzll_set_radio_auto_retries();      // Continue retransmits on same channel
01314         GZLL_RFCE_PULSE();
01315       }
01316     }
01317   }
01318   #endif
01319 
01320   GZLL_RFCK_DISABLE();
01321   GZLL_INTERRUPTS_ENABLE();
01322 }
01323 
01324 void gzll_timer_isr_function(void)
01325 {
01326   uint16_t temp;
01327 
01328   GZLL_INTERRUPTS_DISABLE();
01329   gzll_chm_execute();                         // Execute radio channel manager
01330 
01331   // If timer period temporaly modified - restore correct setting.
01332   #ifndef GZLL_HOST_ONLY
01333   if(gzll_timer_period_modified == 1)
01334   {
01335     gzll_set_timer_period(gzll_dyn_params[GZLL_PARAM_RX_PERIOD]);
01336     gzll_timer_period_modified = 0;
01337   }
01338   #endif
01339 
01340   // If receive state
01341   #ifndef GZLL_DEVICE_ONLY
01342   if(gzll_state_var == GZLL_HOST_ACTIVE)
01343   {
01344     temp = gzll_chm_get_current_rx_channel();      // Get channel radio should be monitoring
01345     GZLL_RFCK_ENABLE();
01346 
01347     // If new channel should be monitored
01348     if(temp != gzll_channel_tab_index)
01349     {
01350       GZLL_RFCE_LOW();
01351       hal_nrf_set_rf_channel(gzll_channel_tab[temp]); // Change channel
01352       GZLL_RFCE_HIGH();                       // Set CE high here to minimize RX off time
01353       gzll_channel_tab_index = temp;
01354     }
01355 
01356     temp = gzll_chm_get_rx_ce_offset();       // Get number of periods until CE should be set high
01357 
01358     // Radio CE handling
01359     if(gzll_chm_get_rx_ce_offset() == 0)
01360     {
01361       gzll_set_radio_power_on(true);
01362       gzll_radio_active_f = true;
01363       GZLL_RFCE_HIGH();
01364     }
01365     else
01366     {
01367       GZLL_RFCE_LOW();
01368       gzll_radio_active_f = false;
01369       gzll_set_radio_power_on(false);
01370     }
01371 
01372     gzll_timeout_counter++;
01373 
01374     temp = gzll_dyn_params[GZLL_PARAM_RX_TIMEOUT];
01375     if(gzll_dyn_params[GZLL_PARAM_RX_TIMEOUT] > 0 && (gzll_timeout_counter >= temp))
01376     {
01377       gzll_set_system_idle();
01378     }
01379   }
01380   else
01381   #endif
01382   {
01383     // If transmit state
01384     #ifndef GZLL_HOST_ONLY
01385     if(gzll_state_var == GZLL_DEVICE_ACTIVE)
01386     {
01387       // If pending TX payload
01388       if(gzll_pending_tx_start)
01389       {
01390         temp = gzll_chm_get_tx_ce_offset();
01391 
01392         if( !gzll_sync_on ||
01393               (temp == 0 && (gzll_channel_tab_index == gzll_chm_get_current_rx_channel()))
01394         )
01395         {
01396           GZLL_RFCE_PULSE();
01397           gzll_radio_active_f = true;
01398           gzll_pending_tx_start = 0;
01399         }
01400       }
01401     }
01402     #endif
01403   }
01404 
01405   #ifndef GZLL_HOST_ONLY
01406   if(gzll_sync_period > 0)
01407   {
01408     gzll_sync_period--;
01409   }
01410   else
01411   {
01412     gzll_sync_on = false;
01413   }
01414   #endif
01415 
01416   GZLL_RFCK_DISABLE();
01417   GZLL_INTERRUPTS_ENABLE();
01418 }
01419 
01420 /*-----------------------------------------------------------------------------
01421   Implementation: Radio channel manager (CHM)
01422 -----------------------------------------------------------------------------*/
01423 
01424 static xdata uint8_t gzll_chm_rx_channel_index = 0;
01425 static xdata uint8_t gzll_chm_hold_rx_channel_index = 0;
01426 static xdata uint16_t gzll_chm_rx_channel_hold = 0;
01427 static xdata uint16_t gzll_chm_rx_mode1_sequence = 0;
01428 
01429 static void gzll_chm_execute()
01430 {
01431   if(gzll_chm_rx_channel_hold > 0)
01432   {
01433     gzll_chm_rx_channel_hold--;
01434   };
01435 
01436   // Increment channel synchronization counters
01437   gzll_chm_rx_mode1_sequence = (gzll_chm_rx_mode1_sequence + 1) % gzll_dyn_params[GZLL_PARAM_HOST_MODE_1_CYCLE_PERIOD];
01438 
01439   if( (gzll_dyn_params[GZLL_PARAM_HOST_MODE] == GZLL_HOST_MODE_0) ||
01440       (gzll_chm_rx_mode1_sequence == 0))
01441   {
01442     gzll_chm_rx_channel_index = (gzll_chm_rx_channel_index + 1) % gzll_channel_tab_size;
01443   }
01444 }
01445 
01446 static void gzll_chm_reset_rx_channel_index()
01447 {
01448   gzll_chm_rx_channel_index = gzll_channel_tab_index;
01449   gzll_chm_rx_mode1_sequence = 0;
01450 }
01451 
01452 static uint8_t gzll_chm_get_next_rx_channel()
01453 {
01454   if(gzll_chm_rx_channel_hold > 1)
01455   {
01456     return gzll_chm_hold_rx_channel_index;
01457   }
01458   else
01459   {
01460     return (gzll_chm_rx_channel_index + 1) % gzll_channel_tab_size;
01461   }
01462 }
01463 
01464 static uint8_t gzll_chm_get_current_rx_channel()
01465 {
01466   if(gzll_chm_rx_channel_hold > 0)
01467   {
01468     return gzll_chm_hold_rx_channel_index;
01469   }
01470   else
01471   {
01472     return gzll_chm_rx_channel_index;
01473   }
01474 }
01475 
01476 static void gzll_chm_hold_rx_channel()
01477 {
01478   gzll_chm_rx_channel_hold = gzll_dyn_params[GZLL_PARAM_RX_CHANNEL_HOLD_PERIODS];
01479   gzll_chm_hold_rx_channel_index = gzll_channel_tab_index;
01480 }
01481 
01482 static uint16_t gzll_chm_get_tx_ce_offset()
01483 {
01484   if((gzll_dyn_params[GZLL_PARAM_HOST_MODE] == GZLL_HOST_MODE_0) || (gzll_chm_rx_channel_hold > 0))
01485   {
01486     return 0;       // CE always high in mode 0
01487   }
01488   // Low power RX sequence
01489   else
01490   {
01491     if(gzll_chm_rx_mode1_sequence == 0)
01492     {
01493       return 0;
01494     }
01495     else
01496     {
01497       return (gzll_dyn_params[GZLL_PARAM_HOST_MODE_1_CYCLE_PERIOD] - gzll_chm_rx_mode1_sequence);
01498     }
01499   }
01500 }
01501 
01502 static uint16_t gzll_chm_get_rx_ce_offset()
01503 {
01504   uint16_t total_tx_time_per_channel;
01505   uint16_t rx_periods_per_channel;
01506 
01507   if(gzll_dyn_params[GZLL_PARAM_HOST_MODE] == GZLL_HOST_MODE_0 || (gzll_chm_rx_channel_hold > 0))
01508   {
01509     return 0;       // CE always high in mode 0, or during "channel hold"
01510   }
01511   else
01512   {
01513     if(gzll_chm_rx_mode1_sequence == 0)
01514     {
01515       return 0;
01516     }
01517     else
01518     {
01519       total_tx_time_per_channel = gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_OFF] * GZLL_TYP_TX_PERIOD;
01520       rx_periods_per_channel = total_tx_time_per_channel / gzll_dyn_params[GZLL_PARAM_RX_PERIOD];
01521 
01522       if(gzll_chm_rx_mode1_sequence <= (gzll_channel_tab_size * rx_periods_per_channel))
01523       {
01524         return ((rx_periods_per_channel - (gzll_chm_rx_mode1_sequence % rx_periods_per_channel)) - 1);
01525       }
01526       else
01527       {
01528         return (gzll_dyn_params[GZLL_PARAM_HOST_MODE_1_CYCLE_PERIOD] - gzll_chm_rx_mode1_sequence);
01529       }
01530     }
01531   }
01532 }
01533 
01534 static void gzll_set_radio_power_on(bool on)
01535 {
01536   uint8_t n;
01537 
01538   if(on)
01539   {
01540     if(!gzll_power_on)
01541     {
01542       hal_nrf_set_power_mode(HAL_NRF_PWR_UP);
01543       n = 3;
01544       while(n--) {}
01545       gzll_power_on = true;
01546     }
01547   }
01548   else
01549   {
01550     hal_nrf_set_power_mode(HAL_NRF_PWR_DOWN);
01551     gzll_power_on = false;
01552   }
01553 }
01554 

Generated on Fri Apr 20 2012 14:11:44 for nRFGo SDK by  doxygen 1.7.2