Merge pull request #8822 from hasnainvirk/dr0_and_fcnt_issue

LoRaWAN: Mitigating reception issues at lower data rates & FCnt increment after retry exhaustion
pull/9043/head
Cruz Monrreal 2018-12-10 19:35:25 -06:00 committed by GitHub
commit 3875ac18d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 141 additions and 78 deletions

View File

@ -37,5 +37,5 @@ set(unittest-test-sources
)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true -DMBED_CONF_LORA_WAKEUP_TIME=5")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH=8 -DMBED_CONF_LORA_DUTY_CYCLE_ON_JOIN=true -DMBED_CONF_LORA_WAKEUP_TIME=5")

View File

@ -168,9 +168,10 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params,
return LoRaPHY_stub::uint8_value;
}
void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb,
uint32_t rx_error, uint32_t wakeup_time,
uint32_t *window_timeout, int32_t *window_offset)
void LoRaPHY::get_rx_window_params(float t_symbol, uint8_t min_rx_symbols,
float rx_error, float wakeup_time,
uint32_t *window_length, int32_t *window_offset,
uint8_t phy_dr)
{
}

View File

@ -614,6 +614,8 @@ void LoRaWANStack::post_process_tx_with_reception()
_loramac.get_device_class() == CLASS_A ? "A" : "C");
_ctrl_flags &= ~TX_DONE_FLAG;
_ctrl_flags |= RETRY_EXHAUSTED_FLAG;
_loramac.post_process_mcps_req();
make_tx_metadata_available();
state_controller(DEVICE_STATE_STATUS_CHECK);
}
}

View File

@ -166,11 +166,12 @@ void LoRaMac::post_process_mcps_req()
_params.is_node_ack_requested = false;
_mcps_confirmation.ack_received = false;
_mcps_indication.is_ack_recvd = false;
_params.ul_frame_counter++;
_params.adr_ack_counter++;
} else {
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
}
_params.ul_frame_counter++;
_params.adr_ack_counter++;
} else {
//UNCONFIRMED or PROPRIETARY
_params.ul_frame_counter++;

View File

@ -32,8 +32,9 @@ SPDX-License-Identifier: BSD-3-Clause
#define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000
#define CHANNELS_IN_MASK 16
#define MAX_PREAMBLE_LENGTH 8.0f
#define TICK_GRANULARITY_JITTER 1.0f
#define CHANNELS_IN_MASK 16
LoRaPHY::LoRaPHY()
: _radio(NULL),
@ -388,23 +389,56 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params,
return status;
}
double LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth)
float LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth)
{
return ((double)(1 << phy_dr) / (double) bandwidth) * 1000;
// in milliseconds
return ((float)(1 << phy_dr) / (float) bandwidth * 1000);
}
double LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr)
float LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr)
{
return (8.0 / (double) phy_dr); // 1 symbol equals 1 byte
return (8.0f / (float) phy_dr); // 1 symbol equals 1 byte
}
void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb,
uint32_t rx_error, uint32_t wakeup_time,
uint32_t *window_timeout, int32_t *window_offset)
void LoRaPHY::get_rx_window_params(float t_symb, uint8_t min_rx_symb,
float error_fudge, float wakeup_time,
uint32_t *window_length, int32_t *window_offset,
uint8_t phy_dr)
{
// Computed number of symbols
*window_timeout = MAX((uint32_t) ceil(((2 * min_rx_symb - 8) * t_symb + 2 * rx_error) / t_symb), min_rx_symb);
*window_offset = (int32_t) ceil((4.0 * t_symb) - ((*window_timeout * t_symb) / 2.0) - wakeup_time);
float target_rx_window_offset;
float window_len_in_ms;
if (phy_params.fsk_supported && phy_dr == phy_params.max_rx_datarate) {
min_rx_symb = MAX_PREAMBLE_LENGTH;
}
// We wish to be as close as possible to the actual start of data, i.e.,
// we are interested in the preamble symbols which are at the tail of the
// preamble sequence.
target_rx_window_offset = (MAX_PREAMBLE_LENGTH - min_rx_symb) * t_symb; //in ms
// Actual window offset in ms in response to timing error fudge factor and
// radio wakeup/turned around time.
*window_offset = floor(target_rx_window_offset - error_fudge - wakeup_time);
// possible wait for next symbol start if we start inside the preamble
float possible_wait_for_symb_start = MIN(t_symb,
((2 * error_fudge) + wakeup_time + TICK_GRANULARITY_JITTER));
// how early we might start reception relative to transmit start (so negative if before transmit starts)
float earliest_possible_start_time = *window_offset - error_fudge - TICK_GRANULARITY_JITTER;
// time in (ms) we may have to wait for the other side to start transmission
float possible_wait_for_transmit = -earliest_possible_start_time;
// Minimum reception time plus extra time (in ms) we may have turned on before the
// other side started transmission
window_len_in_ms = (min_rx_symb * t_symb) + MAX(possible_wait_for_transmit, possible_wait_for_symb_start);
// Setting the window_length in terms of 'symbols' for LoRa modulation or
// in terms of 'bytes' for FSK
*window_length = (uint32_t) ceil(window_len_in_ms / t_symb);
}
int8_t LoRaPHY::compute_tx_power(int8_t tx_power_idx, float max_eirp,
@ -791,7 +825,7 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols,
uint32_t rx_error,
rx_config_params_t *rx_conf_params)
{
double t_symbol = 0.0;
float t_symbol = 0.0;
// Get the datarate, perform a boundary check
rx_conf_params->datarate = MIN(datarate, phy_params.max_rx_datarate);
@ -811,9 +845,9 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols,
rx_conf_params->frequency = phy_params.channels.channel_list[rx_conf_params->channel].frequency;
}
get_rx_window_params(t_symbol, min_rx_symbols, rx_error, RADIO_WAKEUP_TIME,
&rx_conf_params->window_timeout, &rx_conf_params->window_offset);
get_rx_window_params(t_symbol, min_rx_symbols, (float) rx_error, MBED_CONF_LORA_WAKEUP_TIME,
&rx_conf_params->window_timeout, &rx_conf_params->window_offset,
rx_conf_params->datarate);
}
bool LoRaPHY::rx_config(rx_config_params_t *rx_conf)
@ -847,13 +881,13 @@ bool LoRaPHY::rx_config(rx_config_params_t *rx_conf)
// Radio configuration
if (dr == DR_7 && phy_params.fsk_supported) {
modem = MODEM_FSK;
_radio->set_rx_config(modem, 50000, phy_dr * 1000, 0, 83333, 5,
_radio->set_rx_config(modem, 50000, phy_dr * 1000, 0, 83333, MAX_PREAMBLE_LENGTH,
rx_conf->window_timeout, false, 0, true, 0, 0,
false, rx_conf->is_rx_continuous);
} else {
modem = MODEM_LORA;
_radio->set_rx_config(modem, rx_conf->bandwidth, phy_dr, 1, 0,
MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH,
MAX_PREAMBLE_LENGTH,
rx_conf->window_timeout, false, 0, false, 0, 0,
true, rx_conf->is_rx_continuous);
}
@ -899,8 +933,8 @@ bool LoRaPHY::tx_config(tx_config_params_t *tx_conf, int8_t *tx_power,
// High Speed FSK channel
modem = MODEM_FSK;
_radio->set_tx_config(modem, phy_tx_power, 25000, bandwidth,
phy_dr * 1000, 0, 5, false, true, 0, 0, false,
3000);
phy_dr * 1000, 0, MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH,
false, true, 0, 0, false, 3000);
} else {
modem = MODEM_LORA;
_radio->set_tx_config(modem, phy_tx_power, 0, bandwidth, phy_dr, 1,

View File

@ -202,40 +202,63 @@ public:
/** Computing Receive Windows
*
* For more details please consult the following document, chapter 3.1.2.
* http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
* http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
* The algorithm tries to calculate the length of receive windows (i.e.,
* the minimum time it should remain to acquire a lock on the Preamble
* for synchronization) and the error offset which compensates for the system
* timing errors. Basic idea behind the algorithm is to optimize for the
* reception of last 'min_rx_symbols' symbols out of transmitted Premable
* symbols. The algorithm compensates for the clock drifts, tick granularity
* and system wake up time (from sleep state) by opening the window early for
* the lower SFs. For higher SFs, the symbol time is large enough that we can
* afford to open late (hence the positive offset).
* The table below shows the calculated values for SF7 to SF12 with 125 kHz
* bandwidth.
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* TRxEarly | TRxLate
* | | |
* | | +---+---+---+---+---+---+---+---+
* | | | Latest Rx window |
* | | +---+---+---+---+---+---+---+---+
* | | |
* +----+-----+----------+---------+-------------------------+----------------------+-------------------------+
* | SF | BW (kHz) | rx_error (ms) | wake_up (ms) | min_rx_symbols | window_timeout(symb) | window_offset(ms) |
* +----+-----+----------+---------+-------------------------+----------------------+-------------------------+
* | 7 | 125 | 5 | 5 | 5 | 18 | -7 |
* | 8 | 125 | 5 | 5 | 5 | 10 | -4 |
* | 9 | 125 | 5 | 5 | 5 | 6 | 2 |
* | 10 | 125 | 5 | 5 | 5 | 6 | 14 |
* | 11 | 125 | 5 | 5 | 5 | 6 | 39 |
* | 12 | 125 | 5 | 5 | 5 | 6 | 88 |
* +----+-----+----------+---------+-------------------------+----------------------+-------------------------+
*
* For example for SF7, the receive window will open at downlink start time
* plus the offset calculated and will remain open for the length window_timeout.
*
* Symbol time = 1.024 ms
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* |
* |
* |
* |
* +---+---+---+---+---+---+---+---+
* | 8 Preamble Symbols |
* +---+---+---+---+---+---+---+---+
* | RX Window start time = T +/- Offset
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
* | | | | | | | | | | | | | | | | | | |
* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*
* Similarly for SF12:
*
* Symbol time = 32.768 ms
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
* |
* |
* |
* |
* +---+---+---+---+---+---+---+---+
* | Earliest Rx window |
* | 8 Preamble Symbols |
* +---+---+---+---+---+---+---+---+
* |
* +---+---+---+---+---+---+---+---+
*Downlink preamble 8 symbols | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*
* Worst case Rx window timings
*
* TRxLate = DEFAULT_MIN_RX_SYMBOLS * tSymbol - RADIO_WAKEUP_TIME
* TRxEarly = 8 - DEFAULT_MIN_RX_SYMBOLS * tSymbol - RxWindowTimeout - RADIO_WAKEUP_TIME
*
* TRxLate - TRxEarly = 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
*
* RxOffset = ( TRxLate + TRxEarly ) / 2
*
* RxWindowTimeout = ( 2 * DEFAULT_MIN_RX_SYMBOLS - 8 ) * tSymbol + 2 * DEFAULT_SYSTEM_MAX_RX_ERROR
* RxOffset = 4 * tSymbol - RxWindowTimeout / 2 - RADIO_WAKE_UP_TIME
*
* The minimum value of RxWindowTimeout must be 5 symbols which implies that the system always tolerates at least an error of 1.5 * tSymbol.
* | RX Window start time = T +/- Offset
* +---+---+---+---+---+---+
* | | | | | | |
* +---+---+---+---+---+---+
*/
/*!
* Computes the RX window timeout and offset.
@ -597,9 +620,10 @@ protected:
/**
* Computes the RX window timeout and the RX window offset.
*/
void get_rx_window_params(double t_symbol, uint8_t min_rx_symbols,
uint32_t rx_error, uint32_t wakeup_time,
uint32_t *window_timeout, int32_t *window_offset);
void get_rx_window_params(float t_symbol, uint8_t min_rx_symbols,
float rx_error, float wakeup_time,
uint32_t *window_length, int32_t *window_offset,
uint8_t phy_dr);
/**
* Computes the txPower, based on the max EIRP and the antenna gain.
@ -632,12 +656,12 @@ private:
/**
* Computes the symbol time for LoRa modulation.
*/
double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth);
float compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth);
/**
* Computes the symbol time for FSK modulation.
*/
double compute_symb_timeout_fsk(uint8_t phy_dr);
float compute_symb_timeout_fsk(uint8_t phy_dr);
protected:
LoRaRadio *_radio;

View File

@ -70,24 +70,28 @@
"value": true
},
"max-sys-rx-error": {
"help": "Maximum timing error of the receiver in ms. The receiver will turn on in [-RxError : + RxError]",
"value": 10
"help": "Max. timing error fudge. The receiver will turn on in [-RxError : + RxError]",
"value": 5
},
"wakeup-time": {
"help": "Time in (ms) the platform takes to wakeup from sleep/deep sleep state. This number is platform dependent",
"value": 5
},
"downlink-preamble-length": {
"help": "Number of preamble symbols need to be captured (out of 8) for successful demodulation",
"value": 5
"help": "Number of whole preamble symbols needed to have a firm lock on the signal.",
"value": 5
},
"uplink-preamble-length": {
"help": "Number of preamble symbols to transmit. Must be <= 8",
"value": 8
"help": "Number of preamble symbols to transmit. Default: 8",
"value": 8
},
"fsb-mask": {
"help": "FSB mask for upstream [Only for US915 & AU915] Check lorawan/FSB_Usage.txt for more details",
"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}"
"help": "FSB mask for upstream [Only for US915 & AU915] Check lorawan/FSB_Usage.txt for more details",
"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}"
},
"fsb-mask-china": {
"help": "FSB mask for upstream [CN470 PHY] Check lorawan/FSB_Usage.txt for more details",
"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}"
"help": "FSB mask for upstream [CN470 PHY] Check lorawan/FSB_Usage.txt for more details",
"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}"
}
}
}

View File

@ -44,9 +44,6 @@
typedef uint32_t lorawan_time_t;
#endif
// Radio wake-up time from sleep - unit ms.
#define RADIO_WAKEUP_TIME 1
/*!
* Sets the length of the LoRaMAC footer field.
* Mainly indicates the MIC field length.
@ -1259,8 +1256,8 @@ typedef struct {
/*!
* LoRaMac reception windows delay
* \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
* join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
* \remark normal frame: RxWindowXDelay = ReceiveDelayX - Offset
* join frame : RxWindowXDelay = JoinAcceptDelayX - Offset
*/
uint32_t rx_window1_delay;
uint32_t rx_window2_delay;