ver1
Diff: plans/ChannelPlan_AS923.cpp
- Revision:
- 172:7ec44396a51b
- Parent:
- 167:09fd17fee0f5
- Child:
- 178:8f7d93f3bbb5
diff -r 4a3957006cf2 -r 7ec44396a51b plans/ChannelPlan_AS923.cpp --- a/plans/ChannelPlan_AS923.cpp Wed Aug 08 09:33:35 2018 -0500 +++ b/plans/ChannelPlan_AS923.cpp Thu Aug 30 09:05:16 2018 -0500 @@ -24,7 +24,7 @@ const uint8_t ChannelPlan_AS923::AS923_MAX_PAYLOAD_SIZE[] = { 51, 51, 51, 115, 242, 242, 242, 242, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t ChannelPlan_AS923::AS923_MAX_PAYLOAD_SIZE_REPEATER[] = { 51, 51, 51, 115, 222, 222, 222, 222, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t ChannelPlan_AS923::AS923_MAX_PAYLOAD_SIZE_400[] = { 0, 0, 11, 53, 125, 242, 242, 242, 0, 0, 0, 0, 0, 0, 0, 0 }; -const uint8_t ChannelPlan_AS923::AS923_MAX_PAYLOAD_SIZE_REPEATER_400[] = { 0, 0, 11, 53, 128, 222, 222, 222, 0, 0, 0, 0, 0, 0, 0, 0 }; +const uint8_t ChannelPlan_AS923::AS923_MAX_PAYLOAD_SIZE_REPEATER_400[] = { 0, 0, 11, 53, 125, 222, 222, 222, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t MAX_ERP_VALUES[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 }; @@ -92,6 +92,12 @@ GetSettings()->Session.Rx2Frequency = 923200000; GetSettings()->Session.Rx2DatarateIndex = DR_2; + + GetSettings()->Session.BeaconFrequency = AS923_BEACON_FREQ; + GetSettings()->Session.BeaconDatarateIndex = AS923_BEACON_DR; + GetSettings()->Session.PingSlotFrequency = AS923_BEACON_FREQ; + GetSettings()->Session.PingSlotDatarateIndex = AS923_BEACON_DR; + GetSettings()->Session.Max_EIRP = 16; logInfo("Initialize datarates..."); @@ -271,7 +277,7 @@ return LORA_OK; } -uint8_t ChannelPlan_AS923::SetRxConfig(uint8_t window, bool continuous) { +uint8_t ChannelPlan_AS923::SetRxConfig(uint8_t window, bool continuous, uint16_t wnd_growth) { RxWindow rxw = GetRxWindow(window); @@ -285,8 +291,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) @@ -299,6 +307,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) { @@ -315,7 +331,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; } @@ -375,7 +391,9 @@ rxw.Frequency = GetSettings()->Network.TxFrequency; index = GetSettings()->Session.TxDatarate; } else { - if (window == 1) { + switch (window) { + case RX_1: + { // Use same frequency as TX rxw.Frequency = _channels[_txChannel].Frequency; @@ -392,8 +410,21 @@ uint8_t minDr = GetSettings()->Session.DownlinkDwelltime == 1 ? 2 : 0; index = std::min<uint8_t>(5, std::max<uint8_t>(minDr, index)); - } else { - // Use session RX2 frequency + 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; } @@ -492,54 +523,67 @@ } uint8_t ChannelPlan_AS923::HandlePingSlotChannelReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { + uint8_t datarate = 0; + uint32_t freq = 0; - 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 = AS923_BEACON_FREQ; + } 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; + } else { + logInfo("PingSlotChannelReq rejected DR: %d Freq: %d", datarate, freq); + } + return LORA_OK; } uint8_t ChannelPlan_AS923::HandleBeaconFrequencyReq(const uint8_t* payload, uint8_t index, uint8_t size, uint8_t& status) { + uint32_t freq = 0; - 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 = AS923_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 (status & 0x01) { + logInfo("BeaconFrequencyReq accepted Freq: %d", freq); + GetSettings()->Session.BeaconFrequency = freq; + } 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; } @@ -1045,3 +1089,39 @@ } } +bool ChannelPlan_AS923::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; +}