Make DriverView fields more modular
This commit is contained in:
36
TouchGFX/gui/include/gui/common/DataField.hpp
Normal file
36
TouchGFX/gui/include/gui/common/DataField.hpp
Normal 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
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
110
TouchGFX/gui/src/common/DataField.cpp
Normal file
110
TouchGFX/gui/src/common/DataField.cpp
Normal 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");
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user