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 09:00:25 2017 -0600
Revision:
13:996f1663d12e
Parent:
12:2e8fda56093f
Child:
14:5bbcd92d635a
Fix P2P in dynamic plans, channel 0 was being used instead of the set frequency

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