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