void main(void) { uint8_t payload[GZLL_MAX_PAYLOAD_LENGTH]; uint8_t packet_cnt = 0; uint8_t rx_packet_cnt = 0; uint8_t rx_packet_byte0 = 0; mcu_init(); gzll_init(); // Set P0 as output P0DIR = 0; EA = 1; for(;;) { // If gazell link layer idle if(gzll_get_state() == GZLL_IDLE) { if(gzll_rx_fifo_read(payload, NULL, NULL)) { P0 = ~payload[0]; } // Put P0 contents in payload[0] payload[0] = P2; // Transmits payload[] to pipe 0 address gzll_tx_data(payload, 1, 0); } } }
void gzp_pairing_enable(bool enable) { gzll_states_t temp_gzll_state; temp_gzll_state = gzll_get_state(); if(gzp_pairing_enabled_f != enable) { gzll_goto_idle(); if(enable) { gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE)); } else { gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) & ~(1 << GZP_PAIRING_PIPE)); gzp_id_req_stat = GZP_ID_REQ_IDLE; } gzp_pairing_enabled_f = enable; if(temp_gzll_state == GZLL_HOST_ACTIVE) { gzll_rx_start(); } } }
static bool gzp_tx_packet(const uint8_t* tx_packet, uint8_t length, uint8_t pipe) { if(gzll_tx_data(tx_packet, length, pipe)) { while(gzll_get_state() != GZLL_IDLE) ; return gzll_tx_success(); } return false; }
void main(void) { bool send_crypt_data = false; bool tx_success = false; gzp_id_req_res_t id_req_status; uint8_t payload[GZLL_MAX_PAYLOAD_LENGTH]; mcu_init(); // Initialize Gazell Link Layer gzll_init(); // Initialize Gazell Pairing Library gzp_init(); EA = 1; while(true) { payload[0] = ~P0; // Send every other packet as encrypted data if(send_crypt_data) { // Send encrypted packet using the Gazell pairing library tx_success = gzp_crypt_data_send(payload, GZP_ENCRYPTED_USER_DATA_MAX_LENGTH); } else { // Send packet as plaintext on pipe 2 gzll_tx_data(payload, GZLL_MAX_FW_PAYLOAD_LENGTH, 2); while(gzll_get_state() != GZLL_IDLE) ; tx_success = gzll_tx_success(); } send_crypt_data = !send_crypt_data; // If data transfer failed if(!tx_success) { // Send "system address request". Needed for sending any user data to Host. gzp_address_req_send(); // Send "Host ID request". Needed for sending encrypted user data to host. id_req_status = gzp_id_req_send(); } // If waiting for Host to grant or reject ID request if(id_req_status == GZP_ID_RESP_PENDING) { // Send new ID request for fetching response id_req_status = gzp_id_req_send(); } } }
void main(void) { uint8_t poll_cnt = 0; uint8_t payload[GZLL_MAX_PAYLOAD_LENGTH]; mcu_init(); gzll_init(); // Always run on 16MHz crystal oscillator hal_clk_set_16m_source(HAL_CLK_XOSC16M); // Use Gazell Link Layer synchronous device mode 2 for minimizing // transmit attempts gzll_set_param(GZLL_PARAM_DEVICE_MODE, 2); EA = 1; while(true) { // If gazell link layer idle if(gzll_get_state() == GZLL_IDLE) { // Send a packet for every 20 wakeup, equals every ~20 ms if(poll_cnt > 20) { // Read P0 and put in payload[0] payload[0] = ~P0; // Transmits 1 byte ( payload[0] ) to pipe 0 address gzll_tx_data(&payload[0], 1, 0); poll_cnt = 0; } } EA = 0; // If radio not active, enter "register retention" if(!gzll_radio_active()) { PWRDWN = 0x04; // Enter "register retention", will wake up on pre-tick } PWRDWN = 0x07; // Enter "standby", will wake up on tick EA = 1; poll_cnt++; } }
static void gzp_process_address_req(uint8_t* gzp_req) { uint8_t temp_rx_pipes, temp_host_mode; uint8_t pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH]; gzp_address_exchanged_f = false; gzll_goto_idle(); temp_rx_pipes = gzll_get_param(GZLL_PARAM_RX_PIPES); temp_host_mode = gzll_get_param(GZLL_PARAM_HOST_MODE); // If requesting Device within close proximity if(gzll_rx_power_high()) { gzll_set_param(GZLL_PARAM_RX_PIPES, 0); gzll_set_param(GZLL_PARAM_HOST_MODE, 0); gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT); gzll_rx_fifo_flush(); // Start "proximity" back off period gzll_rx_start(); while(gzll_get_state() != GZLL_IDLE) ; // Build pairing response packet pairing_resp[0] = GZP_CMD_HOST_ADDRESS_RESP; gzp_host_chip_id_read(&pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH); gzll_ack_payload_write(&pairing_resp[0], GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH, 0); gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_STEP1_RX_TIMEOUT); // Enable only pairing pipe when waiting for pairing request step 1 gzll_set_param(GZLL_PARAM_RX_PIPES, (1 << GZP_PAIRING_PIPE)); gzll_rx_start(); while(gzll_get_state() != GZLL_IDLE) { if(gzll_rx_fifo_read(&gzp_req[0], NULL, NULL)) { // Validate step 1 of pairing request if(gzp_req[0] == GZP_CMD_HOST_ADDRESS_FETCH) { gzp_address_exchanged_f = true; } } } gzll_tx_fifo_flush(); gzll_rx_fifo_flush(); gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0); gzll_set_param(GZLL_PARAM_RX_PIPES, temp_rx_pipes); gzll_set_param(GZLL_PARAM_HOST_MODE, temp_host_mode); // Return to normal operation gzll_rx_start(); } else { gzll_set_param(GZLL_PARAM_RX_PIPES, temp_rx_pipes & ~(1 << GZP_PAIRING_PIPE)); gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT); // Start "not proximity" backoff period gzll_rx_start(); } }
void gzp_host_execute() { uint8_t rx_pipe; uint8_t payload_length; uint8_t rx_payload[GZLL_MAX_FW_PAYLOAD_LENGTH]; gzp_address_exchanged_f = false; rx_pipe = gzll_get_rx_data_ready_pipe_number(); if((rx_pipe == GZP_PAIRING_PIPE) || ((rx_pipe == GZP_DATA_PIPE) && (gzp_encrypted_user_data_length == 0))) { gzll_rx_fifo_read(rx_payload, &payload_length, NULL); switch(rx_payload[0]) { case GZP_CMD_HOST_ADDRESS_REQ: gzp_process_address_req(rx_payload); break; #ifndef GZP_CRYPT_DISABLE case GZP_CMD_HOST_ID_REQ: gzp_process_id_req(rx_payload); break; case GZP_CMD_HOST_ID_FETCH: gzp_process_id_fetch(rx_payload); break; case GZP_CMD_KEY_UPDATE_PREPARE: gzp_process_key_update_prepare(); break; case GZP_CMD_KEY_UPDATE: gzp_process_key_update(rx_payload); break; case GZP_CMD_ENCRYPTED_USER_DATA: gzp_process_encrypted_user_data(rx_payload, payload_length); break; #endif case GZP_CMD_FETCH_RESP: default: break; } } // Restart reception if "not proximity backoff" period has elapsed if(gzll_get_state() == GZLL_IDLE) { gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0); if(gzp_pairing_enabled_f) { gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE)); } gzll_rx_start(); } #ifndef GZP_CRYPT_DISABLE gzp_session_counter_inc(); #endif }
bool gzp_address_req_send(uint8_t idx) { uint8_t i; bool retval = false; uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH]; uint8_t rx_payload[GZLL_MAX_PAYLOAD_LENGTH]; uint16_t temp_power, temp_tx_timeout, temp_device_mode; if(gzll_get_state() == GZLL_IDLE) { // Store parameters that are temporarily changed temp_tx_timeout = gzll_get_param(GZLL_PARAM_TX_TIMEOUT); temp_power = gzll_get_param(GZLL_PARAM_OUTPUT_POWER); temp_device_mode = gzll_get_param(GZLL_PARAM_DEVICE_MODE); // Modify parameters gzll_set_param(GZLL_PARAM_TX_TIMEOUT, GZP_REQ_TX_TIMEOUT); gzll_set_param(GZLL_PARAM_OUTPUT_POWER, GZP_POWER); gzll_set_param(GZLL_PARAM_DEVICE_MODE, 0); // Flush RX FIFO gzll_rx_fifo_flush(); // Build "request" packet address_req[0] = GZP_CMD_HOST_ADDRESS_REQ; // Send a number of packets in order to broadcast that devices not within // close proximity must back off. for(i = 0; i < GZP_MAX_BACKOFF_PACKETS; i++) { if(!gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0)) { break; } } gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT); // Send message for fetching pairing response from host. address_req[0] = GZP_CMD_HOST_ADDRESS_FETCH; if(gzp_tx_packet(&address_req[0], GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, 0)) { // If pairing response received if(gzll_rx_fifo_read(rx_payload, NULL, NULL)) { if(rx_payload[0] == GZP_CMD_HOST_ADDRESS_RESP) { memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH); gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]); pairing_list_addr_write(idx, gzp_system_address); retval = true; } } } else { gzp_delay_rx_periods(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT - GZP_TX_ACK_WAIT_TIMEOUT); } gzp_delay_rx_periods(GZP_STEP1_RX_TIMEOUT); // Clean-up and restore parameters temporarily modified gzll_rx_fifo_flush(); gzll_tx_fifo_flush(); gzll_set_param(GZLL_PARAM_TX_TIMEOUT, temp_tx_timeout); gzll_set_param(GZLL_PARAM_OUTPUT_POWER, temp_power); gzll_set_param(GZLL_PARAM_DEVICE_MODE, temp_device_mode); } return retval; }
bool com_execute() { xdata bool retval = false; xdata uint8_t user_data[32]; xdata uint16_t temp; xdata uint8_t t_length, t_pipe, curr_gzll_state; static xdata uint8_t prev_gzll_state = 0xff; // If Device operation if(device_mode) { // Get Gazell state curr_gzll_state = gzll_get_state(); if(curr_gzll_state == GZLL_IDLE) { // If state transition from TRANSMIT to IDLE if(prev_gzll_state == GZLL_DEVICE_ACTIVE) { retval = true; if(gzll_tx_success()) { statistics[TX_PL_CNT]++; statistics[TX_BYTE_CNT] += app_setup[TX_PL_LENGTH]; temp = gzll_get_tx_attempts(); statistics[TX_TRY_CNT] += temp; statistics[AVG_TX_TRIES] = (uint16_t)(((float)statistics[TX_TRY_CNT] * 100) / statistics[TX_PL_CNT] ); if(statistics[MAX_TX_TRIES] < temp) { statistics[MAX_TX_TRIES] = temp; } statistics[TX_CH_SWITCHES] += gzll_get_tx_channel_switches(); } if(gzll_rx_fifo_read(user_data, &t_length, &t_pipe)) { statistics[RX_PL_CNT]++; statistics[RX_BYTE_CNT] += t_length; } } if(radio_run) { EA = 0; if(cnt_1ms >= app_setup[TX_PACKET_INTERVAL] ) { gzll_timer_tick = false; cnt_1ms = 0; EA = 1; while(!gzll_timer_tick) // Improves synchronization to start in synch with protocol timer ; gzll_tx_data(user_data, app_setup[TX_PL_LENGTH], app_setup[TX_PIPE]); curr_gzll_state = GZLL_DEVICE_ACTIVE; } EA = 1; } prev_gzll_state = curr_gzll_state; } } // Host operation else { if(gzll_rx_fifo_read(user_data, &t_length, &t_pipe)) { retval = true; statistics[RX_PL_CNT]++; statistics[RX_BYTE_CNT] += t_length; t_length = app_setup[ACK_PL_LENGTH]; if(t_length) { if(gzll_ack_payload_write(user_data, t_length, t_pipe)) { statistics[TX_PL_CNT]++; statistics[TX_BYTE_CNT] += t_length; } } } } return retval; }