DreherTankController/src/display/display.cpp

1131 lines
45 KiB
C++

#include <Arduino.h>
#include "display.h"
#include "../DallasTemperature/DallasTemperature.h"
#include "../mystrings/mystrings.h"
extern u32 currMillis;
extern void setPSensor(const PSensor&);
extern void setModbusParams(const ModbusParameters&);
extern void setParams(Parameters&, bool writeModbusRegister);
extern void setFaultSettings(const FaultSettings&, bool writeModbusRegister);
Display::Display(
uint8_t cs,
uint8_t btnNext,
uint8_t btnPrev,
uint8_t btnSelect,
uint8_t btnCancel,
uint8_t bgLED)
: U8G2_ST7920_128X64_F_HW_SPI(U8G2_R0, cs)
, btnNext(btnNext)
, btnPrev(btnPrev)
, btnSelect(btnSelect)
, btnCancel(btnCancel)
, bgLed(bgLED)
{
// Bei 2 MHz funtionierte im Test das Display schon nicht mehr
// setBusClock(1000000);
_lastCEn = params.cEn;
}
void Display::process()
{
if (_lastCEn != params.cEn || _lastFaultState != faults.state() ||
_lastOpticalState != faultSettings.optical) {
_lastCEn = params.cEn;
_lastFaultState = faults.state();
_lastOpticalState = faultSettings.optical;
if (_lastCEn && _lastFaultState == activeFault && _lastOpticalState) {
_currBrightness = 255;
_lastBrightnessChange = currMillis;
bgLight(true);
} else {
_currBrightness = 0;
if (_lastCEn) {
bgLight(true);
} else {
bgLight(100);
}
}
}
if (_currBrightness) {
if (_currBrightness == 255)
_incBrightness = false;
else if (_currBrightness == 100)
_incBrightness = true;
if (currMillis - _lastBrightnessChange > 2) {
u8 diff = (currMillis - _lastBrightnessChange) / 2;
if (_incBrightness) {
_currBrightness = (_currBrightness + diff > 255) ? 255 : _currBrightness + diff;
bgLight(_currBrightness);
} else {
_currBrightness = (_currBrightness - diff < 100) ? 100 : _currBrightness - diff;
bgLight(_currBrightness);
}
_lastBrightnessChange = currMillis;
}
}
switch (_event()) {
case _BACK_TO_HOME_SCREEN:
_selection = 0;
_home();
return;
case U8X8_MSG_GPIO_MENU_NEXT:
_nextEvent();
_select();
break;
case U8X8_MSG_GPIO_MENU_PREV:
_prevEvent();
_select();
break;
case U8X8_MSG_GPIO_MENU_SELECT:
if (_selection) {
Parameters paramsLocal;
ModbusParameters mbParamsLocal;
FaultSettings faultSettingsLocal;
switch (_selection) {
case _MENU_MAIN:
_printmlnf("case _MENU_MAIN");
_saveCursorPosForLevel(MenuLevel_1);
switch (_prevCursor) {
case _POS_TEMPERATURE_MENU:
_printmlnf("main menu: temperature");
_select(_MENU_TEMPERATURE);
break;
case _POS_PRESSURE_MENU:
_printmlnf("main menu: pressure");
_select(_MENU_PRESSURE);
break;
case _POS_FAULTS_MAIN:
_printmlnf("main menu: faults");
_select(_MENU_FAULTS_MAIN);
break;
case _POS_SYSTEM:
_printmlnf("main menu: system");
_restrictInputValue(0, 255);
_select(_VERIFY_ADMIN);
break;
case _POS_RESET:
_printmlnf("main menu: reset");
_select(_SELECTION_RESET);
break;
}
break;
case _MENU_TEMPERATURE:
_printmlnf("case _MENU_TEMPERATURE");
_saveCursorPosForLevel(MenuLevel_2);
switch (_prevCursor) {
case _POS_TEMPERATURE_ENABLED:
_cursor = params.tEn;
_printmf("menu temperature: control enabled: ");
_printmln(_cursor);
_select(_SELECTION_TEMPERATURE_ENABLED);
break;
case _POS_TEMPERATURE_SETPOINT:
_printmlnf("menu temperature: setpoint");
_val = params.ts1;
_restrictInputValue(_MIN_TEMP_SETPOINT, _MAX_TEMP_SETPOINT, Precision_2);
_select(_SELECTION_TEMPERATURE_SETPOINT);
break;
case _POS_TEMPERATURE_HYSTERESIS:
_printmlnf("menu temperature: hysteresis");
_val = params.th1;
_restrictInputValue(_MIN_TEMP_HYSTERESIS, _MAX_TEMP_HYSTERESIS, Precision_2);
_select(_SELECTION_TEMPERATURE_HYSTERESIS);
break;
}
break;
case _SELECTION_TEMPERATURE_ENABLED:
_printmlnf("case _SELECTION_TEMPERATURE_ENABLED");
paramsLocal.tEn = _cursor;
setParams(paramsLocal, true);
_select(_MENU_TEMPERATURE, true);
break;
case _SELECTION_TEMPERATURE_SETPOINT:
_printmlnf("case _SELECTION_TEMPERATURE_SETPOINT");
paramsLocal.ts1 = _val;
setParams(paramsLocal, true);
_select(_MENU_TEMPERATURE, true);
break;
case _SELECTION_TEMPERATURE_HYSTERESIS:
_printmlnf("case _SELECTION_TEMPERATURE_HYSTERESIS");
paramsLocal.th1 = _val;
setParams(paramsLocal, true);
_select(_MENU_TEMPERATURE, true);
break;
case _MENU_PRESSURE:
_printmlnf("case _MENU_PRESSURE");
_saveCursorPosForLevel(MenuLevel_2);
switch (_prevCursor) {
case _POS_PRESSURE_ENABLE_INCREASE:
_printmlnf("menu pressure: enable increase");
_cursor = params.pInc;
_select(_SELECTION_PRESSURE_ENABLE_INCREASE);
break;
case _POS_PRESSURE_ENABLE_DECREASE:
_printmlnf("menu pressure: enable decrease");
_cursor = params.pDec;
_select(_SELECTION_PRESSURE_ENABLE_DECREASE);
break;
case _POS_PRESSURE_SETPOINT:
_printmlnf("menu pressure: setpoint");
_val = params.ps;
_restrictInputValue(_MIN_P_SETPOINT, _MAX_P_SETPOINT, Precision_2);
_select(_SELECTION_PRESSURE_SETPOINT);
break;
case _POS_PRESSURE_HYSTERESIS:
_printmlnf("menu pressure: hysteresis");
_val = params.ph;
_restrictInputValue(_MIN_P_HYSTERESIS, _MAX_P_HYSTERESIS, Precision_2);
_select(_SELECTION_PRESSURE_HYSTERESIS);
break;
}
break;
case _SELECTION_PRESSURE_ENABLE_INCREASE:
_printmlnf("case _SELECTION_PRESSURE_ENABLE_INCREASE");
paramsLocal.pInc = _cursor;
setParams(paramsLocal, true);
_select(_MENU_PRESSURE, true);
break;
case _SELECTION_PRESSURE_ENABLE_DECREASE:
_printmlnf("case _SELECTION_PRESSURE_ENABLE_DECREASE");
paramsLocal.pDec = _cursor;
setParams(paramsLocal, true);
_select(_MENU_PRESSURE, true);
break;
case _SELECTION_PRESSURE_SETPOINT:
_printmlnf("case _SELECTION_PRESSURE_SETPOINT");
paramsLocal.ps = _val;
setParams(paramsLocal, true);
_select(_MENU_PRESSURE, true);
break;
case _SELECTION_PRESSURE_HYSTERESIS:
_printmlnf("case _SELECTION_PRESSURE_HYSTERESIS");
paramsLocal.ph = _val;
setParams(paramsLocal, true);
_select(_MENU_PRESSURE, true);
break;
case _MENU_FAULTS_MAIN:
_printmlnf("case _MENU_FAULTS_MAIN");
_saveCursorPosForLevel(MenuLevel_2);
switch (_prevCursor) {
case _POS_FAULTS_OPEN:
_printmlnf("menu faults: open faults");
_select(_MENU_FAULTS_OPEN);
break;
case _POS_FAULTS_CLEAR:
_printmlnf("menu faults: clear faults");
_select(_SELECTION_CLEAR_FAULTS);
break;
case _POS_FAULTS_SETTINGS:
_printmlnf("menu faults: settings");
_select(_MENU_FAULTS_SETTINGS);
break;
}
break;
case _MENU_FAULTS_OPEN:
_saveCursorPosForLevel(MenuLevel_3);
if (faults.count()) {
_select(_FAULT_INFO);
} else {
_select(_MENU_FAULTS_MAIN);
}
break;
case _FAULT_INFO:
if (_cursor && !faults.at(_prevCursor)->active) {
faults.removeOne(_prevCursor);
}
_select(_MENU_FAULTS_OPEN, true);
break;
case _SELECTION_CLEAR_FAULTS:
_printmlnf("case _SELECTION_CLEAR_FAULTS");
if (_cursor) {
faults.removeAll();
}
_select(_MENU_FAULTS_MAIN, true);
break;
case _MENU_FAULTS_SETTINGS:
_printmlnf("case _MENU_FAULTS_SETTINGS");
_saveCursorPosForLevel(MenuLevel_3);
switch (_prevCursor) {
case _POS_FAULTS_ACOUSTIC:
_printmlnf("menu faults settings: acoustic warning");
_cursor = faultSettings.acoustic;
_select(_SELECTION_FAULTS_ACOUSTIC);
break;
case _POS_FAULTS_OPTICAL:
_printmlnf("menu faults settings: optical warning");
_cursor = faultSettings.optical;
_select(_SELECTION_FAULTS_OPTICAL);
break;
case _POS_FAULTS_T_OFF:
_printmlnf("menu faults settings: t-off if error");
_cursor = faultSettings.tOnIfError;
_select(_SELECTION_FAULTS_T_OFF);
break;
case _POS_FAULTS_P_OFF:
_printmlnf("menu faults settings: p-off if error");
_cursor = faultSettings.pOnIfError;
_select(_SELECTION_FAULTS_P_OFF);
break;
case _POS_FAULTS_T_R_RATE:
_printmlnf("menu faults settings: min t rise rate");
_val = faultSettings.tMinRRate;
_restrictInputValue(_MIN_FAULTS_RATE, _MAX_FAULTS_RATE, Precision_2);
_select(_SELECTION_FAULTS_T_R_RATE);
break;
case _POS_FAULTS_T_F_RATE:
_printmlnf("menu faults settings: min t fall rate");
_val = faultSettings.tMinFRate;
_restrictInputValue(_MIN_FAULTS_RATE, _MAX_FAULTS_RATE, Precision_2);
_select(_SELECTION_FAULTS_T_F_RATE);
break;
case _POS_FAULTS_P_RATE:
_printmlnf("menu faults settings: min p rate");
_val = faultSettings.pMinRate;
_restrictInputValue(_MIN_FAULTS_RATE, _MAX_FAULTS_RATE, Precision_2);
_select(_SELECTION_FAULTS_P_RATE);
break;
}
break;
case _SELECTION_FAULTS_ACOUSTIC:
faultSettingsLocal.acoustic = _cursor;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _SELECTION_FAULTS_OPTICAL:
faultSettingsLocal.optical = _cursor;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _SELECTION_FAULTS_T_OFF:
faultSettingsLocal.tOnIfError = _cursor;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _SELECTION_FAULTS_P_OFF:
faultSettingsLocal.pOnIfError = _cursor;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _SELECTION_FAULTS_T_R_RATE:
faultSettingsLocal.tMinRRate = _val;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _SELECTION_FAULTS_T_F_RATE:
faultSettingsLocal.tMinFRate = _val;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _SELECTION_FAULTS_P_RATE:
faultSettingsLocal.pMinRate = _val;
setFaultSettings(faultSettingsLocal, true);
_select(_MENU_FAULTS_SETTINGS, true);
break;
case _VERIFY_ADMIN:
_printmlnf("case _VERIFY_ADMIN");
if (_val == _ADMIN_CODE) {
_select(_MENU_SYSTEM);
} else {
_select(_MENU_MAIN, true);
}
_val = 0;
break;
case _MENU_SYSTEM:
_printmlnf("case _MENU_SYSTEM");
_saveCursorPosForLevel(MenuLevel_2);
switch (_prevCursor) {
case _POS_MODBUS_MENU:
_printmlnf("menu system: modbus");
_select(_MENU_SETTINGS_MODBUS);
break;
case _POS_P_SENSOR_SELECTION:
_printmlnf("menu system: pressure sensor");
_cursor = pSensor - 1;
_select(_SELECTION_P_SENSOR);
break;
}
break;
case _MENU_SETTINGS_MODBUS:
_printmlnf("case _MENU_SETTINGS_MODBUS");
_saveCursorPosForLevel(MenuLevel_3);
switch (_prevCursor) {
case _POS_MODBUS_ADDRESS:
_printmlnf("menu modbus settings: address");
_val = modbusParams.address;
_restrictInputValue(_MODBUS_ADDR_MIN, _MODBUS_ADDR_MAX);
_select(_SELECTION_MODBUS_ADDRESS);
break;
case _POS_MODBUS_BAUDRATE:
_printmlnf("menu modbus settings: baudrate");
_baudrateCursorPos();
_select(_SELECTION_MODBUS_BAUDRATE);
break;
case _POS_MODBUS_DELAY:
_printmlnf("menu modbus settings: delay");
_val = modbusParams.delay;
_restrictInputValue(_MODBUS_DELAY_MIN, _MODBUS_DELAY_MAX, Precision_1);
_select(_SELECTION_MODBUS_DELAY);
break;
}
break;
case _SELECTION_MODBUS_BAUDRATE:
_printmlnf("case _SELECTION_MODBUS_BAUDRATE");
_setModbusBaudrate();
_select(_MENU_SETTINGS_MODBUS, true);
break;
case _SELECTION_MODBUS_ADDRESS:
_printmlnf("case _SELECTION_MODBUS_ADDRESS");
mbParamsLocal.address = _val;
setModbusParams(mbParamsLocal);
_select(_MENU_SETTINGS_MODBUS, true);
break;
case _SELECTION_MODBUS_DELAY:
_printmlnf("case _SELECTION_MODBUS_DELAY");
mbParamsLocal.delay = _val;
setModbusParams(mbParamsLocal);
_select(_MENU_SETTINGS_MODBUS, true);
break;
case _SELECTION_P_SENSOR:
_printmlnf("case _SELECTION_P_SENSOR");
switch (_cursor) {
case _POS_P_SMC_1_5V_0_5BAR:
setPSensor(SMC_1_5V_0_5BAR);
break;
case _POS_P_GEMS_0_5V_0_6BAR:
setPSensor(GEMS_0_5V_0_6BAR);
break;
}
_select(_MENU_SYSTEM, true);
break;
case _SELECTION_RESET:
_printmlnf("case _SELECTION_RESET");
if (_cursor == 1) {
reset();
} else {
_select(_MENU_MAIN, true);
}
break;
}
}
break;
case U8X8_MSG_GPIO_MENU_HOME:
if (_selection) {
_val = 0;
if (!_restoreCursor()) {
_home();
return;
}
switch (_selection) {
case _MENU_MAIN:
_printmlnf("back to: home screen");
_selection = 0;
_home();
return;
case _SELECTION_TEMPERATURE_ENABLED:
case _SELECTION_TEMPERATURE_SETPOINT:
case _SELECTION_TEMPERATURE_HYSTERESIS:
_printmlnf("back to: menu temperature");
_select(_MENU_TEMPERATURE);
break;
case _SELECTION_PRESSURE_ENABLE_INCREASE:
case _SELECTION_PRESSURE_ENABLE_DECREASE:
case _SELECTION_PRESSURE_SETPOINT:
case _SELECTION_PRESSURE_HYSTERESIS:
_printmlnf("back to: menu pressure");
_select(_MENU_PRESSURE);
break;
case _MENU_FAULTS_OPEN:
case _SELECTION_CLEAR_FAULTS:
case _MENU_FAULTS_SETTINGS:
_printmlnf("back to: menu faults");
_select(_MENU_FAULTS_MAIN);
break;
case _FAULT_INFO:
_printmlnf("back to: menu faults open");
_select(_MENU_FAULTS_OPEN);
break;
case _SELECTION_FAULTS_ACOUSTIC:
case _SELECTION_FAULTS_OPTICAL:
case _SELECTION_FAULTS_T_OFF:
case _SELECTION_FAULTS_P_OFF:
case _SELECTION_FAULTS_T_R_RATE:
case _SELECTION_FAULTS_T_F_RATE:
case _SELECTION_FAULTS_P_RATE:
_printmlnf("back to: menu faults settings");
_select(_MENU_FAULTS_SETTINGS);
break;
case _MENU_SETTINGS_MODBUS:
case _SELECTION_P_SENSOR:
_printmlnf("back to: menu system");
_select(_MENU_SYSTEM);
break;
case _SELECTION_MODBUS_ADDRESS:
case _SELECTION_MODBUS_BAUDRATE:
case _SELECTION_MODBUS_DELAY:
_printmlnf("back to: menu modbus");
_select(_MENU_SETTINGS_MODBUS);
break;
default:
_printmlnf("back to: main menu");
_select(_MENU_MAIN);
}
}
break;
}
if (currMillis - _prevT > 250) {
_prevT = currMillis;
if (!_selection) {
_home();
}
}
}
void Display::_select(const uint8_t selection, const bool restoreCursor=false)
{
if (restoreCursor)
_restoreCursor();
_selection = selection;
_select();
}
void Display::_select()
{
_printmf("select value: "); _printm(_selection); _printmf(" - ");
_fastStepsDelay = (_selection == _MENU_FAULTS_OPEN) ? 150 : _FAST_STEP_MS;
setFont(_SEL_FONT);
setFontRefHeightAll();
_inputValueActive = false;
_stepSize = 1;
// String str_;
_printtime("select screen");
switch (_selection) {
case _MENU_MAIN:
_printmf("_MENU_MAIN");
_menu_depth = 0;
sprintf(_text, getMyStr501(STR_MENU_MAIN_TITLE), _VERSION_STRING);
_selCnt = my_UserInterfaceSelectionList(&u8g2, _text, _cursor, getMyStr200(STR_MENU_MAIN));
break;
case _MENU_TEMPERATURE:
_printmf("_MENU_TEMPERATURE");
_menu_depth = 1;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_TEMPERATURE), _cursor, getMyStr200(STR_MENU_TEMPERATURE));
break;
case _SELECTION_TEMPERATURE_ENABLED:
_printmf("_SELECTION_TEMPERATURE_ENABLED");
_menu_depth = 2;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr501(STR_COOLING), nullptr, getMyStr502(STR_ACTIVATE), getMyStr503(STR_NO_YES), _cursor);
break;
case _SELECTION_TEMPERATURE_SETPOINT:
_printmf("_SELECTION_TEMPERATURE_SETPOINT");
_menu_depth = 2;
_inputValue(5, getMyStr200(STR_T_SETP), getMyStr501(STR__FLOAT__));
break;
case _SELECTION_TEMPERATURE_HYSTERESIS:
_printmf("_SELECTION_TEMPERATURE_HYSTERESIS");
_menu_depth = 2;
_inputValue(5, getMyStr200(STR_T_HYST), getMyStr501(STR__FLOAT__));
break;
case _MENU_PRESSURE:
_printmf("_MENU_PRESSURE");
_menu_depth = 1;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_P), _cursor, getMyStr200(STR_MENU_PRESSURE));
break;
case _SELECTION_PRESSURE_ENABLE_INCREASE:
_printmf("_SELECTION_PRESSURE_ENABLE_INCREASE");
_menu_depth = 2;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr501(STR_P_INC), nullptr, getMyStr502(STR_ACTIVATE), getMyStr503(STR_NO_YES), _cursor);
break;
case _SELECTION_PRESSURE_ENABLE_DECREASE:
_printmf("_SELECTION_PRESSURE_ENABLE_DECREASE");
_menu_depth = 2;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr501(STR_P_DEC), nullptr, getMyStr502(STR_ACTIVATE), getMyStr503(STR_NO_YES), _cursor);
break;
case _SELECTION_PRESSURE_SETPOINT:
_printmf("_SELECTION_PRESSURE_SETPOINT");
_menu_depth = 2;
_inputValue(5, getMyStr200(STR_P_SETP), getMyStr501(STR__FLOAT__));
break;
case _SELECTION_PRESSURE_HYSTERESIS:
_printmf("_SELECTION_PRESSURE_HYSTERESIS");
_menu_depth = 2;
_inputValue(5, getMyStr200(STR_P_HYST), getMyStr501(STR__FLOAT__));
break;
case _MENU_FAULTS_MAIN:
_printmf("_MENU_FAULTS_MAIN");
_menu_depth = 1;
sprintf(_text, getMyStr501(STR_F_ERR_TITLE), faults.count());
_selCnt = my_UserInterfaceSelectionList(&u8g2, _text, _cursor, getMyStr200(STR_MENU_ERR_HANDLING));
break;
case _MENU_FAULTS_OPEN:
_printmf("_MENU_FAULTS_OPEN");
_menu_depth = 2;
if (faults.count()) {
sprintf(_text, "%s (%u/%u)", getMyStr501(STR_CURR_ERRS), _cursor + 1, faults.count());
_selCnt = my_UserInterfaceSelectionList(&u8g2, _text, _cursor, faults.menu());
} else {
_selCnt = my_UserInterfaceMessage(&u8g2, faults.menu(), nullptr, nullptr, getMyStr501(STR_BACK), _cursor);
}
break;
case _FAULT_INFO:
_printmf("_FAULT_INFO");
_menu_depth = 3;
strcpy(charBuffer502, faults.at(_prevCursor)->title());
strcpy(charBuffer503, faults.at(_prevCursor)->activatedText());
sprintf(charBuffer501, "%s\n%s", charBuffer502, charBuffer503);
strcpy(charBuffer502, faults.at(_prevCursor)->deactivatedText());
sprintf(charBuffer503, "ID: %u", faults.at(_prevCursor)->id);
_selCnt = my_UserInterfaceMessage(&u8g2, charBuffer501, charBuffer502, charBuffer503, getMyStr200((faults.at(_prevCursor)->active) ? STR_BACK : STR_BACK_DEL), _cursor);
break;
case _MENU_FAULTS_SETTINGS:
_menu_depth = 2;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_MENU_FAULT_SETTINGS_TITLE), _cursor, getMyStr200(STR_MENU_FAULT_SETTINGS));
break;
case _SELECTION_FAULTS_ACOUSTIC:
_menu_depth = 3;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr200(STR_FAULTS_ACOUSTIC), nullptr, nullptr, getMyStr502(STR_NO_YES), _cursor);
break;
case _SELECTION_FAULTS_OPTICAL:
_menu_depth = 3;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr200(STR_FAULTS_OPTICAL), nullptr, nullptr, getMyStr502(STR_NO_YES), _cursor);
break;
case _SELECTION_FAULTS_T_OFF:
_menu_depth = 3;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr200(STR_FAULTS_T_OFF), nullptr, nullptr, getMyStr502(STR_NO_YES), _cursor);
break;
case _SELECTION_FAULTS_P_OFF:
_menu_depth = 3;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr200(STR_FAULTS_P_OFF), nullptr, nullptr, getMyStr502(STR_NO_YES), _cursor);
break;
case _SELECTION_FAULTS_T_R_RATE:
_menu_depth = 3;
_inputValue(5, getMyStr200(STR_FAULTS_T_R_RATE), getMyStr501(STR__FLOAT__));
break;
case _SELECTION_FAULTS_T_F_RATE:
_menu_depth = 3;
_inputValue(5, getMyStr200(STR_FAULTS_T_F_RATE), getMyStr501(STR__FLOAT__));
break;
case _SELECTION_FAULTS_P_RATE:
_menu_depth = 3;
_inputValue(5, getMyStr200(STR_FAULTS_P_RATE), getMyStr501(STR__FLOAT__));
break;
case _SELECTION_CLEAR_FAULTS:
_printmf("_SELECTION_CLEAR_FAULTS");
_menu_depth = 2;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr200(STR_DEL_ALL_INACTIVE_FAULTS), nullptr, nullptr, getMyStr501(STR_NO_YES), _cursor);
break;
case _VERIFY_ADMIN:
_printmf("_VERIFY_ADMIN");
_menu_depth = 1;
_inputValueActive = true;
sprintf(_text, getMyStr501(STR_F_DEC_0), _val);
my_UserInterfaceInputValueString(&u8g2, getMyStr200(STR_ADMIN_AUTH), nullptr, _text);
break;
case _MENU_SYSTEM:
_printmf("_MENU_SYSTEM");
_menu_depth = 1;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_SYSTEM), _cursor, getMyStr200(STR_MENU_SYSTEM));
break;
case _MENU_SETTINGS_MODBUS:
_printmf("_MENU_SETTINGS_MODBUS");
_menu_depth = 2;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_MODBUS), _cursor, getMyStr200(STR_MENU_MODBUS));
break;
case _SELECTION_MODBUS_BAUDRATE:
_printmf("_SELECTION_MODBUS_BAUDRATE");
_menu_depth = 3;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_BAUDR), _cursor, getMyStr200(STR_MENU_BAUDR));
break;
case _SELECTION_MODBUS_ADDRESS:
_printmf("_SELECTION_MODBUS_ADDRESS");
_menu_depth = 3;
sprintf(_text, getMyStr501(STR_SEL_MODB_ADDR_F), _val);
_inputValue(1, getMyStr200(STR_SEL_MODB_ADDR));
break;
case _SELECTION_MODBUS_DELAY:
_printmf("_SELECTION_MODBUS_DELAY");
_menu_depth = 3;
sprintf(_text, getMyStr501(STR_SEL_MODB_DELAY_F), _val / 10, _val % 10);
_inputValue(1, getMyStr200(STR_SEL_MODB_DELAY));
break;
case _SELECTION_P_SENSOR:
_printmf("_SELECTION_P_SENSOR");
_menu_depth = 2;
_selCnt = my_UserInterfaceSelectionList(&u8g2, getMyStr501(STR_P_SENSOR), _cursor, getMyStr200(STR_MENU_P_SENSOR));
break;
case _SELECTION_RESET:
_printmf("_SELECTION_RESET");
_menu_depth = 1;
_selCnt = my_UserInterfaceMessage(&u8g2, getMyStr501(STR_RESTART_CONTROLLER), getMyStr502(STR_20_HYPHENS), getMyStr503(STR_REALLY_RESTART), getMyStr200(STR_NO_YES), _cursor);
break;
default:
_printmf("no matched case");
_menu_depth = 0;
}
_printmln();
}
void Display::_home()
{
// Das Display hat eine Auflösung von 128 x 64 Pixel
int ts1a = params.ts1 / 100;
int ts1b = params.ts1 % 100;
int th1a = params.th1 / 100;
int th1b = params.th1 % 100;
int psa = params.ps / 100;
int psb = params.ps % 100;
int pha = params.ph / 100;
int phb = params.ph % 100;
bool cEn = params.cEn;
bool tEn = (!cEn) ? false : params.tEn;
bool pInc = (!cEn) ? false : params.pInc;
bool pDec = (!cEn) ? false : params.pDec;
bool pEn = pInc || pDec;
bool pFault = faults.pActive();
bool tFault = faults.tActive();
uint8_t pState = (vStates.pInc) ? 1 : (vStates.pDec) ? 2 : 0;
bool tState = vStates.t1;
// %u in sprintf() geht nur bis uint16_t
String baudStr(modbusParams.baudrate);
FaultState fState = faults.state();
u8 x = 112;
u8 y;
_printtime("homescreen");
firstPage();
do {
setFont(u8g2_font_fub20_tf);
if (vals.t1 == _SENSOR_FAULT)
sprintf(_text, getMyStr501(STR_HOME_1));
else
sprintf(_text, getMyStr501(STR_HOME_2), vals.t1 / 100, vals.t1 % 100);
drawStr(0, 27, _text);
if (vals.p == _SENSOR_FAULT)
sprintf(_text, getMyStr501(STR_HOME_3));
else
sprintf(_text, getMyStr501(STR_HOME_4), vals.p / 100, vals.p % 100);
drawStr(0, 57, _text);
setFont(u8g2_font_micro_tr);
sprintf(_text, getMyStr501(STR_HOME_5), ts1a, ts1b, th1a, th1b, (tEn) ? "": getMyStr502(STR_IN));
drawStr(0, 5, _text);
sprintf(_text, getMyStr501(STR_HOME_6), psa, psb, pha, phb, (pInc) ? getMyStr502(STR_ON) : getMyStr502(STR_OFF), (pDec) ? getMyStr503(STR_ON) : getMyStr503(STR_OFF));
drawStr(0, 35, _text);
sprintf(_text, getMyStr501(STR_HOME_7), modbusParams.address, baudStr.c_str());
drawStr(0, 64, _text);
if (cEn) {
_displayFaultOrPowerSymbol(fState, false);
y = 22;
if (!tEn) { // Temperaturregelung deaktiviert
if (tFault && _showFault) {
// Sollte nicht eintreten, da entsprechende Alarme
// mit der Temperaturregelung mit deaktiviert werden
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else {
setFont(u8g2_font_open_iconic_check_2x_t);
drawStr(x, y, "\x42"); // X in schwarzem Kreis
}
} else if (!faultSettings.tOnIfError && tFault) {
// Ventile werden nicht mehr in controller.cpp geschaltet
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else if (tFault && _showFault) {
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else if (tState) {
setFont(u8g2_font_open_iconic_arrow_2x_t);
drawStr(x, y, "\x58"); // Kreislaufsymbol
}
y = 58;
if (!pEn) { // Druckregelung deaktiviert
if (pFault && _showFault) {
// Sollte nicht eintreten, da entsprechende Alarme
// mit der Druckregelung mit deaktiviert werden
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else {
setFont(u8g2_font_open_iconic_check_2x_t);
drawStr(x, y, "\x42"); // X in schwarzem Kreis
}
} else if (!faultSettings.pOnIfError && pFault) {
// Ventile werden nicht mehr in controller.cpp geschaltet
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else if (pFault && _showFault) {
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else if (pState == 1) {
setFont(u8g2_font_open_iconic_arrow_2x_t);
drawStr(x, y, "\x4b"); // Pfeil rauf
} else if (pState == 2) {
setFont(u8g2_font_open_iconic_arrow_2x_t);
drawStr(x, y, "\x48"); // Pfeil runter
}
} else {
_displayFaultOrPowerSymbol(fState, true);
y = 22;
if (tFault && _showFault) {
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else {
setFont(u8g2_font_open_iconic_check_2x_t);
drawStr(x, y, "\x42"); // X in schwarzem Kreis
}
y = 58;
if (pFault && _showFault) {
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(x+1, y, "\x47"); // Warnung-Symbol
} else {
setFont(u8g2_font_open_iconic_check_2x_t);
drawStr(x, y, "\x42"); // X in schwarzem Kreis
}
}
} while (nextPage());
}
bool Display::_displayFaultOrPowerSymbol(const FaultState &state, bool power)
{
bool fault = false;
switch (state) {
case activeFault:
case inactiveFault:
fault = true;
_showFaultC++;
if (_showFaultC % ((state == activeFault) ? 2 : 4) == 0) {
_showFault = !_showFault;
_showFaultC = 0;
}
break;
default:
if (power) {
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(113, 40, "\x4e"); // Power-Symbol
}
}
if (fault && _showFault) {
setFont(u8g2_font_open_iconic_embedded_2x_t);
drawStr(113, 40, "\x47"); // Warnung-Symbol
} else if (fault) {
char text[3];
sprintf(text, "%u", faults.count());
setFont(u8g2_font_fub11_tf);
u8 w = getUTF8Width(text);
u8 x;
if (119 + w > 128)
x = 128 - w;
else
x = 119 - (w / 2);
drawStr(x, 37, text);
}
return fault;
}
void Display::init()
{
pinMode(bgLed, OUTPUT);
digitalWrite(bgLed, true);
begin(btnSelect, btnNext, btnPrev, U8X8_PIN_NONE, U8X8_PIN_NONE, btnCancel);
}
void Display::modbusProblem()
{
firstPage();
do {
setFont(_STD_FONT);
uint8_t y = _FIRS_LINE_Y;
drawStr(0, y, "Problem:");
y += _STD_LINEHEIGHT;
drawStr(0, y, "Fehler Modbus");
} while (nextPage());
}
void Display::oneWireDevicesDetected(uint8_t count)
{
setFont(_SEL_FONT);
setFontRefHeightAll();
sprintf(_text, "%u", count);
userInterfaceMessage(getMyStr501(STR_1W_1), getMyStr502(STR_1W_2), _text, getMyStr503(STR_OK));
}
void Display::tooMuchOneWireDevicesDetected(uint8_t actual, uint8_t max)
{
setFont(_SEL_FONT);
setFontRefHeightAll();
sprintf(_text, getMyStr501(STR_1W_F1), actual, max);
userInterfaceMessage(getMyStr501(STR_1W_ERR), getMyStr502(STR_1W_3), _text, getMyStr503(STR_OK));
}
void Display::noOneWireDevicesDetected()
{
setFont(_SEL_FONT);
setFontRefHeightAll();
userInterfaceMessage(getMyStr501(STR_1W_ERR), getMyStr502(STR_1W_4), getMyStr503(STR_1W_5), getMyStr200(STR_OK));
}
void Display::greeting()
{
firstPage();
do {
setFont(_STD_FONT);
uint8_t y = _FIRS_LINE_Y;
drawStr(0, y, "Dreher");
y += _STD_LINEHEIGHT;
drawStr(0, y, "Brauanlagen");
} while (nextPage());
}
void Display::bgLight(uint8_t value)
{
_bgLightAnalog = value;
_bgLightBool = (value > 0) ? true : false;
analogWrite(bgLed, value);
}
void Display::bgLight(bool state)
{
_bgLightAnalog = (state) ? 255 : 0;
_bgLightBool = state;
digitalWrite(bgLed, state);
}
bool Display::bgLightIncrease(uint8_t step)
{
_bgLightBool = true;
if (_bgLightAnalog == 255) {
return true;
}
int val = (int) _bgLightAnalog;
if (val + step >= 255) {
_bgLightAnalog = 255;
digitalWrite(bgLed, true);
return true;
} else {
_bgLightAnalog += step;
analogWrite(bgLed, _bgLightAnalog);
}
return false;
}
bool Display::bgLightDecrease(uint8_t step)
{
if (_bgLightAnalog == 0) {
_bgLightBool = false;
return true;
}
int val = (int) _bgLightAnalog;
if (val - step <= 0) {
_bgLightAnalog = 0;
_bgLightBool = false;
digitalWrite(bgLed, false);
return true;
} else {
_bgLightBool = true;
_bgLightAnalog -= step;
analogWrite(bgLed, _bgLightAnalog);
}
return false;
}
uint8_t Display::bgLightAnalog()
{
return _bgLightAnalog;
}
bool Display::bgLightState()
{
return _bgLightBool;
}
void Display::_baudrateCursorPos()
{
switch (modbusParams.baudrate) {
case 300: _cursor = _POS_BAUDRATE_300; break;
case 1200: _cursor = _POS_BAUDRATE_1200; break;
case 2400: _cursor = _POS_BAUDRATE_2400; break;
case 4800: _cursor = _POS_BAUDRATE_4800; break;
case 19200: _cursor = _POS_BAUDRATE_19200; break;
case 38400: _cursor = _POS_BAUDRATE_38400; break;
case 57600: _cursor = _POS_BAUDRATE_57600; break;
case 115200: _cursor = _POS_BAUDRATE_115200; break;
default: _cursor = _POS_BAUDRATE_9600;
}
}
void Display::_setModbusBaudrate()
{
ModbusParameters mbParamsLocal;
switch (_cursor) {
case _POS_BAUDRATE_300: mbParamsLocal.baudrate = 300; break;
case _POS_BAUDRATE_1200: mbParamsLocal.baudrate = 1200; break;
case _POS_BAUDRATE_2400: mbParamsLocal.baudrate = 2400; break;
case _POS_BAUDRATE_4800: mbParamsLocal.baudrate = 4800; break;
case _POS_BAUDRATE_19200: mbParamsLocal.baudrate = 19200; break;
case _POS_BAUDRATE_38400: mbParamsLocal.baudrate = 38400; break;
case _POS_BAUDRATE_57600: mbParamsLocal.baudrate = 57600; break;
case _POS_BAUDRATE_115200: mbParamsLocal.baudrate = 115200; break;
default: mbParamsLocal.baudrate = 9600;
}
setModbusParams(mbParamsLocal);
}
uint8_t Display::_event()
{
uint8_t event = getMenuEvent();
if (event)
return event;
bool next = !digitalRead(btnNext);
bool prev = !digitalRead(btnPrev);
bool cancel = !digitalRead(btnCancel);
if (next || prev || cancel) {
if (currMillis - _checkFastStepTime > _BEGIN_FAST_STEPS_DELAY) {
if (currMillis - _lastFastStep > _fastStepsDelay) {
_lastFastStep = currMillis;
if (next)
event = U8X8_MSG_GPIO_MENU_NEXT;
else if (prev)
event = U8X8_MSG_GPIO_MENU_PREV;
else if (cancel && _selection)
event = _BACK_TO_HOME_SCREEN;
if (currMillis - _checkFastStepTime > _BEGIN_BIG_STEPS_DELAY)
_enableBigSteps = true;
}
}
} else {
_checkFastStepTime = currMillis;
_enableBigSteps = false;
}
return event;
}
void Display::_nextEvent()
{
if (_selection) {
if (_inputValueActive) {
if (_val > _valMin) {
int step = (_enableBigSteps) ? _BIG_STEP * _stepSize : _stepSize;
if (_val - step > _valMin)
_val -= step;
else
_val = _valMin;
}
} else {
_cursor++;
if (_cursor >= _selCnt) {
_cursor = 0;
}
}
} else {
_selection = _MENU_MAIN;
}
}
void Display::_prevEvent()
{
if (_selection) {
if (_inputValueActive) {
if (_val < _valMax) {
int step = (_enableBigSteps) ? _BIG_STEP * _stepSize : _stepSize;
if (_val < step)
_val = step;
else if (_val + step < _valMax)
_val += step;
else
_val = _valMax;
}
} else {
if (_cursor == 0) {
_cursor = _selCnt;
}
_cursor--;
}
} else {
_selection = _MENU_MAIN;
}
}
void Display::_saveCursorPosForLevel(MenuLevel level)
{
switch (level) {
case MenuLevel_1:
_cur_l1 = _cursor;
break;
case MenuLevel_2:
_cur_l2 = _cursor;
break;
case MenuLevel_3:
_cur_l3 = _cursor;
break;
}
_prevCursor = _cursor;
_cursor = 0;
}
void Display::_restrictInputValue(int min, int max, Precision p=Precision_0)
{
char s1[10];
char s2[10];
switch (p) {
case Precision_1:
if (min % 10 == 0)
sprintf(s1, getMyStr501(STR_F_DEC_0), min / 10);
else
sprintf(s1, getMyStr501(STR_F_DEC_1), min / 10, min % 10);
if (max % 10 == 0)
sprintf(s2, getMyStr501(STR_F_DEC_0), max / 10);
else
sprintf(s2, getMyStr501(STR_F_DEC_1), max / 10, max % 10);
break;
case Precision_2:
if (min % 100 == 0)
sprintf(s1, getMyStr501(STR_F_DEC_0), min / 100);
else
sprintf(s1, getMyStr501(STR_F_DEC_2), min / 100, min % 100);
if (max % 100 == 0)
sprintf(s2, getMyStr501(STR_F_DEC_0), max / 100);
else
sprintf(s2, getMyStr501(STR_F_DEC_2), max / 100, max % 100);
break;
default:
sprintf(s1, getMyStr501(STR_F_DEC_0), min);
sprintf(s2, getMyStr501(STR_F_DEC_0), max);
}
_valMin = min;
_valMax = max;
sprintf(_text2, getMyStr501(STR_F_S_MIN_MAX), s1, s2);
}
void Display::_inputValue(const uint8_t stepSize, const char *title, const char *val=nullptr, const char *text=nullptr)
{
if (!val) {
val = _text;
} else if (!strncmp(val, getMyStr503(STR__FLOAT__), 9)) {
sprintf(_text, getMyStr501(STR_F_DEC_2), _val / 100, _val % 100);
val = _text;
}
if (!text)
text = _text2;
_inputValueActive = true;
_stepSize = stepSize;
my_UserInterfaceInputValueString(&u8g2, title, text, val);
}
uint8_t Display::_restoreCursor()
{
switch (_menu_depth) {
case 1:
_cursor = _cur_l1;
break;
case 2:
_cursor = _cur_l2;
break;
case 3:
_cursor = _cur_l3;
break;
default:
_cursor = 0;
_selection = 0;
}
return _menu_depth;
}