23
23
#include "fhss_channel.h"
24
24
#include "channel_list.h"
25
25
#include "nsdynmemLIB.h"
26
- #include "fhss_beacon.h"
27
26
#include "fhss_statistics.h"
28
- #include "fhss_mac_interface.h"
29
27
#include "ns_trace.h"
30
28
#include "eventOS_event.h"
31
29
#include "eventOS_callback_timer.h"
32
30
#include "platform/arm_hal_interrupt.h"
33
31
#include "randLIB.h"
32
+ #include "common_functions.h"
34
33
#include <string.h>
35
34
36
35
#define TRACE_GROUP "fhss"
@@ -43,6 +42,10 @@ static fhss_failed_tx_t *fhss_failed_handle_find(fhss_structure_t *fhss_structur
43
42
static void fhss_failed_list_free (fhss_structure_t * fhss_structure );
44
43
static void fhss_beacon_received (fhss_structure_t * fhss_structure , const uint8_t * synch_info , const uint32_t elapsed_time );
45
44
static void fhss_superframe_handler (const fhss_api_t * fhss_api , uint16_t delay );
45
+ static int8_t fhss_beacon_create_tasklet (fhss_structure_t * fhss_structure );
46
+ static void fhss_beacon_tasklet_func (arm_event_s * event );
47
+ static int fhss_beacon_periodic_start (fhss_structure_t * fhss_structure , uint32_t time_to_first_beacon );
48
+ static void fhss_beacon_periodic_stop (fhss_structure_t * fhss_structure );
46
49
47
50
fhss_structure_t * fhss_enable (fhss_api_t * fhss_api , const fhss_configuration_t * fhss_configuration , const fhss_timer_t * fhss_timer , fhss_statistics_t * fhss_statistics )
48
51
{
@@ -791,6 +794,123 @@ static void fhss_handle_state_set(const fhss_api_t *api, fhss_states fhss_state,
791
794
return ;
792
795
}
793
796
797
+ static void fhss_beacon_decode_raw (fhss_synchronization_beacon_payload_s * dest , const uint8_t * buffer )
798
+ {
799
+ dest -> data_start_delimeter = * buffer ++ ;
800
+ dest -> channel_index = * buffer ++ ;
801
+ dest -> sender_unicast_channel = * buffer ++ ;
802
+ dest -> current_superframe = common_read_16_bit (buffer );
803
+ buffer += BEACON_FIELD_SIZE (current_superframe );
804
+ dest -> remaining_slots = common_read_16_bit (buffer );
805
+ buffer += BEACON_FIELD_SIZE (remaining_slots );
806
+ dest -> channel_list_counter = common_read_16_bit (buffer );
807
+ buffer += BEACON_FIELD_SIZE (channel_list_counter );
808
+ dest -> hop_count = * buffer ++ ;
809
+ dest -> number_of_broadcast_channels = * buffer ++ ;
810
+ dest -> number_of_tx_slots = * buffer ++ ;
811
+ dest -> time_since_last_beacon = common_read_32_bit (buffer );
812
+ buffer += BEACON_FIELD_SIZE (time_since_last_beacon );
813
+ dest -> processing_delay += common_read_16_bit (buffer );
814
+ buffer += BEACON_FIELD_SIZE (processing_delay );
815
+ dest -> superframe_length = common_read_16_bit (buffer );
816
+ buffer += BEACON_FIELD_SIZE (superframe_length );
817
+ dest -> number_of_superframes_per_channel = * buffer ;
818
+ }
819
+
820
+ static uint32_t fhss_get_time_to_next_channel_change (uint16_t remaining_slots_to_next_superframe , uint8_t number_of_superframes , uint8_t current_superframe , uint16_t superframe_length )
821
+ {
822
+ return remaining_slots_to_next_superframe + ((uint32_t )((number_of_superframes - 1 ) - current_superframe ) * superframe_length );
823
+ }
824
+
825
+ // Decode the given raw byte buffer into a struct into dest struct and calculate
826
+ // the new values for elapsed_time, channel_index, current_superframe and remaining_slots
827
+ // from current state and given data.
828
+ static void fhss_beacon_decode (fhss_synchronization_beacon_payload_s * dest , const uint8_t * buffer , uint32_t elapsed_time , uint16_t number_of_channels )
829
+ {
830
+ fhss_beacon_decode_raw (dest , buffer );
831
+
832
+ elapsed_time += dest -> processing_delay ;
833
+
834
+ /* To calculate channel index after beacon scan, following calculation is performed
835
+ *
836
+ * rem. slots to channel change(X) Channel length (V)
837
+ * |---------------------| |-----------------------------------------------|
838
+ * | RX'd channel index (Y) | ... | Y+n |
839
+ * ...| sf1 | sf2 | sf3 | sf4 | ... | sf1 | sf2 | sf3 | sf4 |...
840
+ * ^ ^
841
+ * |beacon received |beacon scan done
842
+ * |-------------------------------------|
843
+ * measured time after beacon RX'd(Z)
844
+ * V = superframe length * number of superframes
845
+ * X = remaining slots to superframe change + length of the remaining full superframes to channel change
846
+ *
847
+ * Y+n = Y + ((Z - X) / V) + 1
848
+ *
849
+ * Or if (Z < X)
850
+ * Y+n = Y
851
+ */
852
+
853
+ uint32_t remaining_slots_to_next_channel = fhss_get_time_to_next_channel_change (dest -> remaining_slots , dest -> number_of_superframes_per_channel , dest -> current_superframe , dest -> superframe_length );
854
+ uint16_t temp_channel_index = dest -> channel_index ;
855
+ if (elapsed_time >= remaining_slots_to_next_channel ) {
856
+ uint32_t channel_length = (uint32_t ) dest -> number_of_superframes_per_channel * dest -> superframe_length ;
857
+ temp_channel_index = dest -> channel_index + ((elapsed_time - remaining_slots_to_next_channel ) / channel_length ) + 1 ;
858
+ }
859
+ while (temp_channel_index >= number_of_channels ) {
860
+ temp_channel_index -= number_of_channels ;
861
+ dest -> channel_list_counter ++ ;
862
+ }
863
+ dest -> channel_index = temp_channel_index ;
864
+ while (dest -> channel_list_counter >= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES )) {
865
+ dest -> channel_list_counter -= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES );
866
+ }
867
+
868
+ /* To calculate superframe after beacon scan, following calculation is performed
869
+ *
870
+ * rem. slots(X) sf. length(V)
871
+ * |---------------| |-----------------|
872
+ *...| RX'd superframe (Y)| ... | Y+n | Y+n+1 |....
873
+ * ^ ^
874
+ * |beacon received |beacon scan done
875
+ * |-------------------------------------|
876
+ * measured time after beacon RX'd(Z)
877
+ *
878
+ * Y+n = Y + ((Z - X) / V) + 1
879
+ *
880
+ * Or if (Z < X)
881
+ * Y+n = Y
882
+ */
883
+
884
+ if (elapsed_time >= dest -> remaining_slots ) {
885
+ dest -> current_superframe = dest -> current_superframe + ((elapsed_time - dest -> remaining_slots ) / dest -> superframe_length ) + 1 ;
886
+ }
887
+ while (dest -> current_superframe >= dest -> number_of_superframes_per_channel ) {
888
+ dest -> current_superframe -= dest -> number_of_superframes_per_channel ;
889
+ }
890
+
891
+ /* To get the remaining slots after beacon scan, following calculation is performed
892
+ *
893
+ * rem. slots(Y) sf. length(V) new rem. slots(X)
894
+ * |----------| |---------------| |-------------|
895
+ *...| superframe 1 | superframe 2 | superframe 3 | superframe 4 |...
896
+ * ^ ^
897
+ * |beacon received |beacon scan done
898
+ * |--------------------------------------------|
899
+ * measured time after beacon RX'd(Z)
900
+ *
901
+ * X = V - ((Z - Y) % V)
902
+ *
903
+ * Or if (Z < Y)
904
+ * X = Y - Z
905
+ */
906
+
907
+ if (elapsed_time < dest -> remaining_slots ) {
908
+ dest -> remaining_slots = dest -> remaining_slots - elapsed_time ;
909
+ } else {
910
+ dest -> remaining_slots = dest -> superframe_length - ((elapsed_time - dest -> remaining_slots ) % dest -> superframe_length );
911
+ }
912
+ }
913
+
794
914
static void fhss_beacon_received (fhss_structure_t * fhss_structure , const uint8_t * synch_info , const uint32_t elapsed_time )
795
915
{
796
916
@@ -929,8 +1049,52 @@ static void fhss_update_channel_callback(fhss_structure_t *fhss_structure)
929
1049
}
930
1050
}
931
1051
1052
+ static uint8_t * fhss_beacon_encode_raw (uint8_t * buffer , const fhss_synchronization_beacon_payload_s * source )
1053
+ {
1054
+ * buffer ++ = FHSS_DATA_START_DELIMETER ;
1055
+ * buffer ++ = source -> channel_index ;
1056
+ * buffer ++ = source -> sender_unicast_channel ;
1057
+ buffer = common_write_16_bit (source -> current_superframe , buffer );
1058
+ buffer = common_write_16_bit (source -> remaining_slots , buffer );
1059
+ buffer = common_write_16_bit (source -> channel_list_counter , buffer );
1060
+ * buffer ++ = source -> hop_count ;
1061
+ * buffer ++ = source -> number_of_broadcast_channels ;
1062
+ * buffer ++ = source -> number_of_tx_slots ;
1063
+ buffer = common_write_32_bit (source -> time_since_last_beacon , buffer );
1064
+ buffer = common_write_16_bit (source -> processing_delay , buffer );
1065
+ buffer = common_write_16_bit (source -> superframe_length , buffer );
1066
+ * buffer ++ = source -> number_of_superframes_per_channel ;
1067
+
1068
+ return buffer ;
1069
+ }
1070
+
1071
+ static void fhss_beacon_build (fhss_structure_t * fhss_structure , uint8_t * dest )
1072
+ {
1073
+ fhss_synchronization_beacon_payload_s temp_payload ;
1074
+ platform_enter_critical ();
1075
+ const fhss_synch_configuration_t * config = & fhss_structure -> bs -> synch_configuration ;
1076
+ temp_payload .channel_index = fhss_structure -> bs -> current_channel_index ;
1077
+ temp_payload .sender_unicast_channel = 0 ;
1078
+ temp_payload .current_superframe = fhss_structure -> bs -> current_superframe ;
1079
+ // This assumes that the time is always in the range of 0..2**16, which
1080
+ // should be the case as the superframe length field is also in that range.
1081
+ temp_payload .remaining_slots = (uint16_t ) fhss_get_remaining_time_to_next_superframe (fhss_structure );
1082
+ temp_payload .channel_list_counter = fhss_structure -> bs -> channel_list_counter ;
1083
+ temp_payload .hop_count = fhss_structure -> bs -> own_hop ;
1084
+ temp_payload .number_of_broadcast_channels = config -> fhss_number_of_bc_channels ;
1085
+ temp_payload .number_of_tx_slots = config -> fhss_number_of_tx_slots ;
1086
+ temp_payload .time_since_last_beacon = 0 ; // XXX not available yet
1087
+ uint32_t tx_time = fhss_get_tx_time (fhss_structure , 71 , 0 , 0 );
1088
+ temp_payload .processing_delay = fhss_structure -> bs -> fhss_configuration .fhss_tuning_parameters .tx_processing_delay + tx_time ;
1089
+ temp_payload .superframe_length = config -> fhss_superframe_length ;
1090
+ temp_payload .number_of_superframes_per_channel = config -> fhss_number_of_superframes ;
1091
+ platform_exit_critical ();
1092
+ fhss_beacon_encode_raw (dest , & temp_payload );
1093
+ }
1094
+
932
1095
static int16_t fhss_write_synch_info_callback (const fhss_api_t * api , uint8_t * ptr , uint8_t length , int frame_type , uint32_t tx_time )
933
1096
{
1097
+ (void ) length ;
934
1098
fhss_structure_t * fhss_structure = fhss_get_object_with_api (api );
935
1099
(void ) tx_time ;
936
1100
if (!fhss_structure || !ptr || (frame_type != FHSS_SYNCH_FRAME )) {
@@ -1141,6 +1305,16 @@ int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss
1141
1305
return 0 ;
1142
1306
}
1143
1307
1308
+ uint8_t fhss_calculate_uc_index (uint8_t channel_index , uint16_t number_of_channels , uint8_t number_of_broadcast_channels )
1309
+ {
1310
+ // When channel index is 0, return last unicast index
1311
+ if (channel_index == 0 ) {
1312
+ return (number_of_channels - number_of_broadcast_channels - 1 );
1313
+ }
1314
+ uint16_t bc_channel_density = (number_of_channels /number_of_broadcast_channels );
1315
+ return channel_index - (channel_index /bc_channel_density ) - 1 ;
1316
+ }
1317
+
1144
1318
int fhss_set_callbacks (fhss_structure_t * fhss_structure )
1145
1319
{
1146
1320
// Set external API
@@ -1159,3 +1333,94 @@ int fhss_set_callbacks(fhss_structure_t *fhss_structure)
1159
1333
1160
1334
return 0 ;
1161
1335
}
1336
+
1337
+ static int8_t fhss_beacon_create_tasklet (fhss_structure_t * fhss_structure )
1338
+ {
1339
+ if (fhss_structure -> beacon_tasklet_id < 0 ) {
1340
+ fhss_structure -> beacon_tasklet_id = eventOS_event_handler_create (fhss_beacon_tasklet_func , FHSS_TASKLET_INIT_EVENT );
1341
+ }
1342
+ return fhss_structure -> beacon_tasklet_id ;
1343
+ }
1344
+
1345
+ static int fhss_beacon_periodic_start (fhss_structure_t * fhss_structure , uint32_t time_to_first_beacon )
1346
+ {
1347
+ int ret_val = -1 ;
1348
+
1349
+ if (fhss_structure ) {
1350
+ fhss_beacon_periodic_stop (fhss_structure );
1351
+ ret_val = fhss_timeout_start (fhss_structure , time_to_first_beacon * 1000 );
1352
+ }
1353
+ return ret_val ;
1354
+ }
1355
+
1356
+ static void fhss_beacon_periodic_stop (fhss_structure_t * fhss_structure )
1357
+ {
1358
+ if (fhss_structure ) {
1359
+ fhss_timeout_stop (fhss_structure );
1360
+ }
1361
+ }
1362
+
1363
+ static void fhss_beacon_tasklet_func (arm_event_s * event )
1364
+ {
1365
+ fhss_structure_t * fhss_structure = (fhss_structure_t * )event -> data_ptr ;
1366
+ if (!fhss_structure ) {
1367
+ return ;
1368
+ }
1369
+ uint8_t parent_address [8 ];
1370
+ fhss_clear_active_event (fhss_structure , event -> event_type );
1371
+ // skip the init event as there will be a timer event after
1372
+ if (event -> event_type == FHSS_TIMER_EVENT ) {
1373
+ // Stop network when lost number of FHSS_SYNCHRONIZATION_LOST synchronization beacons from parent in a row.
1374
+ if (fhss_structure -> bs -> beacons_received_timer >= FHSS_SYNCHRONIZATION_LOST ) {
1375
+ fhss_structure -> callbacks .synch_lost_notification (fhss_structure -> fhss_api );
1376
+ fhss_stats_update (fhss_structure , STATS_FHSS_SYNCH_LOST , 1 );
1377
+ tr_err ("FHSS synchronization lost" );
1378
+ } else {
1379
+ uint16_t bc_density = (fhss_structure -> number_of_channels / fhss_structure -> bs -> synch_configuration .fhss_number_of_bc_channels );
1380
+ uint16_t channel_dwell_time = ((uint32_t )fhss_structure -> bs -> synch_configuration .fhss_superframe_length * fhss_structure -> bs -> synch_configuration .fhss_number_of_superframes ) / 1000 ;
1381
+
1382
+ fhss_beacon_periodic_start (fhss_structure , (bc_density * channel_dwell_time ) * 2 );
1383
+ // Send synchronization request
1384
+ fhss_structure -> callbacks .send_fhss_frame (fhss_structure -> fhss_api , FHSS_SYNCH_REQUEST_FRAME );
1385
+ fhss_structure -> bs -> beacons_received_timer ++ ;
1386
+ #ifdef FEA_TRACE_SUPPORT
1387
+ if (!fhss_get_parent_address (fhss_structure , parent_address )) {
1388
+ tr_debug ("Update synch, attempt: %u, %s" , fhss_structure -> bs -> beacons_received_timer , trace_array (parent_address , 8 ));
1389
+ } else {
1390
+ tr_err ("No synch parent found" );
1391
+ }
1392
+ #endif /*FEA_TRACE_SUPPORT*/
1393
+ }
1394
+ }
1395
+ // Compare if synchronization parent has changed and request beacon if needed
1396
+ else if (event -> event_type == FHSS_COMPARE_SYNCH_PARENT )
1397
+ {
1398
+ if (fhss_compare_with_synch_parent_address (fhss_structure , fhss_structure -> synch_parent )) {
1399
+ fhss_structure -> bs -> synch_monitor .avg_synch_fix = 0 ;
1400
+ if (fhss_structure -> bs -> synch_monitor .avg_synch_fix_counter > 0 ) {
1401
+ fhss_structure -> bs -> synch_monitor .avg_synch_fix_counter = 0 ;
1402
+ }
1403
+ // Send synchronization request
1404
+ fhss_structure -> callbacks .send_fhss_frame (fhss_structure -> fhss_api , FHSS_SYNCH_REQUEST_FRAME );
1405
+ #ifdef FEA_TRACE_SUPPORT
1406
+ if (!fhss_get_parent_address (fhss_structure , parent_address )) {
1407
+ tr_debug ("Synch parent changed, New: %s, Old: %s\n" , trace_array (parent_address , 8 ), trace_array (fhss_structure -> synch_parent , 8 ));
1408
+ } else {
1409
+ tr_err ("Synch parent changed : No parent found" );
1410
+ }
1411
+ #endif /*FEA_TRACE_SUPPORT*/
1412
+ }
1413
+ }
1414
+ else if (event -> event_type == FHSS_BROADCAST_CHANNEL )
1415
+ {
1416
+ uint16_t superframe_length = fhss_structure -> bs -> synch_configuration .fhss_superframe_length ;
1417
+ uint8_t number_of_superframes = fhss_structure -> bs -> synch_configuration .fhss_number_of_superframes ;
1418
+ // Given broadcast time is channel length minus 1 superframe
1419
+ fhss_structure -> callbacks .broadcast_notify (fhss_structure -> fhss_api , (uint32_t )superframe_length * (number_of_superframes - 1 ));
1420
+ }
1421
+ // Update Beacon info lifetimes
1422
+ else if (event -> event_type == FHSS_UPDATE_SYNCH_INFO_STORAGE )
1423
+ {
1424
+ fhss_update_beacon_info_lifetimes (fhss_structure , fhss_read_timestamp_cb (fhss_structure -> fhss_api ));
1425
+ }
1426
+ }
0 commit comments