BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
fhss.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 #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_channel.h" 00023 #include "channel_list.h" 00024 #include "nsdynmemLIB.h" 00025 #include "fhss_beacon.h" 00026 #include "fhss_statistics.h" 00027 #include "ns_trace.h" 00028 #include "eventOS_event.h" 00029 #include "eventOS_callback_timer.h" 00030 #include "randLIB.h" 00031 #include <string.h> 00032 00033 #define TRACE_GROUP "fhss" 00034 // Uncomment this to get timestamped output on superframe events. 00035 // Note: the result may be massive, as there will be dozens or hundreds of lines of trace per second. 00036 // #define FHSS_MASSIVE_TRACE 00037 00038 // TODO: create linked list 00039 // FHSS object pointer 00040 fhss_structure_t *fhss_struct = 0; 00041 00042 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); 00043 static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); 00044 static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); 00045 static int fhss_generate_scramble_table(fhss_structure_t *fhss_structure); 00046 static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j); 00047 static void fhss_update_channel(fhss_structure_t *fhss_structure); 00048 static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor, bool reset_compensation); 00049 static int fhss_reset(fhss_structure_t *fhss_structure); 00050 static void fhss_failed_list_free(fhss_structure_t *fhss_structure); 00051 00052 00053 int8_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) 00054 { 00055 if (!fhss_api || !fhss_configuration || !fhss_timer || fhss_struct) { 00056 tr_err("Invalid FHSS enable configuration"); 00057 return -1; 00058 } 00059 int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); 00060 if (channel_count <= 0) { 00061 // There must be at least one configured channel in channel list 00062 return -2; 00063 } 00064 fhss_struct = ns_dyn_mem_alloc(sizeof(fhss_structure_t)); 00065 if (!fhss_struct) { 00066 return -3; 00067 } 00068 fhss_struct->fhss_api = fhss_api; 00069 fhss_struct->fhss_configuration = *fhss_configuration; 00070 fhss_struct->platform_functions = *fhss_timer; 00071 fhss_struct->fhss_stats_ptr = fhss_statistics; 00072 fhss_struct->number_of_channels = channel_count; 00073 00074 // set a invalid id to tasklet_id, so we know that one is not started yet 00075 fhss_struct->beacon_tasklet_id = -1; 00076 00077 if (!fhss_struct->platform_functions.fhss_resolution_divider) { 00078 fhss_struct->platform_functions.fhss_resolution_divider = 1; 00079 } 00080 // Default synch interval is 240 seconds 00081 if (!fhss_struct->fhss_configuration.fhss_max_synch_interval) { 00082 fhss_struct->fhss_configuration.fhss_max_synch_interval = 240; 00083 } 00084 ns_list_init(&fhss_struct->fhss_failed_tx_list); 00085 fhss_struct->own_hop = 0xff; 00086 fhss_reset(fhss_struct); 00087 fhss_reset_synch_monitor(&fhss_struct->synch_monitor, true); 00088 fhss_struct->active_fhss_events = 0; 00089 fhss_struct->fhss_beacon_info_store = NULL; 00090 fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); 00091 00092 fhss_generate_scramble_table(fhss_struct); 00093 00094 if (fhss_beacon_create_tasklet(fhss_struct) < 0) { 00095 // XXX: should we free the fhss_structure here? 00096 return -5; 00097 } 00098 00099 return 0; 00100 } 00101 00102 int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate) 00103 { 00104 if (!fhss_structure) { 00105 return -1; 00106 } 00107 // If datarate is not set, use default 250kbit/s. Datarate is used as divider later. 00108 if (!datarate) { 00109 datarate = 250000; 00110 } 00111 fhss_structure->datarate = datarate; 00112 return 0; 00113 } 00114 00115 int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration) 00116 { 00117 if (!fhss_structure) { 00118 return -1; 00119 } 00120 if (!fhss_synch_configuration) { 00121 return -2; 00122 } 00123 // None of the configurations can be set zero 00124 if( fhss_synch_configuration->fhss_number_of_bc_channels == 0 || fhss_synch_configuration->fhss_number_of_tx_slots == 0 00125 || fhss_synch_configuration->fhss_number_of_superframes == 0 || fhss_synch_configuration->fhss_superframe_length == 0) { 00126 return -3; 00127 } 00128 // Number of channels must be divisible with the number of broadcast channels. 00129 // Number of superframes must be divisible with the number of TX slots 00130 if (((fhss_structure->number_of_channels % fhss_synch_configuration->fhss_number_of_bc_channels) != 0) || 00131 ((fhss_synch_configuration->fhss_number_of_superframes % fhss_synch_configuration->fhss_number_of_tx_slots) != 0) || 00132 (fhss_synch_configuration->fhss_number_of_superframes <= fhss_synch_configuration->fhss_number_of_tx_slots)) { 00133 return -4; 00134 } 00135 fhss_structure->synch_configuration = *fhss_synch_configuration; 00136 fhss_structure->own_hop = 0; 00137 return 0; 00138 } 00139 00140 fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api) 00141 { 00142 if (!fhss_api || !fhss_struct) { 00143 return NULL; 00144 } 00145 if (fhss_struct->fhss_api == fhss_api) { 00146 return fhss_struct; 00147 } 00148 return NULL; 00149 } 00150 00151 bool fhss_is_synch_root(fhss_structure_t *fhss_structure) 00152 { 00153 if (fhss_structure->own_hop > 0) { 00154 return false; 00155 } 00156 return true; 00157 } 00158 00159 void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) 00160 { 00161 fhss_structure->active_fhss_events |= (1 << event_type); 00162 } 00163 00164 void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) 00165 { 00166 fhss_structure->active_fhss_events &= ~(1 << event_type); 00167 } 00168 00169 bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) 00170 { 00171 if (fhss_structure->active_fhss_events & (1 << event_type)) { 00172 return true; 00173 } 00174 return false; 00175 } 00176 00177 static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) 00178 { 00179 if (timer_id <0 || !fhss_struct) { 00180 return NULL; 00181 } 00182 if (fhss_struct->fhss_event_timer == timer_id) { 00183 return fhss_struct; 00184 } 00185 return NULL; 00186 } 00187 00188 static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure) 00189 { 00190 if (fhss_structure->current_superframe >= fhss_structure->broadcast_start_superframe) { 00191 return true; 00192 } 00193 00194 return false; 00195 } 00196 00197 bool fhss_check_bad_channel(fhss_structure_t *fhss_structure, uint8_t handle) 00198 { 00199 if (!fhss_structure) { 00200 return false; 00201 } 00202 fhss_failed_tx_t *failed_tx = fhss_failed_handle_find(fhss_structure, handle); 00203 if (!failed_tx) { 00204 return true; 00205 } 00206 if (failed_tx->bad_channel == fhss_structure->rx_channel) { 00207 return false; 00208 } 00209 return true; 00210 } 00211 00212 bool fhss_check_channel_type(fhss_structure_t *fhss_structure, bool is_bc, int frame_type) 00213 { 00214 if (!fhss_structure) { 00215 return false; 00216 } 00217 00218 // Channel type check is valid only when FHSS is synchronized 00219 if(fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00220 return true; 00221 } 00222 00223 if (frame_type == FHSS_DATA_FRAME) { 00224 if (is_bc == true) { 00225 // Drop: if packet has broadcast destination but current channel is unicast channel or current superframe is not broadcast sending superframe 00226 if ((fhss_is_current_channel_broadcast(fhss_structure) == false) || (fhss_is_bc_sending_superframe(fhss_structure) == false)) { 00227 return false; 00228 } 00229 } else if (fhss_is_current_channel_broadcast(fhss_structure) == true) { 00230 // Drop: If waiting synchronization Beacon and packet has unicast destination 00231 if (fhss_structure->beacons_received_timer) { 00232 return false; 00233 } 00234 } 00235 } 00236 if (frame_type == FHSS_SYNCH_FRAME) { 00237 00238 } 00239 if (frame_type == FHSS_SYNCH_REQUEST_FRAME) { 00240 // Drop: If we have unicast channels in our configuration and current channel is broadcast channel 00241 if ((fhss_structure->number_of_channels > fhss_structure->synch_configuration.fhss_number_of_bc_channels) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) { 00242 return false; 00243 } 00244 00245 uint8_t current_superframe = fhss_structure->current_superframe; 00246 uint8_t synch_attempt = fhss_structure->beacons_received_timer; 00247 if (fhss_structure->synch_configuration.fhss_number_of_tx_slots > 1) { 00248 // Send synch request either before or after the middle of the channel depending on attempt number. 00249 uint8_t middle_of_superframes = fhss_structure->synch_configuration.fhss_number_of_superframes / 2; 00250 00251 if (synch_attempt & 1) { 00252 if (fhss_structure->current_superframe < middle_of_superframes) { 00253 return false; 00254 } 00255 } else { 00256 if (fhss_structure->current_superframe >= middle_of_superframes) { 00257 return false; 00258 } 00259 } 00260 } else if ((current_superframe == 0) || (current_superframe == (fhss_structure->synch_configuration.fhss_number_of_superframes - 1))){ 00261 return false; 00262 } 00263 } 00264 return true; 00265 00266 } 00267 00268 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) 00269 { 00270 if (!fhss_structure) { 00271 return false; 00272 } 00273 // Check is valid only when FHSS is synchronized 00274 if(fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00275 return true; 00276 } 00277 // Allow: If sending synchronization frame 00278 if (frame_type == FHSS_SYNCH_FRAME) { 00279 return true; 00280 } 00281 // Allow: If sending broadcast (on broadcast channel) 00282 if (is_bc == true) { 00283 return true; 00284 } 00285 // Deny: If FHSS is not on TX slot 00286 if (fhss_structure->tx_allowed == false) { 00287 return false; 00288 } 00289 // Deny: If not enough time before TX slot end 00290 if (fhss_check_remaining_tx_time(fhss_structure, frame_length, phy_header_length, phy_tail_length) == false) { 00291 return false; 00292 } 00293 return true; 00294 } 00295 00296 static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor, bool reset_compensation) 00297 { 00298 if (synch_monitor) { 00299 synch_monitor->avg_synch_fix = 0; 00300 // Initialize to -1 instead of 0 to drop the first beacon after network scan (from synch monitoring) 00301 synch_monitor->avg_synch_fix_counter = -1; 00302 if (reset_compensation == true) { 00303 synch_monitor->drift_compensation = 0; 00304 } 00305 synch_monitor->channel_counter = 0; 00306 return 0; 00307 } 00308 return -1; 00309 } 00310 00311 static int fhss_reset(fhss_structure_t *fhss_structure) 00312 { 00313 if (fhss_structure) { 00314 fhss_structure->platform_functions.fhss_timer_stop(fhss_structure->fhss_api); 00315 fhss_struct->synch_panid = 0xffff; 00316 fhss_beacon_periodic_stop(fhss_structure); 00317 fhss_struct->current_superframe = 0; 00318 fhss_struct->current_channel_index = 0; 00319 fhss_struct->channel_list_counter = 0; 00320 if (fhss_is_synch_root(fhss_structure) == false) { 00321 fhss_struct->own_hop = 0xff; 00322 } 00323 fhss_struct->tx_allowed = false; 00324 fhss_struct->synch_interval = (uint32_t) (fhss_struct->fhss_configuration.fhss_max_synch_interval/BEACON_INTERVAL_INIT_DIVIDER) * 1000; 00325 fhss_struct->rx_channel = 0; 00326 fhss_struct->beacons_received_timer = 0; 00327 memset(fhss_struct->synch_parent, 0xff, 8); 00328 fhss_struct->send_synch_info_on_next_broadcast_channel = false; 00329 memset(&fhss_struct->synch_configuration, 0, sizeof(fhss_synch_configuration_t)); 00330 fhss_struct->synch_infos_sent_counter = 0; 00331 fhss_struct->broadcast_start_superframe = 0; 00332 fhss_failed_list_free(fhss_structure); 00333 fhss_struct->fhss_state = FHSS_UNSYNCHRONIZED; 00334 return 0; 00335 } 00336 return -1; 00337 } 00338 00339 int fhss_down(fhss_structure_t *fhss_structure) 00340 { 00341 if (fhss_structure) { 00342 fhss_reset(fhss_structure); 00343 fhss_reset_synch_monitor(&fhss_struct->synch_monitor, false); 00344 fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->synch_monitor.drift_compensation); 00345 fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->synch_monitor.avg_synch_fix); 00346 fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->synch_interval / 1000); 00347 return 0; 00348 } 00349 return -1; 00350 } 00351 00352 00353 int8_t fhss_disable(fhss_structure_t *fhss_structure) 00354 { 00355 if (!fhss_structure) { 00356 return -1; 00357 } 00358 ns_dyn_mem_free(fhss_structure); 00359 fhss_structure = 0; 00360 fhss_struct = 0; 00361 return 0; 00362 } 00363 00364 void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)) 00365 { 00366 if (callback){ 00367 // Don't allow starting with zero slots 00368 if (time < fhss_structure->platform_functions.fhss_resolution_divider) { 00369 time = fhss_structure->platform_functions.fhss_resolution_divider; 00370 } 00371 fhss_structure->platform_functions.fhss_timer_start(time / fhss_structure->platform_functions.fhss_resolution_divider, callback, fhss_structure->fhss_api); 00372 } 00373 } 00374 00375 uint32_t fhss_get_remaining_time_to_next_superframe(const fhss_structure_t *fhss_structure) 00376 { 00377 const uint32_t slots = fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_structure->fhss_api); 00378 const uint32_t time = slots * fhss_structure->platform_functions.fhss_resolution_divider; 00379 return time; 00380 } 00381 00382 void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay) 00383 { 00384 int compensation = 0; 00385 fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); 00386 if (!fhss_structure) { 00387 return; 00388 } 00389 /* Drift compensation doesn't work with Linux platform */ 00390 #ifndef __linux__ 00391 // Drift compensation on first superframe 00392 if (fhss_structure->current_superframe == 0) { 00393 /* Idea is to compensate number of drift_compensation (microseconds) on each channel. 00394 * However, fhss_resolution_divider defines the minimum timer resolution. 00395 * E.g. if fhss_resolution_divider = 64, compensate (drift_compensation * 64) on each 64th channel. 00396 */ 00397 if (++fhss_structure->synch_monitor.channel_counter == fhss_structure->platform_functions.fhss_resolution_divider) { 00398 compensation = fhss_structure->synch_monitor.drift_compensation; 00399 fhss_structure->synch_monitor.channel_counter = 0; 00400 } 00401 } 00402 #endif //__linux__ 00403 // Restart timer asap to minimize the effect of dynamic execution time of 00404 // the rest of function. 00405 fhss_start_timer(fhss_structure, (fhss_structure->synch_configuration.fhss_superframe_length) - (delay * fhss_structure->platform_functions.fhss_resolution_divider) + (compensation * fhss_structure->platform_functions.fhss_resolution_divider), fhss_superframe_handler); 00406 00407 // check, if the current frame was the last one 00408 if (fhss_structure->current_superframe >= (fhss_structure->synch_configuration.fhss_number_of_superframes - 1)) { 00409 00410 // last superframe has passed, change channel 00411 fhss_structure->current_superframe = 0; 00412 fhss_structure->current_channel_index++; 00413 if (fhss_structure->current_channel_index >= fhss_structure->number_of_channels) { 00414 fhss_structure->synch_infos_sent_counter = 0; 00415 fhss_structure->current_channel_index = 0; 00416 fhss_structure->channel_list_counter++; 00417 // Repeated cycle is started from beginning, reset counter. Don't let the channel_list_counter overflow. 00418 if (fhss_structure->channel_list_counter >= ((uint16_t) fhss_structure->number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) { 00419 fhss_structure->channel_list_counter = 0; 00420 } 00421 // Hop 0 don't have parent 00422 if (fhss_is_synch_root(fhss_structure) == false) { 00423 fhss_trig_event(fhss_structure, FHSS_COMPARE_SYNCH_PARENT); 00424 } 00425 fhss_trig_event(fhss_structure, FHSS_UPDATE_SYNCH_INFO_STORAGE); 00426 } 00427 fhss_update_channel(fhss_structure); 00428 } else { 00429 // bump up the superframe counter 00430 fhss_structure->current_superframe++; 00431 00432 #ifdef FHSS_MASSIVE_TRACE 00433 tr_debug("%"PRIu32": handler, super: %"PRIu8, 00434 fhss_structure->fhss_api->read_timestamp(fhss_structure->fhss_api), fhss_structure->current_superframe); 00435 #endif 00436 } 00437 if ((fhss_structure->send_synch_info_on_next_broadcast_channel == true) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) { 00438 /* Randomize sending superframe of synchronization frame: 00439 * on first superframe probability is 1/number of superframes 00440 * on second superframe probability is 1/(number of superframes-1) 00441 * on third superframe probability is 1/(number of superframes-2) 00442 * on last superframe probability is 1/1 00443 */ 00444 if (randLIB_get_random_in_range(1, fhss_structure->synch_configuration.fhss_number_of_superframes - fhss_structure->current_superframe) == 1) { 00445 fhss_structure->send_synch_info_on_next_broadcast_channel = false; 00446 fhss_structure->synch_infos_sent_counter++; 00447 fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_FRAME); 00448 } 00449 } 00450 fhss_update_txrx_slots(fhss_structure); 00451 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); 00452 if ((fhss_structure->tx_allowed == true || fhss_is_current_channel_broadcast(fhss_structure) == true) && queue_size) { 00453 /* Start timer with random timeout to trigger TX queue poll event. 00454 * Max random is half of the superframe length. Event timer resolution is 50us. 00455 * Divide Max random with TX queue size to transmit faster when TX queue is growing 00456 */ 00457 uint16_t max_random = ((fhss_structure->synch_configuration.fhss_superframe_length / 2) / 50) / queue_size; 00458 eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(1, max_random)); 00459 } 00460 if (fhss_structure->fhss_timeout) { 00461 fhss_structure->fhss_timer += fhss_structure->synch_configuration.fhss_superframe_length; 00462 if (fhss_structure->fhss_timer >= fhss_structure->fhss_timeout) { 00463 fhss_trig_event(fhss_structure, FHSS_TIMER_EVENT); 00464 fhss_structure->fhss_timeout = 0; 00465 fhss_structure->fhss_timer = 0; 00466 } 00467 } 00468 } 00469 00470 int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time) 00471 { 00472 if (!fhss_structure) { 00473 return -1; 00474 } 00475 fhss_structure->fhss_timeout = time; 00476 fhss_structure->fhss_timer = 0; 00477 return 0; 00478 } 00479 00480 int fhss_timeout_stop(fhss_structure_t *fhss_structure) 00481 { 00482 if (!fhss_structure) { 00483 return -1; 00484 } 00485 fhss_structure->fhss_timeout = 0; 00486 fhss_structure->fhss_timer = 0; 00487 return 0; 00488 } 00489 00490 int fhss_update_txrx_slots(fhss_structure_t *fhss_structure) 00491 { 00492 uint8_t cur_superframe = fhss_structure->current_superframe; 00493 uint8_t number_of_tx_slots = fhss_structure->synch_configuration.fhss_number_of_tx_slots; 00494 uint8_t number_of_superframes = fhss_structure->synch_configuration.fhss_number_of_superframes; 00495 uint8_t tx_slot_length = ((number_of_superframes / 2) / number_of_tx_slots); 00496 uint8_t tx_slot_up_limit = tx_slot_length; 00497 bool tx_allowed = false; 00498 00499 /* FHSS Phase 1 solution. This will be updated in future since we need to be able to communicate with nodes on same hop distance. 00500 * 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. 00501 * 00502 * If number of superframes is 16 and number of TX slots is 2, this will be generated (Note: hop 0 is always border router): 00503 * 00504 * Hop Superframe 00505 * 0 |TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX| 00506 * 1 |RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX| 00507 * 2 |TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX| 00508 * 3 |RX|RX|RX|RX|TX|TX|TX|TX|RX|RX|RX|RX|TX|TX|TX|TX| 00509 * 00510 */ 00511 00512 if ((fhss_structure->own_hop % 2)) { 00513 tx_slot_up_limit += tx_slot_length; 00514 } 00515 while(number_of_tx_slots--) 00516 { 00517 if ((cur_superframe >= (tx_slot_up_limit - tx_slot_length)) && (cur_superframe < tx_slot_up_limit)) { 00518 tx_allowed = true; 00519 break; 00520 } else { 00521 tx_slot_up_limit += (tx_slot_length * 2); 00522 } 00523 } 00524 fhss_structure->tx_allowed = tx_allowed; 00525 return 0; 00526 } 00527 00528 static int fhss_update_drift_compensation(fhss_structure_t *fhss_structure) 00529 { 00530 int retval = 0; 00531 int channels_per_synch_period; 00532 uint16_t bc_density; 00533 uint16_t channel_dwell_time; 00534 uint32_t synch_period; 00535 00536 if (!fhss_structure) { 00537 return 0; 00538 } 00539 bc_density = (fhss_structure->number_of_channels / fhss_structure->synch_configuration.fhss_number_of_bc_channels); 00540 channel_dwell_time = ((uint32_t)fhss_structure->synch_configuration.fhss_superframe_length * fhss_structure->synch_configuration.fhss_number_of_superframes) / 1000; 00541 // Calculate last synchronisation period 00542 if (fhss_structure->synch_interval != ((uint32_t)fhss_structure->fhss_configuration.fhss_max_synch_interval * 1000)) { 00543 // Last period was half of the current started period and max random period is shorter 00544 synch_period = (fhss_structure->synch_interval / 2) + (bc_density * channel_dwell_time) * (fhss_structure->synch_configuration.fhss_number_of_bc_channels / 2); 00545 } else { 00546 synch_period = fhss_structure->synch_interval + (bc_density * channel_dwell_time) * fhss_structure->synch_configuration.fhss_number_of_bc_channels; 00547 } 00548 00549 // E.g. 240000ms / (50000us * 8) = 600 channels per fhss_beacon_send_interval 00550 channels_per_synch_period = (synch_period * 1000) / ((uint32_t)fhss_structure->synch_configuration.fhss_superframe_length * fhss_structure->synch_configuration.fhss_number_of_superframes); 00551 // Calculate compensation value: how much to compensate on each channel. E.g. 6000us / 600channels = 10us/channel 00552 fhss_structure->synch_monitor.drift_compensation += (fhss_structure->synch_monitor.avg_synch_fix / channels_per_synch_period); 00553 fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->synch_monitor.drift_compensation); 00554 if ((fhss_structure->synch_monitor.avg_synch_fix > FHSS_SYNCH_DRIFT_TOO_HIGH_LIMIT) || (fhss_structure->synch_monitor.avg_synch_fix < -FHSS_SYNCH_DRIFT_TOO_HIGH_LIMIT)) { 00555 // Indicates that more frequent synchronization is needed 00556 retval = -1; 00557 } 00558 return retval; 00559 } 00560 00561 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) 00562 { 00563 fhss_synch_configuration_t *configuration = &fhss_structure->synch_configuration; 00564 int super_frame_changed = payload->current_superframe - superframe_own; 00565 int retval = 0; 00566 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)) { 00567 /* Our superframe has changed before parent superframe -> we are running too fast 00568 * Own channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00569 * Parent channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00570 * Time: -----------------------------------> 00571 */ 00572 if (super_frame_changed > 0) { 00573 super_frame_changed = (superframe_own + payload->number_of_superframes_per_channel) - payload->current_superframe; 00574 } 00575 } else { 00576 /* Parent superframe has changed before our superframe -> we are running too slow 00577 * Own channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00578 * Parent channel: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 00579 * Time: -----------------------------------> 00580 */ 00581 if (super_frame_changed < 0) { 00582 super_frame_changed = (payload->current_superframe + payload->number_of_superframes_per_channel) - superframe_own; 00583 } 00584 } 00585 00586 /* If superframe changed during synchronization but remaining time to next superframe is high, it is likely that 00587 * superframe change is not valid anymore. Don't use this Beacon for syncronization monitoring. 00588 */ 00589 if ((configuration->fhss_superframe_length - remaining_time_own) > CLOSE_TO_SUPERFRAME_LENGTH) { 00590 remaining_time_own += (int32_t) configuration->fhss_superframe_length * super_frame_changed; 00591 00592 int32_t prev_synch_fix = (time_to_next_superframe - remaining_time_own); 00593 // After network scan counter was initialized to -1 to drop this fix from monitoring 00594 if (fhss_structure->synch_monitor.avg_synch_fix_counter >= 0) { 00595 fhss_structure->synch_monitor.avg_synch_fix += prev_synch_fix; 00596 } 00597 fhss_structure->synch_monitor.avg_synch_fix_counter++; 00598 if (fhss_structure->synch_monitor.avg_synch_fix_counter == SYNCH_MONITOR_AVG_SAMPLES) { 00599 fhss_structure->synch_monitor.avg_synch_fix /= SYNCH_MONITOR_AVG_SAMPLES; 00600 fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->synch_monitor.avg_synch_fix); 00601 retval = fhss_update_drift_compensation(fhss_structure); 00602 fhss_structure->synch_monitor.avg_synch_fix_counter = 0; 00603 fhss_structure->synch_monitor.avg_synch_fix = 0; 00604 } 00605 } 00606 return retval; 00607 } 00608 00609 int fhss_sync_with_beacon(fhss_structure_t *fhss_structure, 00610 const fhss_synchronization_beacon_payload_s *payload) 00611 { 00612 int ret_val = -1; 00613 int32_t remaining_time_own; 00614 uint8_t superframe_own; 00615 00616 if (fhss_structure) { 00617 // Do not allow synchronising devices above 253 hops. 00618 if (payload->hop_count > 253) { 00619 return 0; 00620 } 00621 // To make synchronization monitoring more effective, drop extra Beacons. 00622 if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED && (fhss_is_current_channel_broadcast(fhss_structure) == false || (fhss_structure->beacon_received_on_this_bc_channel == true))) { 00623 return 0; 00624 } 00625 00626 fhss_synch_configuration_t *configuration = &fhss_structure->synch_configuration; 00627 fhss_structure->beacon_received_on_this_bc_channel = true; 00628 00629 superframe_own = fhss_structure->current_superframe; 00630 fhss_structure->current_superframe = payload->current_superframe; 00631 // Clone the static config values from parent which has the authority. 00632 configuration->fhss_number_of_bc_channels = payload->number_of_broadcast_channels; 00633 configuration->fhss_number_of_tx_slots = payload->number_of_tx_slots; 00634 configuration->fhss_superframe_length = payload->superframe_length; 00635 configuration->fhss_number_of_superframes = payload->number_of_superframes_per_channel; 00636 // todo: 00637 // * payload->time_since_last_beacon 00638 uint8_t own_hop_tmp = fhss_structure->own_hop; 00639 if (fhss_is_synch_root(fhss_structure) == false) { 00640 // my own hop count is one more than the parent's 00641 fhss_structure->own_hop = payload->hop_count + 1; 00642 } 00643 fhss_stats_update(fhss_structure, STATS_FHSS_HOP_COUNT, fhss_structure->own_hop); 00644 fhss_structure->channel_list_counter = payload->channel_list_counter; 00645 fhss_structure->current_channel_index = payload->channel_index; 00646 uint8_t mac_address[8]; 00647 fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); 00648 00649 fhss_structure->uc_channel_index = fhss_calculate_uc_index(fhss_structure->current_channel_index, fhss_structure->number_of_channels, 00650 payload->number_of_broadcast_channels) + fhss_get_offset(fhss_structure, mac_address); 00651 00652 // If current channel is not broadcast, fhss_update_channel will increase UC channel index, otherwise do it here 00653 if (fhss_is_current_channel_broadcast(fhss_structure) == true || (fhss_structure->fhss_state == FHSS_SYNCHRONIZED)) { 00654 fhss_structure->uc_channel_index += 1; 00655 } 00656 if (fhss_structure->uc_channel_index >= (fhss_structure->number_of_channels - payload->number_of_broadcast_channels)) { 00657 fhss_structure->uc_channel_index -= (fhss_structure->number_of_channels - payload->number_of_broadcast_channels); 00658 } 00659 00660 fhss_structure->platform_functions.fhss_timer_stop(fhss_structure->fhss_api); 00661 // start timer to elapse at approximately same time as the parent will. 00662 const int32_t time_to_next_superframe = payload->remaining_slots; 00663 remaining_time_own = fhss_get_remaining_time_to_next_superframe(fhss_structure); 00664 fhss_start_timer(fhss_structure, time_to_next_superframe, fhss_superframe_handler); 00665 // Reset beacon received timer when FHSS synchronization is updated 00666 fhss_structure->beacons_received_timer = 0; 00667 uint16_t bc_density = (fhss_structure->number_of_channels / fhss_structure->synch_configuration.fhss_number_of_bc_channels); 00668 uint8_t fhss_number_of_bc_channels = fhss_structure->synch_configuration.fhss_number_of_bc_channels; 00669 uint16_t channel_dwell_time = ((uint32_t)fhss_structure->synch_configuration.fhss_superframe_length * fhss_structure->synch_configuration.fhss_number_of_superframes) / 1000; 00670 00671 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00672 fhss_structure->fhss_state = FHSS_SYNCHRONIZED; 00673 fhss_update_channel(fhss_structure); 00674 } 00675 if (fhss_is_synch_root(fhss_structure) == false) { 00676 // Initially synch drift might be massive. Request first few Beacons more frequently until compensation starts fixing the error. 00677 uint32_t beacon_interval_random; 00678 00679 if (fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { 00680 if (fhss_update_synch_monitor(fhss_structure, payload, superframe_own, remaining_time_own, time_to_next_superframe)) { 00681 fhss_structure->synch_interval = (uint32_t) (fhss_structure->fhss_configuration.fhss_max_synch_interval/BEACON_INTERVAL_INIT_DIVIDER) * 1000; 00682 } 00683 } 00684 00685 if (fhss_structure->synch_interval != ((uint32_t)fhss_structure->fhss_configuration.fhss_max_synch_interval * 1000)) { 00686 fhss_structure->synch_interval *= 2; 00687 if (fhss_structure->synch_interval > ((uint32_t)fhss_structure->fhss_configuration.fhss_max_synch_interval * 1000)) { 00688 fhss_structure->synch_interval = ((uint32_t)fhss_structure->fhss_configuration.fhss_max_synch_interval * 1000); 00689 } 00690 beacon_interval_random = (bc_density * channel_dwell_time) * randLIB_get_random_in_range(0, fhss_number_of_bc_channels/2); 00691 } else { 00692 beacon_interval_random = (bc_density * channel_dwell_time) * randLIB_get_random_in_range(0, fhss_number_of_bc_channels); 00693 } 00694 fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->synch_interval / 1000); 00695 fhss_beacon_periodic_start(fhss_structure, fhss_structure->synch_interval + beacon_interval_random); 00696 00697 #ifdef FHSS_MASSIVE_TRACE 00698 tr_debug("start timer, time now: %"PRIu32", sfr: %"PRIu8", ch-ind: %"PRIu8", time after: %"PRIu32, 00699 fhss_structure->fhss_api->read_timestamp(fhss_structure->fhss_api), fhss_structure->current_superframe, 00700 payload->channel_index, time_to_next_superframe); 00701 #endif 00702 } 00703 // Our hop has changed, needs to inform possible children by sending Beacon 00704 if ((own_hop_tmp != 0) && (own_hop_tmp != fhss_structure->own_hop)) { 00705 fhss_structure->send_synch_info_on_next_broadcast_channel = true; 00706 } 00707 ret_val = 0; 00708 } 00709 return ret_val; 00710 } 00711 00712 static uint32_t fhss_get_remaining_tx_time(fhss_structure_t *fhss_structure) 00713 { 00714 /* To get the remaining TX time, following calculation is performed 00715 * 00716 * rem. time(Y) 00717 * |----------------| 00718 *...| TX | TX | RX | RX |... 00719 *...| SF n | SF n+1 | SF n+2 | SF n+3 |... 00720 * 00721 * Y = remaining time of SF(n) + length of SF(n+1) 00722 * 00723 */ 00724 00725 uint32_t remaining_tx_time = 0; 00726 00727 if (fhss_structure) { 00728 uint8_t cur_superframe = fhss_structure->current_superframe; 00729 uint8_t number_of_tx_slots = fhss_structure->synch_configuration.fhss_number_of_tx_slots; 00730 uint8_t number_of_superframes = fhss_structure->synch_configuration.fhss_number_of_superframes; 00731 uint8_t tx_slot_length = ((number_of_superframes / 2) / number_of_tx_slots); 00732 uint8_t tx_slot_up_limit = tx_slot_length; 00733 uint16_t superframe_length = fhss_structure->synch_configuration.fhss_superframe_length; 00734 00735 if ((fhss_structure->own_hop % 2)) { 00736 tx_slot_up_limit += tx_slot_length; 00737 } 00738 while(number_of_tx_slots--) 00739 { 00740 if ((cur_superframe >= (tx_slot_up_limit - tx_slot_length)) && (cur_superframe < tx_slot_up_limit)) { 00741 remaining_tx_time = ((uint32_t)((tx_slot_up_limit - 1) - cur_superframe) * superframe_length) + fhss_get_remaining_time_to_next_superframe(fhss_structure); 00742 break; 00743 } else { 00744 tx_slot_up_limit += (tx_slot_length * 2); 00745 } 00746 } 00747 } 00748 return remaining_tx_time; 00749 } 00750 00751 uint32_t fhss_get_tx_time(fhss_structure_t *fhss_structure, uint16_t bytes_to_send, uint8_t phy_header_length, uint8_t phy_tail_length) 00752 { 00753 return ((1000000 / (fhss_structure->datarate / 8)) * (bytes_to_send + phy_header_length + phy_tail_length)); 00754 } 00755 00756 // CCA adds extra 2ms with FHSS 00757 #define CCA_FHSS_PERIOD 2000 00758 // Ack frame length 00759 #define ACK_LENGTH 5 00760 00761 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) 00762 { 00763 bool retval = false; 00764 uint32_t remaining_tx_time; 00765 uint32_t needed_tx_time; 00766 uint32_t tx_processing_delay; 00767 uint32_t ack_processing_delay; 00768 00769 if (!fhss_structure) { 00770 return retval; 00771 } 00772 00773 // Don't care when FHSS is unsynchronized 00774 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00775 retval = true; 00776 } else { 00777 tx_processing_delay = fhss_structure->fhss_configuration.fhss_tuning_parameters.tx_processing_delay; 00778 ack_processing_delay = fhss_structure->fhss_configuration.fhss_tuning_parameters.ack_processing_delay; 00779 // Calculate needed TX time (us): CCA static period + TX processing delays + transmission time + Ack processing delays + Ack transmission time 00780 needed_tx_time = CCA_FHSS_PERIOD + tx_processing_delay + fhss_get_tx_time(fhss_structure, tx_length, phy_header_length, phy_tail_length) 00781 + ack_processing_delay + fhss_get_tx_time(fhss_structure, ACK_LENGTH, phy_header_length, phy_tail_length); 00782 remaining_tx_time = fhss_get_remaining_tx_time(fhss_structure); 00783 if(needed_tx_time <= remaining_tx_time) { 00784 retval = true; 00785 } 00786 } 00787 return retval; 00788 } 00789 00790 int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure) 00791 { 00792 uint8_t parent_address[8]; 00793 00794 if (!fhss_get_parent_address(fhss_structure, parent_address)) { 00795 memcpy(fhss_structure->synch_parent, parent_address, 8); 00796 return 0; 00797 } 00798 return -1; 00799 } 00800 00801 void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type) 00802 { 00803 if (fhss_read_active_event(fhss_structure, event_type) == true) { 00804 return; 00805 } 00806 arm_event_s event; 00807 event.receiver = fhss_structure->beacon_tasklet_id; 00808 event.sender = 0; 00809 event.event_type = event_type; 00810 event.event_id = 0; 00811 event.data_ptr = fhss_structure; 00812 event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; 00813 event.event_data = 0; 00814 if (eventOS_event_send(&event) != 0) { 00815 tr_error("Event trigger failed: eventOS_event_send() failed"); 00816 } else { 00817 fhss_set_active_event(fhss_structure, event_type); 00818 } 00819 } 00820 00821 int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr) 00822 { 00823 int ret_val = -1; 00824 if (!fhss_structure || !p_addr) { 00825 return -1; 00826 } 00827 00828 ret_val = fhss_structure->callbacks.read_coord_mac_address(fhss_structure->fhss_api, p_addr); 00829 00830 if (ret_val) { 00831 // Use default synchronization parent when RPL parent not found 00832 memcpy(p_addr, fhss_structure->synch_parent, 8); 00833 ret_val = 0; 00834 } 00835 return ret_val; 00836 } 00837 00838 int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr) 00839 { 00840 int ret_val = -1; 00841 if (!fhss_structure || !source_addr) { 00842 return ret_val; 00843 } 00844 uint8_t parent_address[8]; 00845 00846 if (fhss_is_synch_root(fhss_structure) == false) { 00847 if (!fhss_get_parent_address(fhss_structure, parent_address)) { 00848 ret_val = memcmp(source_addr, parent_address, 8); 00849 } 00850 } 00851 return ret_val; 00852 } 00853 00854 static void fhss_update_channel(fhss_structure_t *fhss_structure) 00855 { 00856 // If channel is broadcast channel (true), send event 00857 if (fhss_change_to_next_channel(fhss_structure) == true) { 00858 // Only if device is border router 00859 if (fhss_structure->own_hop == 0) { 00860 fhss_trig_event(fhss_structure, FHSS_BROADCAST_CHANNEL); 00861 } 00862 } 00863 } 00864 00865 static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j) 00866 { 00867 if (i < j) { 00868 uint_fast8_t t = j; j = (uint8_t) i; i = t; 00869 } 00870 for(uint_fast8_t k=2; k<=j; k++) { 00871 if (i % k == 0 && j % k == 0) { 00872 return true; 00873 } 00874 } 00875 return false; 00876 } 00877 00878 00879 static int fhss_generate_scramble_table(fhss_structure_t *fhss_structure) 00880 { 00881 uint8_t j = 2; 00882 // Generate indexes to extend the channel sequence. Generated indexes cannot have common divisors with value number_of_channels. 00883 for(int i=0; i<MAX_SCRAMBLE_TABLE_INDEXES;) 00884 { 00885 // Common divisors are skipped 00886 if (fhss_is_there_common_divisor(fhss_structure->number_of_channels, j) == false) { 00887 fhss_structure->fhss_scramble_table[i] = j; 00888 i++; 00889 } 00890 j++; 00891 } 00892 return 0; 00893 } 00894 00895 static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) 00896 { 00897 (void) slots; 00898 fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); 00899 if (fhss_structure) { 00900 fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); 00901 } 00902 } 00903 00904 fhss_beacon_info_t *fhss_get_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id) 00905 { 00906 fhss_beacon_info_t *beacon_info; 00907 beacon_info = fhss_structure->fhss_beacon_info_store; 00908 while (beacon_info) { 00909 if (beacon_info->pan_id == pan_id) { 00910 break; 00911 } 00912 beacon_info = beacon_info->next; 00913 } 00914 return beacon_info; 00915 } 00916 00917 static void fhss_store_beacon_info(fhss_structure_t *fhss_structure, fhss_beacon_info_t *beacon_info) 00918 { 00919 fhss_beacon_info_t *beacon_info_cur; 00920 beacon_info->next = NULL; 00921 if (!fhss_structure->fhss_beacon_info_store) { 00922 fhss_structure->fhss_beacon_info_store = beacon_info; 00923 return; 00924 } 00925 beacon_info_cur = fhss_structure->fhss_beacon_info_store; 00926 while (beacon_info_cur->next != NULL) { 00927 beacon_info_cur = beacon_info_cur->next; 00928 } 00929 beacon_info_cur->next = beacon_info; 00930 } 00931 00932 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) 00933 { 00934 beacon_info->pan_id = pan_id; 00935 memcpy(beacon_info->source_address, source_address, 8); 00936 beacon_info->timestamp = timestamp; 00937 memcpy(beacon_info->synch_info, synch_info, sizeof(beacon_info->synch_info)); 00938 } 00939 00940 static fhss_beacon_info_t *fhss_create_beacon_info(fhss_structure_t *fhss_structure) 00941 { 00942 fhss_beacon_info_t *beacon_info = ns_dyn_mem_temporary_alloc(sizeof(fhss_beacon_info_t)); 00943 if (!beacon_info) { 00944 return NULL; 00945 } 00946 fhss_store_beacon_info(fhss_structure, beacon_info); 00947 return beacon_info; 00948 } 00949 00950 static int fhss_remove_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id) 00951 { 00952 if (!fhss_structure || !fhss_structure->fhss_beacon_info_store) { 00953 return -1; 00954 } 00955 00956 if (fhss_structure->fhss_beacon_info_store->pan_id == pan_id) { 00957 fhss_beacon_info_t *next = fhss_structure->fhss_beacon_info_store->next; 00958 ns_dyn_mem_free(fhss_structure->fhss_beacon_info_store); 00959 fhss_structure->fhss_beacon_info_store = next; 00960 return 0; 00961 } 00962 00963 fhss_beacon_info_t *removed_beacon_info = fhss_structure->fhss_beacon_info_store->next; 00964 fhss_beacon_info_t *prev_beacon_info = fhss_structure->fhss_beacon_info_store; 00965 00966 while (removed_beacon_info) { 00967 if (removed_beacon_info->pan_id == pan_id) { 00968 fhss_beacon_info_t *next = removed_beacon_info->next; 00969 ns_dyn_mem_free(removed_beacon_info); 00970 prev_beacon_info->next = next; 00971 return 0; 00972 } 00973 prev_beacon_info = removed_beacon_info; 00974 removed_beacon_info = removed_beacon_info->next; 00975 } 00976 return -1; 00977 } 00978 00979 int fhss_flush_beacon_info_storage(fhss_structure_t *fhss_structure) 00980 { 00981 if (!fhss_structure) { 00982 return -1; 00983 } 00984 fhss_beacon_info_t *beacon_info = fhss_structure->fhss_beacon_info_store; 00985 while (beacon_info) { 00986 fhss_beacon_info_t *next = beacon_info->next; 00987 ns_dyn_mem_free(beacon_info); 00988 beacon_info = next; 00989 } 00990 fhss_structure->fhss_beacon_info_store = NULL; 00991 return 0; 00992 } 00993 00994 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) 00995 { 00996 if (!fhss_structure || !source_address || !synch_info) { 00997 return -1; 00998 } 00999 fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); 01000 if (!beacon_info) { 01001 beacon_info = fhss_create_beacon_info(fhss_structure); 01002 } 01003 if (!beacon_info) { 01004 tr_error("Beacon data not allocated"); 01005 return -2; 01006 } 01007 fhss_write_beacon_info(beacon_info, pan_id, source_address, timestamp, synch_info); 01008 return 0; 01009 } 01010 01011 void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, uint32_t timestamp) 01012 { 01013 fhss_beacon_info_t *beacon_info; 01014 beacon_info = fhss_structure->fhss_beacon_info_store; 01015 while (beacon_info) { 01016 uint32_t time_since_added = timestamp - beacon_info->timestamp; 01017 // timestamp is microseconds, lifetime is seconds 01018 if (time_since_added >= ((uint32_t)BEACON_INFO_LIFETIME * 1000000)) { 01019 if (fhss_remove_beacon_info(fhss_structure, beacon_info->pan_id) == 0) { 01020 return; 01021 } 01022 } 01023 beacon_info = beacon_info->next; 01024 } 01025 } 01026 01027 fhss_failed_tx_t *fhss_failed_handle_find(fhss_structure_t *fhss_structure, uint8_t handle) 01028 { 01029 ns_list_foreach(fhss_failed_tx_t, cur, &fhss_structure->fhss_failed_tx_list) { 01030 if (cur->handle == handle) { 01031 return cur; 01032 } 01033 } 01034 return NULL; 01035 } 01036 01037 int fhss_failed_handle_add(fhss_structure_t *fhss_structure, uint8_t handle) 01038 { 01039 fhss_failed_tx_t *failed_tx = ns_dyn_mem_alloc(sizeof(fhss_failed_tx_t)); 01040 if (!failed_tx) { 01041 return -2; 01042 } 01043 failed_tx->bad_channel = fhss_structure->rx_channel; 01044 failed_tx->retries_done = 0; 01045 failed_tx->handle = handle; 01046 ns_list_add_to_end(&fhss_structure->fhss_failed_tx_list, failed_tx); 01047 return 0; 01048 } 01049 01050 int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle) 01051 { 01052 fhss_failed_tx_t *failed_tx = fhss_failed_handle_find(fhss_structure, handle); 01053 if (!failed_tx) { 01054 return -1; 01055 } 01056 ns_list_remove(&fhss_structure->fhss_failed_tx_list, failed_tx); 01057 ns_dyn_mem_free(failed_tx); // Free entry 01058 return 0; 01059 } 01060 01061 static void fhss_failed_list_free(fhss_structure_t *fhss_structure) 01062 { 01063 for (uint16_t i = 0; i<256; i++) { 01064 fhss_failed_handle_remove(fhss_structure, i); 01065 } 01066 }
Generated on Tue Jul 12 2022 12:21:51 by
