Adding FSB selection feature for US915 PHY

User can now define a custom frequency sub-band for the US915 PHY.
FSB_Usage.txt defines how this parameter will be configured.
pull/7802/head
Hasnain Virk 2018-08-13 11:22:31 +03:00
parent 2d330533a4
commit 207ae2dedf
3 changed files with 79 additions and 37 deletions

View File

@ -0,0 +1,35 @@
Frequency sub-bands in US915/AU915:
US915/AU915 PHYs define channel structures which can support up-to 72 channels for upstream.
First 64 channels (0-63), occupy 125 kHz and the last 8 channels (64-71) occupy 500 kHz.
However, most of the base stations available in the market support 8 or 16 channels.
Network acquisition can become costly if the device have no prior knowledge of active channel plan and it enables
all 72 channels to begin with.
LoRaWAN 1.0.2 Regional parameters specification refers to a strategy of probing a set of nine channels (8 + 1) for
joining process. According to that strategy the device is supposed to alternatively select a channel from a set of
8, 125 kHz channels and a 500 kHz channel.
For example send a join request alternatively on a randomly selected channel from a set of 0-7 channels and
channel 64 which is the first 500 kHz channel.
Once the device has joined the network (in case of OTAA) or have sent the first uplink (in case of ABP), the network
may send a LinkAdrReq mac command to set the channel mask to be used. Please note that these PHY layers do not
support CFList so LinkAdrReq is the way the network tells you what channel plan to use.
Mbed LoRaWAN stack can be configured to use a particular frequency sub-band (FSB) which means that we don't have to
probe all sets of channels. "fsb-mask" in lorawan/mbed_lib.json is the parameter which can be used to tell the
system which FSB or a set of FSBs to use. By default the "fsb-mask" is set to "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}"
that means all channels are active, i.e., 64 125 kHz channels and 8 500 kHz channels are active. If the user wishes
to use a custom FSB, he/she needs to set appropriate mask as the value of "fsb-mask". For example:
If the user wishes to use the first FSB, i.e., first 8 125 kHz channels (0-7) and the first 500 kHz channel:
"fsb-mask" = "{0x00FF, 0x0000, 0x0000, 0x0000, 0x0001}"
Similarly, if the user wishes to use second FSB, i.e., 2nd set of 8 125 kHz channels (8-15) and the 2nd 500 kHz
channel:
"fsb-mask" = "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}"
You can also combine FSBs if your base station supports more than 8 channels. For example:
"fsb-mask" = "{0x00FF, 0x0000, 0x0000, 0xFF00, 0x0081}"
will mean use channels 0-7(125 kHz) + channel 64 (500 KHz) and channels 56-63 (125 kHz) + channel 71 (500 kHz).
Please note that for Certification requirements, you need to alternate between 125 kHz and 500 kHz channels and that's
why before joining you should not set a mask that enables only 500 kHz or only 125 kHz channels.

View File

@ -204,25 +204,27 @@ static const int8_t datarate_offsets_US915[5][4] =
/*! /*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater. * Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/ */
static const uint8_t max_payloads_US915[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; static const uint8_t max_payloads_US915[] = {11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0};
/*! /*!
* Maximum payload with respect to the datarate index. Can operate with repeater. * Maximum payload with respect to the datarate index. Can operate with repeater.
*/ */
static const uint8_t max_payloads_with_repeater_US915[] = {11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0}; static const uint8_t max_payloads_with_repeater_US915[] = {11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0};
static const uint16_t fsb_mask[] = MBED_CONF_LORA_FSB_MASK;
LoRaPHYUS915::LoRaPHYUS915() LoRaPHYUS915::LoRaPHYUS915()
{ {
bands[0] = US915_BAND0; bands[0] = US915_BAND0;
// Channels // Channels
// 125 kHz channels // 125 kHz channels - Upstream
for (uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++) { for (uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++) {
channels[i].frequency = 902300000 + i * 200000; channels[i].frequency = 902300000 + i * 200000;
channels[i].dr_range.value = ( DR_3 << 4) | DR_0; channels[i].dr_range.value = ( DR_3 << 4) | DR_0;
channels[i].band = 0; channels[i].band = 0;
} }
// 500 kHz channels // 500 kHz channels - Upstream
for (uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++) { for (uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++) {
channels[i].frequency = 903000000 + (i - ( US915_MAX_NB_CHANNELS - 8)) * 1600000; channels[i].frequency = 903000000 + (i - ( US915_MAX_NB_CHANNELS - 8)) * 1600000;
channels[i].dr_range.value = ( DR_4 << 4) | DR_4; channels[i].dr_range.value = ( DR_4 << 4) | DR_4;
@ -230,11 +232,16 @@ LoRaPHYUS915::LoRaPHYUS915()
} }
// ChannelsMask // ChannelsMask
default_channel_mask[0] = 0xFFFF; for (uint8_t i = 0; i < US915_MAX_NB_CHANNELS; i++) {
default_channel_mask[1] = 0xFFFF; if (i == (US915_MAX_NB_CHANNELS - 1)) {
default_channel_mask[2] = 0xFFFF; // 64 - 71, 500 kHz channels will get enabled
default_channel_mask[3] = 0xFFFF; default_channel_mask[i] = 0x00FF & fsb_mask[i];
default_channel_mask[4] = 0x00FF; continue;
}
// 0 - 63 125 kHz channels will get enabled
default_channel_mask[i] = 0xFFFF & fsb_mask[i];
}
memset(channel_mask, 0, sizeof(channel_mask)); memset(channel_mask, 0, sizeof(channel_mask));
memset(current_channel_mask, 0, sizeof(current_channel_mask)); memset(current_channel_mask, 0, sizeof(current_channel_mask));
@ -242,7 +249,7 @@ LoRaPHYUS915::LoRaPHYUS915()
// Copy channels default mask // Copy channels default mask
copy_channel_mask(channel_mask, default_channel_mask, US915_CHANNEL_MASK_SIZE); copy_channel_mask(channel_mask, default_channel_mask, US915_CHANNEL_MASK_SIZE);
// current channel masks keep track what of the // current channel masks keep track of the
// channels previously used, i.e., which channels should be avoided in // channels previously used, i.e., which channels should be avoided in
// next transmission // next transmission
copy_channel_mask(current_channel_mask, channel_mask, US915_CHANNEL_MASK_SIZE); copy_channel_mask(current_channel_mask, channel_mask, US915_CHANNEL_MASK_SIZE);
@ -346,7 +353,7 @@ void LoRaPHYUS915::restore_default_channels()
// Copy channels default mask // Copy channels default mask
copy_channel_mask(channel_mask, default_channel_mask, US915_CHANNEL_MASK_SIZE); copy_channel_mask(channel_mask, default_channel_mask, US915_CHANNEL_MASK_SIZE);
for ( uint8_t i = 0; i < US915_CHANNEL_MASK_SIZE; i++ ) { for (uint8_t i = 0; i < US915_CHANNEL_MASK_SIZE; i++) {
// Copy-And the channels mask // Copy-And the channels mask
current_channel_mask[i] &= channel_mask[i]; current_channel_mask[i] &= channel_mask[i];
} }
@ -384,10 +391,11 @@ bool LoRaPHYUS915::rx_config(rx_config_params_t* config)
_radio->lock(); _radio->lock();
_radio->set_channel( frequency ); _radio->set_channel(frequency);
// Radio configuration // Radio configuration
_radio->set_rx_config(MODEM_LORA, config->bandwidth, phy_dr, 1, 0, 8, _radio->set_rx_config(MODEM_LORA, config->bandwidth, phy_dr, 1, 0,
MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH,
config->window_timeout, false, 0, false, 0, 0, true, config->window_timeout, false, 0, false, 0, 0, true,
config->is_rx_continuous); config->is_rx_continuous);
_radio->unlock(); _radio->unlock();
@ -429,7 +437,8 @@ bool LoRaPHYUS915::tx_config(tx_config_params_t* config, int8_t* tx_power,
_radio->set_channel(channels[config->channel].frequency); _radio->set_channel(channels[config->channel].frequency);
_radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, bandwidth, phy_dr, 1, 8, _radio->set_tx_config(MODEM_LORA, phy_tx_power, 0, bandwidth, phy_dr, 1,
MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH,
false, true, 0, 0, false, 3000); false, true, 0, 0, false, 3000);
// Setup maximum payload lenght of the radio driver // Setup maximum payload lenght of the radio driver
@ -478,20 +487,20 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params,
if (adr_settings.ch_mask_ctrl == 6) { if (adr_settings.ch_mask_ctrl == 6) {
// Enable all 125 kHz channels // Enable all 125 kHz channels
temp_channel_masks[0] = 0xFFFF; for (uint8_t i = 0; i < US915_CHANNEL_MASK_SIZE - 1; i++) {
temp_channel_masks[1] = 0xFFFF; temp_channel_masks[i] = 0xFFFF;
temp_channel_masks[2] = 0xFFFF; }
temp_channel_masks[3] = 0xFFFF;
// Apply chMask to channels 64 to 71 // Apply chMask to channels 64 to 71
temp_channel_masks[4] = adr_settings.channel_mask; temp_channel_masks[4] = adr_settings.channel_mask;
} else if (adr_settings.ch_mask_ctrl == 7) { } else if (adr_settings.ch_mask_ctrl == 7) {
// Disable all 125 kHz channels // Disable all 125 kHz channels
temp_channel_masks[0] = 0x0000; for (uint8_t i = 0; i < US915_CHANNEL_MASK_SIZE - 1; i++) {
temp_channel_masks[1] = 0x0000; temp_channel_masks[i] = 0x0000;
temp_channel_masks[2] = 0x0000; }
temp_channel_masks[3] = 0x0000;
// Apply chMask to channels 64 to 71 // Apply chMask to channels 64 to 71
temp_channel_masks[4] = adr_settings.channel_mask; temp_channel_masks[4] = adr_settings.channel_mask;
@ -531,11 +540,9 @@ uint8_t LoRaPHYUS915::link_ADR_request(adr_req_params_t* params,
// Copy Mask // Copy Mask
copy_channel_mask(channel_mask, temp_channel_masks, US915_CHANNEL_MASK_SIZE); copy_channel_mask(channel_mask, temp_channel_masks, US915_CHANNEL_MASK_SIZE);
current_channel_mask[0] &= channel_mask[0]; for (uint8_t i = 0; i < US915_CHANNEL_MASK_SIZE; i++) {
current_channel_mask[1] &= channel_mask[1]; current_channel_mask[i] &= channel_mask[i];
current_channel_mask[2] &= channel_mask[2]; }
current_channel_mask[3] &= channel_mask[3];
current_channel_mask[4] = channel_mask[4];
} }
// Update status variables // Update status variables
@ -553,7 +560,7 @@ uint8_t LoRaPHYUS915::accept_rx_param_setup_req(rx_param_setup_req_t* params)
uint32_t freq = params->frequency; uint32_t freq = params->frequency;
// Verify radio frequency // Verify radio frequency
if ((_radio->check_rf_frequency( freq ) == false) if ((_radio->check_rf_frequency(freq) == false)
|| (freq < US915_FIRST_RX1_CHANNEL) || (freq < US915_FIRST_RX1_CHANNEL)
|| (freq > US915_LAST_RX1_CHANNEL) || (freq > US915_LAST_RX1_CHANNEL)
|| (((freq - (uint32_t) US915_FIRST_RX1_CHANNEL) % (uint32_t) US915_STEPWIDTH_RX1_CHANNEL) != 0)) { || (((freq - (uint32_t) US915_FIRST_RX1_CHANNEL) % (uint32_t) US915_STEPWIDTH_RX1_CHANNEL) != 0)) {
@ -588,9 +595,6 @@ int8_t LoRaPHYUS915::get_alternate_DR(uint8_t nb_trials)
{ {
int8_t datarate = 0; int8_t datarate = 0;
// Re-enable 500 kHz default channels
channel_mask[4] = 0x00FF;
if ((nb_trials & 0x01) == 0x01) { if ((nb_trials & 0x01) == 0x01) {
datarate = DR_4; datarate = DR_4;
} else { } else {
@ -616,11 +620,10 @@ lorawan_status_t LoRaPHYUS915::set_next_channel(channel_selection_params_t* para
copy_channel_mask(current_channel_mask, channel_mask, 4); copy_channel_mask(current_channel_mask, channel_mask, 4);
} }
// Check other channels // Update the 500 kHz channels in the running mask
if (params->current_datarate >= DR_4) { if ((params->current_datarate >= DR_4)
if ((current_channel_mask[4] & 0x00FF ) == 0) { && (current_channel_mask[4] & 0x00FF) == 0) {
current_channel_mask[4] = channel_mask[4]; current_channel_mask[4] = channel_mask[4];
}
} }
if (params->aggregate_timeoff <= _lora_time->get_elapsed_time(params->last_aggregate_tx_time)) { if (params->aggregate_timeoff <= _lora_time->get_elapsed_time(params->last_aggregate_tx_time)) {
@ -641,9 +644,9 @@ lorawan_status_t LoRaPHYUS915::set_next_channel(channel_selection_params_t* para
if (nb_enabled_channels > 0) { if (nb_enabled_channels > 0) {
// We found a valid channel // We found a valid channel
*channel = enabled_channels[get_random( 0, nb_enabled_channels - 1 )]; *channel = enabled_channels[get_random(0, nb_enabled_channels - 1)];
// Disable the channel in the mask // Disable the channel in the mask
disable_channel(current_channel_mask, *channel, US915_MAX_NB_CHANNELS - 8); disable_channel(current_channel_mask, *channel, US915_MAX_NB_CHANNELS);
*time = 0; *time = 0;
return LORAWAN_STATUS_OK; return LORAWAN_STATUS_OK;

View File

@ -80,6 +80,10 @@
"uplink-preamble-length": { "uplink-preamble-length": {
"help": "Number of preamble symbols to transmit. Must be <= 8", "help": "Number of preamble symbols to transmit. Must be <= 8",
"value": 8 "value": 8
},
"fsb-mask": {
"help": "FSB mask for upstream [Only for US915, US915_HYBRID & AU915] Check lorawan/FSB_Usage.txt for more details",
"value": "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}"
} }
} }
} }