Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_neighbor_class.c Source File

ws_neighbor_class.c

00001 /*
00002  * Copyright (c) 2018-2019, 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 #include "nsconfig.h"
00019 #include <string.h>
00020 #include "ns_types.h"
00021 #include "ns_list.h"
00022 #include "ns_trace.h"
00023 #include "nsdynmemLIB.h"
00024 #include "fhss_config.h "
00025 #include "6LoWPAN/ws/ws_config.h"
00026 #include "6LoWPAN/ws/ws_neighbor_class.h"
00027 #include "6LoWPAN/ws/ws_common.h"
00028 #include "ws_management_api.h"
00029 
00030 #ifdef HAVE_WS
00031 
00032 
00033 #define TRACE_GROUP "wsne"
00034 
00035 
00036 bool ws_neighbor_class_alloc(ws_neighbor_class_t *class_data, uint8_t list_size)
00037 {
00038 
00039     class_data->neigh_info_list  = ns_dyn_mem_alloc(sizeof(ws_neighbor_class_entry_t) * list_size);
00040     if (!class_data->neigh_info_list ) {
00041         return false;
00042     }
00043 
00044     class_data->list_size  = list_size;
00045     ws_neighbor_class_entry_t *list_ptr = class_data->neigh_info_list ;
00046     for (uint8_t i = 0; i < list_size; i++) {
00047         memset(list_ptr, 0, sizeof(ws_neighbor_class_entry_t));
00048         list_ptr->rsl_in = RSL_UNITITIALIZED;
00049         list_ptr->rsl_out = RSL_UNITITIALIZED;
00050         list_ptr++;
00051     }
00052     return true;
00053 }
00054 
00055 
00056 void ws_neighbor_class_dealloc(ws_neighbor_class_t *class_data)
00057 {
00058     ns_dyn_mem_free(class_data->neigh_info_list );
00059     class_data->neigh_info_list  = NULL;
00060     class_data->list_size  = 0;
00061 }
00062 
00063 ws_neighbor_class_entry_t *ws_neighbor_class_entry_get(ws_neighbor_class_t *class_data, uint8_t attribute_index)
00064 {
00065     if (!class_data->neigh_info_list  || attribute_index >= class_data->list_size ) {
00066         return NULL;
00067     }
00068 
00069     ws_neighbor_class_entry_t *entry = class_data->neigh_info_list  + attribute_index;
00070     return entry;
00071 }
00072 
00073 uint8_t ws_neighbor_class_entry_index_get(ws_neighbor_class_t *class_data, ws_neighbor_class_entry_t *entry)
00074 {
00075     if (!class_data->neigh_info_list ) {
00076         return 0xff;
00077     }
00078     return entry - class_data->neigh_info_list ;
00079 }
00080 
00081 void ws_neighbor_class_entry_remove(ws_neighbor_class_t *class_data, uint8_t attribute_index)
00082 {
00083     ws_neighbor_class_entry_t *entry = ws_neighbor_class_entry_get(class_data, attribute_index);
00084     if (entry) {
00085         memset(entry, 0, sizeof(ws_neighbor_class_entry_t));
00086         entry->rsl_in = RSL_UNITITIALIZED;
00087         entry->rsl_out = RSL_UNITITIALIZED;
00088     }
00089 }
00090 
00091 void ws_neighbor_class_neighbor_unicast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_utt_ie_t *ws_utt, uint32_t timestamp)
00092 {
00093     ws_neighbor->fhss_data.uc_timing_info.utt_rx_timestamp = timestamp;
00094     ws_neighbor->fhss_data.uc_timing_info.ufsi = ws_utt->ufsi;
00095 }
00096 
00097 void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_us_ie_t *ws_us)
00098 {
00099     ws_neighbor->fhss_data.uc_timing_info.unicast_channel_function = ws_us->channel_function;
00100     if (ws_us->channel_function == WS_FIXED_CHANNEL) {
00101         ws_neighbor->fhss_data.uc_timing_info.fixed_channel = ws_us->function.zero.fixed_channel;
00102         ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 1;
00103     } else {
00104         if (ws_us->channel_plan == 0) {
00105             ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class);
00106         } else if (ws_us->channel_plan == 1) {
00107             ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel;
00108         } else {
00109             ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = 0;
00110         }
00111     }
00112     ws_neighbor->fhss_data.uc_timing_info.unicast_dwell_interval = ws_us->dwell_interval;
00113 }
00114 
00115 
00116 void ws_neighbor_class_neighbor_broadcast_time_info_update(ws_neighbor_class_entry_t *ws_neighbor, ws_bt_ie_t *ws_bt_ie, uint32_t timestamp)
00117 {
00118     ws_neighbor->broadcast_timing_info_stored = true;
00119     ws_neighbor->fhss_data.bc_timing_info.bt_rx_timestamp = timestamp;
00120     ws_neighbor->fhss_data.bc_timing_info.broadcast_slot = ws_bt_ie->broadcast_slot_number;
00121     ws_neighbor->fhss_data.bc_timing_info.broadcast_interval_offset = ws_bt_ie->broadcast_interval_offset;
00122 }
00123 
00124 
00125 void ws_neighbor_class_neighbor_broadcast_schedule_set(ws_neighbor_class_entry_t *ws_neighbor, ws_bs_ie_t *ws_bs_ie)
00126 {
00127     ws_neighbor->broadcast_shedule_info_stored = true;
00128     ws_neighbor->fhss_data.bc_timing_info.broadcast_channel_function = ws_bs_ie->channel_function;
00129     if (ws_bs_ie->channel_function == WS_FIXED_CHANNEL) {
00130         ws_neighbor->fhss_data.bc_timing_info.fixed_channel = ws_bs_ie->function.zero.fixed_channel;
00131     }
00132     ws_neighbor->fhss_data.bc_timing_info.broadcast_dwell_interval = ws_bs_ie->dwell_interval;
00133     ws_neighbor->fhss_data.bc_timing_info.broadcast_interval = ws_bs_ie->broadcast_interval;
00134     ws_neighbor->fhss_data.bc_timing_info.broadcast_schedule_id = ws_bs_ie->broadcast_schedule_identifier;
00135 }
00136 
00137 void ws_neighbor_class_rf_sensitivity_calculate(uint8_t rsl_heard)
00138 {
00139     if (DEVICE_MIN_SENS > rsl_heard) {
00140         // We are hearing packet with lower than min_sens dynamically learn the sensitivity
00141         DEVICE_MIN_SENS = rsl_heard;
00142     }
00143 }
00144 
00145 uint8_t ws_neighbor_class_rsl_from_dbm_calculate(int8_t dbm_heard)
00146 {
00147     /* RSL MUST be calculated as the received signal level relative to standard
00148      * thermal noise (290oK) at 1 Hz bandwidth or 174 dBm.
00149      * This provides a range of -174 (0) to +80 (254) dBm.
00150      */
00151 
00152     return dbm_heard + 174;
00153 }
00154 
00155 static void ws_neighbor_class_parent_set_analyze(ws_neighbor_class_entry_t *ws_neighbor)
00156 {
00157     if (ws_neighbor->rsl_in == RSL_UNITITIALIZED ||
00158             ws_neighbor->rsl_out == RSL_UNITITIALIZED) {
00159         ws_neighbor->candidate_parent = false;
00160         return;
00161     }
00162 
00163     if (ws_neighbor_class_rsl_in_get(ws_neighbor) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS) &&
00164             ws_neighbor_class_rsl_out_get(ws_neighbor) < (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD - CAND_PARENT_HYSTERISIS)) {
00165         ws_neighbor->candidate_parent = false;
00166     }
00167 
00168     if (ws_neighbor_class_rsl_in_get(ws_neighbor) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS) &&
00169             ws_neighbor_class_rsl_out_get(ws_neighbor) > (DEVICE_MIN_SENS + CAND_PARENT_THRESHOLD + CAND_PARENT_HYSTERISIS)) {
00170         ws_neighbor->candidate_parent = true;
00171     }
00172 }
00173 
00174 void ws_neighbor_class_rsl_in_calculate(ws_neighbor_class_entry_t *ws_neighbor, int8_t dbm_heard)
00175 {
00176     uint8_t rsl = ws_neighbor_class_rsl_from_dbm_calculate(dbm_heard);
00177     // Calculate minimum sensitivity from heard packets.
00178     ws_neighbor_class_rf_sensitivity_calculate(rsl);
00179     if (ws_neighbor->rsl_in == RSL_UNITITIALIZED) {
00180         ws_neighbor->rsl_in = rsl << WS_RSL_SCALING;
00181     }
00182     ws_neighbor->rsl_in = ws_neighbor->rsl_in + rsl - (ws_neighbor->rsl_in >> WS_RSL_SCALING);
00183     ws_neighbor_class_parent_set_analyze(ws_neighbor);
00184     return;
00185 }
00186 
00187 void ws_neighbor_class_rsl_out_calculate(ws_neighbor_class_entry_t *ws_neighbor, uint8_t rsl_reported)
00188 {
00189     if (ws_neighbor->rsl_out == RSL_UNITITIALIZED) {
00190         ws_neighbor->rsl_out = rsl_reported << WS_RSL_SCALING;
00191     }
00192     ws_neighbor->rsl_out = ws_neighbor->rsl_out + rsl_reported - (ws_neighbor->rsl_out >> WS_RSL_SCALING);
00193     ws_neighbor_class_parent_set_analyze(ws_neighbor);
00194     return;
00195 }
00196 
00197 #endif /* HAVE_WS */
00198