Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fhss_beacon.c Source File

fhss_beacon.c

00001 /*
00002  * Copyright (c) 2015-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 
00018 
00019 #include "nsconfig.h"
00020 #include "fhss_api.h "
00021 #include "fhss_config.h "
00022 #include "fhss.h"
00023 #include "fhss_beacon.h"
00024 
00025 #include "common_functions.h"
00026 #include <string.h> // memcpy
00027 #include "ns_trace.h"
00028 
00029 #define TRACE_GROUP "fhss"
00030 
00031 // This function should be called just prior actually sending a beacon packet
00032 // to get precise information. Especially the time variables are essential.
00033 int fhss_beacon_update_payload(fhss_structure_t *fhss_structure,
00034         fhss_synchronization_beacon_payload_s *payload)
00035 {
00036 
00037     int ret_val = 0;
00038     if (!fhss_structure || !payload) {
00039         return -1;
00040     }
00041 
00042     const fhss_synch_configuration_t *config = &fhss_structure->synch_configuration;
00043 
00044     payload->channel_index = fhss_structure->current_channel_index;
00045 
00046     payload->sender_unicast_channel = 0;
00047 
00048     payload->current_superframe = fhss_structure->current_superframe;
00049 
00050     // This assumes that the time is always in the range of 0..2**16, which
00051     // should be the case as the superframe length field is also in that range.
00052     payload->remaining_slots = (uint16_t) fhss_get_remaining_time_to_next_superframe(fhss_structure);
00053     payload->channel_list_counter = fhss_structure->channel_list_counter;
00054 
00055     payload->hop_count = fhss_structure->own_hop;
00056     payload->number_of_broadcast_channels = config->fhss_number_of_bc_channels;
00057     payload->number_of_tx_slots = config->fhss_number_of_tx_slots;
00058     payload->time_since_last_beacon = 0; // XXX not available yet
00059     // TODO: Get Beacon length from MAC
00060     uint32_t tx_time = fhss_get_tx_time(fhss_structure, 71, 0, 0);
00061     payload->processing_delay = fhss_structure->fhss_configuration.fhss_tuning_parameters.tx_processing_delay + tx_time;
00062 
00063     payload->superframe_length = config->fhss_superframe_length;
00064 
00065     payload->number_of_superframes_per_channel = config->fhss_number_of_superframes;
00066 
00067     return ret_val;
00068 }
00069 
00070 uint8_t* fhss_beacon_encode_raw(uint8_t* buffer, const fhss_synchronization_beacon_payload_s* source)
00071 {
00072     *buffer++ = FHSS_DATA_START_DELIMETER;
00073     *buffer++ = source->channel_index;
00074     *buffer++ = source->sender_unicast_channel;
00075     buffer = common_write_16_bit(source->current_superframe, buffer);
00076     buffer = common_write_16_bit(source->remaining_slots, buffer);
00077     buffer = common_write_16_bit(source->channel_list_counter, buffer);
00078     *buffer++ = source->hop_count;
00079     *buffer++ = source->number_of_broadcast_channels;
00080     *buffer++ = source->number_of_tx_slots;
00081     buffer = common_write_32_bit(source->time_since_last_beacon, buffer);
00082     buffer = common_write_16_bit(source->processing_delay, buffer);
00083     buffer = common_write_16_bit(source->superframe_length, buffer);
00084     *buffer++ = source->number_of_superframes_per_channel;
00085 
00086     return buffer;
00087 }
00088 
00089 uint8_t fhss_calculate_uc_index(uint8_t channel_index, uint16_t number_of_channels, uint8_t number_of_broadcast_channels)
00090 {
00091     // When channel index is 0, return last unicast index
00092     if (channel_index == 0) {
00093         return (number_of_channels - number_of_broadcast_channels - 1);
00094     }
00095     uint16_t bc_channel_density = (number_of_channels/number_of_broadcast_channels);
00096     return channel_index - (channel_index/bc_channel_density) - 1;
00097 }
00098 
00099 
00100 uint32_t fhss_get_time_to_next_channel_change(uint16_t remaining_slots_to_next_superframe, uint8_t number_of_superframes,
00101         uint8_t current_superframe, uint16_t superframe_length)
00102 {
00103     return remaining_slots_to_next_superframe + ((uint32_t)((number_of_superframes - 1) - current_superframe) * superframe_length);
00104 }
00105 
00106 void fhss_beacon_decode_raw(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer)
00107 {
00108     dest->data_start_delimeter = *buffer++;
00109 
00110     dest->channel_index = *buffer++;
00111     dest->sender_unicast_channel = *buffer++;
00112 
00113     dest->current_superframe = common_read_16_bit(buffer);
00114     buffer += BEACON_FIELD_SIZE(current_superframe);
00115 
00116     dest->remaining_slots = common_read_16_bit(buffer);
00117     buffer += BEACON_FIELD_SIZE(remaining_slots);
00118 
00119     dest->channel_list_counter = common_read_16_bit(buffer);
00120     buffer += BEACON_FIELD_SIZE(channel_list_counter);
00121 
00122     dest->hop_count = *buffer++;
00123     dest->number_of_broadcast_channels = *buffer++;
00124     dest->number_of_tx_slots = *buffer++;
00125 
00126     dest->time_since_last_beacon = common_read_32_bit(buffer);
00127     buffer += BEACON_FIELD_SIZE(time_since_last_beacon);
00128 
00129     dest->processing_delay += common_read_16_bit(buffer);
00130 
00131     buffer += BEACON_FIELD_SIZE(processing_delay);
00132 
00133     dest->superframe_length = common_read_16_bit(buffer);
00134     buffer += BEACON_FIELD_SIZE(superframe_length);
00135 
00136     dest->number_of_superframes_per_channel = *buffer;
00137 }
00138 
00139 // Decode the given raw byte buffer into a struct into dest struct and calculate
00140 // the new values for elapsed_time, channel_index, current_superframe and remaining_slots 
00141 // from current state and given data.
00142 void fhss_beacon_decode(fhss_synchronization_beacon_payload_s* dest, const uint8_t* buffer, uint32_t elapsed_time, uint16_t number_of_channels)
00143 {
00144     fhss_beacon_decode_raw(dest, buffer);
00145 
00146     elapsed_time += dest->processing_delay;
00147 
00148     /* To calculate channel index after beacon scan, following calculation is performed
00149      *
00150      *                           rem. slots to channel change(X)    Channel length (V)
00151      *                              |---------------------|     |-----------------------------------------------|
00152      *    |    RX'd channel index (Y)                     | ... |                      Y+n                      |
00153      * ...|    sf1    |    sf2    |    sf3    |    sf4    | ... |    sf1    |    sf2    |    sf3    |    sf4    |...
00154      *                              ^                                     ^
00155      *                              |beacon received                      |beacon scan done
00156      *                              |-------------------------------------|
00157      *                               measured time after beacon RX'd(Z)
00158      * V = superframe length * number of superframes
00159      * X = remaining slots to superframe change + length of the remaining full superframes to channel change
00160      *
00161      * Y+n = Y + ((Z - X) / V) + 1
00162      *
00163      * Or if (Z < X)
00164      *       Y+n = Y
00165      */
00166 
00167     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);
00168     uint16_t temp_channel_index = dest->channel_index;
00169     if (elapsed_time >= remaining_slots_to_next_channel) {
00170         uint32_t channel_length = (uint32_t) dest->number_of_superframes_per_channel * dest->superframe_length;
00171         temp_channel_index = dest->channel_index + ((elapsed_time - remaining_slots_to_next_channel) / channel_length) + 1;
00172     }
00173     while (temp_channel_index >= number_of_channels) {
00174         temp_channel_index -= number_of_channels;
00175         dest->channel_list_counter++;
00176     }
00177     dest->channel_index = temp_channel_index;
00178     while (dest->channel_list_counter >= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) {
00179         dest->channel_list_counter -= (number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES);
00180     }
00181 
00182     /* To calculate superframe after beacon scan, following calculation is performed
00183      *
00184      *           rem. slots(X)         sf. length(V)
00185      *        |---------------|     |-----------------|
00186      *...| RX'd superframe (Y)| ... |      Y+n        |      Y+n+1       |....
00187      *        ^                                     ^
00188      *        |beacon received                      |beacon scan done
00189      *        |-------------------------------------|
00190      *          measured time after beacon RX'd(Z)
00191      *
00192      * Y+n = Y + ((Z - X) / V) + 1
00193      *
00194      * Or if (Z < X)
00195      *       Y+n = Y
00196      */
00197 
00198     if (elapsed_time >= dest->remaining_slots) {
00199         dest->current_superframe = dest->current_superframe + ((elapsed_time - dest->remaining_slots) / dest->superframe_length) + 1;
00200     }
00201     while (dest->current_superframe >= dest->number_of_superframes_per_channel) {
00202         dest->current_superframe -= dest->number_of_superframes_per_channel;
00203     }
00204 
00205     /* To get the remaining slots after beacon scan, following calculation is performed
00206      *
00207      *         rem. slots(Y)               sf. length(V)    new rem. slots(X)
00208      *        |----------|               |---------------| |-------------|
00209      *...| superframe 1  | superframe 2  | superframe 3  | superframe 4  |...
00210      *        ^                                            ^
00211      *        |beacon received                             |beacon scan done
00212      *        |--------------------------------------------|
00213      *          measured time after beacon RX'd(Z)
00214      *
00215      * X = V - ((Z - Y) % V)
00216      *
00217      * Or if (Z < Y)
00218      *        X = Y - Z
00219      */
00220 
00221     if (elapsed_time < dest->remaining_slots) {
00222         dest->remaining_slots = dest->remaining_slots - elapsed_time;
00223     } else {
00224         dest->remaining_slots = dest->superframe_length - ((elapsed_time - dest->remaining_slots) % dest->superframe_length);
00225     }
00226 
00227 }