#include "ScreenManager.h" #include "DetailedScreen.h" #include "BasicScreen.h" #include "PrimingScreen.h" #include "WiFiScreen.h" #include "FuelMixtureScreen.h" #include "SetClockScreen.h" #include "SetTimerScreen.h" #include "ClockScreen.h" #include "RebootScreen.h" #include "HeaterSettingsScreen.h" #include "SettingsScreen.h" #include "ExperimentalSettingsScreen.h" #include "TimerChartScreen.h" #include "InheritSettingsScreen.h" #include #include "../cfg/pins.h" #include "../cfg/BTCConfig.h" #include "../protocol/helpers.h" //////////////////////////////////////////////////////////////////////////////////////////////// // splash creen created using image2cpp http://javl.github.io/image2cpp/ // Settings: // Black background // Invert [X] // Arduino code, single bitmap // Identifier: DieselSplash // Draw Mode: Horizontal // const unsigned char DieselSplash [] PROGMEM = { // 'Splash2, 128x64px 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0f, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x21, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x88, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x20, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x84, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x20, 0x40, 0x00, 0x20, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x84, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x40, 0x40, 0x00, 0x10, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x40, 0x20, 0x00, 0x08, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x40, 0x10, 0x00, 0x04, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x80, 0x10, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x80, 0x08, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x80, 0x08, 0x01, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x04, 0x3e, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x07, 0xc0, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x1c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x64, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x84, 0x00, 0x00, 0x01, 0x80, 0x00, 0x01, 0xc0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x23, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x1e, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0xf8, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x1f, 0x20, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x03, 0xe8, 0x20, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x7c, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x08, 0x00, 0x00, 0x00, 0x21, 0x10, 0x01, 0x00, 0x00, 0x84, 0x00, 0x40, 0x01, 0x40, 0x00, 0x11, 0x08, 0x00, 0x00, 0x00, 0x21, 0x10, 0x01, 0x00, 0x00, 0x80, 0x00, 0x40, 0x01, 0x40, 0x00, 0x11, 0x3a, 0x4e, 0x73, 0x18, 0xe1, 0x13, 0x1d, 0xcc, 0xb0, 0x80, 0xc7, 0x75, 0x99, 0x4c, 0xb0, 0x1f, 0x4a, 0x52, 0x94, 0xa5, 0x21, 0xf4, 0xa5, 0x12, 0xc0, 0x81, 0x29, 0x46, 0x25, 0x52, 0xc0, 0x11, 0x4a, 0x52, 0x94, 0x3d, 0x21, 0x17, 0xa5, 0x1e, 0x80, 0x81, 0x29, 0x44, 0x25, 0x5e, 0x80, 0x11, 0x49, 0x92, 0x94, 0xa1, 0x21, 0x14, 0x25, 0x10, 0x80, 0x85, 0x29, 0x44, 0x25, 0x50, 0x80, 0x11, 0x39, 0x8e, 0x93, 0x18, 0xe1, 0x13, 0x1c, 0xcc, 0x80, 0x78, 0xc9, 0x34, 0x19, 0x4c, 0x80 }; CScreenManager::CScreenManager() { _pDisplay = NULL; _rootMenu = -1; _cancelNonRootMenus(); _bReqUpdate = false; _DimTime = millis() + 60000; _pRebootScreen = NULL; } CScreenManager::~CScreenManager() { for(int i=0; i < _RootScreens.size(); i++) { if(_RootScreens[i]) { delete _RootScreens[i]; _RootScreens[i] = NULL; } } for(int i=0; i < _TimerScreens.size(); i++) { if(_TimerScreens[i]) { delete _TimerScreens[i]; _TimerScreens[i] = NULL; } } for(int i=0; i < _BranchScreens.size(); i++) { if(_BranchScreens[i]) { delete _BranchScreens[i]; _BranchScreens[i] = NULL; } } if(_pDisplay) { delete _pDisplay; _pDisplay = NULL; } } void CScreenManager::begin(bool bNoClock) { // 128 x 64 OLED support (I2C) // xxxx_SWITCHCAPVCC = generate display voltage from 3.3V internally _pDisplay = new C128x64_OLED(OLED_SDA_pin, OLED_SCL_pin); #if USE_ADAFRUIT_SH1106 == 1 _pDisplay->begin(SH1106_SWITCHCAPVCC); Wire.begin(OLED_SDA_pin, OLED_SCL_pin, 800000); // speed up I2C from the default crappy 100kHz set via the adafruit begin! #elif USE_ADAFRUIT_SSD1306 == 1 _pDisplay->begin(SSD1306_SWITCHCAPVCC, 0x3c); _pDisplay->ssd1306_command(SSD1306_SETPRECHARGE); // 0xd9 _pDisplay->ssd1306_command(0x1F); // correct lame reversal of OLED current phases #endif // replace adafruit splash screen _pDisplay->clearDisplay(); _pDisplay->drawBitmap(0, 0, DieselSplash, 128, 64, WHITE); // Show initial display buffer contents on the screen -- _pDisplay->display(); DebugPort.println("Creating Screens"); _RootScreens.push_back(new CDetailedScreen(*_pDisplay, *this)); // detail control _RootScreens.push_back(new CBasicScreen(*_pDisplay, *this)); // basic control if(!bNoClock) _RootScreens.push_back(new CClockScreen(*_pDisplay, *this)); // clock _RootScreens.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming _RootScreens.push_back(new CWiFiScreen(*_pDisplay, *this)); // comms info _RootScreens.push_back(new CSettingsScreen(*_pDisplay, *this)); // tuning info // timer screens _TimerScreens.push_back(new CTimerChartScreen(*_pDisplay, *this, 0)); // timer chart _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 0)); // set timer 1 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 1)); // set timer 2 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 2)); // set timer 3 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 3)); // set timer 4 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 4)); // set timer 5 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 5)); // set timer 6 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 6)); // set timer 7 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 7)); // set timer 8 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 8)); // set timer 9 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 9)); // set timer 10 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 10)); // set timer 11 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 11)); // set timer 12 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 12)); // set timer 13 _TimerScreens.push_back(new CSetTimerScreen(*_pDisplay, *this, 13)); // set timer 14 // Heater tuning screens - password protected _TuningScreens.push_back(new CFuelMixtureScreen(*_pDisplay, *this)); // tuning _TuningScreens.push_back(new CHeaterSettingsScreen(*_pDisplay, *this)); // tuning // create branch screens _BranchScreens.push_back(new CSetClockScreen(*_pDisplay, *this)); // clock set branch screen _BranchScreens.push_back(new CInheritSettingsScreen(*_pDisplay, *this)); // inherit OEM settings branch screen _BranchScreens.push_back(new CExperimentalSettingsScreen(*_pDisplay, *this)); // experimental settings branch screen #if RTC_USE_DS3231==0 && RTC_USE_DS1307==0 && RTC_USE_PCF8523==0 _rootMenuScreen = 6; // bring up clock set screen first if using millis based RTC! #else _rootMenu = 1; // basic control screen #endif _enterScreen(); } bool CScreenManager::checkUpdate() { if(_DimTime) { long tDelta = millis() - _DimTime; if(tDelta > 0) { // time to dim the display // if(NVstore.getDimTime()) _pDisplay->dim(true); _DimTime = 0; _leaveScreen(); // fall back to main menu select(RootMenuLoop); // sticky screens are Detailed Control, Basic Control, or Clock. // otherwise return to Basic Control screen if(_rootMenu > 2) { _rootMenu = 1; } _enterScreen(); } } if(_bReqUpdate) { if(_pRebootScreen) { _pRebootScreen->show(); _bReqUpdate = false; return true; } else { if(_branchMenu >= 0) { _BranchScreens[_branchMenu]->show(); _bReqUpdate = false; return true; } else if(_tuningMenu >= 0) { _TuningScreens[_tuningMenu]->show(); _bReqUpdate = false; return true; } else if(_timerMenu >= 0) { _TimerScreens[_timerMenu]->show(); _bReqUpdate = false; return true; } else if(_rootMenu >= 0) { _RootScreens[_rootMenu]->show(); _bReqUpdate = false; return true; } } } return false; } void CScreenManager::reqUpdate() { _bReqUpdate = true; } bool CScreenManager::animate() { if(_tuningMenu >= 0) return _TuningScreens[_tuningMenu]->animate(); if(_branchMenu >= 0) return _BranchScreens[_branchMenu]->animate(); if(_timerMenu >= 0) return _TimerScreens[_timerMenu]->animate(); if(_rootMenu >= 0) return _RootScreens[_rootMenu]->animate(); return false; } void CScreenManager::refresh() { if(_pDisplay) _pDisplay->display(); } void CScreenManager::_enterScreen() { if(_branchMenu >= 0) _BranchScreens[_branchMenu]->onSelect(); else if(_timerMenu >= 0) _TimerScreens[_timerMenu]->onSelect(); else if(_tuningMenu >= 0) _TuningScreens[_tuningMenu]->onSelect(); else if(_rootMenu >= 0) _RootScreens[_rootMenu]->onSelect(); reqUpdate(); } void CScreenManager::_leaveScreen() { if(_branchMenu >= 0) _BranchScreens[_branchMenu]->onExit(); else if(_timerMenu >= 0) _TimerScreens[_timerMenu]->onExit(); else if(_tuningMenu >= 0) _TuningScreens[_tuningMenu]->onExit(); else if(_rootMenu >= 0) _RootScreens[_rootMenu]->onExit(); } void CScreenManager::nextScreen() { if(_branchMenu >= 0) { } else if(_timerMenu >= 0) { _leaveScreen(); _timerMenu++; ROLLUPPERLIMIT(_timerMenu, _TimerScreens.size()-1, 0); _enterScreen(); } else if(_tuningMenu >= 0) { _leaveScreen(); _tuningMenu++; ROLLUPPERLIMIT(_tuningMenu, _TuningScreens.size()-1, 0); _enterScreen(); } else { _leaveScreen(); _rootMenu++; ROLLUPPERLIMIT(_rootMenu, _RootScreens.size()-1, 0); _enterScreen(); } } void CScreenManager::prevScreen() { if(_branchMenu >= 0) { } else if(_timerMenu >=0) { _leaveScreen(); _timerMenu--; ROLLLOWERLIMIT(_timerMenu, 0, _TimerScreens.size()-1); _enterScreen(); } else if(_tuningMenu >= 0) { _leaveScreen(); _tuningMenu--; ROLLLOWERLIMIT(_tuningMenu, 0, _TuningScreens.size()-1); _enterScreen(); } else { _leaveScreen(); _rootMenu--; ROLLLOWERLIMIT(_rootMenu, 0, _RootScreens.size()-1); _enterScreen(); } } void CScreenManager::keyHandler(uint8_t event) { if(_DimTime == 0) { _pDisplay->dim(false); _DimTime = (millis() + NVstore.getDimTime()) | 1; return; // initial press when dimmed is thrown away } _DimTime = (millis() + NVstore.getDimTime()) | 1; // call key handler for active screen if(_branchMenu >= 0) _BranchScreens[_branchMenu]->keyHandler(event); else if(_tuningMenu >= 0) _TuningScreens[_tuningMenu]->keyHandler(event); else if(_timerMenu >= 0) _TimerScreens[_timerMenu]->keyHandler(event); else if(_rootMenu >= 0) _RootScreens[_rootMenu]->keyHandler(event); } void CScreenManager::_cancelNonRootMenus() { _timerMenu = -1; _tuningMenu = -1; _branchMenu = -1; } void CScreenManager::select(eUILoops loop) { _leaveScreen(); _cancelNonRootMenus(); switch(loop) { case RootMenuLoop: break; case TimerMenuLoop: _timerMenu = 0; break; case TuningMenuLoop: _tuningMenu = 0; break; } _enterScreen(); } void CScreenManager::select(eUIBranches branch) { _leaveScreen(); _cancelNonRootMenus(); _branchMenu = branch; _enterScreen(); } void CScreenManager::showRebootMsg(const char* content[2], long delayTime) { if(_pRebootScreen == NULL) _pRebootScreen = new CRebootScreen(*_pDisplay, *this); _pRebootScreen->setMessage(content, delayTime); _bReqUpdate = true; _pDisplay->dim(false); }