Make DriverView fields more modular

This commit is contained in:
2023-03-20 19:35:30 +01:00
parent f0254b92ee
commit c8ee51a78f
31 changed files with 1554 additions and 109 deletions

View File

@ -0,0 +1,36 @@
#ifndef DATAFIELD_HPP
#define DATAFIELD_HPP
#include "touchgfx/TypedText.hpp"
#include <stddef.h>
#include <stdint.h>
// We want to automatically count the number of data field types for the
// description array. This is wacky preprocessor magic that allows us to do just
// that. Unfortunately, it doesn't work with enum classes, so we have to use
// C-style enums.
#define CountedEnum(NAME, TYPE, ...) \
enum NAME : TYPE { __VA_ARGS__ }; \
constexpr size_t NAME##_COUNT = sizeof((int[]){__VA_ARGS__}) / sizeof(int);
CountedEnum(DataFieldType, size_t, DF_TSState, DF_ASState, DF_ActiveMission,
DF_R2DProgress, DF_INVLReady, DF_INVRReady, DF_SDC, DF_ERR,
DF_IniChkState, DF_LapCount, DF_TireTempFL, DF_TireTempFR,
DF_TireTempRL, DF_TireTempRR, DF_MinCellVolt, DF_MaxCellTemp,
DF_TSSoC, DF_LVSoC, DF_TSCurrent, DF_TSVoltageBat, DF_TSVoltageVeh,
DF_Speed, DF_BBal);
enum class DataFieldKind { Numeric, Bool, Text };
struct DataFieldDescription {
DataFieldKind kind;
touchgfx::TypedText title;
size_t int_digits;
size_t decimal_digits;
void* (*getValue)(void);
};
extern DataFieldDescription dataFieldDescs[];
#endif // DATAFIELD_HPP

View File

@ -5,6 +5,8 @@
#include "touchgfx/Unicode.hpp"
#include <gui_generated/containers/DriverViewFieldBase.hpp>
#include "gui/common/DataField.hpp"
class DriverViewField : public DriverViewFieldBase {
public:
DriverViewField();
@ -12,16 +14,20 @@ public:
virtual void initialize();
void setName(const touchgfx::TypedText &text);
void setType(const DataFieldDescription &desc);
void setValue(float newValue);
void setPrecision(size_t intDigits, size_t decimalDigits);
void setValue(const char *str);
void setValue(int boolValue);
protected:
private:
Unicode::UnicodeChar valueBuffer[16];
DataFieldKind fieldKind;
size_t intDigits;
size_t decimalDigits;
float fieldValue;
float floatValue;
int boolValue;
void updateValueBuffer();
};

View File

@ -4,6 +4,8 @@
#include <gui/model/ModelListener.hpp>
#include <mvp/Presenter.hpp>
#include "gui/common/DataField.hpp"
using namespace touchgfx;
class DriverViewView;
@ -33,6 +35,8 @@ private:
DriverViewPresenter();
DriverViewView &view;
DataFieldType fields[3];
};
#endif // DRIVERVIEWPRESENTER_HPP

View File

@ -1,6 +1,7 @@
#ifndef DRIVERVIEWVIEW_HPP
#define DRIVERVIEWVIEW_HPP
#include "gui/common/DataField.hpp"
#include "vehicle.h"
#include <gui/driverview_screen/DriverViewPresenter.hpp>
#include <gui_generated/driverview_screen/DriverViewViewBase.hpp>
@ -12,11 +13,17 @@ public:
virtual void setupScreen();
virtual void tearDownScreen();
void setFieldType(size_t i, const DataFieldDescription &desc);
void setFieldValue(size_t i, float value);
void setFieldValue(size_t i, const char *value);
void setFieldValue(size_t i, int value);
void setTireTemps(const TireTemps &temps);
void setTSSoC(uint8_t soc);
void setMinCellVolt(float v);
protected:
private:
DriverViewField &getField(size_t i);
};
#endif // DRIVERVIEWVIEW_HPP

View File

@ -0,0 +1,110 @@
#include "gui/common/DataField.hpp"
#include "texts/TextKeysAndLanguages.hpp"
#include "vehicle.h"
#define VEH_FIELD(FIELD) []() { return (void *)&vehicle_state.FIELD; }
#define VEH_BIT_FIELD(FIELD) \
[]() { \
static int x; \
x = vehicle_state.FIELD; \
return (void *)&x; \
}
void *get_sdc_text() {
if (vehicle_state.errors.sdc_bfl) {
return (void *)"BFL";
} else if (vehicle_state.errors.sdc_brl) {
return (void *)"BRL";
} else if (vehicle_state.errors.sdc_acc) {
return (void *)"ACC";
} else if (vehicle_state.errors.sdc_hvb) {
return (void *)"HVB";
} else {
return (void *)"CLOSED";
}
}
void *get_err_text() {
if (vehicle_state.errors.err_sdc) {
return (void *)"SDC";
} else if (vehicle_state.errors.err_ams) {
return (void *)"AMS";
} else if (vehicle_state.errors.err_pdu) {
return (void *)"PDU";
} else if (vehicle_state.errors.err_ini_chk) {
return (void *)"IniChk";
} else if (vehicle_state.errors.err_con_mon) {
return (void *)"ConMon";
} else if (vehicle_state.errors.err_scs) {
return (void *)"SCS";
} else if (vehicle_state.errors.err_sbspd) {
return (void *)"sBSPD";
} else if (vehicle_state.errors.err_appsp) {
return (void *)"APPSp";
} else if (vehicle_state.errors.err_as) {
return (void *)"AS";
} else if (vehicle_state.errors.err_ros) {
return (void *)"ROS";
} else if (vehicle_state.errors.err_res) {
return (void *)"RES";
} else if (vehicle_state.errors.err_invl) {
return (void *)"INVL";
} else if (vehicle_state.errors.err_invr) {
return (void *)"INVR";
} else {
return (void *)"NONE";
}
}
void *get_zero() {
static float zero = 0.0f;
return &zero;
}
DataFieldDescription dataFieldDescs[] = {
[DF_TSState] = {DataFieldKind::Numeric, T_FIELD_TSSTATE, 1, 0,
VEH_FIELD(ts_state)},
[DF_ASState] = {DataFieldKind::Numeric, T_FIELD_ASSTATE, 1, 0,
VEH_FIELD(as_state)},
[DF_ActiveMission] = {DataFieldKind::Numeric, T_FIELD_ACTIVEMISSION, 1, 0,
VEH_FIELD(active_mission)},
[DF_R2DProgress] = {DataFieldKind::Numeric, T_FIELD_R2DPROGRESS, 1, 0,
VEH_FIELD(r2d_progress)},
[DF_INVLReady] = {DataFieldKind::Bool, T_FIELD_INVLREADY, 0, 0,
VEH_BIT_FIELD(errors.invl_ready)},
[DF_INVRReady] = {DataFieldKind::Bool, T_FIELD_INVRREADY, 0, 0,
VEH_BIT_FIELD(errors.invr_ready)},
[DF_SDC] = {DataFieldKind::Text, T_FIELD_SDC, 0, 0, get_sdc_text},
[DF_ERR] = {DataFieldKind::Text, T_FIELD_ERR, 0, 0, get_err_text},
[DF_IniChkState] = {DataFieldKind::Numeric, T_FIELD_INICHKSTATE, 1, 0,
VEH_FIELD(ini_chk_state)},
[DF_LapCount] = {DataFieldKind::Numeric, T_FIELD_LAPCOUNT, 3, 0,
VEH_FIELD(lap_count)},
[DF_TireTempFL] = {DataFieldKind::Numeric, T_FIELD_TIREFL, 2, 1,
VEH_FIELD(tire_temps.fl)},
[DF_TireTempFR] = {DataFieldKind::Numeric, T_FIELD_TIREFR, 2, 1,
VEH_FIELD(tire_temps.fr)},
[DF_TireTempRL] = {DataFieldKind::Numeric, T_FIELD_TIRERL, 2, 1,
VEH_FIELD(tire_temps.rl)},
[DF_TireTempRR] = {DataFieldKind::Numeric, T_FIELD_TIRERR, 2, 1,
VEH_FIELD(tire_temps.rr)},
[DF_MinCellVolt] = {DataFieldKind::Numeric, T_FIELD_MINCELLVOLT, 1, 2,
VEH_FIELD(min_cell_volt)},
[DF_MaxCellTemp] = {DataFieldKind::Numeric, T_FIELD_MAXCELLTEMP, 2, 1,
VEH_FIELD(max_cell_temp)},
[DF_TSSoC] = {DataFieldKind::Numeric, T_FIELD_TSSOC, 3, 0, VEH_FIELD(soc)},
[DF_LVSoC] = {DataFieldKind::Numeric, T_FIELD_LVSOC, 3, 0, get_zero},
[DF_TSCurrent] = {DataFieldKind::Numeric, T_FIELD_TSCURRENT, 3, 0,
VEH_FIELD(ts_current)},
[DF_TSVoltageBat] = {DataFieldKind::Numeric, T_FIELD_TSVOLTBAT, 3, 1,
VEH_FIELD(ts_voltage_bat)},
[DF_TSVoltageVeh] = {DataFieldKind::Numeric, T_FIELD_TSVOLTVEH, 3, 1,
VEH_FIELD(ts_voltage_veh)},
[DF_Speed] = {DataFieldKind::Numeric, T_FIELD_SPEED, 3, 0, get_zero},
[DF_BBal] = {DataFieldKind::Numeric, T_FIELD_BBAL, 3, 1, get_zero},
};
static_assert(sizeof(dataFieldDescs) / sizeof(dataFieldDescs[0]) ==
DataFieldType_COUNT,
"Incorrect number of data field descriptions");

View File

@ -1,35 +1,72 @@
#include "gui/common/DataField.hpp"
#include "texts/TextKeysAndLanguages.hpp"
#include "touchgfx/Unicode.hpp"
#include <gui/containers/DriverViewField.hpp>
DriverViewField::DriverViewField()
: intDigits{0}, decimalDigits{0}, fieldValue{0} {}
: intDigits{0}, decimalDigits{0}, floatValue{0}, boolValue{0} {}
void DriverViewField::initialize() { DriverViewFieldBase::initialize(); }
void DriverViewField::setName(const touchgfx::TypedText &text) {
title.setTypedText(text);
void DriverViewField::setType(const DataFieldDescription &desc) {
title.setTypedText(desc.title);
title.invalidate();
}
void DriverViewField::setValue(float newValue) {
fieldValue = newValue;
fieldKind = desc.kind;
switch (desc.kind) {
case DataFieldKind::Numeric:
value.setTypedText(T_NUMBERWILDCARD);
break;
case DataFieldKind::Bool:
case DataFieldKind::Text:
value.setTypedText(T_DEFAULTWILDCARD);
break;
}
intDigits = desc.int_digits;
decimalDigits = desc.decimal_digits;
updateValueBuffer();
}
void DriverViewField::setPrecision(size_t intDigits, size_t decimalDigits) {
this->intDigits = intDigits;
this->decimalDigits = decimalDigits;
void DriverViewField::setValue(float newValue) {
floatValue = newValue;
updateValueBuffer();
}
void DriverViewField::setValue(const char *str) {
Unicode::strncpy(valueBuffer, str,
sizeof(valueBuffer) / sizeof(Unicode::UnicodeChar));
value.setWildcard(valueBuffer);
value.invalidate();
}
void DriverViewField::setValue(int boolValue) {
this->boolValue = boolValue;
updateValueBuffer();
}
void DriverViewField::updateValueBuffer() {
size_t width = intDigits;
if (decimalDigits != 0) {
width += decimalDigits + 1; // 1 digit for the decimal point
switch (fieldKind) {
case DataFieldKind::Numeric: {
size_t width = intDigits;
if (decimalDigits != 0) {
width += decimalDigits + 1; // 1 digit for the decimal point
}
float params[3] = {(float)width, (float)decimalDigits, floatValue};
Unicode::snprintfFloats(valueBuffer,
sizeof(valueBuffer) / sizeof(Unicode::UnicodeChar),
"%*.*f", params);
value.setWildcard(valueBuffer);
break;
}
float params[3] = {(float)width, (float)decimalDigits, fieldValue};
Unicode::snprintfFloats(valueBuffer,
sizeof(valueBuffer) / sizeof(Unicode::UnicodeChar),
"%*.*f", params);
value.setWildcard(valueBuffer);
case DataFieldKind::Bool: {
const char *str = boolValue ? "YES" : "NO";
Unicode::strncpy(valueBuffer, str,
sizeof(valueBuffer) / sizeof(valueBuffer[0]));
value.setWildcard(valueBuffer);
break;
}
case DataFieldKind::Text:
// This is updated directly in setValue()
break;
}
value.invalidate();
}

View File

@ -1,15 +1,37 @@
#include <gui/driverview_screen/DriverViewPresenter.hpp>
#include <gui/driverview_screen/DriverViewView.hpp>
#include "gui/common/DataField.hpp"
#include "vehicle.h"
DriverViewPresenter::DriverViewPresenter(DriverViewView &v) : view(v) {}
DriverViewPresenter::DriverViewPresenter(DriverViewView &v)
: view(v), fields{DF_MinCellVolt, DF_Speed, DF_TSCurrent} {}
void DriverViewPresenter::activate() {}
void DriverViewPresenter::activate() {
for (size_t i = 0; i < 3; i++) {
view.setFieldType(i, dataFieldDescs[fields[i]]);
}
}
void DriverViewPresenter::deactivate() {}
void DriverViewPresenter::vehicleStateUpdated() {
view.setTireTemps(vehicle_state.tire_temps);
view.setTSSoC(vehicle_state.soc);
view.setMinCellVolt(vehicle_state.min_cell_volt);
for (size_t i = 0; i < 3; i++) {
DataFieldType field = fields[i];
void *val = dataFieldDescs[field].getValue();
switch (dataFieldDescs[field].kind) {
case DataFieldKind::Numeric:
view.setFieldValue(i, *((float *)val));
break;
case DataFieldKind::Bool:
view.setFieldValue(i, *((int *)val));
break;
case DataFieldKind::Text:
view.setFieldValue(i, (const char *)val);
break;
}
}
}

View File

@ -1,3 +1,4 @@
#include "gui/common/DataField.hpp"
#include "texts/TextKeysAndLanguages.hpp"
#include <gui/driverview_screen/DriverViewView.hpp>
@ -5,19 +6,29 @@ DriverViewView::DriverViewView() {}
void DriverViewView::setupScreen() {
DriverViewViewBase::setupScreen();
field1.setName(T_FIELD_MINCELLVOLT);
field1.setValue(3.21);
field1.setPrecision(1, 2);
field2.setName(T_FIELD_SPEED);
field2.setValue(42.0);
field2.setPrecision(3, 0);
field3.setName(T_FIELD_TSCURRENT);
field3.setValue(131.0);
field3.setPrecision(3, 0);
field1.setType(dataFieldDescs[DF_MinCellVolt]);
field2.setType(dataFieldDescs[DF_Speed]);
field3.setType(dataFieldDescs[DF_TSCurrent]);
}
void DriverViewView::tearDownScreen() { DriverViewViewBase::tearDownScreen(); }
void DriverViewView::setFieldType(size_t i, const DataFieldDescription &desc) {
getField(i).setType(desc);
}
void DriverViewView::setFieldValue(size_t i, float value) {
getField(i).setValue(value);
}
void DriverViewView::setFieldValue(size_t i, const char *value) {
getField(i).setValue(value);
}
void DriverViewView::setFieldValue(size_t i, int value) {
getField(i).setValue(value);
}
void DriverViewView::setTireTemps(const TireTemps &temps) {
tireTempFL.setTemp(temps.fl);
tireTempFR.setTemp(temps.fr);
@ -30,7 +41,13 @@ void DriverViewView::setTSSoC(uint8_t soc) {
tsSoC.invalidate();
}
void DriverViewView::setMinCellVolt(float v) {
field1.setValue(v);
field1.invalidate();
DriverViewField &DriverViewView::getField(size_t i) {
switch (i) {
case 0:
return field1;
case 1:
return field2;
default:
return field3;
}
}