@@ -40,6 +40,9 @@ static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure);
40
40
static bool fhss_is_bc_sending_superframe (fhss_structure_t * fhss_structure );
41
41
static bool fhss_check_remaining_tx_time (fhss_structure_t * fhss_structure , uint16_t tx_length , uint8_t phy_header_length , uint8_t phy_tail_length );
42
42
static bool fhss_is_there_common_divisor (uint16_t i , uint8_t j );
43
+ static fhss_failed_tx_t * fhss_failed_handle_find (fhss_structure_t * fhss_structure , uint8_t handle );
44
+ static void fhss_failed_list_free (fhss_structure_t * fhss_structure );
45
+ static void fhss_beacon_received (fhss_structure_t * fhss_structure , const uint8_t * synch_info , const uint32_t elapsed_time );
43
46
44
47
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 )
45
48
{
@@ -195,7 +198,7 @@ static bool fhss_check_tx_allowed(fhss_structure_t *fhss_structure, bool is_bc,
195
198
return true;
196
199
}
197
200
198
- int fhss_reset_synch_monitor (fhss_synch_monitor_s * synch_monitor )
201
+ static int fhss_reset_synch_monitor (fhss_synch_monitor_s * synch_monitor )
199
202
{
200
203
if (synch_monitor ) {
201
204
synch_monitor -> avg_synch_fix = 0 ;
@@ -326,7 +329,7 @@ static int fhss_update_synch_monitor(fhss_structure_t *fhss_structure, const fhs
326
329
return retval ;
327
330
}
328
331
329
- int fhss_sync_with_beacon (fhss_structure_t * fhss_structure ,
332
+ static int fhss_sync_with_beacon (fhss_structure_t * fhss_structure ,
330
333
const fhss_synchronization_beacon_payload_s * payload )
331
334
{
332
335
int ret_val = -1 ;
@@ -654,7 +657,7 @@ static int fhss_reset(fhss_structure_t *fhss_structure)
654
657
return 0 ;
655
658
}
656
659
657
- int fhss_add_beacon_info (fhss_structure_t * fhss_structure , uint16_t pan_id , uint8_t * source_address , uint32_t timestamp , uint8_t * synch_info )
660
+ static int fhss_add_beacon_info (fhss_structure_t * fhss_structure , uint16_t pan_id , uint8_t * source_address , uint32_t timestamp , uint8_t * synch_info )
658
661
{
659
662
if (!fhss_structure || !source_address || !synch_info ) {
660
663
return -1 ;
@@ -687,7 +690,7 @@ void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, uint32_
687
690
}
688
691
}
689
692
690
- fhss_failed_tx_t * fhss_failed_handle_find (fhss_structure_t * fhss_structure , uint8_t handle )
693
+ static fhss_failed_tx_t * fhss_failed_handle_find (fhss_structure_t * fhss_structure , uint8_t handle )
691
694
{
692
695
ns_list_foreach (fhss_failed_tx_t , cur , & fhss_structure -> fhss_failed_tx_list ) {
693
696
if (cur -> handle == handle ) {
@@ -697,7 +700,7 @@ fhss_failed_tx_t *fhss_failed_handle_find(fhss_structure_t *fhss_structure, uint
697
700
return NULL ;
698
701
}
699
702
700
- int fhss_failed_handle_add (fhss_structure_t * fhss_structure , uint8_t handle )
703
+ static int fhss_failed_handle_add (fhss_structure_t * fhss_structure , uint8_t handle )
701
704
{
702
705
fhss_failed_tx_t * failed_tx = ns_dyn_mem_alloc (sizeof (fhss_failed_tx_t ));
703
706
if (!failed_tx ) {
@@ -710,7 +713,7 @@ int fhss_failed_handle_add(fhss_structure_t *fhss_structure, uint8_t handle)
710
713
return 0 ;
711
714
}
712
715
713
- int fhss_failed_handle_remove (fhss_structure_t * fhss_structure , uint8_t handle )
716
+ static int fhss_failed_handle_remove (fhss_structure_t * fhss_structure , uint8_t handle )
714
717
{
715
718
fhss_failed_tx_t * failed_tx = fhss_failed_handle_find (fhss_structure , handle );
716
719
if (!failed_tx ) {
@@ -721,7 +724,7 @@ int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle)
721
724
return 0 ;
722
725
}
723
726
724
- void fhss_failed_list_free (fhss_structure_t * fhss_structure )
727
+ static void fhss_failed_list_free (fhss_structure_t * fhss_structure )
725
728
{
726
729
for (uint16_t i = 0 ; i < 256 ; i ++ ) {
727
730
fhss_failed_handle_remove (fhss_structure , i );
@@ -797,6 +800,22 @@ static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure)
797
800
}
798
801
}
799
802
803
+ static void fhss_beacon_received (fhss_structure_t * fhss_structure , const uint8_t * synch_info , const uint32_t elapsed_time )
804
+ {
805
+
806
+ if (fhss_structure ) {
807
+
808
+ if (synch_info ) {
809
+ fhss_synchronization_beacon_payload_s temp_payload ;
810
+ temp_payload .processing_delay = fhss_structure -> fhss_conf .fhss_configuration .fhss_tuning_parameters .rx_processing_delay ;
811
+ fhss_beacon_decode (& temp_payload , synch_info , elapsed_time , fhss_structure -> number_of_channels );
812
+
813
+ // use the received information
814
+ fhss_sync_with_beacon (fhss_structure , & temp_payload );
815
+ }
816
+ }
817
+ }
818
+
800
819
static uint32_t fhss_get_sf_timeout_callback (fhss_structure_t * fhss_structure )
801
820
{
802
821
uint32_t compensation = 0 ;
@@ -955,19 +974,127 @@ static void fhss_data_tx_done_callback(const fhss_api_t *api, bool waiting_ack,
955
974
}
956
975
}
957
976
977
+ static bool fhss_data_tx_fail_callback (const fhss_api_t * api , uint8_t handle , int frame_type )
978
+ {
979
+ fhss_structure_t * fhss_structure = fhss_get_object_with_api (api );
980
+ if (!fhss_structure ) {
981
+ return false;
982
+ }
983
+ // Only use channel retries when device is synchronized
984
+ if (fhss_structure -> fhss_state == FHSS_UNSYNCHRONIZED ) {
985
+ return false;
986
+ }
987
+ // Channel retries are disabled -> return
988
+ if (fhss_structure -> fhss_conf .fhss_configuration .fhss_number_of_channel_retries == 0 ) {
989
+ return false;
990
+ }
991
+ // Use channel retries only for data frames
992
+ if (FHSS_DATA_FRAME != frame_type ) {
993
+ return false;
994
+ }
995
+
996
+ fhss_failed_tx_t * fhss_failed_tx = fhss_failed_handle_find (fhss_structure , handle );
997
+ if (fhss_failed_tx ) {
998
+ fhss_failed_tx -> retries_done ++ ;
999
+ if (fhss_failed_tx -> retries_done >= fhss_structure -> fhss_conf .fhss_configuration .fhss_number_of_channel_retries ) {
1000
+ // No more retries. Return false to stop retransmitting.
1001
+ fhss_failed_handle_remove (fhss_structure , handle );
1002
+ return false;
1003
+ }
1004
+ } else {
1005
+ // Create new failure handle and return true to retransmit
1006
+ fhss_failed_handle_add (fhss_structure , handle );
1007
+ }
1008
+ return true;
1009
+ }
1010
+
1011
+ static void fhss_receive_frame_callback (const fhss_api_t * api , uint16_t pan_id , uint8_t * source_address , uint32_t timestamp , uint8_t * synch_info , int frame_type )
1012
+ {
1013
+ fhss_structure_t * fhss_structure = fhss_get_object_with_api (api );
1014
+ if (!fhss_structure ) {
1015
+ return ;
1016
+ }
1017
+ if (FHSS_SYNCH_FRAME == frame_type ) {
1018
+ if ((fhss_structure -> fhss_state == FHSS_UNSYNCHRONIZED ) || fhss_structure -> synch_panid != pan_id ) {
1019
+ fhss_add_beacon_info (fhss_structure , pan_id , source_address , timestamp , synch_info );
1020
+ } else {
1021
+ if (!fhss_compare_with_synch_parent_address (fhss_structure , source_address )) {
1022
+ // Synch parent address needs to be updated in case parent has changed
1023
+ fhss_update_synch_parent_address (fhss_structure );
1024
+ platform_enter_critical ();
1025
+ // Calculate time since the Beacon was received
1026
+ uint32_t elapsed_time = api -> read_timestamp (api ) - timestamp ;
1027
+ // Synchronize to given PAN
1028
+ fhss_beacon_received (fhss_structure , synch_info , elapsed_time );
1029
+ platform_exit_critical ();
1030
+ }
1031
+ }
1032
+ } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type ) {
1033
+ // If current channel is broadcast, we don't need to send another synch info on next broadcast channel.
1034
+ // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle
1035
+ if ((fhss_structure -> fhss_state == FHSS_SYNCHRONIZED ) && (fhss_is_current_channel_broadcast (fhss_structure ) == false)
1036
+ && (fhss_structure -> synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST )) {
1037
+ fhss_structure -> send_synch_info_on_next_broadcast_channel = true;
1038
+ }
1039
+ }
1040
+ }
1041
+
1042
+ static uint16_t fhss_get_retry_period_callback (const fhss_api_t * api , uint8_t * destination_address , uint16_t phy_mtu )
1043
+ {
1044
+ uint16_t retry_period = 0 ;
1045
+ uint16_t random_number = randLIB_get_16bit ();
1046
+ uint16_t rnd_mask ;
1047
+
1048
+ /* Generate retry back-off period. FHSS is using the known synchronization parent info to delay retransmissions upstream.
1049
+ *
1050
+ */
1051
+ if (phy_mtu < 128 ) {
1052
+ // Max. random when PHY MTU below 128 is 6.4ms
1053
+ rnd_mask = 0x7f ;
1054
+ } else if (phy_mtu < 256 ) {
1055
+ // Max. random when PHY MTU below 256 is 12.8ms
1056
+ rnd_mask = 0xff ;
1057
+ } else {
1058
+ // Max. random when PHY MTU above 255 is 25.6ms
1059
+ rnd_mask = 0x1ff ;
1060
+ }
1061
+
1062
+ fhss_structure_t * fhss_structure = fhss_get_object_with_api (api );
1063
+ if (fhss_structure ) {
1064
+ uint32_t datarate = fhss_structure -> datarate ;
1065
+ uint16_t max_tx_length ;
1066
+
1067
+ if (datarate && phy_mtu ) {
1068
+ if (fhss_compare_with_synch_parent_address (fhss_structure , destination_address ) == 0 ) {
1069
+ // E.g. (1000000 / (250000bit/s / 8 bits)) * 255 bytes = 8160us
1070
+ max_tx_length = ((1000000 / (datarate / 8 )) * phy_mtu );
1071
+ /* Retrying upstream: delay the transmission until assumed hidden node has retried downstream:
1072
+ * Static period: max random + max tx length
1073
+ * 50 comes from MAC timer resolution (50us)
1074
+ */
1075
+ retry_period = (rnd_mask + (max_tx_length / 50 ));
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ // Add 1 to not to ever return zero value.
1081
+ retry_period += ((random_number & rnd_mask ) + 1 );
1082
+ return retry_period ;
1083
+ }
1084
+
958
1085
int fhss_set_callbacks (fhss_structure_t * fhss_structure )
959
1086
{
960
1087
// Set external API
961
1088
fhss_structure -> fhss_api -> is_broadcast_channel = & fhss_is_broadcast_channel_cb ;
962
1089
fhss_structure -> fhss_api -> use_broadcast_queue = & fhss_use_broadcast_queue_cb ;
963
1090
fhss_structure -> fhss_api -> tx_handle = & fhss_tx_handle_callback ;
964
1091
fhss_structure -> fhss_api -> check_tx_conditions = & fhss_check_tx_conditions_callback ;
965
- fhss_structure -> fhss_api -> receive_frame = & fhss_receive_frame_cb ;
1092
+ fhss_structure -> fhss_api -> receive_frame = & fhss_receive_frame_callback ;
966
1093
fhss_structure -> fhss_api -> data_tx_done = & fhss_data_tx_done_callback ;
967
- fhss_structure -> fhss_api -> data_tx_fail = & fhss_data_tx_fail_cb ;
1094
+ fhss_structure -> fhss_api -> data_tx_fail = & fhss_data_tx_fail_callback ;
968
1095
fhss_structure -> fhss_api -> synch_state_set = & fhss_handle_state_set ;
969
1096
fhss_structure -> fhss_api -> read_timestamp = & fhss_read_timestamp_cb ;
970
- fhss_structure -> fhss_api -> get_retry_period = & fhss_get_retry_period_cb ;
1097
+ fhss_structure -> fhss_api -> get_retry_period = & fhss_get_retry_period_callback ;
971
1098
fhss_structure -> fhss_api -> write_synch_info = & fhss_write_synch_info_callback ;
972
1099
fhss_structure -> fhss_api -> init_callbacks = & fhss_init_callbacks_cb ;
973
1100
// Set internal API
0 commit comments