From 4c57028874fbbc80859218acc1e2d4e3c65a8534 Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Thu, 10 Apr 2025 23:27:22 +0100 Subject: [PATCH] I will clean this mess but for now yay for the relative --- lib/cursesAtHome/src/UIComponent.cpp | 13 +- lib/cursesAtHome/src/UIString.cpp | 11 +- lib/cursesAtHome/src/UIString.h | 2 +- lib/cursesAtHome/src/UITable.cpp | 41 +++---- lib/cursesAtHome/src/UITable.h | 2 +- src/data.cpp | 40 +++++++ src/data.h | 32 +++-- src/main.cpp | 172 +++++++++++++++++++++------ src/ui.h | 8 +- 9 files changed, 240 insertions(+), 81 deletions(-) create mode 100644 src/data.cpp diff --git a/lib/cursesAtHome/src/UIComponent.cpp b/lib/cursesAtHome/src/UIComponent.cpp index 0adb5a8..0a60bd7 100644 --- a/lib/cursesAtHome/src/UIComponent.cpp +++ b/lib/cursesAtHome/src/UIComponent.cpp @@ -25,15 +25,6 @@ int16_t UIElement::getContentAreaX0() { int16_t UIElement::getContentAreaY0() { if (this->decor->hasBorder) { - Serial2.print("Value to return: "); - Serial2.print(this->dims.y); - Serial2.print(" + "); - Serial2.print(this->getTitleAreaHeight()); - Serial2.print(" + "); - Serial2.print(DEFAULT_TITLE_CONTENT_SPACING); - Serial2.print(" = "); - Serial2.println(this->dims.y + this->getTitleAreaHeight() + - DEFAULT_TITLE_CONTENT_SPACING); return this->dims.y + this->getTitleAreaHeight() + DEFAULT_TITLE_CONTENT_SPACING; } @@ -80,8 +71,10 @@ void UIElement::replaceString(char *oldVal, char *newVal) { size_t newValLen = strlen(newVal); size_t oldValLen = strlen(oldVal); + // It crashs somewhere around here int16_t x0 = this->getContentAreaX0(); - int16_t y0 = this->getContentAreaY0(); + int16_t y0 = this->getContentAreaY0(); // <- Crashes here + // Before here this->display->setTextSize(this->decor->textSize); diff --git a/lib/cursesAtHome/src/UIString.cpp b/lib/cursesAtHome/src/UIString.cpp index b042031..66c0198 100644 --- a/lib/cursesAtHome/src/UIString.cpp +++ b/lib/cursesAtHome/src/UIString.cpp @@ -1,15 +1,18 @@ #include "UIString.h" +#include "HardwareSerial.h" #include "UIComponent.h" #include UIString::UIString() : UIElement(nullptr, {0, 0, 0, 0}, nullptr, (char *)"") { this->type = STRING; + memset(this->value, 0, this->bufferSize); } UIString::UIString(Arduino_GFX *d, UIDimensions dims, UIDecorations *decor, char *title) : UIElement(d, dims, decor, title) { this->type = STRING; + memset(this->value, 0, this->bufferSize); } void UIString::Update(const char *v) { @@ -30,13 +33,17 @@ void UIString::Update(const char *v) { } char newVal[this->bufferSize]; + memset(newVal, 0, this->bufferSize); + // strncpy(newVal, v, this->bufferSize - 1); sprintf(newVal, "%s", v); char oldVal[this->bufferSize]; + memset(oldVal, 0, this->bufferSize); + // strncpy(oldVal, v, this->bufferSize - 1); sprintf(oldVal, "%s", this->value); // Figure out the x0 and y0 for the text - replaceString(oldVal, newVal); - + replaceString(oldVal, newVal); // <- It crashes here somewhere + // strncpy(this->value, v, this->bufferSize); } diff --git a/lib/cursesAtHome/src/UIString.h b/lib/cursesAtHome/src/UIString.h index fac90fc..883664e 100644 --- a/lib/cursesAtHome/src/UIString.h +++ b/lib/cursesAtHome/src/UIString.h @@ -5,7 +5,7 @@ // Representation of single line strings struct UIString : UIElement { - static const size_t bufferSize = 256; + static const size_t bufferSize = 64; char value[bufferSize]; UIString(); diff --git a/lib/cursesAtHome/src/UITable.cpp b/lib/cursesAtHome/src/UITable.cpp index ebe8656..1b8a82e 100644 --- a/lib/cursesAtHome/src/UITable.cpp +++ b/lib/cursesAtHome/src/UITable.cpp @@ -10,19 +10,18 @@ UITable::UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor, char *title) : UIElement(gfx, dims, decor, title) { this->type = TABLE; - + this->tableData = new UIString*[ROWS * COLUMNS]; + // Default decoration for every cell - UIDecorations *cellDecor = new UIDecorations(); - cellDecor->textSize = 2; this->decor->textSize = 2; for (int k = 0; k < ROWS * COLUMNS; k++) { - this->tableData[k].decor = cellDecor; - this->tableData[k].dims.x = 0; - this->tableData[k].dims.y = 0; - this->tableData[k].dims.width = 0; - this->tableData[k].dims.height = 0; - this->tableData[k].display = this->display; + UIDecorations *cellDecor = new UIDecorations(); + cellDecor->textSize = this->decor->textSize; + + UIDimensions dims = {0, 0, 0, 0}; + + this->tableData[k] = new UIString(display, dims, cellDecor, (char *)""); } int cellH = CHR_HEIGHT(this->decor->textSize) + CELL_MARGIN; @@ -32,7 +31,7 @@ UITable::UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor, DEFAULT_MARGIN + DEFAULT_BORDER_THICKNESS; this->dims.width = (DEFAULT_BORDER_THICKNESS + DEFAULT_MARGIN) * 2 + - (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN) * (3 + 24 + 5); + (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN) * (3 + 18 + 12); } uint16_t UITable::getContentAreaHeight() { @@ -48,8 +47,8 @@ uint16_t UITable::getContentAreaHeight() { void UITable::setup() { // Define the cell dimensions int tableCellW[] = {3 * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN), - 24 * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN), - 5 * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN)}; + 18 * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN), + 12 * (CHR_WIDTH(this->decor->textSize) + CELL_MARGIN)}; int cellH = CHR_HEIGHT(this->decor->textSize) + CELL_MARGIN; // Initialize the cells @@ -57,18 +56,20 @@ void UITable::setup() { for (int r = 0; r < ROWS; r++) { int16_t xOffset = this->getContentAreaX0(); for (int c = 0; c < COLUMNS; c++) { - this->tableData[r * COLUMNS + c].decor->textSize = this->decor->textSize; - this->tableData[r * COLUMNS + c].decor->hasBorder = false; - this->tableData[r * COLUMNS + c].dims.x = xOffset + CELL_MARGIN; - this->tableData[r * COLUMNS + c].dims.y = (cellH * r) + yOffset; - this->tableData[r * COLUMNS + c].dims.height = cellH; - this->tableData[r * COLUMNS + c].dims.width = tableCellW[c]; + this->tableData[r * COLUMNS + c]->decor->textSize = this->decor->textSize; + this->tableData[r * COLUMNS + c]->decor->hasBorder = false; + this->tableData[r * COLUMNS + c]->dims.x = xOffset + CELL_MARGIN; + this->tableData[r * COLUMNS + c]->dims.y = (cellH * r) + yOffset; + this->tableData[r * COLUMNS + c]->dims.height = cellH; + this->tableData[r * COLUMNS + c]->dims.width = tableCellW[c]; + memset(this->tableData[r * COLUMNS + c]->value, 0, + this->tableData[r * COLUMNS + c]->bufferSize); xOffset += tableCellW[c]; #ifdef DEBUG - this->tableData[r * COLUMNS + c].drawBox(); - this->tableData[r * COLUMNS + c].Update("123"); + this->tableData[r * COLUMNS + c]->drawBox(); + this->tableData[r * COLUMNS + c]->Update("---"); #endif } } diff --git a/lib/cursesAtHome/src/UITable.h b/lib/cursesAtHome/src/UITable.h index b43b631..c43dcc2 100644 --- a/lib/cursesAtHome/src/UITable.h +++ b/lib/cursesAtHome/src/UITable.h @@ -15,7 +15,7 @@ struct UITable : UIElement { // will hold rows * columns UIStrings to fill the table int rows = ROWS; int columns = COLUMNS; - UIString tableData[ROWS * COLUMNS]; + UIString **tableData; UITable(Arduino_GFX *gfx, UIDimensions dims, UIDecorations *decor, char *t); diff --git a/src/data.cpp b/src/data.cpp new file mode 100644 index 0000000..20ca06a --- /dev/null +++ b/src/data.cpp @@ -0,0 +1,40 @@ +#include "data.h" +#include +#include +#include + +void SerializeDataPacket(DataPacket *p, uint8_t *buffer) { + size_t offset = 0; + + memcpy(&p->StartMarker, buffer + offset, 1); + offset += 1; + Serial2.printf("\rStartMarker: 0x%02x\n", p->StartMarker); + + memcpy(&p->speed, buffer + offset, speedLen); + offset += speedLen; + Serial2.printf("\rSpeed: %s\n", p->speed); + + memcpy(&p->gear, buffer + offset, gearLen); + offset += gearLen; + Serial2.printf("\rGear: %s\n", p->gear); + + memcpy(&p->rpm, buffer + offset, rpmLen); + offset += rpmLen; + Serial2.printf("\rRPM: %s\n", p->rpm); + + memcpy(&p->LapNumber, buffer + offset, lapNumberLen); + offset += lapNumberLen; + Serial2.printf("\rLapNumber: %s\n", p->LapNumber); + + memcpy(&p->currLapTime, buffer + offset, currLapTimeLen); + offset += currLapTimeLen; + Serial2.printf("\rcurrLapTime: %s\n", p->currLapTime); + + memcpy(&p->lastLapTime, buffer + offset, lastLapTimeLen); + offset += lastLapTimeLen; + Serial2.printf("\rlastLapTime: %s\n", p->lastLapTime); + + memcpy(&p->FuelEst, buffer + offset, FuelEstLen); + offset += FuelEstLen; + Serial2.printf("\rFuelEst: %s\n", p->FuelEst); +} diff --git a/src/data.h b/src/data.h index 2488530..8c9a30d 100644 --- a/src/data.h +++ b/src/data.h @@ -3,12 +3,23 @@ #include +struct DataReq { + uint8_t type; +}; + +const int speedLen = 5; +const int gearLen = 3; +const int rpmLen = 6; +const int lapNumberLen = 5; +const int currLapTimeLen = 10; +const int lastLapTimeLen = 10; const int DriverNameLen = 24; const int TimeBehindStringLen = 16; const int LapStringLen = 4; const int FuelTankLen = 15; const int FuelEstLen = 15; +#pragma pack(push, 1) struct StandingLine { char Lap[LapStringLen]; char DriverName[DriverNameLen]; @@ -16,18 +27,19 @@ struct StandingLine { }; struct DataPacket { - int32_t speed; - int32_t gear; - int32_t rpm; - char LapNumber[5]; - // char lapDelta[10]; - char currLapTime[10]; - // char bestLapTime[10]; - char lastLapTime[10]; - // char FuelTank[FuelTankLen]; + uint8_t StartMarker; + char speed[speedLen]; + char gear[gearLen]; + char rpm[rpmLen]; + char LapNumber[lapNumberLen]; + char currLapTime[currLapTimeLen]; + char lastLapTime[lastLapTimeLen]; char FuelEst[FuelEstLen]; - // int32_t position; StandingLine standings[5]; + uint8_t EndMarker; }; +#pragma pack(pop) + +void SerializeDataPacket(DataPacket *p, uint8_t *buffer); #endif diff --git a/src/main.cpp b/src/main.cpp index 1cead81..3334cd1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,11 +8,13 @@ #include "debug/debug.h" #include "displaySetup.h" #include "esp32-hal-psram.h" +#include "esp_system.h" #include "ui.h" #include #include #include #include +#include #define UART1_TX 19 #define UART1_RX 18 @@ -69,6 +71,7 @@ void setup() { // Initialize the debug serial object Serial2.begin(115200, SERIAL_8N1, UART1_RX, UART1_TX); + Serial2.flush(); Serial2.println(F("=== ESP32 SimRacing DashDisplay ===")); @@ -83,6 +86,7 @@ void setup() { // relative.dims.y = 250; relative.setup(); relative.drawBox(); + ui->relative = &relative; // Setup the rpmText box rpmTextDecor->textSize = 7; @@ -90,19 +94,20 @@ void setup() { calculateHeight(rpmTextDecor->titleSize, rpmTextDecor->textSize, 1); rpmText.dims.width = calculateWidth(rpmTextDecor->textSize, 5); rpmText.horizontalCenter(); - ui->rpmText = &rpmText; - ui->rpmText->drawBox(); - ui->rpmText->Update("12345"); + ui->digiTacho = &rpmText; + ui->digiTacho->drawBox(); + ui->digiTacho->Update("12345"); // Setup the speedText box speedTextDecor->textSize = 4; speedText.dims.height = - calculateHeight(speedTextDecor->titleSize, speedTextDecor->textSize, 1); + calculateHeight(speedTextDecor->titleSize, speedTextDecor->textSize, + 1); speedText.dims.width = calculateWidth(speedTextDecor->textSize, 4); speedText.placeRight(&rpmText); - ui->speedText = &speedText; - ui->speedText->drawBox(); - ui->speedText->Update("253"); + ui->digiSpeedo = &speedText; + ui->digiSpeedo->drawBox(); + ui->digiSpeedo->Update("253"); // Setup the gear text box gearTextDecor->textSize = 7; @@ -111,9 +116,9 @@ void setup() { gearText.dims.width = calculateWidth(gearTextDecor->textSize, 2); gearText.horizontalCenter(); gearText.dims.y = rpmText.dims.height + 5; - ui->gearText = &gearText; - ui->gearText->drawBox(); - ui->gearText->Update("3"); + ui->digiGear = &gearText; + ui->digiGear->drawBox(); + ui->digiGear->Update("3"); // Setup the best lap box bestLapDecor->textSize = 3; @@ -164,46 +169,145 @@ void setup() { ui->fuelConsumption = &fuelConsumption; ui->fuelConsumption->drawBox(); ui->fuelConsumption->Update("10.4 | 11.2"); + + // Connect to ESDI + // Serial2.println("Waiting for ESDI signal"); + // uint8_t buffer[sizeof(DataReq)]; + // size_t bufferIndex = 0; + // bool ready = false; + // while (!ready) { + // while (Serial.available() > 0) { + // buffer[bufferIndex] = Serial.read(); + // bufferIndex++; + // + // if (bufferIndex >= sizeof(DataReq)) { + // // Copy the buffer into the struct + // DataReq packet; + // memcpy(&packet, buffer, sizeof(DataReq)); + // + // // Reset the buffer index + // bufferIndex = 0; + // + // Serial2.print("Received msg from ESDI: "); + // Serial2.println(packet.type); + // + // if (packet.type == 3) { + // ready = true; + // break; + // } + // } + // } + // } + + // const char *words[] = {"hel", "wor", "why", "is", "thi", "hap", "to", + // "me"}; + // + // int wIndex = 0; + // while (1) { + // for (int row = 0; row < ROWS; row++) { + // for (int col = 0; col < COLUMNS; col++) { + // ui->relative->tableData[row * COLUMNS + + // col]->Update(words[wIndex++]); if (wIndex >= 8) { + // wIndex = 0; + // } + // } + // } + // } + + Serial2.println("* Ready for loop"); } uint64_t lastDataRead = 0; uint8_t packetBuffer[sizeof(DataPacket)]; int bufferIndex = 0; +void debugDataPacket(DataPacket *p) { + Serial2.printf("\rSize: %zu\n", sizeof(struct DataPacket)); + Serial2.printf("\rStartMarker: 0x%02x\n", p->StartMarker); + Serial2.printf("\rSpeed: %s\n", p->speed); + Serial2.printf("\rGear: %s\n", p->gear); + Serial2.printf("\rRPM: %s\n", p->rpm); + Serial2.printf("\rLapNumber: %s\n", p->LapNumber); + Serial2.printf("\rcurrLapTime: %s\n", p->currLapTime); + Serial2.printf("\rlastLapTime: %s\n", p->lastLapTime); + Serial2.printf("\rfuelEst: %s\n", p->FuelEst); + Serial2.printf("\rStandings:\n"); + for (int k = 0; k < 5; k++) { + Serial2.printf("\r Lap: %s\n", p->standings[k].Lap); + Serial2.printf("\r DriverName: %s\n", p->standings[k].DriverName); + Serial2.printf("\r TimeBehind: %s\n", p->standings[k].TimeBehindString); + } + Serial2.printf("\rEndMarker: 0x%02x\n\n", p->EndMarker); +} + +bool isReceiving = false; void loop(void) { - // Read bytes one by one + // Request data here + DataReq req = {5}; + Serial.write((uint8_t *)&req, sizeof(req)); + Serial.flush(); + + // Receive data while (Serial.available() > 0) { - packetBuffer[bufferIndex] = Serial.read(); - bufferIndex++; + uint8_t byte = Serial.read(); + + if (!isReceiving) { + if (byte == 0x02) { + isReceiving = true; + bufferIndex = 0; + } + } + packetBuffer[bufferIndex++] = byte; - // Check if we have a complete packet if (bufferIndex >= sizeof(DataPacket)) { - // Copy the buffer into the struct + Serial.flush(); + bufferIndex = 0; + isReceiving = false; + DataPacket packet; + // SerializeDataPacket(&packet, packetBuffer); memcpy(&packet, packetBuffer, sizeof(DataPacket)); - // Reset the buffer index - bufferIndex = 0; - - // Process the packet - // if (millis() - lastDataPrint > 50) { - // debugDataPacket(&packet); - // lastDataPrint = millis(); + if (packet.EndMarker != 0x03) { + // Serial2.println(F("\r////////////// DATA IS MALFORMED + // //////////////")); + continue; + } + // for(int k = 0; k < sizeof(DataPacket); k++) { + // if (k % 8 == 0) { + // Serial2.printf("\r\n"); + // } + // Serial2.printf(" 0x%02x", packetBuffer[k]); // } + // Serial2.printf("\r\n"); - // ui.speedometer->Update(packet.speed); - // - // ui.gear->Update(packet.gear); - // ui.numberTach->Update(packet.rpm); - // ui.barTach->Update(packet.rpm); + // Serial2.printf("%d / %d [%2d] || %d / %d [%2d]\n\n\r", + // ESP.getFreeHeap(), + // ESP.getHeapSize(), + // (int)(((float)(ESP.getHeapSize() - ESP.getFreeHeap()) / + // ESP.getHeapSize()) * + // 100), + // ESP.getFreePsram(), ESP.getPsramSize(), + // (int)(((float)(ESP.getPsramSize() - ESP.getFreePsram()) + // / + // ESP.getPsramSize()) * + // 100)); - // ui.relative->Update(packet.standings); - for (int k = 0; k < 15; k += 3) { - // ui.relative->tableData[k + 0].Update(packet.standings[k / 3].Lap); - // ui.relative->tableData[k + 1].Update( - // packet.standings[k / 3].DriverName); - // ui.relative->tableData[k + 2].Update( - // packet.standings[k / 3].TimeBehindString); + // debugDataPacket(&packet); + + ui->digiSpeedo->Update(packet.speed); + ui->digiTacho->Update(packet.rpm); + ui->digiGear->Update(packet.gear); + ui->curLap->Update(packet.currLapTime); + ui->lastLap->Update(packet.lastLapTime); + + for (int row = 0; row < ROWS; row++) { + ui->relative->tableData[row * COLUMNS + 0]->Update( + packet.standings[row].Lap); + ui->relative->tableData[row * COLUMNS + 1]->Update( + packet.standings[row].DriverName); + ui->relative->tableData[row * COLUMNS + 2]->Update( + packet.standings[row].TimeBehindString); } lastDataRead = millis(); diff --git a/src/ui.h b/src/ui.h index 710aa6e..18f263d 100644 --- a/src/ui.h +++ b/src/ui.h @@ -3,16 +3,18 @@ #include "Arduino_GFX.h" #include "UIString.h" +#include "UITable.h" struct DashUI { - UIString *rpmText; - UIString *speedText; - UIString *gearText; + UIString *digiTacho; + UIString *digiSpeedo; + UIString *digiGear; UIString *bestLap; UIString *lastLap; UIString *curLap; UIString *fuelTank; UIString *fuelConsumption; + UITable *relative; DashUI(); void dashUISetup(Arduino_GFX *gfx);