Skip to content

Commit

Permalink
Merge pull request ARMmbed#1803 from ARMmbed/IOTTHD-2736
Browse files Browse the repository at this point in the history
Iotthd 2736
  • Loading branch information
Jarkko Paso authored Aug 31, 2018
2 parents c6e2457 + 537b60d commit 51f8328
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 46 deletions.
11 changes: 11 additions & 0 deletions source/Service_Libs/fhss/fhss.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#define TRACE_GROUP "fhss"

static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots);
static int fhss_reset(fhss_structure_t *fhss_structure);
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);
Expand Down Expand Up @@ -67,6 +68,7 @@ fhss_structure_t *fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *
}
memset(fhss_struct->bs, 0, sizeof(fhss_bs_t));

fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
fhss_struct->bs->fhss_configuration = *fhss_configuration;
fhss_struct->bs->fhss_stats_ptr = fhss_statistics;
fhss_struct->number_of_channels = channel_count;
Expand Down Expand Up @@ -99,6 +101,15 @@ bool fhss_is_synch_root(fhss_structure_t *fhss_structure)
return true;
}

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);
}
}

static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure)
{
if (fhss_structure->bs->current_superframe >= fhss_structure->bs->broadcast_start_superframe) {
Expand Down
14 changes: 1 addition & 13 deletions source/Service_Libs/fhss/fhss_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@

static fhss_structure_t *fhss_struct = NULL;

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 void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type);
static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type);

Expand All @@ -52,7 +50,6 @@ fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_
memset(fhss_struct, 0, sizeof(fhss_structure_t));
fhss_struct->fhss_api = fhss_api;
fhss_struct->platform_functions = *fhss_timer;
fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
if (!fhss_struct->platform_functions.fhss_resolution_divider) {
fhss_struct->platform_functions.fhss_resolution_divider = 1;
}
Expand All @@ -69,16 +66,7 @@ int8_t fhss_free_instance(fhss_api_t *fhss_api)
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);
}
}

static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id)
fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id)
{
if (timer_id < 0 || !fhss_struct) {
return NULL;
Expand Down
1 change: 1 addition & 0 deletions source/Service_Libs/fhss/fhss_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ struct fhss_structure
uint8_t synch_parent[8];
};

fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id);
fhss_structure_t *fhss_allocate_instance(fhss_api_t *fhss_api, const fhss_timer_t *fhss_timer);
int8_t fhss_free_instance(fhss_api_t *fhss_api);
int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate);
Expand Down
99 changes: 73 additions & 26 deletions source/Service_Libs/fhss/fhss_ws.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ struct ws_ie_t {
uint8_t id;
};

static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots);
static void fhss_ws_update_uc_channel_callback(fhss_structure_t *fhss_structure);
static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay);
static void fhss_ws_start_tx_poll_timer(fhss_structure_t *fhss_structure, uint16_t queue_size, uint8_t channel_dwell_interval);
static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure);
static uint8_t fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure);

fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer)
{
Expand All @@ -83,13 +85,25 @@ fhss_structure_t *fhss_ws_enable(fhss_api_t *fhss_api, const fhss_ws_configurati
}
memset(fhss_struct->ws, 0, sizeof(fhss_ws_t));

fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb);
fhss_struct->ws->fhss_configuration = *fhss_configuration;
fhss_struct->number_of_channels = channel_count;
fhss_struct->own_hop = 0xff;
fhss_set_txrx_slot_length(fhss_struct);
ns_list_init(&fhss_struct->fhss_failed_tx_list);
return fhss_struct;
}

static uint8_t fhss_set_txrx_slot_length(fhss_structure_t *fhss_structure)
{
uint8_t number_of_tx_slots = ((fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / WS_MAX_TXRX_SLOT_LEN_MS) / 2;
if (!number_of_tx_slots) {
return 0;
}
fhss_structure->ws->txrx_slot_length_ms = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / (number_of_tx_slots * 2);
return number_of_tx_slots;
}

static int32_t fhss_ws_calc_bc_channel(fhss_structure_t *fhss_structure)
{
int32_t next_channel = fhss_structure->rx_channel;
Expand Down Expand Up @@ -130,12 +144,37 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
fhss_start_timer(fhss_structure, fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval*1000 - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler);
fhss_structure->ws->is_on_bc_channel = true;
next_channel = fhss_structure->ws->bc_channel = fhss_ws_calc_bc_channel(fhss_structure);

/* Start timer with random timeout to trigger broadcast TX queue poll event.
* Min random is 1/50 of the channel dwell interval.
* Max random is 1/10 of the channel dwell interval.
* Event timer resolution is 50us.
*/
uint32_t bc_dwell_us = fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval*1000;
uint16_t bc_min_random = (bc_dwell_us / 50) / 50;
uint16_t bc_max_random = (bc_dwell_us / 10) / 50;
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(bc_min_random, bc_max_random));
} else {
uint32_t timeout = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) * 1000;
fhss_start_timer(fhss_structure, timeout - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_broadcast_handler);
fhss_structure->ws->is_on_bc_channel = false;
// Should return to own (unicast) listening channel after broadcast channel
next_channel = fhss_structure->rx_channel;
/* Start timer with random timeout to trigger unicast TX queue poll event.
* Min random is 50us.
* Max random is 1/10 of the TX slot length.
* Event timer resolution is 50us.
*/
uint32_t txrx_slot_length_us = fhss_structure->ws->txrx_slot_length_ms * 1000;
uint16_t uc_min_random = 1;
uint16_t uc_max_random = (txrx_slot_length_us / 10) / 50;
bool tx_allowed = fhss_ws_check_tx_allowed(fhss_structure);
if (!tx_allowed) {
uc_min_random += (txrx_slot_length_us)/50;
uc_max_random += (txrx_slot_length_us)/50;
}
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(uc_min_random, uc_max_random));

#ifdef FHSS_CHANNEL_DEBUG
tr_info("%"PRIu32" UC %u", fhss_structure->platform_functions.fhss_get_timestamp(fhss_structure->fhss_api), fhss_structure->rx_channel);
#endif /*FHSS_CHANNEL_DEBUG*/
Expand All @@ -146,8 +185,6 @@ static void fhss_broadcast_handler(const fhss_api_t *fhss_api, uint16_t delay)
fhss_bc_switch();
}
#endif /*FHSS_CHANNEL_DEBUG_CBS*/
fhss_ws_start_tx_poll_timer(fhss_structure, fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true),
fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval);
}

static int own_floor(float value)
Expand All @@ -164,6 +201,28 @@ static int own_ceil(float value)
return ivalue + 1;
}

static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots)
{
(void) slots;
uint16_t queue_size = 0;
fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id);


if (fhss_structure->ws->is_on_bc_channel == true) {
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, true);
} else {
// On unicast, start timer to trigger polling event on next TX slot
uint32_t delay_between_tx_slots_us = fhss_structure->ws->txrx_slot_length_ms*1000*2;
if (delay_between_tx_slots_us < fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_broadcast_handler, fhss_structure->fhss_api)) {
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, delay_between_tx_slots_us/50);
}
queue_size = fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false);
}
if (queue_size) {
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
}
}

static uint32_t fhss_ws_calculate_ufsi(fhss_structure_t *fhss_structure, uint32_t tx_time)
{
uint8_t dwell_time = fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval;
Expand Down Expand Up @@ -348,23 +407,22 @@ static bool fhss_ws_check_tx_allowed(fhss_structure_t *fhss_structure)
if (fhss_structure->ws->is_on_bc_channel == true) {
return true;
}
uint8_t number_of_tx_slots = ((fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / WS_MAX_TXRX_SLOT_LEN_MS) / 2;
uint8_t number_of_tx_slots = fhss_set_txrx_slot_length(fhss_structure);
// Allow transmission when broadcast interval is very short comparing to MAX slot length
if (!number_of_tx_slots) {
return true;
}
uint32_t slot_len_ms = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) / (number_of_tx_slots * 2);
uint32_t remaining_time_ms = fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_broadcast_handler, fhss_structure->fhss_api) / 1000;
uint32_t tx_slot_begin = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (slot_len_ms * (fhss_structure->own_hop & 1));
uint32_t rx_slot_begin = tx_slot_begin - slot_len_ms;
uint32_t tx_slot_begin = (fhss_structure->ws->fhss_configuration.fhss_broadcast_interval - fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) - (fhss_structure->ws->txrx_slot_length_ms * (fhss_structure->own_hop & 1));
uint32_t rx_slot_begin = tx_slot_begin - fhss_structure->ws->txrx_slot_length_ms;
uint8_t n_o_tx_slots = number_of_tx_slots;

while (n_o_tx_slots--) {
if ((remaining_time_ms <= tx_slot_begin) && (remaining_time_ms > rx_slot_begin)) {
return true;
}
tx_slot_begin -= (2*slot_len_ms);
rx_slot_begin = tx_slot_begin - slot_len_ms;
tx_slot_begin -= (2*fhss_structure->ws->txrx_slot_length_ms);
rx_slot_begin = tx_slot_begin - fhss_structure->ws->txrx_slot_length_ms;
}

return false;
Expand Down Expand Up @@ -564,24 +622,12 @@ static void fhss_unicast_handler(const fhss_api_t *fhss_api, uint16_t delay)
timeout = fhss_ws_get_sf_timeout_callback(fhss_structure);
fhss_start_timer(fhss_structure, timeout - (delay * fhss_structure->platform_functions.fhss_resolution_divider), fhss_unicast_handler);
fhss_ws_update_uc_channel_callback(fhss_structure);
fhss_ws_start_tx_poll_timer(fhss_structure, fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false),
fhss_structure->ws->fhss_configuration.fhss_uc_dwell_interval);
}

static void fhss_ws_start_tx_poll_timer(fhss_structure_t *fhss_structure, uint16_t queue_size, uint8_t channel_dwell_interval)
{
if (!queue_size) {
return;
// Unless we have broadcast schedule, we have to poll unicast queue when changing channel. This is randomized by the unicast schedule.
if (!fhss_structure->ws->fhss_configuration.fhss_broadcast_interval || !fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval) {
if (fhss_structure->callbacks.read_tx_queue_size(fhss_structure->fhss_api, false)) {
fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api);
}
}
/* Start timer with random timeout to trigger TX queue poll event.
* Min random is 1/50 of the channel dwell interval.
* Max random is 1/10 of the channel dwell interval.
* Event timer resolution is 50us.
* Divide random with TX queue size to transmit faster when TX queue is growing
*/
uint16_t min_random = ((((uint32_t)channel_dwell_interval * 1000) / 50) / 50) / queue_size;
uint16_t max_random = ((((uint32_t)channel_dwell_interval * 1000) / 10) / 50) / queue_size;
eventOS_callback_timer_start(fhss_structure->fhss_event_timer, randLIB_get_random_in_range(min_random, max_random));
}

int fhss_ws_set_callbacks(fhss_structure_t *fhss_structure)
Expand Down Expand Up @@ -623,6 +669,7 @@ int fhss_ws_set_parent(fhss_structure_t *fhss_structure, const uint8_t eui64[8],
// TODO: Calculate drift error
fhss_structure->ws->fhss_configuration.fhss_bc_dwell_interval = bc_timing_info->broadcast_dwell_interval;
fhss_structure->ws->fhss_configuration.fhss_broadcast_interval = bc_timing_info->broadcast_interval;
fhss_set_txrx_slot_length(fhss_structure);
fhss_structure->ws->bc_slot = bc_timing_info->broadcast_slot + slots_since_reception;

//TODO: support multiple parents
Expand Down
1 change: 1 addition & 0 deletions source/Service_Libs/fhss/fhss_ws.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct fhss_ws
uint8_t bc_channel;
uint16_t uc_slot;
uint16_t bc_slot;
uint32_t txrx_slot_length_ms;
bool is_on_bc_channel;
struct fhss_ws_configuration fhss_configuration;
const struct broadcast_timing_info *parent_bc_info;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,6 @@ bool test_fhss_allocate_instance()
if (NULL == fhss_ptr) {
return false;
}
// Test event timer cb with invalid timer id
fhss_ptr->callbacks.tx_poll = &mac_poll_tx_queue;
ns_timer_stub.cb(-1, 10);
// Test event timer cb with random timer id
ns_timer_stub.cb(1, 10);
// Test event timer cb with valid timer id
ns_timer_stub.cb(0, 10);
// Free allocated instance
fhss_free_instance(&fhss_api);

Expand Down
9 changes: 9 additions & 0 deletions test/nanostack/unittest/stub/fhss_common_stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api)
return &fhss_common_stub.fhss_struct;
}

fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id)
{
if (fhss_common_stub.bool_value == false) {
return NULL;
}
fhss_common_stub.fhss_struct.fhss_event_timer = timer_id;
return &fhss_common_stub.fhss_struct;
}

void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type)
{

Expand Down

0 comments on commit 51f8328

Please sign in to comment.