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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ChannelPlan_US915.cpp Source File

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 }