From 6bc34ea65a48721b984867fbaa54c340e794bada Mon Sep 17 00:00:00 2001 From: Luca Jost Date: Sun, 22 Sep 2024 19:02:11 +1200 Subject: [PATCH] [GS] Add data screen --- ground_station/src/hmi/bmp.hpp | 43 +++++++++-- ground_station/src/hmi/hmi.cpp | 67 ++++++++++++++++- ground_station/src/hmi/hmi.hpp | 4 + ground_station/src/hmi/window.cpp | 117 ++++++++++++++++++++++++++++-- ground_station/src/hmi/window.hpp | 9 ++- 5 files changed, 223 insertions(+), 17 deletions(-) diff --git a/ground_station/src/hmi/bmp.hpp b/ground_station/src/hmi/bmp.hpp index a19d18a3..458ec1bd 100644 --- a/ground_station/src/hmi/bmp.hpp +++ b/ground_station/src/hmi/bmp.hpp @@ -50,13 +50,6 @@ const unsigned char live_lat[] PROGMEM = { 0x03, 0xf8, 0x00, 0x03, 0xf8, 0x00, 0x01, 0xf0, 0x00, 0x01, 0xf1, 0x80, 0x00, 0xe3, 0xc0, 0x00, 0xe7, 0xe0, 0x00, 0xe1, 0x80, 0x00, 0x41, 0x80, 0x00, 0x41, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -// 'live_speed', 24x24px -const unsigned char live_speed[] PROGMEM = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xff, 0x80, 0x01, 0xff, 0x80, 0x0f, 0x00, 0xf0, 0x0f, 0x00, 0xf0, 0x38, 0x00, 0x1c, 0x38, 0x00, 0x1c, - 0x60, 0x00, 0xc6, 0x60, 0x01, 0x86, 0x60, 0x03, 0x06, 0xc0, 0x06, 0x03, 0xc0, 0x0c, 0x03, 0xc0, 0x18, 0x03, - 0xc0, 0x30, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - // 'live_altitude', 24x24px const unsigned char live_altitude[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -562,3 +555,39 @@ const unsigned char usb_logo[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char data_altitude_time[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x06, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x3f, 0xc0, 0x00, 0x7f, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x06, 0x0c, 0x00, 0x06, 0x0c, 0x00, 0x06, 0x1e, 0x00, 0x06, 0x1e, 0x00, 0x06, 0x0c, 0x00, 0x06, 0x0c, 0x00, + 0x1f, 0x8e, 0x00, 0x1f, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char data_altitude_peak[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x06, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x3f, 0xc0, 0x00, 0x7f, 0xe0, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x1f, 0x80, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char data_drogue_speed[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x1f, 0xc0, 0x00, + 0x10, 0x40, 0x00, 0x10, 0x40, 0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0x00, 0x08, 0x80, 0x00, + 0x08, 0x80, 0x00, 0x05, 0x00, 0x00, 0x05, 0x06, 0x60, 0x02, 0x06, 0x60, 0x02, 0x06, 0x60, 0x02, 0x07, 0xe0, + 0x02, 0x03, 0xc0, 0x02, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char data_main_speed[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x0f, 0xfe, 0x00, + 0x1f, 0xff, 0x00, 0x3f, 0xff, 0x80, 0x7f, 0xff, 0xc0, 0x7f, 0xff, 0xc0, 0x20, 0x00, 0x80, 0x10, 0x01, 0x00, + 0x08, 0x02, 0x00, 0x04, 0x04, 0x00, 0x02, 0x08, 0xcc, 0x01, 0x10, 0xcc, 0x00, 0xa0, 0xcc, 0x00, 0x40, 0xfc, + 0x00, 0x40, 0x78, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char data_flight_time[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, + 0x01, 0xff, 0x00, 0x03, 0x83, 0x80, 0x06, 0x10, 0xc0, 0x06, 0x10, 0xc0, 0x0c, 0x10, 0x60, 0x0c, 0x10, 0x60, + 0x0c, 0x1c, 0x60, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x60, 0x06, 0x00, 0xc0, 0x06, 0x00, 0xc0, 0x03, 0x83, 0x80, + 0x01, 0xff, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char data_speed[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x03, 0xff, 0x80, 0x07, 0x01, 0xc0, 0x0e, 0x00, 0xe0, 0x0c, 0x00, 0x60, 0x18, 0x00, 0x30, 0x18, 0x01, 0xb0, + 0x18, 0x03, 0x30, 0x18, 0x06, 0x30, 0x18, 0x0c, 0x30, 0x18, 0x38, 0x30, 0x0c, 0x38, 0x60, 0x0c, 0x00, 0x60, + 0x0f, 0xff, 0xe0, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/ground_station/src/hmi/hmi.cpp b/ground_station/src/hmi/hmi.cpp index c436d46e..c5fb8282 100644 --- a/ground_station/src/hmi/hmi.cpp +++ b/ground_station/src/hmi/hmi.cpp @@ -5,6 +5,7 @@ #include "hmi.hpp" #include "console.hpp" +#include "logging/flightStatistics.hpp" #include "navigation.hpp" #include "telemetry/telemetry.hpp" #include "utils.hpp" @@ -317,12 +318,70 @@ void Hmi::testing() { /* DATA */ -void Hmi::initData() { window.initData(); } +void Hmi::initData() { + dataFileCount = recorder.getFileCount(); + + if (dataFileCount > 0) { + dataIndex = 0; + window.initData(true); + char fileName[30] = {}; + recorder.getFileNameByIndex(0, fileName); + window.dataHighlight(fileName, dataIndex, true); + for (uint8_t i = 1; i < dataFileCount; i++) { + recorder.getFileNameByIndex(i, fileName); + window.listFileName(fileName, i); + } + } else { + window.initData(false); + } + window.refresh(); +} void Hmi::data() { - if (backButton.wasPressed()) { - state = MENU; - window.initMenu(menuIndex); + if (dataFlightStatistic) { + if (backButton.wasPressed()) { + dataFlightStatistic = false; + initData(); + } + } else { + if (backButton.wasPressed()) { + state = MENU; + window.initMenu(menuIndex); + } + if (downButton.wasPressed() && dataIndex < (dataFileCount - 1)) { + dataIndex++; + char fileName[30] = {}; + if (dataIndex >= 1) { + recorder.getFileNameByIndex(dataIndex - 1, fileName); + window.dataHighlight(fileName, dataIndex - 1, false); + } + recorder.getFileNameByIndex(dataIndex, fileName); + window.dataHighlight(fileName, dataIndex, true); + window.refresh(); + } + if (upButton.wasPressed() && dataIndex > 0) { + dataIndex--; + char fileName[30] = {}; + if (dataIndex < (dataFileCount - 1)) { + recorder.getFileNameByIndex(dataIndex + 1, fileName); + window.dataHighlight(fileName, dataIndex + 1, false); + } + recorder.getFileNameByIndex(dataIndex, fileName); + window.dataHighlight(fileName, dataIndex, true); + window.refresh(); + } + + if (okButton.wasPressed()) { + FlightStatistics stats1; + FlightStatistics stats2; + char fileName[30] = {}; + const char *directory = recorder.getDirectory(); + recorder.getFileNameByIndex(dataIndex, fileName); + stats1.parseFlightLog(directory, fileName, 1U); + stats2.parseFlightLog(directory, fileName, 2U); + dataFlightStatistic = true; + window.dataShowFlightStatistics(stats1, stats2); + } } } diff --git a/ground_station/src/hmi/hmi.hpp b/ground_station/src/hmi/hmi.hpp index ac213ee8..c5399deb 100644 --- a/ground_station/src/hmi/hmi.hpp +++ b/ground_station/src/hmi/hmi.hpp @@ -104,6 +104,10 @@ class Hmi { int16_t menuIndex = 0; + uint8_t dataIndex = 0; + uint8_t dataFileCount = 0; + bool dataFlightStatistic = false; + uint32_t flashFreeMemory = 100; bool link1Log = false; diff --git a/ground_station/src/hmi/window.cpp b/ground_station/src/hmi/window.cpp index e87b1243..e3632ad9 100644 --- a/ground_station/src/hmi/window.cpp +++ b/ground_station/src/hmi/window.cpp @@ -244,7 +244,7 @@ void Window::initLive() { display.drawLine(0, 49, 400, 49, BLACK); display.drawBitmap(5, 50, live_altitude, 24, 24, BLACK); - display.drawBitmap(5, 75, live_speed, 24, 24, BLACK); + display.drawBitmap(5, 75, data_speed, 24, 24, BLACK); display.drawBitmap(5, 100, live_lat, 24, 24, BLACK); display.drawBitmap(5, 125, live_lon, 24, 24, BLACK); display.drawBitmap(3, 150, live_battery, 24, 24, BLACK); @@ -256,7 +256,7 @@ void Window::initLive() { display.drawBitmap(358, 149, live_two, 24, 24, BLACK); display.drawBitmap(205, 50, live_altitude, 24, 24, BLACK); - display.drawBitmap(205, 75, live_speed, 24, 24, BLACK); + display.drawBitmap(205, 75, data_speed, 24, 24, BLACK); display.drawBitmap(205, 100, live_lat, 24, 24, BLACK); display.drawBitmap(205, 125, live_lon, 24, 24, BLACK); display.drawBitmap(203, 150, live_battery, 24, 24, BLACK); @@ -825,10 +825,12 @@ void Window::updateTesting(int16_t index) { display.refresh(); } -void Window::initData() { +void Window::initData(bool fileAvailable) { clearMainScreen(); - drawCentreString("Coming soon...", 200, 100); - display.refresh(); + if (!fileAvailable) { + drawCentreString("No flight logs found!", 200, 100); + display.refresh(); + } } void Window::initSensors() { @@ -1329,3 +1331,108 @@ void Window::updateKeyboardText(char *text, uint16_t color) { * Clears everything except the status bar. */ void Window::clearMainScreen() { display.fillRect(0, 19, 400, 222, WHITE); } + +void Window::listFileName(const char *fileName, uint16_t index, uint16_t color) { + display.setFont(&FreeSans9pt7b); + display.setTextSize(1); + display.setTextColor(color); + display.setCursor(10, static_cast(33 + 20 * index)); + display.print(fileName); +} + +void Window::dataHighlight(const char *fileName, uint8_t index, bool highlight) { + display.fillRect(0, static_cast(19 + 20 * index), 400, 20, highlight ? BLACK : WHITE); + listFileName(fileName, index, highlight ? WHITE : BLACK); +} + +void Window::dataShowFlightStatistics(FlightStatistics &stats1, FlightStatistics &stats2) { + clearMainScreen(); + display.setTextColor(BLACK); + display.setTextSize(1); + display.setFont(&FreeSans12pt7b); + + display.drawLine(199, 18, 199, 240, BLACK); + display.drawLine(200, 18, 200, 240, BLACK); + + dataShowFlightStatisticsSide(stats1, 0); + dataShowFlightStatisticsSide(stats2, 1); + + display.setFont(nullptr); + display.refresh(); +} + +void Window::dataShowFlightStatisticsSide(FlightStatistics &stats, uint16_t index) { + const auto xOffset = static_cast(index * 200); + + // Max altitude + display.drawBitmap(static_cast(xOffset + 9), 25, data_altitude_peak, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 45); + const int32_t altitude_m = stats.getMaxAltitude(); + if (systemConfig.config.unitSystem == UnitSystem::kMetric) { + display.print(altitude_m); + display.print(" m"); + } else { + display.print(Utils::MetersToFeet(altitude_m)); + display.print(" ft"); + } + + // Time to apogee + display.drawBitmap(static_cast(xOffset + 9), 50, data_altitude_time, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 70); + display.print(stats.getTimeToApogee(), 1); + display.print(" s"); + + // Max speed + display.drawBitmap(static_cast(xOffset + 5), 75, data_speed, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 95); + const int32_t velocity_ms = stats.getMaxVelocity(); + if (systemConfig.config.unitSystem == UnitSystem::kMetric) { + display.print(velocity_ms); + display.print(" m/s"); + } else { + display.print(Utils::MetersToFeet(velocity_ms)); + display.print(" ft/s"); + } + + // Drogue descent rate + display.drawBitmap(static_cast(xOffset + 8), 100, data_drogue_speed, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 120); + const float drogue_velocity_ms = stats.getDrogueDescentRate(); + if (systemConfig.config.unitSystem == UnitSystem::kMetric) { + display.print(drogue_velocity_ms, 1); + display.print(" m/s"); + } else { + display.print(Utils::MetersToFeet(drogue_velocity_ms), 1); + display.print(" ft/s"); + } + + // Main descent rate + display.drawBitmap(static_cast(xOffset + 5), 125, data_main_speed, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 145); + const float main_velocity_ms = stats.getMainDescentRate(); + if (systemConfig.config.unitSystem == UnitSystem::kMetric) { + display.print(main_velocity_ms, 1); + display.print(" m/s"); + } else { + display.print(Utils::MetersToFeet(main_velocity_ms), 1); + display.print(" ft/s"); + } + + // Latitude + display.drawBitmap(static_cast(xOffset + 5), 150, live_lat, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 170); + display.print(stats.getLastLatitude(), 4); + display.print(" N"); + + // Longitude + display.drawBitmap(static_cast(xOffset + 5), 175, live_lon, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 195); + display.print(stats.getLastLongitude(), 4); + display.print(" E"); + + // Flight Time + display.drawBitmap(static_cast(xOffset + 5), 200, data_flight_time, 24, 24, BLACK); + display.setCursor(static_cast(xOffset + 45), 220); + display.print(stats.getFlightTime(), 1); + display.print(" s"); +} diff --git a/ground_station/src/hmi/window.hpp b/ground_station/src/hmi/window.hpp index dabd4256..b0141c3f 100644 --- a/ground_station/src/hmi/window.hpp +++ b/ground_station/src/hmi/window.hpp @@ -7,6 +7,7 @@ #include #include +#include "logging/flightStatistics.hpp" #include "navigation.hpp" #include "settings.hpp" #include "telemetry/telemetryData.hpp" @@ -57,7 +58,7 @@ class Window { void updateTesting(int16_t index); void initTestingBox(int16_t index); - void initData(); + void initData(bool fileAvailable); void initSensors(); void initSensorPrepareCalibrate(); @@ -75,6 +76,10 @@ class Window { void initKeyboard(char *text, uint32_t maxLength = 0); void updateKeyboard(char *text, int32_t keyHighlight, bool keyPressed = false); + void listFileName(const char *fileName, uint16_t index, uint16_t color = BLACK); + void dataHighlight(const char *fileName, uint8_t index, bool highlight); + void dataShowFlightStatistics(FlightStatistics &stats1, FlightStatistics &stats2); + void refresh() { display.refresh(); } static constexpr uint8_t kShiftIdx = 29; @@ -92,6 +97,8 @@ class Window { void highlightKeyboardKey(int32_t key, uint16_t color); void updateKeyboardText(char *text, uint16_t color); + void dataShowFlightStatisticsSide(FlightStatistics &stats, uint16_t index); + void clearMainScreen(); Adafruit_SharpMem display;