Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GS] Add data screen with flight statistics #386

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions ground_station/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ void Config::load() {
}
if (!systemParser.getUnitSystem(config.unitSystem)) {
config.unitSystem = UnitSystem::kMetric;
} else {
console.log.println(unit_map[static_cast<uint8_t>(config.unitSystem)]);
}

config.neverStopLogging = stop;
Expand Down
43 changes: 36 additions & 7 deletions ground_station/src/hmi/bmp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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};
81 changes: 74 additions & 7 deletions ground_station/src/hmi/hmi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@

#include "hmi.hpp"

#include <TimeLib.h>
#include <freertos/task.h>
#include <algorithm>

#include "console.hpp"
#include "logging/flightStatistics.hpp"
#include "navigation.hpp"
#include "telemetry/telemetry.hpp"
#include "utils.hpp"

#include <TimeLib.h>
#include <freertos/task.h>

// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables)
extern Telemetry link1;
extern Telemetry link2;
Expand Down Expand Up @@ -317,12 +319,77 @@ void Hmi::testing() {

/* DATA */

void Hmi::initData() { window.initData(); }
void Hmi::initData() {
dataFileCount = recorder.getFileCount();

// The display can show a maximum of 11 entries, no scrolling implemented!
// It is highly unlikely to get more than 11 flight logs because the flash is quite small
Comment on lines +325 to +326
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we do have more than 11 files, do we display only the newest or oldest files?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are sorted alphabetically, with how the flights are currently names, it would show the 11 oldest flights

dataFileCount = std::min<decltype(dataFileCount)>(dataFileCount, 11);

if (dataFileCount > 0) {
window.initData(true);
char fileName[30] = {};
for (uint8_t i = 0; i < dataFileCount; i++) {
recorder.getFileNameByIndex(i, fileName);
if (i == dataIndex) {
window.dataHighlight(fileName, i, true);
} else {
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);
dataIndex = 0;
}
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() && (dataFileCount > 0)) {
FlightStatistics stats1;
FlightStatistics stats2;
char fileName[30] = {};
// NOLINTNEXTLINE(cppcoreguidelines-init-variables) not sure why...
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);
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions ground_station/src/hmi/hmi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
119 changes: 114 additions & 5 deletions ground_station/src/hmi/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -825,10 +825,15 @@ 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) {
display.setTextSize(1);
display.setFont(&FreeSans12pt7b);
display.setTextColor(BLACK);
drawCentreString("No flight logs found!", 200, 100);
display.refresh();
}
}

void Window::initSensors() {
Expand Down Expand Up @@ -1329,3 +1334,107 @@ 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<int16_t>(33 + 20 * index));
display.print(fileName);
}

void Window::dataHighlight(const char *fileName, uint8_t index, bool highlight) {
display.fillRect(0, static_cast<int16_t>(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.refresh();
}

void Window::dataShowFlightStatisticsSide(FlightStatistics &stats, uint16_t index) {
const auto xOffset = static_cast<int16_t>(index * 200);

// Max altitude
display.drawBitmap(static_cast<int16_t>(xOffset + 9), 25, data_altitude_peak, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(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<int16_t>(xOffset + 9), 50, data_altitude_time, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(xOffset + 45), 70);
display.print(stats.getTimeToApogee(), 1);
display.print(" s");

// Max speed
display.drawBitmap(static_cast<int16_t>(xOffset + 5), 75, data_speed, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(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<int16_t>(xOffset + 8), 100, data_drogue_speed, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(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<int16_t>(xOffset + 5), 125, data_main_speed, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(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<int16_t>(xOffset + 5), 150, live_lat, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(xOffset + 45), 170);
display.print(stats.getLastLatitude(), 4);
display.print(" N");

// Longitude
display.drawBitmap(static_cast<int16_t>(xOffset + 5), 175, live_lon, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(xOffset + 45), 195);
display.print(stats.getLastLongitude(), 4);
display.print(" E");

// Flight Time
display.drawBitmap(static_cast<int16_t>(xOffset + 5), 200, data_flight_time, 24, 24, BLACK);
display.setCursor(static_cast<int16_t>(xOffset + 45), 220);
display.print(stats.getFlightTime(), 1);
display.print(" s");
}
9 changes: 8 additions & 1 deletion ground_station/src/hmi/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Adafruit_GFX.h>
#include <Adafruit_SharpMem.h>

#include "logging/flightStatistics.hpp"
#include "navigation.hpp"
#include "settings.hpp"
#include "telemetry/telemetryData.hpp"
Expand Down Expand Up @@ -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();
Expand All @@ -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;
Expand All @@ -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;
Expand Down
Loading
Loading