Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fhss_beacon.c
00001 /* 00002 * Copyright (c) 2015-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 00019 #include "nsconfig.h" 00020 #include "fhss_api.h " 00021 #include "fhss_config.h " 00022 #include "fhss.h" 00023 #include "fhss_beacon.h" 00024 00025 #include "common_functions.h" 00026 #include <string.h> // memcpy 00027 #include "ns_trace.h" 00028 00029 #define TRACE_GROUP "fhss" 00030 00031 // This function should be called just prior actually sending a beacon packet 00032 // to get precise information. Especially the time variables are essential. 00033 int fhss_beacon_update_payload(fhss_structure_t *fhss_structure, 00034 fhss_synchronization_beacon_payload_s *payload) 00035 { 00036 00037 int ret_val = 0; 00038 if (!fhss_structure || !payload) { 00039 return -1; 00040 } 00041 00042 const fhss_synch_configuration_t *config = &fhss_structure->synch_configuration; 00043 00044 payload->channel_index = fhss_structure->current_channel_index; 00045 00046 payload->sender_unicast_channel = 0; 00047 00048 payload->current_superframe = fhss_structure->current_superframe; 00049 00050 // This assumes that the time is always in the range of 0..2**16, which 00051 // should be the case as the superframe length field is also in that range. 00052 payload->remaining_slots = (uint16_t) fhss_get_remaining_time_to_next_superframe(fhss_structure); 00053 payload->channel_list_counter = fhss_structure->channel_list_counter; 00054 00055 payload->hop_count = fhss_structure->own_hop; 00056 payload->number_of_broadcast_channels = config->fhss_number_of_bc_channels; 00057 payload->number_of_tx_slots = config->fhss_number_of_tx_slots; 00058 payload->time_since_last_beacon = 0; // XXX not available yet 00059 // TODO: Get Beacon length from MAC 00060 uint32_t tx_time = fhss_get_tx_time(fhss_structure, 71, 0, 0); 00061 payload->processing_delay = fhss_structure->fhss_configuration.fhss_tuning_parameters.tx_processing_delay + tx_time; 00062 00063 payload->superframe_length = config->fhss_superframe_length; 00064 00065 payload->number_of_superframes_per_channel = config->fhss_number_of_superframes; 00066 00067 return ret_val; 00068 } 00069 00070 uint8_t* fhss_beacon_encode_raw(uint8_t* buffer, const fhss_synchronization_beacon_payload_s* source) 00071 { 00072 *buffer++ = FHSS_DATA_START_DELIMETER; 00073 *buffer++ = source->channel_index; 00074 *buffer++ = source->sender_unicast_channel; 00075 buffer = common_write_16_bit(source->current_superframe, buffer); 00076 buffer = common_write_16_bit(source->remaining_slots, buffer); 00077 buffer = common_write_16_bit(source->channel_list_counter, buffer); 00078 *buffer++ = source->hop_count; 00079 *buffer++ = source->number_of_broadcast_channels; 00080 *buffer++ = source->number_of_tx_slots; 00081 buffer = common_write_32_bit(source->time_since_last_beacon, buffer); 00082 buffer = common_write_16_bit(source->processing_delay, buffer); 00083 buffer = common_write_16_bit(source->superframe_length, buffer); 00084 *buffer++ = source->number_of_superframes_per_channel; 00085 00086 return buffer; 00087 } 00088 00089 uint8_t fhss_calculate_uc_index(uint8_t channel_index, uint16_t number_of_channels, uint8_t number_of_broadcast_channels) 00090 { 00091 // When channel index is 0, return last unicast index 00092 if (channel_index == 0) { 00093 return (number_of_channels - number_of_broadcast_channels - 1); 00094 } 00095 uint16_t bc_channel_density = (number_of_channels/number_of_broadcast_channels); 00096 return channel_index - (channel_index/bc_channel_density) - 1; 00097 } 00098 00099 00100 uint32_t fhss_get_time_to_next_channel_change(uint16_t remaining_slots_to_next_superframe, uint8_t number_of_superframes, 00101 uint8_t current_superframe, uint16_t superframe_length) 00102 { 00103 return remaining_slots_to_next_superframe + ((uint32_t)((number_of_superframes - 1) - current_superframe) * superframe_length); 00104 } 00105 00106 void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer) 00107 { 00108 dest->data_start_delimeter = *buffer++; 00109 00110 dest->channel_index = *buffer++; 00111 dest->sender_unicast_channel = *buffer++; 00112 00113 dest->current_superframe = common_read_16_bit(buffer); 00114 buffer += BEACON_FIELD_SIZE(current_superframe); 00115 00116 dest->remaining_slots = common_read_16_bit(buffer); 00117 buffer += BEACON_FIELD_SIZE(remaining_slots); 00118 00119 dest->channel_list_counter = common_read_16_bit(buffer); 00120 buffer += BEACON_FIELD_SIZE(channel_list_counter); 00121 00122 dest->hop_count = *buffer++; 00123 dest->number_of_broadcast_channels = *buffer++; 00124 dest->number_of_tx_slots = *buffer++; 00125 00126 dest->time_since_last_beacon = common_read_32_bit(buffer); 00127 buffer += BEACON_FIELD_SIZE(time_since_last_beacon); 00128 00129 dest->processing_delay += common_read_16_bit(buffer); 00130 00131 buffer += BEACON_FIELD_SIZE(processing_delay); 00132 00133 dest->superframe_length = common_read_16_bit(buffer); 00134 buffer += BEACON_FIELD_SIZE(superframe_length); 00135 00136 dest->number_of_superframes_per_channel = *buffer; 00137 } 00138 00139 // Decode the given raw byte buffer into a struct into dest struct and calculate 00140 // the new values for elapsed_time, channel_index, current_superframe and remaining_slots 00141 // from current state and given data. 00142 void fhss_beacon_decode(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer, uint32_t elapsed_time, uint16_t number_of_channels) 00143 { 00144 fhss_beacon_decode_raw(dest, buffer); 00145 00146 elapsed_time += dest->processing_delay; 00147 00148 /* To calculate channel index after beacon scan, following calculation is performed 00149 * 00150 * rem. slots to channel change(X) Channel length (V) 00151 * |---------------------| |-----------------------------------------------| 00152 * | RX'd channel index (Y) | ... | Y+n | 00153 * ...| sf1 | sf2 | sf3 | sf4 | ... | sf1 | sf2 | sf3 | sf4 |... 00154 * ^ ^ 00155 * |beacon received |beacon scan done 00156 * |-------------------------------------| 00157 * measured time after beacon RX'd(Z) 00158 * V = superframe length * number of superframes 00159 * X = remaining slots to superframe change + length of the remaining full superframes to channel change 00160 * 00161 * Y+n = Y + ((Z - X) / V) + 1 00162 * 00163 * Or if (Z < X) 00164 * Y+n = Y 00165 */ 00166 00167 uint32_t remaining_slots_to_next_channel = fhss_get_time_to_next_channel_change(dest->remaining_slots, dest->number_of_superframes_per_channel, dest->current_superframe, dest->superframe_length); 00168 uint16_t temp_channel_index = dest->channel_index; 00169 if (elapsed_time >= remaining_slots_to_next_channel) { 00170 uint32_t channel_length = (uint32_t) dest->number_of_superframes_per_channel * dest->superframe_length; 00171 temp_channel_index = dest->channel_index + ((elapsed_time - remaining_slots_to_next_channel) / channel_length) + 1; 00172 } 00173 while (temp_channel_index >= number_of_channels) { 00174 temp_channel_index -= number_of_channels; 00175 dest->channel_list_counter++; 00176 } 00177 dest->channel_index = temp_channel_index; 00178 while (dest->channel_list_counter >= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) { 00179 dest->channel_list_counter -= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES); 00180 } 00181 00182 /* To calculate superframe after beacon scan, following calculation is performed 00183 * 00184 * rem. slots(X) sf. length(V) 00185 * |---------------| |-----------------| 00186 *...| RX'd superframe (Y)| ... | Y+n | Y+n+1 |.... 00187 * ^ ^ 00188 * |beacon received |beacon scan done 00189 * |-------------------------------------| 00190 * measured time after beacon RX'd(Z) 00191 * 00192 * Y+n = Y + ((Z - X) / V) + 1 00193 * 00194 * Or if (Z < X) 00195 * Y+n = Y 00196 */ 00197 00198 if (elapsed_time >= dest->remaining_slots) { 00199 dest->current_superframe = dest->current_superframe + ((elapsed_time - dest->remaining_slots) / dest->superframe_length) + 1; 00200 } 00201 while (dest->current_superframe >= dest->number_of_superframes_per_channel) { 00202 dest->current_superframe -= dest->number_of_superframes_per_channel; 00203 } 00204 00205 /* To get the remaining slots after beacon scan, following calculation is performed 00206 * 00207 * rem. slots(Y) sf. length(V) new rem. slots(X) 00208 * |----------| |---------------| |-------------| 00209 *...| superframe 1 | superframe 2 | superframe 3 | superframe 4 |... 00210 * ^ ^ 00211 * |beacon received |beacon scan done 00212 * |--------------------------------------------| 00213 * measured time after beacon RX'd(Z) 00214 * 00215 * X = V - ((Z - Y) % V) 00216 * 00217 * Or if (Z < Y) 00218 * X = Y - Z 00219 */ 00220 00221 if (elapsed_time < dest->remaining_slots) { 00222 dest->remaining_slots = dest->remaining_slots - elapsed_time; 00223 } else { 00224 dest->remaining_slots = dest->superframe_length - ((elapsed_time - dest->remaining_slots) % dest->superframe_length); 00225 } 00226 00227 }
Generated on Tue Jul 12 2022 12:44:05 by
