@@ -54,6 +54,14 @@ void (*fhss_bc_switch)(void) = NULL;
5454#define MS_TO_US (x ) (((uint32_t)x)*1000)
5555// Microseconds to milliseconds
5656#define US_TO_MS (x ) divide_integer(x, 1000)
57+ // Milliseconds to nanoseconds
58+ #define MS_TO_NS (x ) (((uint32_t)x)*1000000)
59+ // Nanoseconds to milliseconds
60+ #define NS_TO_MS (x ) divide_integer(x, 1000000)
61+ // Microseconds to nanoseconds
62+ #define US_TO_NS (x ) (((uint32_t)x)*1000)
63+ // Nanoseconds to microseconds
64+ #define NS_TO_US (x ) divide_integer(x, 1000)
5765#define DEF_2E24 0x1000000
5866#define IE_HEADER_LENGTH_MASK 0x007f
5967#define IE_HEADER_ID_MASK 0x7f80
@@ -92,6 +100,15 @@ static uint32_t get_remaining_slots_us(fhss_structure_t *fhss_structure, void (*
92100 return remaining_time_us ;
93101}
94102
103+ void fhss_ws_start_timer (fhss_structure_t * fhss_structure , uint32_t time , void (* callback )(const fhss_api_t * fhss_api , uint16_t ))
104+ {
105+ // Number of millisecond slots in timeout(us)
106+ int32_t time_in_ms = divide_integer (time , 1000 );
107+ // Reduce the compensation (per millisecond) from timeout.
108+ time -= NS_TO_US (time_in_ms * fhss_structure -> ws -> drift_per_millisecond_ns );
109+ fhss_start_timer (fhss_structure , time , callback );
110+ }
111+
95112fhss_structure_t * fhss_ws_enable (fhss_api_t * fhss_api , const fhss_ws_configuration_t * fhss_configuration , const fhss_timer_t * fhss_timer )
96113{
97114 if (!fhss_api || !fhss_configuration || !fhss_timer ) {
@@ -196,7 +213,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
196213 return ;
197214 }
198215 if (fhss_structure -> ws -> is_on_bc_channel == false) {
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 );
216+ fhss_ws_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 );
200217 fhss_structure -> ws -> is_on_bc_channel = true;
201218 next_channel = fhss_structure -> ws -> bc_channel = fhss_ws_calc_bc_channel (fhss_structure );
202219
@@ -211,7 +228,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
211228 eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (bc_min_random , bc_max_random ));
212229 } else {
213230 uint32_t timeout = MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_broadcast_interval - fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval );
214- fhss_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
231+ fhss_ws_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
215232 fhss_structure -> ws -> is_on_bc_channel = false;
216233 // Should return to own (unicast) listening channel after broadcast channel
217234 next_channel = fhss_structure -> rx_channel ;
@@ -353,7 +370,7 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
353370 // Start unicast schedule
354371 if ((fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function != WS_FIXED_CHANNEL )) {
355372 fhss_ws_update_uc_channel_callback (fhss_structure );
356- fhss_start_timer (fhss_structure , MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval ), fhss_unicast_handler );
373+ fhss_ws_start_timer (fhss_structure , MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval ), fhss_unicast_handler );
357374 fhss_structure -> ws -> unicast_timer_running = true;
358375 }
359376 }
@@ -689,7 +706,7 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
689706 fhss_structure -> ws -> unicast_timer_running = false;
690707 return ;
691708 }
692- fhss_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_unicast_handler );
709+ fhss_ws_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_unicast_handler );
693710 fhss_structure -> ws -> unicast_timer_running = true;
694711 fhss_ws_update_uc_channel_callback (fhss_structure );
695712 // Unless we have broadcast schedule, we have to poll unicast queue when changing channel. This is randomized by the unicast schedule.
@@ -733,6 +750,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
733750 platform_enter_critical ();
734751 uint32_t prev_synchronization_time = fhss_structure -> ws -> synchronization_time ;
735752 fhss_structure -> ws -> synchronization_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
753+ uint32_t time_since_last_synch_us = fhss_structure -> ws -> synchronization_time - prev_synchronization_time ;
736754 uint32_t own_bc_interval_offset = fhss_ws_calculate_broadcast_interval_offset (fhss_structure , fhss_structure -> ws -> synchronization_time );
737755 fhss_stop_timer (fhss_structure , fhss_broadcast_handler );
738756 uint32_t time_from_reception_ms = US_TO_MS (fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api ) - bc_timing_info -> bt_rx_timestamp );
@@ -745,7 +763,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
745763 if (fhss_structure -> ws -> is_on_bc_channel ) {
746764 timeout -= MS_TO_US (bc_timing_info -> broadcast_interval - bc_timing_info -> broadcast_dwell_interval );
747765 }
748- fhss_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
766+ fhss_ws_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
749767 uint16_t slots_since_reception = (bc_timing_info -> broadcast_interval_offset + time_from_reception_ms ) / bc_timing_info -> broadcast_interval ;
750768 // TODO: Calculate drift error
751769 fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval = bc_timing_info -> broadcast_dwell_interval ;
@@ -759,7 +777,17 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
759777 //TODO: support multiple parents
760778 fhss_structure -> ws -> parent_bc_info = bc_timing_info ;
761779 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 ));
780+ if (SYNCH_COMPENSATION_MIN_INTERVAL <= US_TO_S (time_since_last_synch_us )) {
781+ // Compensate clock drift
782+ if (true_bc_interval_offset > own_bc_interval_offset ) {
783+ // Our clock runs too slow compared to parent, mark as positive drift.
784+ fhss_structure -> ws -> drift_per_millisecond_ns += divide_integer (MS_TO_NS (true_bc_interval_offset - own_bc_interval_offset ), US_TO_MS (time_since_last_synch_us ));
785+ } else {
786+ // Our clock runs too fast compared to parent, mark as negative drift.
787+ fhss_structure -> ws -> drift_per_millisecond_ns -= divide_integer (MS_TO_NS (own_bc_interval_offset - true_bc_interval_offset ), US_TO_MS (time_since_last_synch_us ));
788+ }
789+ }
790+ tr_debug ("synch to parent: %s, drift: %ims in %u seconds, compensation: %ins per ms" , trace_array (eui64 , 8 ), true_bc_interval_offset - own_bc_interval_offset , US_TO_S (time_since_last_synch_us ), fhss_structure -> ws -> drift_per_millisecond_ns );
763791 }
764792 return 0 ;
765793}
@@ -786,7 +814,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
786814 fhss_structure -> ws -> unicast_timer_running = false;
787815 }
788816 if ((fhss_structure -> ws -> unicast_timer_running == false) && (fhss_configuration -> ws_uc_channel_function != WS_FIXED_CHANNEL ) && fhss_configuration -> fhss_uc_dwell_interval ) {
789- fhss_start_timer (fhss_structure , MS_TO_US (fhss_configuration -> fhss_uc_dwell_interval ), fhss_unicast_handler );
817+ fhss_ws_start_timer (fhss_structure , MS_TO_US (fhss_configuration -> fhss_uc_dwell_interval ), fhss_unicast_handler );
790818 fhss_structure -> ws -> unicast_timer_running = true;
791819 }
792820 fhss_structure -> ws -> fhss_configuration = * fhss_configuration ;
0 commit comments