MultiTech / mDot_Channel_Plans

The channel plans in this library can be used as starting points for new channel plans and used as a reference for implementation.

Information

To use source version of a channel plan, first remove the Channel Plans folder from libmDot-Custom library.

Not all plans are complete to LoRaWAN specifications.

AS923 and KR920 have the default channels defined and can accept in channels in the Join Accept message or from New Channel MAC commands.

Channel Set must match those expected by the network server in order for ADR to work

AS923 regional settings can be adjusted by the network server using Tx Param Setup MAC command to set max EIRP and dwell time for uplinks.

Committer:
jreiss
Date:
Thu Jan 26 13:07:53 2017 +0000
Revision:
12:2e8fda56093f
Parent:
11:829f8c2ec1c3
Child:
13:996f1663d12e
Adjust ADR DR step down packet by one; Initialize DL channel list with frequency:0 in AS923,EU868,IN865,KR920 plans

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jreiss 12:2e8fda56093f 1 /**********************************************************************
jreiss 12:2e8fda56093f 2 * COPYRIGHT 2016 MULTI-TECH SYSTEMS, INC.
jreiss 12:2e8fda56093f 3 *
jreiss 12:2e8fda56093f 4 * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF
jreiss 12:2e8fda56093f 5 * MULTI-TECH SYSTEMS, INC.
jreiss 12:2e8fda56093f 6 *
jreiss 12:2e8fda56093f 7 * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY
jreiss 12:2e8fda56093f 8 * INFORMATION AND/OR TRADE SECRET.
jreiss 12:2e8fda56093f 9 *
jreiss 12:2e8fda56093f 10 * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION,
jreiss 12:2e8fda56093f 11 * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL
jreiss 12:2e8fda56093f 12 * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC.
jreiss 12:2e8fda56093f 13 * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A
jreiss 12:2e8fda56093f 14 * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED.
jreiss 12:2e8fda56093f 15 *
jreiss 12:2e8fda56093f 16 ***********************************************************************/
jreiss 12:2e8fda56093f 17
jreiss 12:2e8fda56093f 18 #include "CustomChannelPlan_US915.h"
jreiss 12:2e8fda56093f 19 #include "limits.h"
jreiss 12:2e8fda56093f 20
jreiss 12:2e8fda56093f 21 using namespace lora;
jreiss 12:2e8fda56093f 22
jreiss 12:2e8fda56093f 23 const uint8_t CustomChannelPlan_US915::US915_TX_POWERS[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
jreiss 12:2e8fda56093f 24 const uint8_t CustomChannelPlan_US915::US915_RADIO_POWERS[] = { 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 19 };
jreiss 12:2e8fda56093f 25 const uint8_t CustomChannelPlan_US915::US915_MAX_PAYLOAD_SIZE[] = { 11, 53, 126, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
jreiss 12:2e8fda56093f 26 const uint8_t CustomChannelPlan_US915::US915_MAX_PAYLOAD_SIZE_REPEATER[] = { 11, 53, 126, 222, 222, 0, 0, 33, 109, 222, 222, 222, 0, 0 };
jreiss 12:2e8fda56093f 27
jreiss 12:2e8fda56093f 28 CustomChannelPlan_US915::CustomChannelPlan_US915(SxRadio& radio, Settings& settings)
jreiss 12:2e8fda56093f 29 :
jreiss 12:2e8fda56093f 30 ChannelPlan(radio, settings)
jreiss 12:2e8fda56093f 31 {
jreiss 12:2e8fda56093f 32
jreiss 12:2e8fda56093f 33 }
jreiss 12:2e8fda56093f 34
jreiss 12:2e8fda56093f 35 CustomChannelPlan_US915::~CustomChannelPlan_US915() {
jreiss 12:2e8fda56093f 36
jreiss 12:2e8fda56093f 37 }
jreiss 12:2e8fda56093f 38
jreiss 12:2e8fda56093f 39 void CustomChannelPlan_US915::Init() {
jreiss 12:2e8fda56093f 40 _type = FIXED;
jreiss 12:2e8fda56093f 41 _planName = "US915";
jreiss 12:2e8fda56093f 42
jreiss 12:2e8fda56093f 43 _datarates.clear();
jreiss 12:2e8fda56093f 44 _channels.clear();
jreiss 12:2e8fda56093f 45 _dutyBands.clear();
jreiss 12:2e8fda56093f 46
jreiss 12:2e8fda56093f 47 DutyBand band;
jreiss 12:2e8fda56093f 48
jreiss 12:2e8fda56093f 49 band.Index = 0;
jreiss 12:2e8fda56093f 50 band.DutyCycle = 0;
jreiss 12:2e8fda56093f 51
jreiss 12:2e8fda56093f 52 Datarate dr;
jreiss 12:2e8fda56093f 53
jreiss 12:2e8fda56093f 54 logWarning("Custom ChannelPlan");
jreiss 12:2e8fda56093f 55
jreiss 12:2e8fda56093f 56 _maxTxPower = 30;
jreiss 12:2e8fda56093f 57 _minTxPower = 10;
jreiss 12:2e8fda56093f 58
jreiss 12:2e8fda56093f 59 _minFrequency = US915_FREQ_MIN;
jreiss 12:2e8fda56093f 60 _maxFrequency = US915_FREQ_MAX;
jreiss 12:2e8fda56093f 61
jreiss 12:2e8fda56093f 62 TX_POWERS = US915_TX_POWERS;
jreiss 12:2e8fda56093f 63 RADIO_POWERS = US915_RADIO_POWERS;
jreiss 12:2e8fda56093f 64 MAX_PAYLOAD_SIZE = US915_MAX_PAYLOAD_SIZE;
jreiss 12:2e8fda56093f 65 MAX_PAYLOAD_SIZE_REPEATER = US915_MAX_PAYLOAD_SIZE_REPEATER;
jreiss 12:2e8fda56093f 66
jreiss 12:2e8fda56093f 67 band.FrequencyMin = US915_FREQ_MIN;
jreiss 12:2e8fda56093f 68 band.FrequencyMax = US915_FREQ_MAX;
jreiss 12:2e8fda56093f 69
jreiss 12:2e8fda56093f 70 _freqUBase125k = US915_125K_FREQ_BASE;
jreiss 12:2e8fda56093f 71 _freqUStep125k = US915_125K_FREQ_STEP;
jreiss 12:2e8fda56093f 72 _freqUBase500k = US915_500K_FREQ_BASE;
jreiss 12:2e8fda56093f 73 _freqUStep500k = US915_500K_FREQ_STEP;
jreiss 12:2e8fda56093f 74 _freqDBase500k = US915_500K_DBASE;
jreiss 12:2e8fda56093f 75 _freqDStep500k = US915_500K_DSTEP;
jreiss 12:2e8fda56093f 76 _settings.Session.Rx2Frequency = US915_500K_DBASE;
jreiss 12:2e8fda56093f 77
jreiss 12:2e8fda56093f 78 _minDatarate = US915_MIN_DATARATE;
jreiss 12:2e8fda56093f 79 _maxDatarate = US915_MAX_DATARATE;
jreiss 12:2e8fda56093f 80 _minRx2Datarate = DR_8;
jreiss 12:2e8fda56093f 81 _maxRx2Datarate = DR_13;
jreiss 12:2e8fda56093f 82 _minDatarateOffset = US915_MIN_DATARATE_OFFSET;
jreiss 12:2e8fda56093f 83 _maxDatarateOffset = US915_MAX_DATARATE_OFFSET;
jreiss 12:2e8fda56093f 84
jreiss 12:2e8fda56093f 85 _numChans125k = US915_125K_NUM_CHANS;
jreiss 12:2e8fda56093f 86 _numChans500k = US915_500K_NUM_CHANS;
jreiss 12:2e8fda56093f 87
jreiss 12:2e8fda56093f 88 logInfo("Initialize channels...");
jreiss 12:2e8fda56093f 89
jreiss 12:2e8fda56093f 90 SetNumberOfChannels(US915_125K_NUM_CHANS + US915_500K_NUM_CHANS, false);
jreiss 12:2e8fda56093f 91
jreiss 12:2e8fda56093f 92 dr.SpreadingFactor = SF_10;
jreiss 12:2e8fda56093f 93
jreiss 12:2e8fda56093f 94 logInfo("Initialize datarates...");
jreiss 12:2e8fda56093f 95
jreiss 12:2e8fda56093f 96 // Add DR0-3
jreiss 12:2e8fda56093f 97 while (dr.SpreadingFactor >= SF_7) {
jreiss 12:2e8fda56093f 98 AddDatarate(-1, dr);
jreiss 12:2e8fda56093f 99 dr.SpreadingFactor--;
jreiss 12:2e8fda56093f 100 dr.Index++;
jreiss 12:2e8fda56093f 101 }
jreiss 12:2e8fda56093f 102
jreiss 12:2e8fda56093f 103 // Add DR4
jreiss 12:2e8fda56093f 104 dr.SpreadingFactor = SF_8;
jreiss 12:2e8fda56093f 105 dr.Bandwidth = BW_500;
jreiss 12:2e8fda56093f 106 AddDatarate(-1, dr);
jreiss 12:2e8fda56093f 107 dr.Index++;
jreiss 12:2e8fda56093f 108
jreiss 12:2e8fda56093f 109 // Skip DR5-7 RFU
jreiss 12:2e8fda56093f 110 dr.SpreadingFactor = SF_INVALID;
jreiss 12:2e8fda56093f 111 AddDatarate(-1, dr), dr.Index++;
jreiss 12:2e8fda56093f 112 AddDatarate(-1, dr), dr.Index++;
jreiss 12:2e8fda56093f 113 AddDatarate(-1, dr), dr.Index++;
jreiss 12:2e8fda56093f 114
jreiss 12:2e8fda56093f 115 if (_settings.Network.ChannelGroup == 0) {
jreiss 12:2e8fda56093f 116 band.PowerMax = 30;
jreiss 12:2e8fda56093f 117 } else {
jreiss 12:2e8fda56093f 118 band.PowerMax = 21;
jreiss 12:2e8fda56093f 119 }
jreiss 12:2e8fda56093f 120
jreiss 12:2e8fda56093f 121 band.TimeOffEnd = 0;
jreiss 12:2e8fda56093f 122
jreiss 12:2e8fda56093f 123 AddDutyBand(-1, band);
jreiss 12:2e8fda56093f 124
jreiss 12:2e8fda56093f 125 _settings.Session.Rx2DatarateIndex = DR_8;
jreiss 12:2e8fda56093f 126
jreiss 12:2e8fda56093f 127 // Add DR8-13
jreiss 12:2e8fda56093f 128 dr.SpreadingFactor = SF_12;
jreiss 12:2e8fda56093f 129 while (dr.SpreadingFactor >= SF_7) {
jreiss 12:2e8fda56093f 130 AddDatarate(-1, dr);
jreiss 12:2e8fda56093f 131 dr.SpreadingFactor--;
jreiss 12:2e8fda56093f 132 dr.Index++;
jreiss 12:2e8fda56093f 133 }
jreiss 12:2e8fda56093f 134
jreiss 12:2e8fda56093f 135 // Skip DR14-15 RFU
jreiss 12:2e8fda56093f 136 dr.SpreadingFactor = SF_INVALID;
jreiss 12:2e8fda56093f 137 AddDatarate(-1, dr), AddDatarate(-1, dr);
jreiss 12:2e8fda56093f 138
jreiss 12:2e8fda56093f 139 _settings.Session.TxDatarate = DR_0;
jreiss 12:2e8fda56093f 140
jreiss 12:2e8fda56093f 141 SetChannelGroup(_settings.Network.ChannelGroup);
jreiss 12:2e8fda56093f 142
jreiss 12:2e8fda56093f 143 }
jreiss 12:2e8fda56093f 144
jreiss 12:2e8fda56093f 145 uint8_t CustomChannelPlan_US915::HandleJoinAccept(const uint8_t* buffer, uint8_t size) {
jreiss 12:2e8fda56093f 146
jreiss 12:2e8fda56093f 147 if (_settings.Device.FrequencyBand == lora::US915 || _settings.Device.FrequencyBand == lora::AU915) {
jreiss 12:2e8fda56093f 148 if (size > 17) {
jreiss 12:2e8fda56093f 149 // TODO: Handle future channel mask settings
jreiss 12:2e8fda56093f 150 }
jreiss 12:2e8fda56093f 151 }
jreiss 12:2e8fda56093f 152 return LORA_OK;
jreiss 12:2e8fda56093f 153 }
jreiss 12:2e8fda56093f 154
jreiss 12:2e8fda56093f 155 void CustomChannelPlan_US915::SetNumberOfChannels(uint8_t channels, bool resize) {
jreiss 12:2e8fda56093f 156 uint8_t newsize = ((channels - 1) / CHAN_MASK_SIZE) + 1;
jreiss 12:2e8fda56093f 157
jreiss 12:2e8fda56093f 158 if (resize) {
jreiss 12:2e8fda56093f 159 _channels.resize(channels);
jreiss 12:2e8fda56093f 160 }
jreiss 12:2e8fda56093f 161
jreiss 12:2e8fda56093f 162 _channelMask.resize(newsize, 0x0);
jreiss 12:2e8fda56093f 163 _numChans = channels;
jreiss 12:2e8fda56093f 164
jreiss 12:2e8fda56093f 165 }
jreiss 12:2e8fda56093f 166
jreiss 12:2e8fda56093f 167 bool CustomChannelPlan_US915::IsChannelEnabled(uint8_t channel) {
jreiss 12:2e8fda56093f 168 uint8_t index = channel / CHAN_MASK_SIZE;
jreiss 12:2e8fda56093f 169 uint8_t shift = channel % CHAN_MASK_SIZE;
jreiss 12:2e8fda56093f 170
jreiss 12:2e8fda56093f 171 assert(index < _channelMask.size() * CHAN_MASK_SIZE);
jreiss 12:2e8fda56093f 172
jreiss 12:2e8fda56093f 173 // cannot shift over 32 bits
jreiss 12:2e8fda56093f 174 assert(shift < 32);
jreiss 12:2e8fda56093f 175
jreiss 12:2e8fda56093f 176 // logDebug("index: %d shift %d cm: %04x bit: %04x enabled: %d", index, shift, _channelMask[index], (1 << shift), (_channelMask[index] & (1 << shift)) == (1 << shift));
jreiss 12:2e8fda56093f 177
jreiss 12:2e8fda56093f 178 return (_channelMask[index] & (1 << shift)) == (1 << shift);
jreiss 12:2e8fda56093f 179 }
jreiss 12:2e8fda56093f 180
jreiss 12:2e8fda56093f 181 uint8_t CustomChannelPlan_US915::GetMinDatarate() {
jreiss 12:2e8fda56093f 182 if (_settings.Network.Mode == lora::PEER_TO_PEER)
jreiss 12:2e8fda56093f 183 return 8;
jreiss 12:2e8fda56093f 184 else
jreiss 12:2e8fda56093f 185 return _minDatarate;
jreiss 12:2e8fda56093f 186 }
jreiss 12:2e8fda56093f 187
jreiss 12:2e8fda56093f 188 uint8_t CustomChannelPlan_US915::GetMaxDatarate() {
jreiss 12:2e8fda56093f 189 if (_settings.Network.Mode == lora::PEER_TO_PEER)
jreiss 12:2e8fda56093f 190 return 13;
jreiss 12:2e8fda56093f 191 else
jreiss 12:2e8fda56093f 192 return _maxDatarate;
jreiss 12:2e8fda56093f 193 }
jreiss 12:2e8fda56093f 194
jreiss 12:2e8fda56093f 195 uint8_t CustomChannelPlan_US915::SetRx1Offset(uint8_t offset) {
jreiss 12:2e8fda56093f 196 _settings.Session.Rx1DatarateOffset = offset;
jreiss 12:2e8fda56093f 197 return LORA_OK;
jreiss 12:2e8fda56093f 198 }
jreiss 12:2e8fda56093f 199
jreiss 12:2e8fda56093f 200 uint8_t CustomChannelPlan_US915::SetRx2Frequency(uint32_t freq) {
jreiss 12:2e8fda56093f 201 _settings.Session.Rx2Frequency = freq;
jreiss 12:2e8fda56093f 202 return LORA_OK;
jreiss 12:2e8fda56093f 203 }
jreiss 12:2e8fda56093f 204
jreiss 12:2e8fda56093f 205 uint8_t CustomChannelPlan_US915::SetRx2DatarateIndex(uint8_t index) {
jreiss 12:2e8fda56093f 206 _settings.Session.Rx2DatarateIndex = index;
jreiss 12:2e8fda56093f 207 return LORA_OK;
jreiss 12:2e8fda56093f 208 }
jreiss 12:2e8fda56093f 209
jreiss 12:2e8fda56093f 210 uint8_t CustomChannelPlan_US915::SetTxConfig() {
jreiss 12:2e8fda56093f 211
jreiss 12:2e8fda56093f 212 logInfo("Configure radio for TX");
jreiss 12:2e8fda56093f 213
jreiss 12:2e8fda56093f 214 uint8_t band = GetDutyBand(GetChannel(_txChannel).Frequency);
jreiss 12:2e8fda56093f 215 Datarate txDr = GetDatarate(_settings.Session.TxDatarate);
jreiss 12:2e8fda56093f 216 int8_t max_pwr = _dutyBands[band].PowerMax;
jreiss 12:2e8fda56093f 217
jreiss 12:2e8fda56093f 218 int8_t pwr = 0;
jreiss 12:2e8fda56093f 219
jreiss 12:2e8fda56093f 220 pwr = std::min < int8_t > (_settings.Session.TxPower, max_pwr);
jreiss 12:2e8fda56093f 221 if (pwr + _settings.Network.AntennaGain >= max_pwr + 6 && _settings.Network.AntennaGain > 6) {
jreiss 12:2e8fda56093f 222 pwr -= (_settings.Network.AntennaGain - 6);
jreiss 12:2e8fda56093f 223 }
jreiss 12:2e8fda56093f 224
jreiss 12:2e8fda56093f 225 for (int i = 20; i >= 0; i--) {
jreiss 12:2e8fda56093f 226 if (RADIO_POWERS[i] <= pwr) {
jreiss 12:2e8fda56093f 227 pwr = i;
jreiss 12:2e8fda56093f 228 break;
jreiss 12:2e8fda56093f 229 }
jreiss 12:2e8fda56093f 230 if (i == 0) {
jreiss 12:2e8fda56093f 231 pwr = i;
jreiss 12:2e8fda56093f 232 }
jreiss 12:2e8fda56093f 233 }
jreiss 12:2e8fda56093f 234
jreiss 12:2e8fda56093f 235 logDebug("Session pwr: %d ant: %d max: %d", _settings.Session.TxPower, _settings.Network.AntennaGain, max_pwr);
jreiss 12:2e8fda56093f 236 logDebug("Radio Power index: %d output: %d total: %d", pwr, RADIO_POWERS[pwr], RADIO_POWERS[pwr] + _settings.Network.AntennaGain);
jreiss 12:2e8fda56093f 237
jreiss 12:2e8fda56093f 238 uint32_t bw = txDr.Bandwidth;
jreiss 12:2e8fda56093f 239 uint32_t sf = txDr.SpreadingFactor;
jreiss 12:2e8fda56093f 240 uint8_t cr = txDr.Coderate;
jreiss 12:2e8fda56093f 241 uint8_t pl = txDr.PreambleLength;
jreiss 12:2e8fda56093f 242 uint16_t fdev = 0;
jreiss 12:2e8fda56093f 243 bool crc = txDr.Crc;
jreiss 12:2e8fda56093f 244 bool iq = txDr.TxIQ;
jreiss 12:2e8fda56093f 245
jreiss 12:2e8fda56093f 246 if (_settings.Network.DisableCRC == true)
jreiss 12:2e8fda56093f 247 crc = false;
jreiss 12:2e8fda56093f 248
jreiss 12:2e8fda56093f 249 SxRadio::RadioModems_t modem = SxRadio::MODEM_LORA;
jreiss 12:2e8fda56093f 250
jreiss 12:2e8fda56093f 251 if (sf == SF_FSK) {
jreiss 12:2e8fda56093f 252 modem = SxRadio::MODEM_FSK;
jreiss 12:2e8fda56093f 253 sf = 50e3;
jreiss 12:2e8fda56093f 254 fdev = 25e3;
jreiss 12:2e8fda56093f 255 bw = 0;
jreiss 12:2e8fda56093f 256 }
jreiss 12:2e8fda56093f 257
jreiss 12:2e8fda56093f 258 _radio.SetTxConfig(modem, pwr, fdev, bw, sf, cr, pl, false, crc, false, 0, iq, 3e3);
jreiss 12:2e8fda56093f 259
jreiss 12:2e8fda56093f 260 logDebug("TX PWR: %u DR: %u SF: %u BW: %u CR: %u PL: %u CRC: %d IQ: %d", pwr, txDr.Index, sf, bw, cr, pl, crc, iq);
jreiss 12:2e8fda56093f 261
jreiss 12:2e8fda56093f 262 return LORA_OK;
jreiss 12:2e8fda56093f 263 }
jreiss 12:2e8fda56093f 264
jreiss 12:2e8fda56093f 265 uint8_t CustomChannelPlan_US915::SetRxConfig(uint8_t window, bool continuous) {
jreiss 12:2e8fda56093f 266
jreiss 12:2e8fda56093f 267 RxWindow rxw = GetRxWindow(window);
jreiss 12:2e8fda56093f 268 _radio.SetChannel(rxw.Frequency);
jreiss 12:2e8fda56093f 269
jreiss 12:2e8fda56093f 270 Datarate rxDr = GetDatarate(rxw.DatarateIndex);
jreiss 12:2e8fda56093f 271 uint32_t bw = rxDr.Bandwidth;
jreiss 12:2e8fda56093f 272 uint32_t sf = rxDr.SpreadingFactor;
jreiss 12:2e8fda56093f 273 uint8_t cr = rxDr.Coderate;
jreiss 12:2e8fda56093f 274 uint8_t pl = rxDr.PreambleLength;
jreiss 12:2e8fda56093f 275 uint16_t sto = rxDr.SymbolTimeout();
jreiss 12:2e8fda56093f 276 uint32_t afc = 0;
jreiss 12:2e8fda56093f 277 bool crc = rxDr.Crc;
jreiss 12:2e8fda56093f 278
jreiss 12:2e8fda56093f 279 if (_settings.Network.DisableCRC == true)
jreiss 12:2e8fda56093f 280 crc = false;
jreiss 12:2e8fda56093f 281
jreiss 12:2e8fda56093f 282 Datarate txDr = GetDatarate(_settings.Session.TxDatarate);
jreiss 12:2e8fda56093f 283 bool iq = txDr.RxIQ;
jreiss 12:2e8fda56093f 284
jreiss 12:2e8fda56093f 285 if (P2PEnabled()) {
jreiss 12:2e8fda56093f 286 iq = txDr.TxIQ;
jreiss 12:2e8fda56093f 287 }
jreiss 12:2e8fda56093f 288
jreiss 12:2e8fda56093f 289 SxRadio::RadioModems_t modem = SxRadio::MODEM_LORA;
jreiss 12:2e8fda56093f 290
jreiss 12:2e8fda56093f 291 if (sf == SF_FSK) {
jreiss 12:2e8fda56093f 292 modem = SxRadio::MODEM_FSK;
jreiss 12:2e8fda56093f 293 sf = 50e3;
jreiss 12:2e8fda56093f 294 cr = 0;
jreiss 12:2e8fda56093f 295 bw = 50e3;
jreiss 12:2e8fda56093f 296 afc = 83333;
jreiss 12:2e8fda56093f 297 iq = false;
jreiss 12:2e8fda56093f 298 }
jreiss 12:2e8fda56093f 299
jreiss 12:2e8fda56093f 300 // Disable printf's to actually receive packets, printing to debug may mess up the timing
jreiss 12:2e8fda56093f 301 // logTrace("Configure radio for RX%d on freq: %lu", window, rxw.Frequency);
jreiss 12:2e8fda56093f 302 // logTrace("RX SF: %u BW: %u CR: %u PL: %u STO: %u CRC: %d IQ: %d", sf, bw, cr, pl, sto, crc, iq);
jreiss 12:2e8fda56093f 303
jreiss 12:2e8fda56093f 304 _radio.SetRxConfig(modem, bw, sf, cr, afc, pl, sto, false, 0, crc, false, 0, iq, continuous);
jreiss 12:2e8fda56093f 305
jreiss 12:2e8fda56093f 306 return LORA_OK;
jreiss 12:2e8fda56093f 307 }
jreiss 12:2e8fda56093f 308
jreiss 12:2e8fda56093f 309 uint8_t CustomChannelPlan_US915::AddChannel(int8_t index, Channel channel) {
jreiss 12:2e8fda56093f 310 logTrace("Add Channel %d : %lu : %02x %d", index, channel.Frequency, channel.DrRange.Value, _channels.size());
jreiss 12:2e8fda56093f 311
jreiss 12:2e8fda56093f 312 assert(index < (int) _channels.size());
jreiss 12:2e8fda56093f 313
jreiss 12:2e8fda56093f 314 if (index >= 0) {
jreiss 12:2e8fda56093f 315 _channels[index] = channel;
jreiss 12:2e8fda56093f 316 } else {
jreiss 12:2e8fda56093f 317 _channels.push_back(channel);
jreiss 12:2e8fda56093f 318 }
jreiss 12:2e8fda56093f 319
jreiss 12:2e8fda56093f 320 return LORA_OK;
jreiss 12:2e8fda56093f 321 }
jreiss 12:2e8fda56093f 322
jreiss 12:2e8fda56093f 323 Channel CustomChannelPlan_US915::GetChannel(int8_t index) {
jreiss 12:2e8fda56093f 324 Channel chan;
jreiss 12:2e8fda56093f 325 memset(&chan, 0, sizeof(Channel));
jreiss 12:2e8fda56093f 326
jreiss 12:2e8fda56093f 327 if (_channels.size() > 0) {
jreiss 12:2e8fda56093f 328 chan = _channels[index];
jreiss 12:2e8fda56093f 329 } else {
jreiss 12:2e8fda56093f 330 if (index < 64) {
jreiss 12:2e8fda56093f 331 chan.Index = index;
jreiss 12:2e8fda56093f 332 chan.DrRange.Fields.Min = _minDatarate;
jreiss 12:2e8fda56093f 333 chan.DrRange.Fields.Max = _maxDatarate - 1;
jreiss 12:2e8fda56093f 334 chan.Frequency = _freqUBase125k + (_freqUStep125k * index);
jreiss 12:2e8fda56093f 335 } else if (index < 72) {
jreiss 12:2e8fda56093f 336 chan.Index = index;
jreiss 12:2e8fda56093f 337 chan.DrRange.Fields.Min = _maxDatarate;
jreiss 12:2e8fda56093f 338 chan.DrRange.Fields.Max = _maxDatarate;
jreiss 12:2e8fda56093f 339 chan.Frequency = _freqUBase500k + (_freqUStep500k * (index - 64));
jreiss 12:2e8fda56093f 340 }
jreiss 12:2e8fda56093f 341 }
jreiss 12:2e8fda56093f 342
jreiss 12:2e8fda56093f 343 return chan;
jreiss 12:2e8fda56093f 344 }
jreiss 12:2e8fda56093f 345
jreiss 12:2e8fda56093f 346 uint8_t CustomChannelPlan_US915::SetChannelGroup(uint8_t group) {
jreiss 12:2e8fda56093f 347
jreiss 12:2e8fda56093f 348 _txChannelGroup = group;
jreiss 12:2e8fda56093f 349
jreiss 12:2e8fda56093f 350 if (group > 0) {
jreiss 12:2e8fda56093f 351 SetChannelMask(0, 0x0000);
jreiss 12:2e8fda56093f 352 SetChannelMask(1, 0x0000);
jreiss 12:2e8fda56093f 353 SetChannelMask(2, 0x0000);
jreiss 12:2e8fda56093f 354 SetChannelMask(3, 0x0000);
jreiss 12:2e8fda56093f 355 SetChannelMask(4, 0x0000);
jreiss 12:2e8fda56093f 356 SetChannelMask((group - 1) / 2, (group % 2) ? 0x00FF : 0xFF00);
jreiss 12:2e8fda56093f 357 SetChannelMask(4, 1 << (group - 1));
jreiss 12:2e8fda56093f 358 } else {
jreiss 12:2e8fda56093f 359 SetChannelMask(0, 0xFFFF);
jreiss 12:2e8fda56093f 360 SetChannelMask(1, 0xFFFF);
jreiss 12:2e8fda56093f 361 SetChannelMask(2, 0xFFFF);
jreiss 12:2e8fda56093f 362 SetChannelMask(3, 0xFFFF);
jreiss 12:2e8fda56093f 363 SetChannelMask(4, 0x00FF);
jreiss 12:2e8fda56093f 364 }
jreiss 12:2e8fda56093f 365
jreiss 12:2e8fda56093f 366 return LORA_OK;
jreiss 12:2e8fda56093f 367 }
jreiss 12:2e8fda56093f 368
jreiss 12:2e8fda56093f 369
jreiss 12:2e8fda56093f 370 void CustomChannelPlan_US915::LogRxWindow(uint8_t wnd) {
jreiss 12:2e8fda56093f 371
jreiss 12:2e8fda56093f 372 RxWindow rxw = GetRxWindow(wnd);
jreiss 12:2e8fda56093f 373 Datarate rxDr = GetDatarate(rxw.DatarateIndex);
jreiss 12:2e8fda56093f 374 uint8_t bw = rxDr.Bandwidth;
jreiss 12:2e8fda56093f 375 uint8_t sf = rxDr.SpreadingFactor;
jreiss 12:2e8fda56093f 376 uint8_t cr = rxDr.Coderate;
jreiss 12:2e8fda56093f 377 uint8_t pl = rxDr.PreambleLength;
jreiss 12:2e8fda56093f 378 uint16_t sto = rxDr.SymbolTimeout();
jreiss 12:2e8fda56093f 379 bool crc = rxDr.Crc;
jreiss 12:2e8fda56093f 380 bool iq = GetTxDatarate().RxIQ;
jreiss 12:2e8fda56093f 381
jreiss 12:2e8fda56093f 382 logTrace("RX%d on freq: %lu", wnd, rxw.Frequency);
jreiss 12:2e8fda56093f 383 logTrace("RX DR: %u SF: %u BW: %u CR: %u PL: %u STO: %u CRC: %d IQ: %d", rxDr.Index, sf, bw, cr, pl, sto, crc, iq);
jreiss 12:2e8fda56093f 384 }
jreiss 12:2e8fda56093f 385
jreiss 12:2e8fda56093f 386 RxWindow CustomChannelPlan_US915::GetRxWindow(uint8_t window) {
jreiss 12:2e8fda56093f 387 RxWindow rxw;
jreiss 12:2e8fda56093f 388 int index = 0;
jreiss 12:2e8fda56093f 389
jreiss 12:2e8fda56093f 390 if (P2PEnabled()) {
jreiss 12:2e8fda56093f 391 rxw.Frequency = _settings.Network.TxFrequency;
jreiss 12:2e8fda56093f 392 index = _settings.Session.TxDatarate;
jreiss 12:2e8fda56093f 393 } else {
jreiss 12:2e8fda56093f 394 if (window == 1) {
jreiss 12:2e8fda56093f 395 if (_txChannel < _numChans125k) {
jreiss 12:2e8fda56093f 396 if (_settings.Network.Mode == PUBLIC) {
jreiss 12:2e8fda56093f 397 rxw.Frequency = _freqDBase500k + (_txChannel % 8) * _freqDStep500k;
jreiss 12:2e8fda56093f 398 } else {
jreiss 12:2e8fda56093f 399 rxw.Frequency = _freqDBase500k + (_txChannel / 8) * _freqDStep500k;
jreiss 12:2e8fda56093f 400 }
jreiss 12:2e8fda56093f 401 } else
jreiss 12:2e8fda56093f 402 rxw.Frequency = _freqDBase500k + (_txChannel - _numChans125k) * _freqDStep500k;
jreiss 12:2e8fda56093f 403
jreiss 12:2e8fda56093f 404 if (_settings.Session.TxDatarate <= DR_6) {
jreiss 12:2e8fda56093f 405 index = _settings.Session.TxDatarate + 10 - _settings.Session.Rx1DatarateOffset;
jreiss 12:2e8fda56093f 406
jreiss 12:2e8fda56093f 407 if (index < DR_8)
jreiss 12:2e8fda56093f 408 index = DR_8;
jreiss 12:2e8fda56093f 409 if (index > DR_13)
jreiss 12:2e8fda56093f 410 index = DR_13;
jreiss 12:2e8fda56093f 411 } else if (_settings.Session.TxDatarate >= DR_8) {
jreiss 12:2e8fda56093f 412 index = _settings.Session.TxDatarate - _settings.Session.Rx1DatarateOffset;
jreiss 12:2e8fda56093f 413 if (index < DR_8)
jreiss 12:2e8fda56093f 414 index = DR_8;
jreiss 12:2e8fda56093f 415 }
jreiss 12:2e8fda56093f 416 } else {
jreiss 12:2e8fda56093f 417 if (_settings.Network.Mode == PUBLIC) {
jreiss 12:2e8fda56093f 418 rxw.Frequency = _settings.Session.Rx2Frequency;
jreiss 12:2e8fda56093f 419 } else {
jreiss 12:2e8fda56093f 420 if (_txChannel < 64)
jreiss 12:2e8fda56093f 421 rxw.Frequency = _freqDBase500k + (_txChannel / 8) * _freqDStep500k;
jreiss 12:2e8fda56093f 422 else
jreiss 12:2e8fda56093f 423 rxw.Frequency = _freqDBase500k + (_txChannel % 8) * _freqDStep500k;
jreiss 12:2e8fda56093f 424 }
jreiss 12:2e8fda56093f 425 index = _settings.Session.Rx2DatarateIndex;
jreiss 12:2e8fda56093f 426 }
jreiss 12:2e8fda56093f 427 }
jreiss 12:2e8fda56093f 428
jreiss 12:2e8fda56093f 429 rxw.DatarateIndex = index;
jreiss 12:2e8fda56093f 430
jreiss 12:2e8fda56093f 431 return rxw;
jreiss 12:2e8fda56093f 432 }
jreiss 12:2e8fda56093f 433
jreiss 12:2e8fda56093f 434 uint8_t CustomChannelPlan_US915::HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) {
jreiss 12:2e8fda56093f 435 status = 0x07;
jreiss 12:2e8fda56093f 436 int8_t datarate = 0;
jreiss 12:2e8fda56093f 437 int8_t drOffset = 0;
jreiss 12:2e8fda56093f 438 uint32_t freq = 0;
jreiss 12:2e8fda56093f 439
jreiss 12:2e8fda56093f 440 drOffset = payload[index++];
jreiss 12:2e8fda56093f 441 datarate = drOffset & 0x0F;
jreiss 12:2e8fda56093f 442 drOffset = (drOffset >> 4) & 0x07;
jreiss 12:2e8fda56093f 443
jreiss 12:2e8fda56093f 444 freq = payload[index++];
jreiss 12:2e8fda56093f 445 freq |= payload[index++] << 8;
jreiss 12:2e8fda56093f 446 freq |= payload[index++] << 16;
jreiss 12:2e8fda56093f 447 freq *= 100;
jreiss 12:2e8fda56093f 448
jreiss 12:2e8fda56093f 449 if (!CheckRfFrequency(freq)) {
jreiss 12:2e8fda56093f 450 logInfo("Freq KO");
jreiss 12:2e8fda56093f 451 status &= 0xFE; // Channel frequency KO
jreiss 12:2e8fda56093f 452 }
jreiss 12:2e8fda56093f 453
jreiss 12:2e8fda56093f 454 if (datarate < _minRx2Datarate || datarate > _maxRx2Datarate) {
jreiss 12:2e8fda56093f 455 logInfo("DR KO");
jreiss 12:2e8fda56093f 456 status &= 0xFD; // Datarate KO
jreiss 12:2e8fda56093f 457 }
jreiss 12:2e8fda56093f 458
jreiss 12:2e8fda56093f 459 if (drOffset < 0 || drOffset > _maxDatarateOffset) {
jreiss 12:2e8fda56093f 460 logInfo("DR Offset KO");
jreiss 12:2e8fda56093f 461 status &= 0xFB; // Rx1DrOffset range KO
jreiss 12:2e8fda56093f 462 }
jreiss 12:2e8fda56093f 463
jreiss 12:2e8fda56093f 464 if ((status & 0x07) == 0x07) {
jreiss 12:2e8fda56093f 465 logInfo("RxParamSetup accepted Rx2DR: %d Rx2Freq: %d Rx1Offset: %d", datarate, freq, drOffset);
jreiss 12:2e8fda56093f 466 SetRx2DatarateIndex(datarate);
jreiss 12:2e8fda56093f 467 SetRx2Frequency(freq);
jreiss 12:2e8fda56093f 468 SetRx1Offset(drOffset);
jreiss 12:2e8fda56093f 469 } else {
jreiss 12:2e8fda56093f 470 logInfo("RxParamSetup rejected Rx2DR: %d Rx2Freq: %d Rx1Offset: %d", datarate, freq, drOffset);
jreiss 12:2e8fda56093f 471 }
jreiss 12:2e8fda56093f 472
jreiss 12:2e8fda56093f 473 return LORA_OK;
jreiss 12:2e8fda56093f 474 }
jreiss 12:2e8fda56093f 475
jreiss 12:2e8fda56093f 476 uint8_t CustomChannelPlan_US915::HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) {
jreiss 12:2e8fda56093f 477
jreiss 12:2e8fda56093f 478 // Not Supported in US915
jreiss 12:2e8fda56093f 479 status = 0;
jreiss 12:2e8fda56093f 480 return LORA_OK;
jreiss 12:2e8fda56093f 481 }
jreiss 12:2e8fda56093f 482
jreiss 12:2e8fda56093f 483 uint8_t CustomChannelPlan_US915::HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) {
jreiss 12:2e8fda56093f 484
jreiss 12:2e8fda56093f 485 lora::CopyFreqtoInt(payload + index, _beaconRxChannel.Frequency);
jreiss 12:2e8fda56093f 486 index += 3;
jreiss 12:2e8fda56093f 487
jreiss 12:2e8fda56093f 488 if (_beaconRxChannel.Frequency != 0) {
jreiss 12:2e8fda56093f 489 _beaconRxChannel.DrRange.Value = payload[index];
jreiss 12:2e8fda56093f 490 } else {
jreiss 12:2e8fda56093f 491 // TODO: set to default beacon rx channel
jreiss 12:2e8fda56093f 492 }
jreiss 12:2e8fda56093f 493
jreiss 12:2e8fda56093f 494 status = 0x03;
jreiss 12:2e8fda56093f 495 return LORA_OK;
jreiss 12:2e8fda56093f 496 }
jreiss 12:2e8fda56093f 497
jreiss 12:2e8fda56093f 498 uint8_t CustomChannelPlan_US915::HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) {
jreiss 11:829f8c2ec1c3 499
jreiss 12:2e8fda56093f 500 status = 0x03;
jreiss 12:2e8fda56093f 501 Channel chParam;
jreiss 12:2e8fda56093f 502
jreiss 12:2e8fda56093f 503 // Skip channel index
jreiss 12:2e8fda56093f 504 index++;
jreiss 12:2e8fda56093f 505
jreiss 12:2e8fda56093f 506 lora::CopyFreqtoInt(payload + index, chParam.Frequency);
jreiss 12:2e8fda56093f 507 index += 3;
jreiss 12:2e8fda56093f 508 chParam.DrRange.Value = payload[index++];
jreiss 12:2e8fda56093f 509
jreiss 12:2e8fda56093f 510 if (!_radio.CheckRfFrequency(chParam.Frequency)) {
jreiss 12:2e8fda56093f 511 status &= 0xFE; // Channel frequency KO
jreiss 12:2e8fda56093f 512 }
jreiss 12:2e8fda56093f 513
jreiss 12:2e8fda56093f 514 if (chParam.DrRange.Fields.Min < chParam.DrRange.Fields.Max) {
jreiss 12:2e8fda56093f 515 status &= 0xFD; // Datarate range KO
jreiss 12:2e8fda56093f 516 } else if (chParam.DrRange.Fields.Min < _minDatarate || chParam.DrRange.Fields.Min > _maxDatarate) {
jreiss 12:2e8fda56093f 517 status &= 0xFD; // Datarate range KO
jreiss 12:2e8fda56093f 518 } else if (chParam.DrRange.Fields.Max < _minDatarate || chParam.DrRange.Fields.Max > _maxDatarate) {
jreiss 12:2e8fda56093f 519 status &= 0xFD; // Datarate range KO
jreiss 12:2e8fda56093f 520 }
jreiss 12:2e8fda56093f 521
jreiss 12:2e8fda56093f 522 if ((status & 0x03) == 0x03) {
jreiss 12:2e8fda56093f 523 _beaconChannel = chParam;
jreiss 12:2e8fda56093f 524 }
jreiss 12:2e8fda56093f 525
jreiss 12:2e8fda56093f 526 if (_beaconChannel.Frequency == 0) {
jreiss 12:2e8fda56093f 527 // TODO: Set to default
jreiss 12:2e8fda56093f 528 }
jreiss 12:2e8fda56093f 529
jreiss 12:2e8fda56093f 530 status = 0x01;
jreiss 12:2e8fda56093f 531
jreiss 12:2e8fda56093f 532 return LORA_OK;
jreiss 12:2e8fda56093f 533 }
jreiss 12:2e8fda56093f 534
jreiss 12:2e8fda56093f 535 bool CustomChannelPlan_US915::AdrAckReq() {
jreiss 12:2e8fda56093f 536 if (_settings.Network.ADREnabled == false)
jreiss 12:2e8fda56093f 537 return false;
jreiss 12:2e8fda56093f 538
jreiss 12:2e8fda56093f 539 bool ret = false;
jreiss 12:2e8fda56093f 540
jreiss 12:2e8fda56093f 541 if (_settings.Session.TxDatarate == MIN_DATARATE) {
jreiss 12:2e8fda56093f 542 _settings.Session.AdrCounter = 0;
jreiss 12:2e8fda56093f 543 } else {
jreiss 12:2e8fda56093f 544 logDebug("ADR ACK CNT: %d LIMIT: %d DELAY: %d", _settings.Session.AdrCounter, ADR_ACK_LIMIT, ADR_ACK_DELAY);
jreiss 12:2e8fda56093f 545
jreiss 12:2e8fda56093f 546 ret = (_settings.Session.AdrCounter >= ADR_ACK_LIMIT);
jreiss 12:2e8fda56093f 547
jreiss 12:2e8fda56093f 548 if (_settings.Session.AdrCounter >= (ADR_ACK_LIMIT + ADR_ACK_DELAY)) {
jreiss 12:2e8fda56093f 549 if (_settings.Session.AdrCounter - 1 % ADR_ACK_DELAY == 0) {
jreiss 12:2e8fda56093f 550
jreiss 12:2e8fda56093f 551 if (_settings.Session.TxDatarate > MIN_DATARATE) {
jreiss 12:2e8fda56093f 552 _settings.Session.TxDatarate--;
jreiss 12:2e8fda56093f 553 }
jreiss 12:2e8fda56093f 554
jreiss 12:2e8fda56093f 555 if (_settings.Session.TxDatarate == MIN_DATARATE) {
jreiss 12:2e8fda56093f 556 EnableDefaultChannels();
jreiss 12:2e8fda56093f 557 }
jreiss 12:2e8fda56093f 558 }
jreiss 12:2e8fda56093f 559 }
jreiss 12:2e8fda56093f 560 }
jreiss 12:2e8fda56093f 561
jreiss 12:2e8fda56093f 562 return ret;
jreiss 12:2e8fda56093f 563 }
jreiss 12:2e8fda56093f 564
jreiss 12:2e8fda56093f 565 uint8_t CustomChannelPlan_US915::HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) {
jreiss 12:2e8fda56093f 566
jreiss 12:2e8fda56093f 567 uint8_t power = 0;
jreiss 12:2e8fda56093f 568 uint8_t datarate = 0;
jreiss 12:2e8fda56093f 569 uint16_t mask = 0;
jreiss 12:2e8fda56093f 570 uint8_t ctrl = 0;
jreiss 12:2e8fda56093f 571 uint8_t nbRep = 0;
jreiss 12:2e8fda56093f 572
jreiss 12:2e8fda56093f 573 status = 0x07;
jreiss 12:2e8fda56093f 574 datarate = payload[index++];
jreiss 12:2e8fda56093f 575 power = datarate & 0x0F;
jreiss 12:2e8fda56093f 576 datarate = (datarate >> 4) & 0x0F;
jreiss 12:2e8fda56093f 577
jreiss 12:2e8fda56093f 578 mask = payload[index++];
jreiss 12:2e8fda56093f 579 mask |= payload[index++] << 8;
jreiss 12:2e8fda56093f 580
jreiss 12:2e8fda56093f 581 nbRep = payload[index++];
jreiss 12:2e8fda56093f 582 ctrl = (nbRep >> 4) & 0x07;
jreiss 12:2e8fda56093f 583 nbRep &= 0x0F;
jreiss 12:2e8fda56093f 584
jreiss 12:2e8fda56093f 585 if (nbRep == 0) {
jreiss 12:2e8fda56093f 586 nbRep = 1;
jreiss 12:2e8fda56093f 587 }
jreiss 12:2e8fda56093f 588
jreiss 12:2e8fda56093f 589 if (!(mask == 0 && ctrl == 0)) {
jreiss 12:2e8fda56093f 590 if (ctrl == 5) {
jreiss 12:2e8fda56093f 591 mask = 0;
jreiss 12:2e8fda56093f 592 ctrl = 0;
jreiss 12:2e8fda56093f 593 }
jreiss 12:2e8fda56093f 594 }
jreiss 12:2e8fda56093f 595
jreiss 12:2e8fda56093f 596 if (datarate > _maxDatarate) {
jreiss 12:2e8fda56093f 597 logDebug("ADR Datarate KO");
jreiss 12:2e8fda56093f 598 status &= 0xFD; // Datarate KO
jreiss 12:2e8fda56093f 599 }
jreiss 12:2e8fda56093f 600 //
jreiss 12:2e8fda56093f 601 // Remark MaxTxPower = 0 and MinTxPower = 5
jreiss 12:2e8fda56093f 602 //
jreiss 12:2e8fda56093f 603 if (TX_POWERS[power] < _minTxPower || TX_POWERS[power] > _maxTxPower) {
jreiss 12:2e8fda56093f 604 logDebug("ADR TxPower KO");
jreiss 12:2e8fda56093f 605 status &= 0xFB; // TxPower KO
jreiss 12:2e8fda56093f 606 }
jreiss 12:2e8fda56093f 607
jreiss 12:2e8fda56093f 608 if (ctrl == 7 && mask == 0) {
jreiss 12:2e8fda56093f 609 // reject command to disable all channels
jreiss 12:2e8fda56093f 610 logWarning("Rejecting ADR command to disable all channels");
jreiss 12:2e8fda56093f 611 status &= 0xFE; // ChannelMask KO
jreiss 12:2e8fda56093f 612 }
jreiss 12:2e8fda56093f 613
jreiss 12:2e8fda56093f 614 uint8_t chans_enabled = 0;
jreiss 12:2e8fda56093f 615
jreiss 12:2e8fda56093f 616 if (ctrl <= 3) {
jreiss 12:2e8fda56093f 617 // at least 6 - 125 kHz channel must be enabled
jreiss 12:2e8fda56093f 618 chans_enabled += CountBits(_channelMask[0]);
jreiss 12:2e8fda56093f 619 chans_enabled += CountBits(_channelMask[1]);
jreiss 12:2e8fda56093f 620 chans_enabled += CountBits(_channelMask[2]);
jreiss 12:2e8fda56093f 621 chans_enabled += CountBits(_channelMask[3]);
jreiss 12:2e8fda56093f 622 chans_enabled -= CountBits(_channelMask[ctrl]);
jreiss 12:2e8fda56093f 623 chans_enabled += CountBits(mask);
jreiss 12:2e8fda56093f 624
jreiss 12:2e8fda56093f 625 if (chans_enabled == 0) {
jreiss 12:2e8fda56093f 626 // reject command
jreiss 12:2e8fda56093f 627 logWarning("Rejecting ADR command to disable all channels");
jreiss 12:2e8fda56093f 628 status &= 0xFE; // ChannelMask KO
jreiss 12:2e8fda56093f 629 }
jreiss 12:2e8fda56093f 630 }
jreiss 12:2e8fda56093f 631
jreiss 12:2e8fda56093f 632 if (datarate < DR_4) {
jreiss 12:2e8fda56093f 633 if (ctrl > 3) {
jreiss 12:2e8fda56093f 634 chans_enabled += CountBits(_channelMask[0]);
jreiss 12:2e8fda56093f 635 chans_enabled += CountBits(_channelMask[1]);
jreiss 12:2e8fda56093f 636 chans_enabled += CountBits(_channelMask[2]);
jreiss 12:2e8fda56093f 637 chans_enabled += CountBits(_channelMask[3]);
jreiss 12:2e8fda56093f 638 }
jreiss 12:2e8fda56093f 639 if (chans_enabled == 0 || ctrl == 7) {
jreiss 12:2e8fda56093f 640 status &= 0xFD; // Datarate KO
jreiss 12:2e8fda56093f 641 }
jreiss 12:2e8fda56093f 642 } else if (datarate == DR_4) {
jreiss 12:2e8fda56093f 643 if ((ctrl == 4 || ctrl == 6) && ((mask & 0xFF) == 0)) {
jreiss 12:2e8fda56093f 644 status &= 0xFD; // Datarate KO
jreiss 12:2e8fda56093f 645 }
jreiss 12:2e8fda56093f 646 } else if ((_channelMask[4] & 0xFF) == 0) {
jreiss 12:2e8fda56093f 647 status &= 0xFD; // Datarate KO
jreiss 12:2e8fda56093f 648 }
jreiss 12:2e8fda56093f 649
jreiss 12:2e8fda56093f 650 if ((status & 0x07) == 0x07) {
jreiss 12:2e8fda56093f 651 logDebug("ADR settings accepted");
jreiss 12:2e8fda56093f 652
jreiss 12:2e8fda56093f 653 if (_settings.Network.ADREnabled) {
jreiss 12:2e8fda56093f 654 _settings.Session.TxDatarate = datarate;
jreiss 12:2e8fda56093f 655 _settings.Session.TxPower = TX_POWERS[power];
jreiss 12:2e8fda56093f 656 } else {
jreiss 12:2e8fda56093f 657 logInfo("ADR is disabled, DR and Power not changed.");
jreiss 12:2e8fda56093f 658 status &= 0xFB; // TxPower KO
jreiss 12:2e8fda56093f 659 status &= 0xFD; // Datarate KO
jreiss 12:2e8fda56093f 660 }
jreiss 12:2e8fda56093f 661
jreiss 12:2e8fda56093f 662 if (ctrl == 6) {
jreiss 12:2e8fda56093f 663 // enable all 125 kHz channels
jreiss 12:2e8fda56093f 664 SetChannelMask(0, 0xFFFF);
jreiss 12:2e8fda56093f 665 SetChannelMask(1, 0xFFFF);
jreiss 12:2e8fda56093f 666 SetChannelMask(2, 0xFFFF);
jreiss 12:2e8fda56093f 667 SetChannelMask(3, 0xFFFF);
jreiss 12:2e8fda56093f 668 SetChannelMask(4, mask);
jreiss 12:2e8fda56093f 669 } else if (ctrl == 7) {
jreiss 12:2e8fda56093f 670 // disable all 125 kHz channels
jreiss 12:2e8fda56093f 671 SetChannelMask(0, 0x0);
jreiss 12:2e8fda56093f 672 SetChannelMask(1, 0x0);
jreiss 12:2e8fda56093f 673 SetChannelMask(2, 0x0);
jreiss 12:2e8fda56093f 674 SetChannelMask(3, 0x0);
jreiss 12:2e8fda56093f 675 SetChannelMask(4, mask);
jreiss 12:2e8fda56093f 676 } else {
jreiss 12:2e8fda56093f 677 SetChannelMask(ctrl, mask);
jreiss 12:2e8fda56093f 678 }
jreiss 12:2e8fda56093f 679
jreiss 12:2e8fda56093f 680 _settings.Session.Redundancy = nbRep;
jreiss 12:2e8fda56093f 681 }
jreiss 12:2e8fda56093f 682
jreiss 12:2e8fda56093f 683 logDebug("ADR DR: %u PWR: %u Ctrl: %02x Mask: %04x NbRep: %u Stat: %02x", datarate, power, ctrl, mask, nbRep, status);
jreiss 12:2e8fda56093f 684
jreiss 12:2e8fda56093f 685 return LORA_OK;
jreiss 12:2e8fda56093f 686 }
jreiss 12:2e8fda56093f 687
jreiss 12:2e8fda56093f 688 uint32_t CustomChannelPlan_US915::GetTimeOffAir()
jreiss 12:2e8fda56093f 689 {
jreiss 12:2e8fda56093f 690 if (_settings.Test.DisableDutyCycle == lora::ON)
jreiss 12:2e8fda56093f 691 return 0;
jreiss 12:2e8fda56093f 692
jreiss 12:2e8fda56093f 693 uint32_t min = 0;
jreiss 12:2e8fda56093f 694 uint32_t now = _dutyCycleTimer.read_ms();
jreiss 12:2e8fda56093f 695
jreiss 12:2e8fda56093f 696 if (_settings.Session.AggregatedTimeOffEnd > 0 && _settings.Session.AggregatedTimeOffEnd > now) {
jreiss 12:2e8fda56093f 697 min = std::max < uint32_t > (min, _settings.Session.AggregatedTimeOffEnd - now);
jreiss 12:2e8fda56093f 698 }
jreiss 12:2e8fda56093f 699
jreiss 12:2e8fda56093f 700 now = time(NULL);
jreiss 12:2e8fda56093f 701 uint32_t join_time = 0;
jreiss 12:2e8fda56093f 702
jreiss 12:2e8fda56093f 703 if (_settings.Session.JoinFirstAttempt != 0 && now < _settings.Session.JoinTimeOffEnd) {
jreiss 12:2e8fda56093f 704 join_time = (_settings.Session.JoinTimeOffEnd - now) * 1000;
jreiss 12:2e8fda56093f 705 }
jreiss 12:2e8fda56093f 706
jreiss 12:2e8fda56093f 707 min = std::max < uint32_t > (join_time, min);
jreiss 12:2e8fda56093f 708
jreiss 12:2e8fda56093f 709 return min;
jreiss 12:2e8fda56093f 710 }
jreiss 12:2e8fda56093f 711
jreiss 12:2e8fda56093f 712 std::vector<uint32_t> lora::CustomChannelPlan_US915::GetChannels() {
jreiss 12:2e8fda56093f 713 std::vector < uint32_t > chans;
jreiss 12:2e8fda56093f 714
jreiss 12:2e8fda56093f 715 if (_settings.Network.ChannelGroup > 0) {
jreiss 12:2e8fda56093f 716 uint8_t chans_per_group = 8;
jreiss 12:2e8fda56093f 717 size_t start = (_settings.Network.ChannelGroup - 1) * chans_per_group;
jreiss 12:2e8fda56093f 718 for (int8_t i = start; i < int8_t(start + chans_per_group); i++) {
jreiss 12:2e8fda56093f 719 chans.push_back(GetChannel(i).Frequency);
jreiss 12:2e8fda56093f 720 }
jreiss 12:2e8fda56093f 721 chans.push_back(GetChannel(_numChans125k + (_settings.Network.ChannelGroup - 1)).Frequency);
jreiss 12:2e8fda56093f 722 chans.push_back(GetRxWindow(2).Frequency);
jreiss 12:2e8fda56093f 723 } else {
jreiss 12:2e8fda56093f 724 for (int8_t i = 0; i < _numChans; i++) {
jreiss 12:2e8fda56093f 725 chans.push_back(GetChannel(i).Frequency);
jreiss 12:2e8fda56093f 726 }
jreiss 12:2e8fda56093f 727 chans.push_back(GetRxWindow(2).Frequency);
jreiss 12:2e8fda56093f 728 }
jreiss 12:2e8fda56093f 729
jreiss 12:2e8fda56093f 730 return chans;
jreiss 12:2e8fda56093f 731 }
jreiss 12:2e8fda56093f 732
jreiss 12:2e8fda56093f 733 std::vector<uint8_t> lora::CustomChannelPlan_US915::GetChannelRanges() {
jreiss 12:2e8fda56093f 734 std::vector < uint8_t > ranges;
jreiss 12:2e8fda56093f 735
jreiss 12:2e8fda56093f 736 if (_settings.Network.ChannelGroup > 0) {
jreiss 12:2e8fda56093f 737 uint8_t chans_per_group = 8;
jreiss 12:2e8fda56093f 738 size_t start = (_settings.Network.ChannelGroup - 1) * chans_per_group;
jreiss 12:2e8fda56093f 739 for (int8_t i = start; i < int8_t(start + chans_per_group); i++) {
jreiss 12:2e8fda56093f 740 ranges.push_back(GetChannel(i).DrRange.Value);
jreiss 12:2e8fda56093f 741 }
jreiss 12:2e8fda56093f 742 ranges.push_back(GetChannel(_numChans125k + (_settings.Network.ChannelGroup - 1)).DrRange.Value);
jreiss 12:2e8fda56093f 743 ranges.push_back(GetRxWindow(2).DatarateIndex);
jreiss 12:2e8fda56093f 744 } else {
jreiss 12:2e8fda56093f 745 for (int8_t i = 0; i < _numChans; i++) {
jreiss 12:2e8fda56093f 746 ranges.push_back(GetChannel(i).DrRange.Value);
jreiss 12:2e8fda56093f 747 }
jreiss 12:2e8fda56093f 748 ranges.push_back(GetRxWindow(2).DatarateIndex);
jreiss 12:2e8fda56093f 749 }
jreiss 12:2e8fda56093f 750
jreiss 12:2e8fda56093f 751 ranges.push_back(GetRxWindow(2).DatarateIndex);
jreiss 12:2e8fda56093f 752
jreiss 12:2e8fda56093f 753 return ranges;
jreiss 12:2e8fda56093f 754
jreiss 12:2e8fda56093f 755 }
jreiss 12:2e8fda56093f 756
jreiss 12:2e8fda56093f 757 void lora::CustomChannelPlan_US915::EnableDefaultChannels() {
jreiss 12:2e8fda56093f 758 SetChannelGroup(GetChannelGroup());
jreiss 12:2e8fda56093f 759 }
jreiss 12:2e8fda56093f 760
jreiss 12:2e8fda56093f 761 uint8_t CustomChannelPlan_US915::GetNextChannel()
jreiss 12:2e8fda56093f 762 {
jreiss 12:2e8fda56093f 763 if (_settings.Session.AggregatedTimeOffEnd != 0) {
jreiss 12:2e8fda56093f 764 return LORA_AGGREGATED_DUTY_CYCLE;
jreiss 12:2e8fda56093f 765 }
jreiss 12:2e8fda56093f 766
jreiss 12:2e8fda56093f 767 if (P2PEnabled() || _settings.Network.TxFrequency != 0) {
jreiss 12:2e8fda56093f 768 logDebug("Using frequency %d", _settings.Network.TxFrequency);
jreiss 12:2e8fda56093f 769
jreiss 12:2e8fda56093f 770 if (_settings.Test.DisableDutyCycle != lora::ON) {
jreiss 12:2e8fda56093f 771 int8_t band = GetDutyBand(_settings.Network.TxFrequency);
jreiss 12:2e8fda56093f 772 logDebug("band: %d freq: %d", band, _settings.Network.TxFrequency);
jreiss 12:2e8fda56093f 773 if (band != -1 && _dutyBands[band].TimeOffEnd != 0) {
jreiss 12:2e8fda56093f 774 return LORA_NO_CHANS_ENABLED;
jreiss 12:2e8fda56093f 775 }
jreiss 12:2e8fda56093f 776 }
jreiss 12:2e8fda56093f 777
jreiss 12:2e8fda56093f 778 _radio.SetChannel(_settings.Network.TxFrequency);
jreiss 12:2e8fda56093f 779 return LORA_OK;
jreiss 12:2e8fda56093f 780 }
jreiss 12:2e8fda56093f 781
jreiss 12:2e8fda56093f 782 uint8_t start = 0;
jreiss 12:2e8fda56093f 783 uint8_t maxChannels = _numChans125k;
jreiss 12:2e8fda56093f 784 uint8_t nbEnabledChannels = 0;
jreiss 12:2e8fda56093f 785 uint8_t *enabledChannels = new uint8_t[maxChannels];
jreiss 12:2e8fda56093f 786
jreiss 12:2e8fda56093f 787 if (GetTxDatarate().Bandwidth == BW_500) {
jreiss 12:2e8fda56093f 788 maxChannels = _numChans500k;
jreiss 12:2e8fda56093f 789 start = _numChans125k;
jreiss 12:2e8fda56093f 790 }
jreiss 12:2e8fda56093f 791
jreiss 12:2e8fda56093f 792 // Search how many channels are enabled
jreiss 12:2e8fda56093f 793 DatarateRange range;
jreiss 12:2e8fda56093f 794 uint8_t dr_index = _settings.Session.TxDatarate;
jreiss 12:2e8fda56093f 795 uint32_t now = _dutyCycleTimer.read_ms();
jreiss 12:2e8fda56093f 796
jreiss 12:2e8fda56093f 797 for (size_t i = 0; i < _dutyBands.size(); i++) {
jreiss 12:2e8fda56093f 798 if (_dutyBands[i].TimeOffEnd < now || _settings.Test.DisableDutyCycle == lora::ON) {
jreiss 12:2e8fda56093f 799 _dutyBands[i].TimeOffEnd = 0;
jreiss 12:2e8fda56093f 800 }
jreiss 12:2e8fda56093f 801 }
jreiss 12:2e8fda56093f 802
jreiss 12:2e8fda56093f 803 for (uint8_t i = start; i < start + maxChannels; i++) {
jreiss 12:2e8fda56093f 804 range = GetChannel(i).DrRange;
jreiss 12:2e8fda56093f 805 // logDebug("chan: %d freq: %d range:%02x", i, GetChannel(i).Frequency, range.Value);
jreiss 12:2e8fda56093f 806
jreiss 12:2e8fda56093f 807 if (IsChannelEnabled(i) && (dr_index >= range.Fields.Min && dr_index <= range.Fields.Max)) {
jreiss 12:2e8fda56093f 808 int8_t band = GetDutyBand(GetChannel(i).Frequency);
jreiss 12:2e8fda56093f 809 // logDebug("band: %d freq: %d", band, _channels[i].Frequency);
jreiss 12:2e8fda56093f 810 if (band != -1 && _dutyBands[band].TimeOffEnd == 0) {
jreiss 12:2e8fda56093f 811 enabledChannels[nbEnabledChannels++] = i;
jreiss 12:2e8fda56093f 812 }
jreiss 12:2e8fda56093f 813 }
jreiss 12:2e8fda56093f 814 }
jreiss 12:2e8fda56093f 815
jreiss 12:2e8fda56093f 816 if (GetTxDatarate().Bandwidth == BW_500) {
jreiss 12:2e8fda56093f 817 _dutyBands[0].PowerMax = 26;
jreiss 12:2e8fda56093f 818 } else {
jreiss 12:2e8fda56093f 819 if (nbEnabledChannels < 50)
jreiss 12:2e8fda56093f 820 _dutyBands[0].PowerMax = 21;
jreiss 12:2e8fda56093f 821 else
jreiss 12:2e8fda56093f 822 _dutyBands[0].PowerMax = 30;
jreiss 12:2e8fda56093f 823 }
jreiss 12:2e8fda56093f 824
jreiss 12:2e8fda56093f 825 logTrace("Number of available channels: %d", nbEnabledChannels);
jreiss 12:2e8fda56093f 826
jreiss 12:2e8fda56093f 827 uint32_t freq = 0;
jreiss 12:2e8fda56093f 828 uint8_t sf = GetTxDatarate().SpreadingFactor;
jreiss 12:2e8fda56093f 829 uint8_t bw = GetTxDatarate().Bandwidth;
jreiss 12:2e8fda56093f 830 int16_t thres = DEFAULT_FREE_CHAN_RSSI_THRESHOLD;
jreiss 12:2e8fda56093f 831
jreiss 12:2e8fda56093f 832 if (nbEnabledChannels == 0) {
jreiss 12:2e8fda56093f 833 delete [] enabledChannels;
jreiss 12:2e8fda56093f 834 return LORA_NO_CHANS_ENABLED;
jreiss 12:2e8fda56093f 835 }
jreiss 12:2e8fda56093f 836
jreiss 12:2e8fda56093f 837 if (_settings.Network.CADEnabled) {
jreiss 12:2e8fda56093f 838 // Search for free channel with ms timeout
jreiss 12:2e8fda56093f 839 int16_t timeout = 10000;
jreiss 12:2e8fda56093f 840 Timer tmr;
jreiss 12:2e8fda56093f 841 tmr.start();
jreiss 12:2e8fda56093f 842
jreiss 12:2e8fda56093f 843 for (uint8_t j = rand_r(0, nbEnabledChannels - 1); tmr.read_ms() < timeout; j++) {
jreiss 12:2e8fda56093f 844 freq = GetChannel(enabledChannels[j]).Frequency;
jreiss 12:2e8fda56093f 845
jreiss 12:2e8fda56093f 846 if (_radio.IsChannelFree(SxRadio::MODEM_LORA, freq, sf, thres, bw)) {
jreiss 12:2e8fda56093f 847 _txChannel = enabledChannels[j];
jreiss 12:2e8fda56093f 848 break;
jreiss 12:2e8fda56093f 849 }
jreiss 12:2e8fda56093f 850 }
jreiss 12:2e8fda56093f 851 } else {
jreiss 12:2e8fda56093f 852 uint8_t j = rand_r(0, nbEnabledChannels - 1);
jreiss 12:2e8fda56093f 853 _txChannel = enabledChannels[j];
jreiss 12:2e8fda56093f 854 freq = GetChannel(_txChannel).Frequency;
jreiss 12:2e8fda56093f 855 }
jreiss 12:2e8fda56093f 856
jreiss 12:2e8fda56093f 857 assert(freq != 0);
jreiss 12:2e8fda56093f 858
jreiss 12:2e8fda56093f 859 logDebug("Using channel %d : %d", _txChannel, freq);
jreiss 12:2e8fda56093f 860 _radio.SetChannel(freq);
jreiss 12:2e8fda56093f 861
jreiss 12:2e8fda56093f 862 delete [] enabledChannels;
jreiss 12:2e8fda56093f 863 return LORA_OK;
jreiss 12:2e8fda56093f 864 }
jreiss 12:2e8fda56093f 865
jreiss 12:2e8fda56093f 866 uint8_t lora::CustomChannelPlan_US915::GetJoinDatarate() {
jreiss 12:2e8fda56093f 867 uint8_t dr = _settings.Session.TxDatarate;
jreiss 12:2e8fda56093f 868
jreiss 12:2e8fda56093f 869 if (_settings.Test.DisableRandomJoinDatarate == lora::OFF) {
jreiss 12:2e8fda56093f 870 static bool altDatarate = false;
jreiss 12:2e8fda56093f 871
jreiss 12:2e8fda56093f 872 if (_settings.Network.ChannelGroup == 0) {
jreiss 12:2e8fda56093f 873 static uint16_t used_bands_125k = 0;
jreiss 12:2e8fda56093f 874 static uint16_t used_bands_500k = 0;
jreiss 12:2e8fda56093f 875 uint8_t chan_group = 0;
jreiss 12:2e8fda56093f 876
jreiss 12:2e8fda56093f 877 if (altDatarate) {
jreiss 12:2e8fda56093f 878 // 500k channel
jreiss 12:2e8fda56093f 879 if (CountBits(used_bands_500k) == 8) {
jreiss 12:2e8fda56093f 880 used_bands_500k = 0;
jreiss 12:2e8fda56093f 881 }
jreiss 12:2e8fda56093f 882 while ((chan_group = rand_r(1, 8)) && (used_bands_500k & (1 << (chan_group - 1))) != 0)
jreiss 12:2e8fda56093f 883 ;
jreiss 12:2e8fda56093f 884 used_bands_500k |= (1 << (chan_group - 1));
jreiss 12:2e8fda56093f 885 } else {
jreiss 12:2e8fda56093f 886 // 125k channel
jreiss 12:2e8fda56093f 887 if (CountBits(used_bands_125k) == 8) {
jreiss 12:2e8fda56093f 888 used_bands_125k = 0;
jreiss 12:2e8fda56093f 889 }
jreiss 12:2e8fda56093f 890 while ((chan_group = rand_r(1, 8)) && (used_bands_125k & (1 << (chan_group - 1))) != 0)
jreiss 12:2e8fda56093f 891 ;
jreiss 12:2e8fda56093f 892 used_bands_125k |= (1 << (chan_group - 1));
jreiss 12:2e8fda56093f 893 }
jreiss 12:2e8fda56093f 894
jreiss 12:2e8fda56093f 895 logWarning("JoinDatarate setting channel group to %d 125k: %04x 500k: %04x", chan_group, used_bands_125k, used_bands_500k);
jreiss 12:2e8fda56093f 896 SetChannelGroup(chan_group);
jreiss 12:2e8fda56093f 897 }
jreiss 12:2e8fda56093f 898
jreiss 12:2e8fda56093f 899 if (altDatarate && CountBits(_channelMask[4] > 0)) {
jreiss 12:2e8fda56093f 900 dr = lora::DR_4;
jreiss 12:2e8fda56093f 901 } else {
jreiss 12:2e8fda56093f 902 dr = lora::DR_0;
jreiss 12:2e8fda56093f 903 }
jreiss 12:2e8fda56093f 904 altDatarate = !altDatarate;
jreiss 12:2e8fda56093f 905 }
jreiss 12:2e8fda56093f 906
jreiss 12:2e8fda56093f 907 return dr;
jreiss 12:2e8fda56093f 908 }
jreiss 12:2e8fda56093f 909
jreiss 12:2e8fda56093f 910 uint8_t lora::CustomChannelPlan_US915::CalculateJoinBackoff(uint8_t size) {
jreiss 12:2e8fda56093f 911
jreiss 12:2e8fda56093f 912 time_t now = time(NULL);
jreiss 12:2e8fda56093f 913 uint32_t time_on_max = 0;
jreiss 12:2e8fda56093f 914 static uint32_t time_off_max = 15;
jreiss 12:2e8fda56093f 915 uint32_t rand_time_off = 0;
jreiss 12:2e8fda56093f 916 static uint16_t join_cnt = 0;
jreiss 12:2e8fda56093f 917
jreiss 12:2e8fda56093f 918 // TODO: calc time-off-max based on RTC time from JoinFirstAttempt, time-off-max is lost over sleep
jreiss 12:2e8fda56093f 919
jreiss 12:2e8fda56093f 920 if (_settings.Session.JoinTimeOffEnd > now) {
jreiss 12:2e8fda56093f 921 return LORA_JOIN_BACKOFF;
jreiss 12:2e8fda56093f 922 }
jreiss 12:2e8fda56093f 923
jreiss 12:2e8fda56093f 924 uint32_t secs_since_first_attempt = (now - _settings.Session.JoinFirstAttempt);
jreiss 12:2e8fda56093f 925 uint16_t hours_since_first_attempt = secs_since_first_attempt / (60 * 60);
jreiss 12:2e8fda56093f 926
jreiss 12:2e8fda56093f 927 join_cnt = ++join_cnt % 16;
jreiss 12:2e8fda56093f 928
jreiss 12:2e8fda56093f 929 if (_settings.Session.JoinFirstAttempt == 0) {
jreiss 12:2e8fda56093f 930 /* 1 % duty-cycle for first hour
jreiss 12:2e8fda56093f 931 * 0.1 % next 10 hours
jreiss 12:2e8fda56093f 932 * 0.01 % upto 24 hours */
jreiss 12:2e8fda56093f 933 _settings.Session.JoinFirstAttempt = now;
jreiss 12:2e8fda56093f 934 _settings.Session.JoinTimeOnAir += GetTimeOnAir(size);
jreiss 12:2e8fda56093f 935 _settings.Session.JoinTimeOffEnd = now + rand_r(_settings.Network.JoinDelay + 2, _settings.Network.JoinDelay + 3);
jreiss 12:2e8fda56093f 936 } else if (join_cnt == 0) {
jreiss 12:2e8fda56093f 937 if (hours_since_first_attempt < 1) {
jreiss 12:2e8fda56093f 938 time_on_max = 36000;
jreiss 12:2e8fda56093f 939 rand_time_off = rand_r(time_off_max - 1, time_off_max + 1);
jreiss 12:2e8fda56093f 940 // time off max 1 hour
jreiss 12:2e8fda56093f 941 time_off_max = std::min < uint32_t > (time_off_max * 2, 60 * 60);
jreiss 12:2e8fda56093f 942
jreiss 12:2e8fda56093f 943 if (_settings.Session.JoinTimeOnAir < time_on_max) {
jreiss 12:2e8fda56093f 944 _settings.Session.JoinTimeOnAir += GetTimeOnAir(size);
jreiss 12:2e8fda56093f 945 _settings.Session.JoinTimeOffEnd = now + rand_time_off;
jreiss 12:2e8fda56093f 946 } else {
jreiss 12:2e8fda56093f 947 logWarning("Max time-on-air limit met for current join backoff period");
jreiss 12:2e8fda56093f 948 _settings.Session.JoinTimeOffEnd = _settings.Session.JoinFirstAttempt + 60 * 60;
jreiss 12:2e8fda56093f 949 }
jreiss 12:2e8fda56093f 950 } else if (hours_since_first_attempt < 11) {
jreiss 12:2e8fda56093f 951 if (_settings.Session.JoinTimeOnAir < 36000) {
jreiss 12:2e8fda56093f 952 _settings.Session.JoinTimeOnAir = 36000;
jreiss 12:2e8fda56093f 953 }
jreiss 12:2e8fda56093f 954 time_on_max = 72000;
jreiss 12:2e8fda56093f 955 rand_time_off = rand_r(time_off_max - 1, time_off_max + 1);
jreiss 12:2e8fda56093f 956 // time off max 1 hour
jreiss 12:2e8fda56093f 957 time_off_max = std::min < uint32_t > (time_off_max * 2, 60 * 60);
jreiss 12:2e8fda56093f 958
jreiss 12:2e8fda56093f 959 if (_settings.Session.JoinTimeOnAir < time_on_max) {
jreiss 12:2e8fda56093f 960 _settings.Session.JoinTimeOnAir += GetTimeOnAir(size);
jreiss 12:2e8fda56093f 961 _settings.Session.JoinTimeOffEnd = now + rand_time_off;
jreiss 12:2e8fda56093f 962 } else {
jreiss 12:2e8fda56093f 963 logWarning("Max time-on-air limit met for current join backoff period");
jreiss 12:2e8fda56093f 964 _settings.Session.JoinTimeOffEnd = _settings.Session.JoinFirstAttempt + 11 * 60 * 60;
jreiss 12:2e8fda56093f 965 }
jreiss 12:2e8fda56093f 966 } else {
jreiss 12:2e8fda56093f 967 if (_settings.Session.JoinTimeOnAir < 72000) {
jreiss 12:2e8fda56093f 968 _settings.Session.JoinTimeOnAir = 72000;
jreiss 12:2e8fda56093f 969 }
jreiss 12:2e8fda56093f 970 uint32_t join_time = 2500;
jreiss 12:2e8fda56093f 971
jreiss 12:2e8fda56093f 972 // 16 join attempts is ~2754 ms, check if this is the third of the 24 hour period
jreiss 12:2e8fda56093f 973
jreiss 12:2e8fda56093f 974 time_on_max = 80700;
jreiss 12:2e8fda56093f 975 time_off_max = 1 * 60 * 60; // 1 hour
jreiss 12:2e8fda56093f 976 rand_time_off = rand_r(time_off_max - 1, time_off_max + 1);
jreiss 12:2e8fda56093f 977
jreiss 12:2e8fda56093f 978 if (_settings.Session.JoinTimeOnAir < time_on_max - join_time) {
jreiss 12:2e8fda56093f 979 _settings.Session.JoinTimeOnAir += GetTimeOnAir(size);
jreiss 12:2e8fda56093f 980 _settings.Session.JoinTimeOffEnd = now + rand_time_off;
jreiss 12:2e8fda56093f 981 } else {
jreiss 12:2e8fda56093f 982 logWarning("Max time-on-air limit met for current join backoff period");
jreiss 12:2e8fda56093f 983 // Reset the join time on air and set end of restriction to the next 24 hour period
jreiss 12:2e8fda56093f 984 _settings.Session.JoinTimeOnAir = 72000;
jreiss 12:2e8fda56093f 985 uint16_t days = (now - _settings.Session.JoinFirstAttempt) / (24 * 60 * 60) + 1;
jreiss 12:2e8fda56093f 986 logWarning("days : %d", days);
jreiss 12:2e8fda56093f 987 _settings.Session.JoinTimeOffEnd = _settings.Session.JoinFirstAttempt + ((days * 24) + 11) * 60 * 60;
jreiss 12:2e8fda56093f 988 }
jreiss 12:2e8fda56093f 989 }
jreiss 12:2e8fda56093f 990
jreiss 12:2e8fda56093f 991 logWarning("JoinBackoff: %lu seconds Time On Air: %lu / %lu", _settings.Session.JoinTimeOffEnd - now, _settings.Session.JoinTimeOnAir, time_on_max);
jreiss 12:2e8fda56093f 992 } else {
jreiss 12:2e8fda56093f 993 _settings.Session.JoinTimeOnAir += GetTimeOnAir(size);
jreiss 12:2e8fda56093f 994 _settings.Session.JoinTimeOffEnd = now + rand_r(_settings.Network.JoinDelay + 2, _settings.Network.JoinDelay + 3);
jreiss 12:2e8fda56093f 995 }
jreiss 12:2e8fda56093f 996
jreiss 12:2e8fda56093f 997 return LORA_OK;
jreiss 12:2e8fda56093f 998 }
jreiss 12:2e8fda56093f 999