ver1

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;
+}