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
This commit is contained in:
Mark Thompson 2023-10-11 00:44:56 -05:00 committed by GitHub
parent 29a36c8658
commit a1856b9bb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 15 deletions

View File

@ -34,6 +34,8 @@ using namespace portapack;
namespace ui {
bool ac_details_view_active{false};
template <>
void RecentEntriesTable<AircraftRecentEntries>::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<ADSBRxAircraftDetailsView>(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);

View File

@ -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) {

View File

@ -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<void(int32_t, float, float)> 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},