/**@brief Callback on Gazell Transmit failed. Resends the current packet. */ void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { bool push_ok; uint8_t dummy[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t dummy_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; // If the transmission failed, send a new packet. nrf_gpio_pin_set(GZLL_TX_FAIL_LED_PIN_NO); nrf_gpio_pin_clear(GZLL_TX_SUCCESS_LED_PIN_NO); if (tx_info.payload_received_in_ack) { // if data received attached to the ack, pop them. push_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, dummy, &dummy_length); if (!push_ok) { GET_GAZELL_ERROR(); } } push_ok = nrf_gzll_add_packet_to_tx_fifo(0, gzll_packet, PAYLOAD_SIZE); if (!push_ok) { GET_GAZELL_ERROR(); } }
/**@brief Callback function for Gazell Transmit fail. Resends the current packet. */ void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { bool push_ok; uint8_t dummy[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t dummy_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; uint32_t err_code; // If the transmission failed, send a new packet. err_code = bsp_indication_set(BSP_INDICATE_SEND_ERROR); APP_ERROR_CHECK(err_code); if (tx_info.payload_received_in_ack) { // if data received attached to the ack, pop them. push_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, dummy, &dummy_length); if (!push_ok) { GET_GAZELL_ERROR(); } } push_ok = nrf_gzll_add_packet_to_tx_fifo(0, m_gzll_packet, PAYLOAD_SIZE); if (!push_ok) { GET_GAZELL_ERROR(); } }
void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info) { char payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; int length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; if (! nrf_gzll_fetch_packet_from_rx_fifo(pipe, payload, &length)) return; if (RFduinoGZLL_onReceive) RFduinoGZLL_onReceive(pipe, rx_info.rssi, payload, length); }
void nrf_gzp_flush_rx_fifo(uint32_t pipe) { static uint8_t dummy_packet[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t length; nrf_gzp_set_primask(1); while(nrf_gzll_get_rx_fifo_packet_count(pipe) >0) { length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; (void)nrf_gzll_fetch_packet_from_rx_fifo(pipe,dummy_packet,&length); } nrf_gzp_set_primask(0); }
int main(void) { // Debug helper variables uint32_t length; // Data and acknowledgement payloads uint8_t payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; ///< Payload to send to Host. // Setup user interface (buttons and LEDs) ui_init(); // Initialize Gazell Link Layer (void)nrf_gzll_init(NRF_GZLL_MODE_HOST); (void)nrf_gzll_set_timeslot_period(NRF_GZLLDE_RXPERIOD_DIV_2); // Half RX period on nRF24Lxx device // Initialize Gazell Pairing Library gzp_init(); (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << UNENCRYPTED_DATA_PIPE)); gzp_pairing_enable(true); (void)nrf_gzll_enable(); for(;;) { gzp_host_execute(); // If Host ID request received if(gzp_id_req_received()) { // Always grant request gzp_id_req_grant(); } length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; if( nrf_gzll_get_rx_fifo_packet_count(UNENCRYPTED_DATA_PIPE) ) { if(nrf_gzll_fetch_packet_from_rx_fifo(UNENCRYPTED_DATA_PIPE, payload, &length)) { output_present(payload[0]); } } else if (gzp_crypt_user_data_received()) { if(gzp_crypt_user_data_read(payload, (uint8_t*)&length)) { output_present(payload[0]); } } } }
void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { char payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; int length = 0; if (tx_info.payload_received_in_ack) { length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; if (! nrf_gzll_fetch_packet_from_rx_fifo(pipe, payload, &length)) return; } if (RFduinoGZLL_onReceive) RFduinoGZLL_onReceive(HOST, tx_info.rssi, payload, length); }
/**@brief Callback function for Gazell Transmit Success. Transmits next packet. */ void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { bool push_ok; static int cpt = 0; uint8_t dummy[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t dummy_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; uint32_t err_code; // If an ACK was received, we send another packet. err_code = bsp_indication_set(BSP_INDICATE_SENT_OK); APP_ERROR_CHECK(err_code); if (tx_info.payload_received_in_ack) { // if data received attached to the ack, pop them. push_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, dummy, &dummy_length); if (!push_ok) { GET_GAZELL_ERROR(); } } cpt++; if (cpt > NB_TX_WITH_SAME_PAYLOAD) { cpt = 0; m_gzll_packet[0] = ~(m_gzll_packet[0]); if (m_gzll_packet[0] == DUMMY_PACKET) { m_gzll_packet[0] = 0x00; } m_gzll_packet[0] <<= 1; if (m_gzll_packet[0] == 0) { m_gzll_packet[0]++; } m_gzll_packet[0] = ~(m_gzll_packet[0]); } push_ok = nrf_gzll_add_packet_to_tx_fifo(0, m_gzll_packet, PAYLOAD_SIZE); if (!push_ok) { GET_GAZELL_ERROR(); } }
// If a data packet was received, we write the first byte to LEDS. void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info) { uint32_t data_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; packet_received = true; // Pop packet and write first byte of the payload to the GPIO port. pop_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, data_payload, &data_payload_length); if (data_payload_length > 0) { nrf_gpio_port_write(LEDS,~data_payload[0]); } // Read buttons and load ACK payload into TX queue ack_payload[0] = nrf_gpio_port_read(BUTTONS); // Button logic is inverted. push_ok = nrf_gzll_add_packet_to_tx_fifo(pipe, ack_payload, TX_PAYLOAD_LENGTH); }
/**@brief Callback on Gazell Transmit Success. Transmits next packet. */ void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { bool push_ok; static int cpt = 0; uint8_t dummy[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t dummy_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; // If an ACK was received, we send another packet. nrf_gpio_pin_set(GZLL_TX_SUCCESS_LED_PIN_NO); nrf_gpio_pin_clear(GZLL_TX_FAIL_LED_PIN_NO); if (tx_info.payload_received_in_ack) { // if data received attached to the ack, pop them. push_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, dummy, &dummy_length); if (!push_ok) { GET_GAZELL_ERROR(); } } cpt++; if (cpt > NB_TX_WITH_SAME_PAYLOAD) { cpt = 0; gzll_packet[0] = ~(gzll_packet[0]); if (gzll_packet[0] == DUMMY_PACKET) { gzll_packet[0] = 0x00; } gzll_packet[0] <<= 1; if (gzll_packet[0] == 0) { gzll_packet[0]++; } gzll_packet[0] = ~(gzll_packet[0]); } push_ok = nrf_gzll_add_packet_to_tx_fifo(0, gzll_packet, PAYLOAD_SIZE); if (!push_ok) { GET_GAZELL_ERROR(); } }
// If an ACK was received, we send another packet. void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { uint32_t ack_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; tx_success = true; if (tx_info.payload_received_in_ack) { // Pop packet and write first byte of the payload to the GPIO port. pop_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, ack_payload, &ack_payload_length); if (ack_payload_length > 0) { output_present(ack_payload[0]); } } // Read buttons and load data payload into TX queue data_payload[0] = input_get(); push_ok = nrf_gzll_add_packet_to_tx_fifo(pipe, data_payload, TX_PAYLOAD_LENGTH); }
// If an ACK was received, we send another packet. void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info) { uint32_t ack_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; tx_success = true; if (tx_info.payload_received_in_ack) { // Pop packet and write first byte of the payload to the GPIO port. pop_ok = nrf_gzll_fetch_packet_from_rx_fifo(pipe, ack_payload, &ack_payload_length); if (ack_payload_length > 0) { nrf_gpio_port_write(LEDS, ~ack_payload[0]); // Button press is active low. } } // Read buttons and load data payload into TX queue data_payload[0] = nrf_gpio_port_read(BUTTONS); push_ok = nrf_gzll_add_packet_to_tx_fifo(pipe, data_payload, TX_PAYLOAD_LENGTH); }
static gzp_tx_rx_trans_result_t gzp_tx_rx_transaction(const uint8_t *tx_packet, uint8_t tx_length, uint8_t *rx_dst, uint32_t *rx_length, uint8_t pipe) { gzp_tx_rx_trans_result_t retval; uint8_t fetch_packet[GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH]; bool tx_packet_success; bool fetch_success; uint32_t local_rx_length = GZP_MAX_ACK_PAYLOAD_LENGTH; uint32_t temp_lifetime; nrf_gzp_flush_rx_fifo(pipe); retval = GZP_TX_RX_FAILED_TO_SEND; (void)nrf_gzll_disable(); while(nrf_gzll_is_enabled()) {} temp_lifetime = nrf_gzll_get_sync_lifetime(); (void)nrf_gzll_set_sync_lifetime(GZP_TX_RX_TRANS_DELAY * 3); // 3 = RXPERIOD * 2 + margin (void)nrf_gzll_enable(); tx_packet_success = gzp_tx_packet(tx_packet, tx_length, pipe); if(tx_packet_success) { retval = GZP_TX_RX_NO_RESPONSE; nrf_gzp_flush_rx_fifo(pipe); fetch_packet[0] = (uint8_t)GZP_CMD_FETCH_RESP; gzp_tick_sleep_rx_periods(GZP_TX_RX_TRANS_DELAY); tx_packet_success = gzp_tx_packet(fetch_packet, GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH, pipe); if(tx_packet_success) { if(nrf_gzll_get_rx_fifo_packet_count(pipe)) { local_rx_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; fetch_success = nrf_gzll_fetch_packet_from_rx_fifo(pipe, rx_dst, &local_rx_length); } else { fetch_success = false; } if(fetch_success) { retval = GZP_TX_RX_SUCCESS; } else { //print_string("GZP_TX_FETCH_FAILED\r\n"); } } else { //print_string("GZP_TX_FETCH_NO_ACK\r\n"); } } (void)nrf_gzll_disable(); while(nrf_gzll_is_enabled()) {} (void)nrf_gzll_set_sync_lifetime(temp_lifetime); (void)nrf_gzll_enable(); return retval; }
bool gzp_address_req_send() { //lint -save -e514 Unusual use of a Boolean expression (gzll_update_ok &= ...) uint8_t i; bool retval = false; bool success; uint8_t address_req[GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH]; uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; nrf_gzll_tx_power_t temp_power; uint32_t temp_max_tx_attempts; bool gzll_update_ok = true; // Store parameters that are temporarily changed temp_max_tx_attempts = nrf_gzll_get_max_tx_attempts(); temp_power = nrf_gzll_get_tx_power(); // Modify parameters nrf_gzp_disable_gzll(); gzll_update_ok &= nrf_gzll_set_max_tx_attempts(GZP_REQ_TX_TIMEOUT); gzll_update_ok &= nrf_gzll_set_tx_power(GZP_POWER); // Flush RX FIFO gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE); gzll_update_ok &= nrf_gzll_enable(); // Build "request" packet address_req[0] = (uint8_t)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++) { success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE); if(success) { nrf_gzp_flush_rx_fifo(GZP_PAIRING_PIPE); } else { break; } } gzp_delay_rx_periods(GZP_TX_ACK_WAIT_TIMEOUT); // Send message for fetching pairing response from host. address_req[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH; success = gzp_tx_packet(address_req, GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH, GZP_PAIRING_PIPE); if(success && latest_tx_info.payload_received_in_ack) { // If pairing response received if(nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0) { rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; //dummy placeholder if(nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &rx_payload_length)) { if(rx_payload[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_RESP) { memcpy(gzp_system_address, &rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH); gzll_update_ok &= gzp_update_radio_params(&rx_payload[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS]); #ifndef GZP_NV_STORAGE_DISABLE (void)gzp_params_store(false); // "False" indicates that only "system address" part of DB element will be stored #endif 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 nrf_gzp_disable_gzll(); gzll_update_ok &= nrf_gzll_flush_rx_fifo(GZP_PAIRING_PIPE); gzll_update_ok &= nrf_gzll_flush_tx_fifo(GZP_PAIRING_PIPE); gzll_update_ok &= nrf_gzll_set_max_tx_attempts(temp_max_tx_attempts); gzll_update_ok &= nrf_gzll_set_tx_power(temp_power); gzll_update_ok &= nrf_gzll_enable(); if(!gzll_update_ok) { /* The update of the Gazell parameters failed. Use nrf_gzll_get_error_code() to investigate the cause. */ } return retval; //lint -restore }
static void gzp_process_address_req(uint8_t* gzp_req) { uint8_t temp_rx_pipes; uint8_t pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH]; uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; gzp_address_exchanged_f = false; gzll_goto_idle(); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); temp_rx_pipes = nrf_gzll_get_rx_pipes_enabled(); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); // If requesting Device within close proximity if(prev_gzp_rx_info.rssi >= GZP_HOST_RX_POWER_THRESHOLD) { (void)nrf_gzll_set_rx_pipes_enabled(0); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); gzll_set_rx_timeout(GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); gzll_rx_fifo_flush(); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); // Start "proximity" back off period gzll_rx_start(); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); while(nrf_gzll_is_enabled()) {} // Build pairing response packet pairing_resp[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_RESP; gzp_host_chip_id_read(&pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH); (void)nrf_gzll_add_packet_to_tx_fifo(0, &pairing_resp[0], GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); gzll_set_rx_timeout(GZP_STEP1_RX_TIMEOUT); // Enable only pairing pipe when waiting for pairing request step 1 (void)nrf_gzll_set_rx_pipes_enabled((1 << GZP_PAIRING_PIPE)); gzll_rx_start(); while(nrf_gzll_is_enabled()) { if(nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE)) { (void)nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, &gzp_req[0], &rx_payload_length); // Validate step 1 of pairing request if(gzp_req[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH) { gzp_address_exchanged_f = true; } } } gzll_tx_fifo_flush(); gzll_rx_fifo_flush(); gzll_set_rx_timeout(0); (void)nrf_gzll_set_rx_pipes_enabled(temp_rx_pipes); // Return to normal operation gzll_rx_start(); } else { (void)nrf_gzll_set_rx_pipes_enabled(temp_rx_pipes & ~(1 << GZP_PAIRING_PIPE)); gzll_set_rx_timeout(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT); // Start "not proximity" backoff period gzll_rx_start(); } }
void gzp_host_execute() { bool gzp_packet_received = false; uint32_t payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; gzp_address_exchanged_f = false; if(nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0) { gzp_packet_received = nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &payload_length); } if(!gzp_packet_received && (gzp_encrypted_user_data_length == 0)) { if(nrf_gzll_get_rx_fifo_packet_count(GZP_DATA_PIPE) > 0) { gzp_packet_received = nrf_gzll_fetch_packet_from_rx_fifo(GZP_DATA_PIPE, rx_payload, &payload_length); } } if(gzp_packet_received) { //lint -save -esym(644,rx_payload) //may not have been initialized 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(!nrf_gzll_is_enabled()) { gzll_set_rx_timeout(0); if(gzp_pairing_enabled_f) { (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_PAIRING_PIPE)); } gzll_rx_start(); } #ifndef GZP_CRYPT_DISABLE gzp_session_counter_inc(); #endif }