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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
fhss.c
00001 /* 00002 * Copyright (c) 2015-2018, 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 #include "nsconfig.h" 00018 #include "ns_types.h" 00019 #include "fhss_api.h " 00020 #include "fhss_config.h " 00021 #include "fhss.h" 00022 #include "fhss_common.h" 00023 #include "fhss_channel.h" 00024 #include "channel_list.h" 00025 #include "nsdynmemLIB.h" 00026 #include "fhss_statistics.h" 00027 #include "ns_trace.h" 00028 #include "eventOS_event.h" 00029 #include "eventOS_callback_timer.h" 00030 #include "platform/arm_hal_interrupt.h" 00031 #include "randLIB.h" 00032 #include "common_functions.h" 00033 #include <string.h> 00034 00035 #define TRACE_GROUP "fhss" 00036 00037 static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); 00038 static int fhss_reset(fhss_structure_t *fhss_structure); 00039 static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure); 00040 static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length); 00041 static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j); 00042 static void fhss_beacon_received(fhss_structure_t *fhss_structure, const uint8_t *synch_info, const uint32_t elapsed_time); 00043 static void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay); 00044 static int8_t fhss_beacon_create_tasklet(fhss_structure_t *fhss_structure); 00045 static void fhss_beacon_tasklet_func(arm_event_s *event); 00046 static int fhss_beacon_periodic_start(fhss_structure_t *fhss_structure, uint32_t time_to_first_beacon); 00047 static void fhss_beacon_periodic_stop(fhss_structure_t *fhss_structure); 00048 static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor); 00049 00050 fhss_structure_t *fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics) 00051 { 00052 if (!fhss_api || !fhss_configuration || !fhss_timer) { 00053 tr_err("Invalid FHSS enable configuration"); 00054 return NULL; 00055 } 00056 int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); 00057 if (channel_count <= 0) { 00058 // There must be at least one configured channel in channel list 00059 return NULL; 00060 } 00061 fhss_structure_t *fhss_struct = fhss_allocate_instance(fhss_api, fhss_timer); 00062 if (!fhss_struct) { 00063 return NULL; 00064 } 00065 fhss_struct->bs = ns_dyn_mem_alloc(sizeof(fhss_bs_t)); 00066 if (!fhss_struct->bs) { 00067 fhss_free_instance(fhss_api); 00068 return NULL; 00069 } 00070 memset(fhss_struct->bs, 0, sizeof(fhss_bs_t)); 00071 00072 fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); 00073 fhss_struct->bs->fhss_configuration = *fhss_configuration; 00074 fhss_struct->fhss_stats_ptr = fhss_statistics; 00075 fhss_struct->number_of_channels = channel_count; 00076 00077 // set a invalid id to tasklet_id, so we know that one is not started yet 00078 fhss_struct->beacon_tasklet_id = -1; 00079 00080 // Default synch interval is 240 seconds 00081 if (!fhss_struct->bs->fhss_configuration.fhss_max_synch_interval) { 00082 fhss_struct->bs->fhss_configuration.fhss_max_synch_interval = 240; 00083 } 00084 fhss_reset_synch_monitor(&fhss_struct->bs->synch_monitor); 00085 ns_list_init(&fhss_struct->fhss_failed_tx_list); 00086 fhss_struct->own_hop = 0xff; 00087 fhss_reset(fhss_struct); 00088 00089 if (fhss_beacon_create_tasklet(fhss_struct) < 0) { 00090 ns_dyn_mem_free(fhss_struct->bs); 00091 fhss_free_instance(fhss_api); 00092 return NULL; 00093 } 00094 00095 return fhss_struct; 00096 } 00097 00098 bool fhss_is_synch_root(fhss_structure_t *fhss_structure) 00099 { 00100 if (fhss_structure->own_hop > 0) { 00101 return false; 00102 } 00103 return true; 00104 } 00105 00106 static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) 00107 { 00108 (void) slots; 00109 fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); 00110 if (fhss_structure) { 00111 fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); 00112 } 00113 } 00114 00115 static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure) 00116 { 00117 if (fhss_structure->bs->current_superframe >= fhss_structure->bs->broadcast_start_superframe) { 00118 return true; 00119 } 00120 00121 return false; 00122 } 00123 00124 static bool fhss_check_bad_channel(fhss_structure_t *fhss_structure, uint8_t handle) 00125 { 00126 if (!fhss_structure) { 00127 return false; 00128 } 00129 fhss_failed_tx_t *failed_tx = fhss_failed_handle_find(fhss_structure, handle); 00130 if (!failed_tx) { 00131 return true; 00132 } 00133 if (failed_tx->bad_channel == fhss_structure->rx_channel) { 00134 return false; 00135 } 00136 return true; 00137 } 00138 00139 static bool fhss_check_channel_type(fhss_structure_t *fhss_structure, bool is_bc, int frame_type) 00140 { 00141 if (!fhss_structure) { 00142 return false; 00143 } 00144 00145 // Channel type check is valid only when FHSS is synchronized 00146 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00147 return true; 00148 } 00149 00150 if (frame_type == FHSS_DATA_FRAME) { 00151 if (is_bc == true) { 00152 // Drop: if packet has broadcast destination but current channel is unicast channel or current superframe is not broadcast sending superframe 00153 if ((fhss_is_current_channel_broadcast(fhss_structure) == false) || (fhss_is_bc_sending_superframe(fhss_structure) == false)) { 00154 return false; 00155 } 00156 } else if (fhss_is_current_channel_broadcast(fhss_structure) == true) { 00157 // Drop: If waiting synchronization Beacon and packet has unicast destination 00158 if (fhss_structure->bs->beacons_received_timer) { 00159 return false; 00160 } 00161 } 00162 } 00163 if (frame_type == FHSS_SYNCH_FRAME) { 00164 00165 } 00166 if (frame_type == FHSS_SYNCH_REQUEST_FRAME) { 00167 // Drop: If we have unicast channels in our configuration and current channel is broadcast channel 00168 if ((fhss_structure->number_of_channels > fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) { 00169 return false; 00170 } 00171 00172 uint8_t current_superframe = fhss_structure->bs->current_superframe; 00173 uint8_t synch_attempt = fhss_structure->bs->beacons_received_timer; 00174 if (fhss_structure->bs->synch_configuration.fhss_number_of_tx_slots > 1) { 00175 // Send synch request either before or after the middle of the channel depending on attempt number. 00176 uint8_t middle_of_superframes = fhss_structure->bs->synch_configuration.fhss_number_of_superframes / 2; 00177 00178 if (synch_attempt & 1) { 00179 if (fhss_structure->bs->current_superframe < middle_of_superframes) { 00180 return false; 00181 } 00182 } else { 00183 if (fhss_structure->bs->current_superframe >= middle_of_superframes) { 00184 return false; 00185 } 00186 } 00187 } else if ((current_superframe == 0) || (current_superframe == (fhss_structure->bs->synch_configuration.fhss_number_of_superframes - 1))) { 00188 return false; 00189 } 00190 } 00191 return true; 00192 00193 } 00194 00195 static bool fhss_check_tx_allowed(fhss_structure_t *fhss_structure, bool is_bc, uint16_t frame_length, int frame_type, uint8_t phy_header_length, uint8_t phy_tail_length) 00196 { 00197 if (!fhss_structure) { 00198 return false; 00199 } 00200 // Check is valid only when FHSS is synchronized 00201 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00202 return true; 00203 } 00204 // Allow: If sending synchronization frame 00205 if (frame_type == FHSS_SYNCH_FRAME) { 00206 return true; 00207 } 00208 // Allow: If sending broadcast (on broadcast channel) 00209 if (is_bc == true) { 00210 return true; 00211 } 00212 // Deny: If FHSS is not on TX slot 00213 if (fhss_structure->bs->tx_allowed == false) { 00214 return false; 00215 } 00216 // Deny: If not enough time before TX slot end 00217 if (fhss_check_remaining_tx_time(fhss_structure, frame_length, phy_header_length, phy_tail_length) == false) { 00218 return false; 00219 } 00220 return true; 00221 } 00222 00223 static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor) 00224 { 00225 if (synch_monitor) { 00226 synch_monitor->avg_synch_fix = 0; 00227 // Initialize to -1 instead of 0 to drop the first beacon after network scan (from synch monitoring) 00228 synch_monitor->avg_synch_fix_counter = -1; 00229 synch_monitor->channel_counter = 0; 00230 return 0; 00231 } 00232 return -1; 00233 } 00234 00235 static int fhss_update_txrx_slots(fhss_structure_t *fhss_structure) 00236 { 00237 uint8_t cur_superframe = fhss_structure->bs->current_superframe; 00238 uint8_t number_of_tx_slots = fhss_structure->bs->synch_configuration.fhss_number_of_tx_slots; 00239 uint8_t number_of_superframes = fhss_structure->bs->synch_configuration.fhss_number_of_superframes; 00240 uint8_t tx_slot_length = ((number_of_superframes / 2) / number_of_tx_slots); 00241 uint8_t tx_slot_up_limit = tx_slot_length; 00242 bool tx_allowed = false; 00243 00244 /* FHSS Phase 1 solution. This will be updated in future since we need to be able to communicate with nodes on same hop distance. 00245 * Even (0, 2, 4,...) hops starts with TX slot and uneven (1, 3, 5, ...) hops starts with RX slot. This way we are able to communicate to our parent and child nodes. 00246 * 00247 * If number of superframes is 16 and number of TX slots is 2, this will be generated (Note: hop 0 is always border router): 00248 * 00249 * Hop Superframe 00250 * 0 |TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX| 00251 * 1 |RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX| 00252 * 2 |TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX| 00253 * 3 |RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX| 00254 * 00255 */ 00256 00257 if ((fhss_structure->own_hop % 2)) { 00258 tx_slot_up_limit += tx_slot_length; 00259 } 00260 while (number_of_tx_slots--) { 00261 if ((cur_superframe >= (tx_slot_up_limit - tx_slot_length)) && (cur_superframe < tx_slot_up_limit)) { 00262 tx_allowed = true; 00263 break; 00264 } else { 00265 tx_slot_up_limit += (tx_slot_length * 2); 00266 } 00267 } 00268 #ifdef FHSS_CHANNEL_DEBUG_CBS 00269 if (fhss_bc_switch && fhss_structure->bs->tx_allowed != tx_allowed) { 00270 fhss_bc_switch(); 00271 } 00272 #endif /*FHSS_CHANNEL_DEBUG_CBS*/ 00273 fhss_structure->bs->tx_allowed = tx_allowed; 00274 return 0; 00275 } 00276 00277 static int fhss_update_drift_compensation(fhss_structure_t *fhss_structure) 00278 { 00279 int retval = 0; 00280 int channels_per_synch_period; 00281 uint16_t bc_density; 00282 uint16_t channel_dwell_time; 00283 uint32_t synch_period; 00284 00285 if (!fhss_structure) { 00286 return 0; 00287 } 00288 bc_density = (fhss_structure->number_of_channels / fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); 00289 channel_dwell_time = ((uint32_t)fhss_structure->bs->synch_configuration.fhss_superframe_length * fhss_structure->bs->synch_configuration.fhss_number_of_superframes) / 1000; 00290 // Calculate last synchronisation period 00291 if (fhss_structure->bs->synch_interval != ((uint32_t)fhss_structure->bs->fhss_configuration.fhss_max_synch_interval * 1000)) { 00292 // Last period was half of the current started period and max random period is shorter 00293 synch_period = (fhss_structure->bs->synch_interval / 2) + (bc_density * channel_dwell_time) * (fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels / 2); 00294 } else { 00295 synch_period = fhss_structure->bs->synch_interval + (bc_density * channel_dwell_time) * fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels; 00296 } 00297 00298 // E.g. 240000ms / (50000us * 8) = 600 channels per fhss_beacon_send_interval 00299 channels_per_synch_period = (synch_period * 1000) / ((uint32_t)fhss_structure->bs->synch_configuration.fhss_superframe_length * fhss_structure->bs->synch_configuration.fhss_number_of_superframes); 00300 // Calculate compensation value: how much to compensate on each channel. E.g. 6000us / 600channels = 10us/channel 00301 fhss_structure->bs->synch_monitor.drift_compensation += (fhss_structure->bs->synch_monitor.avg_synch_fix / channels_per_synch_period); 00302 fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->bs->synch_monitor.drift_compensation); 00303 if ((fhss_structure->bs->synch_monitor.avg_synch_fix > FHSS_SYNCH_DRIFT_TOO_HIGH_LIMIT) || (fhss_structure->bs->synch_monitor.avg_synch_fix < -FHSS_SYNCH_DRIFT_TOO_HIGH_LIMIT)) { 00304 // Indicates that more frequent synchronization is needed 00305 retval = -1; 00306 } 00307 return retval; 00308 } 00309 00310 static int fhss_update_synch_monitor(fhss_structure_t *fhss_structure, const fhss_synchronization_beacon_payload_s *payload, uint8_t superframe_own, int32_t remaining_time_own, const int32_t time_to_next_superframe) 00311 { 00312 fhss_synch_configuration_t *configuration = &fhss_structure->bs->synch_configuration; 00313 int super_frame_changed = payload->current_superframe - superframe_own; 00314 int retval = 0; 00315 if (((super_frame_changed < 0) && ((super_frame_changed * -1) < (payload->number_of_superframes_per_channel / 2))) || (super_frame_changed > payload->number_of_superframes_per_channel / 2)) { 00316 /* Our superframe has changed before parent superframe -> we are running too fast 00317 * Own channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00318 * Parent channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00319 * Time: -----------------------------------> 00320 */ 00321 if (super_frame_changed > 0) { 00322 super_frame_changed = (superframe_own + payload->number_of_superframes_per_channel) - payload->current_superframe; 00323 } 00324 } else { 00325 /* Parent superframe has changed before our superframe -> we are running too slow 00326 * Own channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00327 * Parent channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00328 * Time: -----------------------------------> 00329 */ 00330 if (super_frame_changed < 0) { 00331 super_frame_changed = (payload->current_superframe + payload->number_of_superframes_per_channel) - superframe_own; 00332 } 00333 } 00334 00335 /* If superframe changed during synchronization but remaining time to next superframe is high, it is likely that 00336 * superframe change is not valid anymore. Don't use this Beacon for syncronization monitoring. 00337 */ 00338 if ((configuration->fhss_superframe_length - remaining_time_own) > CLOSE_TO_SUPERFRAME_LENGTH) { 00339 remaining_time_own += (int32_t) configuration->fhss_superframe_length * super_frame_changed; 00340 00341 int32_t prev_synch_fix = (time_to_next_superframe - remaining_time_own); 00342 // After network scan counter was initialized to -1 to drop this fix from monitoring 00343 if (fhss_structure->bs->synch_monitor.avg_synch_fix_counter >= 0) { 00344 fhss_structure->bs->synch_monitor.avg_synch_fix += prev_synch_fix; 00345 } 00346 fhss_structure->bs->synch_monitor.avg_synch_fix_counter++; 00347 if (fhss_structure->bs->synch_monitor.avg_synch_fix_counter == SYNCH_MONITOR_AVG_SAMPLES) { 00348 fhss_structure->bs->synch_monitor.avg_synch_fix /= SYNCH_MONITOR_AVG_SAMPLES; 00349 fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->bs->synch_monitor.avg_synch_fix); 00350 retval = fhss_update_drift_compensation(fhss_structure); 00351 fhss_structure->bs->synch_monitor.avg_synch_fix_counter = 0; 00352 fhss_structure->bs->synch_monitor.avg_synch_fix = 0; 00353 } 00354 } 00355 return retval; 00356 } 00357 00358 static int fhss_sync_with_beacon(fhss_structure_t *fhss_structure, 00359 const fhss_synchronization_beacon_payload_s *payload) 00360 { 00361 int ret_val = -1; 00362 int32_t remaining_time_own; 00363 uint8_t superframe_own; 00364 00365 if (fhss_structure) { 00366 // Do not allow synchronising devices above 253 hops. 00367 if (payload->hop_count > (FHSS_MAX_ALLOWED_HOPS - 1)) { 00368 return 0; 00369 } 00370 // To make synchronization monitoring more effective, drop extra Beacons. 00371 if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED && (fhss_is_current_channel_broadcast(fhss_structure) == false || (fhss_structure->bs->beacon_received_on_this_bc_channel == true))) { 00372 return 0; 00373 } 00374 00375 fhss_synch_configuration_t *configuration = &fhss_structure->bs->synch_configuration; 00376 fhss_structure->bs->beacon_received_on_this_bc_channel = true; 00377 00378 superframe_own = fhss_structure->bs->current_superframe; 00379 fhss_structure->bs->current_superframe = payload->current_superframe; 00380 // Clone the static config values from parent which has the authority. 00381 configuration->fhss_number_of_bc_channels = payload->number_of_broadcast_channels; 00382 configuration->fhss_number_of_tx_slots = payload->number_of_tx_slots; 00383 configuration->fhss_superframe_length = payload->superframe_length; 00384 configuration->fhss_number_of_superframes = payload->number_of_superframes_per_channel; 00385 // todo: 00386 // * payload->time_since_last_beacon 00387 uint8_t own_hop_tmp = fhss_structure->own_hop; 00388 if (fhss_is_synch_root(fhss_structure) == false) { 00389 // my own hop count is one more than the parent's 00390 fhss_structure->own_hop = payload->hop_count + 1; 00391 } 00392 fhss_stats_update(fhss_structure, STATS_FHSS_HOP_COUNT, fhss_structure->own_hop); 00393 fhss_structure->bs->channel_list_counter = payload->channel_list_counter; 00394 fhss_structure->bs->current_channel_index = payload->channel_index; 00395 uint8_t mac_address[8]; 00396 fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); 00397 00398 fhss_structure->bs->uc_channel_index = fhss_calculate_uc_index(fhss_structure->bs->current_channel_index, fhss_structure->number_of_channels, 00399 payload->number_of_broadcast_channels) + fhss_get_offset(fhss_structure, mac_address); 00400 00401 // If current channel is not broadcast, fhss_update_channel will increase UC channel index, otherwise do it here 00402 if (fhss_is_current_channel_broadcast(fhss_structure) == true || (fhss_structure->fhss_state == FHSS_SYNCHRONIZED)) { 00403 fhss_structure->bs->uc_channel_index += 1; 00404 } 00405 if (fhss_structure->bs->uc_channel_index >= (fhss_structure->number_of_channels - payload->number_of_broadcast_channels)) { 00406 fhss_structure->bs->uc_channel_index -= (fhss_structure->number_of_channels - payload->number_of_broadcast_channels); 00407 } 00408 00409 fhss_structure->platform_functions.fhss_timer_stop(fhss_superframe_handler, fhss_structure->fhss_api); 00410 // start timer to elapse at approximately same time as the parent will. 00411 const int32_t time_to_next_superframe = payload->remaining_slots; 00412 remaining_time_own = fhss_get_remaining_time_to_next_superframe(fhss_structure); 00413 fhss_start_timer(fhss_structure, time_to_next_superframe, fhss_superframe_handler); 00414 // Reset beacon received timer when FHSS synchronization is updated 00415 fhss_structure->bs->beacons_received_timer = 0; 00416 uint16_t bc_density = (fhss_structure->number_of_channels / fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); 00417 uint8_t fhss_number_of_bc_channels = fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels; 00418 uint16_t channel_dwell_time = ((uint32_t)fhss_structure->bs->synch_configuration.fhss_superframe_length * fhss_structure->bs->synch_configuration.fhss_number_of_superframes) / 1000; 00419 00420 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00421 fhss_structure->fhss_state = FHSS_SYNCHRONIZED; 00422 fhss_change_to_next_channel(fhss_structure); 00423 } 00424 if (fhss_is_synch_root(fhss_structure) == false) { 00425 // Initially synch drift might be massive. Request first few Beacons more frequently until compensation starts fixing the error. 00426 uint32_t beacon_interval_random; 00427 00428 if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { 00429 if (fhss_update_synch_monitor(fhss_structure, payload, superframe_own, remaining_time_own, time_to_next_superframe)) { 00430 fhss_structure->bs->synch_interval = (uint32_t)(fhss_structure->bs->fhss_configuration.fhss_max_synch_interval / BEACON_INTERVAL_INIT_DIVIDER) * 1000; 00431 } 00432 } 00433 00434 if (fhss_structure->bs->synch_interval != ((uint32_t)fhss_structure->bs->fhss_configuration.fhss_max_synch_interval * 1000)) { 00435 fhss_structure->bs->synch_interval *= 2; 00436 if (fhss_structure->bs->synch_interval > ((uint32_t)fhss_structure->bs->fhss_configuration.fhss_max_synch_interval * 1000)) { 00437 fhss_structure->bs->synch_interval = ((uint32_t)fhss_structure->bs->fhss_configuration.fhss_max_synch_interval * 1000); 00438 } 00439 beacon_interval_random = (bc_density * channel_dwell_time) * randLIB_get_random_in_range(0, fhss_number_of_bc_channels / 2); 00440 } else { 00441 beacon_interval_random = (bc_density * channel_dwell_time) * randLIB_get_random_in_range(0, fhss_number_of_bc_channels); 00442 } 00443 fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->bs->synch_interval / 1000); 00444 fhss_beacon_periodic_start(fhss_structure, fhss_structure->bs->synch_interval + beacon_interval_random); 00445 } 00446 // Our hop has changed, needs to inform possible children by sending Beacon 00447 if ((own_hop_tmp != 0) && (own_hop_tmp != fhss_structure->own_hop)) { 00448 fhss_structure->bs->send_synch_info_on_next_broadcast_channel = true; 00449 } 00450 ret_val = 0; 00451 } 00452 return ret_val; 00453 } 00454 00455 static uint32_t fhss_get_remaining_tx_time(fhss_structure_t *fhss_structure) 00456 { 00457 /* To get the remaining TX time, following calculation is performed 00458 * 00459 * rem. time(Y) 00460 * |----------------| 00461 *...| TX | TX | RX | RX |... 00462 *...| SF n | SF n+1 | SF n+2 | SF n+3 |... 00463 * 00464 * Y = remaining time of SF(n) + length of SF(n+1) 00465 * 00466 */ 00467 00468 uint32_t remaining_tx_time = 0; 00469 00470 if (fhss_structure) { 00471 uint8_t cur_superframe = fhss_structure->bs->current_superframe; 00472 uint8_t number_of_tx_slots = fhss_structure->bs->synch_configuration.fhss_number_of_tx_slots; 00473 uint8_t number_of_superframes = fhss_structure->bs->synch_configuration.fhss_number_of_superframes; 00474 uint8_t tx_slot_length = ((number_of_superframes / 2) / number_of_tx_slots); 00475 uint8_t tx_slot_up_limit = tx_slot_length; 00476 uint16_t superframe_length = fhss_structure->bs->synch_configuration.fhss_superframe_length; 00477 00478 if ((fhss_structure->own_hop % 2)) { 00479 tx_slot_up_limit += tx_slot_length; 00480 } 00481 while (number_of_tx_slots--) { 00482 if ((cur_superframe >= (tx_slot_up_limit - tx_slot_length)) && (cur_superframe < tx_slot_up_limit)) { 00483 remaining_tx_time = ((uint32_t)((tx_slot_up_limit - 1) - cur_superframe) * superframe_length) + fhss_get_remaining_time_to_next_superframe(fhss_structure); 00484 break; 00485 } else { 00486 tx_slot_up_limit += (tx_slot_length * 2); 00487 } 00488 } 00489 } 00490 return remaining_tx_time; 00491 } 00492 00493 // CCA adds extra 2ms with FHSS 00494 #define CCA_FHSS_PERIOD 2000 00495 // Ack frame length 00496 #define ACK_LENGTH 5 00497 00498 static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length) 00499 { 00500 bool retval = false; 00501 uint32_t remaining_tx_time; 00502 uint32_t needed_tx_time; 00503 uint32_t tx_processing_delay; 00504 uint32_t ack_processing_delay; 00505 00506 if (!fhss_structure) { 00507 return retval; 00508 } 00509 00510 // Don't care when FHSS is unsynchronized 00511 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00512 retval = true; 00513 } else { 00514 tx_processing_delay = fhss_structure->bs->fhss_configuration.fhss_tuning_parameters.tx_processing_delay; 00515 ack_processing_delay = fhss_structure->bs->fhss_configuration.fhss_tuning_parameters.ack_processing_delay; 00516 // Calculate needed TX time (us): CCA static period + TX processing delays + transmission time + Ack processing delays + Ack transmission time 00517 needed_tx_time = CCA_FHSS_PERIOD + tx_processing_delay + fhss_get_tx_time(fhss_structure, tx_length, phy_header_length, phy_tail_length) 00518 + ack_processing_delay + fhss_get_tx_time(fhss_structure, ACK_LENGTH, phy_header_length, phy_tail_length); 00519 remaining_tx_time = fhss_get_remaining_tx_time(fhss_structure); 00520 if (needed_tx_time <= remaining_tx_time) { 00521 retval = true; 00522 } 00523 } 00524 return retval; 00525 } 00526 00527 static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j) 00528 { 00529 if (i < j) { 00530 uint_fast8_t t = j; 00531 j = (uint8_t) i; 00532 i = t; 00533 } 00534 for (uint_fast8_t k = 2; k <= j; k++) { 00535 if (i % k == 0 && j % k == 0) { 00536 return true; 00537 } 00538 } 00539 return false; 00540 } 00541 00542 00543 static int fhss_generate_scramble_table(fhss_structure_t *fhss_structure) 00544 { 00545 uint8_t j = 2; 00546 // Generate indexes to extend the channel sequence. Generated indexes cannot have common divisors with value number_of_channels. 00547 for (int i = 0; i < MAX_SCRAMBLE_TABLE_INDEXES;) { 00548 // Common divisors are skipped 00549 if (fhss_is_there_common_divisor(fhss_structure->number_of_channels, j) == false) { 00550 fhss_structure->bs->fhss_scramble_table[i] = j; 00551 i++; 00552 } 00553 j++; 00554 } 00555 return 0; 00556 } 00557 00558 static fhss_beacon_info_t *fhss_get_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id) 00559 { 00560 fhss_beacon_info_t *beacon_info; 00561 beacon_info = fhss_structure->bs->fhss_beacon_info_store; 00562 while (beacon_info) { 00563 if (beacon_info->pan_id == pan_id) { 00564 break; 00565 } 00566 beacon_info = beacon_info->next; 00567 } 00568 return beacon_info; 00569 } 00570 00571 static void fhss_store_beacon_info(fhss_structure_t *fhss_structure, fhss_beacon_info_t *beacon_info) 00572 { 00573 fhss_beacon_info_t *beacon_info_cur; 00574 beacon_info->next = NULL; 00575 if (!fhss_structure->bs->fhss_beacon_info_store) { 00576 fhss_structure->bs->fhss_beacon_info_store = beacon_info; 00577 return; 00578 } 00579 beacon_info_cur = fhss_structure->bs->fhss_beacon_info_store; 00580 while (beacon_info_cur->next != NULL) { 00581 beacon_info_cur = beacon_info_cur->next; 00582 } 00583 beacon_info_cur->next = beacon_info; 00584 } 00585 00586 static void fhss_write_beacon_info(fhss_beacon_info_t *beacon_info, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info) 00587 { 00588 beacon_info->pan_id = pan_id; 00589 memcpy(beacon_info->source_address, source_address, 8); 00590 beacon_info->timestamp = timestamp; 00591 memcpy(beacon_info->synch_info, synch_info, sizeof(beacon_info->synch_info)); 00592 } 00593 00594 static fhss_beacon_info_t *fhss_create_beacon_info(fhss_structure_t *fhss_structure) 00595 { 00596 fhss_beacon_info_t *beacon_info = ns_dyn_mem_temporary_alloc(sizeof(fhss_beacon_info_t)); 00597 if (!beacon_info) { 00598 return NULL; 00599 } 00600 fhss_store_beacon_info(fhss_structure, beacon_info); 00601 return beacon_info; 00602 } 00603 00604 static int fhss_remove_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id) 00605 { 00606 if (!fhss_structure || !fhss_structure->bs->fhss_beacon_info_store) { 00607 return -1; 00608 } 00609 00610 if (fhss_structure->bs->fhss_beacon_info_store->pan_id == pan_id) { 00611 fhss_beacon_info_t *next = fhss_structure->bs->fhss_beacon_info_store->next; 00612 ns_dyn_mem_free(fhss_structure->bs->fhss_beacon_info_store); 00613 fhss_structure->bs->fhss_beacon_info_store = next; 00614 return 0; 00615 } 00616 00617 fhss_beacon_info_t *removed_beacon_info = fhss_structure->bs->fhss_beacon_info_store->next; 00618 fhss_beacon_info_t *prev_beacon_info = fhss_structure->bs->fhss_beacon_info_store; 00619 00620 while (removed_beacon_info) { 00621 if (removed_beacon_info->pan_id == pan_id) { 00622 fhss_beacon_info_t *next = removed_beacon_info->next; 00623 ns_dyn_mem_free(removed_beacon_info); 00624 prev_beacon_info->next = next; 00625 return 0; 00626 } 00627 prev_beacon_info = removed_beacon_info; 00628 removed_beacon_info = removed_beacon_info->next; 00629 } 00630 return -1; 00631 } 00632 00633 static int fhss_flush_beacon_info_storage(fhss_structure_t *fhss_structure) 00634 { 00635 if (!fhss_structure) { 00636 return -1; 00637 } 00638 fhss_beacon_info_t *beacon_info = fhss_structure->bs->fhss_beacon_info_store; 00639 while (beacon_info) { 00640 fhss_beacon_info_t *next = beacon_info->next; 00641 ns_dyn_mem_free(beacon_info); 00642 beacon_info = next; 00643 } 00644 fhss_structure->bs->fhss_beacon_info_store = NULL; 00645 return 0; 00646 } 00647 00648 static int fhss_reset(fhss_structure_t *fhss_structure) 00649 { 00650 if (!fhss_structure) { 00651 return -1; 00652 } 00653 fhss_structure->platform_functions.fhss_timer_stop(fhss_superframe_handler, fhss_structure->fhss_api); 00654 fhss_structure->bs->synch_panid = 0xffff; 00655 fhss_beacon_periodic_stop(fhss_structure); 00656 fhss_structure->bs->current_superframe = 0; 00657 fhss_structure->bs->current_channel_index = 0; 00658 fhss_structure->bs->channel_list_counter = 0; 00659 if (fhss_is_synch_root(fhss_structure) == false) { 00660 fhss_structure->own_hop = 0xff; 00661 } 00662 fhss_structure->bs->tx_allowed = false; 00663 fhss_structure->bs->synch_interval = (uint32_t)(fhss_structure->bs->fhss_configuration.fhss_max_synch_interval / BEACON_INTERVAL_INIT_DIVIDER) * 1000; 00664 fhss_structure->rx_channel = 0; 00665 fhss_structure->bs->beacons_received_timer = 0; 00666 memset(fhss_structure->synch_parent, 0xff, 8); 00667 fhss_structure->bs->send_synch_info_on_next_broadcast_channel = false; 00668 memset(&fhss_structure->bs->synch_configuration, 0, sizeof(fhss_synch_configuration_t)); 00669 fhss_structure->bs->synch_infos_sent_counter = 0; 00670 fhss_structure->bs->broadcast_start_superframe = 0; 00671 fhss_failed_list_free(fhss_structure); 00672 fhss_structure->fhss_state = FHSS_UNSYNCHRONIZED; 00673 return 0; 00674 } 00675 00676 static int fhss_add_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info) 00677 { 00678 if (!fhss_structure || !source_address || !synch_info) { 00679 return -1; 00680 } 00681 fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); 00682 if (!beacon_info) { 00683 beacon_info = fhss_create_beacon_info(fhss_structure); 00684 } 00685 if (!beacon_info) { 00686 tr_error("Beacon data not allocated"); 00687 return -2; 00688 } 00689 fhss_write_beacon_info(beacon_info, pan_id, source_address, timestamp, synch_info); 00690 return 0; 00691 } 00692 00693 static void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, uint32_t timestamp) 00694 { 00695 fhss_beacon_info_t *beacon_info; 00696 beacon_info = fhss_structure->bs->fhss_beacon_info_store; 00697 while (beacon_info) { 00698 uint32_t time_since_added = timestamp - beacon_info->timestamp; 00699 // timestamp is microseconds, lifetime is seconds 00700 if (time_since_added >= ((uint32_t)BEACON_INFO_LIFETIME * 1000000)) { 00701 if (fhss_remove_beacon_info(fhss_structure, beacon_info->pan_id) == 0) { 00702 return; 00703 } 00704 } 00705 beacon_info = beacon_info->next; 00706 } 00707 } 00708 00709 static int16_t fhss_synch_state_set_callback(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) 00710 { 00711 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00712 if (!fhss_structure) { 00713 return -1; 00714 } 00715 // State is already set 00716 if (fhss_structure->fhss_state == fhss_state) { 00717 tr_debug("Synch same state %u", fhss_state); 00718 return -1; 00719 } 00720 00721 if (fhss_state == FHSS_UNSYNCHRONIZED) { 00722 tr_debug("FHSS down"); 00723 fhss_reset(fhss_structure); 00724 fhss_reset_synch_monitor(&fhss_structure->bs->synch_monitor); 00725 fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->bs->synch_monitor.drift_compensation); 00726 fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->bs->synch_monitor.avg_synch_fix); 00727 fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->bs->synch_interval / 1000); 00728 } else { 00729 // Do not synchronize to current pan 00730 if (fhss_structure->bs->synch_panid == pan_id) { 00731 tr_debug("Synch same panid %u", pan_id); 00732 return -1; 00733 } 00734 fhss_generate_scramble_table(fhss_structure); 00735 00736 uint8_t mac_address[8]; 00737 fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); 00738 fhss_structure->bs->uc_channel_index = fhss_get_offset(fhss_structure, mac_address); 00739 // Get Beacon info from storage 00740 fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); 00741 if (beacon_info) { 00742 memcpy(fhss_structure->synch_parent, beacon_info->source_address, 8); 00743 platform_enter_critical(); 00744 // Calculate time since the Beacon was received 00745 uint32_t elapsed_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api) - beacon_info->timestamp; 00746 // Synchronize to given PAN 00747 fhss_beacon_received(fhss_structure, beacon_info->synch_info, elapsed_time); 00748 platform_exit_critical(); 00749 // Delete stored Beacon infos 00750 fhss_flush_beacon_info_storage(fhss_structure); 00751 fhss_structure->bs->synch_panid = pan_id; 00752 } else if (fhss_is_synch_root(fhss_structure) == true) { 00753 // Synch root will start new network 00754 fhss_start_timer(fhss_structure, fhss_structure->bs->synch_configuration.fhss_superframe_length, fhss_superframe_handler); 00755 } else { 00756 tr_error("Synch info not found"); 00757 return -1; 00758 } 00759 } 00760 fhss_structure->fhss_state = fhss_state; 00761 return fhss_structure->rx_channel; 00762 } 00763 00764 static void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s *dest, const uint8_t *buffer) 00765 { 00766 dest->data_start_delimeter = *buffer++; 00767 dest->channel_index = *buffer++; 00768 dest->sender_unicast_channel = *buffer++; 00769 dest->current_superframe = common_read_16_bit(buffer); 00770 buffer += BEACON_FIELD_SIZE(current_superframe); 00771 dest->remaining_slots = common_read_16_bit(buffer); 00772 buffer += BEACON_FIELD_SIZE(remaining_slots); 00773 dest->channel_list_counter = common_read_16_bit(buffer); 00774 buffer += BEACON_FIELD_SIZE(channel_list_counter); 00775 dest->hop_count = *buffer++; 00776 dest->number_of_broadcast_channels = *buffer++; 00777 dest->number_of_tx_slots = *buffer++; 00778 dest->time_since_last_beacon = common_read_32_bit(buffer); 00779 buffer += BEACON_FIELD_SIZE(time_since_last_beacon); 00780 dest->processing_delay += common_read_16_bit(buffer); 00781 buffer += BEACON_FIELD_SIZE(processing_delay); 00782 dest->superframe_length = common_read_16_bit(buffer); 00783 buffer += BEACON_FIELD_SIZE(superframe_length); 00784 dest->number_of_superframes_per_channel = *buffer; 00785 } 00786 00787 static uint32_t fhss_get_time_to_next_channel_change(uint16_t remaining_slots_to_next_superframe, uint8_t number_of_superframes, uint8_t current_superframe, uint16_t superframe_length) 00788 { 00789 return remaining_slots_to_next_superframe + ((uint32_t)((number_of_superframes - 1) - current_superframe) * superframe_length); 00790 } 00791 00792 // Decode the given raw byte buffer into a struct into dest struct and calculate 00793 // the new values for elapsed_time, channel_index, current_superframe and remaining_slots 00794 // from current state and given data. 00795 static void fhss_beacon_decode(fhss_synchronization_beacon_payload_s *dest, const uint8_t *buffer, uint32_t elapsed_time, uint16_t number_of_channels) 00796 { 00797 fhss_beacon_decode_raw(dest, buffer); 00798 00799 elapsed_time += dest->processing_delay; 00800 00801 /* To calculate channel index after beacon scan, following calculation is performed 00802 * 00803 * rem. slots to channel change(X) Channel length (V) 00804 * |---------------------| |-----------------------------------------------| 00805 * | RX'd channel index (Y) | ... | Y+n | 00806 * ...| sf1 | sf2 | sf3 | sf4 | ... | sf1 | sf2 | sf3 | sf4 |... 00807 * ^ ^ 00808 * |beacon received |beacon scan done 00809 * |-------------------------------------| 00810 * measured time after beacon RX'd(Z) 00811 * V = superframe length * number of superframes 00812 * X = remaining slots to superframe change + length of the remaining full superframes to channel change 00813 * 00814 * Y+n = Y + ((Z - X) / V) + 1 00815 * 00816 * Or if (Z < X) 00817 * Y+n = Y 00818 */ 00819 00820 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); 00821 uint16_t temp_channel_index = dest->channel_index; 00822 if (elapsed_time >= remaining_slots_to_next_channel) { 00823 uint32_t channel_length = (uint32_t) dest->number_of_superframes_per_channel * dest->superframe_length; 00824 temp_channel_index = dest->channel_index + ((elapsed_time - remaining_slots_to_next_channel) / channel_length) + 1; 00825 } 00826 while (temp_channel_index >= number_of_channels) { 00827 temp_channel_index -= number_of_channels; 00828 dest->channel_list_counter++; 00829 } 00830 dest->channel_index = temp_channel_index; 00831 while (dest->channel_list_counter >= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) { 00832 dest->channel_list_counter -= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES); 00833 } 00834 00835 /* To calculate superframe after beacon scan, following calculation is performed 00836 * 00837 * rem. slots(X) sf. length(V) 00838 * |---------------| |-----------------| 00839 *...| RX'd superframe (Y)| ... | Y+n | Y+n+1 |.... 00840 * ^ ^ 00841 * |beacon received |beacon scan done 00842 * |-------------------------------------| 00843 * measured time after beacon RX'd(Z) 00844 * 00845 * Y+n = Y + ((Z - X) / V) + 1 00846 * 00847 * Or if (Z < X) 00848 * Y+n = Y 00849 */ 00850 00851 if (elapsed_time >= dest->remaining_slots) { 00852 dest->current_superframe = dest->current_superframe + ((elapsed_time - dest->remaining_slots) / dest->superframe_length) + 1; 00853 } 00854 while (dest->current_superframe >= dest->number_of_superframes_per_channel) { 00855 dest->current_superframe -= dest->number_of_superframes_per_channel; 00856 } 00857 00858 /* To get the remaining slots after beacon scan, following calculation is performed 00859 * 00860 * rem. slots(Y) sf. length(V) new rem. slots(X) 00861 * |----------| |---------------| |-------------| 00862 *...| superframe 1 | superframe 2 | superframe 3 | superframe 4 |... 00863 * ^ ^ 00864 * |beacon received |beacon scan done 00865 * |--------------------------------------------| 00866 * measured time after beacon RX'd(Z) 00867 * 00868 * X = V - ((Z - Y) % V) 00869 * 00870 * Or if (Z < Y) 00871 * X = Y - Z 00872 */ 00873 00874 if (elapsed_time < dest->remaining_slots) { 00875 dest->remaining_slots = dest->remaining_slots - elapsed_time; 00876 } else { 00877 dest->remaining_slots = dest->superframe_length - ((elapsed_time - dest->remaining_slots) % dest->superframe_length); 00878 } 00879 } 00880 00881 static int fhss_synch_info_validate(fhss_synchronization_beacon_payload_s *payload) 00882 { 00883 if (!payload) { 00884 return -1; 00885 } 00886 if (payload->data_start_delimeter != 0) { 00887 return -1; 00888 } 00889 if (payload->current_superframe >= payload->number_of_superframes_per_channel) { 00890 return -1; 00891 } 00892 if (payload->remaining_slots >= payload->superframe_length) { 00893 return -1; 00894 } 00895 if (payload->hop_count > FHSS_MAX_ALLOWED_HOPS - 1) { 00896 return -1; 00897 } 00898 if (payload->number_of_broadcast_channels == 0) { 00899 return -1; 00900 } 00901 if (payload->number_of_tx_slots == 0) { 00902 return -1; 00903 } 00904 if (payload->number_of_superframes_per_channel == 0) { 00905 return -1; 00906 } 00907 return 0; 00908 } 00909 00910 static void fhss_beacon_received(fhss_structure_t *fhss_structure, const uint8_t *synch_info, const uint32_t elapsed_time) 00911 { 00912 00913 if (fhss_structure) { 00914 00915 if (synch_info) { 00916 fhss_synchronization_beacon_payload_s temp_payload; 00917 temp_payload.processing_delay = fhss_structure->bs->fhss_configuration.fhss_tuning_parameters.rx_processing_delay; 00918 fhss_beacon_decode(&temp_payload, synch_info, elapsed_time, fhss_structure->number_of_channels); 00919 if (!fhss_synch_info_validate(&temp_payload)) { 00920 fhss_sync_with_beacon(fhss_structure, &temp_payload); 00921 } else { 00922 tr_err("Invalid synch info received"); 00923 } 00924 } 00925 } 00926 } 00927 00928 static uint32_t fhss_get_sf_timeout_callback(fhss_structure_t *fhss_structure) 00929 { 00930 uint32_t compensation = 0; 00931 /* Drift compensation doesn't work with Linux platform */ 00932 #ifndef __linux__ 00933 // Drift compensation on first superframe 00934 if (fhss_structure->bs->current_superframe == 0) { 00935 /* Idea is to compensate number of drift_compensation (microseconds) on each channel. 00936 * However, fhss_resolution_divider defines the minimum timer resolution. 00937 * E.g. if fhss_resolution_divider = 64, compensate (drift_compensation * 64) on each 64th channel. 00938 */ 00939 if (++fhss_structure->bs->synch_monitor.channel_counter == fhss_structure->platform_functions.fhss_resolution_divider) { 00940 compensation = fhss_structure->bs->synch_monitor.drift_compensation; 00941 fhss_structure->bs->synch_monitor.channel_counter = 0; 00942 } 00943 } 00944 #else 00945 (void) fhss_structure; 00946 #endif //__linux__ 00947 return (fhss_structure->bs->synch_configuration.fhss_superframe_length) + (compensation * fhss_structure->platform_functions.fhss_resolution_divider); 00948 } 00949 00950 static void fhss_superframe_callback(fhss_structure_t *fhss_structure) 00951 { 00952 if ((fhss_structure->bs->send_synch_info_on_next_broadcast_channel == true) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) { 00953 /* Randomize sending superframe of synchronization frame: 00954 * on first superframe probability is 1/number of superframes 00955 * on second superframe probability is 1/(number of superframes-1) 00956 * on third superframe probability is 1/(number of superframes-2) 00957 * on last superframe probability is 1/1 00958 */ 00959 if (randLIB_get_random_in_range(1, fhss_structure->bs->synch_configuration.fhss_number_of_superframes - fhss_structure->bs->current_superframe) == 1) { 00960 fhss_structure->bs->send_synch_info_on_next_broadcast_channel = false; 00961 fhss_structure->bs->synch_infos_sent_counter++; 00962 fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_FRAME); 00963 } 00964 } 00965 fhss_update_txrx_slots(fhss_structure); 00966 uint16_t queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false) + fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true); 00967 if ((fhss_structure->bs->tx_allowed == true || fhss_is_current_channel_broadcast(fhss_structure) == true) && queue_size) { 00968 /* Start timer with random timeout to trigger TX queue poll event. 00969 * Max random is half of the superframe length. Event timer resolution is 50us. 00970 * Divide Max random with TX queue size to transmit faster when TX queue is growing 00971 */ 00972 uint16_t max_random = ((fhss_structure->bs->synch_configuration.fhss_superframe_length / 2) / 50) / queue_size; 00973 eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(1, max_random)); 00974 } 00975 } 00976 00977 static int fhss_tx_handle_callback(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length, uint32_t tx_time) 00978 { 00979 (void) tx_time; 00980 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00981 if (!fhss_structure) { 00982 return -2; 00983 } 00984 // TODO: needs some more logic to push buffer back to queue 00985 if (frame_type == FHSS_DATA_FRAME) { 00986 if (is_broadcast_addr == true) { 00987 if (fhss_is_current_channel_broadcast(fhss_structure) == false) { 00988 return -3; 00989 } 00990 } 00991 } 00992 if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { 00993 return -1; 00994 } 00995 // If sending Beacon request on parents Unicast channel 00996 if (frame_type == FHSS_SYNCH_REQUEST_FRAME && fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { 00997 fhss_change_to_parent_channel(fhss_structure); 00998 } else if (frame_type == FHSS_DATA_FRAME) { 00999 fhss_change_to_tx_channel(fhss_structure, destination_address); 01000 } 01001 return 0; 01002 } 01003 01004 static bool fhss_check_tx_conditions_callback(const fhss_api_t *api, bool is_broadcast_addr, uint8_t handle, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length) 01005 { 01006 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01007 if (!fhss_structure) { 01008 return true; 01009 } 01010 // This condition will check that message is not sent on bad channel 01011 if (fhss_check_bad_channel(fhss_structure, handle) == false) { 01012 return false; 01013 } 01014 01015 // This condition will check that broadcast messages are sent only broadcast channels 01016 if (fhss_check_channel_type(fhss_structure, is_broadcast_addr, frame_type) == false) { 01017 return false; 01018 } 01019 01020 // This condition will check that FHSS is on TX slot and there is enough time to transmit before channel or slot change 01021 if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { 01022 return false; 01023 } 01024 01025 return true; 01026 } 01027 01028 static void fhss_update_channel_callback(fhss_structure_t *fhss_structure) 01029 { 01030 if (fhss_structure->bs->current_channel_index == 0) { 01031 fhss_structure->bs->synch_infos_sent_counter = 0; 01032 if (++fhss_structure->bs->channel_list_counter >= ((uint16_t) fhss_structure->number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) { 01033 fhss_structure->bs->channel_list_counter = 0; 01034 } 01035 if (fhss_is_synch_root(fhss_structure) == false) { 01036 fhss_trig_event(fhss_structure, FHSS_COMPARE_SYNCH_PARENT); 01037 } 01038 fhss_trig_event(fhss_structure, FHSS_UPDATE_SYNCH_INFO_STORAGE); 01039 } 01040 // If channel is broadcast channel (true), send event 01041 if (fhss_change_to_next_channel(fhss_structure) == true) { 01042 // Only if device is border router 01043 if (fhss_structure->own_hop == 0) { 01044 fhss_trig_event(fhss_structure, FHSS_BROADCAST_CHANNEL); 01045 } 01046 } 01047 } 01048 01049 static uint8_t *fhss_beacon_encode_raw(uint8_t *buffer, const fhss_synchronization_beacon_payload_s *source) 01050 { 01051 *buffer++ = FHSS_DATA_START_DELIMETER; 01052 *buffer++ = source->channel_index; 01053 *buffer++ = source->sender_unicast_channel; 01054 buffer = common_write_16_bit(source->current_superframe, buffer); 01055 buffer = common_write_16_bit(source->remaining_slots, buffer); 01056 buffer = common_write_16_bit(source->channel_list_counter, buffer); 01057 *buffer++ = source->hop_count; 01058 *buffer++ = source->number_of_broadcast_channels; 01059 *buffer++ = source->number_of_tx_slots; 01060 buffer = common_write_32_bit(source->time_since_last_beacon, buffer); 01061 buffer = common_write_16_bit(source->processing_delay, buffer); 01062 buffer = common_write_16_bit(source->superframe_length, buffer); 01063 *buffer++ = source->number_of_superframes_per_channel; 01064 01065 return buffer; 01066 } 01067 01068 static void fhss_beacon_build(fhss_structure_t *fhss_structure, uint8_t *dest, uint32_t tx_time) 01069 { 01070 fhss_synchronization_beacon_payload_s temp_payload; 01071 platform_enter_critical(); 01072 const fhss_synch_configuration_t *config = &fhss_structure->bs->synch_configuration; 01073 temp_payload.channel_index = fhss_structure->bs->current_channel_index; 01074 temp_payload.sender_unicast_channel = 0; 01075 temp_payload.current_superframe = fhss_structure->bs->current_superframe; 01076 // This assumes that the time is always in the range of 0..2**16, which 01077 // should be the case as the superframe length field is also in that range. 01078 temp_payload.remaining_slots = (uint16_t) fhss_get_remaining_time_to_next_superframe(fhss_structure); 01079 temp_payload.channel_list_counter = fhss_structure->bs->channel_list_counter; 01080 temp_payload.hop_count = fhss_structure->own_hop; 01081 temp_payload.number_of_broadcast_channels = config->fhss_number_of_bc_channels; 01082 temp_payload.number_of_tx_slots = config->fhss_number_of_tx_slots; 01083 temp_payload.time_since_last_beacon = 0; // XXX not available yet 01084 uint32_t time_to_tx = 0; 01085 uint32_t cur_time = fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api); 01086 if (cur_time < tx_time) { 01087 time_to_tx = tx_time - cur_time; 01088 } 01089 temp_payload.processing_delay = fhss_structure->bs->fhss_configuration.fhss_tuning_parameters.tx_processing_delay + time_to_tx; 01090 temp_payload.superframe_length = config->fhss_superframe_length; 01091 temp_payload.number_of_superframes_per_channel = config->fhss_number_of_superframes; 01092 platform_exit_critical(); 01093 fhss_beacon_encode_raw(dest, &temp_payload); 01094 } 01095 01096 static int16_t fhss_write_synch_info_callback(const fhss_api_t *api, uint8_t *ptr, uint8_t length, int frame_type, uint32_t tx_time) 01097 { 01098 (void) length; 01099 (void) tx_time; 01100 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01101 if (!fhss_structure || !ptr || (frame_type != FHSS_SYNCH_FRAME)) { 01102 return -1; 01103 } 01104 fhss_beacon_build(fhss_structure, ptr, tx_time); 01105 return FHSS_SYNCH_INFO_LENGTH; 01106 } 01107 01108 static void fhss_data_tx_done_callback(const fhss_api_t *api, bool waiting_ack, bool tx_completed, uint8_t handle) 01109 { 01110 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01111 if (!fhss_structure) { 01112 return; 01113 } 01114 if (waiting_ack == false) { 01115 fhss_change_to_rx_channel(fhss_structure); 01116 } 01117 // Buffer was successfully transmitted. Remove stored failure handle if exists. 01118 if (tx_completed == true) { 01119 fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle); 01120 if (fhss_failed_tx) { 01121 fhss_failed_handle_remove(fhss_structure, handle); 01122 } 01123 } 01124 } 01125 01126 static bool fhss_data_tx_fail_callback(const fhss_api_t *api, uint8_t handle, int frame_type) 01127 { 01128 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01129 if (!fhss_structure) { 01130 return false; 01131 } 01132 // Only use channel retries when device is synchronized 01133 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 01134 return false; 01135 } 01136 #ifdef FHSS_CHANNEL_DEBUG 01137 tr_info("TX failed on ch: %u", debug_destination_channel); 01138 #endif /*FHSS_CHANNEL_DEBUG*/ 01139 // Channel retries are disabled -> return 01140 if (fhss_structure->bs->fhss_configuration.fhss_number_of_channel_retries == 0) { 01141 return false; 01142 } 01143 // Use channel retries only for data frames 01144 if (FHSS_DATA_FRAME != frame_type) { 01145 return false; 01146 } 01147 01148 fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle); 01149 if (fhss_failed_tx) { 01150 fhss_failed_tx->retries_done++; 01151 if (fhss_failed_tx->retries_done >= fhss_structure->bs->fhss_configuration.fhss_number_of_channel_retries) { 01152 // No more retries. Return false to stop retransmitting. 01153 fhss_failed_handle_remove(fhss_structure, handle); 01154 return false; 01155 } 01156 } else { 01157 // Create new failure handle and return true to retransmit 01158 fhss_failed_handle_add(fhss_structure, handle, fhss_structure->rx_channel); 01159 } 01160 return true; 01161 } 01162 01163 static void fhss_receive_frame_callback(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type) 01164 { 01165 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01166 if (!fhss_structure) { 01167 return; 01168 } 01169 if (FHSS_SYNCH_FRAME == frame_type) { 01170 if ((fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) || fhss_structure->bs->synch_panid != pan_id) { 01171 fhss_add_beacon_info(fhss_structure, pan_id, source_address, timestamp, synch_info); 01172 } else { 01173 if (!fhss_compare_with_synch_parent_address(fhss_structure, source_address)) { 01174 // Synch parent address needs to be updated in case parent has changed 01175 fhss_update_synch_parent_address(fhss_structure); 01176 platform_enter_critical(); 01177 // Calculate time since the Beacon was received 01178 uint32_t elapsed_time = fhss_structure->callbacks.read_timestamp(api) - timestamp; 01179 // Synchronize to given PAN 01180 fhss_beacon_received(fhss_structure, synch_info, elapsed_time); 01181 platform_exit_critical(); 01182 } 01183 } 01184 } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type) { 01185 // If current channel is broadcast, we don't need to send another synch info on next broadcast channel. 01186 // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle 01187 if ((fhss_structure->fhss_state == FHSS_SYNCHRONIZED) && (fhss_is_current_channel_broadcast(fhss_structure) == false) 01188 && (fhss_structure->bs->synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST)) { 01189 fhss_structure->bs->send_synch_info_on_next_broadcast_channel = true; 01190 } 01191 } 01192 } 01193 01194 static uint32_t fhss_get_retry_period_callback(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu) 01195 { 01196 uint16_t retry_period = 0; 01197 uint16_t random_number = randLIB_get_16bit(); 01198 uint16_t rnd_mask; 01199 01200 /* Generate retry back-off period. FHSS is using the known synchronization parent info to delay retransmissions upstream. 01201 * 01202 */ 01203 if (phy_mtu < 128) { 01204 // Max. random when PHY MTU below 128 is 6.4ms 01205 rnd_mask = 0x7f; 01206 } else if (phy_mtu < 256) { 01207 // Max. random when PHY MTU below 256 is 12.8ms 01208 rnd_mask = 0xff; 01209 } else { 01210 // Max. random when PHY MTU above 255 is 25.6ms 01211 rnd_mask = 0x1ff; 01212 } 01213 01214 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01215 if (fhss_structure) { 01216 uint32_t datarate = fhss_structure->callbacks.read_datarate(fhss_structure->fhss_api); 01217 uint16_t max_tx_length; 01218 01219 if (datarate && phy_mtu) { 01220 if (fhss_compare_with_synch_parent_address(fhss_structure, destination_address) == 0) { 01221 // E.g. (1000000 / (250000bit/s / 8 bits)) * 255 bytes = 8160us 01222 max_tx_length = ((1000000 / (datarate / 8)) * phy_mtu); 01223 /* Retrying upstream: delay the transmission until assumed hidden node has retried downstream: 01224 * Static period: max random + max tx length 01225 * 50 comes from MAC timer resolution (50us) 01226 */ 01227 retry_period = (rnd_mask + (max_tx_length / 50)); 01228 } 01229 } 01230 } 01231 01232 // Add 1 to not to ever return zero value. 01233 retry_period += ((random_number & rnd_mask) + 1); 01234 return retry_period; 01235 } 01236 01237 static bool fhss_is_broadcast_channel_callback(const fhss_api_t *api) 01238 { 01239 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01240 if (!fhss_structure) { 01241 return true; 01242 } 01243 // FHSS is unsynchronized, broadcasts allowed 01244 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 01245 return true; 01246 } 01247 return fhss_is_current_channel_broadcast(fhss_structure); 01248 } 01249 01250 static bool fhss_use_broadcast_queue_cb(const fhss_api_t *api, bool is_broadcast_addr, int frame_type) 01251 { 01252 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 01253 if (!fhss_structure) { 01254 return false; 01255 } 01256 // Synch requests are always stored in unicast queue 01257 if (frame_type == FHSS_SYNCH_REQUEST_FRAME) { 01258 return false; 01259 } 01260 // Broadcast packets are stored in broadcast queue 01261 return is_broadcast_addr; 01262 } 01263 01264 static void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay) 01265 { 01266 uint32_t timeout = 0; 01267 fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); 01268 if (!fhss_structure) { 01269 return; 01270 } 01271 01272 timeout = fhss_get_sf_timeout_callback(fhss_structure); 01273 01274 fhss_start_timer(fhss_structure, timeout - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_superframe_handler); 01275 01276 if (fhss_structure->bs->current_superframe++ >= (fhss_structure->bs->synch_configuration.fhss_number_of_superframes - 1)) { 01277 fhss_structure->bs->current_superframe = 0; 01278 if (++fhss_structure->bs->current_channel_index >= fhss_structure->number_of_channels) { 01279 fhss_structure->bs->current_channel_index = 0; 01280 } 01281 fhss_update_channel_callback(fhss_structure); 01282 } 01283 fhss_superframe_callback(fhss_structure); 01284 01285 if (fhss_structure->fhss_timeout) { 01286 fhss_structure->fhss_timer += fhss_structure->bs->synch_configuration.fhss_superframe_length; 01287 if (fhss_structure->fhss_timer >= fhss_structure->fhss_timeout) { 01288 fhss_trig_event(fhss_structure, FHSS_TIMER_EVENT); 01289 fhss_structure->fhss_timeout = 0; 01290 fhss_structure->fhss_timer = 0; 01291 } 01292 } 01293 } 01294 01295 uint32_t fhss_get_remaining_time_to_next_superframe(const fhss_structure_t *fhss_structure) 01296 { 01297 const uint32_t slots = fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_superframe_handler, fhss_structure->fhss_api); 01298 return (slots * fhss_structure->platform_functions.fhss_resolution_divider); 01299 } 01300 01301 int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration) 01302 { 01303 if (!fhss_structure) { 01304 return -1; 01305 } 01306 if (!fhss_synch_configuration) { 01307 return -2; 01308 } 01309 // None of the configurations can be set zero 01310 if (fhss_synch_configuration->fhss_number_of_bc_channels == 0 || fhss_synch_configuration->fhss_number_of_tx_slots == 0 01311 || fhss_synch_configuration->fhss_number_of_superframes == 0 || fhss_synch_configuration->fhss_superframe_length == 0) { 01312 return -3; 01313 } 01314 // Number of channels must be divisible with the number of broadcast channels. 01315 // Number of superframes must be divisible with the number of TX slots 01316 if (((fhss_structure->number_of_channels % fhss_synch_configuration->fhss_number_of_bc_channels) != 0) || 01317 ((fhss_synch_configuration->fhss_number_of_superframes % fhss_synch_configuration->fhss_number_of_tx_slots) != 0) || 01318 (fhss_synch_configuration->fhss_number_of_superframes <= fhss_synch_configuration->fhss_number_of_tx_slots)) { 01319 return -4; 01320 } 01321 fhss_structure->bs->synch_configuration = *fhss_synch_configuration; 01322 fhss_structure->own_hop = 0; 01323 return 0; 01324 } 01325 01326 uint8_t fhss_calculate_uc_index(uint8_t channel_index, uint16_t number_of_channels, uint8_t number_of_broadcast_channels) 01327 { 01328 // When channel index is 0, return last unicast index 01329 if (channel_index == 0) { 01330 return (number_of_channels - number_of_broadcast_channels - 1); 01331 } 01332 uint16_t bc_channel_density = (number_of_channels / number_of_broadcast_channels); 01333 return channel_index - (channel_index / bc_channel_density) - 1; 01334 } 01335 01336 int fhss_set_callbacks(fhss_structure_t *fhss_structure) 01337 { 01338 // Set external API 01339 fhss_structure->fhss_api->is_broadcast_channel = &fhss_is_broadcast_channel_callback; 01340 fhss_structure->fhss_api->use_broadcast_queue = &fhss_use_broadcast_queue_cb; 01341 fhss_structure->fhss_api->tx_handle = &fhss_tx_handle_callback; 01342 fhss_structure->fhss_api->check_tx_conditions = &fhss_check_tx_conditions_callback; 01343 fhss_structure->fhss_api->receive_frame = &fhss_receive_frame_callback; 01344 fhss_structure->fhss_api->data_tx_done = &fhss_data_tx_done_callback; 01345 fhss_structure->fhss_api->data_tx_fail = &fhss_data_tx_fail_callback; 01346 fhss_structure->fhss_api->synch_state_set = &fhss_synch_state_set_callback; 01347 fhss_structure->fhss_api->read_timestamp = &fhss_read_timestamp_cb; 01348 fhss_structure->fhss_api->get_retry_period = &fhss_get_retry_period_callback; 01349 fhss_structure->fhss_api->write_synch_info = &fhss_write_synch_info_callback; 01350 fhss_structure->fhss_api->init_callbacks = &fhss_init_callbacks_cb; 01351 01352 return 0; 01353 } 01354 01355 static int8_t fhss_beacon_create_tasklet(fhss_structure_t *fhss_structure) 01356 { 01357 if (fhss_structure->beacon_tasklet_id < 0) { 01358 fhss_structure->beacon_tasklet_id = eventOS_event_handler_create(fhss_beacon_tasklet_func, FHSS_TASKLET_INIT_EVENT); 01359 } 01360 return fhss_structure->beacon_tasklet_id; 01361 } 01362 01363 static int fhss_beacon_periodic_start(fhss_structure_t *fhss_structure, uint32_t time_to_first_beacon) 01364 { 01365 int ret_val = -1; 01366 01367 if (fhss_structure) { 01368 fhss_beacon_periodic_stop(fhss_structure); 01369 ret_val = fhss_timeout_start(fhss_structure, time_to_first_beacon * 1000); 01370 } 01371 return ret_val; 01372 } 01373 01374 static void fhss_beacon_periodic_stop(fhss_structure_t *fhss_structure) 01375 { 01376 if (fhss_structure) { 01377 fhss_timeout_stop(fhss_structure); 01378 } 01379 } 01380 01381 static void fhss_beacon_tasklet_func(arm_event_s *event) 01382 { 01383 fhss_structure_t *fhss_structure = (fhss_structure_t *)event->data_ptr; 01384 if (!fhss_structure) { 01385 return; 01386 } 01387 uint8_t parent_address[8]; 01388 fhss_clear_active_event(fhss_structure, event->event_type); 01389 // skip the init event as there will be a timer event after 01390 if (event->event_type == FHSS_TIMER_EVENT) { 01391 // Stop network when lost number of FHSS_SYNCHRONIZATION_LOST synchronization beacons from parent in a row. 01392 if (fhss_structure->bs->beacons_received_timer >= FHSS_SYNCHRONIZATION_LOST) { 01393 fhss_structure->callbacks.synch_lost_notification(fhss_structure->fhss_api); 01394 fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_LOST, 1); 01395 tr_err("FHSS synchronization lost"); 01396 } else { 01397 uint16_t bc_density = (fhss_structure->number_of_channels / fhss_structure->bs->synch_configuration.fhss_number_of_bc_channels); 01398 uint16_t channel_dwell_time = ((uint32_t)fhss_structure->bs->synch_configuration.fhss_superframe_length * fhss_structure->bs->synch_configuration.fhss_number_of_superframes) / 1000; 01399 01400 fhss_beacon_periodic_start(fhss_structure, (bc_density * channel_dwell_time) * 2); 01401 // Send synchronization request 01402 fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_REQUEST_FRAME); 01403 fhss_structure->bs->beacons_received_timer++; 01404 #ifdef FEA_TRACE_SUPPORT 01405 if (!fhss_get_parent_address(fhss_structure, parent_address)) { 01406 tr_debug("Update synch, attempt: %u, %s", fhss_structure->bs->beacons_received_timer, trace_array(parent_address, 8)); 01407 } else { 01408 tr_err("No synch parent found"); 01409 } 01410 #endif /*FEA_TRACE_SUPPORT*/ 01411 } 01412 } 01413 // Compare if synchronization parent has changed and request beacon if needed 01414 else if (event->event_type == FHSS_COMPARE_SYNCH_PARENT) { 01415 if (fhss_compare_with_synch_parent_address(fhss_structure, fhss_structure->synch_parent)) { 01416 fhss_structure->bs->synch_monitor.avg_synch_fix = 0; 01417 if (fhss_structure->bs->synch_monitor.avg_synch_fix_counter > 0) { 01418 fhss_structure->bs->synch_monitor.avg_synch_fix_counter = 0; 01419 } 01420 // Send synchronization request 01421 fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_REQUEST_FRAME); 01422 #ifdef FEA_TRACE_SUPPORT 01423 if (!fhss_get_parent_address(fhss_structure, parent_address)) { 01424 tr_debug("Synch parent changed, New: %s, Old: %s\n", trace_array(parent_address, 8), trace_array(fhss_structure->synch_parent, 8)); 01425 } else { 01426 tr_err("Synch parent changed : No parent found"); 01427 } 01428 #endif /*FEA_TRACE_SUPPORT*/ 01429 } 01430 } else if (event->event_type == FHSS_BROADCAST_CHANNEL) { 01431 uint16_t superframe_length = fhss_structure->bs->synch_configuration.fhss_superframe_length; 01432 uint8_t number_of_superframes = fhss_structure->bs->synch_configuration.fhss_number_of_superframes; 01433 // Given broadcast time is channel length minus 1 superframe 01434 fhss_structure->callbacks.broadcast_notify(fhss_structure->fhss_api, (uint32_t)superframe_length * (number_of_superframes - 1)); 01435 } 01436 // Update Beacon info lifetimes 01437 else if (event->event_type == FHSS_UPDATE_SYNCH_INFO_STORAGE) { 01438 fhss_update_beacon_info_lifetimes(fhss_structure, fhss_structure->callbacks.read_timestamp(fhss_structure->fhss_api)); 01439 } 01440 }
Generated on Tue Jul 12 2022 13:54:21 by
1.7.2