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
|
@ -114,6 +114,7 @@
|
|||
#include <rom/rtc.h>
|
||||
#include <esp_spiffs.h>
|
||||
#include <SPIFFS.h>
|
||||
#include <nvs.h>
|
||||
|
||||
// SSID & password now stored in NV storage - these are still the default values.
|
||||
//#define AP_SSID "Afterburner"
|
||||
|
@ -323,6 +324,9 @@ void setup() {
|
|||
digitalWrite(GPIOout1_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
|
||||
// Serial is the usual USB connection to a PC
|
||||
// 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("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
|
||||
if(!SPIFFS.begin(true)){
|
||||
|
@ -1330,7 +1335,7 @@ bool isCyclicActive()
|
|||
|
||||
void setupGPIO()
|
||||
{
|
||||
if(BoardRevision) {
|
||||
if(BoardRevision == 10 || BoardRevision == 20 || BoardRevision == 21) {
|
||||
// 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.
|
||||
// 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);
|
||||
}
|
||||
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);
|
||||
GPIOout.begin(0, 0, GPIOoutNone);
|
||||
GPIOalg.begin(ADC1_CHANNEL_5, GPIOalgNone);
|
||||
|
@ -1379,10 +1384,14 @@ bool toggleGPIOout(int channel)
|
|||
return false;
|
||||
}
|
||||
|
||||
void setGPIOout(int channel, bool state)
|
||||
bool setGPIOout(int channel, bool state)
|
||||
{
|
||||
DebugPort.printf("setGPIO: Output #%d = %d\r\n", channel+1, state);
|
||||
GPIOout.setState(channel, state);
|
||||
if(GPIOout.getMode() != GPIOoutNone) {
|
||||
DebugPort.printf("setGPIO: Output #%d = %d\r\n", channel+1, state);
|
||||
GPIOout.setState(channel, state);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool getGPIOout(int channel)
|
||||
|
|
|
@ -52,7 +52,29 @@
|
|||
#include "fonts/MidiFont.h"
|
||||
#include "../Protocol/Protocol.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/
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -249,7 +379,10 @@ CScreenManager::begin(bool bNoClock)
|
|||
|
||||
// replace adafruit splash screen
|
||||
_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);
|
||||
CTransientFont AF(*_pDisplay, &segoeUI_Italic_7ptFontInfo); // temporarily use a midi font
|
||||
_pDisplay->setTextColor(WHITE);
|
||||
|
@ -269,7 +402,8 @@ CScreenManager::begin(bool bNoClock)
|
|||
if(!bNoClock)
|
||||
menuloop.push_back(new CClockScreen(*_pDisplay, *this)); // clock
|
||||
menuloop.push_back(new CPrimingScreen(*_pDisplay, *this)); // mode / priming
|
||||
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
||||
if(getBoardRevision() != 0 && getBoardRevision() != 22)
|
||||
menuloop.push_back(new CGPIOInfoScreen(*_pDisplay, *this)); // GPIO info
|
||||
menuloop.push_back(new CMenuTrunkScreen(*_pDisplay, *this));
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
|
@ -304,7 +438,8 @@ CScreenManager::begin(bool bNoClock)
|
|||
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 COtherOptionsScreen(*_pDisplay, *this)); // Other options screen
|
||||
menuloop.push_back(new CGPIOScreen(*_pDisplay, *this)); // GPIO settings screen
|
||||
if(getBoardRevision() != 0 && getBoardRevision() != 22)
|
||||
menuloop.push_back(new CGPIOScreen(*_pDisplay, *this)); // GPIO settings screen
|
||||
_Screens.push_back(menuloop);
|
||||
|
||||
// create System Settings screens loop
|
||||
|
@ -630,4 +765,5 @@ CScreenManager::_dim(bool state)
|
|||
{
|
||||
_bDimmed = state;
|
||||
_pDisplay->dim(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class CScreenManager {
|
|||
void _dim(bool state);
|
||||
public:
|
||||
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,
|
||||
Timer8UI, Timer9UI, Timer10UI, Timer11UI, Timer12UI, Timer13UI, Timer14UI };
|
||||
enum eUITuningMenus { MixtureUI, HeaterSettingsUI, FuelCalUI };
|
||||
|
|
|
@ -50,12 +50,13 @@
|
|||
// a reliable read.
|
||||
//
|
||||
// Input state truth table
|
||||
// GPIO26 GPIO33
|
||||
// ------ ------
|
||||
// V1.0 HIGH HIGH
|
||||
// unmodified V2.0 HIGH LOW
|
||||
// modified V2.0 LOW HIGH
|
||||
// V2.1 LOW HIGH
|
||||
// GPIO25 GPIO26 GPIO33
|
||||
// ------ ------ ------
|
||||
// V1.0 HIGH HIGH HIGH
|
||||
// unmodified V2.0 LOW HIGH LOW
|
||||
// modified V2.0 LOW 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");
|
||||
pinMode(25, INPUT_PULLUP);
|
||||
pinMode(33, INPUT_PULLUP);
|
||||
pinMode(26, INPUT_PULLUP);
|
||||
// there is a 100nF capacitor across the analogue input, allow that to charge before testing
|
||||
delay(100);
|
||||
int pin25 = digitalRead(25);
|
||||
int pin33 = digitalRead(33);
|
||||
int pin26 = digitalRead(26);
|
||||
|
||||
if(pin33 == HIGH && pin26 == HIGH) {
|
||||
if((pin33 == HIGH) && (pin26 == HIGH) && (pin25 == HIGH)) {
|
||||
revision = 10;
|
||||
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;
|
||||
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;
|
||||
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 {
|
||||
DebugPort.println("Board detect: digital input test failed to detect a valid combination!!!");
|
||||
}
|
||||
|
||||
pinMode(33, INPUT); // revert to normal inputs (remove pull ups)
|
||||
pinMode(26, INPUT);
|
||||
pinMode(25, INPUT); // revert to normal inputs (remove pull ups)
|
||||
|
||||
//store the detected revision
|
||||
if(revision) {
|
||||
|
|
|
@ -68,7 +68,7 @@ const char* getVersionStr();
|
|||
extern const char* getVersionDate();
|
||||
extern int getBoardRevision();
|
||||
extern void setupGPIO();
|
||||
extern void setGPIOout(int channel, bool state);
|
||||
extern bool setGPIOout(int channel, bool state);
|
||||
extern bool getGPIOout(int channel);
|
||||
extern bool toggleGPIOout(int channel);
|
||||
extern void feedWatchdog();
|
||||
|
|
|
@ -49,6 +49,8 @@ extern const char* updateIndex;
|
|||
extern const char* formatDoneContent;
|
||||
extern const char* rebootIndex;
|
||||
|
||||
extern void storeSplashScreenFile();
|
||||
|
||||
sBrowserUpload BrowserUpload;
|
||||
WebServer server(80);
|
||||
WebSocketsServer webSocket = WebSocketsServer(81);
|
||||
|
@ -693,6 +695,7 @@ void onUploadCompletion()
|
|||
// completion functionality
|
||||
if(BrowserUpload.isSPIFFSupload()) {
|
||||
if(BrowserUpload.isOK()) {
|
||||
storeSplashScreenFile();
|
||||
DebugPort.println("WEB: SPIFFS OK");
|
||||
server.send(200, "text/plain", "OK - File uploaded to SPIFFS");
|
||||
// javascript reselects the /update page!
|
||||
|
|
Loading…
Reference in a new issue