MultiTech / mDot_Channel_Plans

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

Information

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

Not all plans are complete to LoRaWAN specifications.

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

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

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

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

Who changed what in which revision?

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