Merge pull request #1708 from atiselsts/tsch_enhancements
TSCH enhancements
This commit is contained in:
commit
30e820ffa5
|
@ -86,12 +86,16 @@ timesync_entry_add(int32_t val, uint32_t time_delta)
|
||||||
static void
|
static void
|
||||||
timesync_learn_drift_ticks(uint32_t time_delta_asn, int32_t drift_ticks)
|
timesync_learn_drift_ticks(uint32_t time_delta_asn, int32_t drift_ticks)
|
||||||
{
|
{
|
||||||
/* should fit in 32-bit unsigned integer */
|
/* should fit in a 32-bit integer */
|
||||||
uint32_t time_delta_ticks = time_delta_asn * tsch_timing[tsch_ts_timeslot_length];
|
int32_t time_delta_ticks = time_delta_asn * tsch_timing[tsch_ts_timeslot_length];
|
||||||
int32_t real_drift_ticks = drift_ticks + compensated_ticks;
|
int32_t real_drift_ticks = drift_ticks + compensated_ticks;
|
||||||
int32_t last_drift_ppm = (int32_t)((int64_t)real_drift_ticks * TSCH_DRIFT_UNIT / time_delta_ticks);
|
int32_t last_drift_ppm = (int32_t)((int64_t)real_drift_ticks * TSCH_DRIFT_UNIT / time_delta_ticks);
|
||||||
|
|
||||||
drift_ppm = timesync_entry_add(last_drift_ppm, time_delta_ticks);
|
drift_ppm = timesync_entry_add(last_drift_ppm, time_delta_ticks);
|
||||||
|
|
||||||
|
TSCH_LOG_ADD(tsch_log_message,
|
||||||
|
snprintf(log->message, sizeof(log->message),
|
||||||
|
"drift %ld", drift_ppm / 256));
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Either reset or update the neighbor's drift */
|
/* Either reset or update the neighbor's drift */
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#define TSCH_HOPPING_SEQUENCE_4_16 (uint8_t[]){ 20, 26, 25, 26, 15, 15, 25, 20, 26, 15, 26, 25, 20, 15, 20, 25 }
|
#define TSCH_HOPPING_SEQUENCE_4_16 (uint8_t[]){ 20, 26, 25, 26, 15, 15, 25, 20, 26, 15, 26, 25, 20, 15, 20, 25 }
|
||||||
/* 4 channels, sequence length 4 */
|
/* 4 channels, sequence length 4 */
|
||||||
#define TSCH_HOPPING_SEQUENCE_4_4 (uint8_t[]){ 15, 25, 26, 20 }
|
#define TSCH_HOPPING_SEQUENCE_4_4 (uint8_t[]){ 15, 25, 26, 20 }
|
||||||
|
/* 2 channels, sequence length 2 */
|
||||||
|
#define TSCH_HOPPING_SEQUENCE_2_2 (uint8_t[]){ 20, 25 }
|
||||||
/* 1 channel, sequence length 1 */
|
/* 1 channel, sequence length 1 */
|
||||||
#define TSCH_HOPPING_SEQUENCE_1_1 (uint8_t[]){ 20 }
|
#define TSCH_HOPPING_SEQUENCE_1_1 (uint8_t[]){ 20 }
|
||||||
|
|
||||||
|
@ -120,7 +122,7 @@
|
||||||
#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 10000
|
#define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 10000
|
||||||
|
|
||||||
#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 15000
|
#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 15000
|
||||||
/* Default timeslot timing for platfroms requiring 15ms slots */
|
/* Default timeslot timing for platforms requiring 15ms slots */
|
||||||
|
|
||||||
#define TSCH_DEFAULT_TS_CCA_OFFSET 1800
|
#define TSCH_DEFAULT_TS_CCA_OFFSET 1800
|
||||||
#define TSCH_DEFAULT_TS_CCA 128
|
#define TSCH_DEFAULT_TS_CCA 128
|
||||||
|
@ -182,4 +184,18 @@
|
||||||
#define TSCH_HW_FRAME_FILTERING 1
|
#define TSCH_HW_FRAME_FILTERING 1
|
||||||
#endif /* TSCH_CONF_HW_FRAME_FILTERING */
|
#endif /* TSCH_CONF_HW_FRAME_FILTERING */
|
||||||
|
|
||||||
|
/* Keep radio always on within TSCH timeslot (1) or turn it off between packet and ACK? (0) */
|
||||||
|
#ifdef TSCH_CONF_RADIO_ON_DURING_TIMESLOT
|
||||||
|
#define TSCH_RADIO_ON_DURING_TIMESLOT TSCH_CONF_RADIO_ON_DURING_TIMESLOT
|
||||||
|
#else
|
||||||
|
#define TSCH_RADIO_ON_DURING_TIMESLOT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* How long to scan each channel in the scanning phase */
|
||||||
|
#ifdef TSCH_CONF_CHANNEL_SCAN_DURATION
|
||||||
|
#define TSCH_CHANNEL_SCAN_DURATION TSCH_CONF_CHANNEL_SCAN_DURATION
|
||||||
|
#else
|
||||||
|
#define TSCH_CHANNEL_SCAN_DURATION CLOCK_SECOND
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __TSCH_CONF_H__ */
|
#endif /* __TSCH_CONF_H__ */
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "lib/ringbufindex.h"
|
#include "lib/ringbufindex.h"
|
||||||
#include "net/linkaddr.h"
|
#include "net/linkaddr.h"
|
||||||
#include "net/mac/tsch/tsch-schedule.h"
|
#include "net/mac/tsch/tsch-schedule.h"
|
||||||
|
#include "net/mac/mac.h"
|
||||||
|
|
||||||
/******** Configuration *******/
|
/******** Configuration *******/
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ tsch_rpl_callback_leaving_network(void)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Set TSCH EB period based on current RPL DIO period.
|
/* Set TSCH EB period based on current RPL DIO period.
|
||||||
* To use, set #define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_new_dio_interval */
|
* To use, set #define RPL_CALLBACK_NEW_DIO_INTERVAL tsch_rpl_callback_new_dio_interval */
|
||||||
void
|
void
|
||||||
tsch_rpl_callback_new_dio_interval(uint8_t dio_interval)
|
tsch_rpl_callback_new_dio_interval(uint8_t dio_interval)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
* \author
|
* \author
|
||||||
* Simon Duquennoy <simonduq@sics.se>
|
* Simon Duquennoy <simonduq@sics.se>
|
||||||
* Beshr Al Nahas <beshr@sics.se>
|
* Beshr Al Nahas <beshr@sics.se>
|
||||||
|
* Atis Elsts <atis.elsts@bristol.ac.uk>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -109,6 +110,18 @@
|
||||||
#define RTIMER_GUARD 2u
|
#define RTIMER_GUARD 2u
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum tsch_radio_state_on_cmd {
|
||||||
|
TSCH_RADIO_CMD_ON_START_OF_TIMESLOT,
|
||||||
|
TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT,
|
||||||
|
TSCH_RADIO_CMD_ON_FORCE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum tsch_radio_state_off_cmd {
|
||||||
|
TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT,
|
||||||
|
TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT,
|
||||||
|
TSCH_RADIO_CMD_OFF_FORCE,
|
||||||
|
};
|
||||||
|
|
||||||
/* A ringbuf storing outgoing packets after they were dequeued.
|
/* A ringbuf storing outgoing packets after they were dequeued.
|
||||||
* Will be processed layer by tsch_tx_process_pending */
|
* Will be processed layer by tsch_tx_process_pending */
|
||||||
struct ringbufindex dequeued_ringbuf;
|
struct ringbufindex dequeued_ringbuf;
|
||||||
|
@ -370,6 +383,68 @@ update_neighbor_state(struct tsch_neighbor *n, struct tsch_packet *p,
|
||||||
return in_queue;
|
return in_queue;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* This function turns on the radio. Its semantics is dependent on
|
||||||
|
* the value of TSCH_RADIO_ON_DURING_TIMESLOT constant:
|
||||||
|
* - if enabled, the radio is turned on at the start of the slot
|
||||||
|
* - if disabled, the radio is turned on within the slot,
|
||||||
|
* directly before the packet Rx guard time and ACK Rx guard time.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
tsch_radio_on(enum tsch_radio_state_on_cmd command)
|
||||||
|
{
|
||||||
|
int do_it = 0;
|
||||||
|
switch(command) {
|
||||||
|
case TSCH_RADIO_CMD_ON_START_OF_TIMESLOT:
|
||||||
|
if(TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||||
|
do_it = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT:
|
||||||
|
if(!TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||||
|
do_it = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TSCH_RADIO_CMD_ON_FORCE:
|
||||||
|
do_it = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(do_it) {
|
||||||
|
NETSTACK_RADIO.on();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/**
|
||||||
|
* This function turns off the radio. In the same way as for tsch_radio_on(),
|
||||||
|
* it depends on the value of TSCH_RADIO_ON_DURING_TIMESLOT constant:
|
||||||
|
* - if enabled, the radio is turned off at the end of the slot
|
||||||
|
* - if disabled, the radio is turned off within the slot,
|
||||||
|
* directly after Tx'ing or Rx'ing a packet or Tx'ing an ACK.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
tsch_radio_off(enum tsch_radio_state_off_cmd command)
|
||||||
|
{
|
||||||
|
int do_it = 0;
|
||||||
|
switch(command) {
|
||||||
|
case TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT:
|
||||||
|
if(TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||||
|
do_it = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT:
|
||||||
|
if(!TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||||
|
do_it = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TSCH_RADIO_CMD_OFF_FORCE:
|
||||||
|
do_it = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(do_it) {
|
||||||
|
NETSTACK_RADIO.off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static
|
static
|
||||||
PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
{
|
{
|
||||||
|
@ -456,7 +531,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
/* delay before CCA */
|
/* delay before CCA */
|
||||||
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, TS_CCA_OFFSET, "cca");
|
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, TS_CCA_OFFSET, "cca");
|
||||||
TSCH_DEBUG_TX_EVENT();
|
TSCH_DEBUG_TX_EVENT();
|
||||||
NETSTACK_RADIO.on();
|
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
|
||||||
/* CCA */
|
/* CCA */
|
||||||
BUSYWAIT_UNTIL_ABS(!(cca_status |= NETSTACK_RADIO.channel_clear()),
|
BUSYWAIT_UNTIL_ABS(!(cca_status |= NETSTACK_RADIO.channel_clear()),
|
||||||
current_slot_start, TS_CCA_OFFSET + TS_CCA);
|
current_slot_start, TS_CCA_OFFSET + TS_CCA);
|
||||||
|
@ -480,7 +555,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
/* limit tx_time to its max value */
|
/* limit tx_time to its max value */
|
||||||
tx_duration = MIN(tx_duration, tsch_timing[tsch_ts_max_tx]);
|
tx_duration = MIN(tx_duration, tsch_timing[tsch_ts_max_tx]);
|
||||||
/* turn tadio off -- will turn on again to wait for ACK if needed */
|
/* turn tadio off -- will turn on again to wait for ACK if needed */
|
||||||
NETSTACK_RADIO.off();
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||||
|
|
||||||
if(mac_tx_status == RADIO_TX_OK) {
|
if(mac_tx_status == RADIO_TX_OK) {
|
||||||
if(!is_broadcast) {
|
if(!is_broadcast) {
|
||||||
|
@ -488,12 +563,12 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
int ack_len;
|
int ack_len;
|
||||||
rtimer_clock_t ack_start_time;
|
rtimer_clock_t ack_start_time;
|
||||||
int is_time_source;
|
int is_time_source;
|
||||||
radio_value_t radio_rx_mode;
|
|
||||||
struct ieee802154_ies ack_ies;
|
struct ieee802154_ies ack_ies;
|
||||||
uint8_t ack_hdrlen;
|
uint8_t ack_hdrlen;
|
||||||
frame802154_t frame;
|
frame802154_t frame;
|
||||||
|
|
||||||
#if TSCH_HW_FRAME_FILTERING
|
#if TSCH_HW_FRAME_FILTERING
|
||||||
|
radio_value_t radio_rx_mode;
|
||||||
/* Entering promiscuous mode so that the radio accepts the enhanced ACK */
|
/* Entering promiscuous mode so that the radio accepts the enhanced ACK */
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
|
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
|
||||||
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode & (~RADIO_RX_MODE_ADDRESS_FILTER));
|
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode & (~RADIO_RX_MODE_ADDRESS_FILTER));
|
||||||
|
@ -502,7 +577,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
|
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
|
||||||
tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck");
|
tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck");
|
||||||
TSCH_DEBUG_TX_EVENT();
|
TSCH_DEBUG_TX_EVENT();
|
||||||
NETSTACK_RADIO.on();
|
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
|
||||||
/* Wait for ACK to come */
|
/* Wait for ACK to come */
|
||||||
BUSYWAIT_UNTIL_ABS(NETSTACK_RADIO.receiving_packet(),
|
BUSYWAIT_UNTIL_ABS(NETSTACK_RADIO.receiving_packet(),
|
||||||
tx_start_time, tx_duration + tsch_timing[tsch_ts_rx_ack_delay] + tsch_timing[tsch_ts_ack_wait]);
|
tx_start_time, tx_duration + tsch_timing[tsch_ts_rx_ack_delay] + tsch_timing[tsch_ts_ack_wait]);
|
||||||
|
@ -514,7 +589,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
|
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
|
||||||
ack_start_time, tsch_timing[tsch_ts_max_ack]);
|
ack_start_time, tsch_timing[tsch_ts_max_ack]);
|
||||||
TSCH_DEBUG_TX_EVENT();
|
TSCH_DEBUG_TX_EVENT();
|
||||||
NETSTACK_RADIO.off();
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||||
|
|
||||||
#if TSCH_HW_FRAME_FILTERING
|
#if TSCH_HW_FRAME_FILTERING
|
||||||
/* Leaving promiscuous mode */
|
/* Leaving promiscuous mode */
|
||||||
|
@ -588,6 +663,8 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT);
|
||||||
|
|
||||||
current_packet->transmissions++;
|
current_packet->transmissions++;
|
||||||
current_packet->ret = mac_tx_status;
|
current_packet->ret = mac_tx_status;
|
||||||
|
|
||||||
|
@ -671,32 +748,26 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
TSCH_DEBUG_RX_EVENT();
|
TSCH_DEBUG_RX_EVENT();
|
||||||
|
|
||||||
/* Start radio for at least guard time */
|
/* Start radio for at least guard time */
|
||||||
NETSTACK_RADIO.on();
|
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
|
||||||
packet_seen = NETSTACK_RADIO.receiving_packet();
|
packet_seen = NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet();
|
||||||
if(!packet_seen) {
|
if(!packet_seen) {
|
||||||
/* Check if receiving within guard time */
|
/* Check if receiving within guard time */
|
||||||
BUSYWAIT_UNTIL_ABS((packet_seen = NETSTACK_RADIO.receiving_packet()),
|
BUSYWAIT_UNTIL_ABS((packet_seen = NETSTACK_RADIO.receiving_packet()),
|
||||||
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait]);
|
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait]);
|
||||||
}
|
}
|
||||||
if(packet_seen) {
|
if(!packet_seen) {
|
||||||
|
/* no packets on air */
|
||||||
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_FORCE);
|
||||||
|
} else {
|
||||||
TSCH_DEBUG_RX_EVENT();
|
TSCH_DEBUG_RX_EVENT();
|
||||||
/* Save packet timestamp */
|
/* Save packet timestamp */
|
||||||
rx_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
|
rx_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
|
||||||
}
|
|
||||||
if(!NETSTACK_RADIO.receiving_packet() && !NETSTACK_RADIO.pending_packet()) {
|
|
||||||
NETSTACK_RADIO.off();
|
|
||||||
/* no packets on air */
|
|
||||||
} else {
|
|
||||||
/* Wait until packet is received, turn radio off */
|
/* Wait until packet is received, turn radio off */
|
||||||
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
|
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
|
||||||
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait] + tsch_timing[tsch_ts_max_tx]);
|
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait] + tsch_timing[tsch_ts_max_tx]);
|
||||||
TSCH_DEBUG_RX_EVENT();
|
TSCH_DEBUG_RX_EVENT();
|
||||||
NETSTACK_RADIO.off();
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||||
|
|
||||||
#if TSCH_RESYNC_WITH_SFD_TIMESTAMPS
|
|
||||||
/* At the end of the reception, get an more accurate estimate of SFD arrival time */
|
|
||||||
NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &rx_start_time, sizeof(rtimer_clock_t));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(NETSTACK_RADIO.pending_packet()) {
|
if(NETSTACK_RADIO.pending_packet()) {
|
||||||
static int frame_valid;
|
static int frame_valid;
|
||||||
|
@ -704,9 +775,9 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
static frame802154_t frame;
|
static frame802154_t frame;
|
||||||
radio_value_t radio_last_rssi;
|
radio_value_t radio_last_rssi;
|
||||||
|
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
|
|
||||||
/* Read packet */
|
/* Read packet */
|
||||||
current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN);
|
current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN);
|
||||||
|
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
|
||||||
current_input->rx_asn = current_asn;
|
current_input->rx_asn = current_asn;
|
||||||
current_input->rssi = (signed)radio_last_rssi;
|
current_input->rssi = (signed)radio_last_rssi;
|
||||||
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
|
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
|
||||||
|
@ -714,6 +785,11 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
frame802154_check_dest_panid(&frame) &&
|
frame802154_check_dest_panid(&frame) &&
|
||||||
frame802154_extract_linkaddr(&frame, &source_address, &destination_address);
|
frame802154_extract_linkaddr(&frame, &source_address, &destination_address);
|
||||||
|
|
||||||
|
#if TSCH_RESYNC_WITH_SFD_TIMESTAMPS
|
||||||
|
/* At the end of the reception, get an more accurate estimate of SFD arrival time */
|
||||||
|
NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &rx_start_time, sizeof(rtimer_clock_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
packet_duration = TSCH_PACKET_DURATION(current_input->len);
|
packet_duration = TSCH_PACKET_DURATION(current_input->len);
|
||||||
|
|
||||||
#if LLSEC802154_ENABLED
|
#if LLSEC802154_ENABLED
|
||||||
|
@ -745,7 +821,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
|
|
||||||
#if TSCH_TIMESYNC_REMOVE_JITTER
|
#if TSCH_TIMESYNC_REMOVE_JITTER
|
||||||
/* remove jitter due to measurement errors */
|
/* remove jitter due to measurement errors */
|
||||||
if(abs(estimated_drift) <= TSCH_TIMESYNC_MEASUREMENT_ERROR) {
|
if(ABS(estimated_drift) <= TSCH_TIMESYNC_MEASUREMENT_ERROR) {
|
||||||
estimated_drift = 0;
|
estimated_drift = 0;
|
||||||
} else if(estimated_drift > 0) {
|
} else if(estimated_drift > 0) {
|
||||||
estimated_drift -= TSCH_TIMESYNC_MEASUREMENT_ERROR;
|
estimated_drift -= TSCH_TIMESYNC_MEASUREMENT_ERROR;
|
||||||
|
@ -784,7 +860,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX, "RxBeforeAck");
|
packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX, "RxBeforeAck");
|
||||||
TSCH_DEBUG_RX_EVENT();
|
TSCH_DEBUG_RX_EVENT();
|
||||||
NETSTACK_RADIO.transmit(ack_len);
|
NETSTACK_RADIO.transmit(ack_len);
|
||||||
NETSTACK_RADIO.off();
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the sender is a time source, proceed to clock drift compensation */
|
/* If the sender is a time source, proceed to clock drift compensation */
|
||||||
|
@ -820,6 +896,8 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
process_poll(&tsch_pending_events_process);
|
process_poll(&tsch_pending_events_process);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(input_queue_drop != 0) {
|
if(input_queue_drop != 0) {
|
||||||
|
@ -860,8 +938,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
uint8_t current_channel;
|
uint8_t current_channel;
|
||||||
|
int is_active_slot;
|
||||||
TSCH_DEBUG_SLOT_START();
|
TSCH_DEBUG_SLOT_START();
|
||||||
tsch_in_slot_operation = 1;
|
tsch_in_slot_operation = 1;
|
||||||
|
/* Reset drift correction */
|
||||||
|
drift_correction = 0;
|
||||||
|
is_drift_correction_used = 0;
|
||||||
/* Get a packet ready to be sent */
|
/* Get a packet ready to be sent */
|
||||||
current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
|
current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
|
||||||
/* There is no packet to send, and this link does not have Rx flag. Instead of doing
|
/* There is no packet to send, and this link does not have Rx flag. Instead of doing
|
||||||
|
@ -870,12 +952,13 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||||
current_link = backup_link;
|
current_link = backup_link;
|
||||||
current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
|
current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
|
||||||
}
|
}
|
||||||
|
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
|
||||||
|
if(is_active_slot) {
|
||||||
/* Hop channel */
|
/* Hop channel */
|
||||||
current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset);
|
current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset);
|
||||||
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
|
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
|
||||||
/* Reset drift correction */
|
/* Turn the radio on already here if configured so; necessary for radios with slow startup */
|
||||||
drift_correction = 0;
|
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
|
||||||
is_drift_correction_used = 0;
|
|
||||||
/* Decide whether it is a TX/RX/IDLE or OFF slot */
|
/* Decide whether it is a TX/RX/IDLE or OFF slot */
|
||||||
/* Actual slot operation */
|
/* Actual slot operation */
|
||||||
if(current_packet != NULL) {
|
if(current_packet != NULL) {
|
||||||
|
@ -886,11 +969,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||||
**/
|
**/
|
||||||
static struct pt slot_tx_pt;
|
static struct pt slot_tx_pt;
|
||||||
PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t));
|
PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t));
|
||||||
} else if((current_link->link_options & LINK_OPTION_RX)) {
|
} else {
|
||||||
/* Listen */
|
/* Listen */
|
||||||
static struct pt slot_rx_pt;
|
static struct pt slot_rx_pt;
|
||||||
PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
|
PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
TSCH_DEBUG_SLOT_END();
|
TSCH_DEBUG_SLOT_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -609,24 +609,25 @@ PT_THREAD(tsch_scan(struct pt *pt))
|
||||||
|
|
||||||
static struct input_packet input_eb;
|
static struct input_packet input_eb;
|
||||||
static struct etimer scan_timer;
|
static struct etimer scan_timer;
|
||||||
|
/* Time when we started scanning on current_channel */
|
||||||
|
static clock_time_t current_channel_since;
|
||||||
|
|
||||||
ASN_INIT(current_asn, 0, 0);
|
ASN_INIT(current_asn, 0, 0);
|
||||||
|
|
||||||
etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY);
|
etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY);
|
||||||
|
current_channel_since = clock_time();
|
||||||
|
|
||||||
while(!tsch_is_associated && !tsch_is_coordinator) {
|
while(!tsch_is_associated && !tsch_is_coordinator) {
|
||||||
/* Hop to any channel offset */
|
/* Hop to any channel offset */
|
||||||
static int current_channel = 0;
|
static uint8_t current_channel = 0;
|
||||||
/* Time when we started scanning on current_channel */
|
|
||||||
static clock_time_t current_channel_since = 0;
|
|
||||||
|
|
||||||
/* We are not coordinator, try to associate */
|
/* We are not coordinator, try to associate */
|
||||||
rtimer_clock_t t0;
|
rtimer_clock_t t0;
|
||||||
int is_packet_pending = 0;
|
int is_packet_pending = 0;
|
||||||
clock_time_t now_seconds = clock_seconds();
|
clock_time_t now_time = clock_time();
|
||||||
|
|
||||||
/* Switch to a (new) channel for scanning */
|
/* Switch to a (new) channel for scanning */
|
||||||
if(current_channel == 0 || now_seconds != current_channel_since) {
|
if(current_channel == 0 || now_time - current_channel_since > TSCH_CHANNEL_SCAN_DURATION) {
|
||||||
/* Pick a channel at random in TSCH_JOIN_HOPPING_SEQUENCE */
|
/* Pick a channel at random in TSCH_JOIN_HOPPING_SEQUENCE */
|
||||||
uint8_t scan_channel = TSCH_JOIN_HOPPING_SEQUENCE[
|
uint8_t scan_channel = TSCH_JOIN_HOPPING_SEQUENCE[
|
||||||
random_rand() % sizeof(TSCH_JOIN_HOPPING_SEQUENCE)];
|
random_rand() % sizeof(TSCH_JOIN_HOPPING_SEQUENCE)];
|
||||||
|
@ -635,7 +636,7 @@ PT_THREAD(tsch_scan(struct pt *pt))
|
||||||
current_channel = scan_channel;
|
current_channel = scan_channel;
|
||||||
PRINTF("TSCH: scanning on channel %u\n", scan_channel);
|
PRINTF("TSCH: scanning on channel %u\n", scan_channel);
|
||||||
}
|
}
|
||||||
current_channel_since = now_seconds;
|
current_channel_since = now_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn radio on and wait for EB */
|
/* Turn radio on and wait for EB */
|
||||||
|
@ -649,12 +650,12 @@ PT_THREAD(tsch_scan(struct pt *pt))
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_packet_pending) {
|
if(is_packet_pending) {
|
||||||
/* Save packet timestamp */
|
|
||||||
NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t0, sizeof(rtimer_clock_t));
|
|
||||||
|
|
||||||
/* Read packet */
|
/* Read packet */
|
||||||
input_eb.len = NETSTACK_RADIO.read(input_eb.payload, TSCH_PACKET_MAX_LEN);
|
input_eb.len = NETSTACK_RADIO.read(input_eb.payload, TSCH_PACKET_MAX_LEN);
|
||||||
|
|
||||||
|
/* Save packet timestamp */
|
||||||
|
NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t0, sizeof(rtimer_clock_t));
|
||||||
|
|
||||||
/* Parse EB and attempt to associate */
|
/* Parse EB and attempt to associate */
|
||||||
PRINTF("TSCH: association: received packet (%u bytes) on channel %u\n", input_eb.len, current_channel);
|
PRINTF("TSCH: association: received packet (%u bytes) on channel %u\n", input_eb.len, current_channel);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue