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