42
42
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)
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)
46
57
#define DEF_2E24 0x1000000
47
58
#define IE_HEADER_LENGTH_MASK 0x007f
48
59
#define IE_HEADER_ID_MASK 0x7f80
@@ -71,6 +82,16 @@ static uint32_t divide_integer(uint32_t dividend, uint32_t divisor)
71
82
return (dividend + divisor /2 ) / divisor ;
72
83
}
73
84
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
+
74
95
fhss_structure_t * fhss_ws_enable (fhss_api_t * fhss_api , const fhss_ws_configuration_t * fhss_configuration , const fhss_timer_t * fhss_timer )
75
96
{
76
97
if (!fhss_api || !fhss_configuration || !fhss_timer ) {
@@ -156,7 +177,7 @@ static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure)
156
177
}
157
178
}
158
179
#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 );
160
181
#endif /*FHSS_CHANNEL_DEBUG*/
161
182
return next_channel ;
162
183
}
@@ -175,7 +196,7 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
175
196
return ;
176
197
}
177
198
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 );
179
200
fhss_structure -> ws -> is_on_bc_channel = true;
180
201
next_channel = fhss_structure -> ws -> bc_channel = fhss_ws_calc_bc_channel (fhss_structure );
181
202
@@ -184,12 +205,12 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
184
205
* Max random is 1/10 of the channel dwell interval.
185
206
* Event timer resolution is 50us.
186
207
*/
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 ) ;
188
209
uint16_t bc_min_random = (bc_dwell_us / 50 ) / 50 ;
189
210
uint16_t bc_max_random = (bc_dwell_us / 10 ) / 50 ;
190
211
eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (bc_min_random , bc_max_random ));
191
212
} 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 );
193
214
fhss_start_timer (fhss_structure , timeout - (delay * fhss_structure -> platform_functions .fhss_resolution_divider ), fhss_broadcast_handler );
194
215
fhss_structure -> ws -> is_on_bc_channel = false;
195
216
// 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)
199
220
* Max random is 1/10 of the TX slot length.
200
221
* Event timer resolution is 50us.
201
222
*/
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 ) ;
203
224
uint16_t uc_min_random = (txrx_slot_length_us / 30 ) / 50 ;
204
225
uint16_t uc_max_random = (txrx_slot_length_us / 10 ) / 50 ;
205
226
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)
210
231
eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , randLIB_get_random_in_range (uc_min_random , uc_max_random ));
211
232
212
233
#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 );
214
235
#endif /*FHSS_CHANNEL_DEBUG*/
215
236
}
216
237
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)
246
267
queue_size = fhss_structure -> callbacks .read_tx_queue_size (fhss_structure -> fhss_api , true);
247
268
} else {
248
269
// 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 ) )) {
251
272
eventOS_callback_timer_start (fhss_structure -> fhss_event_timer , delay_between_tx_slots_us /50 );
252
273
}
253
274
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_
265
286
cur_slot = fhss_structure -> number_of_channels ;
266
287
}
267
288
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 )));
272
290
uint32_t time_to_tx = 0 ;
273
291
uint32_t cur_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
274
292
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 );
276
294
}
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 ;
278
296
uint32_t seq_length = 0x10000 ;
279
297
if (fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function == WS_TR51CF ) {
280
298
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
287
305
{
288
306
uint8_t dwell_time = fhss_structure -> ws -> fhss_configuration .fhss_bc_dwell_interval ;
289
307
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 )));
292
309
if (fhss_structure -> ws -> is_on_bc_channel == true) {
293
- remaining_time += (broadcast_interval - dwell_time );
310
+ remaining_time_ms += (broadcast_interval - dwell_time );
294
311
}
295
312
uint32_t time_to_tx = 0 ;
296
313
uint32_t cur_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
297
314
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 );
299
316
}
300
- return (broadcast_interval - remaining_time ) + time_to_tx ;
317
+ return (broadcast_interval - remaining_time_ms ) + time_to_tx ;
301
318
}
302
319
303
320
static 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_
310
327
seq_length = neighbor_timing_info -> uc_timing_info .unicast_number_of_channels ;
311
328
}
312
329
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 );
314
331
}
315
332
316
333
static uint32_t fhss_ws_get_sf_timeout_callback (fhss_structure_t * fhss_structure )
317
334
{
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 ) ;
319
336
}
320
337
321
338
static 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
336
353
// Start unicast schedule
337
354
if ((fhss_structure -> ws -> fhss_configuration .ws_uc_channel_function != WS_FIXED_CHANNEL )) {
338
355
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 );
340
357
fhss_structure -> ws -> unicast_timer_running = true;
341
358
}
342
359
}
@@ -374,7 +391,7 @@ static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure)
374
391
return ;
375
392
}
376
393
#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 );
378
395
#endif /*FHSS_CHANNEL_DEBUG*/
379
396
fhss_structure -> callbacks .change_channel (fhss_structure -> fhss_api , next_channel );
380
397
#ifdef FHSS_CHANNEL_DEBUG_CBS
@@ -466,7 +483,8 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure)
466
483
if (!number_of_tx_slots ) {
467
484
return true;
468
485
}
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 ;
470
488
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 ));
471
489
uint32_t rx_slot_begin = tx_slot_begin - fhss_structure -> ws -> txrx_slot_length_ms ;
472
490
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_
488
506
return true;
489
507
}
490
508
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 ) {
493
511
return false;
494
512
}
495
513
return true;
@@ -709,21 +727,23 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
709
727
if (!bc_timing_info -> broadcast_interval || !bc_timing_info -> broadcast_dwell_interval ) {
710
728
return -1 ;
711
729
}
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 ) {
713
731
return 0 ;
714
732
}
715
- fhss_structure -> ws -> synchronization_time = fhss_structure -> callbacks .read_timestamp (fhss_structure -> fhss_api );
716
733
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 );
717
737
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 );
719
739
uint32_t true_bc_interval_offset = (bc_timing_info -> broadcast_interval_offset + time_from_reception_ms ) % bc_timing_info -> broadcast_interval ;
720
740
if (true_bc_interval_offset >= bc_timing_info -> broadcast_dwell_interval ) {
721
741
fhss_structure -> ws -> is_on_bc_channel = false;
722
742
}
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 );
724
744
725
745
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 );
727
747
}
728
748
fhss_start_timer (fhss_structure , timeout , fhss_broadcast_handler );
729
749
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],
738
758
platform_exit_critical ();
739
759
//TODO: support multiple parents
740
760
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
+ }
741
764
return 0 ;
742
765
}
743
766
@@ -763,7 +786,7 @@ int fhss_ws_configuration_set(fhss_structure_t *fhss_structure, const fhss_ws_co
763
786
fhss_structure -> ws -> unicast_timer_running = false;
764
787
}
765
788
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 );
767
790
fhss_structure -> ws -> unicast_timer_running = true;
768
791
}
769
792
fhss_structure -> ws -> fhss_configuration = * fhss_configuration ;
0 commit comments