From a1856b9bb08b0659c8c9147007a91e4365517955 Mon Sep 17 00:00:00 2001 From: Mark Thompson <129641948+NotherNgineer@users.noreply.github.com> Date: Wed, 11 Oct 2023 00:44:56 -0500 Subject: [PATCH] Fix some Guru Meditation Faults in ADSB-RX app (#1483) * Don't use screen_rect in functions called from rtc_timer_tick * Pause AircraftRecentEntry list changes when AC Details screen is displayed --- firmware/application/apps/ui_adsb_rx.cpp | 10 ++++++++++ firmware/application/ui/ui_geomap.cpp | 21 +++++++++------------ firmware/application/ui/ui_geomap.hpp | 8 +++++--- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index b59a18fb7..7fa5f9a5c 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -34,6 +34,8 @@ using namespace portapack; namespace ui { +bool ac_details_view_active{false}; + template <> void RecentEntriesTable::draw( const Entry& entry, @@ -182,6 +184,7 @@ ADSBRxAircraftDetailsView::ADSBRxAircraftDetailsView( break; } button_close.on_select = [&nav](Button&) { + ac_details_view_active = false; nav.pop(); }; }; @@ -217,6 +220,7 @@ void ADSBRxDetailsView::update(const AircraftRecentEntry& entry) { } ADSBRxDetailsView::~ADSBRxDetailsView() { + ac_details_view_active = false; on_close_(); } @@ -260,6 +264,7 @@ ADSBRxDetailsView::ADSBRxDetailsView( text_icao_address.set(to_string_hex(entry_copy.ICAO_address, 6)); button_aircraft_details.on_select = [this, &nav](Button&) { + ac_details_view_active = true; aircraft_details_view = nav.push(entry_copy, [this]() { send_updates = false; }); send_updates = false; }; @@ -433,6 +438,11 @@ void ADSBRxView::updateDetailsAndMap(int ageStep) { ui::GeoMarker marker; bool storeNewMarkers = false; + // NB: Temporarily pausing updates in rtc_timer_tick context when viewing AC Details screen (kludge for some Guru faults) + // TODO: More targeted blocking of updates in rtc_timer_tick when ADSB processes are running + if (ac_details_view_active) + return; + // Sort and truncate the entries, grouped, newest group first sort_entries_by_state(); truncate_entries(recent); diff --git a/firmware/application/ui/ui_geomap.cpp b/firmware/application/ui/ui_geomap.cpp index d85273f41..e3a6d4202 100644 --- a/firmware/application/ui/ui_geomap.cpp +++ b/firmware/application/ui/ui_geomap.cpp @@ -149,7 +149,7 @@ bool GeoMap::on_encoder(const EncoderEvent delta) { map_zoom++; // Ensure that MOD(240,map_zoom)==0 for the map_zoom_line() function - if (240 % map_zoom != 0) { + if (geomap_rect_width % map_zoom != 0) { map_zoom--; } } else if ((delta < 0) && (map_zoom > 1)) { @@ -171,7 +171,7 @@ void GeoMap::map_zoom_line(ui::Color* buffer) { // As long as MOD(width,map_zoom)==0 then we don't need to check buffer overflow case when stretching last pixel; // For 240 width, than means no check is needed for map_zoom values up to 6 - for (int i = (240 / map_zoom) - 1; i >= 0; i--) { + for (int i = (geomap_rect_width / map_zoom) - 1; i >= 0; i--) { for (int j = 0; j < map_zoom; j++) { buffer[(i * map_zoom) + j] = buffer[i]; } @@ -271,24 +271,22 @@ void GeoMap::move(const float lon, const float lat) { lon_ = lon; lat_ = lat; - Rect map_rect = screen_rect(); - // Using WGS 84/Pseudo-Mercator projection - x_pos = map_width * (lon_ + 180) / 360 - (map_rect.width() / 2); + x_pos = map_width * (lon_ + 180) / 360 - (geomap_rect_width / 2); // Latitude calculation based on https://stackoverflow.com/a/10401734/2278659 double lat_rad = sin(lat * pi / 180); y_pos = map_height - ((map_world_lon / 2 * log((1 + lat_rad) / (1 - lat_rad))) - map_offset) - 128; // Offset added for the GUI // Cap position - if (x_pos > (map_width - map_rect.width())) - x_pos = map_width - map_rect.width(); - if (y_pos > (map_height + map_rect.height())) - y_pos = map_height - map_rect.height(); + if (x_pos > (map_width - geomap_rect_width)) + x_pos = map_width - geomap_rect_width; + if (y_pos > (map_height + geomap_rect_height)) + y_pos = map_height - geomap_rect_height; // Scale calculation float km_per_deg_lon = cos(lat * pi / 180) * 111.321; // 111.321 km/deg longitude at equator, and 0 km at poles - pixels_per_km = (map_rect.width() / 2) / km_per_deg_lon; + pixels_per_km = (geomap_rect_width / 2) / km_per_deg_lon; } bool GeoMap::init() { @@ -391,11 +389,10 @@ MapMarkerStored GeoMap::store_marker(GeoMarker& marker) { // Check if it could be on screen // Only checking one direction to reduce CPU - const auto r = screen_rect(); double lat_rad = sin(marker.lat * pi / 180); int x = (map_width * (marker.lon + 180) / 360) - x_pos; int y = (map_height - ((map_world_lon / 2 * log((1 + lat_rad) / (1 - lat_rad))) - map_offset)) - y_pos; // Offset added for the GUI - if (false == ((x >= 0) && (x < r.width()) && (y > 10) && (y < r.height()))) // Dont draw within symbol size of top + if (false == ((x >= 0) && (x < geomap_rect_width) && (y > 10) && (y < geomap_rect_height))) // Dont draw within symbol size of top { ret = MARKER_NOT_STORED; } else if (markerListLen < NumMarkerListElements) { diff --git a/firmware/application/ui/ui_geomap.hpp b/firmware/application/ui/ui_geomap.hpp index d53c35b16..04e8bfef1 100644 --- a/firmware/application/ui/ui_geomap.hpp +++ b/firmware/application/ui/ui_geomap.hpp @@ -178,6 +178,10 @@ class GeoMap : public Widget { void clear_markers(); MapMarkerStored store_marker(GeoMarker& marker); + static const Dim banner_height = 3 * 16; + static const Dim geomap_rect_width = 240; + static const Dim geomap_rect_height = 320 - 16 - banner_height; + private: void draw_scale(Painter& painter); void draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color); @@ -250,8 +254,6 @@ class GeoMapView : public View { void setup(); const std::function on_done{}; - - const Dim banner_height = 3 * 16; GeoMapMode mode_{}; int32_t altitude_{}; GeoPos::alt_unit altitude_unit_{}; @@ -267,7 +269,7 @@ class GeoMapView : public View { altitude_unit_}; GeoMap geomap{ - {0, banner_height, 240, 320 - 16 - banner_height}}; + {0, GeoMap::banner_height, GeoMap::geomap_rect_width, GeoMap::geomap_rect_height}}; Button button_ok{ {20 * 8, 8, 8 * 8, 2 * 16},