#include #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; }