MultiTech / libxDot-dev-mbed5-deprecated

Dependents:   Dot-Examples Dot-AT-Firmware Dot-Examples TEST_FF1705 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ChannelPlan_AU915.cpp Source File

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 }