| 
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