|
28 | 28 | #include "ns_trace.h"
|
29 | 29 | #include "eventOS_event.h"
|
30 | 30 | #include "eventOS_callback_timer.h"
|
| 31 | +#include "platform/arm_hal_interrupt.h" |
31 | 32 | #include "randLIB.h"
|
32 | 33 | #include <string.h>
|
33 | 34 |
|
@@ -165,97 +166,7 @@ int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor)
|
165 | 166 | return -1;
|
166 | 167 | }
|
167 | 168 |
|
168 |
| -uint32_t fhss_get_remaining_time_to_next_superframe(const fhss_structure_t *fhss_structure) |
169 |
| -{ |
170 |
| - const uint32_t slots = fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_superframe_handler, fhss_structure->fhss_api); |
171 |
| - const uint32_t time = slots * fhss_structure->platform_functions.fhss_resolution_divider; |
172 |
| - return time; |
173 |
| -} |
174 |
| - |
175 |
| -void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay) |
176 |
| -{ |
177 |
| - int compensation = 0; |
178 |
| - fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api); |
179 |
| - if (!fhss_structure) { |
180 |
| - return; |
181 |
| - } |
182 |
| -/* Drift compensation doesn't work with Linux platform */ |
183 |
| -#ifndef __linux__ |
184 |
| - // Drift compensation on first superframe |
185 |
| - if (fhss_structure->current_superframe == 0) { |
186 |
| - /* Idea is to compensate number of drift_compensation (microseconds) on each channel. |
187 |
| - * However, fhss_resolution_divider defines the minimum timer resolution. |
188 |
| - * E.g. if fhss_resolution_divider = 64, compensate (drift_compensation * 64) on each 64th channel. |
189 |
| - */ |
190 |
| - if (++fhss_structure->synch_monitor.channel_counter == fhss_structure->platform_functions.fhss_resolution_divider) { |
191 |
| - compensation = fhss_structure->synch_monitor.drift_compensation; |
192 |
| - fhss_structure->synch_monitor.channel_counter = 0; |
193 |
| - } |
194 |
| - } |
195 |
| -#endif //__linux__ |
196 |
| - // Restart timer asap to minimize the effect of dynamic execution time of |
197 |
| - // the rest of function. |
198 |
| - fhss_start_timer(fhss_structure, (fhss_structure->synch_configuration.fhss_superframe_length) - (delay * fhss_structure->platform_functions.fhss_resolution_divider) + (compensation * fhss_structure->platform_functions.fhss_resolution_divider), fhss_superframe_handler); |
199 |
| - |
200 |
| - // check, if the current frame was the last one |
201 |
| - if (fhss_structure->current_superframe >= (fhss_structure->synch_configuration.fhss_number_of_superframes - 1)) { |
202 |
| - |
203 |
| - // last superframe has passed, change channel |
204 |
| - fhss_structure->current_superframe = 0; |
205 |
| - fhss_structure->current_channel_index++; |
206 |
| - if (fhss_structure->current_channel_index >= fhss_structure->number_of_channels) { |
207 |
| - fhss_structure->synch_infos_sent_counter = 0; |
208 |
| - fhss_structure->current_channel_index = 0; |
209 |
| - fhss_structure->channel_list_counter++; |
210 |
| - // Repeated cycle is started from beginning, reset counter. Don't let the channel_list_counter overflow. |
211 |
| - if (fhss_structure->channel_list_counter >= ((uint16_t) fhss_structure->number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) { |
212 |
| - fhss_structure->channel_list_counter = 0; |
213 |
| - } |
214 |
| - // Hop 0 don't have parent |
215 |
| - if (fhss_is_synch_root(fhss_structure) == false) { |
216 |
| - fhss_trig_event(fhss_structure, FHSS_COMPARE_SYNCH_PARENT); |
217 |
| - } |
218 |
| - fhss_trig_event(fhss_structure, FHSS_UPDATE_SYNCH_INFO_STORAGE); |
219 |
| - } |
220 |
| - fhss_update_channel(fhss_structure); |
221 |
| - } else { |
222 |
| - // bump up the superframe counter |
223 |
| - fhss_structure->current_superframe++; |
224 |
| - } |
225 |
| - if ((fhss_structure->send_synch_info_on_next_broadcast_channel == true) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) { |
226 |
| - /* Randomize sending superframe of synchronization frame: |
227 |
| - * on first superframe probability is 1/number of superframes |
228 |
| - * on second superframe probability is 1/(number of superframes-1) |
229 |
| - * on third superframe probability is 1/(number of superframes-2) |
230 |
| - * on last superframe probability is 1/1 |
231 |
| - */ |
232 |
| - if (randLIB_get_random_in_range(1, fhss_structure->synch_configuration.fhss_number_of_superframes - fhss_structure->current_superframe) == 1) { |
233 |
| - fhss_structure->send_synch_info_on_next_broadcast_channel = false; |
234 |
| - fhss_structure->synch_infos_sent_counter++; |
235 |
| - fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_FRAME); |
236 |
| - } |
237 |
| - } |
238 |
| - fhss_update_txrx_slots(fhss_structure); |
239 |
| - uint16_t queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false) + fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true); |
240 |
| - if ((fhss_structure->tx_allowed == true || fhss_is_current_channel_broadcast(fhss_structure) == true) && queue_size) { |
241 |
| - /* Start timer with random timeout to trigger TX queue poll event. |
242 |
| - * Max random is half of the superframe length. Event timer resolution is 50us. |
243 |
| - * Divide Max random with TX queue size to transmit faster when TX queue is growing |
244 |
| - */ |
245 |
| - uint16_t max_random = ((fhss_structure->synch_configuration.fhss_superframe_length / 2) / 50) / queue_size; |
246 |
| - eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(1, max_random)); |
247 |
| - } |
248 |
| - if (fhss_structure->fhss_timeout) { |
249 |
| - fhss_structure->fhss_timer += fhss_structure->synch_configuration.fhss_superframe_length; |
250 |
| - if (fhss_structure->fhss_timer >= fhss_structure->fhss_timeout) { |
251 |
| - fhss_trig_event(fhss_structure, FHSS_TIMER_EVENT); |
252 |
| - fhss_structure->fhss_timeout = 0; |
253 |
| - fhss_structure->fhss_timer = 0; |
254 |
| - } |
255 |
| - } |
256 |
| -} |
257 |
| - |
258 |
| -int fhss_update_txrx_slots(fhss_structure_t *fhss_structure) |
| 169 | +static int fhss_update_txrx_slots(fhss_structure_t *fhss_structure) |
259 | 170 | {
|
260 | 171 | uint8_t cur_superframe = fhss_structure->current_superframe;
|
261 | 172 | uint8_t number_of_tx_slots = fhss_structure->synch_configuration.fhss_number_of_tx_slots;
|
@@ -438,7 +349,7 @@ int fhss_sync_with_beacon(fhss_structure_t *fhss_structure,
|
438 | 349 |
|
439 | 350 | if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) {
|
440 | 351 | fhss_structure->fhss_state = FHSS_SYNCHRONIZED;
|
441 |
| - fhss_update_channel(fhss_structure); |
| 352 | + fhss_change_to_next_channel(fhss_structure); |
442 | 353 | }
|
443 | 354 | if (fhss_is_synch_root(fhss_structure) == false) {
|
444 | 355 | // Initially synch drift might be massive. Request first few Beacons more frequently until compensation starts fixing the error.
|
@@ -563,7 +474,7 @@ static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j)
|
563 | 474 | }
|
564 | 475 |
|
565 | 476 |
|
566 |
| -int fhss_generate_scramble_table(fhss_structure_t *fhss_structure) |
| 477 | +static int fhss_generate_scramble_table(fhss_structure_t *fhss_structure) |
567 | 478 | {
|
568 | 479 | uint8_t j = 2;
|
569 | 480 | fhss_structure->fhss_scramble_table = ns_dyn_mem_alloc(MAX_SCRAMBLE_TABLE_INDEXES);
|
@@ -746,3 +657,134 @@ void fhss_failed_list_free(fhss_structure_t *fhss_structure)
|
746 | 657 | fhss_failed_handle_remove(fhss_structure, i);
|
747 | 658 | }
|
748 | 659 | }
|
| 660 | + |
| 661 | +static int fhss_handle_state_set(fhss_structure_t *fhss_structure, fhss_states fhss_state, uint16_t pan_id) |
| 662 | +{ |
| 663 | + // State is already set |
| 664 | + if (fhss_structure->fhss_state == fhss_state) { |
| 665 | + tr_debug("Synch same state %u", fhss_state); |
| 666 | + return -1; |
| 667 | + } |
| 668 | + |
| 669 | + if (fhss_state == FHSS_UNSYNCHRONIZED) { |
| 670 | + tr_debug("FHSS down"); |
| 671 | + fhss_down(fhss_structure); |
| 672 | + } else { |
| 673 | + // Do not synchronize to current pan |
| 674 | + if (fhss_structure->synch_panid == pan_id) { |
| 675 | + tr_debug("Synch same panid %u", pan_id); |
| 676 | + return -1; |
| 677 | + } |
| 678 | + if (fhss_structure->fhss_scramble_table == NULL) { |
| 679 | + if (fhss_generate_scramble_table(fhss_structure)) { |
| 680 | + tr_error("Failed to generate scramble table"); |
| 681 | + return -1; |
| 682 | + } |
| 683 | + } |
| 684 | + uint32_t datarate = fhss_structure->callbacks.read_datarate(fhss_structure->fhss_api); |
| 685 | + fhss_set_datarate(fhss_structure, datarate); |
| 686 | + uint8_t mac_address[8]; |
| 687 | + fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); |
| 688 | + fhss_structure->uc_channel_index = fhss_get_offset(fhss_structure, mac_address); |
| 689 | + // Get Beacon info from storage |
| 690 | + fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); |
| 691 | + if (beacon_info) { |
| 692 | + memcpy(fhss_structure->synch_parent, beacon_info->source_address, 8); |
| 693 | + platform_enter_critical(); |
| 694 | + // Calculate time since the Beacon was received |
| 695 | + uint32_t elapsed_time = fhss_structure->fhss_api->read_timestamp(fhss_structure->fhss_api) - beacon_info->timestamp; |
| 696 | + // Synchronize to given PAN |
| 697 | + fhss_beacon_received(fhss_structure, beacon_info->synch_info, elapsed_time); |
| 698 | + platform_exit_critical(); |
| 699 | + // Delete stored Beacon infos |
| 700 | + fhss_flush_beacon_info_storage(fhss_structure); |
| 701 | + fhss_structure->synch_panid = pan_id; |
| 702 | + } else if (fhss_is_synch_root(fhss_structure) == true) { |
| 703 | + // Synch root will start new network |
| 704 | + fhss_start_timer(fhss_structure, fhss_structure->synch_configuration.fhss_superframe_length, fhss_superframe_handler); |
| 705 | + } else { |
| 706 | + tr_error("Synch info not found"); |
| 707 | + return -1; |
| 708 | + } |
| 709 | + } |
| 710 | + return 0; |
| 711 | +} |
| 712 | + |
| 713 | +static uint32_t fhss_get_compensation(fhss_structure_t *fhss_structure) |
| 714 | +{ |
| 715 | + uint32_t compensation = 0; |
| 716 | + /* Drift compensation doesn't work with Linux platform */ |
| 717 | +#ifndef __linux__ |
| 718 | + // Drift compensation on first superframe |
| 719 | + if (fhss_structure->current_superframe == 0) { |
| 720 | + /* Idea is to compensate number of drift_compensation (microseconds) on each channel. |
| 721 | + * However, fhss_resolution_divider defines the minimum timer resolution. |
| 722 | + * E.g. if fhss_resolution_divider = 64, compensate (drift_compensation * 64) on each 64th channel. |
| 723 | + */ |
| 724 | + if (++fhss_structure->synch_monitor.channel_counter == fhss_structure->platform_functions.fhss_resolution_divider) { |
| 725 | + compensation = fhss_structure->synch_monitor.drift_compensation; |
| 726 | + fhss_structure->synch_monitor.channel_counter = 0; |
| 727 | + } |
| 728 | + } |
| 729 | +#else |
| 730 | + (void) fhss_structure; |
| 731 | +#endif //__linux__ |
| 732 | + return compensation; |
| 733 | +} |
| 734 | + |
| 735 | +static void fhss_superframe_callback(fhss_structure_t *fhss_structure) |
| 736 | +{ |
| 737 | + if ((fhss_structure->send_synch_info_on_next_broadcast_channel == true) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) { |
| 738 | + /* Randomize sending superframe of synchronization frame: |
| 739 | + * on first superframe probability is 1/number of superframes |
| 740 | + * on second superframe probability is 1/(number of superframes-1) |
| 741 | + * on third superframe probability is 1/(number of superframes-2) |
| 742 | + * on last superframe probability is 1/1 |
| 743 | + */ |
| 744 | + if (randLIB_get_random_in_range(1, fhss_structure->synch_configuration.fhss_number_of_superframes - fhss_structure->current_superframe) == 1) { |
| 745 | + fhss_structure->send_synch_info_on_next_broadcast_channel = false; |
| 746 | + fhss_structure->synch_infos_sent_counter++; |
| 747 | + fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_FRAME); |
| 748 | + } |
| 749 | + } |
| 750 | + fhss_update_txrx_slots(fhss_structure); |
| 751 | + uint16_t queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false) + fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true); |
| 752 | + if ((fhss_structure->tx_allowed == true || fhss_is_current_channel_broadcast(fhss_structure) == true) && queue_size) { |
| 753 | + /* Start timer with random timeout to trigger TX queue poll event. |
| 754 | + * Max random is half of the superframe length. Event timer resolution is 50us. |
| 755 | + * Divide Max random with TX queue size to transmit faster when TX queue is growing |
| 756 | + */ |
| 757 | + uint16_t max_random = ((fhss_structure->synch_configuration.fhss_superframe_length / 2) / 50) / queue_size; |
| 758 | + eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(1, max_random)); |
| 759 | + } |
| 760 | +} |
| 761 | + |
| 762 | +static void fhss_update_channel_callback(fhss_structure_t *fhss_structure) |
| 763 | +{ |
| 764 | + if (fhss_structure->current_channel_index == 0) { |
| 765 | + fhss_structure->synch_infos_sent_counter = 0; |
| 766 | + if (++fhss_structure->channel_list_counter >= ((uint16_t) fhss_structure->number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) { |
| 767 | + fhss_structure->channel_list_counter = 0; |
| 768 | + } |
| 769 | + if (fhss_is_synch_root(fhss_structure) == false) { |
| 770 | + fhss_trig_event(fhss_structure, FHSS_COMPARE_SYNCH_PARENT); |
| 771 | + } |
| 772 | + fhss_trig_event(fhss_structure, FHSS_UPDATE_SYNCH_INFO_STORAGE); |
| 773 | + } |
| 774 | + // If channel is broadcast channel (true), send event |
| 775 | + if (fhss_change_to_next_channel(fhss_structure) == true) { |
| 776 | + // Only if device is border router |
| 777 | + if (fhss_structure->own_hop == 0) { |
| 778 | + fhss_trig_event(fhss_structure, FHSS_BROADCAST_CHANNEL); |
| 779 | + } |
| 780 | + } |
| 781 | +} |
| 782 | + |
| 783 | +int fhss_set_internal_callbacks(fhss_structure_t *fhss_structure) |
| 784 | +{ |
| 785 | + fhss_structure->update_channel = fhss_update_channel_callback; |
| 786 | + fhss_structure->update_superframe = fhss_superframe_callback; |
| 787 | + fhss_structure->read_compensation = fhss_get_compensation; |
| 788 | + fhss_structure->handle_state_set = fhss_handle_state_set; |
| 789 | + return 0; |
| 790 | +} |
0 commit comments