Defines | |
#define | GZLL_CRYPT_PAYLOAD_OVERHEAD 5 |
#define | GZLL_MAX_INTERNAL_PAYLOAD_LENGTH 32 |
#define | GZLL_MAX_CRYPT_PAYLOAD_LENGTH (GZLL_MAX_INTERNAL_PAYLOAD_LENGTH - GZLL_CRYPT_PAYLOAD_OVERHEAD) |
#define | GZLL_MAX_PAYLOAD_LENGTH GZLL_MAX_ACK_PAYLOAD_LENGTH |
#define | GZLL_INTERNAL_FW_PAYLOAD_LENGTH GZLL_MAX_FW_PAYLOAD_LENGTH |
#define | GZLL_INTERNAL_ACK_PAYLOAD_LENGTH GZLL_MAX_ACK_PAYLOAD_LENGTH |
#define | GZLL_MAX_CRYPT_PIPES_VAL 0x00 |
#define | GZLL_INTERNAL_PAYLOAD_LENGTH GZLL_INTERNAL_ACK_PAYLOAD_LENGTH |
#define | GZLL_US_PR_BYTE 8 |
#define | GZLL_HAL_DATARATE HAL_NRF_1MBPS |
#define | GZLL_HOST_CE_LOW_IDLE_DELAY 14 |
#define | GZLL_AUTO_RETR_DELAY 250 |
General functions | |
These functions are useful on both the Host and Device side. | |
void | gzll_init (void) |
void | gzll_set_address (hal_nrf_address_t pipe, const uint8_t *address) |
void | gzll_set_channels (uint8_t *channels, uint8_t size) |
void | gzll_set_param (gzll_dyn_params_t param, uint16_t value) |
uint16_t | gzll_get_param_max (gzll_dyn_params_t param) |
uint16_t | gzll_get_param (gzll_dyn_params_t param) |
gzll_states_t | gzll_get_state (void) |
_Bool | gzll_radio_active () |
void | gzll_goto_idle (void) |
_Bool | gzll_rx_data_ready (uint8_t pipe) |
uint8_t | gzll_get_rx_data_ready_pipe_number (void) |
_Bool | gzll_rx_fifo_read (uint8_t *dst, uint8_t *length, uint8_t *pipe) |
_Bool | gzll_rx_power_high (void) |
uint8_t | gzll_get_channel_tab_size () |
void | gzll_get_channels (uint8_t *channels) |
void | gzll_get_address (uint8_t pipe, uint8_t *address) |
void | gzll_tx_fifo_flush (void) |
void | gzll_rx_fifo_flush (void) |
void | gzll_set_crypt_key (uint8_t pipe, uint8_t *key128) |
void | gzll_get_crypt_key (uint8_t pipe, uint8_t *key128) |
void | gzll_radio_isr_function (void) |
void | gzll_timer_isr_function (void) |
Device functions | |
These functions are only useful for a Device application. | |
_Bool | gzll_dev_mode2_rx_channel_match (void) |
_Bool | gzll_tx_data (const uint8_t *src, uint8_t length, uint8_t pipe) |
_Bool | gzll_tx_success (void) |
uint16_t | gzll_get_tx_attempts (void) |
uint16_t | gzll_get_tx_channel_switches (void) |
Host functions | |
These functions are only useful for a Host application. | |
void | gzll_rx_start (void) |
_Bool | gzll_ack_payload_write (const uint8_t *src, uint8_t length, uint8_t pipe) |
#define | gzll_rx_stop() gzll_goto_idle() |
Hardware dependent functions | |
These functions must be customized for the MCU being used. | |
void | gzll_set_timer_period (uint16_t period) |
#define gzll_rx_stop | ( | ) | gzll_goto_idle() |
#define GZLL_MAX_CRYPT_PAYLOAD_LENGTH (GZLL_MAX_INTERNAL_PAYLOAD_LENGTH - GZLL_CRYPT_PAYLOAD_OVERHEAD) |
#define GZLL_INTERNAL_FW_PAYLOAD_LENGTH GZLL_MAX_FW_PAYLOAD_LENGTH |
#define GZLL_INTERNAL_ACK_PAYLOAD_LENGTH GZLL_MAX_ACK_PAYLOAD_LENGTH |
#define GZLL_INTERNAL_PAYLOAD_LENGTH GZLL_INTERNAL_ACK_PAYLOAD_LENGTH |
void gzll_init | ( | void | ) |
Initialization function for the Gazell Link Layer.
This function must be called before any other Gazell functions.
Definition at line 384 of file gzll.c.
{ uint8_t temp_adr[GZLL_ADDRESS_WIDTH] = GZLL_DEFAULT_ADDRESS_PIPE1; gzll_interupts_disable_rfck_enable(); GZLL_RFCE_LOW(); hal_nrf_enable_ack_payload(true); hal_nrf_enable_dynamic_payload(true); hal_nrf_setup_dynamic_payload(0xff); /* Initialize status variables. */ gzll_channel_tab_index = 0; gzll_channel_tab_size = GZLL_DEFAULT_CHANNEL_TAB_SIZE; gzll_pending_goto_idle = false; gzll_timer_period_modified = false; gzll_current_tx_pipe = 0; gzll_pending_tx_start = false; gzll_tx_setup_modified = true; gzll_rx_setup_modified = true; gzll_radio_active_f = false; gzll_tx_success_f = true; gzll_sync_period = 0; gzll_sync_on = false; gzll_rx_dr = false; gzll_rx_power_high_f = false; gzll_ack_rx_pipe_fifo_cnt = 0; /* Set up default addresses. */ hal_nrf_set_address(HAL_NRF_PIPE0, gzll_p0_adr); hal_nrf_set_address(HAL_NRF_PIPE1, temp_adr); temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE2; hal_nrf_set_address(HAL_NRF_PIPE2, temp_adr); temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE3; hal_nrf_set_address(HAL_NRF_PIPE3, temp_adr); temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE4; hal_nrf_set_address(HAL_NRF_PIPE4, temp_adr); temp_adr[0] = GZLL_DEFAULT_ADDRESS_PIPE5; hal_nrf_set_address(HAL_NRF_PIPE5, temp_adr); /* Set up default channel. */ hal_nrf_set_rf_channel(gzll_channel_tab[gzll_channel_tab_index]); /* Initialize dynamic parameters using default values. */ gzll_dyn_params[GZLL_PARAM_DEVICE_MODE] = GZLL_DEFAULT_PARAM_DEVICE_MODE; gzll_dyn_params[GZLL_PARAM_TX_TIMEOUT] = GZLL_DEFAULT_PARAM_TX_TIMEOUT; gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_ON] = GZLL_DEFAULT_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_ON; gzll_dyn_params[GZLL_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_OFF] = GZLL_DEFAULT_PARAM_TX_ATTEMPTS_PR_CHANNEL_WHEN_SYNC_OFF; gzll_dyn_params[GZLL_PARAM_HOST_MODE] = GZLL_DEFAULT_PARAM_HOST_MODE; gzll_dyn_params[GZLL_PARAM_RX_PIPES] = GZLL_DEFAULT_PARAM_RX_PIPES; gzll_dyn_params[GZLL_PARAM_CRYPT_PIPES] = GZLL_DEFAULT_PARAM_CRYPT_PIPES; gzll_dyn_params[GZLL_PARAM_RX_TIMEOUT] = GZLL_DEFAULT_PARAM_RX_TIMEOUT; gzll_dyn_params[GZLL_PARAM_HOST_MODE_1_CYCLE_PERIOD] = GZLL_DEFAULT_PARAM_HOST_MODE_1_CYCLE_PERIOD; gzll_dyn_params[GZLL_PARAM_RX_PERIOD] = GZLL_DEFAULT_PARAM_RX_PERIOD; gzll_dyn_params[GZLL_PARAM_RX_PERIOD_MODIFIER] = GZLL_DEFAULT_PARAM_RX_PERIOD_MODIFIER; gzll_dyn_params[GZLL_PARAM_RX_CHANNEL_HOLD_PERIODS] = GZLL_DEFAULT_PARAM_RX_CHANNEL_HOLD_PERIODS; gzll_dyn_params[GZLL_PARAM_OUTPUT_POWER] = GZLL_DEFAULT_PARAM_OUTPUT_POWER; gzll_dyn_params[GZLL_PARAM_POWER_DOWN_IDLE_ENABLE] = GZLL_DEFAULT_PARAM_POWER_DOWN_IDLE_ENABLE; gzll_dyn_params[GZLL_PARAM_MAX_SYNC_PERIOD] = GZLL_DEFAULT_PARAM_MAX_SYNC_PERIOD; gzll_dyn_params[GZLL_PARAM_COLLISION_CHANNEL_SWITCH_LIMIT] = GZLL_DEFAULT_PARAM_COLLISION_CHANNEL_SWITCH_LIMIT; /* Set up default output power. */ hal_nrf_set_output_power((hal_nrf_output_power_t) gzll_dyn_params[GZLL_PARAM_OUTPUT_POWER]); /* Static radio setup. */ hal_nrf_set_datarate(GZLL_HAL_DATARATE); hal_nrf_set_crc_mode(GZLL_CRC); hal_nrf_set_address_width(GZLL_ADDRESS_WIDTH); /* Clear radio IRQ flags. */ //lint -esym(534, hal_nrf_get_clear_irq_flags) "return value ignored" hal_nrf_get_clear_irq_flags(); hal_nrf_flush_rx(); hal_nrf_flush_tx(); gzll_set_timer_period(GZLL_DEFAULT_PARAM_RX_PERIOD); gzll_set_system_idle(); gzll_interupts_enable_rfck_disable(); }
void gzll_set_address | ( | hal_nrf_address_t | pipe, |
const uint8_t * | address | ||
) |
Function for setting the address of a pipe.
When in receive mode, the radio can monitor up to six pipes simultaneously. Each pipe has its own address.
For pipes 0 and 1 all 5 address bytes have to be set. For pipes 2 to 5 the least significant address byte has to be set. The remaining address bytes for pipes 2 to 5 will be the same as for pipe 1.
It is only allowed to modify the address in GZLL_IDLE state.
pipe | specifies the pipe number (0-5). |
address | is a pointer to the pipe address. |
Definition at line 583 of file gzll.c.
{ ASSERT((gzll_state_var == GZLL_IDLE)); ASSERT((pipe <= 5)); gzll_interupts_disable_rfck_enable(); gzll_tx_setup_modified = true; gzll_rx_setup_modified = true; if(pipe == HAL_NRF_PIPE0) { memcpy(gzll_p0_adr, (uint8_t*)address, GZLL_ADDRESS_WIDTH); } hal_nrf_set_address(pipe, address); gzll_interupts_enable_rfck_disable(); }
void gzll_set_channels | ( | uint8_t * | channels, |
uint8_t | size | ||
) |
Function for setting the channels to be used by the Gazell protocol.
In order for several units running the Gazell protocol to be able to communicate, they have to use the same (or overlapping) set of channels.
It is recommended that the selected channels are distributed over a wide frequency range. The maximum channel range for the nRF24L01 radio is 0 to 123. However, in order to ensure compliance with world wide frequency regulations it is recommended to use channels 2 to 80 only.
channels | is a pointer to the channel array. |
size | is the number of channels in the array. |
Definition at line 567 of file gzll.c.
{ gzll_interupts_disable_rfck_enable(); ASSERT((gzll_state_var == GZLL_IDLE)); ASSERT((channel_tab_size <= GZLL_MAX_CHANNEL_TAB_SIZE)); gzll_channel_tab_index = 0; gzll_channel_tab_size = channel_tab_size; memcpy(gzll_channel_tab, channels, gzll_channel_tab_size); hal_nrf_set_rf_channel(gzll_channel_tab[gzll_channel_tab_index]); gzll_interupts_enable_rfck_disable(); }
void gzll_set_param | ( | gzll_dyn_params_t | param, |
uint16_t | value | ||
) |
Function for setting a dynamic protocol parameter.
param | is the parameter to set. The possible parameters are:
|
value | is the new value for the parameter. |
Definition at line 487 of file gzll.c.
{ ASSERT((gzll_state_var == GZLL_IDLE)); ASSERT((param < GZLL_DYN_PARAM_SIZE)); ASSERT(!(param == GZLL_PARAM_DEVICE_MODE && val > GZLL_DEVICE_MODE_4)); ASSERT(!(param == GZLL_PARAM_HOST_MODE && val > GZLL_HOST_MODE_1)); ASSERT(!(param == GZLL_PARAM_RX_PIPES && val > 0x3f)); ASSERT(!(param == GZLL_PARAM_CRYPT_PIPES && val > GZLL_MAX_CRYPT_PIPES_VAL)); ASSERT(!(param == GZLL_PARAM_OUTPUT_POWER && val > 3)); gzll_interupts_disable_rfck_enable(); if(param < GZLL_DYN_PARAM_SIZE) { gzll_dyn_params[param] = val; switch(param) { case GZLL_PARAM_DEVICE_MODE: if((val == GZLL_DEVICE_MODE_0 || val == GZLL_DEVICE_MODE_1)) { gzll_sync_on = false; } break; case GZLL_PARAM_POWER_DOWN_IDLE_ENABLE: if(val == 1) { gzll_set_radio_power_on(false); } break; case GZLL_PARAM_RX_PERIOD: gzll_timer_period_modified = 1; break; case GZLL_PARAM_OUTPUT_POWER: hal_nrf_set_output_power((hal_nrf_output_power_t)gzll_dyn_params[GZLL_PARAM_OUTPUT_POWER]); break; case GZLL_PARAM_RX_PIPES: gzll_rx_setup_modified = true; break; } } gzll_interupts_enable_rfck_disable(); }
uint16_t gzll_get_param_max | ( | gzll_dyn_params_t | param ) |
Function returning the maximum allowed value for a dynamic parameter. The minimum value for a parameter is zero.
param | is the parameter for which to get the maximum value. Possible parameters are:
|
Definition at line 532 of file gzll.c.
{ uint16_t param_max[GZLL_DYN_PARAM_SIZE] = GZLL_PARAMS_MAX; return param_max[param]; }
uint16_t gzll_get_param | ( | gzll_dyn_params_t | param ) |
Function returning the current value of a dynamic parameter.
param | is the parameter for which to get the current value. The possible parameters are:
|
Definition at line 539 of file gzll.c.
{ ASSERT((param < GZLL_DYN_PARAM_SIZE)); gzll_interupts_disable_rfck_enable(); if(param < GZLL_DYN_PARAM_SIZE) { gzll_interupts_enable_rfck_disable(); return gzll_dyn_params[param]; } else { gzll_interupts_enable_rfck_disable(); return 0; } }
gzll_states_t gzll_get_state | ( | void | ) |
Function for achieving the current protocol state.
GZLL_IDLE | |
GZLL_DEVICE_ACTIVE | |
GZLL_HOST_ACTIVE |
Definition at line 897 of file gzll.c.
{
return gzll_state_var;
}
_Bool gzll_radio_active | ( | ) |
Function telling if the radio is currently active (receiving or transmitting).
This function is used for assisting power management in the application.
For nRF24LE1, the application cannot enter any other power-saving mode deeper than standby when the radio is active.
Definition at line 902 of file gzll.c.
{
return gzll_radio_active_f;
}
void gzll_goto_idle | ( | void | ) |
Function for forcing the protocol to GZLL_IDLE state.
The Gazell protocol has three states: GZLL_IDLE, GZLL_DEVICE_ACTIVE and GZLL_HOST_ACTIVE.
Definition at line 1017 of file gzll.c.
{ if(gzll_state_var == GZLL_DEVICE_ACTIVE) { gzll_pending_goto_idle = true; while(gzll_state_var != GZLL_IDLE) ; } else { if(gzll_state_var == GZLL_HOST_ACTIVE) { gzll_interupts_disable_rfck_enable(); gzll_set_system_idle(); gzll_interupts_enable_rfck_disable(); } } }
_Bool gzll_rx_data_ready | ( | uint8_t | pipe ) |
Function for checking for data in the RX FIFO.
The function checks if data is available on a given pipe.
If a packet is available, the packet can be read from the FIFO by using gzll_rx_fifo_read().
pipe | is the pipe number.
|
true | if data is available |
false | if data is not available |
Definition at line 933 of file gzll.c.
{ uint8_t available_rx_data_pipe; available_rx_data_pipe = gzll_get_rx_data_ready_pipe_number(); return (available_rx_data_pipe <= 5 && (pipe == 0xff || pipe == available_rx_data_pipe)); }
uint8_t gzll_get_rx_data_ready_pipe_number | ( | void | ) |
Function for checking for data in the RX FIFO.
The function returns the pipe number for the available data.
If a packet is available, the packet can be read from the FIFO by using gzll_rx_fifo_read().
Definition at line 907 of file gzll.c.
{ uint8_t dr_rx_pipe; gzll_interupts_disable_rfck_enable(); if(gzll_rx_dr) { if(gzll_ack_rx_pipe_fifo_cnt > 0) { dr_rx_pipe = gzll_ack_rx_pipe_fifo[gzll_ack_rx_pipe_fifo_cnt - 1]; } else { dr_rx_pipe = hal_nrf_get_rx_data_source(); } } else { dr_rx_pipe = 0xff; } gzll_interupts_enable_rfck_disable(); return dr_rx_pipe; }
_Bool gzll_rx_fifo_read | ( | uint8_t * | dst, |
uint8_t * | length, | ||
uint8_t * | pipe | ||
) |
Function for reading a packet from the RX FIFO.
Reading the RX FIFO during GZLL_DEVICE_ACTIVE state can cause loss of packets.
*dst | is the destination for the data. To avoid memory corruption the destination array should at least have space for GZLL_MAX_PAYLOAD_LENGTH bytes. |
*length | returns the number of bytes read. By passing a NULL pointer this parameter will be ignored. |
*pipe | returns the pipe from which data was read. By passing a NULL pointer this parameter will be ignored. |
true | if data was read from the RX FIFO. |
false | if RX FIFO was empty. |
Definition at line 942 of file gzll.c.
{ uint8_t temp_pipe; uint8_t temp_length; uint16_t pipe_and_length; ASSERT(dst != NULL); gzll_interupts_disable_rfck_enable(); if(gzll_rx_dr) { temp_length = hal_nrf_read_rx_payload_width(); if(temp_length <= 32) //TODO: Remove or comment hardcoded value { pipe_and_length = hal_nrf_read_rx_payload(dst); if(gzll_ack_rx_pipe_fifo_cnt > 0) { gzll_ack_rx_pipe_fifo_cnt--; temp_pipe = gzll_ack_rx_pipe_fifo[gzll_ack_rx_pipe_fifo_cnt]; } else { temp_pipe = (pipe_and_length >> 8); } /* Handles if two or more payloads were received while only one interrupt request serviced. */ if(hal_nrf_rx_fifo_empty()) { gzll_rx_dr = false; } if(pipe != NULL) { *pipe = temp_pipe; } if(length != NULL) { *length = temp_length; } gzll_interupts_enable_rfck_disable(); return true; } else { gzll_rx_fifo_flush(); } } gzll_interupts_enable_rfck_disable(); return false; }
_Bool gzll_rx_power_high | ( | void | ) |
Function returning true if the receive signal level for the previous received packet was above -64 dBm. This function is useful for estimating the relative proximity of the transmitting device.
true | if receive signal level >= -64 dBm. |
false | if receive signal level < -64 dBm. |
Definition at line 1001 of file gzll.c.
{
return gzll_rx_power_high_f;
}
uint8_t gzll_get_channel_tab_size | ( | ) |
Function returning the number of channels set up for Gazell.
Definition at line 557 of file gzll.c.
{
return gzll_channel_tab_size;
}
void gzll_get_channels | ( | uint8_t * | channels ) |
void gzll_get_address | ( | uint8_t | pipe, |
uint8_t * | address | ||
) |
Function for getting the address of a pipe.
pipe | is the pipe number(0-5). |
*address | returns the address of the pipe. For pipes 0 and 1, five address bytes are returned. For pipes 2 to 5 one address byte is returned. |
Definition at line 603 of file gzll.c.
{ ASSERT((pipe <= 5)); ASSERT(address != NULL); gzll_interupts_disable_rfck_enable(); hal_nrf_get_address(pipe, address); //lint !e534 "return value ignored" gzll_interupts_enable_rfck_disable(); }
void gzll_tx_fifo_flush | ( | void | ) |
Function for flushing the transmit (TX) FIFO.
This function will only have effect in the GZLL_IDLE state.
Definition at line 887 of file gzll.c.
{ gzll_interupts_disable_rfck_enable(); hal_nrf_flush_tx(); gzll_interupts_enable_rfck_disable(); }
void gzll_rx_fifo_flush | ( | void | ) |
Function for flushing the receive (RX) FIFO.
The function can be used in any protocol state.
Definition at line 1006 of file gzll.c.
{ gzll_interupts_disable_rfck_enable(); hal_nrf_flush_rx(); gzll_ack_rx_pipe_fifo_cnt = 0; gzll_rx_dr = false; gzll_interupts_enable_rfck_disable(); }
void gzll_set_crypt_key | ( | uint8_t | pipe, |
uint8_t * | key128 | ||
) |
Function for setting the 16 byte (128 bit) AES key to be used for encrypting/decrypting data.
This key must be distributed in a secure manner to the transmitter and the receiver.
Afterwards, AES 128 bit "Counter mode" is used for the communication. In Counter mode a given plaintext payload will be encrypted differently each time.
Each pipe can use different AES keys.
key128 | is a pointer to the 16 byte AES key to be used. |
pipe | is the pipe number for which to set the AES key. The pipe number must be < than the constant GZLL_MAX_CRYPT_PIPES. |
void gzll_get_crypt_key | ( | uint8_t | pipe, |
uint8_t * | key128 | ||
) |
Function for getting the 16 byte (128 bit) AES key set for a given pipe.
key128 | is a pointer to where the 16 byte AES shall be copied. |
pipe | is the pipe number for which to get the AES key. The pipe number must be < than the constant GZLL_MAX_CRYPT_PIPES. |
void gzll_radio_isr_function | ( | void | ) |
Function to be called by the radio interrupt service routine.
Definition at line 1171 of file gzll.c.
{ #ifndef GZLL_HOST_ONLY //lint -esym(644,tries) "Variable may not have been initialized" uint8_t tries; uint16_t timer_mod_period, temp; #endif uint8_t status; GZLL_INTERRUPTS_DISABLE(); GZLL_RFCK_ENABLE(); status = hal_nrf_clear_irq_flags_get_status(); //If "received data ready" interrupt from radio if(status & ((1<<RX_DR))) { gzll_rx_dr = true; gzll_rx_power_high_f = hal_nrf_get_carrier_detect(); gzll_chm_hold_rx_channel(); #ifndef GZLL_HOST_ONLY /* If ACK payload has been received . Here, the actual RX pipe is always 0, so rx_pipe_fifo[] needs to store the current tx pipe. */ if(gzll_state_var == GZLL_DEVICE_ACTIVE) { gzll_ack_rx_pipe_fifo[gzll_ack_rx_pipe_fifo_cnt] = gzll_current_tx_pipe; if(gzll_ack_rx_pipe_fifo_cnt < 2) { gzll_ack_rx_pipe_fifo_cnt++; } } #endif } //Read radio retransmit attempt counter and update affected variables. #ifndef GZLL_HOST_ONLY if((status & (1<<MAX_RT)) || (status & ((1<<TX_DS)))) { tries = hal_nrf_get_transmit_attempts() + 1; gzll_tries_pr_channel_counter -= tries; gzll_try_counter += tries; } #endif //If "data sent" interrupt from radio if(status & (1<<TX_DS)) { #ifndef GZLL_HOST_ONLY if(gzll_state_var == GZLL_DEVICE_ACTIVE) { gzll_timer_period_modified = 1; 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)); if(status & ((1<<RX_DR))) { timer_mod_period -= (GZLL_US_PR_BYTE * GZLL_INTERNAL_ACK_PAYLOAD_LENGTH); } gzll_set_timer_period(timer_mod_period); gzll_chm_reset_rx_channel_index(); gzll_chm_hold_rx_channel(); temp = gzll_dyn_params[GZLL_PARAM_DEVICE_MODE]; gzll_sync_period = gzll_dyn_params[GZLL_PARAM_MAX_SYNC_PERIOD]; if(temp == GZLL_DEVICE_MODE_2 || temp == GZLL_DEVICE_MODE_3 || temp == GZLL_DEVICE_MODE_4) { gzll_sync_on = true; } /* Goto IDLE state if TX FIFO empty. */ if(hal_nrf_tx_fifo_empty()) { gzll_tx_success_f = true; gzll_set_system_idle(); } else { gzll_reload_tries_pr_channel_counter(); gzll_timeout_counter = 0; gzll_try_counter = 0; GZLL_RFCE_PULSE(); } } #endif } /* If "max retransmit" interrupt from radio */ #ifndef GZLL_HOST_ONLY if(status & (1<<MAX_RT)) { GZLL_RFCE_LOW(); gzll_timeout_counter += tries; temp = gzll_dyn_params[GZLL_PARAM_TX_TIMEOUT]; // If TX has timed out, or user has called gzll_goto_idle() if((temp != 0 && gzll_timeout_counter >= temp) || gzll_pending_goto_idle) { gzll_set_system_idle(); } else { // If tries per channel has elapsed if(gzll_tries_pr_channel_counter == 0) { // If possible unintended sync to another device if(gzll_channel_switch_counter > gzll_dyn_params[GZLL_PARAM_COLLISION_CHANNEL_SWITCH_LIMIT]) { gzll_sync_period = 0; gzll_sync_on = false; gzll_start_new_tx(GZLL_CHANNEL_RANDOM); } else { if(gzll_sync_on) { // If < 1 timer period until radio active -> state shall not go to !radio_active if(gzll_chm_get_tx_ce_offset() > 1) { gzll_radio_active_f = false; } gzll_start_new_tx(GZLL_CHANNEL_ESTIMATED); } else { gzll_start_new_tx(GZLL_CHANNEL_NEXT_INDEX); } } } else { gzll_set_radio_auto_retries(); // Continue retransmits on same channel GZLL_RFCE_PULSE(); } } } #endif GZLL_RFCK_DISABLE(); GZLL_INTERRUPTS_ENABLE(); }
void gzll_timer_isr_function | ( | void | ) |
Function to be called by the protocol timer interrupt service routine.
Definition at line 1324 of file gzll.c.
{ uint16_t temp; GZLL_INTERRUPTS_DISABLE(); gzll_chm_execute(); // Execute radio channel manager // If timer period temporaly modified - restore correct setting. #ifndef GZLL_HOST_ONLY if(gzll_timer_period_modified == 1) { gzll_set_timer_period(gzll_dyn_params[GZLL_PARAM_RX_PERIOD]); gzll_timer_period_modified = 0; } #endif // If receive state #ifndef GZLL_DEVICE_ONLY if(gzll_state_var == GZLL_HOST_ACTIVE) { temp = gzll_chm_get_current_rx_channel(); // Get channel radio should be monitoring GZLL_RFCK_ENABLE(); // If new channel should be monitored if(temp != gzll_channel_tab_index) { GZLL_RFCE_LOW(); hal_nrf_set_rf_channel(gzll_channel_tab[temp]); // Change channel GZLL_RFCE_HIGH(); // Set CE high here to minimize RX off time gzll_channel_tab_index = temp; } temp = gzll_chm_get_rx_ce_offset(); // Get number of periods until CE should be set high // Radio CE handling if(gzll_chm_get_rx_ce_offset() == 0) { gzll_set_radio_power_on(true); gzll_radio_active_f = true; GZLL_RFCE_HIGH(); } else { GZLL_RFCE_LOW(); gzll_radio_active_f = false; gzll_set_radio_power_on(false); } gzll_timeout_counter++; temp = gzll_dyn_params[GZLL_PARAM_RX_TIMEOUT]; if(gzll_dyn_params[GZLL_PARAM_RX_TIMEOUT] > 0 && (gzll_timeout_counter >= temp)) { gzll_set_system_idle(); } } else #endif { // If transmit state #ifndef GZLL_HOST_ONLY if(gzll_state_var == GZLL_DEVICE_ACTIVE) { // If pending TX payload if(gzll_pending_tx_start) { temp = gzll_chm_get_tx_ce_offset(); if( !gzll_sync_on || (temp == 0 && (gzll_channel_tab_index == gzll_chm_get_current_rx_channel())) ) { GZLL_RFCE_PULSE(); gzll_radio_active_f = true; gzll_pending_tx_start = 0; } } } #endif } #ifndef GZLL_HOST_ONLY if(gzll_sync_period > 0) { gzll_sync_period--; } else { gzll_sync_on = false; } #endif GZLL_RFCK_DISABLE(); GZLL_INTERRUPTS_ENABLE(); }
_Bool gzll_dev_mode2_rx_channel_match | ( | void | ) |
Function used during device mode 2 for minimizing the delay from gzll_tx_data() is called and until the transmission is started.
Device mode 2 is the synchronous frequency agility mode. This means that the Gazell link layer for every new transmission will use the previous successful transmission channel, and await starting the transmission until the host is actually monitoring this channel.
This wait time will be minimized if the gzll_tx_data() function is called when gzll_dev_mode2_rx_channel_match() returns true.
Definition at line 845 of file gzll.c.
{ if(gzll_sync_on) { if(gzll_channel_tab_index == gzll_chm_get_next_rx_channel()) { if((gzll_dyn_params[GZLL_PARAM_HOST_MODE] == GZLL_HOST_MODE_0) || gzll_chm_get_tx_ce_offset() == 1) { return true; } } return false; } else { return true; } }
_Bool gzll_tx_data | ( | const uint8_t * | src, |
uint8_t | length, | ||
uint8_t | pipe | ||
) |
Function for uploading data to TX FIFO and start data transmission (Device operation).
The protocol does not have to be in GZLL_IDLE state to issue this function.
If the protocol is in GZLL_DEVICE_ACTIVE state, the data will be uploaded to the TX FIFO and sent immediately after the ongoing transmission has completed. This can be used to stream data.
For this to happen the following must be fulfilled:
If the protocol is in GZLL_HOST_ACTIVE state (Host operation) when issuing gzll_tx_data(), reception will be terminated and the protocol will switch to GZLL_DEVICE_ACTIVE state (Device operation).
*src | is the payload to be transmitted. |
length | is the number of bytes in the payload. |
pipe | is the pipe to be used. The TX address for the pipe is set using gzll_set_address(). |
true | if data was successfully uploaded to the TX FIFO. This does NOT indicate that the packet was successfully transmitted, which should instead be checked with gzll_tx_success() |
false | if data was not uploaded. In this case any the protocol state remains the same as before the function was called. |
Definition at line 681 of file gzll.c.
{ uint8_t temp_address[GZLL_ADDRESS_WIDTH]; uint16_t temp; ASSERT(length <= GZLL_MAX_FW_PAYLOAD_LENGTH && length > 0); ASSERT(pipe <= 5); /* Length check to prevent memory corruption. (Note, assertion will capture this as well). */ if(length == 0 || length > GZLL_MAX_FW_PAYLOAD_LENGTH) { return false; } gzll_current_tx_payload_length = length; if(gzll_state_var == GZLL_HOST_ACTIVE) { gzll_goto_idle(); } gzll_interupts_disable_rfck_enable(); /* If the specified pipe is different from the previous TX pipe, the TX setup must be updated */ if(pipe != gzll_current_tx_pipe) { gzll_current_tx_pipe = pipe; gzll_tx_setup_modified = true; } /* Here, state can be GZLL_IDLE or GZLL_DEVICE_ACTIVE */ if(gzll_state_var == GZLL_IDLE) { if(gzll_tx_setup_modified) // TX setup has to be restored? { gzll_tx_setup_modified = false; gzll_rx_setup_modified = true; hal_nrf_set_operation_mode(HAL_NRF_PTX); hal_nrf_open_pipe(HAL_NRF_PIPE0, EN_AA); //Read out the full RX address for pipe number "pipe" if(pipe == HAL_NRF_PIPE0) { hal_nrf_set_address(HAL_NRF_TX, gzll_p0_adr); hal_nrf_set_address(HAL_NRF_PIPE0, gzll_p0_adr); } else { //lint -esym(550,bytes_in_buffer) "variable not accessed" //lint -esym(438,bytes_in_buffer) "last assigned value not used" uint8_t bytes_in_buffer; bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE1, temp_address); if(pipe != HAL_NRF_PIPE1) { switch(pipe) { default: case HAL_NRF_PIPE2: bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE2, temp_address); break; case HAL_NRF_PIPE3: bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE3, temp_address); break; case HAL_NRF_PIPE4: bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE4, temp_address); break; case HAL_NRF_PIPE5: bytes_in_buffer = hal_nrf_get_address(HAL_NRF_PIPE5, temp_address); break; } } //Here, temp_address will contain the full TX address hal_nrf_set_address(HAL_NRF_PIPE0, temp_address); hal_nrf_set_address(HAL_NRF_TX, temp_address); /* Change seed for random generator. Will prevent different devices transmitting to the same host from using the same channel hopping sequence. */ //lint -esym(534, gzll_lfsr_get) "return value ignored" gzll_lfsr_get(pipe, 1); } } // Prepare for new transmission gzll_timeout_counter = 0; gzll_channel_switch_counter = 0; gzll_try_counter = 0; hal_nrf_flush_tx(); GZLL_UPLOAD_PAYLOAD_TO_RADIO(); gzll_tx_success_f = false; // Transmission by default "failure" temp = gzll_dyn_params[GZLL_PARAM_DEVICE_MODE]; gzll_set_radio_power_on(true); if(gzll_sync_on) { switch(temp) { case GZLL_DEVICE_MODE_2: default: gzll_start_new_tx(GZLL_CHANNEL_PREVIOUS_SUCCESS); break; case GZLL_DEVICE_MODE_3: gzll_start_new_tx(GZLL_CHANNEL_RANDOM); break; case GZLL_DEVICE_MODE_4: gzll_start_new_tx(GZLL_CHANNEL_ESTIMATED); break; } } else { switch(temp) { case GZLL_DEVICE_MODE_0: case GZLL_DEVICE_MODE_2: gzll_start_new_tx(GZLL_CHANNEL_PREVIOUS_SUCCESS); break; default: gzll_start_new_tx(GZLL_CHANNEL_RANDOM); break; } } gzll_state_var = GZLL_DEVICE_ACTIVE; gzll_interupts_enable_rfck_disable(); return true; // Payload successfully written to TX FIFO } else // Else TRANSMIT state { /* Check if criteria for starting new transmission when already transmitting is fulfilled */ if(!gzll_tx_setup_modified && !hal_nrf_tx_fifo_full() ) { GZLL_UPLOAD_PAYLOAD_TO_RADIO(); gzll_interupts_enable_rfck_disable(); return true; // Payload successfully written to TX FIFO } else { gzll_interupts_enable_rfck_disable(); return false; // Payload not written to TX FIFO } } }
_Bool gzll_tx_success | ( | void | ) |
Function for checking the result of the latest transmit operation.
The return value from this function is only reliable when the protocol is in GZLL_IDLE state
true | if the latest packet was successfully transmitted. |
false | if the latest packet was not successfully transmitted. |
Definition at line 865 of file gzll.c.
{ ASSERT(gzll_state_var != GZLL_DEVICE_ACTIVE); return gzll_tx_success_f; }
uint16_t gzll_get_tx_attempts | ( | void | ) |
Function returning the number of transmission attempts for the latest packet.
This function is useful for checking the current radio conditions and whether the protocol is in sync or not.
The returned value from this function is only reliable when the protocol is in GZLL_IDLE state.
Definition at line 872 of file gzll.c.
{ ASSERT(gzll_state_var != GZLL_DEVICE_ACTIVE); return gzll_try_counter; }
uint16_t gzll_get_tx_channel_switches | ( | void | ) |
Function returning the number of channel switches during transmission of the latest packet. A large number of channel switches will be an indication of heavy radio interference.
The returned value from this function is only reliable when the protocol is in GZLL_IDLE state.
Definition at line 879 of file gzll.c.
{ ASSERT(gzll_state_var != GZLL_DEVICE_ACTIVE) return gzll_channel_switch_counter; }
void gzll_rx_start | ( | void | ) |
Function for starting reception.
This function will make the protocol enter GZLL_HOST_ACTIVE state and start listening for incoming data.
If this function is called during the GZLL_DEVICE_ACTIVE state, the transmission will be terminated and the protocol will enter GZLL_HOST_ACTIVE state.
Definition at line 618 of file gzll.c.
{ uint8_t i; gzll_goto_idle(); if(gzll_rx_setup_modified) { gzll_interupts_disable_rfck_enable(); gzll_rx_setup_modified = false; gzll_tx_setup_modified = true; /* Restore pipe 0 address (this may have been altered during transmission) */ hal_nrf_set_address(HAL_NRF_PIPE0, gzll_p0_adr); /* Enable the receive pipes selected by gzll_set_param() */ hal_nrf_close_pipe(HAL_NRF_ALL); for(i = 0; i < 6; i++) { if(gzll_dyn_params[GZLL_PARAM_RX_PIPES] & (1 << i)) { hal_nrf_open_pipe((hal_nrf_address_t)i, EN_AA); } } hal_nrf_set_operation_mode(HAL_NRF_PRX); } gzll_set_radio_power_on(true); gzll_timeout_counter = 0; gzll_state_var = GZLL_HOST_ACTIVE; GZLL_RFCE_HIGH(); gzll_interupts_enable_rfck_disable(); }
_Bool gzll_ack_payload_write | ( | const uint8_t * | src, |
uint8_t | length, | ||
uint8_t | pipe | ||
) |
Function for uploading the payload to be piggybacked onto the next acknowledgement packet (ACK) for the selected pipe.
It is recommended that the Gazell Link Layer is in IDLE state when uploading an acknowledgement packet. Alternatively, the application can upload packets during HOST_ACTIVE state as long as the TX FIFO for the given pipe is not empty.
Uploading acknowledgement packet during HOST_ACTIVE state when the TX FIFO is empty can cause loss of packets.
*src | is a pointer to the payload. |
length | is the number of bytes of the payload. The maximum number of bytes in an ACK payload is GZLL_MAX_ACK_PAYLOAD_LENGTH. |
pipe | is the receive pipe. The payload will be sent as part of the next ACK packet for this pipe. |
true | if uploading of the ACK payload to TX FIFO was successful. |
false | if uploading of the ACK payload failed due to full TX FIFO or length above GZLL_MAX_ACK_PAYLOAD_LENGTH. |
Definition at line 658 of file gzll.c.
{ ASSERT(length <= GZLL_MAX_ACK_PAYLOAD_LENGTH && length > 0); ASSERT(pipe <= 5); gzll_interupts_disable_rfck_enable(); if(length == 0 || (length > GZLL_MAX_ACK_PAYLOAD_LENGTH) || hal_nrf_tx_fifo_full()) { gzll_interupts_enable_rfck_disable(); return false; // ACK payload not written } hal_nrf_write_ack_payload(pipe, src, length); gzll_interupts_enable_rfck_disable(); return true; // ACK payload successfully written }
void gzll_set_timer_period | ( | uint16_t | period ) |
Function used by the Gazell protocol for setting the protocol timer period.
The implementation of this function must be customized for the actual MCU used.
Definition at line 30 of file gzll_mcu.c.
{ hal_rtc_start(false); hal_rtc_start(true); // Start/stop to reset counter period = (int)((float)period * 32768 / 1000000 + 0.5); hal_rtc_set_compare_value(period - 1); }