ver1
Diff: plans/ChannelPlan_US915.cpp
- Revision:
- 172:7ec44396a51b
- Parent:
- 153:7c00843e4bba
- Child:
- 178:8f7d93f3bbb5
diff -r 4a3957006cf2 -r 7ec44396a51b plans/ChannelPlan_US915.cpp --- a/plans/ChannelPlan_US915.cpp Wed Aug 08 09:33:35 2018 -0500 +++ b/plans/ChannelPlan_US915.cpp Thu Aug 30 09:05:16 2018 -0500 @@ -28,6 +28,8 @@ ChannelPlan_US915::ChannelPlan_US915() : ChannelPlan(NULL, NULL) + , _bcnFreqHop(true) + , _pingFreqHop(true) { } @@ -35,6 +37,8 @@ ChannelPlan_US915::ChannelPlan_US915(Settings* settings) : ChannelPlan(NULL, settings) + , _bcnFreqHop(true) + , _pingFreqHop(true) { } @@ -42,6 +46,8 @@ ChannelPlan_US915::ChannelPlan_US915(SxRadio* radio, Settings* settings) : ChannelPlan(radio, settings) + , _bcnFreqHop(true) + , _pingFreqHop(true) { } @@ -87,6 +93,11 @@ _freqDStep500k = US915_500K_DSTEP; GetSettings()->Session.Rx2Frequency = US915_500K_DBASE; + GetSettings()->Session.BeaconFrequency = US915_BEACON_FREQ_BASE; + GetSettings()->Session.BeaconDatarateIndex = US915_BEACON_DR; + GetSettings()->Session.PingSlotFrequency = US915_BEACON_FREQ_BASE; + GetSettings()->Session.PingSlotDatarateIndex = US915_BEACON_DR; + _minDatarate = US915_MIN_DATARATE; _maxDatarate = US915_MAX_DATARATE; _minRx2Datarate = DR_8; @@ -280,7 +291,7 @@ return LORA_OK; } -uint8_t ChannelPlan_US915::SetRxConfig(uint8_t window, bool continuous) { +uint8_t ChannelPlan_US915::SetRxConfig(uint8_t window, bool continuous, uint16_t wnd_growth) { RxWindow rxw = GetRxWindow(window); GetRadio()->SetChannel(rxw.Frequency); @@ -290,8 +301,10 @@ uint32_t sf = rxDr.SpreadingFactor; uint8_t cr = rxDr.Coderate; uint8_t pl = rxDr.PreambleLength; - uint16_t sto = rxDr.SymbolTimeout(); + uint16_t sto = rxDr.SymbolTimeout() * wnd_growth; uint32_t afc = 0; + bool fixLen = false; + uint8_t payloadLen = 0U; bool crc = false; // downlink does not use CRC according to LORAWAN if (GetSettings()->Network.DisableCRC == true) @@ -304,6 +317,14 @@ iq = txDr.TxIQ; } + // Beacon modifications - no I/Q inversion, fixed length rx, preamble + if (window == RX_BEACON) { + iq = txDr.TxIQ; + fixLen = true; + payloadLen = sizeof(BCNPayload); + pl = BEACON_PREAMBLE_LENGTH; + } + SxRadio::RadioModems_t modem = SxRadio::MODEM_LORA; if (sf == SF_FSK) { @@ -320,7 +341,7 @@ // logTrace("Configure radio for RX%d on freq: %lu", window, rxw.Frequency); // logTrace("RX SF: %u BW: %u CR: %u PL: %u STO: %u CRC: %d IQ: %d", sf, bw, cr, pl, sto, crc, iq); - GetRadio()->SetRxConfig(modem, bw, sf, cr, afc, pl, sto, false, 0, crc, false, 0, iq, continuous); + GetRadio()->SetRxConfig(modem, bw, sf, cr, afc, pl, sto, fixLen, payloadLen, crc, false, 0, iq, continuous); return LORA_OK; } @@ -410,7 +431,8 @@ rxw.Frequency = GetSettings()->Network.TxFrequency; index = GetSettings()->Session.TxDatarate; } else { - if (window == 1) { + switch (window) { + case RX_1: if (_txChannel < _numChans125k) { if (GetSettings()->Network.Mode == lora::PRIVATE_MTS) rxw.Frequency = _freqDBase500k + (_txChannel / 8) * _freqDStep500k; @@ -431,15 +453,31 @@ if (index < DR_8) index = DR_8; } - } else { - if (GetSettings()->Network.Mode == lora::PRIVATE_MTS) + + break; + + case RX_BEACON: + rxw.Frequency = GetSettings()->Session.BeaconFrequency; + index = GetSettings()->Session.BeaconDatarateIndex; + break; + + case RX_SLOT: + rxw.Frequency = GetSettings()->Session.PingSlotFrequency; + index = GetSettings()->Session.PingSlotDatarateIndex; + break; + + // RX2, RXC, RX_TEST, etc.. + default: + if (GetSettings()->Network.Mode == lora::PRIVATE_MTS) { if (_txChannel < _numChans125k) { rxw.Frequency = _freqDBase500k + (_txChannel / 8) * _freqDStep500k; } else { rxw.Frequency = _freqDBase500k + (_txChannel % 8) * _freqDStep500k; } - else + } else { rxw.Frequency = GetSettings()->Session.Rx2Frequency; + } + index = GetSettings()->Session.Rx2DatarateIndex; } } @@ -506,54 +544,73 @@ } uint8_t ChannelPlan_US915::HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { + uint8_t datarate = 0; + uint32_t freq = 0; + bool freqHop = false; - lora::CopyFreqtoInt(payload + index, _beaconRxChannel.Frequency); - index += 3; + status = 0x03; - if (_beaconRxChannel.Frequency != 0) { - _beaconRxChannel.DrRange.Value = payload[index]; - } else { - // TODO: set to default beacon rx channel + freq = payload[index++]; + freq |= payload[index++] << 8; + freq |= payload[index++] << 16; + freq *= 100; + + datarate = payload[index] & 0x0F; + + if (freq == 0U) { + logInfo("Received request to reset ping slot frequency to default"); + freq = US915_BEACON_FREQ_BASE; + freqHop = true; + } else if (!CheckRfFrequency(freq)) { + logInfo("Freq KO"); + status &= 0xFE; // Channel frequency KO } - status = 0x03; + if (datarate < _minRx2Datarate || datarate > _maxRx2Datarate) { + logInfo("DR KO"); + status &= 0xFD; // Datarate KO + } + + if ((status & 0x03) == 0x03) { + logInfo("PingSlotChannelReq accepted DR: %d Freq: %d", datarate, freq); + GetSettings()->Session.PingSlotFrequency = freq; + GetSettings()->Session.PingSlotDatarateIndex = datarate; + _pingFreqHop = freqHop; + } else { + logInfo("PingSlotChannelReq rejected DR: %d Freq: %d", datarate, freq); + } + return LORA_OK; } uint8_t ChannelPlan_US915::HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { + uint32_t freq = 0; + bool freqHop = false; - status = 0x03; - Channel chParam; + status = 0x01; - // Skip channel index - index++; + freq = payload[index++]; + freq |= payload[index++] << 8; + freq |= payload[index] << 16; + freq *= 100; - lora::CopyFreqtoInt(payload + index, chParam.Frequency); - index += 3; - chParam.DrRange.Value = payload[index++]; - - if (!GetRadio()->CheckRfFrequency(chParam.Frequency)) { + if (freq == 0U) { + logInfo("Received request to reset beacon frequency to default"); + freq = US915_BEACON_FREQ_BASE; + freqHop = true; + } else if (!CheckRfFrequency(freq)) { + logInfo("Freq KO"); status &= 0xFE; // Channel frequency KO } - if (chParam.DrRange.Fields.Min < chParam.DrRange.Fields.Max) { - status &= 0xFD; // Datarate range KO - } else if (chParam.DrRange.Fields.Min < _minDatarate || chParam.DrRange.Fields.Min > _maxDatarate) { - status &= 0xFD; // Datarate range KO - } else if (chParam.DrRange.Fields.Max < _minDatarate || chParam.DrRange.Fields.Max > _maxDatarate) { - status &= 0xFD; // Datarate range KO + if (status & 0x01) { + logInfo("BeaconFrequencyReq accepted Freq: %d", freq); + GetSettings()->Session.BeaconFrequency = freq; + _bcnFreqHop = freqHop; + } else { + logInfo("BeaconFrequencyReq rejected Freq: %d", freq); } - if ((status & 0x03) == 0x03) { - _beaconChannel = chParam; - } - - if (_beaconChannel.Frequency == 0) { - // TODO: Set to default - } - - status = 0x01; - return LORA_OK; } @@ -991,3 +1048,57 @@ return LORA_OK; } + +bool ChannelPlan_US915::DecodeBeacon(const uint8_t* payload, size_t size, BeaconData_t& data) { + uint16_t crc1, crc1_rx, crc2, crc2_rx; + const BCNPayload* beacon = (const BCNPayload*)payload; + + // First check the size of the packet + if (size != sizeof(BCNPayload)) + return false; + + // Next we verify the CRCs are correct + crc1 = CRC16(beacon->RFU1, sizeof(beacon->RFU1) + sizeof(beacon->Time)); + memcpy((uint8_t*)&crc1_rx, beacon->CRC1, sizeof(uint16_t)); + + if (crc1 != crc1_rx) + return false; + + crc2 = CRC16(beacon->GwSpecific, sizeof(beacon->GwSpecific) + sizeof(beacon->RFU2)); + memcpy((uint8_t*)&crc2_rx, beacon->CRC2, sizeof(uint16_t)); + + if (crc2 != crc2_rx) + return false; + + // Now that we have confirmed this packet is a beacon, parse and complete the output struct + memcpy(&data.Time, beacon->Time, sizeof(beacon->Time)); + data.InfoDesc = beacon->GwSpecific[0]; + + // Update the GPS fields if we have a gps info descriptor + if (data.InfoDesc == GPS_FIRST_ANTENNA || + data.InfoDesc == GPS_SECOND_ANTENNA || + data.InfoDesc == GPS_THIRD_ANTENNA) { + // Latitude and Longitude 3 bytes in length + memcpy(&data.Latitude, &beacon->GwSpecific[1], 3); + memcpy(&data.Longitude, &beacon->GwSpecific[4], 3); + } + + return true; +} + +void ChannelPlan_US915::FrequencyHop(uint32_t time, uint32_t period, uint32_t devAddr) { + uint32_t channel; + uint32_t freq; + + if (_bcnFreqHop) { + channel = (time / period) % US915_BEACON_CHANNELS; + freq = US915_BEACON_FREQ_BASE + (channel * US915_BEACON_FREQ_STEP); + GetSettings()->Session.BeaconFrequency = freq; + } + + if (_pingFreqHop) { + channel = (time / period + devAddr) % US915_BEACON_CHANNELS; + freq = US915_BEACON_FREQ_BASE + (channel * US915_BEACON_FREQ_STEP); + GetSettings()->Session.PingSlotFrequency = freq; + } +}