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