MultiTech / mDot_Channel_Plans

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

Information

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

Not all plans are complete to LoRaWAN specifications.

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

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

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

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

Who changed what in which revision?

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