2019-04-06 10:45:25 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the "bluetoothheater" distribution
|
|
|
|
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
|
|
|
*
|
2019-09-08 00:14:36 +00:00
|
|
|
* Copyright (C) 2019 Ray Jones <ray@mrjones.id.au>
|
2019-04-06 10:45:25 +00:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-12-01 00:36:25 +00:00
|
|
|
#include "ScreenManager.h"
|
2019-01-18 07:09:40 +00:00
|
|
|
#include "DetailedScreen.h"
|
|
|
|
#include "BasicScreen.h"
|
|
|
|
#include "PrimingScreen.h"
|
|
|
|
#include "WiFiScreen.h"
|
2020-03-23 05:54:15 +00:00
|
|
|
#include "WiFiSTAScreen.h"
|
2019-01-18 07:09:40 +00:00
|
|
|
#include "FuelMixtureScreen.h"
|
|
|
|
#include "SetClockScreen.h"
|
|
|
|
#include "SetTimerScreen.h"
|
|
|
|
#include "ClockScreen.h"
|
2019-01-16 09:22:17 +00:00
|
|
|
#include "RebootScreen.h"
|
2019-01-18 20:15:02 +00:00
|
|
|
#include "HeaterSettingsScreen.h"
|
2019-07-21 11:17:54 +00:00
|
|
|
#include "FuelCalScreen.h"
|
2019-01-19 11:05:14 +00:00
|
|
|
#include "SettingsScreen.h"
|
2019-04-09 23:28:46 +00:00
|
|
|
#include "ThermostatModeScreen.h"
|
2019-02-14 10:20:15 +00:00
|
|
|
#include "TimerChartScreen.h"
|
2019-03-01 23:16:37 +00:00
|
|
|
#include "InheritSettingsScreen.h"
|
2019-08-25 22:41:44 +00:00
|
|
|
#include "GPIOInfoScreen.h"
|
|
|
|
#include "GPIOSetupScreen.h"
|
2019-04-19 11:38:39 +00:00
|
|
|
#include "VersionInfoScreen.h"
|
2019-04-19 23:49:22 +00:00
|
|
|
#include "HomeMenuSelScreen.h"
|
2019-09-16 22:30:49 +00:00
|
|
|
#include "MenuSelScreen.h"
|
2019-09-08 00:14:36 +00:00
|
|
|
#include "TimeoutsScreen.h"
|
2019-07-26 13:12:00 +00:00
|
|
|
#include "HourMeterScreen.h"
|
2019-07-27 14:28:39 +00:00
|
|
|
#include "BTScreen.h"
|
|
|
|
#include "MenuTrunkScreen.h"
|
2019-09-04 10:59:01 +00:00
|
|
|
#include "MQTTScreen.h"
|
2019-09-21 23:03:42 +00:00
|
|
|
#include "DS18B20Screen.h"
|
2020-01-13 08:48:32 +00:00
|
|
|
#include "BME280Screen.h"
|
2019-10-18 01:55:16 +00:00
|
|
|
#include "TempSensorScreen.h"
|
2019-11-10 04:44:54 +00:00
|
|
|
#include "FrostScreen.h"
|
2020-01-13 08:48:32 +00:00
|
|
|
#include "HumidityScreen.h"
|
2020-03-25 09:28:12 +00:00
|
|
|
#include "WebPageUpdateScreen.h"
|
2020-06-19 01:24:44 +00:00
|
|
|
#include "433MHzScreen.h"
|
2020-03-30 05:17:54 +00:00
|
|
|
#include "LVCScreen.h"
|
2018-12-16 07:34:39 +00:00
|
|
|
#include <Wire.h>
|
|
|
|
#include "../cfg/pins.h"
|
|
|
|
#include "../cfg/BTCConfig.h"
|
2019-07-02 08:27:20 +00:00
|
|
|
#include "KeyPad.h"
|
2019-04-28 10:23:11 +00:00
|
|
|
#include "fonts/Icons.h"
|
|
|
|
#include "fonts/MiniFont.h"
|
2019-06-15 23:09:29 +00:00
|
|
|
#include "fonts/MidiFont.h"
|
|
|
|
#include "../Protocol/Protocol.h"
|
2019-07-28 01:37:39 +00:00
|
|
|
#include "fonts/Arial.h"
|
2019-08-01 12:57:18 +00:00
|
|
|
#include <SPIFFS.h>
|
2019-08-07 08:59:30 +00:00
|
|
|
#include "../Utility/BoardDetect.h"
|
2019-08-01 12:57:18 +00:00
|
|
|
|
|
|
|
#pragma pack ( push, 1)
|
|
|
|
struct sBMPhdr {
|
|
|
|
char b0;
|
|
|
|
char b1;
|
|
|
|
uint32_t filesize;
|
|
|
|
uint16_t resv1;
|
|
|
|
uint16_t resv2;
|
|
|
|
uint32_t startofs;
|
|
|
|
uint32_t hdrsize;
|
|
|
|
uint32_t width;
|
|
|
|
uint32_t height;
|
|
|
|
uint16_t numcolorplanes;
|
|
|
|
uint16_t bitsperpixel;
|
|
|
|
uint32_t compmethod;
|
|
|
|
uint32_t imagesize;
|
|
|
|
uint32_t hRes;
|
|
|
|
uint32_t vRes;
|
|
|
|
uint32_t numColorsPalette;
|
|
|
|
uint32_t numImportantColors;
|
|
|
|
};
|
|
|
|
#pragma pack (pop)
|
2018-11-25 04:45:17 +00:00
|
|
|
|
2019-08-03 02:42:49 +00:00
|
|
|
extern CScreenManager ScreenManager;
|
|
|
|
|
2018-11-27 10:44:47 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// splash creen created using image2cpp http://javl.github.io/image2cpp/
|
|
|
|
// Settings:
|
|
|
|
// Black background
|
|
|
|
// Invert [X]
|
|
|
|
// Arduino code, single bitmap
|
|
|
|
// Identifier: DieselSplash
|
|
|
|
// Draw Mode: Horizontal
|
|
|
|
//
|
2019-06-15 23:09:29 +00:00
|
|
|
|
|
|
|
|
2019-07-06 13:46:20 +00:00
|
|
|
const uint8_t DieselSplash [] PROGMEM =
|
2019-06-15 23:09:29 +00:00
|
|
|
{
|
|
|
|
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ####### ##
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0xC4, 0x00, 0x03, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # ##### # ## #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # # ##
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x03, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # # ## #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ### # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ##
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
|
|
|
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #
|
|
|
|
0x00, 0x30, 0x03, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ## ## ## #
|
|
|
|
0x00, 0x30, 0x07, 0x86, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ## #### ## ##
|
|
|
|
0x00, 0x78, 0x0E, 0xC6, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #### ### ## ## ##
|
|
|
|
0x00, 0x78, 0x0C, 0xC6, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // #### ## ## ## ##
|
|
|
|
0x00, 0xD8, 0x0C, 0x0C, 0x0E, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x1C, // ## ## ## ## ### ## ## ### ### ###
|
|
|
|
0x00, 0xCC, 0x18, 0x0C, 0x1F, 0x06, 0x3B, 0x1C, 0x00, 0x30, 0x31, 0xCC, 0x00, 0x1F, 0x06, 0x38, // ## ## ## ## ##### ## ### ## ### ## ## ### ## ##### ## ###
|
|
|
|
0x01, 0x8C, 0x18, 0xFF, 0xF3, 0x06, 0x73, 0x3E, 0x18, 0x30, 0x33, 0x8C, 0xF0, 0x33, 0x06, 0x70, // ## ## ## ############ ## ## ### ## ##### ## ## ## ### ## #### ## ## ## ###
|
|
|
|
0x03, 0x8C, 0x3F, 0x8C, 0x33, 0x0E, 0xC3, 0x66, 0x38, 0x30, 0x76, 0x0D, 0xF8, 0x33, 0x0E, 0xC0, // ### ## ####### ## ## ## ### ## ## ## ## ### ## ### ## ## ###### ## ## ### ##
|
|
|
|
0x03, 0x0C, 0x3E, 0x0C, 0x36, 0x17, 0x83, 0xC6, 0x58, 0x70, 0xBC, 0x0F, 0xB8, 0x76, 0x17, 0x80, // ## ## ##### ## ## ## # #### #### ## # ## ### # #### ##### ### ### ## # ####
|
|
|
|
0x07, 0xFE, 0x18, 0x0C, 0x3C, 0x27, 0x03, 0x86, 0x98, 0x71, 0x38, 0x0F, 0x18, 0xBC, 0x27, 0x00, // ########## ## ## #### # ### ### ## # ## ### # ### #### ## # #### # ###
|
|
|
|
0x0F, 0xCE, 0x18, 0x18, 0x30, 0x47, 0x03, 0x8F, 0x18, 0xDE, 0x38, 0x0E, 0x19, 0x30, 0x47, 0x00, // ###### ### ## ## ## # ### ### #### ## ## #### ### ### ## # ## # ###
|
|
|
|
0x1C, 0x07, 0x18, 0x18, 0x31, 0x86, 0x03, 0x1E, 0x19, 0x8C, 0x30, 0x0E, 0x1E, 0x31, 0x86, 0x00, // ### ### ## ## ## ## ## ## #### ## ## ## ## ### #### ## ## ##
|
|
|
|
0x38, 0x03, 0x18, 0x18, 0x3F, 0x06, 0x03, 0x38, 0x1F, 0x00, 0x30, 0x0C, 0x0C, 0x3F, 0x06, 0x00, // ### ## ## ## ###### ## ## ### ##### ## ## ## ###### ##
|
|
|
|
0x30, 0x01, 0x98, 0x18, 0x1E, 0x04, 0x01, 0xF0, 0x0C, 0x00, 0x20, 0x00, 0x00, 0x1E, 0x04, 0x00, // ## ## ## ## #### # ##### ## # #### #
|
|
|
|
0x20, 0x01, 0xB0, 0x30, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // # ## ## ## ##
|
|
|
|
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ##
|
|
|
|
0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ###
|
|
|
|
0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x21, 0x24, 0x00, // ### ## # # # # #
|
|
|
|
0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x24, 0x00, // ## # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x19, 0x28, 0xCA, 0x30, 0xE1, 0xC9, 0x06, 0x39, 0x25, 0x20, // ## ## # # # ## # # ## ### ### # # ## ### # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x25, 0x69, 0x2D, 0x49, 0x21, 0x29, 0x09, 0x29, 0x49, 0x20, // # # # # # ## # # # ## # # # # # # # # # # # # # # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x45, 0xAB, 0xC8, 0xF2, 0x22, 0x29, 0x10, 0x4A, 0x49, 0x20, // # # # # ## # # #### # #### # # # # # # # # # # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x45, 0xB2, 0x08, 0x82, 0x22, 0x2A, 0x10, 0x4A, 0x49, 0x40, // # # # # ## ## # # # # # # # # # # # # # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x49, 0x22, 0x50, 0x92, 0x42, 0x44, 0x11, 0x4A, 0x48, 0x80, // # # # # # # # # # # # # # # # # # # # # # # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x31, 0x21, 0x90, 0x61, 0x81, 0x84, 0x0E, 0x4A, 0x6C, 0x80, // ### ## # # ## # ## ## ## # ### # # # ## ## #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, // # # #
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
|
|
|
|
};
|
|
|
|
|
2018-11-27 10:44:47 +00:00
|
|
|
|
2019-08-01 12:57:18 +00:00
|
|
|
void storeSplashScreen(const uint8_t* image)
|
|
|
|
{
|
|
|
|
Preferences preferences;
|
|
|
|
|
|
|
|
DebugPort.println("Storing new splash screen");
|
|
|
|
preferences.begin("splashscreen", false);
|
|
|
|
preferences.putBytes("image", image, 1024);
|
|
|
|
preferences.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void loadSplashScreen(uint8_t* image)
|
|
|
|
{
|
|
|
|
Preferences preferences;
|
|
|
|
|
|
|
|
preferences.begin("splashscreen", false);
|
|
|
|
int size = preferences.getBytes("image", image, 1024);
|
|
|
|
preferences.end();
|
|
|
|
|
|
|
|
if(size == 0) {
|
|
|
|
storeSplashScreen(DieselSplash);
|
|
|
|
memcpy(image, DieselSplash, 1024);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-03 02:42:49 +00:00
|
|
|
void checkSplashScreenUpdate()
|
2019-08-01 12:57:18 +00:00
|
|
|
{
|
|
|
|
if(SPIFFS.exists("/splash.bmp")) { // If a splash.bmp file was uploaded
|
|
|
|
File file = SPIFFS.open("/splash.bmp", "rb"); // Open it
|
|
|
|
sBMPhdr header;
|
|
|
|
file.readBytes((char*)&header, 0x3e);
|
|
|
|
do {
|
|
|
|
if(header.b0 != 'B' || header.b1 != 'M') {
|
|
|
|
DebugPort.println("Bad BMP header");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(header.width != 128 || header.height != 64) {
|
|
|
|
DebugPort.println("Bad BMP size");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
file.seek(header.startofs);
|
|
|
|
bool bOK = true;
|
|
|
|
uint8_t image[1024];
|
|
|
|
uint8_t line[128];
|
|
|
|
switch(header.bitsperpixel) {
|
|
|
|
case 1:
|
|
|
|
DebugPort.println("Reading monochrome bitmap file for splash screen");
|
|
|
|
memset(image, 0, 1024);
|
|
|
|
for(int i=0; i<64; i++) {
|
|
|
|
file.readBytes((char*)line, 16);
|
|
|
|
for(int j=0; j < 16; j++)
|
|
|
|
line[j] ^= 0xff; // invert black/white
|
|
|
|
memcpy(&image[(63-i)*16], line, 16);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
DebugPort.println("Reading 16 color bitmap file for splash screen");
|
|
|
|
memset(image, 0, 1024);
|
|
|
|
for(int i=0; i<64; i++) {
|
|
|
|
file.readBytes((char*)line, 64);
|
|
|
|
for(int j=0; j < 16; j++) {
|
|
|
|
uint8_t packed = 0;
|
|
|
|
for(int k=0; k<4; k++) {
|
|
|
|
packed <<= 2;
|
|
|
|
uint8_t hold = line[k+j*4];
|
|
|
|
if((hold & 0xf0) == 0)
|
|
|
|
packed |= 0x02;
|
|
|
|
if((hold & 0x0f) == 0)
|
|
|
|
packed |= 0x01;
|
|
|
|
}
|
|
|
|
line[j] = packed;
|
|
|
|
}
|
|
|
|
memcpy(&image[(63-i)*16], line, 16);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
DebugPort.println("Reading 256 color bitmap file for splash screen");
|
|
|
|
memset(image, 0, 1024);
|
|
|
|
for(int i=0; i<64; i++) {
|
|
|
|
file.readBytes((char*)line, 128);
|
|
|
|
for(int j=0; j < 16; j++) {
|
|
|
|
uint8_t packed = 0;
|
|
|
|
for(int k=0; k<8; k++) {
|
|
|
|
packed <<= 1;
|
|
|
|
if(line[k+j*8] == 0)
|
|
|
|
packed |= 0x01;
|
|
|
|
}
|
|
|
|
line[j] = packed;
|
|
|
|
}
|
|
|
|
memcpy(&image[(63-i)*16], line, 16);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DebugPort.println("Bad BMP bpp");
|
|
|
|
bOK = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bOK)
|
|
|
|
storeSplashScreen(image);
|
|
|
|
|
|
|
|
} while(0);
|
|
|
|
|
|
|
|
file.close();
|
|
|
|
SPIFFS.remove("/splash.bmp");
|
2019-08-03 02:42:49 +00:00
|
|
|
|
|
|
|
ScreenManager.showSplash();
|
|
|
|
delay(2000);
|
2019-08-01 12:57:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-01 00:36:25 +00:00
|
|
|
|
2018-11-25 04:45:17 +00:00
|
|
|
CScreenManager::CScreenManager()
|
2018-11-17 02:08:22 +00:00
|
|
|
{
|
2018-11-25 04:45:17 +00:00
|
|
|
_pDisplay = NULL;
|
2019-03-15 12:42:54 +00:00
|
|
|
_menu = -1;
|
|
|
|
_subMenu = 0;
|
2019-03-15 10:48:22 +00:00
|
|
|
_rootMenu = -1;
|
2018-11-27 10:44:47 +00:00
|
|
|
_bReqUpdate = false;
|
2019-04-27 10:41:47 +00:00
|
|
|
_DimTime_ms = millis() + 60000;
|
|
|
|
_MenuTimeout = millis() + 60000;
|
2019-01-16 09:22:17 +00:00
|
|
|
_pRebootScreen = NULL;
|
2019-04-27 10:41:47 +00:00
|
|
|
_bDimmed = false;
|
2019-09-16 22:30:49 +00:00
|
|
|
_bReload = true;
|
2020-05-13 00:37:31 +00:00
|
|
|
_OTAholdoff = 0;
|
2018-11-25 04:45:17 +00:00
|
|
|
}
|
2018-11-23 10:34:37 +00:00
|
|
|
|
2018-11-25 04:45:17 +00:00
|
|
|
CScreenManager::~CScreenManager()
|
|
|
|
{
|
2019-03-15 12:42:54 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2019-01-18 07:09:40 +00:00
|
|
|
}
|
2018-11-25 04:45:17 +00:00
|
|
|
if(_pDisplay) {
|
|
|
|
delete _pDisplay; _pDisplay = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-09-16 22:30:49 +00:00
|
|
|
CScreenManager::begin()
|
2018-11-25 04:45:17 +00:00
|
|
|
{
|
|
|
|
|
2018-12-06 19:53:45 +00:00
|
|
|
// 128 x 64 OLED support (I2C)
|
2019-01-10 05:01:52 +00:00
|
|
|
// xxxx_SWITCHCAPVCC = generate display voltage from 3.3V internally
|
2018-11-26 10:26:38 +00:00
|
|
|
_pDisplay = new C128x64_OLED(OLED_SDA_pin, OLED_SCL_pin);
|
2019-01-10 05:01:52 +00:00
|
|
|
#if USE_ADAFRUIT_SH1106 == 1
|
2018-11-26 10:26:38 +00:00
|
|
|
_pDisplay->begin(SH1106_SWITCHCAPVCC);
|
2019-01-10 05:01:52 +00:00
|
|
|
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
|
2018-11-26 10:26:38 +00:00
|
|
|
|
2018-11-26 19:25:51 +00:00
|
|
|
// replace adafruit splash screen
|
2019-08-03 02:42:49 +00:00
|
|
|
showSplash();
|
2018-11-17 02:08:22 +00:00
|
|
|
|
2019-06-15 23:09:29 +00:00
|
|
|
delay(2000);
|
|
|
|
|
2019-09-16 22:30:49 +00:00
|
|
|
_loadScreens();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CScreenManager::_unloadScreens()
|
|
|
|
{
|
|
|
|
for (auto menuloop : _Screens) {
|
|
|
|
for(auto menu : menuloop) {
|
|
|
|
delete menu;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_Screens.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CScreenManager::_loadScreens()
|
|
|
|
{
|
|
|
|
_unloadScreens();
|
|
|
|
|
2018-12-07 11:16:04 +00:00
|
|
|
DebugPort.println("Creating Screens");
|
2019-03-15 12:42:54 +00:00
|
|
|
|
|
|
|
std::vector<CScreen*> menuloop;
|
|
|
|
// create root menu loop
|
2019-09-15 02:51:51 +00:00
|
|
|
if(NVstore.getUserSettings().menuMode == 0) {
|
|
|
|
menuloop.push_back(new CDetailedScreen(*_pDisplay, *this)); // detail control
|
2019-09-07 13:48:46 +00:00
|
|
|
menuloop.push_back(new CBasicScreen(*_pDisplay, *this)); // basic control
|
2019-09-16 22:30:49 +00:00
|
|
|
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
2019-09-15 02:51:51 +00:00
|
|
|
menuloop.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming
|
2019-09-07 13:48:46 +00:00
|
|
|
if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support
|
|
|
|
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
2019-09-15 02:51:51 +00:00
|
|
|
menuloop.push_back(new CMenuTrunkScreen(*_pDisplay, *this));
|
2019-09-07 13:48:46 +00:00
|
|
|
}
|
2019-09-15 02:51:51 +00:00
|
|
|
else if(NVstore.getUserSettings().menuMode == 1) {
|
|
|
|
menuloop.push_back(new CMenuTrunkScreen(*_pDisplay, *this));
|
|
|
|
menuloop.push_back(new CBasicScreen(*_pDisplay, *this)); // basic control
|
2019-09-16 22:30:49 +00:00
|
|
|
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
2019-09-15 02:51:51 +00:00
|
|
|
}
|
|
|
|
else if(NVstore.getUserSettings().menuMode == 2) {
|
|
|
|
menuloop.push_back(new CMenuTrunkScreen(*_pDisplay, *this));
|
2019-09-07 13:48:46 +00:00
|
|
|
menuloop.push_back(new CBasicScreen(*_pDisplay, *this)); // basic control
|
2019-09-16 22:30:49 +00:00
|
|
|
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
2019-09-07 13:48:46 +00:00
|
|
|
if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support
|
|
|
|
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
|
|
|
}
|
2019-03-15 12:42:54 +00:00
|
|
|
_Screens.push_back(menuloop);
|
2019-04-19 11:38:39 +00:00
|
|
|
|
2019-03-15 12:42:54 +00:00
|
|
|
// 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);
|
2019-04-19 11:38:39 +00:00
|
|
|
|
2019-04-09 23:28:46 +00:00
|
|
|
// create User Settings screens loop
|
|
|
|
menuloop.clear();
|
2020-01-13 08:48:32 +00:00
|
|
|
if(NVstore.getUserSettings().menuMode == 0) { // standard heater control menu set
|
2019-09-15 02:51:51 +00:00
|
|
|
menuloop.push_back(new CThermostatModeScreen(*_pDisplay, *this)); // thermostat settings screen
|
2019-11-10 04:44:54 +00:00
|
|
|
menuloop.push_back(new CFrostScreen(*_pDisplay, *this)); // frost mode screen
|
2020-01-13 08:48:32 +00:00
|
|
|
if(getTempSensor().getBME280().getCount()) {
|
|
|
|
menuloop.push_back(new CHumidityScreen(*_pDisplay, *this)); // humidity settings screen
|
|
|
|
}
|
2019-09-15 02:51:51 +00:00
|
|
|
menuloop.push_back(new CHomeMenuSelScreen(*_pDisplay, *this)); // Home menu settings screen
|
|
|
|
menuloop.push_back(new CTimeoutsScreen(*_pDisplay, *this)); // Other options screen
|
2019-09-16 22:30:49 +00:00
|
|
|
menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen
|
2019-09-07 13:48:46 +00:00
|
|
|
if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ?
|
|
|
|
menuloop.push_back(new CGPIOSetupScreen(*_pDisplay, *this)); // GPIO settings screen
|
|
|
|
}
|
2020-01-13 08:48:32 +00:00
|
|
|
else if(NVstore.getUserSettings().menuMode == 1) { // "no fiddle" menu set
|
2019-09-16 22:30:49 +00:00
|
|
|
menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen
|
2019-09-15 02:51:51 +00:00
|
|
|
}
|
2020-01-13 08:48:32 +00:00
|
|
|
else if(NVstore.getUserSettings().menuMode == 2) { // no heater menu set
|
2019-09-15 02:51:51 +00:00
|
|
|
menuloop.push_back(new CNoHeaterHomeMenuSelScreen(*_pDisplay, *this)); // No Heater Home menu settings screen
|
2019-09-16 22:30:49 +00:00
|
|
|
menuloop.push_back(new CMenuSelScreen(*_pDisplay, *this)); // Menu mode screen
|
2020-05-09 09:17:21 +00:00
|
|
|
// if(getBoardRevision() != 0 && getBoardRevision() != BRD_V2_NOGPIO) // has GPIO support ?
|
|
|
|
// menuloop.push_back(new CGPIOSetupScreen(*_pDisplay, *this)); // GPIO settings screen
|
2019-09-07 13:48:46 +00:00
|
|
|
}
|
2019-07-27 14:28:39 +00:00
|
|
|
_Screens.push_back(menuloop);
|
|
|
|
|
|
|
|
// create System Settings screens loop
|
2019-09-15 02:51:51 +00:00
|
|
|
if(NVstore.getUserSettings().menuMode == 0 || NVstore.getUserSettings().menuMode == 2) {
|
|
|
|
menuloop.clear();
|
|
|
|
menuloop.push_back(new CVersionInfoScreen(*_pDisplay, *this)); // GPIO settings screen
|
2020-03-25 09:28:12 +00:00
|
|
|
menuloop.push_back(new CWebPageUpdateScreen(*_pDisplay, *this)); // Web Page update screen
|
2019-09-15 02:51:51 +00:00
|
|
|
if(NVstore.getUserSettings().menuMode == 0) {
|
|
|
|
menuloop.push_back(new CHourMeterScreen(*_pDisplay, *this)); // Hour Meter screen
|
2020-05-09 09:17:21 +00:00
|
|
|
menuloop.push_back(new CWiFiScreen(*_pDisplay, *this));
|
2019-09-15 02:51:51 +00:00
|
|
|
}
|
2020-03-23 05:54:15 +00:00
|
|
|
menuloop.push_back(new CWiFiSTAScreen(*_pDisplay, *this));
|
2019-09-15 02:51:51 +00:00
|
|
|
menuloop.push_back(new CMQTTScreen(*_pDisplay, *this));
|
|
|
|
menuloop.push_back(new CBTScreen(*_pDisplay, *this));
|
2020-06-19 01:24:44 +00:00
|
|
|
menuloop.push_back(new C433MHzScreen(*_pDisplay, *this));
|
2020-01-13 08:48:32 +00:00
|
|
|
if(getTempSensor().getBME280().getCount()) {
|
2019-10-18 01:55:16 +00:00
|
|
|
menuloop.push_back(new CTempSensorScreen(*_pDisplay, *this));
|
2020-01-13 08:48:32 +00:00
|
|
|
menuloop.push_back(new CBME280Screen(*_pDisplay, *this));
|
|
|
|
}
|
|
|
|
else {
|
2019-10-18 01:55:16 +00:00
|
|
|
menuloop.push_back(new CDS18B20Screen(*_pDisplay, *this));
|
2020-01-13 08:48:32 +00:00
|
|
|
}
|
2019-09-15 02:51:51 +00:00
|
|
|
_Screens.push_back(menuloop);
|
2019-09-07 13:48:46 +00:00
|
|
|
}
|
2019-09-15 02:51:51 +00:00
|
|
|
|
|
|
|
// create heater tuning screens loop - password protected
|
|
|
|
menuloop.clear();
|
|
|
|
menuloop.push_back(new CFuelMixtureScreen(*_pDisplay, *this)); // mixture tuning
|
|
|
|
menuloop.push_back(new CHeaterSettingsScreen(*_pDisplay, *this)); // heater system tuning
|
|
|
|
menuloop.push_back(new CFuelCalScreen(*_pDisplay, *this)); // fuel pump calibration
|
2020-03-30 05:17:54 +00:00
|
|
|
menuloop.push_back(new CLVCScreen(*_pDisplay, *this)); // low volt cutout calibration
|
2019-04-09 23:28:46 +00:00
|
|
|
_Screens.push_back(menuloop);
|
2019-04-19 11:38:39 +00:00
|
|
|
|
2019-03-15 10:48:22 +00:00
|
|
|
// create branch screens
|
2019-03-15 12:42:54 +00:00
|
|
|
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
|
2019-07-27 14:28:39 +00:00
|
|
|
menuloop.push_back(new CSettingsScreen(*_pDisplay, *this)); // Tuning info
|
2019-10-18 01:55:16 +00:00
|
|
|
menuloop.push_back(new CDS18B20Screen(*_pDisplay, *this));
|
2019-03-15 12:42:54 +00:00
|
|
|
_Screens.push_back(menuloop);
|
2018-12-09 01:10:56 +00:00
|
|
|
|
2019-03-15 12:42:54 +00:00
|
|
|
_menu = 0;
|
2018-12-09 01:10:56 +00:00
|
|
|
#if RTC_USE_DS3231==0 && RTC_USE_DS1307==0 && RTC_USE_PCF8523==0
|
2019-03-15 12:42:54 +00:00
|
|
|
_rootMenu = 2; // bring up clock set screen first if using millis based RTC!
|
|
|
|
_subMenu = 2;
|
2018-12-09 01:10:56 +00:00
|
|
|
#else
|
2019-03-15 10:48:22 +00:00
|
|
|
_rootMenu = 1; // basic control screen
|
2019-03-15 12:42:54 +00:00
|
|
|
_subMenu = 1;
|
2018-12-09 01:10:56 +00:00
|
|
|
#endif
|
2019-09-16 22:30:49 +00:00
|
|
|
_bReload = false;
|
|
|
|
reqUpdate();
|
2019-02-28 08:56:13 +00:00
|
|
|
_enterScreen();
|
2020-04-22 06:21:24 +00:00
|
|
|
showSplash();
|
2018-11-17 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
2020-05-13 00:37:31 +00:00
|
|
|
bool
|
|
|
|
CScreenManager::_checkOTAholdoff()
|
|
|
|
{
|
|
|
|
if(_OTAholdoff) {
|
|
|
|
long tDelta = millis() - _OTAholdoff;
|
|
|
|
if(tDelta < 0)
|
|
|
|
return false;
|
|
|
|
_pDisplay->clearDisplay();
|
|
|
|
_pDisplay->display(); // blank screen
|
|
|
|
_OTAholdoff = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2018-12-01 18:25:10 +00:00
|
|
|
bool
|
2018-12-01 00:36:25 +00:00
|
|
|
CScreenManager::checkUpdate()
|
2018-11-25 04:45:17 +00:00
|
|
|
{
|
2020-05-13 00:37:31 +00:00
|
|
|
if(!_checkOTAholdoff())
|
|
|
|
return false;
|
|
|
|
|
2019-09-16 22:30:49 +00:00
|
|
|
if(_bReload)
|
|
|
|
_loadScreens();
|
|
|
|
|
2019-06-06 01:32:43 +00:00
|
|
|
long dimTimeout = NVstore.getUserSettings().dimTime;
|
2019-04-27 10:41:47 +00:00
|
|
|
|
|
|
|
// manage dimming or blanking the display, according to user defined inactivity interval
|
|
|
|
if(dimTimeout && _DimTime_ms) {
|
|
|
|
long tDelta = millis() - _DimTime_ms;
|
2018-12-22 10:32:13 +00:00
|
|
|
if(tDelta > 0) {
|
2019-02-28 07:14:02 +00:00
|
|
|
// time to dim the display
|
2019-04-27 10:41:47 +00:00
|
|
|
_dim(true);
|
|
|
|
_DimTime_ms = 0;
|
|
|
|
|
|
|
|
if(dimTimeout < 0) {
|
|
|
|
_pDisplay->clearDisplay();
|
|
|
|
_pDisplay->display(); // blank screen
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-06 01:32:43 +00:00
|
|
|
if(NVstore.getUserSettings().menuTimeout && _MenuTimeout) {
|
2019-04-27 10:41:47 +00:00
|
|
|
long tDelta = millis() - _MenuTimeout;
|
|
|
|
if(tDelta > 0) {
|
|
|
|
_MenuTimeout = 0;
|
|
|
|
// we will be blanking the display, transit through a dim stage first
|
|
|
|
if(dimTimeout < 0)
|
|
|
|
_dim(true);
|
2019-02-28 07:14:02 +00:00
|
|
|
|
2019-02-28 08:56:13 +00:00
|
|
|
_leaveScreen();
|
2019-02-28 07:14:02 +00:00
|
|
|
// fall back to main menu
|
2019-03-15 21:43:44 +00:00
|
|
|
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
|
2019-09-15 02:51:51 +00:00
|
|
|
if((_rootMenu > 2) || ((_rootMenu == 0) && NVstore.getUserSettings().menuMode)) {
|
2019-11-21 08:25:14 +00:00
|
|
|
selectHomeMenu();
|
2019-02-28 07:14:02 +00:00
|
|
|
}
|
2019-02-28 08:56:13 +00:00
|
|
|
_enterScreen();
|
2018-12-22 10:32:13 +00:00
|
|
|
}
|
2019-04-20 09:13:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int prevRunState = -1;
|
|
|
|
int runState = getHeaterInfo().getRunStateEx();
|
|
|
|
if(runState != prevRunState) {
|
|
|
|
if(runState > 0 && prevRunState == 0) {
|
|
|
|
// heater has started
|
2019-07-03 13:01:36 +00:00
|
|
|
uint8_t userStartMenu = NVstore.getUserSettings().HomeMenu.onStart;
|
2019-07-19 20:53:12 +00:00
|
|
|
if(userStartMenu && userStartMenu <= 3) { // allow user to override default screen
|
2019-04-20 09:13:24 +00:00
|
|
|
userStartMenu--;
|
|
|
|
DebugPort.print("Screen Manager: Heater start detected, switching to user preferred screen: ");
|
|
|
|
switch(userStartMenu) {
|
|
|
|
case 0: DebugPort.println("Detailed control menu"); break;
|
|
|
|
case 1: DebugPort.println("Basic control menu"); break;
|
|
|
|
case 2: DebugPort.println("Clock menu"); break;
|
|
|
|
}
|
|
|
|
_rootMenu = _subMenu = userStartMenu;
|
|
|
|
_enterScreen();
|
|
|
|
}
|
|
|
|
}
|
2019-07-19 20:53:12 +00:00
|
|
|
if(runState == 0 && prevRunState > 0) {
|
2019-04-20 09:13:24 +00:00
|
|
|
// heater has stopped
|
2019-07-03 13:01:36 +00:00
|
|
|
uint8_t userStopMenu = NVstore.getUserSettings().HomeMenu.onStop;
|
2019-07-19 20:53:12 +00:00
|
|
|
if(userStopMenu && userStopMenu <= 3) { // allow user to override default screen
|
2019-04-20 09:13:24 +00:00
|
|
|
userStopMenu--;
|
|
|
|
DebugPort.print("Screen Manager: Heater stop detected, switching to user preferred screen: ");
|
|
|
|
switch(userStopMenu) {
|
|
|
|
case 0: DebugPort.println("Detailed control menu"); break;
|
|
|
|
case 1: DebugPort.println("Basic control menu"); break;
|
|
|
|
case 2: DebugPort.println("Clock menu"); break;
|
|
|
|
}
|
|
|
|
_rootMenu = _subMenu = userStopMenu;
|
|
|
|
_enterScreen();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
prevRunState = runState;
|
2018-12-22 10:32:13 +00:00
|
|
|
}
|
|
|
|
|
2019-04-20 09:13:24 +00:00
|
|
|
|
2018-11-27 10:44:47 +00:00
|
|
|
if(_bReqUpdate) {
|
2019-04-27 10:41:47 +00:00
|
|
|
if((dimTimeout < 0) && (_DimTime_ms == 0)) {
|
|
|
|
// no screen updates, we should be blanked!
|
2019-01-16 09:22:17 +00:00
|
|
|
}
|
|
|
|
else {
|
2019-04-27 10:41:47 +00:00
|
|
|
if(_pRebootScreen) {
|
|
|
|
_pRebootScreen->show();
|
2019-01-16 09:22:17 +00:00
|
|
|
_bReqUpdate = false;
|
|
|
|
return true;
|
|
|
|
}
|
2019-04-27 10:41:47 +00:00
|
|
|
else {
|
|
|
|
if(_menu >= 0) {
|
|
|
|
_Screens[_menu][_subMenu]->show();
|
|
|
|
_bReqUpdate = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2018-11-27 10:44:47 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-01 18:25:10 +00:00
|
|
|
return false;
|
2018-11-25 04:45:17 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 10:44:47 +00:00
|
|
|
void
|
|
|
|
CScreenManager::reqUpdate()
|
|
|
|
{
|
|
|
|
_bReqUpdate = true;
|
|
|
|
}
|
|
|
|
|
2018-12-01 18:25:10 +00:00
|
|
|
bool
|
2018-11-25 04:45:17 +00:00
|
|
|
CScreenManager::animate()
|
2018-11-17 02:08:22 +00:00
|
|
|
{
|
2020-05-13 00:37:31 +00:00
|
|
|
if(!_checkOTAholdoff())
|
|
|
|
return false;
|
|
|
|
|
2019-06-06 01:32:43 +00:00
|
|
|
if(_pRebootScreen)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if((NVstore.getUserSettings().dimTime < 0) && (_DimTime_ms == 0))
|
2019-04-27 10:41:47 +00:00
|
|
|
// no screen updates, we should be blanked!
|
|
|
|
return false;
|
2019-06-06 01:32:43 +00:00
|
|
|
|
2019-03-15 12:42:54 +00:00
|
|
|
if(_menu >= 0)
|
|
|
|
return _Screens[_menu][_subMenu]->animate();
|
2019-06-06 01:32:43 +00:00
|
|
|
|
2018-12-01 18:25:10 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CScreenManager::refresh()
|
|
|
|
{
|
|
|
|
if(_pDisplay)
|
|
|
|
_pDisplay->display();
|
2018-11-25 04:45:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-02-28 08:56:13 +00:00
|
|
|
CScreenManager::_enterScreen()
|
2018-11-25 04:45:17 +00:00
|
|
|
{
|
2019-03-15 12:42:54 +00:00
|
|
|
if(_menu >= 0)
|
|
|
|
_Screens[_menu][_subMenu]->onSelect();
|
2018-12-08 04:18:37 +00:00
|
|
|
|
2018-11-27 10:44:47 +00:00
|
|
|
reqUpdate();
|
2018-11-25 04:45:17 +00:00
|
|
|
}
|
|
|
|
|
2019-02-28 08:56:13 +00:00
|
|
|
void
|
|
|
|
CScreenManager::_leaveScreen()
|
|
|
|
{
|
2019-03-15 12:42:54 +00:00
|
|
|
if(_menu >= 0)
|
|
|
|
_Screens[_menu][_subMenu]->onExit();
|
2019-10-18 01:55:16 +00:00
|
|
|
|
|
|
|
_returnMenu = _menu;
|
|
|
|
_returnSubMenu = _subMenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CScreenManager::returnMenu()
|
|
|
|
{
|
|
|
|
_menu = _returnMenu;
|
|
|
|
_subMenu = _returnSubMenu;
|
|
|
|
_enterScreen();
|
2019-02-28 08:56:13 +00:00
|
|
|
}
|
|
|
|
|
2019-03-15 21:43:44 +00:00
|
|
|
void
|
|
|
|
CScreenManager::_changeSubMenu(int dir)
|
|
|
|
{
|
|
|
|
_leaveScreen();
|
|
|
|
_subMenu += dir;
|
|
|
|
int bounds = _Screens[_menu].size() - 1;
|
2019-06-02 12:47:35 +00:00
|
|
|
WRAPLIMITS(_subMenu, 0, bounds);
|
2019-03-15 21:43:44 +00:00
|
|
|
if(_menu == 0)
|
|
|
|
_rootMenu = _subMenu; // track the root menu for when we branch then return
|
|
|
|
_enterScreen();
|
|
|
|
}
|
|
|
|
|
2018-11-25 04:45:17 +00:00
|
|
|
void
|
2019-03-15 21:43:44 +00:00
|
|
|
CScreenManager::nextMenu()
|
2018-11-25 04:45:17 +00:00
|
|
|
{
|
2019-03-15 21:43:44 +00:00
|
|
|
if(_menu >= 0 && _menu != BranchMenu) {
|
|
|
|
_changeSubMenu(+1);
|
2018-11-23 10:34:37 +00:00
|
|
|
}
|
2018-11-25 04:45:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-15 21:43:44 +00:00
|
|
|
CScreenManager::prevMenu()
|
2018-11-25 04:45:17 +00:00
|
|
|
{
|
2019-03-15 21:43:44 +00:00
|
|
|
if(_menu >= 0 && _menu != BranchMenu) {
|
|
|
|
_changeSubMenu(-1);
|
2018-11-25 04:45:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CScreenManager::keyHandler(uint8_t event)
|
|
|
|
{
|
2019-04-27 10:41:47 +00:00
|
|
|
if(_bDimmed) {
|
2019-04-08 23:12:42 +00:00
|
|
|
if(event & keyReleased) {
|
2019-04-27 10:41:47 +00:00
|
|
|
_dim(false);
|
2019-07-20 06:08:43 +00:00
|
|
|
bumpTimeout();
|
2019-04-08 23:12:42 +00:00
|
|
|
}
|
2019-04-27 10:41:47 +00:00
|
|
|
return; // initial press when dimmed is always thrown away
|
2019-01-19 11:05:14 +00:00
|
|
|
}
|
2018-12-22 10:32:13 +00:00
|
|
|
|
2019-07-20 06:08:43 +00:00
|
|
|
bumpTimeout();
|
2019-01-20 03:19:38 +00:00
|
|
|
|
2019-03-01 23:32:50 +00:00
|
|
|
// call key handler for active screen
|
2019-03-15 12:42:54 +00:00
|
|
|
if(_menu >= 0)
|
|
|
|
_Screens[_menu][_subMenu]->keyHandler(event);
|
2018-11-17 02:08:22 +00:00
|
|
|
}
|
|
|
|
|
2019-07-20 06:08:43 +00:00
|
|
|
void
|
|
|
|
CScreenManager::bumpTimeout()
|
|
|
|
{
|
|
|
|
long dimTime = NVstore.getUserSettings().dimTime;
|
|
|
|
_DimTime_ms = (millis() + abs(dimTime)) | 1;
|
|
|
|
_MenuTimeout = (millis() + NVstore.getUserSettings().menuTimeout) | 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-03-01 23:32:50 +00:00
|
|
|
void
|
2019-03-15 21:43:44 +00:00
|
|
|
CScreenManager::selectMenu(eUIMenuSets menuSet, int specific)
|
2019-03-15 07:19:30 +00:00
|
|
|
{
|
|
|
|
_leaveScreen();
|
2019-03-15 21:43:44 +00:00
|
|
|
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!
|
2019-07-19 20:53:12 +00:00
|
|
|
DebugPort.printf("selectMenu %d %d\r\n", _menu, _subMenu);
|
2019-03-15 21:43:44 +00:00
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
2019-03-15 12:42:54 +00:00
|
|
|
}
|
2019-03-15 07:19:30 +00:00
|
|
|
_enterScreen();
|
|
|
|
}
|
|
|
|
|
2019-01-16 09:22:17 +00:00
|
|
|
void
|
|
|
|
CScreenManager::showRebootMsg(const char* content[2], long delayTime)
|
|
|
|
{
|
|
|
|
if(_pRebootScreen == NULL)
|
|
|
|
_pRebootScreen = new CRebootScreen(*_pDisplay, *this);
|
|
|
|
|
|
|
|
_pRebootScreen->setMessage(content, delayTime);
|
|
|
|
_bReqUpdate = true;
|
2019-04-27 10:41:47 +00:00
|
|
|
_dim(false);
|
2019-01-16 09:22:17 +00:00
|
|
|
}
|
2019-01-18 07:09:40 +00:00
|
|
|
|
2019-07-28 10:59:26 +00:00
|
|
|
void
|
|
|
|
CScreenManager::clearDisplay()
|
|
|
|
{
|
|
|
|
_pDisplay->clearDisplay();
|
|
|
|
}
|
|
|
|
|
2019-05-11 02:18:06 +00:00
|
|
|
void
|
2019-06-02 20:34:45 +00:00
|
|
|
CScreenManager::showOTAMessage(int percent, eOTAmodes updateType)
|
2019-05-11 02:18:06 +00:00
|
|
|
{
|
|
|
|
static int prevPercent = -1;
|
2019-07-06 13:46:20 +00:00
|
|
|
|
2019-07-28 01:37:39 +00:00
|
|
|
if(percent != prevPercent) {
|
2020-05-13 00:37:31 +00:00
|
|
|
DebugPort.printf("%d%%\r\n", percent);
|
2019-07-28 10:59:26 +00:00
|
|
|
prevPercent = percent;
|
2019-05-11 02:18:06 +00:00
|
|
|
_pDisplay->clearDisplay();
|
2019-07-28 10:59:26 +00:00
|
|
|
if(percent < 0)
|
|
|
|
return;
|
|
|
|
|
2019-07-28 01:37:39 +00:00
|
|
|
_pDisplay->setFontInfo(&arial_8ptBoldFontInfo);
|
|
|
|
_pDisplay->setCursor(64, -1);
|
|
|
|
_pDisplay->printCentreJustified("Firmware update");
|
|
|
|
_pDisplay->setFontInfo(NULL);
|
|
|
|
_pDisplay->drawFastHLine(0, 10, 128, WHITE);
|
2019-05-11 02:18:06 +00:00
|
|
|
_pDisplay->setCursor(64,22);
|
2019-06-02 20:34:45 +00:00
|
|
|
switch(updateType) {
|
2019-07-28 01:37:39 +00:00
|
|
|
case eOTAnormal: _pDisplay->printCentreJustified("OTA upload"); break;
|
|
|
|
case eOTAbrowser: _pDisplay->printCentreJustified("Browser upload"); break;
|
|
|
|
case eOTAWWW: _pDisplay->printCentreJustified("Web download"); break;
|
2019-06-02 20:34:45 +00:00
|
|
|
}
|
2019-05-11 02:18:06 +00:00
|
|
|
if(percent) {
|
2019-07-28 01:37:39 +00:00
|
|
|
_pDisplay->drawRect(14, 32, 100, 8, WHITE);
|
|
|
|
_pDisplay->fillRect(14, 32, percent, 8, WHITE);
|
2019-05-11 02:18:06 +00:00
|
|
|
char msg[16];
|
|
|
|
sprintf(msg, "%d%%", percent);
|
2019-07-28 01:37:39 +00:00
|
|
|
_pDisplay->setCursor(64,42);
|
2019-05-11 02:18:06 +00:00
|
|
|
_pDisplay->printCentreJustified(msg);
|
|
|
|
}
|
|
|
|
_pDisplay->display();
|
|
|
|
}
|
2020-05-13 00:37:31 +00:00
|
|
|
_OTAholdoff = millis() + 1000;
|
2019-05-11 02:18:06 +00:00
|
|
|
}
|
|
|
|
|
2019-04-27 10:41:47 +00:00
|
|
|
void
|
|
|
|
CScreenManager::_dim(bool state)
|
|
|
|
{
|
|
|
|
_bDimmed = state;
|
|
|
|
_pDisplay->dim(state);
|
2019-08-01 12:57:18 +00:00
|
|
|
}
|
|
|
|
|
2019-08-03 02:42:49 +00:00
|
|
|
void
|
|
|
|
CScreenManager::showSplash()
|
|
|
|
{
|
|
|
|
_pDisplay->clearDisplay();
|
|
|
|
uint8_t splash[1024];
|
|
|
|
loadSplashScreen(splash);
|
|
|
|
_pDisplay->drawBitmap(0, 0, splash, 128, 64, WHITE);
|
|
|
|
_pDisplay->setTextColor(WHITE);
|
2020-01-04 07:13:40 +00:00
|
|
|
{
|
|
|
|
CTransientFont AF(*_pDisplay, &segoeUI_Italic_7ptFontInfo); // temporarily use a midi font
|
|
|
|
_pDisplay->setCursor(90, 56);
|
|
|
|
_pDisplay->print(getVersionStr());
|
|
|
|
}
|
|
|
|
{
|
|
|
|
CTransientFont AF(*_pDisplay, &arial_8ptBoldFontInfo);
|
|
|
|
_pDisplay->setCursor(10, 54);
|
|
|
|
_pDisplay->print(getVersionStr(true)); // prints "BETA" if minor version defined
|
|
|
|
}
|
2019-08-03 02:42:49 +00:00
|
|
|
|
|
|
|
// Show initial display buffer contents on the screen --
|
|
|
|
_pDisplay->display();
|
|
|
|
}
|
2019-11-21 08:25:14 +00:00
|
|
|
|
2020-04-22 06:21:24 +00:00
|
|
|
void
|
|
|
|
CScreenManager::showBootMsg(const char* msg)
|
|
|
|
{
|
|
|
|
CTransientFont AF(*_pDisplay, &arialItalic_7ptFontInfo);
|
|
|
|
_pDisplay->fillRect(0, 50, 128, 14, BLACK);
|
|
|
|
_pDisplay->setCursor(0, 50);
|
|
|
|
_pDisplay->print(msg);
|
|
|
|
_pDisplay->display();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CScreenManager::showBootWait(int show)
|
|
|
|
{
|
|
|
|
static int idx = 0;
|
|
|
|
// idx++;
|
|
|
|
BITMAP_INFO bitmap = hourGlassIcon0Info;
|
|
|
|
switch(idx++ & 0x03) {
|
|
|
|
case 0: bitmap = hourGlassIcon0Info; break;
|
|
|
|
case 1: bitmap = hourGlassIcon1Info; break;
|
|
|
|
case 2: bitmap = hourGlassIcon2Info; break;
|
|
|
|
case 3: bitmap = hourGlassIcon3Info; break;
|
|
|
|
}
|
|
|
|
_pDisplay->fillRect(80, 50, bitmap.width, bitmap.height, BLACK);
|
|
|
|
if(show)
|
|
|
|
_pDisplay->drawBitmap(80, 50, bitmap.pBitmap, bitmap.width, bitmap.height, WHITE);
|
|
|
|
_pDisplay->display();
|
|
|
|
}
|
|
|
|
|
2019-11-21 08:25:14 +00:00
|
|
|
void
|
|
|
|
CScreenManager::selectHomeMenu()
|
|
|
|
{
|
|
|
|
uint8_t userHomeMenu = NVstore.getUserSettings().HomeMenu.onTimeout;
|
|
|
|
if(userHomeMenu) { // allow user to override defualt screen
|
|
|
|
userHomeMenu--;
|
|
|
|
DebugPort.print("Screen Manager: Menu timeout, falling back to user preferred screen: ");
|
|
|
|
switch(userHomeMenu) {
|
|
|
|
case 0: DebugPort.println("Detailed control menu"); break;
|
|
|
|
case 1: DebugPort.println("Basic control menu"); break;
|
|
|
|
case 2: DebugPort.println("Clock menu"); break;
|
|
|
|
}
|
|
|
|
_rootMenu = _subMenu = userHomeMenu;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_rootMenu = _subMenu = 1;
|
|
|
|
DebugPort.println("Screen Manager: Menu timeout, falling back to Basic control screen");
|
|
|
|
}
|
|
|
|
}
|