From 16fd3128b8312d4ff7b5a3391f718dec41a72028 Mon Sep 17 00:00:00 2001
From: Jon Beniston <jon@beniston.com>
Date: Fri, 26 Aug 2022 13:47:36 +0100
Subject: [PATCH] Check ICAO in sink worker, so CRC can be checked. Fix
 warnings

---
 plugins/channelrx/demodadsb/adsbdemodgui.cpp  | 12 +++----
 plugins/channelrx/demodadsb/adsbdemodgui.h    |  2 +-
 .../demodadsb/adsbdemodsinkworker.cpp         | 34 ++++++++++++++-----
 .../channelrx/demodadsb/adsbdemodsinkworker.h |  1 +
 4 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp
index 9a0b8ddb1..898119544 100644
--- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp
+++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp
@@ -1557,7 +1557,7 @@ void ADSBDemodGUI::handleADSB(
         else if (tc == 29)
         {
             // Target state and status
-            bool selAltitudeType = (data[5] >> 7) & 0x1;
+            //bool selAltitudeType = (data[5] >> 7) & 0x1;
             int selAltitudeFix = ((data[5] & 0x7f) << 4) | ((data[6] >> 4) & 0xf);
             if (selAltitudeFix != 0)
             {
@@ -1665,11 +1665,11 @@ void ADSBDemodGUI::handleADSB(
     }
     else if ((df == 4) || (df == 5))
     {
-        decodeModeS(data, dateTime, df, aircraft);
+        decodeModeS(data, df, aircraft);
     }
     else if ((df == 20) || (df == 21))
     {
-        decodeModeS(data, dateTime, df, aircraft);
+        decodeModeS(data, df, aircraft);
         decodeCommB(data, dateTime, df, aircraft, updatedCallsign);
     }
 
@@ -1682,7 +1682,7 @@ void ADSBDemodGUI::handleADSB(
     }
 }
 
-void ADSBDemodGUI::decodeModeS(const QByteArray data, const QDateTime dateTime, int df, Aircraft *aircraft)
+void ADSBDemodGUI::decodeModeS(const QByteArray data, int df, Aircraft *aircraft)
 {
     bool wasOnSurface = aircraft->m_onSurface;
     bool takenOff = false;
@@ -2060,7 +2060,7 @@ void ADSBDemodGUI::decodeCommB(const QByteArray data, const QDateTime dateTime,
         bool hazardWindShearInconsistent = !hazardWindShearStatus && (hazardWindShear != 0);
 
         bool hazardMicroburstStatus = (data[4] >> 1) & 0x1;
-        int hazardMicroburst = ((data[4] & 0x1) << 1) || ((data[5] >> 7) & 0x1);
+        int hazardMicroburst = ((data[4] & 0x1) << 1) | ((data[5] >> 7) & 0x1);
         bool hazardMicroburstInconsistent = !hazardMicroburstStatus && (hazardMicroburst != 0);
 
         bool hazardIcingStatus = (data[5] >> 6) & 0x1;
@@ -2201,7 +2201,7 @@ void ADSBDemodGUI::decodeCommB(const QByteArray data, const QDateTime dateTime,
         int arAltitudeRate = arAltitudeRateFix * 64; // Ft/min
         bool arAltitudeRateInconsistent = (abs(arAltitudeRate) > 6000) || (!arAltitudeRateStatus && (arAltitudeRateFix != 0));
 
-        bool bds_5_3 = !arMagHeadingInconsistent && !arIndicatedAirspeedInconsistent && !arMachInconsistent && !arTrueAirspeedInconsistent;
+        bool bds_5_3 = !arMagHeadingInconsistent && !arIndicatedAirspeedInconsistent && !arMachInconsistent && !arTrueAirspeedInconsistent && !arAltitudeRateInconsistent;
 
         // BDS 6,0 - Heading and speed report - EHS
 
diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h
index e7bbd9b00..8bf57accf 100644
--- a/plugins/channelrx/demodadsb/adsbdemodgui.h
+++ b/plugins/channelrx/demodadsb/adsbdemodgui.h
@@ -969,7 +969,7 @@ private:
         float correlationOnes,
         unsigned crc,
         bool updateModel);
-    void decodeModeS(const QByteArray data, const QDateTime dateTime, int df, Aircraft *aircraft);
+    void decodeModeS(const QByteArray data, int df, Aircraft *aircraft);
     void decodeCommB(const QByteArray data, const QDateTime dateTime, int df, Aircraft *aircraft, bool &updatedCallsign);
     QList<SWGSDRangel::SWGMapAnimation *> *animate(QDateTime dateTime, Aircraft *aircraft);
     SWGSDRangel::SWGMapAnimation *gearAnimation(QDateTime startDateTime, bool up);
diff --git a/plugins/channelrx/demodadsb/adsbdemodsinkworker.cpp b/plugins/channelrx/demodadsb/adsbdemodsinkworker.cpp
index f3bf5f09e..bd48e4db8 100644
--- a/plugins/channelrx/demodadsb/adsbdemodsinkworker.cpp
+++ b/plugins/channelrx/demodadsb/adsbdemodsinkworker.cpp
@@ -195,6 +195,9 @@ void ADSBDemodSinkWorker::run()
                 {
                     // Got a valid frame
                     m_demodStats.m_adsbFrames++;
+                    // Get 24-bit ICAO and save in hash of ICAOs that have been seen
+                    unsigned icao = ((data[1] & 0xff) << 16) | ((data[2] & 0xff) << 8) | (data[3] & 0xff);
+                    m_icaos.insert(icao, true);
                     // Don't try to re-demodulate the same frame
                     // We could possibly allow a partial overlap here
                     readIdx += (ADS_B_ES_BITS+ADS_B_PREAMBLE_BITS)*ADS_B_CHIPS_PER_BIT*samplesPerChip - 1;
@@ -228,26 +231,39 @@ void ADSBDemodSinkWorker::run()
             {
                 int bytes;
 
-                m_crc.init();
-                if ((df == 0) || (df == 4) || (df == 5) || (df == 11))
+                // Determine number of bytes in frame depending on downlink format
+                if ((df == 0) || (df == 4) || (df == 5) || (df == 11)) {
                     bytes = 56/8;
-                else if ((df == 16) || (df == 20) || (df == 21) || (df >= 24))
+                } else if ((df == 16) || (df == 20) || (df == 21) || (df >= 24)) {
                     bytes = 112/8;
-                else
+                } else {
                     bytes = 0;
+                }
                 if (bytes > 0)
                 {
+                    // Extract received parity
                     int parity = (data[bytes-3] << 16) | (data[bytes-2] << 8) | data[bytes-1];
+                    // Calculate CRC on received frame
+                    m_crc.init();
                     m_crc.calculate(data, bytes-3);
                     int crc = m_crc.get();
+                    // DF4 / DF5 / DF20 / DF21 have ICAO address XORed in to parity.
+                    // Extract ICAO from parity and see if it matches an aircraft we've already
+                    // received an ADS-B frame from
+                    if ((df == 4) || (df == 5) || (df == 20) || (df == 21))
+                    {
+                        unsigned icao = (parity ^ crc) & 0xffffff;
+                        if (m_icaos.contains(icao)) {
+                            crc ^= icao;
+                        }
+                    }
                     // For DF11, the last 7 bits may have an address/interogration indentifier (II)
                     // XORed in, so we ignore those bits
-                    // DF4 / DF5 / DF20 / DF21 have full address XORed in to parity. GUI will check if valid
-                    if ((parity == crc) || ((df == 11) && (parity & 0xffff80) == (crc & 0xffff80)) || (df == 4) || (df == 5) || (df == 20) || (df == 21))
+                    if ((parity == crc) || ((df == 11) && ((parity & 0xffff80) == (crc & 0xffff80))))
                     {
                         m_demodStats.m_modesFrames++;
-                        // Pass to GUI
-                        if (m_sink->getMessageQueueToGUI())
+                        // Pass to GUI (only pass formats it can decode)
+                        if (m_sink->getMessageQueueToGUI() && ((df == 4) || (df == 5) || (df == 20) || (df == 21)))
                         {
                             ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
                                 QByteArray((char*)data, sizeof(data)),
@@ -258,7 +274,7 @@ void ADSBDemodSinkWorker::run()
                             m_sink->getMessageQueueToGUI()->push(msg);
                         }
                         // Pass to worker to feed to other servers
-                        if (m_sink->getMessageQueueToWorker() && (parity == crc))
+                        if (m_sink->getMessageQueueToWorker())
                         {
                             ADSBDemodReport::MsgReportADSB *msg = ADSBDemodReport::MsgReportADSB::create(
                                 QByteArray((char*)data, sizeof(data)),
diff --git a/plugins/channelrx/demodadsb/adsbdemodsinkworker.h b/plugins/channelrx/demodadsb/adsbdemodsinkworker.h
index fe9a295e8..db60e57b8 100644
--- a/plugins/channelrx/demodadsb/adsbdemodsinkworker.h
+++ b/plugins/channelrx/demodadsb/adsbdemodsinkworker.h
@@ -76,6 +76,7 @@ private:
     Real m_correlationThresholdLinear;
     Real m_correlationScale;
     crcadsb m_crc;                      //!< Have as member to avoid recomputing LUT
+    QHash<int, bool> m_icaos;           //!< ICAO addresses that have been received
 
     QDateTime rxDateTime(int firstIdx, int readBuffer) const;