@@ -40,6 +40,9 @@ static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure);
4040static bool fhss_is_bc_sending_superframe (fhss_structure_t * fhss_structure );
4141static 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 );
4242static 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 );
4346
4447fhss_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 )
4548{
@@ -195,7 +198,7 @@ static bool fhss_check_tx_allowed(fhss_structure_t *fhss_structure, bool is_bc,
195198 return true;
196199}
197200
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 )
199202{
200203 if (synch_monitor ) {
201204 synch_monitor -> avg_synch_fix = 0 ;
@@ -326,7 +329,7 @@ static int fhss_update_synch_monitor(fhss_structure_t *fhss_structure, const fhs
326329 return retval ;
327330}
328331
329- int fhss_sync_with_beacon (fhss_structure_t * fhss_structure ,
332+ static int fhss_sync_with_beacon (fhss_structure_t * fhss_structure ,
330333 const fhss_synchronization_beacon_payload_s * payload )
331334{
332335 int ret_val = -1 ;
@@ -654,7 +657,7 @@ static int fhss_reset(fhss_structure_t *fhss_structure)
654657 return 0 ;
655658}
656659
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 )
658661{
659662 if (!fhss_structure || !source_address || !synch_info ) {
660663 return -1 ;
@@ -687,7 +690,7 @@ void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, uint32_
687690 }
688691}
689692
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 )
691694{
692695 ns_list_foreach (fhss_failed_tx_t , cur , & fhss_structure -> fhss_failed_tx_list ) {
693696 if (cur -> handle == handle ) {
@@ -697,7 +700,7 @@ fhss_failed_tx_t *fhss_failed_handle_find(fhss_structure_t *fhss_structure, uint
697700 return NULL ;
698701}
699702
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 )
701704{
702705 fhss_failed_tx_t * failed_tx = ns_dyn_mem_alloc (sizeof (fhss_failed_tx_t ));
703706 if (!failed_tx ) {
@@ -710,7 +713,7 @@ int fhss_failed_handle_add(fhss_structure_t *fhss_structure, uint8_t handle)
710713 return 0 ;
711714}
712715
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 )
714717{
715718 fhss_failed_tx_t * failed_tx = fhss_failed_handle_find (fhss_structure , handle );
716719 if (!failed_tx ) {
@@ -721,7 +724,7 @@ int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle)
721724 return 0 ;
722725}
723726
724- void fhss_failed_list_free (fhss_structure_t * fhss_structure )
727+ static void fhss_failed_list_free (fhss_structure_t * fhss_structure )
725728{
726729 for (uint16_t i = 0 ; i < 256 ; i ++ ) {
727730 fhss_failed_handle_remove (fhss_structure , i );
@@ -797,6 +800,22 @@ static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure)
797800 }
798801}
799802
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+
800819static uint32_t fhss_get_sf_timeout_callback (fhss_structure_t * fhss_structure )
801820{
802821 uint32_t compensation = 0 ;
@@ -955,19 +974,127 @@ static void fhss_data_tx_done_callback(const fhss_api_t *api, bool waiting_ack,
955974 }
956975}
957976
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+
9581085int fhss_set_callbacks (fhss_structure_t * fhss_structure )
9591086{
9601087 // Set external API
9611088 fhss_structure -> fhss_api -> is_broadcast_channel = & fhss_is_broadcast_channel_cb ;
9621089 fhss_structure -> fhss_api -> use_broadcast_queue = & fhss_use_broadcast_queue_cb ;
9631090 fhss_structure -> fhss_api -> tx_handle = & fhss_tx_handle_callback ;
9641091 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 ;
9661093 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 ;
9681095 fhss_structure -> fhss_api -> synch_state_set = & fhss_handle_state_set ;
9691096 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 ;
9711098 fhss_structure -> fhss_api -> write_synch_info = & fhss_write_synch_info_callback ;
9721099 fhss_structure -> fhss_api -> init_callbacks = & fhss_init_callbacks_cb ;
9731100 // Set internal API
0 commit comments