mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #7191 from hasnainvirk/precise_timing
LoRaWAN: Fine tuning timing for delays and receive windowspull/7264/head
commit
ba5b5a3870
|
@ -503,6 +503,7 @@ lorawan_status_t LoRaWANStack::acquire_backoff_metadata(int& backoff)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void LoRaWANStack::tx_interrupt_handler(void)
|
void LoRaWANStack::tx_interrupt_handler(void)
|
||||||
{
|
{
|
||||||
|
_tx_timestamp = _loramac.get_current_time();
|
||||||
const int ret = _queue->call(this, &LoRaWANStack::process_transmission);
|
const int ret = _queue->call(this, &LoRaWANStack::process_transmission);
|
||||||
MBED_ASSERT(ret != 0);
|
MBED_ASSERT(ret != 0);
|
||||||
(void)ret;
|
(void)ret;
|
||||||
|
@ -565,7 +566,7 @@ void LoRaWANStack::process_transmission_timeout()
|
||||||
void LoRaWANStack::process_transmission(void)
|
void LoRaWANStack::process_transmission(void)
|
||||||
{
|
{
|
||||||
tr_debug("Transmission completed");
|
tr_debug("Transmission completed");
|
||||||
_loramac.on_radio_tx_done();
|
_loramac.on_radio_tx_done(_tx_timestamp);
|
||||||
|
|
||||||
make_tx_metadata_available();
|
make_tx_metadata_available();
|
||||||
|
|
||||||
|
@ -680,10 +681,12 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size
|
||||||
|
|
||||||
void LoRaWANStack::process_reception_timeout(bool is_timeout)
|
void LoRaWANStack::process_reception_timeout(bool is_timeout)
|
||||||
{
|
{
|
||||||
|
rx_slot_t slot = _loramac.get_current_slot();
|
||||||
|
|
||||||
// when is_timeout == false, a CRC error took place in the received frame
|
// when is_timeout == false, a CRC error took place in the received frame
|
||||||
// we treat that erroneous frame as no frame received at all, hence handle
|
// we treat that erroneous frame as no frame received at all, hence handle
|
||||||
// it exactly as we would handle timeout
|
// it exactly as we would handle timeout
|
||||||
rx_slot_t slot = _loramac.on_radio_rx_timeout(is_timeout);
|
_loramac.on_radio_rx_timeout(is_timeout);
|
||||||
|
|
||||||
if (slot == RX_SLOT_WIN_2 && !_loramac.nwk_joined()) {
|
if (slot == RX_SLOT_WIN_2 && !_loramac.nwk_joined()) {
|
||||||
state_controller(DEVICE_STATE_JOINING);
|
state_controller(DEVICE_STATE_JOINING);
|
||||||
|
@ -851,9 +854,11 @@ void LoRaWANStack::mlme_indication_handler()
|
||||||
#if MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE
|
#if MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE
|
||||||
_automatic_uplink_ongoing = true;
|
_automatic_uplink_ongoing = true;
|
||||||
tr_debug("mlme indication: sending empty uplink to port 0 to acknowledge MAC commands...");
|
tr_debug("mlme indication: sending empty uplink to port 0 to acknowledge MAC commands...");
|
||||||
send_automatic_uplink_message(0);
|
const uint8_t port = 0;
|
||||||
|
const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, port);
|
||||||
|
MBED_ASSERT(ret != 0);
|
||||||
|
(void)ret;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
send_event_to_application(UPLINK_REQUIRED);
|
send_event_to_application(UPLINK_REQUIRED);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
@ -957,8 +962,9 @@ void LoRaWANStack::mcps_indication_handler()
|
||||||
_rx_msg.msg.mcps_indication.type = mcps_indication->type;
|
_rx_msg.msg.mcps_indication.type = mcps_indication->type;
|
||||||
|
|
||||||
// Notify application about received frame..
|
// Notify application about received frame..
|
||||||
tr_debug("Packet Received %d bytes",
|
tr_debug("Packet Received %d bytes, Port=%d",
|
||||||
_rx_msg.msg.mcps_indication.buffer_size);
|
_rx_msg.msg.mcps_indication.buffer_size,
|
||||||
|
mcps_indication->port);
|
||||||
_rx_msg.receive_ready = true;
|
_rx_msg.receive_ready = true;
|
||||||
send_event_to_application(RX_DONE);
|
send_event_to_application(RX_DONE);
|
||||||
}
|
}
|
||||||
|
@ -981,7 +987,9 @@ void LoRaWANStack::mcps_indication_handler()
|
||||||
#if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
|
#if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
|
||||||
tr_debug("Sending empty uplink message...");
|
tr_debug("Sending empty uplink message...");
|
||||||
_automatic_uplink_ongoing = true;
|
_automatic_uplink_ongoing = true;
|
||||||
send_automatic_uplink_message(mcps_indication->port);
|
const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port);
|
||||||
|
MBED_ASSERT(ret != 0);
|
||||||
|
(void)ret;
|
||||||
#else
|
#else
|
||||||
send_event_to_application(UPLINK_REQUIRED);
|
send_event_to_application(UPLINK_REQUIRED);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1354,8 +1362,10 @@ void LoRaWANStack::compliance_test_handler(loramac_mcps_indication_t *mcps_indic
|
||||||
} else if (mcps_indication->buffer_size == 7) {
|
} else if (mcps_indication->buffer_size == 7) {
|
||||||
loramac_mlme_req_t mlme_req;
|
loramac_mlme_req_t mlme_req;
|
||||||
mlme_req.type = MLME_TXCW_1;
|
mlme_req.type = MLME_TXCW_1;
|
||||||
mlme_req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8) | mcps_indication->buffer[2]);
|
mlme_req.cw_tx_mode.timeout = (uint16_t)((mcps_indication->buffer[1] << 8)
|
||||||
mlme_req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16) | (mcps_indication->buffer[4] << 8)
|
| mcps_indication->buffer[2]);
|
||||||
|
mlme_req.cw_tx_mode.frequency = (uint32_t)((mcps_indication->buffer[3] << 16)
|
||||||
|
| (mcps_indication->buffer[4] << 8)
|
||||||
| mcps_indication->buffer[5]) * 100;
|
| mcps_indication->buffer[5]) * 100;
|
||||||
mlme_req.cw_tx_mode.power = mcps_indication->buffer[6];
|
mlme_req.cw_tx_mode.power = mcps_indication->buffer[6];
|
||||||
_loramac.mlme_request(&mlme_req);
|
_loramac.mlme_request(&mlme_req);
|
||||||
|
|
|
@ -548,6 +548,7 @@ private:
|
||||||
volatile bool _ready_for_rx;
|
volatile bool _ready_for_rx;
|
||||||
uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
|
uint8_t _rx_payload[LORAMAC_PHY_MAXPAYLOAD];
|
||||||
events::EventQueue *_queue;
|
events::EventQueue *_queue;
|
||||||
|
lorawan_time_t _tx_timestamp;
|
||||||
|
|
||||||
#if defined(LORAWAN_COMPLIANCE_TEST)
|
#if defined(LORAWAN_COMPLIANCE_TEST)
|
||||||
|
|
||||||
|
|
|
@ -189,41 +189,14 @@ void LoRaMac::post_process_mlme_ind()
|
||||||
_mlme_indication.pending = false;
|
_mlme_indication.pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaMac::on_radio_tx_done(void)
|
lorawan_time_t LoRaMac::get_current_time(void)
|
||||||
{
|
{
|
||||||
lorawan_time_t cur_time = _lora_time.get_current_time();
|
return _lora_time.get_current_time();
|
||||||
|
|
||||||
if (_device_class != CLASS_C) {
|
|
||||||
_lora_phy.put_radio_to_sleep();
|
|
||||||
} else {
|
|
||||||
// this will open a continuous RX2 window until time==RECV_DELAY1
|
|
||||||
if (!_continuous_rx2_window_open) {
|
|
||||||
open_rx2_window();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_params.is_rx_window_enabled == true) {
|
rx_slot_t LoRaMac::get_current_slot(void)
|
||||||
// start timer after which rx1_window will get opened
|
{
|
||||||
_lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay);
|
return _params.rx_slot;
|
||||||
|
|
||||||
if (_device_class != CLASS_C) {
|
|
||||||
_lora_time.start(_params.timers.rx_window2_timer, _params.rx_window2_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_params.is_node_ack_requested) {
|
|
||||||
_lora_time.start(_params.timers.ack_timeout_timer,
|
|
||||||
_params.rx_window2_delay + _lora_phy.get_ack_timeout());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
|
||||||
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
_params.last_channel_idx = _params.channel;
|
|
||||||
|
|
||||||
_lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, cur_time);
|
|
||||||
|
|
||||||
_params.timers.aggregated_last_tx_time = cur_time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -656,23 +629,50 @@ void LoRaMac::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_le
|
||||||
_mac_commands.set_batterylevel_callback(battery_level);
|
_mac_commands.set_batterylevel_callback(battery_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp)
|
||||||
|
{
|
||||||
|
if (_device_class == CLASS_C) {
|
||||||
|
// this will open a continuous RX2 window until time==RECV_DELAY1
|
||||||
|
open_rx2_window();
|
||||||
|
} else {
|
||||||
|
_lora_phy.put_radio_to_sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_params.is_rx_window_enabled == true) {
|
||||||
|
lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp;
|
||||||
|
// start timer after which rx1_window will get opened
|
||||||
|
_lora_time.start(_params.timers.rx_window1_timer,
|
||||||
|
_params.rx_window1_delay - time_diff);
|
||||||
|
|
||||||
|
if (_device_class != CLASS_C) {
|
||||||
|
_lora_time.start(_params.timers.rx_window2_timer,
|
||||||
|
_params.rx_window2_delay - time_diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_params.is_node_ack_requested) {
|
||||||
|
_lora_time.start(_params.timers.ack_timeout_timer,
|
||||||
|
(_params.rx_window2_delay - time_diff) +
|
||||||
|
_lora_phy.get_ack_timeout());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK;
|
||||||
|
_mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
_params.last_channel_idx = _params.channel;
|
||||||
|
|
||||||
|
_lora_phy.set_last_tx_done(_params.channel, _is_nwk_joined, timestamp);
|
||||||
|
|
||||||
|
_params.timers.aggregated_last_tx_time = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size,
|
void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size,
|
||||||
int16_t rssi, int8_t snr)
|
int16_t rssi, int8_t snr)
|
||||||
{
|
{
|
||||||
// stop the RX1 timer here if its the first RX slot.
|
if (_device_class == CLASS_C && !_continuous_rx2_window_open) {
|
||||||
// If the MIC will pass we will stop RX2 timer as well later.
|
|
||||||
// If its RX2, stop RX2 timer.
|
|
||||||
if (_params.rx_slot == RX_SLOT_WIN_1) {
|
|
||||||
_lora_time.stop(_params.timers.rx_window1_timer);
|
|
||||||
} else if (_params.rx_slot == RX_SLOT_WIN_2) {
|
|
||||||
_lora_time.stop(_params.timers.rx_window2_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_device_class == CLASS_C) {
|
|
||||||
if (!_continuous_rx2_window_open) {
|
|
||||||
open_rx2_window();
|
open_rx2_window();
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
_lora_time.stop(_params.timers.rx_window1_timer);
|
||||||
_lora_phy.put_radio_to_sleep();
|
_lora_phy.put_radio_to_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,9 +731,11 @@ void LoRaMac::on_radio_tx_timeout(void)
|
||||||
post_process_mcps_req();
|
post_process_mcps_req();
|
||||||
}
|
}
|
||||||
|
|
||||||
rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout)
|
void LoRaMac::on_radio_rx_timeout(bool is_timeout)
|
||||||
{
|
{
|
||||||
if (_device_class != CLASS_C) {
|
if (_device_class == CLASS_C && !_continuous_rx2_window_open) {
|
||||||
|
open_rx2_window();
|
||||||
|
} else {
|
||||||
_lora_phy.put_radio_to_sleep();
|
_lora_phy.put_radio_to_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,12 +765,6 @@ rx_slot_t LoRaMac::on_radio_rx_timeout(bool is_timeout)
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT :
|
LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT :
|
||||||
LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
|
LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_device_class == CLASS_C) {
|
|
||||||
open_rx2_window();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _params.rx_slot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoRaMac::continue_joining_process()
|
bool LoRaMac::continue_joining_process()
|
||||||
|
@ -804,8 +800,8 @@ lorawan_status_t LoRaMac::send_join_request()
|
||||||
loramac_mhdr_t mac_hdr;
|
loramac_mhdr_t mac_hdr;
|
||||||
loramac_frame_ctrl_t fctrl;
|
loramac_frame_ctrl_t fctrl;
|
||||||
|
|
||||||
_params.sys_params.channel_data_rate = _lora_phy.get_alternate_DR(
|
_params.sys_params.channel_data_rate =
|
||||||
_params.join_request_trial_counter + 1);
|
_lora_phy.get_alternate_DR(_params.join_request_trial_counter + 1);
|
||||||
|
|
||||||
mac_hdr.value = 0;
|
mac_hdr.value = 0;
|
||||||
mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
|
mac_hdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
|
||||||
|
@ -857,7 +853,6 @@ void LoRaMac::on_backoff_timer_expiry(void)
|
||||||
void LoRaMac::open_rx1_window(void)
|
void LoRaMac::open_rx1_window(void)
|
||||||
{
|
{
|
||||||
Lock lock(*this);
|
Lock lock(*this);
|
||||||
tr_debug("Opening RX1 Window");
|
|
||||||
_continuous_rx2_window_open = false;
|
_continuous_rx2_window_open = false;
|
||||||
_lora_time.stop(_params.timers.rx_window1_timer);
|
_lora_time.stop(_params.timers.rx_window1_timer);
|
||||||
_params.rx_slot = RX_SLOT_WIN_1;
|
_params.rx_slot = RX_SLOT_WIN_1;
|
||||||
|
@ -878,25 +873,26 @@ void LoRaMac::open_rx1_window(void)
|
||||||
|
|
||||||
_lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous,
|
_lora_phy.setup_rx_window(_params.rx_window1_config.is_rx_continuous,
|
||||||
_params.sys_params.max_rx_win_time);
|
_params.sys_params.max_rx_win_time);
|
||||||
|
|
||||||
|
tr_debug("Opening RX1 Window");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaMac::open_rx2_window()
|
void LoRaMac::open_rx2_window()
|
||||||
{
|
{
|
||||||
Lock lock(*this);
|
Lock lock(*this);
|
||||||
tr_debug("Opening RX2 Window");
|
_continuous_rx2_window_open = true;
|
||||||
_lora_time.stop(_params.timers.rx_window2_timer);
|
_lora_time.stop(_params.timers.rx_window2_timer);
|
||||||
|
|
||||||
_params.rx_window2_config.channel = _params.channel;
|
_params.rx_window2_config.channel = _params.channel;
|
||||||
_params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
|
_params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
|
||||||
_params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
|
_params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
|
||||||
_params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
|
_params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
|
||||||
_params.rx_window2_config.rx_slot = RX_SLOT_WIN_2;
|
_params.rx_window2_config.rx_slot = _params.rx_window2_config.is_rx_continuous ?
|
||||||
|
RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2;
|
||||||
|
|
||||||
if (get_device_class() == CLASS_C) {
|
if (get_device_class() == CLASS_C) {
|
||||||
_continuous_rx2_window_open = true;
|
|
||||||
_params.rx_window2_config.is_rx_continuous = true;
|
_params.rx_window2_config.is_rx_continuous = true;
|
||||||
} else {
|
} else {
|
||||||
_continuous_rx2_window_open = false;
|
|
||||||
_params.rx_window2_config.is_rx_continuous = false;
|
_params.rx_window2_config.is_rx_continuous = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,9 +903,10 @@ void LoRaMac::open_rx2_window()
|
||||||
_lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous,
|
_lora_phy.setup_rx_window(_params.rx_window2_config.is_rx_continuous,
|
||||||
_params.sys_params.max_rx_win_time);
|
_params.sys_params.max_rx_win_time);
|
||||||
|
|
||||||
_params.rx_slot = _params.rx_window2_config.is_rx_continuous ?
|
_params.rx_slot = _params.rx_window2_config.rx_slot;
|
||||||
RX_SLOT_WIN_CLASS_C : RX_SLOT_WIN_2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr_debug("Opening RX2 Window, Frequency = %u", _params.rx_window2_config.frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaMac::on_ack_timeout_timer_event(void)
|
void LoRaMac::on_ack_timeout_timer_event(void)
|
||||||
|
@ -1346,8 +1343,6 @@ void LoRaMac::set_device_class(const device_class_t &device_class,
|
||||||
tr_debug("Changing device class to -> CLASS_C");
|
tr_debug("Changing device class to -> CLASS_C");
|
||||||
open_rx2_window();
|
open_rx2_window();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaMac::setup_link_check_request()
|
void LoRaMac::setup_link_check_request()
|
||||||
|
@ -1556,8 +1551,7 @@ lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t *machdr,
|
||||||
// Update FCtrl field with new value of OptionsLength
|
// Update FCtrl field with new value of OptionsLength
|
||||||
_params.tx_buffer[0x05] = fctrl->value;
|
_params.tx_buffer[0x05] = fctrl->value;
|
||||||
|
|
||||||
const uint8_t *buffer =
|
const uint8_t *buffer = _mac_commands.get_mac_commands_buffer();
|
||||||
_mac_commands.get_mac_commands_buffer();
|
|
||||||
for (i = 0; i < mac_commands_len; i++) {
|
for (i = 0; i < mac_commands_len; i++) {
|
||||||
_params.tx_buffer[pkt_header_len++] = buffer[i];
|
_params.tx_buffer[pkt_header_len++] = buffer[i];
|
||||||
}
|
}
|
||||||
|
@ -2035,8 +2029,7 @@ void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter )
|
||||||
|
|
||||||
void LoRaMac::LoRaMacTestSetDutyCycleOn(bool enable)
|
void LoRaMac::LoRaMacTestSetDutyCycleOn(bool enable)
|
||||||
{
|
{
|
||||||
if(_lora_phy.verify_duty_cycle(enable) == true)
|
if (_lora_phy.verify_duty_cycle(enable) == true) {
|
||||||
{
|
|
||||||
_params.is_dutycycle_on = enable;
|
_params.is_dutycycle_on = enable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -386,7 +386,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* MAC operations upon successful transmission
|
* MAC operations upon successful transmission
|
||||||
*/
|
*/
|
||||||
void on_radio_tx_done(void);
|
void on_radio_tx_done(lorawan_time_t timestamp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MAC operations upon reception
|
* MAC operations upon reception
|
||||||
|
@ -407,7 +407,7 @@ public:
|
||||||
*
|
*
|
||||||
* @return current RX slot
|
* @return current RX slot
|
||||||
*/
|
*/
|
||||||
rx_slot_t on_radio_rx_timeout(bool is_timeout);
|
void on_radio_rx_timeout(bool is_timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles retransmissions of Join requests if an Accept
|
* Handles retransmissions of Join requests if an Accept
|
||||||
|
@ -455,6 +455,16 @@ public:
|
||||||
*/
|
*/
|
||||||
lorawan_status_t clear_tx_pipe(void);
|
lorawan_status_t clear_tx_pipe(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current time
|
||||||
|
*/
|
||||||
|
lorawan_time_t get_current_time(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current receive slot
|
||||||
|
*/
|
||||||
|
rx_slot_t get_current_slot(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These locks trample through to the upper layers and make
|
* These locks trample through to the upper layers and make
|
||||||
* the stack thread safe.
|
* the stack thread safe.
|
||||||
|
|
|
@ -47,15 +47,18 @@ LoRaPHY::~LoRaPHY()
|
||||||
_radio = NULL;
|
_radio = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoRaPHY::mask_bit_test(const uint16_t *mask, unsigned bit) {
|
bool LoRaPHY::mask_bit_test(const uint16_t *mask, unsigned bit)
|
||||||
|
{
|
||||||
return mask[bit / 16] & (1U << (bit % 16));
|
return mask[bit / 16] & (1U << (bit % 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaPHY::mask_bit_set(uint16_t *mask, unsigned bit) {
|
void LoRaPHY::mask_bit_set(uint16_t *mask, unsigned bit)
|
||||||
|
{
|
||||||
mask[bit / 16] |= (1U << (bit % 16));
|
mask[bit / 16] |= (1U << (bit % 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaPHY::mask_bit_clear(uint16_t *mask, unsigned bit) {
|
void LoRaPHY::mask_bit_clear(uint16_t *mask, unsigned bit)
|
||||||
|
{
|
||||||
mask[bit / 16] &= ~(1U << (bit % 16));
|
mask[bit / 16] &= ~(1U << (bit % 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,13 +67,15 @@ void LoRaPHY::set_radio_instance(LoRaRadio& radio)
|
||||||
_radio = &radio;
|
_radio = &radio;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaPHY::put_radio_to_sleep() {
|
void LoRaPHY::put_radio_to_sleep()
|
||||||
|
{
|
||||||
_radio->lock();
|
_radio->lock();
|
||||||
_radio->sleep();
|
_radio->sleep();
|
||||||
_radio->unlock();
|
_radio->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaPHY::put_radio_to_standby() {
|
void LoRaPHY::put_radio_to_standby()
|
||||||
|
{
|
||||||
_radio->lock();
|
_radio->lock();
|
||||||
_radio->standby();
|
_radio->standby();
|
||||||
_radio->unlock();
|
_radio->unlock();
|
||||||
|
@ -129,27 +134,22 @@ uint8_t LoRaPHY::request_new_channel(int8_t channel_id, channel_params_t* new_ch
|
||||||
} else {
|
} else {
|
||||||
new_channel->band = lookup_band_for_frequency(new_channel->frequency);
|
new_channel->band = lookup_band_for_frequency(new_channel->frequency);
|
||||||
switch (add_channel(new_channel, channel_id)) {
|
switch (add_channel(new_channel, channel_id)) {
|
||||||
case LORAWAN_STATUS_OK:
|
case LORAWAN_STATUS_OK: {
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LORAWAN_STATUS_FREQUENCY_INVALID:
|
case LORAWAN_STATUS_FREQUENCY_INVALID: {
|
||||||
{
|
|
||||||
status &= 0xFE;
|
status &= 0xFE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LORAWAN_STATUS_DATARATE_INVALID:
|
case LORAWAN_STATUS_DATARATE_INVALID: {
|
||||||
{
|
|
||||||
status &= 0xFD;
|
status &= 0xFD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LORAWAN_STATUS_FREQ_AND_DR_INVALID:
|
case LORAWAN_STATUS_FREQ_AND_DR_INVALID: {
|
||||||
{
|
|
||||||
status &= 0xFC;
|
status &= 0xFC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
status &= 0xFC;
|
status &= 0xFC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,8 @@ lorawan_time_t LoRaPHY::update_band_timeoff(bool joined, bool duty_cycle,
|
||||||
return next_tx_delay;
|
return next_tx_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t* payload, link_adr_params_t* params)
|
uint8_t LoRaPHY::parse_link_ADR_req(const uint8_t *payload,
|
||||||
|
link_adr_params_t *params)
|
||||||
{
|
{
|
||||||
uint8_t ret_index = 0;
|
uint8_t ret_index = 0;
|
||||||
|
|
||||||
|
@ -700,8 +701,8 @@ void LoRaPHY::apply_cf_list(const uint8_t* payload, uint8_t size)
|
||||||
channel_params_t new_channel;
|
channel_params_t new_channel;
|
||||||
|
|
||||||
// Setup default datarate range
|
// Setup default datarate range
|
||||||
new_channel.dr_range.value = (phy_params.default_max_datarate << 4)
|
new_channel.dr_range.value = (phy_params.default_max_datarate << 4) |
|
||||||
| phy_params.default_datarate;
|
phy_params.default_datarate;
|
||||||
|
|
||||||
// Size of the optional CF list
|
// Size of the optional CF list
|
||||||
if (size != 16) {
|
if (size != 16) {
|
||||||
|
@ -960,8 +961,7 @@ uint8_t LoRaPHY::link_ADR_request(adr_req_params_t* link_adr_req,
|
||||||
}
|
}
|
||||||
|
|
||||||
// channel mask applies to first 16 channels
|
// channel mask applies to first 16 channels
|
||||||
if (adr_settings.ch_mask_ctrl == 0 ||
|
if (adr_settings.ch_mask_ctrl == 0 || adr_settings.ch_mask_ctrl == 6) {
|
||||||
adr_settings.ch_mask_ctrl == 6) {
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) {
|
for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) {
|
||||||
|
|
||||||
|
@ -1034,6 +1034,10 @@ uint8_t LoRaPHY::accept_rx_param_setup_req(rx_param_setup_req_t* params)
|
||||||
{
|
{
|
||||||
uint8_t status = 0x07;
|
uint8_t status = 0x07;
|
||||||
|
|
||||||
|
if (lookup_band_for_frequency(params->frequency) < 0) {
|
||||||
|
status &= 0xFE;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify radio frequency
|
// Verify radio frequency
|
||||||
if (_radio->check_rf_frequency(params->frequency) == false) {
|
if (_radio->check_rf_frequency(params->frequency) == false) {
|
||||||
status &= 0xFE; // Channel frequency KO
|
status &= 0xFE; // Channel frequency KO
|
||||||
|
@ -1194,8 +1198,7 @@ void LoRaPHY::calculate_backoff(bool joined, bool last_tx_was_join_req, bool dc_
|
||||||
|
|
||||||
// No back-off if the last frame was not a join request and when the
|
// No back-off if the last frame was not a join request and when the
|
||||||
// duty cycle is not enabled
|
// duty cycle is not enabled
|
||||||
if (dc_enabled == false &&
|
if (dc_enabled == false && last_tx_was_join_req == false) {
|
||||||
last_tx_was_join_req == false) {
|
|
||||||
band_table[band_idx].off_time = 0;
|
band_table[band_idx].off_time = 0;
|
||||||
} else {
|
} else {
|
||||||
// Apply band time-off.
|
// Apply band time-off.
|
||||||
|
@ -1247,8 +1250,8 @@ lorawan_status_t LoRaPHY::set_next_channel(channel_selection_params_t* params,
|
||||||
enabled_channels, &delay_tx);
|
enabled_channels, &delay_tx);
|
||||||
} else {
|
} else {
|
||||||
delay_tx++;
|
delay_tx++;
|
||||||
next_tx_delay = params->aggregate_timeoff
|
next_tx_delay = params->aggregate_timeoff -
|
||||||
- _lora_time.get_elapsed_time(params->last_aggregate_tx_time);
|
_lora_time.get_elapsed_time(params->last_aggregate_tx_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel_count > 0) {
|
if (channel_count > 0) {
|
||||||
|
@ -1272,7 +1275,8 @@ lorawan_status_t LoRaPHY::set_next_channel(channel_selection_params_t* params,
|
||||||
return LORAWAN_STATUS_NO_CHANNEL_FOUND;
|
return LORAWAN_STATUS_NO_CHANNEL_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
lorawan_status_t LoRaPHY::add_channel(const channel_params_t* new_channel, uint8_t id)
|
lorawan_status_t LoRaPHY::add_channel(const channel_params_t *new_channel,
|
||||||
|
uint8_t id)
|
||||||
{
|
{
|
||||||
bool dr_invalid = false;
|
bool dr_invalid = false;
|
||||||
bool freq_invalid = false;
|
bool freq_invalid = false;
|
||||||
|
|
Loading…
Reference in New Issue