4242void (* fhss_uc_switch )(void ) = NULL ;
4343void (* fhss_bc_switch )(void ) = NULL ;
4444#endif /*FHSS_CHANNEL_DEBUG_CBS*/
45-
45+ // Seconds to milliseconds
46+ #define S_TO_MS (x ) (((uint32_t)x)*1000)
47+ // Milliseconds to seconds
48+ #define MS_TO_S (x ) divide_integer(x, 1000)
49+ // Seconds to microseconds
50+ #define S_TO_US (x ) (((uint32_t)x)*1000000)
51+ // Microseconds to seconds
52+ #define US_TO_S (x ) divide_integer(x, 1000000)
53+ // Milliseconds to microseconds
54+ #define MS_TO_US (x ) (((uint32_t)x)*1000)
55+ // Microseconds to milliseconds
56+ #define US_TO_MS (x ) divide_integer(x, 1000)
4657#define DEF_2E24 0x1000000
4758#define IE_HEADER_LENGTH_MASK 0x007f
4859#define IE_HEADER_ID_MASK 0x7f80
@@ -71,6 +82,16 @@ static uint32_t divide_integer(uint32_t dividend, uint32_t divisor)
7182 return (dividend + divisor /2 ) / divisor ;
7283}
7384
85+ static uint32_t get_remaining_slots_us (fhss_structure_t * fhss_structure , void (* callback )(const fhss_api_t * api , uint16_t ), uint32_t max_timeout_us )
86+ {
87+ uint32_t remaining_time_us = fhss_structure -> platform_functions .fhss_get_remaining_slots (callback , fhss_structure -> fhss_api );
88+ // When remaining time goes negative, use 0.
89+ if (remaining_time_us > max_timeout_us ) {
90+ remaining_time_us = 0 ;
91+ }
92+ return remaining_time_us ;
93+ }
94+
7495fhss_structure_t * fhss_ws_enable (fhss_api_t * fhss_api , const fhss_ws_configuration_t * fhss_configuration , const fhss_timer_t * fhss_timer )
7596{
7697 if (!fhss_api || !fhss_configuration || !fhss_timer ) {
@@ -156,7 +177,7 @@ static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure)
156177 }
157178 }
158179#ifdef FHSS_CHANNEL_DEBUG
159- tr_info ("%" PRIu32 " BC %u %u" , fhss_structure -> platform_functions . fhss_get_timestamp (fhss_structure -> fhss_api ), next_channel , fhss_structure -> ws -> bc_slot );
180+ tr_info ("%" PRIu32 " BC %u %u" , fhss_structure -> callbacks . read_timestamp (fhss_structure -> fhss_api ), next_channel , fhss_structure -> ws -> bc_slot );
160181#endif /*FHSS_CHANNEL_DEBUG*/
161182 return next_channel ;
162183}
@@ -175,7 +196,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
175196 return ;
176197 }
177198 if (fhss_structure -> ws -> is_on_bc_channel == false) {
178- fhss_start_timer (fhss_structure , fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval * 1000 - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
199+ fhss_start_timer (fhss_structure , MS_TO_US ( fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval ) - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
179200 fhss_structure -> ws -> is_on_bc_channel = true;
180201 next_channel = fhss_structure -> ws -> bc_channel = fhss_ws_calc_bc_channel (fhss_structure );
181202
@@ -184,12 +205,12 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
184205 * Max random is 1/10 of the channel dwell interval.
185206 * Event timer resolution is 50us.
186207 */
187- uint32_t bc_dwell_us = fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval * 1000 ;
208+ uint32_t bc_dwell_us = MS_TO_US ( fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval ) ;
188209 uint16_t bc_min_random = (bc_dwell_us / 50 ) / 50 ;
189210 uint16_t bc_max_random = (bc_dwell_us / 10 ) / 50 ;
190211 eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (bc_min_random , bc_max_random ));
191212 } else {
192- uint32_t timeout = (fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval - fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval ) * 1000 ;
213+ uint32_t timeout = MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval - fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval );
193214 fhss_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
194215 fhss_structure -> ws -> is_on_bc_channel = false;
195216 // Should return to own (unicast) listening channel after broadcast channel
@@ -199,7 +220,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
199220 * Max random is 1/10 of the TX slot length.
200221 * Event timer resolution is 50us.
201222 */
202- uint32_t txrx_slot_length_us = fhss_structure -> ws -> txrx_slot_length_ms * 1000 ;
223+ uint32_t txrx_slot_length_us = MS_TO_US ( fhss_structure -> ws -> txrx_slot_length_ms ) ;
203224 uint16_t uc_min_random = (txrx_slot_length_us / 30 ) / 50 ;
204225 uint16_t uc_max_random = (txrx_slot_length_us / 10 ) / 50 ;
205226 bool tx_allowed = fhss_ws_check_tx_allowed (fhss_structure );
@@ -210,7 +231,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
210231 eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (uc_min_random , uc_max_random ));
211232
212233#ifdef FHSS_CHANNEL_DEBUG
213- tr_info ("%" PRIu32 " UC %u" , fhss_structure -> platform_functions . fhss_get_timestamp (fhss_structure -> fhss_api ), fhss_structure -> rx_channel );
234+ tr_info ("%" PRIu32 " UC %u" , fhss_structure -> callbacks . read_timestamp (fhss_structure -> fhss_api ), fhss_structure -> rx_channel );
214235#endif /*FHSS_CHANNEL_DEBUG*/
215236 }
216237 fhss_structure -> callbacks .change_channel (fhss_structure -> fhss_api , next_channel );
@@ -246,8 +267,8 @@ static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
246267 queue_size = fhss_structure -> callbacks .read_tx_queue_size (fhss_structure -> fhss_api , true);
247268 } else {
248269 // On unicast, start timer to trigger polling event on next TX slot
249- uint32_t delay_between_tx_slots_us = fhss_structure -> ws -> txrx_slot_length_ms * 1000 * 2 ;
250- if (delay_between_tx_slots_us < fhss_structure -> platform_functions . fhss_get_remaining_slots ( fhss_broadcast_handler , fhss_structure -> fhss_api )) {
270+ uint32_t delay_between_tx_slots_us = MS_TO_US ( fhss_structure -> ws -> txrx_slot_length_ms ) * 2 ;
271+ if (delay_between_tx_slots_us < get_remaining_slots_us ( fhss_structure , fhss_broadcast_handler , MS_TO_US ( fhss_structure -> ws -> fhss_configuration . fhss_broadcast_interval ) )) {
251272 eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , delay_between_tx_slots_us /50 );
252273 }
253274 queue_size = fhss_structure -> callbacks .read_tx_queue_size (fhss_structure -> fhss_api , false);
@@ -265,16 +286,13 @@ static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_
265286 cur_slot = fhss_structure -> number_of_channels ;
266287 }
267288 cur_slot -- ;
268- uint32_t remaining_time = (fhss_structure -> platform_functions .fhss_get_remaining_slots (fhss_unicast_handler , fhss_structure -> fhss_api ) / 1000 );
269- if (remaining_time > dwell_time ) {
270- remaining_time = 0 ;
271- }
289+ uint32_t remaining_time_ms = US_TO_MS (get_remaining_slots_us (fhss_structure , fhss_unicast_handler , MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval )));
272290 uint32_t time_to_tx = 0 ;
273291 uint32_t cur_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
274292 if (cur_time < tx_time ) {
275- time_to_tx = (tx_time - cur_time ) / 1000 ;
293+ time_to_tx = US_TO_MS (tx_time - cur_time );
276294 }
277- uint64_t ms_since_seq_start = (cur_slot * dwell_time ) + (dwell_time - remaining_time ) + time_to_tx ;
295+ uint64_t ms_since_seq_start = (cur_slot * dwell_time ) + (dwell_time - remaining_time_ms ) + time_to_tx ;
278296 uint32_t seq_length = 0x10000 ;
279297 if (fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function == WS_TR51CF ) {
280298 ms_since_seq_start %= (dwell_time * fhss_structure -> number_of_channels );
@@ -287,17 +305,16 @@ static uint32_t fhss_ws_calculate_broadcast_interval_offset(fhss_structure_t *fh
287305{
288306 uint8_t dwell_time = fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval ;
289307 uint32_t broadcast_interval = fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval ;
290-
291- uint32_t remaining_time = divide_integer (fhss_structure -> platform_functions .fhss_get_remaining_slots (fhss_broadcast_handler , fhss_structure -> fhss_api ), 1000 );
308+ uint32_t remaining_time_ms = US_TO_MS (get_remaining_slots_us (fhss_structure , fhss_broadcast_handler , MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval )));
292309 if (fhss_structure -> ws -> is_on_bc_channel == true) {
293- remaining_time += (broadcast_interval - dwell_time );
310+ remaining_time_ms += (broadcast_interval - dwell_time );
294311 }
295312 uint32_t time_to_tx = 0 ;
296313 uint32_t cur_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
297314 if (cur_time < tx_time ) {
298- time_to_tx = divide_integer (tx_time - cur_time , 1000 );
315+ time_to_tx = US_TO_MS (tx_time - cur_time );
299316 }
300- return (broadcast_interval - remaining_time ) + time_to_tx ;
317+ return (broadcast_interval - remaining_time_ms ) + time_to_tx ;
301318}
302319
303320static uint16_t fhss_ws_calculate_destination_slot (fhss_ws_neighbor_timing_info_t * neighbor_timing_info , uint32_t tx_time )
@@ -310,12 +327,12 @@ static uint16_t fhss_ws_calculate_destination_slot(fhss_ws_neighbor_timing_info_
310327 seq_length = neighbor_timing_info -> uc_timing_info .unicast_number_of_channels ;
311328 }
312329 uint32_t dest_ms_since_seq_start = own_ceil ((float )((uint64_t )ufsi * seq_length * dwell_time ) / DEF_2E24 );
313- return (own_floor (((float )((tx_time - ufsi_timestamp )/ 1000 + dest_ms_since_seq_start ) / dwell_time )) % seq_length );
330+ return (own_floor (((float )(US_TO_MS (tx_time - ufsi_timestamp ) + dest_ms_since_seq_start ) / dwell_time )) % seq_length );
314331}
315332
316333static uint32_t fhss_ws_get_sf_timeout_callback (fhss_structure_t * fhss_structure )
317334{
318- return fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval * 1000 ;
335+ return MS_TO_US ( fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval ) ;
319336}
320337
321338static int16_t fhss_ws_synch_state_set_callback (const fhss_api_t * api , fhss_states fhss_state , uint16_t pan_id )
@@ -336,7 +353,7 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
336353 // Start unicast schedule
337354 if ((fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function != WS_FIXED_CHANNEL )) {
338355 fhss_ws_update_uc_channel_callback (fhss_structure );
339- fhss_start_timer (fhss_structure , fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval * 1000 , fhss_unicast_handler );
356+ fhss_start_timer (fhss_structure , MS_TO_US ( fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval ) , fhss_unicast_handler );
340357 fhss_structure -> ws -> unicast_timer_running = true;
341358 }
342359 }
@@ -374,7 +391,7 @@ static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure)
374391 return ;
375392 }
376393#ifdef FHSS_CHANNEL_DEBUG
377- tr_info ("%" PRIu32 " UC %u %u" , fhss_structure -> platform_functions . fhss_get_timestamp (fhss_structure -> fhss_api ), next_channel , fhss_structure -> ws -> uc_slot );
394+ tr_info ("%" PRIu32 " UC %u %u" , fhss_structure -> callbacks . read_timestamp (fhss_structure -> fhss_api ), next_channel , fhss_structure -> ws -> uc_slot );
378395#endif /*FHSS_CHANNEL_DEBUG*/
379396 fhss_structure -> callbacks .change_channel (fhss_structure -> fhss_api , next_channel );
380397#ifdef FHSS_CHANNEL_DEBUG_CBS
@@ -466,7 +483,8 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure)
466483 if (!number_of_tx_slots ) {
467484 return true;
468485 }
469- uint32_t remaining_time_ms = fhss_structure -> platform_functions .fhss_get_remaining_slots (fhss_broadcast_handler , fhss_structure -> fhss_api ) / 1000 ;
486+
487+ uint32_t remaining_time_ms = get_remaining_slots_us (fhss_structure , fhss_broadcast_handler , MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval )) / 1000 ;
470488 uint32_t tx_slot_begin = (fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval - fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval ) - (fhss_structure -> ws -> txrx_slot_length_ms * (fhss_structure -> own_hop & 1 ));
471489 uint32_t rx_slot_begin = tx_slot_begin - fhss_structure -> ws -> txrx_slot_length_ms ;
472490 uint8_t n_o_tx_slots = number_of_tx_slots ;
@@ -488,8 +506,8 @@ static bool fhss_ws_check_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_
488506 return true;
489507 }
490508 uint32_t tx_time = fhss_get_tx_time (fhss_structure , tx_length , phy_header_length , phy_tail_length );
491- uint32_t time_to_bc_channel = fhss_structure -> platform_functions . fhss_get_remaining_slots ( fhss_broadcast_handler , fhss_structure -> fhss_api );
492- if (tx_time > time_to_bc_channel ) {
509+ uint32_t time_to_bc_channel_us = get_remaining_slots_us ( fhss_structure , fhss_broadcast_handler , MS_TO_US ( fhss_structure -> ws -> fhss_configuration . fhss_broadcast_interval ) );
510+ if (tx_time > time_to_bc_channel_us ) {
493511 return false;
494512 }
495513 return true;
@@ -709,21 +727,23 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
709727 if (!bc_timing_info -> broadcast_interval || !bc_timing_info -> broadcast_dwell_interval ) {
710728 return -1 ;
711729 }
712- if (((( uint32_t ) fhss_structure -> ws -> min_synch_interval * 1000000 ) > (fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api ) - fhss_structure -> ws -> synchronization_time )) && !force_synch ) {
730+ if ((S_TO_US ( fhss_structure -> ws -> min_synch_interval ) > (fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api ) - fhss_structure -> ws -> synchronization_time )) && !force_synch ) {
713731 return 0 ;
714732 }
715- fhss_structure -> ws -> synchronization_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
716733 platform_enter_critical ();
734+ uint32_t prev_synchronization_time = fhss_structure -> ws -> synchronization_time ;
735+ fhss_structure -> ws -> synchronization_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
736+ uint32_t own_bc_interval_offset = fhss_ws_calculate_broadcast_interval_offset (fhss_structure , fhss_structure -> ws -> synchronization_time );
717737 fhss_stop_timer (fhss_structure , fhss_broadcast_handler );
718- uint32_t time_from_reception_ms = divide_integer (fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api ) - bc_timing_info -> bt_rx_timestamp , 1000 );
738+ uint32_t time_from_reception_ms = US_TO_MS (fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api ) - bc_timing_info -> bt_rx_timestamp );
719739 uint32_t true_bc_interval_offset = (bc_timing_info -> broadcast_interval_offset + time_from_reception_ms ) % bc_timing_info -> broadcast_interval ;
720740 if (true_bc_interval_offset >= bc_timing_info -> broadcast_dwell_interval ) {
721741 fhss_structure -> ws -> is_on_bc_channel = false;
722742 }
723- uint32_t timeout = (( bc_timing_info -> broadcast_interval - true_bc_interval_offset ) * 1000 );
743+ uint32_t timeout = MS_TO_US ( bc_timing_info -> broadcast_interval - true_bc_interval_offset );
724744
725745 if (fhss_structure -> ws -> is_on_bc_channel ) {
726- timeout -= (( bc_timing_info -> broadcast_interval - bc_timing_info -> broadcast_dwell_interval ) * 1000 );
746+ timeout -= MS_TO_US ( bc_timing_info -> broadcast_interval - bc_timing_info -> broadcast_dwell_interval );
727747 }
728748 fhss_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
729749 uint16_t slots_since_reception = (bc_timing_info -> broadcast_interval_offset + time_from_reception_ms ) / bc_timing_info -> broadcast_interval ;
@@ -738,6 +758,9 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
738758 platform_exit_critical ();
739759 //TODO: support multiple parents
740760 fhss_structure -> ws -> parent_bc_info = bc_timing_info ;
761+ if (prev_synchronization_time ) {
762+ tr_debug ("synch to parent: %s, drift: %ims in %u seconds" , trace_array (eui64 , 8 ), true_bc_interval_offset - own_bc_interval_offset , US_TO_S (fhss_structure -> ws -> synchronization_time - prev_synchronization_time ));
763+ }
741764 return 0 ;
742765}
743766
@@ -763,7 +786,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
763786 fhss_structure -> ws -> unicast_timer_running = false;
764787 }
765788 if ((fhss_structure -> ws -> unicast_timer_running == false) && (fhss_configuration -> ws_uc_channel_function != WS_FIXED_CHANNEL ) && fhss_configuration -> fhss_uc_dwell_interval ) {
766- fhss_start_timer (fhss_structure , fhss_configuration -> fhss_uc_dwell_interval * 1000 , fhss_unicast_handler );
789+ fhss_start_timer (fhss_structure , MS_TO_US ( fhss_configuration -> fhss_uc_dwell_interval ) , fhss_unicast_handler );
767790 fhss_structure -> ws -> unicast_timer_running = true;
768791 }
769792 fhss_structure -> ws -> fhss_configuration = * fhss_configuration ;
0 commit comments