From 599c31493a72442d145fb7049cf243ba2d554fb2 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 10 Nov 2020 12:03:36 +0000 Subject: [PATCH 01/10] Add decode of Mode-A transonder (Squawk) code --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 47 ++++++++++++++------ plugins/channelrx/demodadsb/adsbdemodgui.h | 3 ++ plugins/channelrx/demodadsb/adsbdemodgui.ui | 18 +++++--- plugins/channelrx/demodadsb/readme.md | 1 + 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index 08b8ca36f..d62ee3e41 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -61,16 +61,17 @@ #define ADSB_COL_LONGITUDE 11 #define ADSB_COL_CATEGORY 12 #define ADSB_COL_STATUS 13 -#define ADSB_COL_REGISTRATION 14 -#define ADSB_COL_COUNTRY 15 -#define ADSB_COL_REGISTERED 16 -#define ADSB_COL_MANUFACTURER 17 -#define ADSB_COL_OWNER 18 -#define ADSB_COL_OPERATOR_ICAO 19 -#define ADSB_COL_TIME 20 -#define ADSB_COL_FRAMECOUNT 21 -#define ADSB_COL_CORRELATION 22 -#define ADSB_COL_RSSI 23 +#define ADSB_COL_SQUAWK 14 +#define ADSB_COL_REGISTRATION 15 +#define ADSB_COL_COUNTRY 16 +#define ADSB_COL_REGISTERED 17 +#define ADSB_COL_MANUFACTURER 18 +#define ADSB_COL_OWNER 19 +#define ADSB_COL_OPERATOR_ICAO 20 +#define ADSB_COL_TIME 21 +#define ADSB_COL_FRAMECOUNT 22 +#define ADSB_COL_CORRELATION 23 +#define ADSB_COL_RSSI 24 const char *Aircraft::m_speedTypeNames[] = { "GS", "TAS", "IAS" @@ -617,6 +618,7 @@ void ADSBDemodGUI::handleADSB( ui->adsbData->setItem(row, ADSB_COL_LONGITUDE, aircraft->m_longitudeItem); ui->adsbData->setItem(row, ADSB_COL_CATEGORY, aircraft->m_emitterCategoryItem); ui->adsbData->setItem(row, ADSB_COL_STATUS, aircraft->m_statusItem); + ui->adsbData->setItem(row, ADSB_COL_SQUAWK, aircraft->m_squawkItem); ui->adsbData->setItem(row, ADSB_COL_REGISTRATION, aircraft->m_registrationItem); ui->adsbData->setItem(row, ADSB_COL_COUNTRY, aircraft->m_countryItem); ui->adsbData->setItem(row, ADSB_COL_REGISTERED, aircraft->m_registeredItem); @@ -957,12 +959,27 @@ void ADSBDemodGUI::handleADSB( { // Aircraft status int st = data[4] & 0x7; // Subtype - int es = (data[5] >> 5) & 0x7; // Emergency state if (st == 1) + { + int es = (data[5] >> 5) & 0x7; // Emergency state + int modeA = ((data[5] << 8) & 0x1f00) | (data[6] & 0xff); // Mode-A code (squawk) aircraft->m_status = emergencyStatus[es]; - else - aircraft->m_status = QString(""); - aircraft->m_statusItem->setText(aircraft->m_status); + aircraft->m_statusItem->setText(aircraft->m_status); + int a, b, c, d; + c = ((modeA >> 12) & 1) | ((modeA >> (10-1)) & 0x2) | ((modeA >> (8-2)) & 0x4); + a = ((modeA >> 11) & 1) | ((modeA >> (9-1)) & 0x2) | ((modeA >> (7-2)) & 0x4); + b = ((modeA >> 5) & 1) | ((modeA >> (3-1)) & 0x2) | ((modeA << (1)) & 0x4); + d = ((modeA >> 4) & 1) | ((modeA >> (2-1)) & 0x2) | ((modeA << (2)) & 0x4); + aircraft->m_squawk = a*1000 + b*100 + c*10 + d; + if (modeA & 0x40) + aircraft->m_squawkItem->setText(QString("%1 IDENT").arg(aircraft->m_squawk, 4, 10, QLatin1Char('0'))); + else + aircraft->m_squawkItem->setText(QString("%1").arg(aircraft->m_squawk, 4, 10, QLatin1Char('0'))); + } + else if (st == 2) + { + // TCAS/ACAS RA Broadcast + } } else if (tc == 29) { @@ -1872,6 +1889,7 @@ void ADSBDemodGUI::resizeTable() ui->adsbData->setItem(row, ADSB_COL_LONGITUDE, new QTableWidgetItem("-180.00000")); ui->adsbData->setItem(row, ADSB_COL_CATEGORY, new QTableWidgetItem("Heavy")); ui->adsbData->setItem(row, ADSB_COL_STATUS, new QTableWidgetItem("No emergency")); + ui->adsbData->setItem(row, ADSB_COL_SQUAWK, new QTableWidgetItem("Squawk")); ui->adsbData->setItem(row, ADSB_COL_REGISTRATION, new QTableWidgetItem("G-12345")); ui->adsbData->setItem(row, ADSB_COL_COUNTRY, new QTableWidgetItem("Country")); ui->adsbData->setItem(row, ADSB_COL_REGISTERED, new QTableWidgetItem("Registered")); @@ -1897,6 +1915,7 @@ void ADSBDemodGUI::resizeTable() ui->adsbData->removeCellWidget(row, ADSB_COL_LONGITUDE); ui->adsbData->removeCellWidget(row, ADSB_COL_CATEGORY); ui->adsbData->removeCellWidget(row, ADSB_COL_STATUS); + ui->adsbData->removeCellWidget(row, ADSB_COL_SQUAWK); ui->adsbData->removeCellWidget(row, ADSB_COL_REGISTRATION); ui->adsbData->removeCellWidget(row, ADSB_COL_COUNTRY); ui->adsbData->removeCellWidget(row, ADSB_COL_REGISTERED); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index d00c6c961..e62d51334 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -91,6 +91,7 @@ struct Aircraft { int m_verticalRate; // Vertical climb rate in ft/min QString m_emitterCategory; // Aircraft type QString m_status; // Aircraft status + int m_squawk; // Mode-A code Real m_range; // Distance from station to aircraft Real m_azimuth; // Azimuth from station to aircraft Real m_elevation; // Elevation from station to aicraft; @@ -138,6 +139,7 @@ struct Aircraft { QTableWidgetItem *m_azElItem; QTableWidgetItem *m_emitterCategoryItem; QTableWidgetItem *m_statusItem; + QTableWidgetItem *m_squawkItem; QTableWidgetItem *m_registrationItem; QTableWidgetItem *m_countryItem; QTableWidgetItem *m_registeredItem; @@ -193,6 +195,7 @@ struct Aircraft { m_longitudeItem = new QTableWidgetItem(); m_emitterCategoryItem = new QTableWidgetItem(); m_statusItem = new QTableWidgetItem(); + m_squawkItem = new QTableWidgetItem(); m_registrationItem = new QTableWidgetItem(); m_countryItem = new QTableWidgetItem(); m_registeredItem = new QTableWidgetItem(); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.ui b/plugins/channelrx/demodadsb/adsbdemodgui.ui index 582c8ba0b..d02baadfc 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.ui +++ b/plugins/channelrx/demodadsb/adsbdemodgui.ui @@ -693,6 +693,14 @@ Aircraft emergency status + + + Squawk + + + Mode-A transponder code + + Reg @@ -844,6 +852,11 @@ QWidget
QtQuickWidgets/QQuickWidget
+ + ButtonSwitch + QToolButton +
gui/buttonswitch.h
+
RollupWidget QWidget @@ -862,11 +875,6 @@
gui/valuedialz.h
1
- - ButtonSwitch - QToolButton -
gui/buttonswitch.h
-
deltaFrequency diff --git a/plugins/channelrx/demodadsb/readme.md b/plugins/channelrx/demodadsb/readme.md index 34cfecd82..faedb3e33 100644 --- a/plugins/channelrx/demodadsb/readme.md +++ b/plugins/channelrx/demodadsb/readme.md @@ -109,6 +109,7 @@ The table displays the decoded ADS-B data for each aircraft along side data avai * Longitude - Horizontal position coordinate, in decimal degrees. (ADS-B) * Category - The vehicle category, such as Light, Large, Heavy or Rotorcraft. (ADS-B) * Status - The status of the flight, including if there is an emergency. (ADS-B) +* Squawk - The squawk code (Mode-A transponder code). (ADS-B) * Registration - The registration number of the aircraft. (DB) * Country - The flag of the country the aircraft is registered in. (DB) * Registered - The date when the aircraft was registered. (DB) From 51bf8a6b21786a2b89b26a66305c36e479b6b105 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 10 Nov 2020 13:40:57 +0000 Subject: [PATCH 02/10] Add Az/El and distance to airport information box. Use km rather than nm for distance to airport calculation. Require double click to set ATC freqeuncy. Allow airport to be set as target, by double clicking Az/El in airport info box. --- .../demodadsb/adsbdemoddisplaydialog.ui | 4 +- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 36 +++++++++++---- plugins/channelrx/demodadsb/adsbdemodgui.h | 18 ++++++-- .../channelrx/demodadsb/adsbdemodsettings.h | 2 +- plugins/channelrx/demodadsb/map/map.qml | 12 +++-- plugins/channelrx/demodadsb/readme.md | 45 ++++++++++--------- 6 files changed, 78 insertions(+), 39 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui index 128192f74..1f91fc2da 100644 --- a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui +++ b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui @@ -89,14 +89,14 @@ - Airport display range (nm) + Airport display distance (km) - Displays airports within the specified range in nautical miles from My Position + Displays airports within the specified distance in kilometres from My Position 20000 diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index d62ee3e41..07cc002c7 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -432,8 +432,12 @@ bool AirportModel::setData(const QModelIndex &index, const QVariant& value, int int idx = value.toInt(); if ((idx >= 0) && (idx < m_airports[row]->m_frequencies.size())) m_gui->setFrequency(m_airports[row]->m_frequencies[idx]->m_frequency * 1000000); - else - qDebug() << "AirportModel::setData unexpected idx " << idx << " frequencies.size() " << m_airports[row]->m_frequencies.size(); + else if (idx == m_airports[row]->m_frequencies.size()) + { + // Set airport as target + m_gui->target(m_azimuth[row], m_elevation[row]); + emit dataChanged(index, index); + } return true; } return true; @@ -1456,15 +1460,18 @@ void ADSBDemodGUI::updateAirports() { m_airportModel.removeAllAirports(); QHash::iterator i = m_airportInfo->begin(); + AzEl azEl = m_azEl; + while (i != m_airportInfo->end()) { AirportInformation *airportInfo = i.value(); - // Calculate range to airport from My Position - One degree = 60 nautical miles - float latDiff = std::fabs(airportInfo->m_latitude - m_azEl.getLocationSpherical().m_latitude) * 60.0f; - float longDiff = std::fabs(airportInfo->m_longitude - m_azEl.getLocationSpherical().m_longitude) * 60.0f; - float range = sqrt(latDiff*latDiff+longDiff*longDiff); + + // Calculate distance and az/el to airport from My Position + azEl.setTarget(airportInfo->m_latitude, airportInfo->m_longitude, feetToMetres(airportInfo->m_elevation)); + azEl.calculate(); + // Only display airport if in range - if (range <= m_settings.m_airportRange) + if (azEl.getDistance() <= m_settings.m_airportRange*1000.0f) { // Only display the airport if it's large enough if (airportInfo->m_type >= m_settings.m_airportMinimumSize) @@ -1472,7 +1479,7 @@ void ADSBDemodGUI::updateAirports() // Only display heliports if enabled if (m_settings.m_displayHeliports || (airportInfo->m_type != ADSBDemodSettings::AirportType::Heliport)) { - m_airportModel.addAirport(airportInfo); + m_airportModel.addAirport(airportInfo, azEl.getAzimuth(), azEl.getElevation(), azEl.getDistance()); } } } @@ -1484,6 +1491,19 @@ void ADSBDemodGUI::updateAirports() m_currentDisplayHeliports = m_settings.m_displayHeliports; } +// Set a static target, such as an airport +void ADSBDemodGUI::target(float az, float el) +{ + if (m_trackAircraft) + { + // Restore colour of current target + m_trackAircraft->m_isTarget = false; + m_aircraftModel.aircraftUpdated(m_trackAircraft); + m_trackAircraft = nullptr; + } + m_adsbDemod->setTarget(az, el); +} + void ADSBDemodGUI::targetAircraft(Aircraft *aircraft) { if (aircraft != m_trackAircraft) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index e62d51334..99d210c76 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -324,16 +324,18 @@ public: { } - Q_INVOKABLE void addAirport(AirportInformation *airport) { + Q_INVOKABLE void addAirport(AirportInformation *airport, float az, float el, float distance) { QString text; int rows; beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_airports.append(airport); - airportFreq(airport, text, rows); + airportFreq(airport, az, el, distance, text, rows); m_airportDataFreq.append(text); m_airportDataFreqRows.append(rows); m_showFreq.append(false); + m_azimuth.append(az); + m_elevation.append(el); endInsertRows(); } @@ -346,6 +348,8 @@ public: m_airportDataFreq.removeAt(row); m_airportDataFreqRows.removeAt(row); m_showFreq.removeAt(row); + m_azimuth.removeAt(row); + m_elevation.removeAt(row); endRemoveRows(); } } @@ -356,6 +360,8 @@ public: m_airportDataFreq.clear(); m_airportDataFreqRows.clear(); m_showFreq.clear(); + m_azimuth.clear(); + m_elevation.clear(); endRemoveRows(); } @@ -372,7 +378,7 @@ public: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; } - void airportFreq(AirportInformation *airport, QString& text, int& rows) { + void airportFreq(AirportInformation *airport, float az, float el, float distance, QString& text, int& rows) { // Create the text to go in the bubble next to the airport // Display name and frequencies QStringList list; @@ -385,6 +391,9 @@ public: list.append(QString("%1: %2 MHz").arg(frequencyInfo->m_type).arg(frequencyInfo->m_frequency)); rows++; } + list.append(QString("Az/El: %1/%2").arg((int)std::round(az)).arg((int)std::round(el))); + list.append(QString("Distance: %1 km").arg(distance/1000.0f, 0, 'f', 1)); + rows += 2; text = list.join("\n"); } @@ -415,6 +424,8 @@ private: QList m_airportDataFreq; QList m_airportDataFreqRows; QList m_showFreq; + QList m_azimuth; + QList m_elevation; }; class ADSBDemodGUI : public ChannelGUI { @@ -430,6 +441,7 @@ public: virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } void highlightAircraft(Aircraft *aircraft); void targetAircraft(Aircraft *aircraft); + void target(float az, float el); bool setFrequency(float frequency); bool useSIUints() { return m_settings.m_siUnits; } diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.h b/plugins/channelrx/demodadsb/adsbdemodsettings.h index 064e46d21..3aeb13c89 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.h +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.h @@ -57,7 +57,7 @@ struct ADSBDemodSettings Serializable *m_channelMarker; - float m_airportRange; //!< How far away should we display airports (nm) + float m_airportRange; //!< How far away should we display airports (km) enum AirportType { Small, Medium, diff --git a/plugins/channelrx/demodadsb/map/map.qml b/plugins/channelrx/demodadsb/map/map.qml index 7df851993..b64fd2024 100644 --- a/plugins/channelrx/demodadsb/map/map.qml +++ b/plugins/channelrx/demodadsb/map/map.qml @@ -161,11 +161,17 @@ Item { var freqIdx = Math.floor((mouse.y-5)/((height-10)/airportDataRows)) if (freqIdx == 0) { showFreq = false - } else { - selectedFreq = freqIdx - 1 } } else { - showFreq = true + showFreq = true + } + } + onDoubleClicked: (mouse) => { + if (showFreq) { + var freqIdx = Math.floor((mouse.y-5)/((height-10)/airportDataRows)) + if (freqIdx != 0) { + selectedFreq = freqIdx - 1 + } } } } diff --git a/plugins/channelrx/demodadsb/readme.md b/plugins/channelrx/demodadsb/readme.md index faedb3e33..ce04ea0c4 100644 --- a/plugins/channelrx/demodadsb/readme.md +++ b/plugins/channelrx/demodadsb/readme.md @@ -61,7 +61,7 @@ Clicking the Display Settings button will open the Display Settings dialog, whic * The units for altitude, speed and vertical climb rate. These can be either ft (feet), kn (knots) and ft/min (feet per minute), or m (metres), kph (kilometers per hour) and m/s (metres per second). * The minimum size airport that will be displayed on the map: small, medium or large. Use small to display GA airfields, medium for regional airports and large for international airports. * Whether or not to display heliports. -* The range (in nautical miles) from My Position at which airports will be displayed on the map. +* The distance (in kilometres), from the location set under Preferences > My Position, at which airports will be displayed on the map. * The timeout, in seconds, after which an aircraft will be removed from the table and map, if an ADS-B frame has not been received from it. * The font used for the table. @@ -99,18 +99,18 @@ The table displays the decoded ADS-B data for each aircraft along side data avai * Flight No. - Airline flight number or callsign. (ADS-B) * Aircraft - The aircraft model. (DB) * Airline - The logo of the operator of the aircraft (or owner if no operator known). (DB) -* Altitude - Altitude in feet or metres. (ADS-B) -* Speed - Speed (either ground speed, indicated airspeed, or true airspeed) in knots or kph. (ADS-B) -* Heading - The direction the aircraft is heading, in degrees. (ADS-B) -* VR - The vertical climb rate (or descent rate if negative) in feet/minute or m/s. (ADS-B) -* Range - The range (distance) to the aircraft from the receiving antenna in kilometres. The location of the receiving antenna is set under the Preferences > My Position menu. +* Altitude (Alt) - Altitude in feet or metres. (ADS-B) +* Speed (Spd) - Speed (either ground speed, indicated airspeed, or true airspeed) in knots or kph. (ADS-B) +* Heading (Hd) - The direction the aircraft is heading, in degrees. (ADS-B) +* Vertical rate (VR) - The vertical climb rate (or descent rate if negative) in feet/minute or m/s. (ADS-B) +* Distance (D) - The distance to the aircraft from the receiving antenna in kilometres. The location of the receiving antenna is set under the Preferences > My Position menu. * Az/El - The azimuth and elevation angles to the aircraft from the receiving antenna in degrees. These values can be sent to a rotator controller Feature plugin to track the aircraft. -* Latitude - Vertical position coordinate, in decimal degrees. (ADS-B) -* Longitude - Horizontal position coordinate, in decimal degrees. (ADS-B) -* Category - The vehicle category, such as Light, Large, Heavy or Rotorcraft. (ADS-B) +* Latitude (Lat) - Vertical position coordinate, in decimal degrees. (ADS-B) +* Longitude (Lon) - Horizontal position coordinate, in decimal degrees. (ADS-B) +* Category (Cat) - The vehicle category, such as Light, Large, Heavy or Rotorcraft. (ADS-B) * Status - The status of the flight, including if there is an emergency. (ADS-B) * Squawk - The squawk code (Mode-A transponder code). (ADS-B) -* Registration - The registration number of the aircraft. (DB) +* Registration (Reg) - The registration number of the aircraft. (DB) * Country - The flag of the country the aircraft is registered in. (DB) * Registered - The date when the aircraft was registered. (DB) * Manufacturer - The manufacturer of the aircraft. (DB) @@ -122,14 +122,14 @@ The table displays the decoded ADS-B data for each aircraft along side data avai If an ADS-B frame has not been received from an aircraft for 60 seconds, the aircraft is removed from the table and map. This timeout can be adjusted in the Display Settings dialog. -Single clicking in a cell will highlight the row and the corresponding aircraft information box on the map will be coloured orange, rather than blue. -Right clicking on the header will open a menu allowing you to select which columns are visible. -To reorder the columns, left click and drag left or right a column header. -Left click on a header to sort the table by the data in that column. -Double clicking in an ICAO ID cell will open a Web browser and search for the corresponding aircraft on https://www.planespotters.net/ -Double clicking in an Flight No cell will open a Web browser and search for the corresponding flight on https://www.flightradar24.com/ -Double clicking in an Az/El cell will set the aircraft as the active target. The azimuth and elevation to the aicraft will be sent to a rotator controller plugin. The aircraft information box will be coloured green, rather than blue, on the map. -Double clicking on any other cell in the table will centre the map on the corresponding aircraft. +* Single clicking in a cell will highlight the row and the corresponding aircraft information box on the map will be coloured orange, rather than blue. +* Right clicking on the header will open a menu allowing you to select which columns are visible. +* To reorder the columns, left click and drag left or right a column header. +* Left click on a header to sort the table by the data in that column. +* Double clicking in an ICAO ID cell will open a Web browser and search for the corresponding aircraft on https://www.planespotters.net/ +* Double clicking in an Flight No cell will open a Web browser and search for the corresponding flight on https://www.flightradar24.com/ +* Double clicking in an Az/El cell will set the aircraft as the active target. The azimuth and elevation to the aicraft will be sent to a rotator controller plugin. The aircraft information box will be coloured green, rather than blue, on the map. +* Double clicking on any other cell in the table will centre the map on the corresponding aircraft.

Map

@@ -141,10 +141,11 @@ The initial antenna location is placed according to My Position set under the Pr Aircraft are only placed upon the map when a position can be calculated, which can require several frames to be received. -To pan around the map, click the left mouse button and drag. To zoom in or out, use the mouse scroll wheel. -Left clicking on an aicraft will highlight the corresponding row in the table for the aircraft and the information box on the map will be coloured orange, rather than blue. -Left clicking the information box next to an aircraft will reveal more information. If can be closed by clicking it again. -Left clicking the information box next to an airport will reveal ATC frequencies for the airport (if the OurAirports database has been downloaded.). This information box can be closed by left clicking on the airport identifier. Left clicking on one of the listed frequencies, will set it as the centre frequency on the selected SDRangel device set. +* To pan around the map, click the left mouse button and drag. To zoom in or out, use the mouse scroll wheel. +* Left clicking on an aicraft will highlight the corresponding row in the table for the aircraft and the information box on the map will be coloured orange, rather than blue. +* Double clicking on an aircraft will set it as the active target and the information box will be coloured green. +* Left clicking the information box next to an aircraft will reveal more information. It can be closed by clicking it again. +* Left clicking the information box next to an airport will reveal ATC frequencies for the airport (if the OurAirports database has been downloaded.). This information box can be closed by left clicking on the airport identifier. Double clicking on one of the listed frequencies, will set it as the centre frequency on the selected SDRangel device set (15). The Az/El row gives the azimuth and elevation of the airport from the location set under Preferences > My Position. Double clicking on this row will set the airport as the active target.

Attribution

From 6aa294384993423d09c4755d0557cd76785cfa9f Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 10 Nov 2020 14:07:15 +0000 Subject: [PATCH 03/10] Confirm redownload of files if less than 100 days old --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 73 +++++++++++++++----- plugins/channelrx/demodadsb/adsbdemodgui.h | 2 + 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index 07cc002c7..f19599682 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "ui_adsbdemodgui.h" @@ -1215,14 +1216,18 @@ void ADSBDemodGUI::on_getOSNDB_clicked(bool checked) // Don't try to download while already in progress if (m_progressDialog == nullptr) { - // Download Opensky network database to a file - QUrl dbURL(QString(OSNDB_URL)); - m_progressDialog = new QProgressDialog(this); - m_progressDialog->setAttribute(Qt::WA_DeleteOnClose); - m_progressDialog->setCancelButton(nullptr); - m_progressDialog->setLabelText(QString("Downloading %1.").arg(OSNDB_URL)); - QNetworkReply *reply = m_dlm.download(dbURL, getOSNDBFilename()); - connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64))); + QString osnDBFilename = getOSNDBFilename(); + if (confirmDownload(osnDBFilename)) + { + // Download Opensky network database to a file + QUrl dbURL(QString(OSNDB_URL)); + m_progressDialog = new QProgressDialog(this); + m_progressDialog->setAttribute(Qt::WA_DeleteOnClose); + m_progressDialog->setCancelButton(nullptr); + m_progressDialog->setLabelText(QString("Downloading %1.").arg(OSNDB_URL)); + QNetworkReply *reply = m_dlm.download(dbURL, osnDBFilename); + connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64))); + } } } @@ -1231,14 +1236,18 @@ void ADSBDemodGUI::on_getAirportDB_clicked(bool checked) // Don't try to download while already in progress if (m_progressDialog == nullptr) { - // Download Opensky network database to a file - QUrl dbURL(QString(AIRPORTS_URL)); - m_progressDialog = new QProgressDialog(this); - m_progressDialog->setAttribute(Qt::WA_DeleteOnClose); - m_progressDialog->setCancelButton(nullptr); - m_progressDialog->setLabelText(QString("Downloading %1.").arg(AIRPORTS_URL)); - QNetworkReply *reply = m_dlm.download(dbURL, getAirportDBFilename()); - connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64))); + QString airportDBFile = getAirportDBFilename(); + if (confirmDownload(airportDBFile)) + { + // Download Opensky network database to a file + QUrl dbURL(QString(AIRPORTS_URL)); + m_progressDialog = new QProgressDialog(this); + m_progressDialog->setAttribute(Qt::WA_DeleteOnClose); + m_progressDialog->setCancelButton(nullptr); + m_progressDialog->setLabelText(QString("Downloading %1.").arg(AIRPORTS_URL)); + QNetworkReply *reply = m_dlm.download(dbURL, airportDBFile); + connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64))); + } } } @@ -1276,6 +1285,38 @@ QString ADSBDemodGUI::getFastDBFilename() return getDataDir() + "/aircraftDatabaseFast.csv"; } +qint64 ADSBDemodGUI::fileAgeInDays(QString filename) +{ + QFile file(filename); + if (file.exists()) + { + QDateTime modified = file.fileTime(QFileDevice::FileModificationTime); + if (modified.isValid()) + return modified.daysTo(QDateTime::currentDateTime()); + else + return -1; + } + return -1; +} + +bool ADSBDemodGUI::confirmDownload(QString filename) +{ + qint64 age = fileAgeInDays(filename); + if ((age == -1) || (age > 100)) + return true; + else + { + QMessageBox::StandardButton reply; + if (age == 0) + reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded today. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No); + else if (age == 1) + reply = QMessageBox::question(this, "Confirm download", "This file was last downloaded yesterday. Are you sure you wish to redownload it?", QMessageBox::Yes|QMessageBox::No); + else + reply = QMessageBox::question(this, "Confirm download", QString("This file was last downloaded %1 days ago. Are you sure you wish to redownload this file?").arg(age), QMessageBox::Yes|QMessageBox::No); + return reply == QMessageBox::Yes; + } +} + bool ADSBDemodGUI::readOSNDB(const QString& filename) { m_aircraftInfo = AircraftInformation::readOSNDB(filename); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index 99d210c76..9f80b833b 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -508,6 +508,8 @@ private: QString getAirportFrequenciesDBFilename(); QString getOSNDBFilename(); QString getFastDBFilename(); + qint64 ADSBDemodGUI::fileAgeInDays(QString filename); + bool ADSBDemodGUI::confirmDownload(QString filename); void readAirportDB(const QString& filename); void readAirportFrequenciesDB(const QString& filename); bool readOSNDB(const QString& filename); From 27c4802a7fde872cad2e94492469f335d01985a8 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Tue, 10 Nov 2020 14:27:42 +0000 Subject: [PATCH 04/10] Add option to automatically resize columns after an aircraft is added to the table --- .../demodadsb/adsbdemoddisplaydialog.cpp | 9 +- .../demodadsb/adsbdemoddisplaydialog.h | 5 +- .../demodadsb/adsbdemoddisplaydialog.ui | 176 ++++++++++-------- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 7 +- .../channelrx/demodadsb/adsbdemodsettings.cpp | 3 + .../channelrx/demodadsb/adsbdemodsettings.h | 1 + plugins/channelrx/demodadsb/readme.md | 2 + 7 files changed, 116 insertions(+), 87 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.cpp b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.cpp index b43a13c53..2bad39b47 100644 --- a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.cpp +++ b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.cpp @@ -20,9 +20,10 @@ #include "adsbdemoddisplaydialog.h" -ADSBDemodDisplayDialog::ADSBDemodDisplayDialog -(int removeTimeout, float airportRange, ADSBDemodSettings::AirportType airportMinimumSize, - bool displayHeliports, bool siUnits, QString fontName, int fontSize, bool displayDemodStats, QWidget* parent) : +ADSBDemodDisplayDialog::ADSBDemodDisplayDialog( + int removeTimeout, float airportRange, ADSBDemodSettings::AirportType airportMinimumSize, + bool displayHeliports, bool siUnits, QString fontName, int fontSize, bool displayDemodStats, + bool autoResizeTableColumns, QWidget* parent) : QDialog(parent), ui(new Ui::ADSBDemodDisplayDialog), m_fontName(fontName), @@ -35,6 +36,7 @@ ADSBDemodDisplayDialog::ADSBDemodDisplayDialog ui->heliports->setChecked(displayHeliports); ui->units->setCurrentIndex((int)siUnits); ui->displayStats->setChecked(displayDemodStats); + ui->autoResizeTableColumns->setChecked(autoResizeTableColumns); } ADSBDemodDisplayDialog::~ADSBDemodDisplayDialog() @@ -50,6 +52,7 @@ void ADSBDemodDisplayDialog::accept() m_displayHeliports = ui->heliports->isChecked(); m_siUnits = ui->units->currentIndex() == 0 ? false : true; m_displayDemodStats = ui->displayStats->isChecked(); + m_autoResizeTableColumns = ui->autoResizeTableColumns->isChecked(); QDialog::accept(); } diff --git a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.h b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.h index a8c3099c7..6ee9fb9c9 100644 --- a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.h +++ b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.h @@ -26,8 +26,8 @@ class ADSBDemodDisplayDialog : public QDialog { public: explicit ADSBDemodDisplayDialog(int removeTimeout, float airportRange, ADSBDemodSettings::AirportType airportMinimumSize, - bool displayHeliports, bool siUnits, QString fontName, int fontSize, bool displayDemodStats -, QWidget* parent = 0); + bool displayHeliports, bool siUnits, QString fontName, int fontSize, bool displayDemodStats, + bool autoResizeTableColumns, QWidget* parent = 0); ~ADSBDemodDisplayDialog(); int m_removeTimeout; @@ -38,6 +38,7 @@ public: QString m_fontName; int m_fontSize; bool m_displayDemodStats; + bool m_autoResizeTableColumns; private slots: void accept(); diff --git a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui index 1f91fc2da..db428c060 100644 --- a/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui +++ b/plugins/channelrx/demodadsb/adsbdemoddisplaydialog.ui @@ -7,7 +7,7 @@ 0 0 351 - 275 + 289
@@ -22,29 +22,52 @@ - - - + + + + + Select a font for the table + - Units + Select... - - - - The units to use for altitude, speed and climb rate + + + + Aircraft timeout (s) + + + + + + + Displays airports within the specified distance in kilometres from My Position + + + 20000 + + + + + + + When checked, heliports are displayed on the map + + + Display heliports + + + + + + + How long in seconds after not receving any frames will an aircraft be removed from the table and map + + + 1000000 - - - ft, kn, ft/min - - - - - m, kph, m/s - - @@ -54,6 +77,43 @@ + + + + Airport display distance (km) + + + + + + + Table font + + + + + + + + 0 + 0 + + + + Display demodulator statistics + + + Display demodulator statistics + + + + + + + Units + + + @@ -76,75 +136,31 @@ - - + + - When checked, heliports are displayed on the map + Resize the columns in the table after an aircraft is added to it - Display heliports + Resize columns after adding aircraft - - - - Airport display distance (km) - - - - - + + - Displays airports within the specified distance in kilometres from My Position - - - 20000 - - - - - - - Aircraft timeout (s) - - - - - - - How long in seconds after not receving any frames will an aircraft be removed from the table and map - - - 1000000 - - - - - - - Table font - - - - - - - Select a font for the table - - - Select... - - - - - - - Display demodulator statistics - - - Display demodulator statistics + The units to use for altitude, speed and climb rate + + + ft, kn, ft/min + + + + + m, kph, m/s + + diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index f19599682..7f2c43c44 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -703,6 +703,8 @@ void ADSBDemodGUI::handleADSB( } } } + if (m_settings.m_autoResizeTableColumns) + ui->adsbData->resizeColumnsToContents(); ui->adsbData->setSortingEnabled(true); } aircraft->m_time = dateTime; @@ -1604,7 +1606,7 @@ void ADSBDemodGUI::on_displaySettings_clicked(bool checked) ADSBDemodDisplayDialog dialog(m_settings.m_removeTimeout, m_settings.m_airportRange, m_settings.m_airportMinimumSize, m_settings.m_displayHeliports, m_settings.m_siUnits, m_settings.m_tableFontName, m_settings.m_tableFontSize, - m_settings.m_displayDemodStats); + m_settings.m_displayDemodStats, m_settings.m_autoResizeTableColumns); if (dialog.exec() == QDialog::Accepted) { bool unitsChanged = m_settings.m_siUnits != dialog.m_siUnits; @@ -1617,6 +1619,7 @@ void ADSBDemodGUI::on_displaySettings_clicked(bool checked) m_settings.m_tableFontName = dialog.m_fontName; m_settings.m_tableFontSize = dialog.m_fontSize; m_settings.m_displayDemodStats = dialog.m_displayDemodStats; + m_settings.m_autoResizeTableColumns = dialog.m_autoResizeTableColumns; if (unitsChanged) m_aircraftModel.allAircraftUpdated(); @@ -1947,7 +1950,7 @@ void ADSBDemodGUI::resizeTable() ui->adsbData->setItem(row, ADSB_COL_RANGE, new QTableWidgetItem("D (km)")); ui->adsbData->setItem(row, ADSB_COL_AZEL, new QTableWidgetItem("Az/El (o)")); ui->adsbData->setItem(row, ADSB_COL_LATITUDE, new QTableWidgetItem("-90.00000")); - ui->adsbData->setItem(row, ADSB_COL_LONGITUDE, new QTableWidgetItem("-180.00000")); + ui->adsbData->setItem(row, ADSB_COL_LONGITUDE, new QTableWidgetItem("-180.000000")); ui->adsbData->setItem(row, ADSB_COL_CATEGORY, new QTableWidgetItem("Heavy")); ui->adsbData->setItem(row, ADSB_COL_STATUS, new QTableWidgetItem("No emergency")); ui->adsbData->setItem(row, ADSB_COL_SQUAWK, new QTableWidgetItem("Squawk")); diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.cpp b/plugins/channelrx/demodadsb/adsbdemodsettings.cpp index a41153b89..464db1aa7 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.cpp @@ -60,6 +60,7 @@ void ADSBDemodSettings::resetToDefaults() m_correlateFullPreamble = true; m_demodModeS = false; m_deviceIndex = -1; + m_autoResizeTableColumns = false; for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) { m_columnIndexes[i] = i; @@ -103,6 +104,7 @@ QByteArray ADSBDemodSettings::serialize() const s.writeBool(27, m_displayDemodStats); s.writeBool(28, m_correlateFullPreamble); s.writeBool(29, m_demodModeS); + s.writeBool(30, m_autoResizeTableColumns); for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) s.writeS32(100 + i, m_columnIndexes[i]); @@ -179,6 +181,7 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data) d.readBool(27, &m_displayDemodStats, false); d.readBool(28, &m_correlateFullPreamble, true); d.readBool(29, &m_demodModeS, false); + d.readBool(30, &m_autoResizeTableColumns, false); for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) d.readS32(100 + i, &m_columnIndexes[i], i); diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.h b/plugins/channelrx/demodadsb/adsbdemodsettings.h index 3aeb13c89..c8d1d621d 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.h +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.h @@ -73,6 +73,7 @@ struct ADSBDemodSettings bool m_correlateFullPreamble; bool m_demodModeS; //!< Demodulate all Mode-S frames, not just ADS-B int m_deviceIndex; //!< Device to set to ATC frequencies + bool m_autoResizeTableColumns; ADSBDemodSettings(); void resetToDefaults(); diff --git a/plugins/channelrx/demodadsb/readme.md b/plugins/channelrx/demodadsb/readme.md index ce04ea0c4..364e32fbb 100644 --- a/plugins/channelrx/demodadsb/readme.md +++ b/plugins/channelrx/demodadsb/readme.md @@ -64,6 +64,8 @@ Clicking the Display Settings button will open the Display Settings dialog, whic * The distance (in kilometres), from the location set under Preferences > My Position, at which airports will be displayed on the map. * The timeout, in seconds, after which an aircraft will be removed from the table and map, if an ADS-B frame has not been received from it. * The font used for the table. +* Whether demodulator statistics are displayed (primarily an option for developers). +* Whether the columns in the table are automatically resized after an aircraft is added to it. If unchecked, columns can be resized manually and should be saved with presets.

12: Display Flight Paths

From f823741b34d3ed6ed04467dd730566d507516931 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 11 Nov 2020 09:19:37 +0000 Subject: [PATCH 05/10] Add decoding of surface position messages --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 111 ++++++++++++++++--- 1 file changed, 96 insertions(+), 15 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index 7f2c43c44..bd2d8ae33 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -763,23 +763,104 @@ void ADSBDemodGUI::handleADSB( aircraft->m_flight = QString(callsign); aircraft->m_flightItem->setText(aircraft->m_flight); } - else if ((tc >= 5) && (tc <= 8)) + else if (((tc >= 5) && (tc <= 18)) || ((tc >= 20) && (tc <= 22))) { - // Surface position - } - else if (((tc >= 9) && (tc <= 18)) || ((tc >= 20) && (tc <= 22))) - { - // Airbourne position (9-18 baro, 20-22 GNSS) - int ss = (data[4] >> 1) & 0x3; // Surveillance status - int nicsb = data[4] & 1; // NIC supplement-B - int alt = ((data[5] & 0xff) << 4) | ((data[6] >> 4) & 0xf); // Altitude - int n = ((alt >> 1) & 0x7f0) | (alt & 0xf); - int alt_ft = n * ((alt & 0x10) ? 25 : 100) - 1000; + if ((tc >= 5) && (tc <= 8)) + { + // Surface position - aircraft->m_altitude = alt_ft; - aircraft->m_altitudeValid = true; - // setData rather than setText so it sorts numerically - aircraft->m_altitudeItem->setData(Qt::DisplayRole, m_settings.m_siUnits ? feetToMetresInt(aircraft->m_altitude) : aircraft->m_altitude); + // Set altitude to 0, if we're on the surface + // Actual altitude may of course depend on airport elevation + aircraft->m_altitudeValid = true; + aircraft->m_altitudeItem->setData(Qt::DisplayRole, 0); + + int movement = ((data[4] & 0x7) << 4) | ((data[5] >> 4) & 0xf); + if (movement == 0) + { + // No information available + aircraft->m_speedValid = false; + aircraft->m_speedItem->setData(Qt::DisplayRole, ""); + } + else if (movement == 1) + { + // Aircraft stopped + aircraft->m_speedValid = true; + aircraft->m_speedItem->setData(Qt::DisplayRole, 0); + } + else if ((movement >= 2) && (movement <= 123)) + { + float base, step; // In knts + int adjust; + if ((movement >= 2) && (movement <= 8)) + { + base = 0.125f; + step = 0.125f; + adjust = 2; + } + else if ((movement >= 9) && (movement <= 12)) + { + base = 1.0f; + step = 0.25f; + adjust = 9; + } + else if ((movement >= 13) && (movement <= 38)) + { + base = 2.0f; + step = 0.5f; + adjust = 13; + } + else if ((movement >= 39) && (movement <= 93)) + { + base = 15.0f; + step = 1.0f; + adjust = 39; + } + else if ((movement >= 94) && (movement <= 108)) + { + base = 70.0f; + step = 2.0f; + adjust = 94; + } + else + { + base = 100.0f; + step = 5.0f; + adjust = 109; + } + float speed = base + (movement - adjust) * step; + aircraft->m_speedType = Aircraft::GS; + aircraft->m_speedValid = true; + aircraft->m_speedItem->setData(Qt::DisplayRole, m_settings.m_siUnits ? knotsToKPHInt(aircraft->m_speed) : (int)std::round(aircraft->m_speed)); + } + else if (movement == 124) + { + aircraft->m_speedValid = true; + aircraft->m_speedItem->setData(Qt::DisplayRole, m_settings.m_siUnits ? 324 : 175); // Actually greater than this + } + + int groundTrackStatus = (data[5] >> 3) & 1; + int groundTrackValue = ((data[5] & 0x7) << 4) | ((data[6] >> 4) & 0xf); + if (groundTrackStatus) + { + aircraft->m_heading = std::round((groundTrackValue * 360.0/128.0)); + aircraft->m_headingValid = true; + aircraft->m_headingItem->setData(Qt::DisplayRole, aircraft->m_heading); + } + } + else if (((tc >= 9) && (tc <= 18)) || ((tc >= 20) && (tc <= 22))) + { + // Airbourne position (9-18 baro, 20-22 GNSS) + int ss = (data[4] >> 1) & 0x3; // Surveillance status + int nicsb = data[4] & 1; // NIC supplement-B - Or single antenna flag + int alt = ((data[5] & 0xff) << 4) | ((data[6] >> 4) & 0xf); // Altitude + int n = ((alt >> 1) & 0x7f0) | (alt & 0xf); + int alt_ft = n * ((alt & 0x10) ? 25 : 100) - 1000; + + aircraft->m_altitude = alt_ft; + aircraft->m_altitudeValid = true; + // setData rather than setText so it sorts numerically + aircraft->m_altitudeItem->setData(Qt::DisplayRole, m_settings.m_siUnits ? feetToMetresInt(aircraft->m_altitude) : aircraft->m_altitude); + } int t = (data[6] >> 3) & 1; // Time synchronisation to UTC int f = (data[6] >> 2) & 1; // CPR odd/even frame - should alternate every 0.2s From 21956dc9d0318f02d89270c2e482ac0429d56f1e Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Nov 2020 08:40:12 +0000 Subject: [PATCH 06/10] Fix surface position calculation. Check latitude and local decode is in valid range. --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 130 ++++++++++++------- plugins/channelrx/demodadsb/adsbdemodgui.h | 1 + 2 files changed, 85 insertions(+), 46 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index bd2d8ae33..eee08a21c 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -474,6 +474,26 @@ void ADSBDemodGUI::updatePosition(Aircraft *aircraft) m_adsbDemod->setTarget(aircraft->m_azimuth, aircraft->m_elevation); } +// Called when we have lat & long from local decode and we need to check if it is in a valid range (<180nm/333km) +// or 1/4 of that for surface positions +bool ADSBDemodGUI::updateLocalPosition(Aircraft *aircraft, double latitude, double longitude, bool surfacePosition) +{ + // Calculate range to aircraft from station + m_azEl.setTarget(latitude, longitude, feetToMetres(aircraft->m_altitude)); + m_azEl.calculate(); + + // Don't use the full 333km, as there may be some error in station position + if (m_azEl.getDistance() < (surfacePosition ? 80000 : 320000)) + { + aircraft->m_latitude = latitude; + aircraft->m_longitude = longitude; + updatePosition(aircraft); + return true; + } + else + return false; +} + // Try to find an airline logo based on ICAO QIcon *ADSBDemodGUI::getAirlineIcon(const QString &operatorICAO) { @@ -727,6 +747,7 @@ void ADSBDemodGUI::handleADSB( m_correlationOnesAvg(correlationOnes); aircraft->m_rssiItem->setText(QString("%1") .arg(CalcDb::dbPower(m_correlationOnesAvg.instantAverage()), 3, 'f', 1)); + // ADS-B, non-transponder ADS-B or TIS-B rebroadcast of ADS-B (ADS-R) if ((df == 17) || ((df == 18) && ((ca == 0) || (ca == 1) || (ca == 6)))) { @@ -765,7 +786,8 @@ void ADSBDemodGUI::handleADSB( } else if (((tc >= 5) && (tc <= 18)) || ((tc >= 20) && (tc <= 22))) { - if ((tc >= 5) && (tc <= 8)) + bool surfacePosition = (tc >= 5) && (tc <= 8); + if (surfacePosition) { // Surface position @@ -879,7 +901,8 @@ void ADSBDemodGUI::handleADSB( // We also need to check that both frames aren't greater than 10s apart in time (C.2.6.7), otherwise position may be out by ~10deg // We could compare global + local methods to see if the positions are sensible if (aircraft->m_cprValid[0] && aircraft->m_cprValid[1] - && (std::abs(aircraft->m_cprTime[0].toSecsSinceEpoch() - aircraft->m_cprTime[1].toSecsSinceEpoch()) < 10)) + && (std::abs(aircraft->m_cprTime[0].toSecsSinceEpoch() - aircraft->m_cprTime[1].toSecsSinceEpoch()) < 10) + && !surfacePosition) { // Global decode using odd and even frames (C.2.6) @@ -891,84 +914,99 @@ void ADSBDemodGUI::handleADSB( int ni, m; int j = std::floor(59.0f*aircraft->m_cprLat[0] - 60.0f*aircraft->m_cprLat[1] + 0.5); - latEven = dLatEven * ((j % 60) + aircraft->m_cprLat[0]); + latEven = dLatEven * (modulus(j, 60) + aircraft->m_cprLat[0]); + // Southern hemisphere is in range 270-360, so adjust to -90-0 if (latEven >= 270.0f) latEven -= 360.0f; - else if (latEven <= -270.0f) - latEven += 360.0f; - latOdd = dLatOdd * ((j % 59) + aircraft->m_cprLat[1]); + latOdd = dLatOdd * (modulus(j, 59) + aircraft->m_cprLat[1]); if (latOdd >= 270.0f) latOdd -= 360.0f; - else if (latOdd <= -270.0f) - latOdd += 360.0f; if (aircraft->m_cprTime[0] >= aircraft->m_cprTime[1]) latitude = latEven; else latitude = latOdd; - - // Check if both frames in same latitude zone - int latEvenNL = cprNL(latEven); - int latOddNL = cprNL(latOdd); - if (latEvenNL == latOddNL) + if ((latitude <= 90.0) && (latitude >= -90.0)) { - // Calculate longitude - if (!f) + // Check if both frames in same latitude zone + int latEvenNL = cprNL(latEven); + int latOddNL = cprNL(latOdd); + if (latEvenNL == latOddNL) { - ni = cprN(latEven, 0); - m = std::floor(aircraft->m_cprLong[0] * (latEvenNL - 1) - aircraft->m_cprLong[1] * latEvenNL + 0.5f); - longitude = (360.0f/ni) * (modulus(m, ni) + aircraft->m_cprLong[0]); + // Calculate longitude + if (!f) + { + ni = cprN(latEven, 0); + m = std::floor(aircraft->m_cprLong[0] * (latEvenNL - 1) - aircraft->m_cprLong[1] * latEvenNL + 0.5f); + longitude = (360.0f/ni) * (modulus(m, ni) + aircraft->m_cprLong[0]); + } + else + { + ni = cprN(latOdd, 1); + m = std::floor(aircraft->m_cprLong[0] * (latOddNL - 1) - aircraft->m_cprLong[1] * latOddNL + 0.5f); + longitude = (360.0f/ni) * (modulus(m, ni) + aircraft->m_cprLong[1]); + } + if (longitude > 180.0f) + longitude -= 360.0f; + aircraft->m_latitude = latitude; + aircraft->m_latitudeItem->setData(Qt::DisplayRole, aircraft->m_latitude); + aircraft->m_longitude = longitude; + aircraft->m_longitudeItem->setData(Qt::DisplayRole, aircraft->m_longitude); + aircraft->m_coordinates.push_back(QVariant::fromValue(*new QGeoCoordinate(aircraft->m_latitude, aircraft->m_longitude, aircraft->m_altitude))); + updatePosition(aircraft); } - else - { - ni = cprN(latOdd, 1); - m = std::floor(aircraft->m_cprLong[0] * (latOddNL - 1) - aircraft->m_cprLong[1] * latOddNL + 0.5f); - longitude = (360.0f/ni) * (modulus(m, ni) + aircraft->m_cprLong[1]); - } - if (longitude > 180.0f) - longitude -= 360.0f; - aircraft->m_latitude = latitude; - aircraft->m_latitudeItem->setData(Qt::DisplayRole, aircraft->m_latitude); - aircraft->m_longitude = longitude; - aircraft->m_longitudeItem->setData(Qt::DisplayRole, aircraft->m_longitude); - aircraft->m_coordinates.push_back(QVariant::fromValue(*new QGeoCoordinate(aircraft->m_latitude, aircraft->m_longitude, aircraft->m_altitude))); - updatePosition(aircraft); + } + else + { + qDebug() << "ADSBDemodGUI::handleADSB: Invalid latitude " << latitude << " for " << hex << aircraft->m_icao + << " m_cprLat[0] " << aircraft->m_cprLat[0] + << " m_cprLat[1] " << aircraft->m_cprLat[1]; + aircraft->m_cprValid[0] = false; + aircraft->m_cprValid[1] = false; } } else { // Local decode using a single aircraft position + location of receiver - // Only valid if within 180nm (C.2.6.4) + // Only valid if airbourne within 180nm/333km (C.2.6.4) or 45nm for surface // Caclulate latitude - const double dLatEven = 360.0/60.0; - const double dLatOdd = 360.0/59.0; + const double maxDeg = surfacePosition ? 90.0 : 360.0; + const double dLatEven = maxDeg/60.0; + const double dLatOdd = maxDeg/59.0; double dLat = f ? dLatOdd : dLatEven; + double latitude, longitude; + int j = std::floor(m_azEl.getLocationSpherical().m_latitude/dLat) + std::floor(modulus(m_azEl.getLocationSpherical().m_latitude, dLat)/dLat - aircraft->m_cprLat[f] + 0.5); - aircraft->m_latitude = dLat * (j + aircraft->m_cprLat[f]); - aircraft->m_latitudeItem->setData(Qt::DisplayRole, aircraft->m_latitude); + latitude = dLat * (j + aircraft->m_cprLat[f]); // Caclulate longitude double dLong; - int latNL = cprNL(aircraft->m_latitude); + int latNL = cprNL(latitude); if (f == 0) { if (latNL > 0) - dLong = 360.0 / latNL; + dLong = maxDeg / latNL; else - dLong = 360.0; + dLong = maxDeg; } else { if ((latNL - 1) > 0) - dLong = 360.0 / (latNL - 1); + dLong = maxDeg / (latNL - 1); else - dLong = 360.0; + dLong = maxDeg; } int m = std::floor(m_azEl.getLocationSpherical().m_longitude/dLong) + std::floor(modulus(m_azEl.getLocationSpherical().m_longitude, dLong)/dLong - aircraft->m_cprLong[f] + 0.5); - aircraft->m_longitude = dLong * (m + aircraft->m_cprLong[f]); - aircraft->m_longitudeItem->setData(Qt::DisplayRole, aircraft->m_longitude); - aircraft->m_coordinates.push_back(QVariant::fromValue(*new QGeoCoordinate(aircraft->m_latitude, aircraft->m_longitude, aircraft->m_altitude))); - updatePosition(aircraft); + longitude = dLong * (m + aircraft->m_cprLong[f]); + + if (updateLocalPosition(aircraft, latitude, longitude, surfacePosition)) + { + aircraft->m_latitude = latitude; + aircraft->m_latitudeItem->setData(Qt::DisplayRole, aircraft->m_latitude); + aircraft->m_longitude = longitude; + aircraft->m_longitudeItem->setData(Qt::DisplayRole, aircraft->m_longitude); + aircraft->m_coordinates.push_back(QVariant::fromValue(*new QGeoCoordinate(aircraft->m_latitude, aircraft->m_longitude, aircraft->m_altitude))); + } } } else if (tc == 19) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index 9f80b833b..347003611 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -497,6 +497,7 @@ private: void displayStreamIndex(); bool handleMessage(const Message& message); void updatePosition(Aircraft *aircraft); + bool updateLocalPosition(Aircraft *aircraft, double latitude, double longitude, bool surfacePosition); void handleADSB( const QByteArray data, const QDateTime dateTime, From 9a3585a7568b1375ac6e2c59f65f3151f27bd0cb Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Nov 2020 13:25:49 +0000 Subject: [PATCH 07/10] Reduce interpolator taps to enable it to run in real-time. Should significantly improve PER for RTLSDR at 2.4MSa/s. Add developer controls to adjust interpolator settings. Fix tab-order in GUI. --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 27 ++++ plugins/channelrx/demodadsb/adsbdemodgui.h | 2 + plugins/channelrx/demodadsb/adsbdemodgui.ui | 116 +++++++++++++++++- .../channelrx/demodadsb/adsbdemodsettings.cpp | 6 + .../channelrx/demodadsb/adsbdemodsettings.h | 2 + plugins/channelrx/demodadsb/adsbdemodsink.cpp | 53 ++++---- 6 files changed, 180 insertions(+), 26 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index eee08a21c..9eae4e952 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -1214,6 +1214,21 @@ void ADSBDemodGUI::on_threshold_valueChanged(int value) applySettings(); } +void ADSBDemodGUI::on_phaseSteps_valueChanged(int value) +{ + ui->phaseStepsText->setText(QString("%1").arg(value)); + m_settings.m_interpolatorPhaseSteps = value; + applySettings(); +} + +void ADSBDemodGUI::on_tapsPerPhase_valueChanged(int value) +{ + Real tapsPerPhase = ((Real)value)/10.0f; + ui->tapsPerPhaseText->setText(QString("%1").arg(tapsPerPhase, 0, 'f', 1)); + m_settings.m_interpolatorTapsPerPhase = tapsPerPhase; + applySettings(); +} + void ADSBDemodGUI::on_feed_clicked(bool checked) { m_settings.m_feedEnabled = checked; @@ -1927,6 +1942,18 @@ void ADSBDemodGUI::displaySettings() ui->thresholdText->setText(QString("%1").arg(m_settings.m_correlationThreshold, 0, 'f', 1)); ui->threshold->setValue((int)(m_settings.m_correlationThreshold*10.0f)); + ui->phaseStepsText->setText(QString("%1").arg(m_settings.m_interpolatorPhaseSteps)); + ui->phaseSteps->setValue(m_settings.m_interpolatorPhaseSteps); + ui->tapsPerPhaseText->setText(QString("%1").arg(m_settings.m_interpolatorTapsPerPhase, 0, 'f', 1)); + ui->tapsPerPhase->setValue((int)(m_settings.m_interpolatorTapsPerPhase*10.0f)); + // Enable these controls only for developers + if (1) + { + ui->phaseStepsText->setVisible(false); + ui->phaseSteps->setVisible(false); + ui->tapsPerPhaseText->setVisible(false); + ui->tapsPerPhase->setVisible(false); + } ui->feed->setChecked(m_settings.m_feedEnabled); ui->flightPaths->setChecked(m_settings.m_flightPaths); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index 347003611..04e82c3a8 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -528,6 +528,8 @@ private slots: void on_deltaFrequency_changed(qint64 value); void on_rfBW_valueChanged(int value); void on_threshold_valueChanged(int value); + void on_phaseSteps_valueChanged(int value); + void on_tapsPerPhase_valueChanged(int value); void on_adsbData_cellClicked(int row, int column); void on_adsbData_cellDoubleClicked(int row, int column); void adsbData_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex); diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.ui b/plugins/channelrx/demodadsb/adsbdemodgui.ui index d02baadfc..95886ee4e 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.ui +++ b/plugins/channelrx/demodadsb/adsbdemodgui.ui @@ -6,7 +6,7 @@ 0 0 - 384 + 435 1046
@@ -36,7 +36,7 @@ 0 0 - 381 + 431 141
@@ -167,6 +167,13 @@ + + + + Qt::Vertical + + + @@ -203,10 +210,17 @@ + + + + Qt::Vertical + + + - RFBW + BW @@ -262,6 +276,85 @@ + + + + + 24 + 24 + + + + Interpolator phase steps + + + 1 + + + 16 + + + 1 + + + 16 + + + + + + + + 16 + 0 + + + + 12 + + + + + + + true + + + + 24 + 24 + + + + Interpolator taps per phase + + + 10 + + + 60 + + + 1 + + + 45 + + + + + + + + 16 + 0 + + + + 4.5 + + + @@ -547,7 +640,7 @@ 0 140 - 381 + 431 291 @@ -787,7 +880,7 @@ 10 450 - 361 + 421 581 @@ -879,8 +972,21 @@ deltaFrequency rfBW + phaseSteps + tapsPerPhase spb + demodModeS + correlateFullPreamble threshold + getOSNDB + getAirportDB + displaySettings + flightPaths + feed + devicesRefresh + device + adsbData + map diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.cpp b/plugins/channelrx/demodadsb/adsbdemodsettings.cpp index 464db1aa7..c8edf7997 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.cpp @@ -61,6 +61,8 @@ void ADSBDemodSettings::resetToDefaults() m_demodModeS = false; m_deviceIndex = -1; m_autoResizeTableColumns = false; + m_interpolatorPhaseSteps = 4; // Higher than these two values will struggle to run in real-time + m_interpolatorTapsPerPhase = 3.5f; // without gaining much improvement in PER for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) { m_columnIndexes[i] = i; @@ -105,6 +107,8 @@ QByteArray ADSBDemodSettings::serialize() const s.writeBool(28, m_correlateFullPreamble); s.writeBool(29, m_demodModeS); s.writeBool(30, m_autoResizeTableColumns); + s.writeS32(31, m_interpolatorPhaseSteps); + s.writeFloat(32, m_interpolatorTapsPerPhase); for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) s.writeS32(100 + i, m_columnIndexes[i]); @@ -182,6 +186,8 @@ bool ADSBDemodSettings::deserialize(const QByteArray& data) d.readBool(28, &m_correlateFullPreamble, true); d.readBool(29, &m_demodModeS, false); d.readBool(30, &m_autoResizeTableColumns, false); + d.readS32(31, &m_interpolatorPhaseSteps, 4); + d.readFloat(32, &m_interpolatorTapsPerPhase, 3.5f); for (int i = 0; i < ADSBDEMOD_COLUMNS; i++) d.readS32(100 + i, &m_columnIndexes[i], i); diff --git a/plugins/channelrx/demodadsb/adsbdemodsettings.h b/plugins/channelrx/demodadsb/adsbdemodsettings.h index c8d1d621d..081e5934d 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsettings.h +++ b/plugins/channelrx/demodadsb/adsbdemodsettings.h @@ -74,6 +74,8 @@ struct ADSBDemodSettings bool m_demodModeS; //!< Demodulate all Mode-S frames, not just ADS-B int m_deviceIndex; //!< Device to set to ATC frequencies bool m_autoResizeTableColumns; + int m_interpolatorPhaseSteps; + float m_interpolatorTapsPerPhase; ADSBDemodSettings(); void resetToDefaults(); diff --git a/plugins/channelrx/demodadsb/adsbdemodsink.cpp b/plugins/channelrx/demodadsb/adsbdemodsink.cpp index 80ee2a517..1983f82f4 100644 --- a/plugins/channelrx/demodadsb/adsbdemodsink.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodsink.cpp @@ -83,33 +83,41 @@ void ADSBDemodSink::feed(const SampleVector::const_iterator& begin, const Sample processOneSample(magsq); } } - else + else if (m_interpolatorDistance == 1.0f) // just apply offset { for (SampleVector::const_iterator it = begin; it != end; ++it) { Complex c(it->real(), it->imag()); Complex ci; c *= m_nco.nextIQ(); - - if (m_interpolatorDistance == 1.0f) + processOneSample(complexMagSq(c)); + } + } + else if (m_interpolatorDistance < 1.0f) // interpolate + { + for (SampleVector::const_iterator it = begin; it != end; ++it) + { + Complex c(it->real(), it->imag()); + Complex ci; + c *= m_nco.nextIQ(); + while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) { - processOneSample(complexMagSq(c)); + processOneSample(complexMagSq(ci)); + m_interpolatorDistanceRemain += m_interpolatorDistance; } - else if (m_interpolatorDistance < 1.0f) // interpolate + } + } + else // decimate + { + for (SampleVector::const_iterator it = begin; it != end; ++it) + { + Complex c(it->real(), it->imag()); + Complex ci; + c *= m_nco.nextIQ(); + if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) { - while (!m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) - { - processOneSample(complexMagSq(ci)); - m_interpolatorDistanceRemain += m_interpolatorDistance; - } - } - else // decimate - { - if (m_interpolator.decimate(&m_interpolatorDistanceRemain, c, &ci)) - { - processOneSample(complexMagSq(ci)); - m_interpolatorDistanceRemain += m_interpolatorDistance; - } + processOneSample(complexMagSq(ci)); + m_interpolatorDistanceRemain += m_interpolatorDistance; } } } @@ -228,7 +236,7 @@ void ADSBDemodSink::applyChannelSettings(int channelSampleRate, int channelFrequ if ((channelSampleRate != m_channelSampleRate) || force) { - m_interpolator.create(16, channelSampleRate, m_settings.m_rfBandwidth / 2.2); + m_interpolator.create(m_settings.m_interpolatorPhaseSteps, channelSampleRate, m_settings.m_rfBandwidth / 2.2, m_settings.m_interpolatorTapsPerPhase); m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) channelSampleRate / (Real) (ADS_B_BITS_PER_SECOND * m_settings.m_samplesPerBit); } @@ -249,9 +257,12 @@ void ADSBDemodSink::applySettings(const ADSBDemodSettings& settings, bool force) << " force: " << force; if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) - || (settings.m_samplesPerBit != m_settings.m_samplesPerBit) || force) + || (settings.m_samplesPerBit != m_settings.m_samplesPerBit) + || (settings.m_interpolatorPhaseSteps != m_settings.m_interpolatorPhaseSteps) + || (settings.m_interpolatorTapsPerPhase != m_settings.m_interpolatorTapsPerPhase) + || force) { - m_interpolator.create(16, m_channelSampleRate, settings.m_rfBandwidth / 2.2); + m_interpolator.create(m_settings.m_interpolatorPhaseSteps, m_channelSampleRate, settings.m_rfBandwidth / 2.2, m_settings.m_interpolatorTapsPerPhase); m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) m_channelSampleRate / (Real) (ADS_B_BITS_PER_SECOND * settings.m_samplesPerBit); } From 55e7b56ae9b13292d938f13b8aad92b2b39fb41c Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Nov 2020 13:31:01 +0000 Subject: [PATCH 08/10] Fix compiler warnings --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 2 +- plugins/channelrx/demodadsb/osndb.h | 1 - plugins/channelrx/demodadsb/ourairportsdb.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index 9eae4e952..e830382db 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -957,7 +957,7 @@ void ADSBDemodGUI::handleADSB( } else { - qDebug() << "ADSBDemodGUI::handleADSB: Invalid latitude " << latitude << " for " << hex << aircraft->m_icao + qDebug() << "ADSBDemodGUI::handleADSB: Invalid latitude " << latitude << " for " << Qt::hex << aircraft->m_icao << " m_cprLat[0] " << aircraft->m_cprLat[0] << " m_cprLat[1] " << aircraft->m_cprLat[1]; aircraft->m_cprValid[0] = false; diff --git a/plugins/channelrx/demodadsb/osndb.h b/plugins/channelrx/demodadsb/osndb.h index 263d475c0..766229be0 100644 --- a/plugins/channelrx/demodadsb/osndb.h +++ b/plugins/channelrx/demodadsb/osndb.h @@ -70,7 +70,6 @@ struct AircraftInformation { if ((file = fopen(utfFilename.constData(), "r")) != NULL) { char row[2048]; - int idx; if (fgets(row, sizeof(row), file)) { diff --git a/plugins/channelrx/demodadsb/ourairportsdb.h b/plugins/channelrx/demodadsb/ourairportsdb.h index ee16810f1..77956f485 100644 --- a/plugins/channelrx/demodadsb/ourairportsdb.h +++ b/plugins/channelrx/demodadsb/ourairportsdb.h @@ -82,7 +82,6 @@ struct AirportInformation { if ((file = fopen(utfFilename.constData(), "r")) != NULL) { char row[2048]; - int idx; if (fgets(row, sizeof(row), file)) { From 23c625548269a60fa99cd2f9893837cf23d00b09 Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Nov 2020 13:49:34 +0000 Subject: [PATCH 09/10] Fix syntax error for GCC --- plugins/channelrx/demodadsb/adsbdemodgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.h b/plugins/channelrx/demodadsb/adsbdemodgui.h index 04e82c3a8..834252b79 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.h +++ b/plugins/channelrx/demodadsb/adsbdemodgui.h @@ -509,8 +509,8 @@ private: QString getAirportFrequenciesDBFilename(); QString getOSNDBFilename(); QString getFastDBFilename(); - qint64 ADSBDemodGUI::fileAgeInDays(QString filename); - bool ADSBDemodGUI::confirmDownload(QString filename); + qint64 fileAgeInDays(QString filename); + bool confirmDownload(QString filename); void readAirportDB(const QString& filename); void readAirportFrequenciesDB(const QString& filename); bool readOSNDB(const QString& filename); From 8321e68ec2a36416f90ec5486a8c6f463e64877a Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Thu, 12 Nov 2020 15:36:40 +0000 Subject: [PATCH 10/10] Fix for older version of Qt --- plugins/channelrx/demodadsb/adsbdemodgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/channelrx/demodadsb/adsbdemodgui.cpp b/plugins/channelrx/demodadsb/adsbdemodgui.cpp index e830382db..46a43b2f0 100644 --- a/plugins/channelrx/demodadsb/adsbdemodgui.cpp +++ b/plugins/channelrx/demodadsb/adsbdemodgui.cpp @@ -957,7 +957,7 @@ void ADSBDemodGUI::handleADSB( } else { - qDebug() << "ADSBDemodGUI::handleADSB: Invalid latitude " << latitude << " for " << Qt::hex << aircraft->m_icao + qDebug() << "ADSBDemodGUI::handleADSB: Invalid latitude " << latitude << " for " << QString("%1").arg(aircraft->m_icao, 1, 16) << " m_cprLat[0] " << aircraft->m_cprLat[0] << " m_cprLat[1] " << aircraft->m_cprLat[1]; aircraft->m_cprValid[0] = false;