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