Skip to content

Commit

Permalink
FHSS: Separated common FHSS functions to own module
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarkko Paso committed Jan 17, 2018
1 parent 59b7b76 commit 37425ca
Show file tree
Hide file tree
Showing 11 changed files with 486 additions and 437 deletions.
324 changes: 4 additions & 320 deletions source/Service_Libs/fhss/fhss.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "ns_types.h"
#include "fhss_api.h"
#include "fhss_config.h"
#include "fhss_common.h"
#include "fhss.h"
#include "fhss_channel.h"
#include "channel_list.h"
Expand All @@ -32,116 +33,9 @@

#define TRACE_GROUP "fhss"

// TODO: create linked list
// FHSS object pointer
fhss_structure_t *fhss_struct = 0;

static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure);
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);
static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots);
static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id);
static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j);
static void fhss_update_channel(fhss_structure_t *fhss_structure);
static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor, bool reset_compensation);
static int fhss_reset(fhss_structure_t *fhss_structure);
static void fhss_failed_list_free(fhss_structure_t *fhss_structure);


int8_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)
{
if (!fhss_api || !fhss_configuration || !fhss_timer || fhss_struct) {
tr_err("Invalid FHSS enable configuration");
return -1;
}
int channel_count = channel_list_count_channels(fhss_configuration->channel_mask);
if (channel_count <= 0) {
// There must be at least one configured channel in channel list
return -2;
}
fhss_struct = ns_dyn_mem_alloc(sizeof(fhss_structure_t));
if (!fhss_struct) {
return -3;
}
memset(fhss_struct, 0, sizeof(fhss_structure_t));
fhss_struct->fhss_api = fhss_api;
fhss_struct->fhss_configuration = *fhss_configuration;
fhss_struct->platform_functions = *fhss_timer;
fhss_struct->fhss_stats_ptr = fhss_statistics;
fhss_struct->number_of_channels = channel_count;

// set a invalid id to tasklet_id, so we know that one is not started yet
fhss_struct->beacon_tasklet_id = -1;

if (!fhss_struct->platform_functions.fhss_resolution_divider) {
fhss_struct->platform_functions.fhss_resolution_divider = 1;
}
// Default synch interval is 240 seconds
if (!fhss_struct->fhss_configuration.fhss_max_synch_interval) {
fhss_struct->fhss_configuration.fhss_max_synch_interval = 240;
}
ns_list_init(&fhss_struct->fhss_failed_tx_list);
fhss_struct->own_hop = 0xff;
fhss_reset(fhss_struct);
fhss_reset_synch_monitor(&fhss_struct->synch_monitor, true);
fhss_struct->active_fhss_events = 0;
fhss_struct->fhss_beacon_info_store = NULL;
fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);

if (fhss_beacon_create_tasklet(fhss_struct) < 0) {
// XXX: should we free the fhss_structure here?
return -5;
}

return 0;
}

int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate)
{
if (!fhss_structure) {
return -1;
}
// If datarate is not set, use default 250kbit/s. Datarate is used as divider later.
if (!datarate) {
datarate = 250000;
}
fhss_structure->datarate = datarate;
return 0;
}

int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration)
{
if (!fhss_structure) {
return -1;
}
if (!fhss_synch_configuration) {
return -2;
}
// None of the configurations can be set zero
if( fhss_synch_configuration->fhss_number_of_bc_channels == 0 || fhss_synch_configuration->fhss_number_of_tx_slots == 0
|| fhss_synch_configuration->fhss_number_of_superframes == 0 || fhss_synch_configuration->fhss_superframe_length == 0) {
return -3;
}
// Number of channels must be divisible with the number of broadcast channels.
// Number of superframes must be divisible with the number of TX slots
if (((fhss_structure->number_of_channels % fhss_synch_configuration->fhss_number_of_bc_channels) != 0) ||
((fhss_synch_configuration->fhss_number_of_superframes % fhss_synch_configuration->fhss_number_of_tx_slots) != 0) ||
(fhss_synch_configuration->fhss_number_of_superframes <= fhss_synch_configuration->fhss_number_of_tx_slots)) {
return -4;
}
fhss_structure->synch_configuration = *fhss_synch_configuration;
fhss_structure->own_hop = 0;
return 0;
}

fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api)
{
if (!fhss_api || !fhss_struct) {
return NULL;
}
if (fhss_struct->fhss_api == fhss_api) {
return fhss_struct;
}
return NULL;
}

bool fhss_is_synch_root(fhss_structure_t *fhss_structure)
{
Expand All @@ -151,35 +45,6 @@ bool fhss_is_synch_root(fhss_structure_t *fhss_structure)
return true;
}

void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type)
{
fhss_structure->active_fhss_events |= (1 << event_type);
}

void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type)
{
fhss_structure->active_fhss_events &= ~(1 << event_type);
}

bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type)
{
if (fhss_structure->active_fhss_events & (1 << event_type)) {
return true;
}
return false;
}

static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id)
{
if (timer_id <0 || !fhss_struct) {
return NULL;
}
if (fhss_struct->fhss_event_timer == timer_id) {
return fhss_struct;
}
return NULL;
}

static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure)
{
if (fhss_structure->current_superframe >= fhss_structure->broadcast_start_superframe) {
Expand Down Expand Up @@ -288,95 +153,18 @@ bool fhss_check_tx_allowed(fhss_structure_t *fhss_structure, bool is_bc, uint16_
return true;
}

static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor, bool reset_compensation)
int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor)
{
if (synch_monitor) {
synch_monitor->avg_synch_fix = 0;
// Initialize to -1 instead of 0 to drop the first beacon after network scan (from synch monitoring)
synch_monitor->avg_synch_fix_counter = -1;
if (reset_compensation == true) {
synch_monitor->drift_compensation = 0;
}
synch_monitor->channel_counter = 0;
return 0;
}
return -1;
}

static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure)
{
if (fhss_structure->fhss_scramble_table) {
ns_dyn_mem_free(fhss_structure->fhss_scramble_table);
fhss_structure->fhss_scramble_table = NULL;
}
}

static int fhss_reset(fhss_structure_t *fhss_structure)
{
if (fhss_structure) {
fhss_structure->platform_functions.fhss_timer_stop(fhss_superframe_handler, fhss_structure->fhss_api);
fhss_destroy_scramble_table(fhss_structure);
fhss_struct->synch_panid = 0xffff;
fhss_beacon_periodic_stop(fhss_structure);
fhss_struct->current_superframe = 0;
fhss_struct->current_channel_index = 0;
fhss_struct->channel_list_counter = 0;
if (fhss_is_synch_root(fhss_structure) == false) {
fhss_struct->own_hop = 0xff;
}
fhss_struct->tx_allowed = false;
fhss_struct->synch_interval = (uint32_t) (fhss_struct->fhss_configuration.fhss_max_synch_interval/BEACON_INTERVAL_INIT_DIVIDER) * 1000;
fhss_struct->rx_channel = 0;
fhss_struct->beacons_received_timer = 0;
memset(fhss_struct->synch_parent, 0xff, 8);
fhss_struct->send_synch_info_on_next_broadcast_channel = false;
memset(&fhss_struct->synch_configuration, 0, sizeof(fhss_synch_configuration_t));
fhss_struct->synch_infos_sent_counter = 0;
fhss_struct->broadcast_start_superframe = 0;
fhss_failed_list_free(fhss_structure);
fhss_struct->fhss_state = FHSS_UNSYNCHRONIZED;
return 0;
}
return -1;
}

int fhss_down(fhss_structure_t *fhss_structure)
{
if (fhss_structure) {
fhss_reset(fhss_structure);
fhss_reset_synch_monitor(&fhss_struct->synch_monitor, false);
fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->synch_monitor.drift_compensation);
fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->synch_monitor.avg_synch_fix);
fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->synch_interval / 1000);
return 0;
}
return -1;
}


int8_t fhss_disable(fhss_structure_t *fhss_structure)
{
if (!fhss_structure) {
return -1;
}
fhss_destroy_scramble_table(fhss_structure);
ns_dyn_mem_free(fhss_structure);
fhss_structure = 0;
fhss_struct = 0;
return 0;
}

void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t))
{
if (callback){
// Don't allow starting with zero slots
if (time < fhss_structure->platform_functions.fhss_resolution_divider) {
time = fhss_structure->platform_functions.fhss_resolution_divider;
}
fhss_structure->platform_functions.fhss_timer_start(time / fhss_structure->platform_functions.fhss_resolution_divider, callback, fhss_structure->fhss_api);
}
}

uint32_t fhss_get_remaining_time_to_next_superframe(const fhss_structure_t *fhss_structure)
{
const uint32_t slots = fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_superframe_handler, fhss_structure->fhss_api);
Expand Down Expand Up @@ -467,26 +255,6 @@ void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay)
}
}

int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time)
{
if (!fhss_structure) {
return -1;
}
fhss_structure->fhss_timeout = time;
fhss_structure->fhss_timer = 0;
return 0;
}

int fhss_timeout_stop(fhss_structure_t *fhss_structure)
{
if (!fhss_structure) {
return -1;
}
fhss_structure->fhss_timeout = 0;
fhss_structure->fhss_timer = 0;
return 0;
}

int fhss_update_txrx_slots(fhss_structure_t *fhss_structure)
{
uint8_t cur_superframe = fhss_structure->current_superframe;
Expand Down Expand Up @@ -781,81 +549,6 @@ static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint1
return retval;
}

int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure)
{
uint8_t parent_address[8];

if (!fhss_get_parent_address(fhss_structure, parent_address)) {
memcpy(fhss_structure->synch_parent, parent_address, 8);
return 0;
}
return -1;
}

void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type)
{
if (fhss_read_active_event(fhss_structure, event_type) == true) {
return;
}
arm_event_s event;
event.receiver = fhss_structure->beacon_tasklet_id;
event.sender = 0;
event.event_type = event_type;
event.event_id = 0;
event.data_ptr = fhss_structure;
event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
event.event_data = 0;
if (eventOS_event_send(&event) != 0) {
tr_error("Event trigger failed: eventOS_event_send() failed");
} else {
fhss_set_active_event(fhss_structure, event_type);
}
}

int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr)
{
int ret_val = -1;
if (!fhss_structure || !p_addr) {
return -1;
}

ret_val = fhss_structure->callbacks.read_coord_mac_address(fhss_structure->fhss_api, p_addr);

if (ret_val) {
// Use default synchronization parent when RPL parent not found
memcpy(p_addr, fhss_structure->synch_parent, 8);
ret_val = 0;
}
return ret_val;
}

int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr)
{
int ret_val = -1;
if (!fhss_structure || !source_addr) {
return ret_val;
}
uint8_t parent_address[8];

if (fhss_is_synch_root(fhss_structure) == false) {
if (!fhss_get_parent_address(fhss_structure, parent_address)) {
ret_val = memcmp(source_addr, parent_address, 8);
}
}
return ret_val;
}

static void fhss_update_channel(fhss_structure_t *fhss_structure)
{
// If channel is broadcast channel (true), send event
if (fhss_change_to_next_channel(fhss_structure) == true) {
// Only if device is border router
if (fhss_structure->own_hop == 0) {
fhss_trig_event(fhss_structure, FHSS_BROADCAST_CHANNEL);
}
}
}

static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j)
{
if (i < j) {
Expand Down Expand Up @@ -890,15 +583,6 @@ int fhss_generate_scramble_table(fhss_structure_t *fhss_structure)
return 0;
}

static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
{
(void) slots;
fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id);
if (fhss_structure) {
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
}
}

fhss_beacon_info_t *fhss_get_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id)
{
fhss_beacon_info_t *beacon_info;
Expand Down Expand Up @@ -1056,7 +740,7 @@ int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle)
return 0;
}

static void fhss_failed_list_free(fhss_structure_t *fhss_structure)
void fhss_failed_list_free(fhss_structure_t *fhss_structure)
{
for (uint16_t i = 0; i<256; i++) {
fhss_failed_handle_remove(fhss_structure, i);
Expand Down
Loading

0 comments on commit 37425ca

Please sign in to comment.