mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Updates to put the multiple aircraft on the map
Also manage the CPU in on the one second tick to keep GUI responsive Some other small edits that fix minor problems from my previous checkins
This commit is contained in:
parent
00b75eacda
commit
778111d466
@ -46,10 +46,10 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
|
||||
auto entry_age = entry.age;
|
||||
|
||||
// Color decay for flights not being updated anymore
|
||||
if (entry_age < ADSB_DECAY_A) {
|
||||
if (entry_age < ADSB_CURRENT) {
|
||||
aged_color = 0x10;
|
||||
target_color = Color::green();
|
||||
} else if (entry_age < ADSB_DECAY_B) {
|
||||
} else if (entry_age < ADSB_RECENT) {
|
||||
aged_color = 0x07;
|
||||
target_color = Color::light_grey();
|
||||
} else {
|
||||
@ -59,21 +59,13 @@ void RecentEntriesTable<AircraftRecentEntries>::draw(
|
||||
|
||||
std::string entry_string = "\x1B";
|
||||
entry_string += aged_color;
|
||||
#if false
|
||||
entry_string += to_string_hex(entry.ICAO_address, 6) + " " +
|
||||
entry.callsign + " " +
|
||||
(entry.hits <= 999 ? to_string_dec_uint(entry.hits, 4) : "999+") + " " +
|
||||
entry.time_string;
|
||||
#else
|
||||
// SBT
|
||||
entry_string +=
|
||||
(entry.callsign[0]!=' ' ? entry.callsign + " " : to_string_hex(entry.ICAO_address, 6) + " ") +
|
||||
to_string_dec_uint((unsigned int)((entry.pos.altitude+50)/100),4) +
|
||||
(entry.callsign[0]!=' ' ? entry.callsign + " " : entry.icaoStr + " ") +
|
||||
to_string_dec_uint((unsigned int)(entry.pos.altitude/100),4) +
|
||||
to_string_dec_uint((unsigned int)entry.velo.speed,4) +
|
||||
to_string_dec_uint((unsigned int)(entry.amp>>9),4) + " " +
|
||||
(entry.hits <= 999 ? to_string_dec_uint(entry.hits, 3) + " " : "1k+ ") +
|
||||
to_string_dec_uint(entry.age, 4);
|
||||
#endif
|
||||
|
||||
painter.draw_string(
|
||||
target_rect.location(),
|
||||
@ -124,8 +116,6 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView(
|
||||
});
|
||||
|
||||
std::unique_ptr<ADSBLogger> logger { };
|
||||
//update(entry_copy);
|
||||
|
||||
|
||||
icao_code = to_string_hex(entry_copy.ICAO_address, 6);
|
||||
text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6));
|
||||
@ -225,8 +215,11 @@ void ADSBRxDetailsView::update(const AircraftRecentEntry& entry) {
|
||||
text_frame_pos_odd.set(to_string_hex_array(entry_copy.frame_pos_odd.get_raw_data(), 14));
|
||||
|
||||
if (send_updates)
|
||||
{
|
||||
geomap_view->update_tag(trimr(entry.callsign[0]!=' ' ? entry.callsign : to_string_hex(entry.ICAO_address, 6)));
|
||||
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude, entry_copy.velo.heading, entry_copy.pos.altitude);
|
||||
}
|
||||
}
|
||||
|
||||
ADSBRxDetailsView::~ADSBRxDetailsView() {
|
||||
on_close_();
|
||||
@ -277,19 +270,14 @@ ADSBRxDetailsView::ADSBRxDetailsView(
|
||||
text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6));
|
||||
|
||||
button_aircraft_details.on_select = [this, &nav](Button&) {
|
||||
//detailed_entry_key = entry.key();
|
||||
aircraft_details_view = nav.push<ADSBRxAircraftDetailsView>(
|
||||
entry_copy,
|
||||
[this]() {
|
||||
send_updates = false;
|
||||
});
|
||||
aircraft_details_view = nav.push<ADSBRxAircraftDetailsView>(entry_copy, [this]() { send_updates = false;});
|
||||
send_updates = false;
|
||||
};
|
||||
|
||||
button_see_map.on_select = [this, &nav](Button&) {
|
||||
if (!send_updates) { // Prevent recursively launching the map
|
||||
geomap_view = nav.push<GeoMapView>(
|
||||
entry_copy.callsign,
|
||||
trimr(entry_copy.callsign[0]!=' ' ? entry_copy.callsign : entry_copy.icaoStr),
|
||||
entry_copy.pos.altitude,
|
||||
GeoPos::alt_unit::FEET,
|
||||
entry_copy.pos.latitude,
|
||||
@ -309,6 +297,7 @@ void ADSBRxView::focus() {
|
||||
}
|
||||
|
||||
ADSBRxView::~ADSBRxView() {
|
||||
receiver_model.set_tuning_frequency(prevFreq); // Restore previous frequency on exit
|
||||
|
||||
// save app settings
|
||||
settings.save("rx_adsb", &app_settings);
|
||||
@ -326,8 +315,6 @@ AircraftRecentEntry ADSBRxView::find_or_create_entry(uint32_t ICAO_address) {
|
||||
// If not found
|
||||
if (it == std::end(recent)){
|
||||
recent.emplace_front(ICAO_address); // Add it
|
||||
truncate_entries(recent); // Truncate the list
|
||||
sort_entries_by_state();
|
||||
it = find(recent, ICAO_address); // Find it again
|
||||
}
|
||||
return *it;
|
||||
@ -342,6 +329,21 @@ void ADSBRxView::replace_entry(AircraftRecentEntry & entry)
|
||||
entry);
|
||||
}
|
||||
|
||||
void ADSBRxView::remove_old_entries()
|
||||
{
|
||||
auto it = recent.rbegin();
|
||||
auto end = recent.rend();
|
||||
while (it != end)
|
||||
{
|
||||
if (it->age_state>=4) {
|
||||
std::advance(it, 1);
|
||||
recent.erase( it.base() );
|
||||
} else {
|
||||
break; // stop looking because the list is sorted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ADSBRxView::sort_entries_by_state()
|
||||
{
|
||||
// Sorting List pn age_state using lambda function as comparator
|
||||
@ -349,8 +351,8 @@ void ADSBRxView::sort_entries_by_state()
|
||||
}
|
||||
|
||||
void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
|
||||
logger = std::make_unique<ADSBLogger>();
|
||||
rtc::RTC datetime;
|
||||
std::string str_timestamp;
|
||||
std::string callsign;
|
||||
std::string str_info;
|
||||
std::string logentry;
|
||||
@ -365,16 +367,16 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
|
||||
entry.reset_age();
|
||||
if (entry.hits==0)
|
||||
{
|
||||
entry.amp = message->amp;
|
||||
entry.amp = message->amp; // Store amplitude on first hit
|
||||
} else {
|
||||
entry.amp = ((entry.amp*15)+message->amp)>>4;
|
||||
entry.amp = ((entry.amp*15)+message->amp)>>4; // Update smoothed amplitude on updates
|
||||
}
|
||||
str_timestamp = to_string_datetime(datetime, HMS);
|
||||
entry.set_time_string(str_timestamp);
|
||||
|
||||
entry.inc_hit();
|
||||
if (logger) {
|
||||
logentry += to_string_hex_array(frame.get_raw_data(), 14) + " ";
|
||||
logentry += "ICAO:" + to_string_hex(ICAO_address, 6) + " ";
|
||||
logentry += "ICAO:" + entry.icaoStr + " ";
|
||||
}
|
||||
|
||||
if (frame.get_DF() == DF_ADSB) {
|
||||
uint8_t msg_type = frame.get_msg_type();
|
||||
@ -385,8 +387,10 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
|
||||
if ((msg_type >= AIRCRAFT_ID_L) && (msg_type <= AIRCRAFT_ID_H)) {
|
||||
callsign = decode_frame_id(frame);
|
||||
entry.set_callsign(callsign);
|
||||
if (logger) {
|
||||
logentry+=callsign+" ";
|
||||
}
|
||||
}
|
||||
// 9:
|
||||
// 18: { // Extended squitter/non-transponder
|
||||
// 21: // Comm-B, identity reply
|
||||
@ -400,6 +404,10 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
|
||||
" Lat:" + to_string_decimal(entry.pos.latitude, 2) +
|
||||
" Lon:" + to_string_decimal(entry.pos.longitude, 2);
|
||||
|
||||
|
||||
entry.set_info_string(str_info);
|
||||
|
||||
if (logger) {
|
||||
// printing the coordinates in the log file with more
|
||||
// resolution, as we are not constrained by screen
|
||||
// real estate there:
|
||||
@ -407,23 +415,22 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
|
||||
std::string log_info = "Alt:" + to_string_dec_int(entry.pos.altitude) +
|
||||
" Lat:" + to_string_decimal(entry.pos.latitude, 7) +
|
||||
" Lon:" + to_string_decimal(entry.pos.longitude, 7);
|
||||
|
||||
entry.set_info_string(str_info);
|
||||
logentry+=log_info + " ";
|
||||
}
|
||||
|
||||
}
|
||||
} else if(msg_type == AIRBORNE_VEL && msg_sub >= VEL_GND_SUBSONIC && msg_sub <= VEL_AIR_SUPERSONIC){
|
||||
entry.set_frame_velo(frame);
|
||||
if (logger) {
|
||||
logentry += "Type:" + to_string_dec_uint(msg_sub) +
|
||||
" Hdg:" + to_string_dec_uint(entry.velo.heading) +
|
||||
" Spd: "+ to_string_dec_int(entry.velo.speed);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
replace_entry(entry);
|
||||
} // frame.get_DF() == DF_ADSB
|
||||
|
||||
logger = std::make_unique<ADSBLogger>();
|
||||
if (logger) {
|
||||
logger->append(u"adsb.txt");
|
||||
// will log each frame in format:
|
||||
@ -434,19 +441,68 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
|
||||
}
|
||||
|
||||
void ADSBRxView::on_tick_second() {
|
||||
// Decay and refresh if needed
|
||||
for (auto& entry : recent) {
|
||||
entry.inc_age();
|
||||
if (recent.size() <= 16){ // Not many entries update everything (16 is one screen full)
|
||||
updateDetailsAndMap(1);
|
||||
updateRecentEntries();
|
||||
} else if (updateState==0) { // Even second
|
||||
updateState = 1;
|
||||
updateDetailsAndMap(2);
|
||||
} else { // Odd second only performed when there are many entries
|
||||
updateState = 0;
|
||||
updateRecentEntries();
|
||||
}
|
||||
}
|
||||
|
||||
if (details_view) {
|
||||
if (send_updates && (entry.key() == detailed_entry_key)) // Check if the ICAO address match
|
||||
void ADSBRxView::updateDetailsAndMap(int ageStep) {
|
||||
ui::GeoMarker marker;
|
||||
bool storeNewMarkers = false;
|
||||
|
||||
// Sort and truncate the entries, grouped, newest group first
|
||||
sort_entries_by_state();
|
||||
truncate_entries(recent);
|
||||
remove_old_entries();
|
||||
|
||||
// Calculate if it is time to update markers
|
||||
if (send_updates && details_view && details_view->geomap_view) {
|
||||
ticksSinceMarkerRefresh += ageStep;
|
||||
if (ticksSinceMarkerRefresh >= MARKER_UPDATE_SECONDS) { // Update other aircraft every few seconds
|
||||
storeNewMarkers = true;
|
||||
ticksSinceMarkerRefresh=0;
|
||||
}
|
||||
} else {
|
||||
ticksSinceMarkerRefresh = MARKER_UPDATE_SECONDS; // Send the markers as soon as the geoview exists
|
||||
}
|
||||
|
||||
// Increment age, and pass updates to the details and map
|
||||
const bool otherMarkersCanBeSent = send_updates && storeNewMarkers && details_view && details_view->geomap_view; // Save retesting all of this
|
||||
MapMarkerStored markerStored = MARKER_NOT_STORED;
|
||||
if (otherMarkersCanBeSent) {details_view->geomap_view->clear_markers();}
|
||||
// Loop through all entries
|
||||
for (auto& entry : recent) {
|
||||
entry.inc_age(ageStep);
|
||||
|
||||
// Only if there is a details view
|
||||
if (send_updates && details_view) {
|
||||
if (entry.key() == detailed_entry_key) // Check if the ICAO address match
|
||||
{
|
||||
details_view->update(entry);
|
||||
}
|
||||
// Store if the view is present and the list isn't full
|
||||
else if (otherMarkersCanBeSent && (markerStored != MARKER_LIST_FULL) && (entry.age_state==0))
|
||||
{
|
||||
marker.lon = entry.pos.longitude;
|
||||
marker.lat = entry.pos.latitude;
|
||||
marker.angle = entry.velo.heading;
|
||||
marker.tag = trimr(entry.callsign[0]!=' ' ? entry.callsign : entry.icaoStr);
|
||||
markerStored = details_view->geomap_view->store_marker(marker);
|
||||
}
|
||||
}
|
||||
} // Loop through all entries, if only to update the age
|
||||
}
|
||||
|
||||
// Sort the list if it is being displayed
|
||||
void ADSBRxView::updateRecentEntries() {
|
||||
// Redraw the list of aircraft
|
||||
if (!send_updates){
|
||||
sort_entries_by_state();
|
||||
recent_entries_view.set_dirty();
|
||||
}
|
||||
}
|
||||
@ -492,7 +548,7 @@ ADSBRxView::ADSBRxView(NavigationView& nav) {
|
||||
on_tick_second();
|
||||
};
|
||||
|
||||
prevFreq = receiver_model.tuning_frequency();
|
||||
prevFreq = receiver_model.tuning_frequency(); // Store previous frequency on creation
|
||||
|
||||
baseband::set_adsb();
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "ui_receiver.hpp"
|
||||
#include "ui_geomap.hpp"
|
||||
#include "ui_font_fixed_8x16.hpp"
|
||||
#include "string_format.hpp"
|
||||
|
||||
#include "file.hpp"
|
||||
#include "database.hpp"
|
||||
@ -39,9 +40,9 @@ using namespace adsb;
|
||||
|
||||
namespace ui {
|
||||
|
||||
#define ADSB_DECAY_A 10 // In seconds
|
||||
#define ADSB_DECAY_B 30
|
||||
#define ADSB_DECAY_C 60 // Can be used for removing old entries, RecentEntries already caps to 64
|
||||
#define ADSB_CURRENT 10 // Seconds
|
||||
#define ADSB_RECENT 30 // Seconds
|
||||
#define ADSB_REMOVE 300 // Used for removing old entries
|
||||
|
||||
#define AIRCRAFT_ID_L 1 // aircraft ID message type (lowest type id)
|
||||
#define AIRCRAFT_ID_H 4 // aircraft ID message type (highest type id)
|
||||
@ -83,14 +84,15 @@ struct AircraftRecentEntry {
|
||||
ADSBFrame frame_pos_even { };
|
||||
ADSBFrame frame_pos_odd { };
|
||||
|
||||
std::string icaoStr {" "};
|
||||
std::string callsign { " " };
|
||||
std::string time_string { "" };
|
||||
std::string info_string { "" };
|
||||
|
||||
AircraftRecentEntry(
|
||||
const uint32_t ICAO_address
|
||||
) : ICAO_address { ICAO_address }
|
||||
{
|
||||
this->icaoStr = to_string_hex(ICAO_address, 6);
|
||||
}
|
||||
|
||||
Key key() const {
|
||||
@ -125,23 +127,20 @@ struct AircraftRecentEntry {
|
||||
info_string = new_info_string;
|
||||
}
|
||||
|
||||
void set_time_string(std::string& new_time_string) {
|
||||
time_string = new_time_string;
|
||||
}
|
||||
|
||||
void reset_age() {
|
||||
age = 0;
|
||||
}
|
||||
|
||||
void inc_age() {
|
||||
age++;
|
||||
if (age < ADSB_DECAY_A)
|
||||
{
|
||||
void inc_age(int delta) {
|
||||
age+=delta;
|
||||
if (age < ADSB_CURRENT){
|
||||
age_state = pos.valid ? 0 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
age_state = (age < ADSB_DECAY_B) ? 2 : 3;
|
||||
} else if(age < ADSB_RECENT){
|
||||
age_state = 2;
|
||||
} else if(age < ADSB_REMOVE){
|
||||
age_state = 3;
|
||||
} else{
|
||||
age_state = 4;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -276,7 +275,6 @@ public:
|
||||
private:
|
||||
AircraftRecentEntry entry_copy { 0 };
|
||||
std::function<void(void)> on_close_ { };
|
||||
GeoMapView* geomap_view { nullptr };
|
||||
ADSBRxAircraftDetailsView* aircraft_details_view { nullptr };
|
||||
bool send_updates { false };
|
||||
std::database db = { };
|
||||
@ -364,6 +362,7 @@ public:
|
||||
std::string title() const override { return "ADS-B RX"; };
|
||||
|
||||
void replace_entry(AircraftRecentEntry & entry);
|
||||
void remove_old_entries();
|
||||
AircraftRecentEntry find_or_create_entry(uint32_t ICAO_address);
|
||||
void sort_entries_by_state();
|
||||
|
||||
@ -372,24 +371,23 @@ private:
|
||||
std::unique_ptr<ADSBLogger> logger { };
|
||||
void on_frame(const ADSBFrameMessage * message);
|
||||
void on_tick_second();
|
||||
int updateState = { 0 };
|
||||
void updateRecentEntries();
|
||||
void updateDetailsAndMap(int ageStep);
|
||||
|
||||
#define MARKER_UPDATE_SECONDS (5)
|
||||
int ticksSinceMarkerRefresh { MARKER_UPDATE_SECONDS-1 };
|
||||
// app save settings
|
||||
std::app_settings settings { };
|
||||
std::app_settings::AppSettings app_settings { };
|
||||
|
||||
const RecentEntriesColumns columns { {
|
||||
#if false
|
||||
{ "ICAO", 6 },
|
||||
{ "Callsign", 9 },
|
||||
{ "Hits", 4 },
|
||||
{ "Time", 8 }
|
||||
#else
|
||||
{ "ICAO/Call", 9 },
|
||||
{ "Lvl", 3 },
|
||||
{ "Spd", 3 },
|
||||
{ "Amp", 3 },
|
||||
{ "Hit", 3 },
|
||||
{ "Age", 4 }
|
||||
#endif
|
||||
} };
|
||||
AircraftRecentEntries recent { };
|
||||
RecentEntriesView<RecentEntries<AircraftRecentEntry>> recent_entries_view { columns, recent };
|
||||
|
@ -45,8 +45,8 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
for (size_t i = 0; i < buffer.count; i++) {
|
||||
|
||||
// Compute sample's magnitude
|
||||
re = (int32_t)buffer.p[i].real(); // make re float and scale it
|
||||
im = (int32_t)buffer.p[i].imag(); // make re float and scale it
|
||||
re = (int32_t)buffer.p[i].real();
|
||||
im = (int32_t)buffer.p[i].imag();
|
||||
mag = ((uint32_t)(re*re) + (uint32_t)(im*im));
|
||||
|
||||
if (decoding) {
|
||||
@ -63,7 +63,6 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
}
|
||||
else
|
||||
{
|
||||
//confidence = true;
|
||||
bit = (prev_mag > mag) ? 1 : 0;
|
||||
}
|
||||
|
||||
@ -94,7 +93,7 @@ void ADSBRXProcessor::execute(const buffer_c8_t& buffer) {
|
||||
}
|
||||
|
||||
// Continue looking for preamble even if in a packet
|
||||
// switch is new preamble id higher magnitude
|
||||
// switch if new preamble is higher magnitude
|
||||
|
||||
// Shift the preamble
|
||||
for (c = 0; c < (ADSB_PREAMBLE_LENGTH ); c++) { shifter[c] = shifter[c + 1]; }
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "adsb.hpp"
|
||||
#include "sine_table.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@ -369,11 +370,11 @@ adsb_vel decode_frame_velo(ADSBFrame& frame){
|
||||
if(frame_data[5]&0x04) velo_ew *= -1; //check ew direction sign
|
||||
if(frame_data[7]&0x80) velo_ns *= -1; //check ns direction sign
|
||||
|
||||
velo.speed = sqrt(velo_ns*velo_ns + velo_ew*velo_ew);
|
||||
velo.speed = fast_int_magnitude(velo_ns,velo_ew);
|
||||
|
||||
if(velo.speed){
|
||||
//calculate heading in degrees from ew/ns velocities
|
||||
int16_t heading_temp = (int16_t)(atan2(velo_ew,velo_ns) * 180.0 / pi);
|
||||
int16_t heading_temp = (int16_t)(int_atan2(velo_ew,velo_ns)); // Nearest degree
|
||||
// We don't want negative values but a 0-360 scale.
|
||||
if (heading_temp < 0) heading_temp += 360.0;
|
||||
velo.heading = (uint16_t)heading_temp;
|
||||
|
Loading…
Reference in New Issue
Block a user