EL4121 Embedded System / mbed-os

Dependents:   cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fhss_mac_interface.c Source File

fhss_mac_interface.c

00001 /*
00002  * Copyright (c) 2016-2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include "nsconfig.h"
00018 #include <string.h>
00019 #include "ns_types.h"
00020 #include "fhss_api.h "
00021 #include "fhss_config.h "
00022 #include "Service_Libs/fhss/fhss.h"
00023 #include "Service_Libs/fhss/fhss_channel.h"
00024 #include "Service_Libs/fhss/fhss_beacon.h"
00025 #include "randLIB.h"
00026 #include "ns_trace.h"
00027 
00028 #define TRACE_GROUP "fhss"
00029 
00030 
00031 bool fhss_is_broadcast_channel_cb(const fhss_api_t *api)
00032 {
00033     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00034     if (!fhss_structure) {
00035         return false;
00036     }
00037     // FHSS is unsynchronized, broadcasts allowed
00038     if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) {
00039         return true;
00040     }
00041     return fhss_is_current_channel_broadcast(fhss_structure);
00042 }
00043 
00044 bool fhss_use_broadcast_queue_cb(const fhss_api_t *api, bool is_broadcast_addr, int frame_type)
00045 {
00046     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00047     if (!fhss_structure) {
00048         return false;
00049     }
00050     // Synch requests are always stored in unicast queue
00051     if (frame_type == FHSS_SYNCH_REQUEST_FRAME) {
00052         return false;
00053     }
00054     // Broadcast packets are stored in broadcast queue
00055     return is_broadcast_addr;
00056 }
00057 
00058 int fhss_tx_handle_cb(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint8_t *synch_info, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length)
00059 {
00060     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00061     if (!fhss_structure) {
00062         return -2;
00063     }
00064     // TODO: needs some more logic to push buffer back to queue
00065     if (frame_type == FHSS_DATA_FRAME) {
00066         if (is_broadcast_addr == true) {
00067             if (fhss_is_current_channel_broadcast(fhss_structure) == false) {
00068                 tr_info("Broadcast on UC channel -> Back to queue");
00069                 return -3;
00070             }
00071         }
00072     }
00073     if (frame_type == FHSS_SYNCH_FRAME) {
00074         if (!synch_info) {
00075             return -4;
00076         }
00077         fhss_beacon_build(fhss_structure, synch_info);
00078     } else if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) {
00079         return -1;
00080     }
00081     // If sending Beacon request on parents Unicast channel
00082     if (frame_type == FHSS_SYNCH_REQUEST_FRAME && fhss_structure->fhss_state == FHSS_SYNCHRONIZED) {
00083         fhss_change_to_parent_channel(fhss_structure);
00084     } else if (frame_type == FHSS_DATA_FRAME) {
00085         fhss_change_to_tx_channel(fhss_structure, destination_address);
00086     }
00087     return 0;
00088 }
00089 
00090 bool fhss_check_tx_conditions_cb(const fhss_api_t *api, bool is_broadcast_addr, uint8_t handle, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length)
00091 {
00092     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00093     if (!fhss_structure) {
00094         return false;
00095     }
00096     // This condition will check that message is not sent on bad channel
00097     if (fhss_check_bad_channel(fhss_structure, handle) == false) {
00098         return false;
00099     }
00100 
00101     // This condition will check that broadcast messages are sent only broadcast channels
00102     if (fhss_check_channel_type(fhss_structure, is_broadcast_addr, frame_type) == false) {
00103         return false;
00104     }
00105 
00106     // This condition will check that FHSS is on TX slot and there is enough time to transmit before channel or slot change
00107     if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) {
00108         return false;
00109     }
00110 
00111     return true;
00112 }
00113 
00114 void fhss_receive_frame_cb(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type)
00115 {
00116     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00117     if (!fhss_structure) {
00118         return;
00119     }
00120     if (FHSS_SYNCH_FRAME == frame_type) {
00121         if ((fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) || fhss_structure->synch_panid != pan_id) {
00122             fhss_add_beacon_info(fhss_structure, pan_id, source_address, timestamp, synch_info);
00123         } else {
00124             if (!fhss_compare_with_synch_parent_address(fhss_structure, source_address)) {
00125                 // Synch parent address needs to be updated in case parent has changed
00126                 fhss_update_synch_parent_address(fhss_structure);
00127                 // Calculate time since the Beacon was received
00128                 uint32_t elapsed_time = api->read_timestamp(api) - timestamp;
00129                 // Synchronize to given PAN
00130                 fhss_beacon_received(fhss_structure, synch_info, elapsed_time);
00131             }
00132         }
00133     } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type) {
00134         // If current channel is broadcast, we don't need to send another synch info on next broadcast channel.
00135         // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle
00136         if ((fhss_structure->fhss_state == FHSS_SYNCHRONIZED) && (fhss_is_current_channel_broadcast(fhss_structure) == false)
00137                 && (fhss_structure->synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST)) {
00138             fhss_structure->send_synch_info_on_next_broadcast_channel = true;
00139         }
00140     }
00141 }
00142 
00143 void fhss_data_tx_done_cb(const fhss_api_t *api, bool waiting_ack, bool tx_completed, uint8_t handle)
00144 {
00145     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00146     if (!fhss_structure) {
00147         return;
00148     }
00149     if (waiting_ack == false) {
00150         fhss_change_to_rx_channel(fhss_structure);
00151     }
00152     // Buffer was successfully transmitted. Remove stored failure handle if exists.
00153     if (tx_completed == true) {
00154         fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle);
00155         if (fhss_failed_tx) {
00156             fhss_failed_handle_remove(fhss_structure, handle);
00157         }
00158     }
00159 }
00160 
00161 bool fhss_data_tx_fail_cb(const fhss_api_t *api, uint8_t handle, int frame_type)
00162 {
00163     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00164     if (!fhss_structure) {
00165         return false;
00166     }
00167     // Only use channel retries when device is synchronized
00168     if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) {
00169         return false;
00170     }
00171     // Channel retries are disabled -> return
00172     if (fhss_structure->fhss_configuration.fhss_number_of_channel_retries == 0) {
00173         return false;
00174     }
00175     // Use channel retries only for data frames
00176     if (FHSS_DATA_FRAME != frame_type) {
00177         return false;
00178     }
00179 
00180     fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle);
00181     if (fhss_failed_tx) {
00182         fhss_failed_tx->retries_done++;
00183         if (fhss_failed_tx->retries_done >= fhss_structure->fhss_configuration.fhss_number_of_channel_retries) {
00184             // No more retries. Return false to stop retransmitting.
00185             fhss_failed_handle_remove(fhss_structure, handle);
00186             return false;
00187         }
00188     } else {
00189         // Create new failure handle and return true to retransmit
00190         fhss_failed_handle_add(fhss_structure, handle);
00191     }
00192     return true;
00193 }
00194 
00195 void fhss_synch_state_set_cb(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id)
00196 {
00197     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00198     if (!fhss_structure) {
00199         return;
00200     }
00201 
00202     // State is already set
00203     if (fhss_structure->fhss_state == fhss_state) {
00204         return;
00205     }
00206 
00207     if (fhss_state == FHSS_UNSYNCHRONIZED) {
00208         fhss_down(fhss_structure);
00209     } else {
00210         // Do not synchronize to current pan
00211         if (fhss_structure->synch_panid == pan_id) {
00212             return;
00213         }
00214         uint32_t datarate = fhss_structure->callbacks.read_datarate(api);
00215         fhss_set_datarate(fhss_structure, datarate);
00216         uint8_t mac_address[8];
00217         fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address);
00218         fhss_structure->uc_channel_index = fhss_get_offset(fhss_structure, mac_address);
00219         // Get Beacon info from storage
00220         fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id);
00221         if (beacon_info) {
00222             memcpy(fhss_structure->synch_parent, beacon_info->source_address, 8);
00223             // Calculate time since the Beacon was received
00224             uint32_t elapsed_time = api->read_timestamp(api) - beacon_info->timestamp;
00225             // Synchronize to given PAN
00226             fhss_beacon_received(fhss_structure, beacon_info->synch_info, elapsed_time);
00227             // Delete stored Beacon infos
00228             fhss_flush_beacon_info_storage(fhss_structure);
00229             fhss_structure->synch_panid = pan_id;
00230         } else if (fhss_is_synch_root(fhss_structure) == true) {
00231             // Synch root will start new network
00232             fhss_start_timer(fhss_structure, fhss_structure->synch_configuration.fhss_superframe_length, fhss_superframe_handler);
00233         }
00234     }
00235     fhss_structure->fhss_state = fhss_state;
00236 }
00237 
00238 uint32_t fhss_read_timestamp_cb(const fhss_api_t *api)
00239 {
00240     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00241     if (!fhss_structure) {
00242         return 0;
00243     }
00244     return (fhss_structure->platform_functions.fhss_get_timestamp(api) * fhss_structure->platform_functions.fhss_resolution_divider);
00245 }
00246 
00247 uint16_t fhss_get_retry_period_cb(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu)
00248 {
00249     uint16_t retry_period = 0;
00250     uint16_t random_number = randLIB_get_16bit();
00251     uint16_t rnd_mask;
00252 
00253     /* Generate retry back-off period. FHSS is using the known synchronization parent info to delay retransmissions upstream.
00254      *
00255      */
00256     if (phy_mtu < 128) {
00257         // Max. random when PHY MTU below 128 is 6.4ms
00258         rnd_mask = 0x7f;
00259     } else if (phy_mtu < 256) {
00260         // Max. random when PHY MTU below 256 is 12.8ms
00261         rnd_mask = 0xff;
00262     } else {
00263         // Max. random when PHY MTU above 255 is 25.6ms
00264         rnd_mask = 0x1ff;
00265     }
00266 
00267     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00268     if (fhss_structure) {
00269         uint32_t datarate = fhss_structure->datarate;
00270         uint16_t max_tx_length;
00271 
00272         if (datarate && phy_mtu) {
00273             if (fhss_compare_with_synch_parent_address(fhss_structure, destination_address) == 0) {
00274                 // E.g. (1000000 / (250000bit/s / 8 bits)) * 255 bytes = 8160us
00275                 max_tx_length = ((1000000 / (datarate / 8)) * phy_mtu);
00276                 /* Retrying upstream: delay the transmission until assumed hidden node has retried downstream:
00277                  * Static period: max random + max tx length
00278                  * 50 comes from MAC timer resolution (50us)
00279                  */
00280                 retry_period = (rnd_mask + (max_tx_length / 50));
00281             }
00282         }
00283     }
00284 
00285     // Add 1 to not to ever return zero value.
00286     retry_period += ((random_number & rnd_mask) + 1);
00287     return retry_period;
00288 }
00289 
00290 int fhss_init_callbacks_cb(const fhss_api_t *api, fhss_callback_t *callbacks)
00291 {
00292     fhss_structure_t *fhss_structure = fhss_get_object_with_api(api);
00293     if (!fhss_structure || !callbacks) {
00294         return -1;
00295     }
00296     fhss_structure->callbacks = *callbacks;
00297     return 0;
00298 }