I will clean this mess but for now yay for the relative
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#include "UIString.h"
|
||||
#include "HardwareSerial.h"
|
||||
#include "UIComponent.h"
|
||||
#include <Arduino_GFX.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "data.h"
|
||||
#include <Arduino.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
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);
|
||||
}
|
||||
+22
-10
@@ -3,12 +3,23 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
||||
|
||||
+138
-34
@@ -8,11 +8,13 @@
|
||||
#include "debug/debug.h"
|
||||
#include "displaySetup.h"
|
||||
#include "esp32-hal-psram.h"
|
||||
#include "esp_system.h"
|
||||
#include "ui.h"
|
||||
#include <Arduino.h>
|
||||
#include <Arduino_GFX_Library.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
|
||||
#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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user