@@ -43,17 +43,25 @@ void (*fhss_uc_switch)(void) = NULL;
43
43
void (* fhss_bc_switch )(void ) = NULL ;
44
44
#endif /*FHSS_CHANNEL_DEBUG_CBS*/
45
45
// Seconds to milliseconds
46
- #define S_TO_MS (x ) (((uint32_t )x)*1000)
46
+ #define S_TO_MS (x ) (((int32_t )x)*1000)
47
47
// Milliseconds to seconds
48
48
#define MS_TO_S (x ) divide_integer(x, 1000)
49
49
// Seconds to microseconds
50
- #define S_TO_US (x ) (((uint32_t )x)*1000000)
50
+ #define S_TO_US (x ) (((int32_t )x)*1000000)
51
51
// Microseconds to seconds
52
52
#define US_TO_S (x ) divide_integer(x, 1000000)
53
53
// Milliseconds to microseconds
54
- #define MS_TO_US (x ) (((uint32_t )x)*1000)
54
+ #define MS_TO_US (x ) (((int32_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 ) (((int32_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 ) (((int32_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
@@ -77,8 +85,11 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure);
77
85
static uint8_t fhss_set_txrx_slot_length (fhss_structure_t * fhss_structure );
78
86
79
87
// This function supports rounding up
80
- static uint32_t divide_integer (uint32_t dividend , uint32_t divisor )
88
+ static int32_t divide_integer (int32_t dividend , int32_t divisor )
81
89
{
90
+ if (dividend < 0 ) {
91
+ return (dividend - divisor / 2 ) / divisor ;
92
+ }
82
93
return (dividend + divisor / 2 ) / divisor ;
83
94
}
84
95
@@ -92,6 +103,15 @@ static uint32_t get_remaining_slots_us(fhss_structure_t *fhss_structure, void (*
92
103
return remaining_time_us ;
93
104
}
94
105
106
+ void fhss_ws_start_timer (fhss_structure_t * fhss_structure , uint32_t time , void (* callback )(const fhss_api_t * fhss_api , uint16_t ))
107
+ {
108
+ // Number of millisecond slots in timeout(us)
109
+ int32_t time_in_ms = divide_integer (time , 1000 );
110
+ // Reduce the compensation (per millisecond) from timeout.
111
+ time -= NS_TO_US (time_in_ms * fhss_structure -> ws -> drift_per_millisecond_ns );
112
+ fhss_start_timer (fhss_structure , time , callback );
113
+ }
114
+
95
115
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
116
{
97
117
if (!fhss_api || !fhss_configuration || !fhss_timer ) {
@@ -196,7 +216,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
196
216
return ;
197
217
}
198
218
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 );
219
+ 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
220
fhss_structure -> ws -> is_on_bc_channel = true;
201
221
next_channel = fhss_structure -> ws -> bc_channel = fhss_ws_calc_bc_channel (fhss_structure );
202
222
@@ -211,7 +231,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
211
231
eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (bc_min_random , bc_max_random ));
212
232
} else {
213
233
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 );
234
+ fhss_ws_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
215
235
fhss_structure -> ws -> is_on_bc_channel = false;
216
236
// Should return to own (unicast) listening channel after broadcast channel
217
237
next_channel = fhss_structure -> rx_channel ;
@@ -353,7 +373,7 @@ static int16_t fhss_ws_synch_state_set_callback(const fhss_api_t *api, fhss_stat
353
373
// Start unicast schedule
354
374
if ((fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function != WS_FIXED_CHANNEL )) {
355
375
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 );
376
+ fhss_ws_start_timer (fhss_structure , MS_TO_US (fhss_structure -> ws -> fhss_configuration .fhss_uc_dwell_interval ), fhss_unicast_handler );
357
377
fhss_structure -> ws -> unicast_timer_running = true;
358
378
}
359
379
}
@@ -689,7 +709,7 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
689
709
fhss_structure -> ws -> unicast_timer_running = false;
690
710
return ;
691
711
}
692
- fhss_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_unicast_handler );
712
+ fhss_ws_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_unicast_handler );
693
713
fhss_structure -> ws -> unicast_timer_running = true;
694
714
fhss_ws_update_uc_channel_callback (fhss_structure );
695
715
// Unless we have broadcast schedule, we have to poll unicast queue when changing channel. This is randomized by the unicast schedule.
@@ -733,6 +753,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
733
753
platform_enter_critical ();
734
754
uint32_t prev_synchronization_time = fhss_structure -> ws -> synchronization_time ;
735
755
fhss_structure -> ws -> synchronization_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
756
+ uint32_t time_since_last_synch_us = fhss_structure -> ws -> synchronization_time - prev_synchronization_time ;
736
757
uint32_t own_bc_interval_offset = fhss_ws_calculate_broadcast_interval_offset (fhss_structure , fhss_structure -> ws -> synchronization_time );
737
758
fhss_stop_timer (fhss_structure , fhss_broadcast_handler );
738
759
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 +766,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
745
766
if (fhss_structure -> ws -> is_on_bc_channel ) {
746
767
timeout -= MS_TO_US (bc_timing_info -> broadcast_interval - bc_timing_info -> broadcast_dwell_interval );
747
768
}
748
- fhss_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
769
+ fhss_ws_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
749
770
uint16_t slots_since_reception = (bc_timing_info -> broadcast_interval_offset + time_from_reception_ms ) / bc_timing_info -> broadcast_interval ;
750
771
// TODO: Calculate drift error
751
772
fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval = bc_timing_info -> broadcast_dwell_interval ;
@@ -759,7 +780,11 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
759
780
//TODO: support multiple parents
760
781
fhss_structure -> ws -> parent_bc_info = bc_timing_info ;
761
782
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 ));
783
+ if (SYNCH_COMPENSATION_MIN_INTERVAL <= US_TO_S (time_since_last_synch_us )) {
784
+ // Update clock drift
785
+ 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 ));
786
+ }
787
+ 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
788
}
764
789
return 0 ;
765
790
}
@@ -786,7 +811,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
786
811
fhss_structure -> ws -> unicast_timer_running = false;
787
812
}
788
813
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 );
814
+ fhss_ws_start_timer (fhss_structure , MS_TO_US (fhss_configuration -> fhss_uc_dwell_interval ), fhss_unicast_handler );
790
815
fhss_structure -> ws -> unicast_timer_running = true;
791
816
}
792
817
fhss_structure -> ws -> fhss_configuration = * fhss_configuration ;
0 commit comments