Added ability to upload custom splash ScreenFlowV3.dia.
Added 4th board type - GPIO disabled on V2.0 PCB - install 0R in C6, leave other bits out.
This commit is contained in:
parent
945d9c88b7
commit
ac091fa6d8
6 changed files with 176 additions and 20 deletions
|
@ -114,6 +114,7 @@
|
||||||
#include <rom/rtc.h>
|
#include <rom/rtc.h>
|
||||||
#include <esp_spiffs.h>
|
#include <esp_spiffs.h>
|
||||||
#include <SPIFFS.h>
|
#include <SPIFFS.h>
|
||||||
|
#include <nvs.h>
|
||||||
|
|
||||||
// SSID & password now stored in NV storage - these are still the default values.
|
// SSID & password now stored in NV storage - these are still the default values.
|
||||||
//#define AP_SSID "Afterburner"
|
//#define AP_SSID "Afterburner"
|
||||||
|
@ -323,6 +324,9 @@ void setup() {
|
||||||
digitalWrite(GPIOout1_pin, LOW);
|
digitalWrite(GPIOout1_pin, LOW);
|
||||||
digitalWrite(GPIOout2_pin, LOW);
|
digitalWrite(GPIOout2_pin, LOW);
|
||||||
|
|
||||||
|
nvs_stats_t nvs_stats;
|
||||||
|
esp_err_t err = nvs_get_stats(NULL, &nvs_stats);
|
||||||
|
|
||||||
// initialise TelnetSpy (port 23) as well as Serial to 115200
|
// initialise TelnetSpy (port 23) as well as Serial to 115200
|
||||||
// Serial is the usual USB connection to a PC
|
// Serial is the usual USB connection to a PC
|
||||||
// DO THIS BEFORE WE TRY AND SEND DEBUG INFO!
|
// DO THIS BEFORE WE TRY AND SEND DEBUG INFO!
|
||||||
|
@ -351,6 +355,7 @@ void setup() {
|
||||||
DebugPort.printf("Board revision: V%.1f\r\n", float(BoardRevision) * 0.1);
|
DebugPort.printf("Board revision: V%.1f\r\n", float(BoardRevision) * 0.1);
|
||||||
|
|
||||||
DebugPort.printf("ESP32 IDF Version: %s\r\n", esp_get_idf_version());
|
DebugPort.printf("ESP32 IDF Version: %s\r\n", esp_get_idf_version());
|
||||||
|
DebugPort.printf("NVS: entries- free=%d used=%d total=%d namespace count=%d\r\n", nvs_stats.free_entries, nvs_stats.used_entries, nvs_stats.total_entries, nvs_stats.namespace_count);
|
||||||
|
|
||||||
// Initialize SPIFFS
|
// Initialize SPIFFS
|
||||||
if(!SPIFFS.begin(true)){
|
if(!SPIFFS.begin(true)){
|
||||||
|
@ -1330,7 +1335,7 @@ bool isCyclicActive()
|
||||||
|
|
||||||
void setupGPIO()
|
void setupGPIO()
|
||||||
{
|
{
|
||||||
if(BoardRevision) {
|
if(BoardRevision == 10 || BoardRevision == 20 || BoardRevision == 21) {
|
||||||
// some special considerations for GPIO inputs, depending upon PCB hardware
|
// some special considerations for GPIO inputs, depending upon PCB hardware
|
||||||
// V1.0 PCBs only expose bare inputs, which are pulled high. Active state into ESP32 is LOW.
|
// V1.0 PCBs only expose bare inputs, which are pulled high. Active state into ESP32 is LOW.
|
||||||
// V2.0+ PCBs use an input transistor buffer. Active state into ESP32 is HIGH (inverted).
|
// V2.0+ PCBs use an input transistor buffer. Active state into ESP32 is HIGH (inverted).
|
||||||
|
@ -1363,7 +1368,7 @@ void setupGPIO()
|
||||||
GPIOalg.begin(GPIOalg_pin, algMode);
|
GPIOalg.begin(GPIOalg_pin, algMode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// unknown board - deny all GPIO operation (unlikely)
|
// unknown board or forced no GPIO by grounding pin26 - deny all GPIO operation
|
||||||
GPIOin.begin(0, 0, GPIOinNone, LOW);
|
GPIOin.begin(0, 0, GPIOinNone, LOW);
|
||||||
GPIOout.begin(0, 0, GPIOoutNone);
|
GPIOout.begin(0, 0, GPIOoutNone);
|
||||||
GPIOalg.begin(ADC1_CHANNEL_5, GPIOalgNone);
|
GPIOalg.begin(ADC1_CHANNEL_5, GPIOalgNone);
|
||||||
|
@ -1379,10 +1384,14 @@ bool toggleGPIOout(int channel)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGPIOout(int channel, bool state)
|
bool setGPIOout(int channel, bool state)
|
||||||
{
|
{
|
||||||
|
if(GPIOout.getMode() != GPIOoutNone) {
|
||||||
DebugPort.printf("setGPIO: Output #%d = %d\r\n", channel+1, state);
|
DebugPort.printf("setGPIO: Output #%d = %d\r\n", channel+1, state);
|
||||||
GPIOout.setState(channel, state);
|
GPIOout.setState(channel, state);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getGPIOout(int channel)
|
bool getGPIOout(int channel)
|
||||||
|
|
|
@ -52,7 +52,29 @@
|
||||||
#include "fonts/MidiFont.h"
|
#include "fonts/MidiFont.h"
|
||||||
#include "../Protocol/Protocol.h"
|
#include "../Protocol/Protocol.h"
|
||||||
#include "fonts/Arial.h"
|
#include "fonts/Arial.h"
|
||||||
|
#include <SPIFFS.h>
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// splash creen created using image2cpp http://javl.github.io/image2cpp/
|
// splash creen created using image2cpp http://javl.github.io/image2cpp/
|
||||||
|
@ -202,6 +224,114 @@ const uint8_t DieselSplash [] PROGMEM =
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void storeSplashScreenFile()
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CScreenManager::CScreenManager()
|
CScreenManager::CScreenManager()
|
||||||
{
|
{
|
||||||
|
@ -249,7 +379,10 @@ CScreenManager::begin(bool bNoClock)
|
||||||
|
|
||||||
// replace adafruit splash screen
|
// replace adafruit splash screen
|
||||||
_pDisplay->clearDisplay();
|
_pDisplay->clearDisplay();
|
||||||
_pDisplay->drawBitmap(0, 0, DieselSplash, 128, 64, WHITE);
|
uint8_t splash[1024];
|
||||||
|
loadSplashScreen(splash);
|
||||||
|
_pDisplay->drawBitmap(0, 0, splash, 128, 64, WHITE);
|
||||||
|
// _pDisplay->drawBitmap(0, 0, DieselSplash, 128, 64, WHITE);
|
||||||
_pDisplay->setCursor(90, 56);
|
_pDisplay->setCursor(90, 56);
|
||||||
CTransientFont AF(*_pDisplay, &segoeUI_Italic_7ptFontInfo); // temporarily use a midi font
|
CTransientFont AF(*_pDisplay, &segoeUI_Italic_7ptFontInfo); // temporarily use a midi font
|
||||||
_pDisplay->setTextColor(WHITE);
|
_pDisplay->setTextColor(WHITE);
|
||||||
|
@ -269,6 +402,7 @@ CScreenManager::begin(bool bNoClock)
|
||||||
if(!bNoClock)
|
if(!bNoClock)
|
||||||
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
||||||
menuloop.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming
|
menuloop.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming
|
||||||
|
if(getBoardRevision() != 0 && getBoardRevision() != 22)
|
||||||
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
||||||
menuloop.push_back(new CMenuTrunkScreen(*_pDisplay, *this));
|
menuloop.push_back(new CMenuTrunkScreen(*_pDisplay, *this));
|
||||||
_Screens.push_back(menuloop);
|
_Screens.push_back(menuloop);
|
||||||
|
@ -304,6 +438,7 @@ CScreenManager::begin(bool bNoClock)
|
||||||
menuloop.push_back(new CThermostatModeScreen(*_pDisplay, *this)); // thermostat settings screen
|
menuloop.push_back(new CThermostatModeScreen(*_pDisplay, *this)); // thermostat settings screen
|
||||||
menuloop.push_back(new CHomeMenuSelScreen(*_pDisplay, *this)); // Home menu settings screen
|
menuloop.push_back(new CHomeMenuSelScreen(*_pDisplay, *this)); // Home menu settings screen
|
||||||
menuloop.push_back(new COtherOptionsScreen(*_pDisplay, *this)); // Other options screen
|
menuloop.push_back(new COtherOptionsScreen(*_pDisplay, *this)); // Other options screen
|
||||||
|
if(getBoardRevision() != 0 && getBoardRevision() != 22)
|
||||||
menuloop.push_back(new CGPIOScreen(*_pDisplay, *this)); // GPIO settings screen
|
menuloop.push_back(new CGPIOScreen(*_pDisplay, *this)); // GPIO settings screen
|
||||||
_Screens.push_back(menuloop);
|
_Screens.push_back(menuloop);
|
||||||
|
|
||||||
|
@ -631,3 +766,4 @@ CScreenManager::_dim(bool state)
|
||||||
_bDimmed = state;
|
_bDimmed = state;
|
||||||
_pDisplay->dim(state);
|
_pDisplay->dim(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ class CScreenManager {
|
||||||
void _dim(bool state);
|
void _dim(bool state);
|
||||||
public:
|
public:
|
||||||
enum eUIMenuSets { RootMenuLoop, TimerMenuLoop, TuningMenuLoop, UserSettingsLoop, SystemSettingsLoop, BranchMenu };
|
enum eUIMenuSets { RootMenuLoop, TimerMenuLoop, TuningMenuLoop, UserSettingsLoop, SystemSettingsLoop, BranchMenu };
|
||||||
enum eUIRootMenus { DetailedControlUI, BasicControlUI, ClockUI, ModeUI, /* CommsUI,*/ GPIOInfoUI, TrunkUI };
|
enum eUIRootMenus { DetailedControlUI, BasicControlUI, ClockUI, ModeUI, GPIOInfoUI, TrunkUI };
|
||||||
enum eUITimerMenus { TimerOverviewUI, Timer1UI, Timer2UI, Timer3UI, Timer4UI, Timer5UI, Timer6UI, Timer7UI,
|
enum eUITimerMenus { TimerOverviewUI, Timer1UI, Timer2UI, Timer3UI, Timer4UI, Timer5UI, Timer6UI, Timer7UI,
|
||||||
Timer8UI, Timer9UI, Timer10UI, Timer11UI, Timer12UI, Timer13UI, Timer14UI };
|
Timer8UI, Timer9UI, Timer10UI, Timer11UI, Timer12UI, Timer13UI, Timer14UI };
|
||||||
enum eUITuningMenus { MixtureUI, HeaterSettingsUI, FuelCalUI };
|
enum eUITuningMenus { MixtureUI, HeaterSettingsUI, FuelCalUI };
|
||||||
|
|
|
@ -50,12 +50,13 @@
|
||||||
// a reliable read.
|
// a reliable read.
|
||||||
//
|
//
|
||||||
// Input state truth table
|
// Input state truth table
|
||||||
// GPIO26 GPIO33
|
// GPIO25 GPIO26 GPIO33
|
||||||
// ------ ------
|
// ------ ------ ------
|
||||||
// V1.0 HIGH HIGH
|
// V1.0 HIGH HIGH HIGH
|
||||||
// unmodified V2.0 HIGH LOW
|
// unmodified V2.0 LOW HIGH LOW
|
||||||
// modified V2.0 LOW HIGH
|
// modified V2.0 LOW LOW HIGH
|
||||||
// V2.1 LOW HIGH
|
// V2.1 LOW LOW HIGH
|
||||||
|
// No GPIO V2.0 HIGH LOW HIGH
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// ****************************************************************************************
|
// ****************************************************************************************
|
||||||
|
@ -94,31 +95,38 @@ int BoardDetect()
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugPort.println("Board detect: Virgin system - attempting to detect revision");
|
DebugPort.println("Board detect: Virgin system - attempting to detect revision");
|
||||||
|
pinMode(25, INPUT_PULLUP);
|
||||||
pinMode(33, INPUT_PULLUP);
|
pinMode(33, INPUT_PULLUP);
|
||||||
pinMode(26, INPUT_PULLUP);
|
pinMode(26, INPUT_PULLUP);
|
||||||
// there is a 100nF capacitor across the analogue input, allow that to charge before testing
|
// there is a 100nF capacitor across the analogue input, allow that to charge before testing
|
||||||
delay(100);
|
delay(100);
|
||||||
|
int pin25 = digitalRead(25);
|
||||||
int pin33 = digitalRead(33);
|
int pin33 = digitalRead(33);
|
||||||
int pin26 = digitalRead(26);
|
int pin26 = digitalRead(26);
|
||||||
|
|
||||||
if(pin33 == HIGH && pin26 == HIGH) {
|
if((pin33 == HIGH) && (pin26 == HIGH) && (pin25 == HIGH)) {
|
||||||
revision = 10;
|
revision = 10;
|
||||||
DebugPort.println("Board detect: digital input test reveals V1.x PCB");
|
DebugPort.println("Board detect: digital input test reveals V1.x PCB");
|
||||||
}
|
}
|
||||||
else if(pin33 == LOW && pin26 == HIGH) {
|
else if((pin33 == LOW) && (pin26 == HIGH) && (pin25 == LOW)) {
|
||||||
revision = 20;
|
revision = 20;
|
||||||
DebugPort.println("Board detect: digital input test reveals V2.0 PCB");
|
DebugPort.println("Board detect: digital input test reveals V2.0 PCB");
|
||||||
}
|
}
|
||||||
else if(pin33 == HIGH && pin26 == LOW) {
|
else if((pin33 == HIGH) && (pin26 == LOW) && (pin25 == LOW)) {
|
||||||
revision = 21;
|
revision = 21;
|
||||||
DebugPort.println("Board detect: digital input test reveals V2.1 PCB");
|
DebugPort.println("Board detect: digital input test reveals V2.1 PCB");
|
||||||
}
|
}
|
||||||
|
else if((pin33 == HIGH) && (pin26 == LOW) && (pin25 == HIGH)) {
|
||||||
|
revision = 22;
|
||||||
|
DebugPort.println("Board detect: digital input test reveals V2.0 PCB - no GPIO");
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
DebugPort.println("Board detect: digital input test failed to detect a valid combination!!!");
|
DebugPort.println("Board detect: digital input test failed to detect a valid combination!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pinMode(33, INPUT); // revert to normal inputs (remove pull ups)
|
pinMode(33, INPUT); // revert to normal inputs (remove pull ups)
|
||||||
pinMode(26, INPUT);
|
pinMode(26, INPUT);
|
||||||
|
pinMode(25, INPUT); // revert to normal inputs (remove pull ups)
|
||||||
|
|
||||||
//store the detected revision
|
//store the detected revision
|
||||||
if(revision) {
|
if(revision) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ const char* getVersionStr();
|
||||||
extern const char* getVersionDate();
|
extern const char* getVersionDate();
|
||||||
extern int getBoardRevision();
|
extern int getBoardRevision();
|
||||||
extern void setupGPIO();
|
extern void setupGPIO();
|
||||||
extern void setGPIOout(int channel, bool state);
|
extern bool setGPIOout(int channel, bool state);
|
||||||
extern bool getGPIOout(int channel);
|
extern bool getGPIOout(int channel);
|
||||||
extern bool toggleGPIOout(int channel);
|
extern bool toggleGPIOout(int channel);
|
||||||
extern void feedWatchdog();
|
extern void feedWatchdog();
|
||||||
|
|
|
@ -49,6 +49,8 @@ extern const char* updateIndex;
|
||||||
extern const char* formatDoneContent;
|
extern const char* formatDoneContent;
|
||||||
extern const char* rebootIndex;
|
extern const char* rebootIndex;
|
||||||
|
|
||||||
|
extern void storeSplashScreenFile();
|
||||||
|
|
||||||
sBrowserUpload BrowserUpload;
|
sBrowserUpload BrowserUpload;
|
||||||
WebServer server(80);
|
WebServer server(80);
|
||||||
WebSocketsServer webSocket = WebSocketsServer(81);
|
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||||
|
@ -693,6 +695,7 @@ void onUploadCompletion()
|
||||||
// completion functionality
|
// completion functionality
|
||||||
if(BrowserUpload.isSPIFFSupload()) {
|
if(BrowserUpload.isSPIFFSupload()) {
|
||||||
if(BrowserUpload.isOK()) {
|
if(BrowserUpload.isOK()) {
|
||||||
|
storeSplashScreenFile();
|
||||||
DebugPort.println("WEB: SPIFFS OK");
|
DebugPort.println("WEB: SPIFFS OK");
|
||||||
server.send(200, "text/plain", "OK - File uploaded to SPIFFS");
|
server.send(200, "text/plain", "OK - File uploaded to SPIFFS");
|
||||||
// javascript reselects the /update page!
|
// javascript reselects the /update page!
|
||||||
|
|
Loading…
Reference in a new issue