ver1
Diff: plans/ChannelPlan_EU868.cpp
- Revision:
- 172:7ec44396a51b
- Parent:
- 167:09fd17fee0f5
- Child:
- 178:8f7d93f3bbb5
--- a/plans/ChannelPlan_EU868.cpp Wed Aug 08 09:33:35 2018 -0500 +++ b/plans/ChannelPlan_EU868.cpp Thu Aug 30 09:05:16 2018 -0500 @@ -92,6 +92,11 @@ GetSettings()->Session.Rx2Frequency = EU868_RX2_FREQ; GetSettings()->Session.Rx2DatarateIndex = DR_0; + GetSettings()->Session.BeaconFrequency = EU868_BEACON_FREQ; + GetSettings()->Session.BeaconDatarateIndex = EU868_BEACON_DR; + GetSettings()->Session.PingSlotFrequency = EU868_BEACON_FREQ; + GetSettings()->Session.PingSlotDatarateIndex = EU868_BEACON_DR; + logInfo("Initialize datarates..."); dr.SpreadingFactor = SF_12; @@ -249,14 +254,6 @@ return LORA_OK; } -uint32_t ChannelPlan_EU868::GetTimeOnAir(uint8_t bytes) { - SetTxConfig(); - if (GetSettings()->Session.TxDatarate == lora::DR_7) { - return GetRadio()->TimeOnAir(SxRadio::MODEM_FSK, bytes) / 1000u; - } - return GetRadio()->TimeOnAir(SxRadio::MODEM_LORA, bytes) / 1000u; -} - uint8_t ChannelPlan_EU868::SetTxConfig() { logInfo("Configure radio for TX"); @@ -310,7 +307,7 @@ return LORA_OK; } -uint8_t ChannelPlan_EU868::SetRxConfig(uint8_t window, bool continuous) { +uint8_t ChannelPlan_EU868::SetRxConfig(uint8_t window, bool continuous, uint16_t wnd_growth) { RxWindow rxw = GetRxWindow(window); @@ -324,8 +321,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) @@ -338,6 +337,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) { @@ -354,7 +361,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; } @@ -400,7 +407,8 @@ rxw.Frequency = GetSettings()->Network.TxFrequency; index = GetSettings()->Session.TxDatarate; } else { - if (window == 1) { + switch (window) { + case RX_1: rxw.Frequency = _channels[_txChannel].Frequency; if (GetSettings()->Session.TxDatarate > GetSettings()->Session.Rx1DatarateOffset) { @@ -408,7 +416,21 @@ } else { index = 0; } - } else { + + 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: rxw.Frequency = GetSettings()->Session.Rx2Frequency; index = GetSettings()->Session.Rx2DatarateIndex; } @@ -507,57 +529,70 @@ } uint8_t ChannelPlan_EU868::HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { - - lora::CopyFreqtoInt(payload + index, _beaconRxChannel.Frequency); - index += 3; - - if (_beaconRxChannel.Frequency != 0) { - _beaconRxChannel.DrRange.Value = payload[index]; - } else { - // TODO: set to default beacon rx channel - } + uint8_t datarate = 0; + uint32_t freq = 0; status = 0x03; - return LORA_OK; -} -uint8_t ChannelPlan_EU868::HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { - - status = 0x03; - Channel chParam; + freq = payload[index++]; + freq |= payload[index++] << 8; + freq |= payload[index++] << 16; + freq *= 100; - // Skip channel index - index++; + datarate = payload[index] & 0x0F; - 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 ping slot frequency to default"); + freq = EU868_BEACON_FREQ; + } 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 (datarate < _minRx2Datarate || datarate > _maxRx2Datarate) { + logInfo("DR KO"); + status &= 0xFD; // Datarate KO } if ((status & 0x03) == 0x03) { - _beaconChannel = chParam; + logInfo("PingSlotChannelReq accepted DR: %d Freq: %d", datarate, freq); + GetSettings()->Session.PingSlotFrequency = freq; + GetSettings()->Session.PingSlotDatarateIndex = datarate; + } else { + logInfo("PingSlotChannelReq rejected DR: %d Freq: %d", datarate, freq); } - if (_beaconChannel.Frequency == 0) { - // TODO: Set to default - } - - status = 0x01; - return LORA_OK; } +uint8_t ChannelPlan_EU868::HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) +{ + uint32_t freq = 0; + + status = 0x01; + + freq = payload[index++]; + freq |= payload[index++] << 8; + freq |= payload[index] << 16; + freq *= 100; + + if (freq == 0U) { + logInfo("Received request to reset beacon frequency to default"); + freq = EU868_BEACON_FREQ; + } else if (!CheckRfFrequency(freq)) { + logInfo("Freq KO"); + status &= 0xFE; // Channel frequency KO + } + + if (status & 0x01) { + logInfo("BeaconFrequencyReq accepted Freq: %d", freq); + GetSettings()->Session.BeaconFrequency = freq; + } else { + logInfo("BeaconFrequencyReq rejected Freq: %d", freq); + } + + return LORA_OK; +} uint8_t ChannelPlan_EU868::HandleAdrCommand(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { @@ -1020,3 +1055,39 @@ return LORA_OK; } +bool ChannelPlan_EU868::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->RFU, sizeof(beacon->RFU) + 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)); + 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; +}