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