MultiTech / mDot_Channel_Plans

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

Information

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

Not all plans are complete to LoRaWAN specifications.

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

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

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

Committer:
jreiss
Date:
Wed Jan 18 13:33:36 2017 +0000
Revision:
11:829f8c2ec1c3
Child:
12:2e8fda56093f
KR920: max DR 7; AS923: max tx power 36 max EIRP 20 defaults

Who changed what in which revision?

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