int fhss_tx_handle_cb(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint8_t *synch_info, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return -2; } // TODO: needs some more logic to push buffer back to queue if (frame_type == FHSS_DATA_FRAME) { if (is_broadcast_addr == true) { if (fhss_is_current_channel_broadcast(fhss_structure) == false) { tr_info("Broadcast on UC channel -> Back to queue"); return -3; } } } if (frame_type == FHSS_SYNCH_FRAME) { if (!synch_info) { return -4; } fhss_beacon_build(fhss_structure, synch_info); } else if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { return -1; } // If sending Beacon request on parents Unicast channel if (frame_type == FHSS_SYNCH_REQUEST_FRAME && fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { fhss_change_to_parent_channel(fhss_structure); } else if (frame_type == FHSS_DATA_FRAME) { fhss_change_to_tx_channel(fhss_structure, destination_address); } return 0; }
void fhss_receive_frame_cb(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return; } if (FHSS_SYNCH_FRAME == frame_type) { if ((fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) || fhss_structure->synch_panid != pan_id) { fhss_add_beacon_info(fhss_structure, pan_id, source_address, timestamp, synch_info); } else { if (!fhss_compare_with_synch_parent_address(fhss_structure, source_address)) { // Synch parent address needs to be updated in case parent has changed fhss_update_synch_parent_address(fhss_structure); platform_enter_critical(); // Calculate time since the Beacon was received uint32_t elapsed_time = api->read_timestamp(api) - timestamp; // Synchronize to given PAN fhss_beacon_received(fhss_structure, synch_info, elapsed_time); platform_exit_critical(); } } } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type) { // If current channel is broadcast, we don't need to send another synch info on next broadcast channel. // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle if ((fhss_structure->fhss_state == FHSS_SYNCHRONIZED) && (fhss_is_current_channel_broadcast(fhss_structure) == false) && (fhss_structure->synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST)) { fhss_structure->send_synch_info_on_next_broadcast_channel = true; } } }
/** * Update channel * * This function is called by superframe handler on first(0) superframe * of every channel to resolve and change new channel. * * @param cur network interface to work on * @return true if changed to broadcast channel, false otherwise */ bool fhss_change_to_next_channel(fhss_structure_t *fhss_structure) { int next_channel; bool broadcast_channel = false; uint16_t number_of_channels = fhss_structure->number_of_channels; uint8_t number_of_broadcast_channels = fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels; uint8_t unicast_channel_index = fhss_structure->bs->uc_channel_index; uint8_t channel_index_tmp; /* Get the channel number using channel index. Latter (number_of_broadcast_channels) indexes in channel table are broadcast channels and * first (number_of_channels - number_of_broadcast_channels) are unicast channels. * In channel hopping sequence, every (number_of_channels / number_of_broadcast_channels) channel is broadcast channel and * channel hopping sequence is e.g. |uc0|uc1|uc2|bc0|uc3|uc4|uc5|bc1|uc6|... */ /* Get broadcast channel */ if (fhss_is_current_channel_broadcast(fhss_structure) == true) { channel_index_tmp = fhss_calc_channel_shuffle((number_of_channels - number_of_broadcast_channels) + fhss_get_bc_index(fhss_structure), fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); fhss_generate_broadcast_start_superframe(fhss_structure); broadcast_channel = true; } else { /* Get unicast channel */ channel_index_tmp = fhss_calc_channel_shuffle(unicast_channel_index, fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); if (++fhss_structure->bs->uc_channel_index >= number_of_channels - number_of_broadcast_channels) { fhss_structure->bs->uc_channel_index = 0; } } // Reset Beacon received flag when channel has changed fhss_structure->bs->beacon_received_on_this_bc_channel = false; channel_index_tmp = fhss_add_channel_list_counter(channel_index_tmp, fhss_structure->number_of_channels, fhss_structure->bs->channel_list_counter, fhss_structure->bs->fhss_scramble_table); next_channel = channel_list_get_channel(fhss_structure->bs->fhss_configuration.channel_mask, channel_index_tmp); fhss_structure->rx_channel = next_channel; #ifdef FHSS_CHANNEL_DEBUG if (fhss_is_current_channel_broadcast(fhss_structure) == true) { tr_info("%"PRIu32" BC %u", fhss_structure->platform_functions.fhss_get_timestamp(fhss_structure->fhss_api), next_channel); } else { tr_info("%"PRIu32" UC %u", fhss_structure->platform_functions.fhss_get_timestamp(fhss_structure->fhss_api), next_channel); } #endif /*FHSS_CHANNEL_DEBUG*/ fhss_structure->callbacks.change_channel(fhss_structure->fhss_api, next_channel); return broadcast_channel; }
bool fhss_is_broadcast_channel_cb(const fhss_api_t *api) { fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); if (!fhss_structure) { return false; } // FHSS is unsynchronized, broadcasts allowed if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { return true; } return fhss_is_current_channel_broadcast(fhss_structure); }
static uint8_t fhss_get_destination_channel(fhss_structure_t *fhss_structure, uint8_t *destination_address) { uint8_t destination_offset; uint8_t uc_index; if (fhss_structure) { if (fhss_is_current_channel_broadcast(fhss_structure) == false) { destination_offset = fhss_get_offset(fhss_structure, destination_address); uc_index = fhss_calculate_uc_index(fhss_structure->bs->current_channel_index, fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels) + destination_offset; if (uc_index >= (fhss_structure->number_of_channels - fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels)) { uc_index -= (fhss_structure->number_of_channels - fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); } uc_index = fhss_calc_channel_shuffle(uc_index, fhss_structure->number_of_channels, fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); uc_index = fhss_add_channel_list_counter(uc_index, fhss_structure->number_of_channels, fhss_structure->bs->channel_list_counter, fhss_structure->bs->fhss_scramble_table); return channel_list_get_channel(fhss_structure->bs->fhss_configuration.channel_mask, uc_index); } return fhss_structure->rx_channel; } return 0; }