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:
Jason Reiss
Date:
Tue Feb 07 15:32:43 2017 -0600
Revision:
14:5bbcd92d635a
Parent:
13:996f1663d12e
Update ADR ACK to change DR after each ACK_DELAY packets after ACK_LIMIT

Who changed what in which revision?

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