PHY Class B handling

Support class b beacon and ping slot rx configuration
feature-lorawan-1-1
Unknown 2019-04-26 13:48:16 -04:00 committed by Antti Kauppila
parent 0a30aeeec2
commit bf6f45a05b
2 changed files with 289 additions and 40 deletions

View File

@ -42,6 +42,13 @@ SPDX-License-Identifier: BSD-3-Clause
#define DEVICE_DOES_NOT_SUPPORT_TIME 0
#define DEVICE_SUPPORTS_TIME 1
#define BEACON_PREAMBLE_LENGTH 10.0f
#define BEACON_COMMON_FRAME_SIZE 15
#define BEACON_BANDWIDTH 500000
#define BEACON_CODING_RATE 1
#define BEACON_CRC_ON false
#define BEACON_FIXED_LEN true
LoRaPHY::LoRaPHY()
: _radio(NULL),
_lora_time(NULL),
@ -414,23 +421,22 @@ float LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr)
}
void LoRaPHY::get_rx_window_params(float t_symb, uint8_t min_rx_symb,
float error_fudge, float wakeup_time,
uint32_t *window_length, uint32_t *window_length_ms,
int32_t *window_offset,
uint8_t phy_dr)
void LoRaPHY::get_rx_window_params(float t_symb, float max_preamble_len,
uint8_t min_rx_symb, float error_fudge,
float wakeup_time, uint32_t *window_length,
int32_t *window_offset, uint8_t phy_dr)
{
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;
min_rx_symb = max_preamble_len;
}
// 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
target_rx_window_offset = (max_preamble_len - 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.
@ -873,6 +879,7 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols,
rx_config_params_t *rx_conf_params)
{
float t_symbol = 0.0f;
float max_preamble_len = MAX_PREAMBLE_LENGTH;
// Get the datarate, perform a boundary check
rx_conf_params->datarate = MIN(datarate, phy_params.max_rx_datarate);
@ -888,32 +895,75 @@ void LoRaPHY::compute_rx_win_params(int8_t datarate, uint8_t min_rx_symbols,
((uint32_t *)phy_params.bandwidths.table)[rx_conf_params->datarate]);
}
if (rx_conf_params->rx_slot == RX_SLOT_WIN_1) {
switch (rx_conf_params->rx_slot) {
case RX_SLOT_WIN_1:
rx_conf_params->frequency = phy_params.channels.channel_list[rx_conf_params->channel].frequency;
break;
case RX_SLOT_BEACON:
max_preamble_len = BEACON_PREAMBLE_LENGTH;
break;
case RX_SLOT_WIN_UNICAST_PING_SLOT:
case RX_SLOT_WIN_MULTICAST_PING_SLOT:
case RX_SLOT_WIN_2:
case RX_SLOT_WIN_CLASS_C:
break;
default:
MBED_ASSERT(false);
}
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_timeout_ms,
&rx_conf_params->window_offset,
get_rx_window_params(t_symbol, max_preamble_len, 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);
}
uint32_t LoRaPHY::get_rx_time_on_air(uint8_t modem, uint16_t pkt_len)
{
uint32_t toa = 0;
_radio->lock();
toa = _radio->time_on_air((radio_modems_t) modem, pkt_len);
_radio->unlock();
return toa;
}
bool LoRaPHY::rx_config(rx_config_params_t *rx_conf)
{
uint8_t dr = rx_conf->datarate;
radio_modems_t modem;
int8_t dr = rx_conf->datarate;
int8_t phy_dr = 0;
uint8_t max_payload = 0;
uint8_t phy_dr = 0;
uint32_t frequency = rx_conf->frequency;
uint16_t preamble_len = MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH;
bool fixed_len = false;
bool iq_invert = true;
_radio->lock();
if (_radio->get_status() != RF_IDLE) {
_radio->unlock();
return false;
}
_radio->unlock();
switch (rx_conf->rx_slot) {
case RX_SLOT_WIN_1:
frequency = get_rx1_frequency(rx_conf->channel);
rx_conf->frequency = frequency;
break;
case RX_SLOT_WIN_UNICAST_PING_SLOT:
case RX_SLOT_WIN_MULTICAST_PING_SLOT:
// Frequency must be set by compute_ping_win_params
MBED_ASSERT(rx_conf->frequency);
frequency = rx_conf->frequency;
break;
case RX_SLOT_BEACON:
// Frequency must be set by compute_beacon_win_params
MBED_ASSERT(rx_conf->frequency);
preamble_len = MBED_CONF_LORA_BEACON_PREAMBLE_LENGTH;
iq_invert = false;
fixed_len = true;
max_payload = BEACON_COMMON_FRAME_SIZE + phy_params.beacon.rfu1_size +
phy_params.beacon.rfu2_size;
break;
case RX_SLOT_WIN_2:
case RX_SLOT_WIN_CLASS_C:
break;
default:
MBED_ASSERT(false);
}
// Read the physical datarate from the datarates table
uint8_t *datarate_table = (uint8_t *) phy_params.datarates.table;
@ -922,6 +972,15 @@ bool LoRaPHY::rx_config(rx_config_params_t *rx_conf)
phy_dr = datarate_table[dr];
// Calculate max payload for datarate
if (rx_conf->rx_slot != RX_SLOT_BEACON) {
if (rx_conf->is_repeater_supported) {
max_payload = payload_with_repeater_table[dr] + LORA_MAC_FRMPAYLOAD_OVERHEAD;
} else {
max_payload = payload_table[dr] + LORA_MAC_FRMPAYLOAD_OVERHEAD;
}
}
_radio->lock();
_radio->set_channel(rx_conf->frequency);
@ -933,20 +992,14 @@ bool LoRaPHY::rx_config(rx_config_params_t *rx_conf)
rx_conf->window_timeout, false, 0, true, 0, 0,
false, rx_conf->is_rx_continuous);
} else {
rx_conf->modem_type = MODEM_LORA;
_radio->set_rx_config((radio_modems_t) rx_conf->modem_type, rx_conf->bandwidth, phy_dr, 1, 0,
MAX_PREAMBLE_LENGTH,
rx_conf->window_timeout, false, 0, false, 0, 0,
true, rx_conf->is_rx_continuous);
modem = MODEM_LORA;
_radio->set_rx_config(MODEM_LORA, rx_conf->bandwidth, phy_dr, 1, 0,
preamble_len,
rx_conf->window_timeout, fixed_len, max_payload, false, 0, 0,
iq_invert, rx_conf->is_rx_continuous);
}
if (rx_conf->is_repeater_supported) {
max_payload = payload_with_repeater_table[dr];
} else {
max_payload = payload_table[dr];
}
_radio->set_max_payload_length((radio_modems_t) rx_conf->modem_type, max_payload + LORA_MAC_FRMPAYLOAD_OVERHEAD);
_radio->set_max_payload_length(modem, max_payload);
_radio->unlock();
@ -1483,3 +1536,116 @@ uint32_t LoRaPHY::get_rejoin_max_count() const
return _rejoin_max_count;
}
uint8_t LoRaPHY::accept_ping_slot_channel_req(uint32_t frequency, uint8_t datarate)
{
uint8_t status = 0;
// A value of 0 instructs the device to use the default configuration
if ((frequency == 0) || (lookup_band_for_frequency(frequency) != -1)) {
status |= 1 << 0;
}
if ((datarate == 0) || verify_rx_datarate(datarate)) {
status |= 1 << 1;
}
if (status == 0x03) {
phy_params.ping_slot_frequency = frequency;
phy_params.ping_slot_datarate = datarate;
}
return status;
}
uint8_t LoRaPHY::accept_beacon_frequency_request(uint32_t frequency)
{
uint8_t status = 0;
// A value of 0 instructs the device to use the default configuration
if ((frequency == 0) || (lookup_band_for_frequency(frequency) != -1)) {
phy_params.beacon.alternate_frequency = frequency;
status |= 1 << 0;
}
return status;
}
void LoRaPHY::get_beacon_rfu_size(uint8_t &rfu1, uint8_t &rfu2)
{
rfu1 = phy_params.beacon.rfu1_size;
rfu2 = phy_params.beacon.rfu2_size;
}
uint32_t LoRaPHY::get_beacon_frequency(uint32_t beacon_time)
{
return phy_params.beacon.default_frequency;
}
void LoRaPHY::compute_beacon_win_params(uint32_t beacon_time, uint8_t min_rx_symbols,
uint32_t rx_error, rx_config_params_t *config)
{
config->datarate = phy_params.beacon.datarate;
// Apply the alternative frequency, if it is available
if (phy_params.beacon.alternate_frequency) {
config->frequency = phy_params.beacon.alternate_frequency;
} else {
config->frequency = get_beacon_frequency(beacon_time);
MBED_ASSERT(config->frequency != 0);
}
compute_rx_win_params(config->datarate, min_rx_symbols, rx_error, config);
}
void LoRaPHY::compute_ping_win_params(uint32_t beacon_time, uint32_t dev_addr,
uint8_t min_rx_symbols, uint32_t rx_error,
rx_config_params_t *config)
{
// Apply the alternative frequency, if it is available
if (phy_params.ping_slot_frequency) {
config->frequency = phy_params.ping_slot_frequency;
} else {
config->frequency = get_ping_slot_frequency(dev_addr, beacon_time);
MBED_ASSERT(config->frequency != 0);
}
// Apply the alternative datarate, if it is available
if (phy_params.ping_slot_datarate) {
config->datarate = phy_params.ping_slot_datarate;
} else {
config->datarate = phy_params.beacon.datarate;
}
compute_rx_win_params(config->datarate, min_rx_symbols, rx_error, config);
}
uint32_t LoRaPHY::get_rx1_frequency(uint8_t channel)
{
return phy_params.channels.channel_list[channel].frequency;
}
uint32_t LoRaPHY::get_ping_slot_frequency(uint32_t dev_addr, uint32_t beacon_time)
{
return phy_params.ping_slot_default_frequency;
}
uint32_t LoRaPHY::compute_beacon_time_on_air()
{
uint8_t beacon_length;
uint8_t phy_dr;
beacon_length = BEACON_COMMON_FRAME_SIZE + phy_params.beacon.rfu1_size +
phy_params.beacon.rfu2_size;
// Read the physical datarate from the datarates table
phy_dr = ((uint8_t *)phy_params.datarates.table)[phy_params.beacon.datarate];
return _radio->lora_time_on_air(BEACON_PREAMBLE_LENGTH,
phy_dr,
BEACON_BANDWIDTH,
BEACON_CODING_RATE,
BEACON_CRC_ON,
BEACON_FIXED_LEN,
beacon_length);
}

View File

@ -414,6 +414,42 @@ public:
*/
void reset_to_default_values(loramac_protocol_params *params, bool init = false);
/**
* @brief accept_ping_slot_channel_req Makes decision whether to accept
* or reject PingSlotChannelReq MAC command.
*
* @param frequency The unicast ping slot channel
*
* @return True to let the MAC know that the request is
* accepted and MAC can apply Ping slot channel received
* form Network Server. Otherwise false is returned.
*/
/**
* @brief accept_ping_slot_channel_req Makes decision whether to accept
* or reject PIngSlotChannelReq MAC command.
*
* @param frequency The unicast ping slot channel
*
* @return Status bits RFU[7:2], DrOk[1], FreqOk[0]. If status bit is 1 the
* parameter is compatible. If either status bit is zero, the request
* fails.
*/
virtual uint8_t accept_ping_slot_channel_req(uint32_t frequency, uint8_t datarate);
/**
* @brief accept_beacon_frequency_request Makes decision whether to accept
* or reject BeaconFreqReq MAC command.
*
* @param frequency The frequency at which beacons will be broadcast
*
* @return 1 to let the MAC know that the device can use the frequency
* @return 1 to let the MAC know that the request is accepted and
* MAC can apply Beacon frequency received form Network Server.
* Otherwise 0 is returned.
*/
virtual uint8_t accept_beacon_frequency_request(uint32_t frequency);
public:
/**
* @brief get_next_lower_tx_datarate Gets the next lower datarate
@ -600,6 +636,50 @@ public: //Verifiers
*/
uint32_t get_rejoin_max_count() const;
virtual void compute_beacon_win_params(uint32_t beacon_time, uint8_t min_rx_symbols,
uint32_t rx_error, rx_config_params_t *config);
/**
* @brief get_beacon_rfu_size Gets the current region beacon RFU field sizes
*/
virtual void get_beacon_rfu_size(uint8_t &rfu1, uint8_t &rfu2);
/**
* @brief get_beacon_frequency Computes beacon frequency
* @param beacon_time beacon time used to compute beacon frequency
* @return beacon frequency
*/
virtual uint32_t get_beacon_frequency(uint32_t beacon_time);
/*!
* Computes the ping slot frequency, window timeout and offset.
*
* @param [in] beacon_time The current beacon period time
*
* @param [in] devaddr Device address for ping frequency computation
*
* @param [in] min_rx_symbols The minimum number of symbols required to
* detect an RX frame.
*
* @param [in] rx_error The maximum timing error of the receiver
* in milliseconds. The receiver will turn on
* in a [-rxError : +rxError] ms interval around
* RxOffset.
*
* @param [out] rx_conf_params Pointer to the structure that needs to be
* filled with receive window parameters.
*/
virtual void compute_ping_win_params(uint32_t beacon_time, uint32_t devaddr,
uint8_t min_rx_symbols, uint32_t rx_error,
rx_config_params_t *config);
/**
* @brief compute_beacon_time_on_air
* @param compute_beacon_time_on_air computes beacon frame time on air
* @return time on air in milliseconds
*/
virtual uint32_t compute_beacon_time_on_air();
protected:
LoRaPHY();
@ -666,10 +746,9 @@ protected:
/**
* Computes the RX window timeout and the RX 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, uint32_t *window_length_ms,
int32_t *window_offset,
void get_rx_window_params(float t_symbol, float max_preamble_len,
uint8_t min_rx_symbols, float rx_error, float wakeup_time,
uint32_t *window_length, int32_t *window_offset,
uint8_t phy_dr);
/**
@ -698,6 +777,10 @@ protected:
bool is_datarate_supported(const int8_t datarate) const;
virtual uint32_t get_rx1_frequency(uint8_t channel);
virtual uint32_t get_ping_slot_frequency(uint32_t dev_addr, uint32_t beacon_time);
private:
/**