Skip to content

Commit

Permalink
FHSS: Added common superframe handler
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarkko Paso committed Jan 24, 2018
1 parent a881580 commit 7a21ca1
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 102 deletions.
162 changes: 71 additions & 91 deletions source/Service_Libs/fhss/fhss.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,96 +166,6 @@ int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor)
return -1;
}

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);
const uint32_t time = slots * fhss_structure->platform_functions.fhss_resolution_divider;
return time;
}

void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay)
{
int compensation = 0;
fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api);
if (!fhss_structure) {
return;
}
/* Drift compensation doesn't work with Linux platform */
#ifndef __linux__
// Drift compensation on first superframe
if (fhss_structure->current_superframe == 0) {
/* Idea is to compensate number of drift_compensation (microseconds) on each channel.
* However, fhss_resolution_divider defines the minimum timer resolution.
* E.g. if fhss_resolution_divider = 64, compensate (drift_compensation * 64) on each 64th channel.
*/
if (++fhss_structure->synch_monitor.channel_counter == fhss_structure->platform_functions.fhss_resolution_divider) {
compensation = fhss_structure->synch_monitor.drift_compensation;
fhss_structure->synch_monitor.channel_counter = 0;
}
}
#endif //__linux__
// Restart timer asap to minimize the effect of dynamic execution time of
// the rest of function.
fhss_start_timer(fhss_structure, (fhss_structure->synch_configuration.fhss_superframe_length) - (delay * fhss_structure->platform_functions.fhss_resolution_divider) + (compensation * fhss_structure->platform_functions.fhss_resolution_divider), fhss_superframe_handler);

// check, if the current frame was the last one
if (fhss_structure->current_superframe >= (fhss_structure->synch_configuration.fhss_number_of_superframes - 1)) {

// last superframe has passed, change channel
fhss_structure->current_superframe = 0;
fhss_structure->current_channel_index++;
if (fhss_structure->current_channel_index >= fhss_structure->number_of_channels) {
fhss_structure->synch_infos_sent_counter = 0;
fhss_structure->current_channel_index = 0;
fhss_structure->channel_list_counter++;
// Repeated cycle is started from beginning, reset counter. Don't let the channel_list_counter overflow.
if (fhss_structure->channel_list_counter >= ((uint16_t) fhss_structure->number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) {
fhss_structure->channel_list_counter = 0;
}
// Hop 0 don't have parent
if (fhss_is_synch_root(fhss_structure) == false) {
fhss_trig_event(fhss_structure, FHSS_COMPARE_SYNCH_PARENT);
}
fhss_trig_event(fhss_structure, FHSS_UPDATE_SYNCH_INFO_STORAGE);
}
fhss_update_channel(fhss_structure);
} else {
// bump up the superframe counter
fhss_structure->current_superframe++;
}
if ((fhss_structure->send_synch_info_on_next_broadcast_channel == true) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) {
/* Randomize sending superframe of synchronization frame:
* on first superframe probability is 1/number of superframes
* on second superframe probability is 1/(number of superframes-1)
* on third superframe probability is 1/(number of superframes-2)
* on last superframe probability is 1/1
*/
if (randLIB_get_random_in_range(1, fhss_structure->synch_configuration.fhss_number_of_superframes - fhss_structure->current_superframe) == 1) {
fhss_structure->send_synch_info_on_next_broadcast_channel = false;
fhss_structure->synch_infos_sent_counter++;
fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_FRAME);
}
}
fhss_update_txrx_slots(fhss_structure);
uint16_t queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false) + fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
if ((fhss_structure->tx_allowed == true || fhss_is_current_channel_broadcast(fhss_structure) == true) && queue_size) {
/* Start timer with random timeout to trigger TX queue poll event.
* Max random is half of the superframe length. Event timer resolution is 50us.
* Divide Max random with TX queue size to transmit faster when TX queue is growing
*/
uint16_t max_random = ((fhss_structure->synch_configuration.fhss_superframe_length / 2) / 50) / queue_size;
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(1, max_random));
}
if (fhss_structure->fhss_timeout) {
fhss_structure->fhss_timer += fhss_structure->synch_configuration.fhss_superframe_length;
if (fhss_structure->fhss_timer >= fhss_structure->fhss_timeout) {
fhss_trig_event(fhss_structure, FHSS_TIMER_EVENT);
fhss_structure->fhss_timeout = 0;
fhss_structure->fhss_timer = 0;
}
}
}

int fhss_update_txrx_slots(fhss_structure_t *fhss_structure)
{
uint8_t cur_superframe = fhss_structure->current_superframe;
Expand Down Expand Up @@ -439,7 +349,7 @@ int fhss_sync_with_beacon(fhss_structure_t *fhss_structure,

if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) {
fhss_structure->fhss_state = FHSS_SYNCHRONIZED;
fhss_update_channel(fhss_structure);
fhss_change_to_next_channel(fhss_structure);
}
if (fhss_is_synch_root(fhss_structure) == false) {
// Initially synch drift might be massive. Request first few Beacons more frequently until compensation starts fixing the error.
Expand Down Expand Up @@ -799,3 +709,73 @@ int fhss_handle_state_set(fhss_structure_t *fhss_structure, fhss_states fhss_sta
}
return 0;
}

uint32_t fhss_get_compensation(fhss_structure_t *fhss_structure)
{
uint32_t compensation = 0;
/* Drift compensation doesn't work with Linux platform */
#ifndef __linux__
// Drift compensation on first superframe
if (fhss_structure->current_superframe == 0) {
/* Idea is to compensate number of drift_compensation (microseconds) on each channel.
* However, fhss_resolution_divider defines the minimum timer resolution.
* E.g. if fhss_resolution_divider = 64, compensate (drift_compensation * 64) on each 64th channel.
*/
if (++fhss_structure->synch_monitor.channel_counter == fhss_structure->platform_functions.fhss_resolution_divider) {
compensation = fhss_structure->synch_monitor.drift_compensation;
fhss_structure->synch_monitor.channel_counter = 0;
}
}
#else
(void) fhss_structure;
#endif //__linux__
return compensation;
}

void fhss_superframe_callback(fhss_structure_t *fhss_structure)
{
if ((fhss_structure->send_synch_info_on_next_broadcast_channel == true) && (fhss_is_current_channel_broadcast(fhss_structure) == true)) {
/* Randomize sending superframe of synchronization frame:
* on first superframe probability is 1/number of superframes
* on second superframe probability is 1/(number of superframes-1)
* on third superframe probability is 1/(number of superframes-2)
* on last superframe probability is 1/1
*/
if (randLIB_get_random_in_range(1, fhss_structure->synch_configuration.fhss_number_of_superframes - fhss_structure->current_superframe) == 1) {
fhss_structure->send_synch_info_on_next_broadcast_channel = false;
fhss_structure->synch_infos_sent_counter++;
fhss_structure->callbacks.send_fhss_frame(fhss_structure->fhss_api, FHSS_SYNCH_FRAME);
}
}
fhss_update_txrx_slots(fhss_structure);
uint16_t queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false) + fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
if ((fhss_structure->tx_allowed == true || fhss_is_current_channel_broadcast(fhss_structure) == true) && queue_size) {
/* Start timer with random timeout to trigger TX queue poll event.
* Max random is half of the superframe length. Event timer resolution is 50us.
* Divide Max random with TX queue size to transmit faster when TX queue is growing
*/
uint16_t max_random = ((fhss_structure->synch_configuration.fhss_superframe_length / 2) / 50) / queue_size;
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(1, max_random));
}
}

void fhss_update_channel_callback(fhss_structure_t *fhss_structure)
{
if (fhss_structure->current_channel_index == 0) {
fhss_structure->synch_infos_sent_counter = 0;
if (++fhss_structure->channel_list_counter >= ((uint16_t) fhss_structure->number_of_channels * MAX_SCRAMBLE_TABLE_INDEXES)) {
fhss_structure->channel_list_counter = 0;
}
if (fhss_is_synch_root(fhss_structure) == false) {
fhss_trig_event(fhss_structure, FHSS_COMPARE_SYNCH_PARENT);
}
fhss_trig_event(fhss_structure, FHSS_UPDATE_SYNCH_INFO_STORAGE);
}
// 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);
}
}
}
4 changes: 3 additions & 1 deletion source/Service_Libs/fhss/fhss.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ int fhss_flush_beacon_info_storage(fhss_structure_t *fhss_structure);
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);
void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, uint32_t timestamp);
uint32_t fhss_get_tx_time(fhss_structure_t *fhss_structure, uint16_t bytes_to_send, uint8_t phy_header_length, uint8_t phy_tail_length);
void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay);
uint32_t fhss_get_compensation(fhss_structure_t *fhss_structure);
void fhss_superframe_callback(fhss_structure_t *fhss_structure);
void fhss_update_channel_callback(fhss_structure_t *fhss_structure);
fhss_failed_tx_t *fhss_failed_handle_find(fhss_structure_t *fhss_structure, uint8_t handle);
int fhss_failed_handle_add(fhss_structure_t *fhss_structure, uint8_t handle);
int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle);
Expand Down
2 changes: 1 addition & 1 deletion source/Service_Libs/fhss/fhss_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#define TRACE_GROUP "fhss"

// Enable this flag to use channel traces
//#define FHSS_CHANNEL_DEBUG
// #define FHSS_CHANNEL_DEBUG

static uint8_t fhss_get_bc_index(const fhss_structure_t *fhss_structure);

Expand Down
61 changes: 55 additions & 6 deletions source/Service_Libs/fhss/fhss_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "fhss_config.h"
#include "fhss_common.h"
#include "fhss.h"
#include "fhss_ws.h"
#include "fhss_beacon.h"
#include "fhss_statistics.h"
#include "fhss_channel.h"
Expand Down Expand Up @@ -332,13 +333,61 @@ int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, con
return ret_val;
}

void fhss_update_channel(fhss_structure_t *fhss_structure)
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);
if (fhss_structure->mode == MODE_FHSS) {
fhss_update_channel_callback(fhss_structure);
} else if (fhss_structure->mode == MODE_W_S) {
fhss_ws_update_channel_callback(fhss_structure);
}
}

static void fhss_update_superframe(fhss_structure_t *fhss_structure)
{
if (fhss_structure->mode == MODE_FHSS) {
fhss_superframe_callback(fhss_structure);
} else if (fhss_structure->mode == MODE_W_S) {
fhss_ws_superframe_callback(fhss_structure);
}
}

void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay)
{
uint32_t compensation = 0;
fhss_structure_t *fhss_structure = fhss_get_object_with_api(fhss_api);
if (!fhss_structure) {
return;
}

if (fhss_structure->current_superframe == 0) {
if (fhss_structure->mode == MODE_FHSS) {
compensation = fhss_get_compensation(fhss_structure);
}
}

fhss_start_timer(fhss_structure, (fhss_structure->synch_configuration.fhss_superframe_length) - (delay * fhss_structure->platform_functions.fhss_resolution_divider) + (compensation * fhss_structure->platform_functions.fhss_resolution_divider), fhss_superframe_handler);

if (fhss_structure->current_superframe++ >= (fhss_structure->synch_configuration.fhss_number_of_superframes - 1)) {
fhss_structure->current_superframe = 0;
if (++fhss_structure->current_channel_index >= fhss_structure->number_of_channels) {
fhss_structure->current_channel_index = 0;
}
fhss_update_channel(fhss_structure);
}
fhss_update_superframe(fhss_structure);
if (fhss_structure->fhss_timeout) {
fhss_structure->fhss_timer += fhss_structure->synch_configuration.fhss_superframe_length;
if (fhss_structure->fhss_timer >= fhss_structure->fhss_timeout) {
fhss_trig_event(fhss_structure, FHSS_TIMER_EVENT);
fhss_structure->fhss_timeout = 0;
fhss_structure->fhss_timer = 0;
}
}
}

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);
const uint32_t time = slots * fhss_structure->platform_functions.fhss_resolution_divider;
return time;
}
4 changes: 1 addition & 3 deletions source/Service_Libs/fhss/fhss_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,4 @@ int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure);
void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type);
int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr);
int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr);


void fhss_update_channel(fhss_structure_t *fhss_structure);
void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay);
11 changes: 11 additions & 0 deletions source/Service_Libs/fhss/fhss_ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,16 @@

int fhss_ws_handle_state_set(fhss_structure_t *fhss_structure, fhss_states fhss_state)
{
fhss_start_timer(fhss_structure, fhss_structure->synch_configuration.fhss_superframe_length, fhss_superframe_handler);
return 0;
}

void fhss_ws_superframe_callback(fhss_structure_t *fhss_structure)
{

}

void fhss_ws_update_channel_callback(fhss_structure_t *fhss_structure)
{

}
2 changes: 2 additions & 0 deletions source/Service_Libs/fhss/fhss_ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
*/

int fhss_ws_handle_state_set(fhss_structure_t *fhss_structure, fhss_states fhss_state);
void fhss_ws_superframe_callback(fhss_structure_t *fhss_structure);
void fhss_ws_update_channel_callback(fhss_structure_t *fhss_structure);
1 change: 1 addition & 0 deletions test/nanostack/unittest/service_libs/fhss/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ TEST_SRC_FILES = \
../../stub/fhss_beacon_tasklet_stub.c \
../../stub/fhss_beacon_stub.c \
../../stub/fhss_statistics_stub.c \
../../stub/fhss_ws_stub.c \
../../stub/ns_timer_stub.c \
../../stub/randLIB_stub.c \
../../stub/event_stub.c \
Expand Down

0 comments on commit 7a21ca1

Please sign in to comment.