From 831dbeaab527910d41800c43a40f94703ea6580a Mon Sep 17 00:00:00 2001 From: Totoo Date: Thu, 11 Jan 2024 17:46:35 +0100 Subject: [PATCH] Add extra info from serial (#1754) * Inject GPS postition from serial --- firmware/application/apps/ui_adsb_rx.cpp | 11 +++++ firmware/application/apps/ui_adsb_rx.hpp | 15 +++++++ firmware/application/ui/ui_geomap.cpp | 54 +++++++++++++++++++++++ firmware/application/ui/ui_geomap.hpp | 12 +++++ firmware/application/usb_serial_shell.cpp | 31 +++++++++++++ firmware/common/message.hpp | 31 +++++++++++++ 6 files changed, 154 insertions(+) diff --git a/firmware/application/apps/ui_adsb_rx.cpp b/firmware/application/apps/ui_adsb_rx.cpp index 2279427b..a3a83619 100644 --- a/firmware/application/apps/ui_adsb_rx.cpp +++ b/firmware/application/apps/ui_adsb_rx.cpp @@ -318,6 +318,17 @@ bool ADSBRxDetailsView::add_map_marker(const AircraftRecentEntry& entry) { return markerStored == MARKER_STORED; } +void ADSBRxDetailsView::on_gps(const GPSPosDataMessage* msg) { + if (!geomap_view_) + return; + geomap_view_->update_my_position(msg->lat, msg->lon, msg->altitude); +} +void ADSBRxDetailsView::on_orientation(const OrientationDataMessage* msg) { + if (!geomap_view_) + return; + geomap_view_->update_my_orientation(msg->angle); +} + void ADSBRxDetailsView::refresh_ui() { auto age = entry_.age; if (age < 60) diff --git a/firmware/application/apps/ui_adsb_rx.hpp b/firmware/application/apps/ui_adsb_rx.hpp index 20ee817a..3285f01f 100644 --- a/firmware/application/apps/ui_adsb_rx.hpp +++ b/firmware/application/apps/ui_adsb_rx.hpp @@ -271,6 +271,8 @@ class ADSBRxDetailsView : public View { private: void refresh_ui(); + void on_gps(const GPSPosDataMessage* msg); + void on_orientation(const OrientationDataMessage* msg); GeoMapView* geomap_view_{nullptr}; ADSBRxAircraftDetailsView* aircraft_details_view_{nullptr}; @@ -330,6 +332,19 @@ class ADSBRxDetailsView : public View { Button button_see_map{ {16 * 8, 9 * 16, 12 * 8, 3 * 16}, "See on map"}; + + MessageHandlerRegistration message_handler_gps{ + Message::ID::GPSPosData, + [this](Message* const p) { + const auto message = static_cast(p); + this->on_gps(message); + }}; + MessageHandlerRegistration message_handler_orientation{ + Message::ID::OrientationData, + [this](Message* const p) { + const auto message = static_cast(p); + this->on_orientation(message); + }}; }; /* Main ADSB application view and message dispatch. */ diff --git a/firmware/application/ui/ui_geomap.cpp b/firmware/application/ui/ui_geomap.cpp index 71cf6279..f06fa560 100644 --- a/firmware/application/ui/ui_geomap.cpp +++ b/firmware/application/ui/ui_geomap.cpp @@ -305,6 +305,7 @@ void GeoMap::paint(Painter& painter) { // Draw the other markers draw_markers(painter); draw_scale(painter); + draw_mypos(); markerListUpdated = false; set_clean(); } @@ -447,6 +448,41 @@ void GeoMap::draw_marker(Painter& painter, const ui::Point itemPoint, const uint } } +void GeoMap::draw_mypos() { + const auto r = screen_rect(); + if (my_lat >= 200 || my_lon >= 200) return; // invalid + int x = (map_width * (my_lon + 180) / 360) - x_pos; + double lat_rad = sin(my_lat * pi / 180); + int y = (map_height - ((map_world_lon / 2 * log((1 + lat_rad) / (1 - lat_rad))) - map_offset)) - y_pos; // Offset added for the GUI + auto color = Color::yellow(); + + if (map_zoom > 1) { + x = ((x - (r.width() / 2)) * map_zoom) + (r.width() / 2); + y = ((y - (r.height() / 2)) * map_zoom) + (r.height() / 2); + } else if (map_zoom < 0) { + x = ((x - (r.width() / 2)) / (-map_zoom)) + (r.width() / 2); + y = ((y - (r.height() / 2)) / (-map_zoom)) + (r.height() / 2); + } + + if ((x >= 0) && (x < r.width()) && + (y > 10) && (y < r.height())) // Dont draw within symbol size of top + { + ui::Point itemPoint(x, y + r.top()); + if (mode_ == PROMPT) { + // Cross + display.fill_rectangle({itemPoint - Point(16, 1), {32, 2}}, color); + display.fill_rectangle({itemPoint - Point(1, 16), {2, 32}}, color); + } else if (my_angle < 360) { + // if we have a valid angle draw bearing + draw_bearing(itemPoint, my_angle, 10, color); + } else { + // draw a small cross + display.fill_rectangle({itemPoint - Point(8, 1), {16, 2}}, color); + display.fill_rectangle({itemPoint - Point(1, 8), {2, 16}}, color); + } + } +} + void GeoMap::clear_markers() { markerListLen = 0; } @@ -473,6 +509,17 @@ MapMarkerStored GeoMap::store_marker(GeoMarker& marker) { return ret; } +void GeoMap::update_my_position(float lat, float lon, int32_t altitude) { + my_lat = lat; + my_lon = lon; + my_altitude = altitude; + markerListUpdated = true; + set_dirty(); +} +void GeoMap::update_my_orientation(uint16_t angle) { + my_angle = angle; +} + void GeoMapView::focus() { geopos.focus(); @@ -480,6 +527,13 @@ void GeoMapView::focus() { nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT); } +void GeoMapView::update_my_position(float lat, float lon, int32_t altitude) { + geomap.update_my_position(lat, lon, altitude); +} +void GeoMapView::update_my_orientation(uint16_t angle) { + geomap.update_my_orientation(angle); +} + void GeoMapView::update_position(float lat, float lon, uint16_t angle, int32_t altitude, int32_t speed) { if (geomap.manual_panning()) { geomap.set_dirty(); diff --git a/firmware/application/ui/ui_geomap.hpp b/firmware/application/ui/ui_geomap.hpp index bb5bc586..a8849250 100644 --- a/firmware/application/ui/ui_geomap.hpp +++ b/firmware/application/ui/ui_geomap.hpp @@ -185,6 +185,9 @@ class GeoMap : public Widget { bool on_encoder(const EncoderEvent delta) override; bool on_keyboard(const KeyboardEvent event) override; + void update_my_position(float lat, float lon, int32_t altitude); + void update_my_orientation(uint16_t angle); + bool init(); void set_mode(GeoMapMode mode); void set_manual_panning(bool v); @@ -212,6 +215,7 @@ class GeoMap : public Widget { void draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color); void draw_marker(Painter& painter, const ui::Point itemPoint, const uint16_t itemAngle, const std::string itemTag, const Color color = Color::red(), const Color fontColor = Color::white(), const Color backColor = Color::black()); void draw_markers(Painter& painter); + void draw_mypos(); void map_read_line(ui::Color* buffer, uint16_t pixels); bool manual_panning_{false}; @@ -233,6 +237,12 @@ class GeoMap : public Widget { uint16_t angle_{}; std::string tag_{}; + // the portapack's position data ( for example injected from serial ) + float my_lat{200}; + float my_lon{200}; + int32_t my_altitude{0}; + uint16_t my_angle{400}; + int markerListLen{0}; GeoMarker markerList[NumMarkerListElements]; bool markerListUpdated{false}; @@ -267,6 +277,8 @@ class GeoMapView : public View { void focus() override; void update_position(float lat, float lon, uint16_t angle, int32_t altitude, int32_t speed = 0); + void update_my_position(float lat, float lon, int32_t altitude); + void update_my_orientation(uint16_t angle); std::string title() const override { return "Map view"; }; diff --git a/firmware/application/usb_serial_shell.cpp b/firmware/application/usb_serial_shell.cpp index 463f1c84..2051fc85 100644 --- a/firmware/application/usb_serial_shell.cpp +++ b/firmware/application/usb_serial_shell.cpp @@ -877,6 +877,35 @@ static void cmd_cpld_read(BaseSequentialStream* chp, int argc, char* argv[]) { } } +static void cmd_gotgps(BaseSequentialStream* chp, int argc, char* argv[]) { + const char* usage = "usage: gotgps [altitude] [speed]\r\n"; + if (argc < 2 || argc > 4) { + chprintf(chp, usage); + return; + } + float lat = atof(argv[0]); + float lon = atof(argv[1]); + int32_t altitude = 0; + int32_t speed = 0; + if (argc >= 3) altitude = strtol(argv[2], NULL, 10); + if (argc >= 4) speed = strtol(argv[3], NULL, 10); + GPSPosDataMessage msg{lat, lon, altitude, speed}; + EventDispatcher::send_message(msg); + chprintf(chp, "ok\r\n"); +} + +static void cmd_gotorientation(BaseSequentialStream* chp, int argc, char* argv[]) { + const char* usage = "usage: gotorientation \r\n"; + if (argc != 1) { + chprintf(chp, usage); + return; + } + uint16_t angle = strtol(argv[0], NULL, 10); + OrientationDataMessage msg{angle}; + EventDispatcher::send_message(msg); + chprintf(chp, "ok\r\n"); +} + static const ShellCommand commands[] = { {"reboot", cmd_reboot}, {"dfu", cmd_dfu}, @@ -900,6 +929,8 @@ static const ShellCommand commands[] = { {"accessibility_readcurr", cmd_accessibility_readcurr}, {"applist", cmd_applist}, {"appstart", cmd_appstart}, + {"gotgps", cmd_gotgps}, + {"gotorientation", cmd_gotorientation}, {NULL, NULL}}; static const ShellConfig shell_cfg1 = { diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 43a268e4..b8924abe 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -118,6 +118,8 @@ class Message { SubGhzFPRxConfigure = 60, WeatherData = 61, SubGhzDData = 62, + GPSPosData = 63, + OrientationData = 64, MAX }; @@ -1301,4 +1303,33 @@ class SubGhzDDataMessage : public Message { uint64_t data = 0; }; +class GPSPosDataMessage : public Message { + public: + constexpr GPSPosDataMessage( + float lat = 200.0, + float lon = 200.0, + int32_t altitude = 0, + int32_t speed = 0) + : Message{ID::GPSPosData}, + lat{lat}, + lon{lon}, + altitude{altitude}, + speed{speed} { + } + float lat = 200.0; + float lon = 200.0; + int32_t altitude = 0; + int32_t speed = 0; +}; + +class OrientationDataMessage : public Message { + public: + constexpr OrientationDataMessage( + uint16_t angle = 400) + : Message{ID::OrientationData}, + angle{angle} { + } + uint16_t angle = 400; //>360 -> no orientation set +}; + #endif /*__MESSAGE_H__*/