@@ -54,6 +54,14 @@ void (*fhss_bc_switch)(void) = NULL;
54
54
#define MS_TO_US (x ) (((uint32_t)x)*1000)
55
55
// Microseconds to milliseconds
56
56
#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)
57
65
#define DEF_2E24 0x1000000
58
66
#define IE_HEADER_LENGTH_MASK 0x007f
59
67
#define IE_HEADER_ID_MASK 0x7f80
@@ -92,6 +100,15 @@ static uint32_t get_remaining_slots_us(fhss_structure_t *fhss_structure, void (*
92
100
return remaining_time_us ;
93
101
}
94
102
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
+
95
112
fhss_structure_t * fhss_ws_enable (fhss_api_t * fhss_api , const fhss_ws_configuration_t * fhss_configuration , const fhss_timer_t * fhss_timer )
96
113
{
97
114
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)
196
213
return ;
197
214
}
198
215
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 );
200
217
fhss_structure -> ws -> is_on_bc_channel = true;
201
218
next_channel = fhss_structure -> ws -> bc_channel = fhss_ws_calc_bc_channel (fhss_structure );
202
219
@@ -211,7 +228,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
211
228
eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (bc_min_random , bc_max_random ));
212
229
} else {
213
230
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 );
215
232
fhss_structure -> ws -> is_on_bc_channel = false;
216
233
// Should return to own (unicast) listening channel after broadcast channel
217
234
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
353
370
// Start unicast schedule
354
371
if ((fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function != WS_FIXED_CHANNEL )) {
355
372
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 );
357
374
fhss_structure -> ws -> unicast_timer_running = true;
358
375
}
359
376
}
@@ -689,7 +706,7 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
689
706
fhss_structure -> ws -> unicast_timer_running = false;
690
707
return ;
691
708
}
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 );
693
710
fhss_structure -> ws -> unicast_timer_running = true;
694
711
fhss_ws_update_uc_channel_callback (fhss_structure );
695
712
// 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],
733
750
platform_enter_critical ();
734
751
uint32_t prev_synchronization_time = fhss_structure -> ws -> synchronization_time ;
735
752
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 ;
736
754
uint32_t own_bc_interval_offset = fhss_ws_calculate_broadcast_interval_offset (fhss_structure , fhss_structure -> ws -> synchronization_time );
737
755
fhss_stop_timer (fhss_structure , fhss_broadcast_handler );
738
756
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],
745
763
if (fhss_structure -> ws -> is_on_bc_channel ) {
746
764
timeout -= MS_TO_US (bc_timing_info -> broadcast_interval - bc_timing_info -> broadcast_dwell_interval );
747
765
}
748
- fhss_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
766
+ fhss_ws_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
749
767
uint16_t slots_since_reception = (bc_timing_info -> broadcast_interval_offset + time_from_reception_ms ) / bc_timing_info -> broadcast_interval ;
750
768
// TODO: Calculate drift error
751
769
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],
759
777
//TODO: support multiple parents
760
778
fhss_structure -> ws -> parent_bc_info = bc_timing_info ;
761
779
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 );
763
791
}
764
792
return 0 ;
765
793
}
@@ -786,7 +814,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
786
814
fhss_structure -> ws -> unicast_timer_running = false;
787
815
}
788
816
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 );
790
818
fhss_structure -> ws -> unicast_timer_running = true;
791
819
}
792
820
fhss_structure -> ws -> fhss_configuration = * fhss_configuration ;
0 commit comments