ESP32_ChinaDieselHeater_Con.../Arduino/BTCDieselHeater/src/OLED/ScreenManager.cpp
2019-03-16 14:57:37 +11:00

364 lines
14 KiB
C++

#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 "FontDumpScreen.h"
#include "TimerChartScreen.h"
#include "InheritSettingsScreen.h"
#include <Wire.h>
#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;
_menu = -1;
_subMenu = 0;
_rootMenu = -1;
_bReqUpdate = false;
_DimTime = millis() + 60000;
_pRebootScreen = NULL;
}
CScreenManager::~CScreenManager()
{
for(int i=0; i < _Screens.size(); i++) {
for(int j=0; j < _Screens[i].size(); j++) {
if(_Screens[i][j]) {
delete _Screens[i][j];
_Screens[i][j] = 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");
std::vector<CScreen*> menuloop;
// create root menu loop
menuloop.push_back(new CDetailedScreen(*_pDisplay, *this)); // detail control
menuloop.push_back(new CBasicScreen(*_pDisplay, *this)); // basic control
if(!bNoClock)
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
menuloop.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming
menuloop.push_back(new CWiFiScreen(*_pDisplay, *this)); // comms info
menuloop.push_back(new CSettingsScreen(*_pDisplay, *this)); // tuning info
_Screens.push_back(menuloop);
// create timer screens loop
menuloop.clear();
menuloop.push_back(new CTimerChartScreen(*_pDisplay, *this, 0)); // timer chart
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 0)); // set timer 1
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 1)); // set timer 2
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 2)); // set timer 3
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 3)); // set timer 4
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 4)); // set timer 5
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 5)); // set timer 6
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 6)); // set timer 7
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 7)); // set timer 8
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 8)); // set timer 9
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 9)); // set timer 10
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 10)); // set timer 11
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 11)); // set timer 12
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 12)); // set timer 13
menuloop.push_back(new CSetTimerScreen(*_pDisplay, *this, 13)); // set timer 14
_Screens.push_back(menuloop);
// create heater tuning screens loop - password protected
menuloop.clear();
menuloop.push_back(new CFuelMixtureScreen(*_pDisplay, *this)); // tuning
menuloop.push_back(new CHeaterSettingsScreen(*_pDisplay, *this)); // tuning
_Screens.push_back(menuloop);
// create branch screens
menuloop.clear();
menuloop.push_back(new CSetClockScreen(*_pDisplay, *this)); // clock set branch screen
menuloop.push_back(new CInheritSettingsScreen(*_pDisplay, *this)); // inherit OEM settings branch screen
menuloop.push_back(new CExperimentalSettingsScreen(*_pDisplay, *this)); // experimental settings branch screen
menuloop.push_back(new CFontDumpScreen(*_pDisplay, *this)); // font dump branch screen
_Screens.push_back(menuloop);
_menu = 0;
#if RTC_USE_DS3231==0 && RTC_USE_DS1307==0 && RTC_USE_PCF8523==0
_rootMenu = 2; // bring up clock set screen first if using millis based RTC!
_subMenu = 2;
#else
_rootMenu = 1; // basic control screen
_subMenu = 1;
#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
selectMenu(RootMenuLoop);
// upon dim timeout - sticky root menu screens are the first 3 in the list:
// Detailed Control
// Basic Control
// Clock
// return to those upon timeout, otherwise return to Basic Control screen
if(_rootMenu > 2) {
_subMenu = 1;
_rootMenu = 1;
}
_enterScreen();
}
}
if(_bReqUpdate) {
if(_pRebootScreen) {
_pRebootScreen->show();
_bReqUpdate = false;
return true;
}
else {
if(_menu >= 0) {
_Screens[_menu][_subMenu]->show();
_bReqUpdate = false;
return true;
}
}
}
return false;
}
void
CScreenManager::reqUpdate()
{
_bReqUpdate = true;
}
bool
CScreenManager::animate()
{
if(_menu >= 0)
return _Screens[_menu][_subMenu]->animate();
return false;
}
void
CScreenManager::refresh()
{
if(_pDisplay)
_pDisplay->display();
}
void
CScreenManager::_enterScreen()
{
if(_menu >= 0)
_Screens[_menu][_subMenu]->onSelect();
reqUpdate();
}
void
CScreenManager::_leaveScreen()
{
if(_menu >= 0)
_Screens[_menu][_subMenu]->onExit();
}
void
CScreenManager::_changeSubMenu(int dir)
{
_leaveScreen();
_subMenu += dir;
int bounds = _Screens[_menu].size() - 1;
ROLLUPPERLIMIT(_subMenu, bounds, 0);
ROLLLOWERLIMIT(_subMenu, 0, bounds);
if(_menu == 0)
_rootMenu = _subMenu; // track the root menu for when we branch then return
_enterScreen();
}
void
CScreenManager::nextMenu()
{
if(_menu >= 0 && _menu != BranchMenu) {
_changeSubMenu(+1);
}
}
void
CScreenManager::prevMenu()
{
if(_menu >= 0 && _menu != BranchMenu) {
_changeSubMenu(-1);
}
}
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(_menu >= 0)
_Screens[_menu][_subMenu]->keyHandler(event);
}
void
CScreenManager::selectMenu(eUIMenuSets menuSet, int specific)
{
_leaveScreen();
if(_menu >= 0) { // only true once we have created the screens
_menu = menuSet;
if(specific >= 0) {
// targetting a specific menu
_subMenu = specific;
UPPERLIMIT(_subMenu, _Screens[_menu].size()-1); // check bounds!
}
else {
// default sub menu behaviour
if(_menu == 0)
_subMenu = _rootMenu; // return to last used root menu
else
_subMenu = 0; // branches always go to first sub menu
}
}
_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);
}