Bleeding edge development version of the xDot library for mbed 5. This version of the library is not guaranteed to be stable or well tested and should not be used in production or deployment scenarios.
Dependents: Dot-Examples Dot-AT-Firmware Dot-Examples TEST_FF1705 ... more
ChannelPlan_US915.cpp
00001 /********************************************************************** 00002 * COPYRIGHT 2016 MULTI-TECH SYSTEMS, INC. 00003 * 00004 * ALL RIGHTS RESERVED BY AND FOR THE EXCLUSIVE BENEFIT OF 00005 * MULTI-TECH SYSTEMS, INC. 00006 * 00007 * MULTI-TECH SYSTEMS, INC. - CONFIDENTIAL AND PROPRIETARY 00008 * INFORMATION AND/OR TRADE SECRET. 00009 * 00010 * NOTICE: ALL CODE, PROGRAM, INFORMATION, SCRIPT, INSTRUCTION, 00011 * DATA, AND COMMENT HEREIN IS AND SHALL REMAIN THE CONFIDENTIAL 00012 * INFORMATION AND PROPERTY OF MULTI-TECH SYSTEMS, INC. 00013 * USE AND DISCLOSURE THEREOF, EXCEPT AS STRICTLY AUTHORIZED IN A 00014 * WRITTEN AGREEMENT SIGNED BY MULTI-TECH SYSTEMS, INC. IS PROHIBITED. 00015 * 00016 ***********************************************************************/ 00017 00018 #include "ChannelPlan_US915.h" 00019 #include "limits.h" 00020 00021 using namespace lora; 00022 00023 const uint8_t ChannelPlan_US915::US915_TX_POWERS[] = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 }; 00024 const uint8_t ChannelPlan_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 }; 00025 const uint8_t ChannelPlan_US915::US915_MAX_PAYLOAD_SIZE[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 }; 00026 const uint8_t ChannelPlan_US915::US915_MAX_PAYLOAD_SIZE_REPEATER[] = { 11, 53, 125, 222, 222, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 }; 00027 00028 ChannelPlan_US915::ChannelPlan_US915() 00029 : 00030 ChannelPlan(NULL, NULL) 00031 { 00032 00033 } 00034 00035 ChannelPlan_US915::ChannelPlan_US915(Settings* settings) 00036 : 00037 ChannelPlan(NULL, settings) 00038 { 00039 00040 } 00041 00042 ChannelPlan_US915::ChannelPlan_US915(SxRadio* radio, Settings* settings) 00043 : 00044 ChannelPlan(radio, settings) 00045 { 00046 00047 } 00048 00049 ChannelPlan_US915::~ChannelPlan_US915() { 00050 00051 } 00052 00053 void ChannelPlan_US915::Init() { 00054 _plan = US915; 00055 _planName = "US915"; 00056 00057 _datarates.clear(); 00058 _channels.clear(); 00059 _dutyBands.clear(); 00060 00061 DutyBand band; 00062 00063 band.Index = 0; 00064 band.DutyCycle = 0; 00065 00066 Datarate dr; 00067 00068 _maxTxPower = 30; 00069 _minTxPower = 0; 00070 00071 _minFrequency = US915_FREQ_MIN; 00072 _maxFrequency = US915_FREQ_MAX; 00073 00074 TX_POWERS = US915_TX_POWERS; 00075 RADIO_POWERS = US915_RADIO_POWERS; 00076 MAX_PAYLOAD_SIZE = US915_MAX_PAYLOAD_SIZE; 00077 MAX_PAYLOAD_SIZE_REPEATER = US915_MAX_PAYLOAD_SIZE_REPEATER; 00078 00079 band.FrequencyMin = US915_FREQ_MIN; 00080 band.FrequencyMax = US915_FREQ_MAX; 00081 00082 _freqUBase125k = US915_125K_FREQ_BASE; 00083 _freqUStep125k = US915_125K_FREQ_STEP; 00084 _freqUBase500k = US915_500K_FREQ_BASE; 00085 _freqUStep500k = US915_500K_FREQ_STEP; 00086 _freqDBase500k = US915_500K_DBASE; 00087 _freqDStep500k = US915_500K_DSTEP; 00088 GetSettings()->Session.Rx2Frequency = US915_500K_DBASE; 00089 00090 GetSettings()->Session.BeaconFrequency = US915_BEACON_FREQ_BASE; 00091 GetSettings()->Session.BeaconFreqHop = true; 00092 GetSettings()->Session.PingSlotFrequency = US915_BEACON_FREQ_BASE; 00093 GetSettings()->Session.PingSlotDatarateIndex = US915_BEACON_DR; 00094 GetSettings()->Session.PingSlotFreqHop = true; 00095 00096 _minDatarate = US915_MIN_DATARATE; 00097 _maxDatarate = US915_MAX_DATARATE; 00098 _minRx2Datarate = DR_8; 00099 _maxRx2Datarate = DR_13; 00100 _minDatarateOffset = US915_MIN_DATARATE_OFFSET; 00101 _maxDatarateOffset = US915_MAX_DATARATE_OFFSET; 00102 00103 _numChans125k = US915_125K_NUM_CHANS; 00104 _numChans500k = US915_500K_NUM_CHANS; 00105 00106 logInfo("Initialize channels..."); 00107 00108 SetNumberOfChannels(US915_125K_NUM_CHANS + US915_500K_NUM_CHANS, false); 00109 00110 dr.SpreadingFactor = SF_10; 00111 00112 logInfo("Initialize datarates..."); 00113 00114 // Add DR0-3 00115 while (dr.SpreadingFactor >= SF_7) { 00116 AddDatarate(-1, dr); 00117 dr.SpreadingFactor--; 00118 dr.Index++; 00119 } 00120 00121 // Add DR4 00122 dr.SpreadingFactor = SF_8; 00123 dr.Bandwidth = BW_500; 00124 AddDatarate(-1, dr); 00125 dr.Index++; 00126 00127 // Skip DR5-7 RFU 00128 dr.SpreadingFactor = SF_INVALID; 00129 AddDatarate(-1, dr), dr.Index++; 00130 AddDatarate(-1, dr), dr.Index++; 00131 AddDatarate(-1, dr), dr.Index++; 00132 00133 band.PowerMax = 30; 00134 00135 band.TimeOffEnd = 0; 00136 00137 AddDutyBand(-1, band); 00138 00139 GetSettings()->Session.Rx2DatarateIndex = DR_8; 00140 00141 // Add DR8-13 00142 dr.SpreadingFactor = SF_12; 00143 while (dr.SpreadingFactor >= SF_7) { 00144 AddDatarate(-1, dr); 00145 dr.SpreadingFactor--; 00146 dr.Index++; 00147 } 00148 00149 // Skip DR14-15 RFU 00150 dr.SpreadingFactor = SF_INVALID; 00151 AddDatarate(-1, dr), AddDatarate(-1, dr); 00152 00153 GetSettings()->Session.TxDatarate = DR_0; 00154 GetSettings()->Session.TxPower = GetSettings()->Network.TxPower; 00155 00156 SetFrequencySubBand(GetSettings()->Network.FrequencySubBand); 00157 00158 } 00159 00160 uint8_t ChannelPlan_US915::HandleJoinAccept(const uint8_t* buffer, uint8_t size) { 00161 00162 if (size > 17 && buffer[28] == 0x01) { 00163 for (int i = 13; i < size - 5; i += 2) { 00164 SetChannelMask((i-13)/2, buffer[i+1] << 8 | buffer[i]); 00165 } 00166 } 00167 00168 return LORA_OK; 00169 } 00170 00171 void ChannelPlan_US915::SetNumberOfChannels(uint8_t channels, bool resize) { 00172 uint8_t newsize = ((channels - 1) / CHAN_MASK_SIZE) + 1; 00173 00174 if (resize) { 00175 _channels.resize(channels); 00176 } 00177 00178 _channelMask.resize(newsize, 0x0); 00179 _numChans = channels; 00180 00181 } 00182 00183 bool ChannelPlan_US915::IsChannelEnabled(uint8_t channel) { 00184 uint8_t index = channel / CHAN_MASK_SIZE; 00185 uint8_t shift = channel % CHAN_MASK_SIZE; 00186 00187 assert(index < _channelMask.size() * CHAN_MASK_SIZE); 00188 00189 // cannot shift over 32 bits 00190 assert(shift < 32); 00191 00192 // logDebug("index: %d shift %d cm: %04x bit: %04x enabled: %d", index, shift, _channelMask[index], (1 << shift), (_channelMask[index] & (1 << shift)) == (1 << shift)); 00193 00194 return (_channelMask[index] & (1 << shift)) == (1 << shift); 00195 } 00196 00197 uint8_t ChannelPlan_US915::GetMinDatarate() { 00198 if (GetSettings()->Network.Mode == lora::PEER_TO_PEER) 00199 return 8; 00200 else 00201 return _minDatarate; 00202 } 00203 00204 uint8_t ChannelPlan_US915::GetMaxDatarate() { 00205 if (GetSettings()->Network.Mode == lora::PEER_TO_PEER) 00206 return 13; 00207 else 00208 return _maxDatarate; 00209 } 00210 00211 uint8_t ChannelPlan_US915::SetRx1Offset(uint8_t offset) { 00212 GetSettings()->Session.Rx1DatarateOffset = offset; 00213 return LORA_OK; 00214 } 00215 00216 uint8_t ChannelPlan_US915::SetRx2Frequency(uint32_t freq) { 00217 GetSettings()->Session.Rx2Frequency = freq; 00218 return LORA_OK; 00219 } 00220 00221 uint8_t ChannelPlan_US915::SetRx2DatarateIndex(uint8_t index) { 00222 GetSettings()->Session.Rx2DatarateIndex = index; 00223 return LORA_OK; 00224 } 00225 00226 uint8_t ChannelPlan_US915::SetTxConfig() { 00227 logInfo("Configure radio for TX"); 00228 00229 uint8_t band = GetDutyBand(GetChannel(_txChannel).Frequency); 00230 Datarate txDr = GetDatarate(GetSettings()->Session.TxDatarate); 00231 int8_t max_pwr = _dutyBands[band].PowerMax; 00232 uint8_t chans_enabled = 0; 00233 00234 int8_t pwr = 0; 00235 00236 pwr = std::min < int8_t > (GetSettings()->Session.TxPower, max_pwr); 00237 00238 // spec states that if < 50 125kHz channels are enabled, power is limited to 21dB conducted 00239 chans_enabled += CountBits(_channelMask[0]); 00240 chans_enabled += CountBits(_channelMask[1]); 00241 chans_enabled += CountBits(_channelMask[2]); 00242 chans_enabled += CountBits(_channelMask[3]); 00243 if (chans_enabled < 50 && pwr > 21) { 00244 pwr = 21; 00245 } 00246 00247 if (pwr + GetSettings()->Network.AntennaGain >= max_pwr + 6 && GetSettings()->Network.AntennaGain > 6) { 00248 pwr -= (GetSettings()->Network.AntennaGain - 6); 00249 } 00250 00251 for (int i = 20; i >= 0; i--) { 00252 if (RADIO_POWERS[i] <= pwr) { 00253 pwr = i; 00254 break; 00255 } 00256 if (i == 0) { 00257 pwr = i; 00258 } 00259 } 00260 00261 logDebug("Session pwr: %d ant: %d max: %d", GetSettings()->Session.TxPower, GetSettings()->Network.AntennaGain, max_pwr); 00262 logDebug("Radio Power index: %d output: %d total: %d", pwr, RADIO_POWERS[pwr], RADIO_POWERS[pwr] + GetSettings()->Network.AntennaGain); 00263 00264 uint32_t bw = txDr.Bandwidth; 00265 uint32_t sf = txDr.SpreadingFactor; 00266 uint8_t cr = txDr.Coderate; 00267 uint8_t pl = txDr.PreambleLength; 00268 uint16_t fdev = 0; 00269 bool crc = txDr.Crc; 00270 bool iq = txDr.TxIQ; 00271 00272 if (GetSettings()->Network.DisableCRC == true) 00273 crc = false; 00274 00275 SxRadio::RadioModems_t modem = SxRadio::MODEM_LORA; 00276 00277 if (sf == SF_FSK) { 00278 modem = SxRadio::MODEM_FSK; 00279 sf = 50e3; 00280 fdev = 25e3; 00281 bw = 0; 00282 } 00283 00284 GetRadio()->SetTxConfig(modem, pwr, fdev, bw, sf, cr, pl, false, crc, false, 0, iq, 3e3); 00285 00286 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); 00287 00288 return LORA_OK; 00289 } 00290 00291 uint8_t ChannelPlan_US915::SetRxConfig(uint8_t window, bool continuous, uint16_t wnd_growth) { 00292 00293 RxWindow rxw = GetRxWindow(window); 00294 GetRadio()->SetChannel(rxw.Frequency); 00295 00296 Datarate rxDr = GetDatarate(rxw.DatarateIndex); 00297 uint32_t bw = rxDr.Bandwidth; 00298 uint32_t sf = rxDr.SpreadingFactor; 00299 uint8_t cr = rxDr.Coderate; 00300 uint8_t pl = rxDr.PreambleLength; 00301 uint16_t sto = rxDr.SymbolTimeout() * wnd_growth; 00302 uint32_t afc = 0; 00303 bool fixLen = false; 00304 uint8_t payloadLen = 0U; 00305 bool crc = false; // downlink does not use CRC according to LORAWAN 00306 00307 if (GetSettings()->Network.DisableCRC == true) 00308 crc = false; 00309 00310 Datarate txDr = GetDatarate(GetSettings()->Session.TxDatarate); 00311 bool iq = txDr.RxIQ; 00312 00313 if (P2PEnabled()) { 00314 iq = txDr.TxIQ; 00315 } 00316 00317 // Beacon modifications - no I/Q inversion, fixed length rx, preamble 00318 if (window == RX_BEACON) { 00319 iq = txDr.TxIQ; 00320 fixLen = true; 00321 payloadLen = sizeof(BCNPayload); 00322 pl = BEACON_PREAMBLE_LENGTH; 00323 } 00324 00325 SxRadio::RadioModems_t modem = SxRadio::MODEM_LORA; 00326 00327 if (sf == SF_FSK) { 00328 modem = SxRadio::MODEM_FSK; 00329 sf = 50e3; 00330 cr = 0; 00331 bw = 50e3; 00332 afc = 83333; 00333 iq = false; 00334 crc = true; // FSK must use CRC 00335 } 00336 00337 // Disable printf's to actually receive packets, printing to debug may mess up the timing 00338 // logTrace("Configure radio for RX%d on freq: %lu", window, rxw.Frequency); 00339 // logTrace("RX SF: %u BW: %u CR: %u PL: %u STO: %u CRC: %d IQ: %d", sf, bw, cr, pl, sto, crc, iq); 00340 00341 GetRadio()->SetRxConfig(modem, bw, sf, cr, afc, pl, sto, fixLen, payloadLen, crc, false, 0, iq, continuous); 00342 00343 return LORA_OK; 00344 } 00345 00346 uint8_t ChannelPlan_US915::AddChannel(int8_t index, Channel channel) { 00347 logTrace("Add Channel %d : %lu : %02x %d", index, channel.Frequency, channel.DrRange.Value, _channels.size()); 00348 00349 assert(index < (int) _channels.size()); 00350 00351 if (index >= 0) { 00352 _channels[index] = channel; 00353 } else { 00354 _channels.push_back(channel); 00355 } 00356 00357 return LORA_OK; 00358 } 00359 00360 Channel ChannelPlan_US915::GetChannel(int8_t index) { 00361 Channel chan; 00362 memset(&chan, 0, sizeof(Channel)); 00363 00364 if (_channels.size() > 0) { 00365 chan = _channels[index]; 00366 } else { 00367 if (index < 64) { 00368 chan.Index = index; 00369 chan.DrRange.Fields.Min = _minDatarate; 00370 chan.DrRange.Fields.Max = _maxDatarate - 1; 00371 chan.Frequency = _freqUBase125k + (_freqUStep125k * index); 00372 } else if (index < 72) { 00373 chan.Index = index; 00374 chan.DrRange.Fields.Min = _maxDatarate; 00375 chan.DrRange.Fields.Max = _maxDatarate; 00376 chan.Frequency = _freqUBase500k + (_freqUStep500k * (index - 64)); 00377 } 00378 } 00379 00380 return chan; 00381 } 00382 00383 uint8_t ChannelPlan_US915::SetFrequencySubBand(uint8_t sub_band) { 00384 00385 _txFrequencySubBand = sub_band; 00386 00387 if (sub_band > 0) { 00388 SetChannelMask(0, 0x0000); 00389 SetChannelMask(1, 0x0000); 00390 SetChannelMask(2, 0x0000); 00391 SetChannelMask(3, 0x0000); 00392 SetChannelMask(4, 0x0000); 00393 SetChannelMask((sub_band - 1) / 2, (sub_band % 2) ? 0x00FF : 0xFF00); 00394 SetChannelMask(4, 1 << (sub_band - 1)); 00395 } else { 00396 SetChannelMask(0, 0xFFFF); 00397 SetChannelMask(1, 0xFFFF); 00398 SetChannelMask(2, 0xFFFF); 00399 SetChannelMask(3, 0xFFFF); 00400 SetChannelMask(4, 0x00FF); 00401 } 00402 00403 return LORA_OK; 00404 } 00405 00406 00407 void ChannelPlan_US915::LogRxWindow(uint8_t wnd) { 00408 00409 RxWindow rxw = GetRxWindow(wnd); 00410 Datarate rxDr = GetDatarate(rxw.DatarateIndex); 00411 uint8_t bw = rxDr.Bandwidth; 00412 uint8_t sf = rxDr.SpreadingFactor; 00413 uint8_t cr = rxDr.Coderate; 00414 uint8_t pl = rxDr.PreambleLength; 00415 uint16_t sto = rxDr.SymbolTimeout(); 00416 bool crc = false; // downlink does not use CRC according to LORAWAN 00417 bool iq = GetTxDatarate().RxIQ; 00418 00419 logTrace("RX%d on freq: %lu", wnd, rxw.Frequency); 00420 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); 00421 } 00422 00423 RxWindow ChannelPlan_US915::GetRxWindow(uint8_t window) { 00424 RxWindow rxw; 00425 int index = 0; 00426 00427 if (P2PEnabled()) { 00428 rxw.Frequency = GetSettings()->Network.TxFrequency; 00429 index = GetSettings()->Session.TxDatarate; 00430 } else { 00431 switch (window) { 00432 case RX_1: 00433 if (_txChannel < _numChans125k) { 00434 if (GetSettings()->Network.Mode == lora::PRIVATE_MTS) 00435 rxw.Frequency = _freqDBase500k + (_txChannel / 8) * _freqDStep500k; 00436 else 00437 rxw.Frequency = _freqDBase500k + (_txChannel % 8) * _freqDStep500k; 00438 } else 00439 rxw.Frequency = _freqDBase500k + (_txChannel - _numChans125k) * _freqDStep500k; 00440 00441 if (GetSettings()->Session.TxDatarate <= DR_4) { 00442 index = GetSettings()->Session.TxDatarate + 10 - GetSettings()->Session.Rx1DatarateOffset; 00443 00444 if (index < DR_8) 00445 index = DR_8; 00446 if (index > DR_13) 00447 index = DR_13; 00448 } else if (GetSettings()->Session.TxDatarate >= DR_8) { 00449 index = GetSettings()->Session.TxDatarate - GetSettings()->Session.Rx1DatarateOffset; 00450 if (index < DR_8) 00451 index = DR_8; 00452 } 00453 00454 break; 00455 00456 case RX_BEACON: 00457 rxw.Frequency = GetSettings()->Session.BeaconFrequency; 00458 index = US915_BEACON_DR; 00459 break; 00460 00461 case RX_SLOT: 00462 rxw.Frequency = GetSettings()->Session.PingSlotFrequency; 00463 index = GetSettings()->Session.PingSlotDatarateIndex; 00464 break; 00465 00466 // RX2, RXC, RX_TEST, etc.. 00467 default: 00468 if (GetSettings()->Network.Mode == lora::PRIVATE_MTS) { 00469 if (_txChannel < _numChans125k) { 00470 rxw.Frequency = _freqDBase500k + (_txChannel / 8) * _freqDStep500k; 00471 } else { 00472 rxw.Frequency = _freqDBase500k + (_txChannel % 8) * _freqDStep500k; 00473 } 00474 } else { 00475 rxw.Frequency = GetSettings()->Session.Rx2Frequency; 00476 } 00477 00478 index = GetSettings()->Session.Rx2DatarateIndex; 00479 } 00480 } 00481 00482 rxw.DatarateIndex = index; 00483 00484 return rxw; 00485 } 00486 00487 uint8_t ChannelPlan_US915::HandleRxParamSetup(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { 00488 status = 0x07; 00489 int8_t datarate = 0; 00490 int8_t drOffset = 0; 00491 uint32_t freq = 0; 00492 00493 drOffset = payload[index++]; 00494 datarate = drOffset & 0x0F; 00495 drOffset = (drOffset >> 4) & 0x07; 00496 00497 freq = payload[index++]; 00498 freq |= payload[index++] << 8; 00499 freq |= payload[index++] << 16; 00500 freq *= 100; 00501 00502 if (!CheckRfFrequency(freq)) { 00503 logInfo("Freq KO"); 00504 status &= 0xFE; // Channel frequency KO 00505 } 00506 00507 if (datarate < _minRx2Datarate || datarate > _maxRx2Datarate) { 00508 logInfo("DR KO"); 00509 status &= 0xFD; // Datarate KO 00510 } 00511 00512 if (drOffset < 0 || drOffset > _maxDatarateOffset) { 00513 logInfo("DR Offset KO"); 00514 status &= 0xFB; // Rx1DrOffset range KO 00515 } 00516 00517 if ((status & 0x07) == 0x07) { 00518 logInfo("RxParamSetup accepted Rx2DR: %d Rx2Freq: %d Rx1Offset: %d", datarate, freq, drOffset); 00519 SetRx2DatarateIndex(datarate); 00520 SetRx2Frequency(freq); 00521 SetRx1Offset(drOffset); 00522 } else { 00523 logInfo("RxParamSetup rejected Rx2DR: %d Rx2Freq: %d Rx1Offset: %d", datarate, freq, drOffset); 00524 } 00525 00526 return LORA_OK; 00527 } 00528 00529 uint8_t ChannelPlan_US915::HandleNewChannel(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { 00530 00531 // Not Supported in US915 00532 status = 0; 00533 return LORA_OK; 00534 } 00535 00536 uint8_t ChannelPlan_US915::HandleDownlinkChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { 00537 00538 // Not Supported in US915 00539 status = 0; 00540 return LORA_OK; 00541 } 00542 00543 uint8_t ChannelPlan_US915::HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { 00544 uint8_t datarate = 0; 00545 uint32_t freq = 0; 00546 bool freqHop = false; 00547 00548 status = 0x03; 00549 00550 freq = payload[index++]; 00551 freq |= payload[index++] << 8; 00552 freq |= payload[index++] << 16; 00553 freq *= 100; 00554 00555 datarate = payload[index] & 0x0F; 00556 00557 if (freq == 0U) { 00558 logInfo("Received request to reset ping slot frequency to default"); 00559 freq = US915_BEACON_FREQ_BASE; 00560 freqHop = true; 00561 } else if (!CheckRfFrequency(freq)) { 00562 logInfo("Freq KO"); 00563 status &= 0xFE; // Channel frequency KO 00564 } 00565 00566 if (datarate < _minRx2Datarate || datarate > _maxRx2Datarate) { 00567 logInfo("DR KO"); 00568 status &= 0xFD; // Datarate KO 00569 } 00570 00571 if ((status & 0x03) == 0x03) { 00572 logInfo("PingSlotChannelReq accepted DR: %d Freq: %d", datarate, freq); 00573 GetSettings()->Session.PingSlotFrequency = freq; 00574 GetSettings()->Session.PingSlotDatarateIndex = datarate; 00575 GetSettings()->Session.PingSlotFreqHop = freqHop; 00576 } else { 00577 logInfo("PingSlotChannelReq rejected DR: %d Freq: %d", datarate, freq); 00578 } 00579 00580 return LORA_OK; 00581 } 00582 00583 uint8_t ChannelPlan_US915::HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { 00584 uint32_t freq = 0; 00585 bool freqHop = false; 00586 00587 status = 0x01; 00588 00589 freq = payload[index++]; 00590 freq |= payload[index++] << 8; 00591 freq |= payload[index] << 16; 00592 freq *= 100; 00593 00594 if (freq == 0U) { 00595 logInfo("Received request to reset beacon frequency to default"); 00596 freq = US915_BEACON_FREQ_BASE; 00597 freqHop = true; 00598 } else if (!CheckRfFrequency(freq)) { 00599 logInfo("Freq KO"); 00600 status &= 0xFE; // Channel frequency KO 00601 } 00602 00603 if (status & 0x01) { 00604 logInfo("BeaconFrequencyReq accepted Freq: %d", freq); 00605 GetSettings()->Session.BeaconFrequency = freq; 00606 GetSettings()->Session.BeaconFreqHop = freqHop; 00607 } else { 00608 logInfo("BeaconFrequencyReq rejected Freq: %d", freq); 00609 } 00610 00611 return LORA_OK; 00612 } 00613 00614 00615 uint8_t ChannelPlan_US915::HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { 00616 00617 uint8_t power = 0; 00618 uint8_t datarate = 0; 00619 uint16_t mask = 0; 00620 uint8_t ctrl = 0; 00621 uint8_t nbRep = 0; 00622 00623 status = 0x07; 00624 datarate = payload[index++]; 00625 power = datarate & 0x0F; 00626 datarate = (datarate >> 4) & 0x0F; 00627 00628 mask = payload[index++]; 00629 mask |= payload[index++] << 8; 00630 00631 nbRep = payload[index++]; 00632 ctrl = (nbRep >> 4) & 0x07; 00633 nbRep &= 0x0F; 00634 00635 if (nbRep == 0) { 00636 nbRep = 1; 00637 } 00638 00639 if (datarate > _maxDatarate) { 00640 status &= 0xFD; // Datarate KO 00641 } 00642 // 00643 // Remark MaxTxPower = 0 and MinTxPower = 10 00644 // 00645 if (power > 10) { 00646 status &= 0xFB; // TxPower KO 00647 } 00648 00649 uint16_t t_125k = 0; //used only in ctrl case 5 00650 00651 switch (ctrl) { 00652 case 0: 00653 case 1: 00654 case 2: 00655 case 3: 00656 case 4: 00657 SetChannelMask(ctrl, mask); 00658 break; 00659 00660 case 5: 00661 if(mask != 0) { 00662 for(int i = 0; i < 8; i++) { //0 - 7 bits 00663 if(((mask >> i) & 1) == 1) { //if bit in mask is a one 00664 t_125k |= (0xff << ((i % 2) * 8)); // this does either 0xff00 or 0x00ff to t_125k 00665 } 00666 if(i % 2 == 1) { // if 1 then both halfs of the mask were set 00667 SetChannelMask(i/2, t_125k); 00668 t_125k = 0; //reset mask for next two bits 00669 } 00670 } 00671 SetChannelMask(4, mask); 00672 } else { 00673 status &= 0xFE; // ChannelMask KO 00674 logWarning("Rejecting mask, will not disable all channels"); 00675 return LORA_ERROR; 00676 } 00677 break; 00678 00679 case 6: 00680 // enable all 125 kHz channels 00681 SetChannelMask(0, 0xFFFF); 00682 SetChannelMask(1, 0xFFFF); 00683 SetChannelMask(2, 0xFFFF); 00684 SetChannelMask(3, 0xFFFF); 00685 SetChannelMask(4, mask); 00686 break; 00687 00688 case 7: 00689 // disable all 125 kHz channels 00690 SetChannelMask(0, 0x0); 00691 SetChannelMask(1, 0x0); 00692 SetChannelMask(2, 0x0); 00693 SetChannelMask(3, 0x0); 00694 SetChannelMask(4, mask); 00695 break; 00696 00697 default: 00698 logWarning("rejecting RFU or unknown control value %d", ctrl); 00699 status &= 0xFE; // ChannelMask KO 00700 return LORA_ERROR; 00701 } 00702 00703 if (GetSettings()->Network.ADREnabled) { 00704 if (status == 0x07) { 00705 GetSettings()->Session.TxDatarate = datarate; 00706 GetSettings()->Session.TxPower = TX_POWERS[power]; 00707 GetSettings()->Session.Redundancy = nbRep; 00708 } 00709 } else { 00710 logDebug("ADR is disabled, DR and Power not changed."); 00711 status &= 0xFB; // TxPower KO 00712 status &= 0xFD; // Datarate KO 00713 } 00714 00715 logDebug("ADR DR: %u PWR: %u Ctrl: %02x Mask: %04x NbRep: %u Stat: %02x", datarate, power, ctrl, mask, nbRep, status); 00716 00717 return LORA_OK; 00718 } 00719 00720 uint8_t ChannelPlan_US915::ValidateAdrConfiguration() { 00721 uint8_t status = 0x07; 00722 uint8_t chans_enabled = 0; 00723 uint8_t datarate = GetSettings()->Session.TxDatarate; 00724 uint8_t power = GetSettings()->Session.TxPower; 00725 00726 if (!GetSettings()->Network.ADREnabled) { 00727 logDebug("ADR disabled - no applied changes to validate"); 00728 return status; 00729 } 00730 00731 if (datarate > _maxDatarate) { 00732 logWarning("ADR Datarate KO - outside allowed range"); 00733 status &= 0xFD; // Datarate KO 00734 } 00735 if (power < _minTxPower || power > _maxTxPower) { 00736 logWarning("ADR TX Power KO - outside allowed range"); 00737 status &= 0xFB; // TxPower KO 00738 } 00739 00740 // at least 2 125kHz channels must be enabled 00741 chans_enabled += CountBits(_channelMask[0]); 00742 chans_enabled += CountBits(_channelMask[1]); 00743 chans_enabled += CountBits(_channelMask[2]); 00744 chans_enabled += CountBits(_channelMask[3]); 00745 // Semtech reference (LoRaMac-node) enforces at least 2 channels 00746 if (chans_enabled < 2) { 00747 logWarning("ADR Channel Mask KO - at least 2 125kHz channels must be enabled"); 00748 status &= 0xFE; // ChannelMask KO 00749 } 00750 00751 // if TXDR == 4 (SF8@500kHz) at least 1 500kHz channel must be enabled 00752 if (datarate == DR_4 && (CountBits(_channelMask[4] & 0xFF) == 0)) { 00753 logWarning("ADR Datarate KO - DR4 requires at least 1 500kHz channel enabled"); 00754 status &= 0xFD; // Datarate KO 00755 } 00756 00757 return status; 00758 } 00759 00760 uint32_t ChannelPlan_US915::GetTimeOffAir() 00761 { 00762 if (GetSettings()->Test.DisableDutyCycle == lora::ON) 00763 return 0; 00764 00765 uint32_t min = 0; 00766 uint32_t now = _dutyCycleTimer.read_ms(); 00767 00768 if (GetSettings()->Session.AggregatedTimeOffEnd > 0 && GetSettings()->Session.AggregatedTimeOffEnd > now) { 00769 min = std::max < uint32_t > (min, GetSettings()->Session.AggregatedTimeOffEnd - now); 00770 } 00771 00772 now = time(NULL); 00773 uint32_t join_time = 0; 00774 00775 if (GetSettings()->Session.JoinFirstAttempt != 0 && now < GetSettings()->Session.JoinTimeOffEnd) { 00776 join_time = (GetSettings()->Session.JoinTimeOffEnd - now) * 1000; 00777 } 00778 00779 min = std::max < uint32_t > (join_time, min); 00780 00781 return min; 00782 } 00783 00784 std::vector<uint32_t> lora::ChannelPlan_US915::GetChannels() { 00785 std::vector < uint32_t > chans; 00786 00787 if (GetSettings()->Network.FrequencySubBand > 0) { 00788 uint8_t chans_per_group = 8; 00789 size_t start = (GetSettings()->Network.FrequencySubBand - 1) * chans_per_group; 00790 for (int8_t i = start; i < int8_t(start + chans_per_group); i++) { 00791 chans.push_back(GetChannel(i).Frequency); 00792 } 00793 chans.push_back(GetChannel(_numChans125k + (GetSettings()->Network.FrequencySubBand - 1)).Frequency); 00794 chans.push_back(GetRxWindow(2).Frequency); 00795 } else { 00796 for (int8_t i = 0; i < _numChans; i++) { 00797 chans.push_back(GetChannel(i).Frequency); 00798 } 00799 chans.push_back(GetRxWindow(2).Frequency); 00800 } 00801 00802 return chans; 00803 } 00804 00805 std::vector<uint8_t> lora::ChannelPlan_US915::GetChannelRanges() { 00806 std::vector < uint8_t > ranges; 00807 00808 if (GetSettings()->Network.FrequencySubBand > 0) { 00809 uint8_t chans_per_group = 8; 00810 size_t start = (GetSettings()->Network.FrequencySubBand - 1) * chans_per_group; 00811 for (int8_t i = start; i < int8_t(start + chans_per_group); i++) { 00812 ranges.push_back(GetChannel(i).DrRange.Value); 00813 } 00814 ranges.push_back(GetChannel(_numChans125k + (GetSettings()->Network.FrequencySubBand - 1)).DrRange.Value); 00815 ranges.push_back(GetRxWindow(2).DatarateIndex); 00816 } else { 00817 for (int8_t i = 0; i < _numChans; i++) { 00818 ranges.push_back(GetChannel(i).DrRange.Value); 00819 } 00820 ranges.push_back(GetRxWindow(2).DatarateIndex); 00821 } 00822 00823 ranges.push_back(GetRxWindow(2).DatarateIndex); 00824 00825 return ranges; 00826 00827 } 00828 00829 void lora::ChannelPlan_US915::EnableDefaultChannels() { 00830 SetFrequencySubBand(GetFrequencySubBand()); 00831 } 00832 00833 uint8_t ChannelPlan_US915::GetNextChannel() 00834 { 00835 if (GetSettings()->Session.AggregatedTimeOffEnd != 0) { 00836 return LORA_AGGREGATED_DUTY_CYCLE; 00837 } 00838 00839 if (P2PEnabled() || GetSettings()->Network.TxFrequency != 0) { 00840 logDebug("Using frequency %d", GetSettings()->Network.TxFrequency); 00841 00842 if (GetSettings()->Test.DisableDutyCycle != lora::ON) { 00843 int8_t band = GetDutyBand(GetSettings()->Network.TxFrequency); 00844 logDebug("band: %d freq: %d", band, GetSettings()->Network.TxFrequency); 00845 if (band != -1 && _dutyBands[band].TimeOffEnd != 0) { 00846 return LORA_NO_CHANS_ENABLED; 00847 } 00848 } 00849 00850 GetRadio()->SetChannel(GetSettings()->Network.TxFrequency); 00851 return LORA_OK; 00852 } 00853 00854 uint8_t start = 0; 00855 uint8_t maxChannels = _numChans125k; 00856 uint8_t nbEnabledChannels = 0; 00857 uint8_t *enabledChannels = new uint8_t[maxChannels]; 00858 00859 if (GetTxDatarate().Bandwidth == BW_500) { 00860 maxChannels = _numChans500k; 00861 start = _numChans125k; 00862 } 00863 00864 // Search how many channels are enabled 00865 DatarateRange range; 00866 uint8_t dr_index = GetSettings()->Session.TxDatarate; 00867 uint32_t now = _dutyCycleTimer.read_ms(); 00868 00869 for (size_t i = 0; i < _dutyBands.size(); i++) { 00870 if (_dutyBands[i].TimeOffEnd < now || GetSettings()->Test.DisableDutyCycle == lora::ON) { 00871 _dutyBands[i].TimeOffEnd = 0; 00872 } 00873 } 00874 00875 for (uint8_t i = start; i < start + maxChannels; i++) { 00876 range = GetChannel(i).DrRange; 00877 // logDebug("chan: %d freq: %d range:%02x", i, GetChannel(i).Frequency, range.Value); 00878 00879 if (IsChannelEnabled(i) && (dr_index >= range.Fields.Min && dr_index <= range.Fields.Max)) { 00880 int8_t band = GetDutyBand(GetChannel(i).Frequency); 00881 // logDebug("band: %d freq: %d", band, _channels[i].Frequency); 00882 if (band != -1 && _dutyBands[band].TimeOffEnd == 0) { 00883 enabledChannels[nbEnabledChannels++] = i; 00884 } 00885 } 00886 } 00887 00888 if (GetTxDatarate().Bandwidth == BW_500) { 00889 _dutyBands[0].PowerMax = 26; 00890 } else { 00891 if (nbEnabledChannels < 50) 00892 _dutyBands[0].PowerMax = 21; 00893 else 00894 _dutyBands[0].PowerMax = 30; 00895 } 00896 00897 logTrace("Number of available channels: %d", nbEnabledChannels); 00898 00899 uint32_t freq = 0; 00900 uint8_t sf = GetTxDatarate().SpreadingFactor; 00901 uint8_t bw = GetTxDatarate().Bandwidth; 00902 int16_t thres = DEFAULT_FREE_CHAN_RSSI_THRESHOLD; 00903 00904 if (nbEnabledChannels == 0) { 00905 delete [] enabledChannels; 00906 return LORA_NO_CHANS_ENABLED; 00907 } 00908 00909 if (GetSettings()->Network.CADEnabled) { 00910 // Search for free channel with ms timeout 00911 int16_t timeout = 10000; 00912 Timer tmr; 00913 tmr.start(); 00914 00915 for (uint8_t j = rand_r(0, nbEnabledChannels - 1); tmr.read_ms() < timeout; j++) { 00916 freq = GetChannel(enabledChannels[j]).Frequency; 00917 00918 if (GetRadio()->IsChannelFree(SxRadio::MODEM_LORA, freq, sf, thres, bw)) { 00919 _txChannel = enabledChannels[j]; 00920 break; 00921 } 00922 } 00923 } else { 00924 uint8_t j = rand_r(0, nbEnabledChannels - 1); 00925 _txChannel = enabledChannels[j]; 00926 freq = GetChannel(_txChannel).Frequency; 00927 } 00928 00929 assert(freq != 0); 00930 00931 logDebug("Using channel %d : %d", _txChannel, freq); 00932 GetRadio()->SetChannel(freq); 00933 00934 delete [] enabledChannels; 00935 return LORA_OK; 00936 } 00937 00938 uint8_t lora::ChannelPlan_US915::GetJoinDatarate() { 00939 uint8_t dr = GetSettings()->Session.TxDatarate; 00940 static int fsb = 1; 00941 if (GetSettings()->Test.DisableRandomJoinDatarate == lora::OFF) { 00942 00943 if (GetSettings()->Network.FrequencySubBand == 0) { 00944 00945 if (fsb < 9) { 00946 SetFrequencySubBand(fsb); 00947 logDebug("JoinDatarate setting frequency sub band to %d",fsb); 00948 fsb++; 00949 dr = lora::DR_0; 00950 } else { 00951 dr = lora::DR_4; 00952 fsb = 1; 00953 } 00954 } else { 00955 dr = lora::DR_0; 00956 } 00957 } 00958 return dr; 00959 } 00960 00961 uint8_t lora::ChannelPlan_US915::CalculateJoinBackoff(uint8_t size) { 00962 00963 time_t now = time(NULL); 00964 uint32_t time_on_max = 0; 00965 static uint32_t time_off_max = 15; 00966 uint32_t rand_time_off = 0; 00967 static uint16_t join_cnt = 0; 00968 00969 // TODO: calc time-off-max based on RTC time from JoinFirstAttempt, time-off-max is lost over sleep 00970 00971 if ((time_t)GetSettings()->Session.JoinTimeOffEnd > now) { 00972 return LORA_JOIN_BACKOFF; 00973 } 00974 00975 uint32_t secs_since_first_attempt = (now - GetSettings()->Session.JoinFirstAttempt); 00976 uint16_t hours_since_first_attempt = secs_since_first_attempt / (60 * 60); 00977 00978 join_cnt = (join_cnt+1) % 16; 00979 00980 if (GetSettings()->Session.JoinFirstAttempt == 0) { 00981 /* 1 % duty-cycle for first hour 00982 * 0.1 % next 10 hours 00983 * 0.01 % upto 24 hours */ 00984 GetSettings()->Session.JoinFirstAttempt = now; 00985 GetSettings()->Session.JoinTimeOnAir += GetTimeOnAir(size); 00986 GetSettings()->Session.JoinTimeOffEnd = now + rand_r(GetSettings()->Network.JoinDelay + 2, GetSettings()->Network.JoinDelay + 3); 00987 } else if (join_cnt == 0) { 00988 if (hours_since_first_attempt < 1) { 00989 time_on_max = 36000; 00990 rand_time_off = rand_r(time_off_max - 1, time_off_max + 1); 00991 // time off max 1 hour 00992 time_off_max = std::min < uint32_t > (time_off_max * 2, 60 * 60); 00993 00994 if (GetSettings()->Session.JoinTimeOnAir < time_on_max) { 00995 GetSettings()->Session.JoinTimeOnAir += GetTimeOnAir(size); 00996 GetSettings()->Session.JoinTimeOffEnd = now + rand_time_off; 00997 } else { 00998 logWarning("Max time-on-air limit met for current join backoff period"); 00999 GetSettings()->Session.JoinTimeOffEnd = GetSettings()->Session.JoinFirstAttempt + 60 * 60; 01000 } 01001 } else if (hours_since_first_attempt < 11) { 01002 if (GetSettings()->Session.JoinTimeOnAir < 36000) { 01003 GetSettings()->Session.JoinTimeOnAir = 36000; 01004 } 01005 time_on_max = 72000; 01006 rand_time_off = rand_r(time_off_max - 1, time_off_max + 1); 01007 // time off max 1 hour 01008 time_off_max = std::min < uint32_t > (time_off_max * 2, 60 * 60); 01009 01010 if (GetSettings()->Session.JoinTimeOnAir < time_on_max) { 01011 GetSettings()->Session.JoinTimeOnAir += GetTimeOnAir(size); 01012 GetSettings()->Session.JoinTimeOffEnd = now + rand_time_off; 01013 } else { 01014 logWarning("Max time-on-air limit met for current join backoff period"); 01015 GetSettings()->Session.JoinTimeOffEnd = GetSettings()->Session.JoinFirstAttempt + 11 * 60 * 60; 01016 } 01017 } else { 01018 if (GetSettings()->Session.JoinTimeOnAir < 72000) { 01019 GetSettings()->Session.JoinTimeOnAir = 72000; 01020 } 01021 uint32_t join_time = 2500; 01022 01023 // 16 join attempts is ~2754 ms, check if this is the third of the 24 hour period 01024 01025 time_on_max = 80700; 01026 time_off_max = 1 * 60 * 60; // 1 hour 01027 rand_time_off = rand_r(time_off_max - 1, time_off_max + 1); 01028 01029 if (GetSettings()->Session.JoinTimeOnAir < time_on_max - join_time) { 01030 GetSettings()->Session.JoinTimeOnAir += GetTimeOnAir(size); 01031 GetSettings()->Session.JoinTimeOffEnd = now + rand_time_off; 01032 } else { 01033 logWarning("Max time-on-air limit met for current join backoff period"); 01034 // Reset the join time on air and set end of restriction to the next 24 hour period 01035 GetSettings()->Session.JoinTimeOnAir = 72000; 01036 uint16_t days = (now - GetSettings()->Session.JoinFirstAttempt) / (24 * 60 * 60) + 1; 01037 logWarning("days : %d", days); 01038 GetSettings()->Session.JoinTimeOffEnd = GetSettings()->Session.JoinFirstAttempt + ((days * 24) + 11) * 60 * 60; 01039 } 01040 } 01041 01042 logWarning("JoinBackoff: %lu seconds Time On Air: %lu / %lu", GetSettings()->Session.JoinTimeOffEnd - now, GetSettings()->Session.JoinTimeOnAir, time_on_max); 01043 } else { 01044 GetSettings()->Session.JoinTimeOnAir += GetTimeOnAir(size); 01045 GetSettings()->Session.JoinTimeOffEnd = now + rand_r(GetSettings()->Network.JoinDelay + 2, GetSettings()->Network.JoinDelay + 3); 01046 } 01047 01048 return LORA_OK; 01049 } 01050 01051 bool ChannelPlan_US915::DecodeBeacon(const uint8_t* payload, size_t size, BeaconData_t& data) { 01052 uint16_t crc1, crc1_rx, crc2, crc2_rx; 01053 const BCNPayload* beacon = (const BCNPayload*)payload; 01054 01055 // First check the size of the packet 01056 if (size != sizeof(BCNPayload)) 01057 return false; 01058 01059 // Next we verify the CRCs are correct 01060 crc1 = CRC16(beacon->RFU1, sizeof(beacon->RFU1) + sizeof(beacon->Time)); 01061 memcpy((uint8_t*)&crc1_rx, beacon->CRC1, sizeof(uint16_t)); 01062 01063 if (crc1 != crc1_rx) 01064 return false; 01065 01066 crc2 = CRC16(beacon->GwSpecific, sizeof(beacon->GwSpecific) + sizeof(beacon->RFU2)); 01067 memcpy((uint8_t*)&crc2_rx, beacon->CRC2, sizeof(uint16_t)); 01068 01069 if (crc2 != crc2_rx) 01070 return false; 01071 01072 // Now that we have confirmed this packet is a beacon, parse and complete the output struct 01073 memcpy(&data.Time, beacon->Time, sizeof(beacon->Time)); 01074 data.InfoDesc = beacon->GwSpecific[0]; 01075 01076 // Update the GPS fields if we have a gps info descriptor 01077 if (data.InfoDesc == GPS_FIRST_ANTENNA || 01078 data.InfoDesc == GPS_SECOND_ANTENNA || 01079 data.InfoDesc == GPS_THIRD_ANTENNA) { 01080 // Latitude and Longitude 3 bytes in length 01081 memcpy(&data.Latitude, &beacon->GwSpecific[1], 3); 01082 memcpy(&data.Longitude, &beacon->GwSpecific[4], 3); 01083 } 01084 01085 return true; 01086 } 01087 01088 void ChannelPlan_US915::FrequencyHop(uint32_t time, uint32_t period, uint32_t devAddr) { 01089 uint32_t channel; 01090 uint32_t freq; 01091 01092 if (GetSettings()->Session.BeaconFreqHop) { 01093 channel = (time / period) % US915_BEACON_CHANNELS; 01094 freq = US915_BEACON_FREQ_BASE + (channel * US915_BEACON_FREQ_STEP); 01095 GetSettings()->Session.BeaconFrequency = freq; 01096 } 01097 01098 if (GetSettings()->Session.PingSlotFreqHop) { 01099 channel = (time / period + devAddr) % US915_BEACON_CHANNELS; 01100 freq = US915_BEACON_FREQ_BASE + (channel * US915_BEACON_FREQ_STEP); 01101 GetSettings()->Session.PingSlotFrequency = freq; 01102 } 01103 }
Generated on Tue Jul 12 2022 18:19:47 by 1.7.2