Add rotation, teleperiod and statusupdate

This commit is contained in:
fvanroie 2020-02-26 21:38:23 +01:00
parent 08bd6e448d
commit 0ba976bcde
10 changed files with 334 additions and 129 deletions

View File

@ -2,7 +2,7 @@
#define HASP_VERSION_MAJOR 0
#define HASP_VERSION_MINOR 0
#define HASP_VERSION_REVISION 7
#define HASP_VERSION_REVISION 8
#define HASP_USE_APP 1
@ -21,6 +21,9 @@
#define HASP_USE_QRCODE 1
#define HASP_USE_PNGDECODE 0
#define HASP_NUM_INPUTS 3 // Buttons
#define HASP_NUM_OUTPUTS 3
//#define LV_DEMO_WALLPAPER 0 /*Create a wallpaper too*/
//#define LV_HASP_HOR_RES_MAX 128

View File

@ -14,14 +14,11 @@
#include "hasp_wifi.h"
#include "hasp_mdns.h"
#include "hasp_gui.h"
#include "hasp_tft.h"
// #include "hasp_tft.h"
#include "hasp_ota.h"
#include "hasp_spiffs.h"
#include "hasp.h"
//#define HASP_CONFIG_FILE F("/config.json")
static const char HASP_CONFIG_FILE[] PROGMEM = "/config.json";
bool configChanged()
{
return false;
@ -37,7 +34,7 @@ void configLoop()
void configStartDebug(bool setupdebug, String & configFile)
{
if(setupdebug) {
debugSetup(); // Debug started, now we can use it; HASP header sent
debugStart(); // Debug started, now we can use it; HASP header sent
debugPrintln(F("FILE: [SUCCESS] SPI flash FS mounted"));
spiffsList();
}
@ -46,8 +43,10 @@ void configStartDebug(bool setupdebug, String & configFile)
void configGetConfig(JsonDocument & settings, bool setupdebug = false)
{
String configFile = String(FPSTR(HASP_CONFIG_FILE));
File file = SPIFFS.open(configFile, "r");
String configFile((char *)0);
configFile.reserve(127);
configFile = String(FPSTR(HASP_CONFIG_FILE));
File file = SPIFFS.open(configFile, "r");
if(file) {
size_t size = file.size();
@ -60,6 +59,8 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false)
if(!error) {
file.close();
/* Load Debug params */
debugPreSetup(settings[F("debug")]);
configStartDebug(setupdebug, configFile);
// show settings in log
@ -72,6 +73,7 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false)
debugPrintln(String(F("CONF: ")) + output);
debugPrintln(String(F("CONF: [SUCCESS] Loaded ")) + configFile);
debugSetup(settings[F("debug")]);
return;
}
}
@ -82,7 +84,9 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false)
void configWriteConfig()
{
String configFile = String(FPSTR(HASP_CONFIG_FILE));
String configFile((char *)0);
configFile.reserve(127);
configFile = String(FPSTR(HASP_CONFIG_FILE));
/* Read Config File */
DynamicJsonDocument settings(2 * 1024);
@ -91,7 +95,7 @@ void configWriteConfig()
debugPrintln(String(F("CONF: Config LOADED first ")) + configFile);
bool changed = true;
// changed |= debugGetConfig(settings[F("debug")].to<JsonObject>());
changed |= debugGetConfig(settings[F("debug")].to<JsonObject>());
changed |= guiGetConfig(settings[F("gui")].to<JsonObject>());
changed |= haspGetConfig(settings[F("hasp")].to<JsonObject>());
changed |= httpGetConfig(settings[F("http")].to<JsonObject>());
@ -133,7 +137,17 @@ void configOutput(const JsonObject & settings)
String output((char *)0);
output.reserve(127);
serializeJson(settings, output);
String passmask = F("********");
output.replace(settings[F("pass")].as<String>(), passmask);
String passmask((char *)0);
passmask.reserve(127);
passmask = F("\"pass\":\"********\"");
String password((char *)0);
password.reserve(127);
password = F("\"pass\":\"");
password += settings[F("pass")].as<String>();
password += F("\"");
if(password.length() > 2) output.replace(password, passmask);
debugPrintln(String(F("CONF: ")) + output);
}

View File

@ -17,10 +17,15 @@ const char F_CONFIG_USER[] PROGMEM = "user";
const char F_CONFIG_PASS[] PROGMEM = "pass";
const char F_CONFIG_SSID[] PROGMEM = "ssid";
const char F_CONFIG_GROUP[] PROGMEM = "group";
const char F_GUI_ROTATION[] PROGMEM = "rotation";
const char F_GUI_TICKPERIOD[] PROGMEM = "tickperiod";
const char F_GUI_IDLEPERIOD[] PROGMEM = "idle";
const char F_GUI_IDLEPERIOD1[] PROGMEM = "idle1";
const char F_GUI_IDLEPERIOD2[] PROGMEM = "idle2";
const char F_GUI_CALIBRATION[] PROGMEM = "calibration";
const char F_GUI_BACKLIGHTPIN[] PROGMEM = "bcklpin";
const char F_DEBUG_TELEPERIOD[] PROGMEM = "teleperiod";
const char HASP_CONFIG_FILE[] PROGMEM = "/config.json";
void configSetup(JsonDocument & settings);
void configLoop(void);

View File

@ -9,9 +9,11 @@
#endif
#include <WiFiUdp.h>
#include "hasp_log.h"
#include "hasp_hal.h"
#include "hasp_debug.h"
#include "hasp_config.h"
#include "hasp_dispatch.h"
#ifdef USE_CONFIG_OVERRIDE
#include "user_config_override.h"
@ -44,7 +46,10 @@ Syslog syslog(syslogClient, debugSyslogHost.c_str(), debugSyslogPort, debugAppNa
LOG_LOCAL0);
#endif
void debugSetup()
unsigned long debugLastMillis = 0;
uint16_t debugTelePeriod = 300;
void debugStart()
{
#if defined(ARDUINO_ARCH_ESP32)
Serial.begin(115200); /* prepare for possible serial debug */
@ -71,9 +76,6 @@ void debugSetup()
#endif
}
void debugLoop()
{}
void serialPrintln(const char * debugText)
{
String debugTimeText((char *)0);
@ -82,7 +84,7 @@ void serialPrintln(const char * debugText)
debugTimeText = F("[");
debugTimeText += String(float(millis()) / 1000, 3);
debugTimeText += F("s] ");
debugTimeText += ESP.getMaxFreeBlockSize();
debugTimeText += halGetMaxFreeBlock();
debugTimeText += F("/");
debugTimeText += ESP.getFreeHeap();
debugTimeText += F(" ");
@ -119,4 +121,53 @@ void syslogSend(uint8_t log, const char * debugText)
void debugStop()
{
Serial.flush();
}
}
bool debugGetConfig(const JsonObject & settings)
{
settings[FPSTR(F_DEBUG_TELEPERIOD)] = debugTelePeriod;
configOutput(settings);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool debugSetConfigLog(const JsonObject & settings, bool silent)
{
bool changed = false;
if(!settings[FPSTR(F_DEBUG_TELEPERIOD)].isNull()) {
if(debugTelePeriod != settings[FPSTR(F_DEBUG_TELEPERIOD)].as<uint16_t>()) {
if(!silent) debugPrintln(F("debugTelePeriod set"));
}
changed |= debugTelePeriod != settings[FPSTR(F_DEBUG_TELEPERIOD)].as<uint16_t>();
debugTelePeriod = settings[FPSTR(F_DEBUG_TELEPERIOD)].as<uint16_t>();
}
if(!silent) configOutput(settings);
return changed;
}
bool debugSetConfig(const JsonObject & settings)
{
return debugSetConfigLog(settings, false);
}
void debugPreSetup(JsonObject settings)
{
debugSetConfigLog(settings, true);
}
void debugSetup(JsonObject settings)
{
debugSetConfigLog(settings, false);
}
void debugLoop()
{
if(debugTelePeriod > 0 && (millis() - debugLastMillis) >= debugTelePeriod * 1000) {
dispatchStatusUpdate();
debugLastMillis = millis();
}
}

View File

@ -1,8 +1,12 @@
#ifndef HASP_DEBUG_H
#define HASP_DEBUG_H
void debugSetup(void);
#include "ArduinoJson.h"
void debugPreSetup(JsonObject settings);
void debugSetup(JsonObject settings);
void debugLoop(void);
void debugStart(void);
void debugStop(void);
void serialPrintln(String & debugText);
@ -10,4 +14,7 @@ void serialPrintln(const char * debugText);
void syslogSend(uint8_t log, const char * debugText);
bool debugGetConfig(const JsonObject & settings);
bool debugSetConfig(const JsonObject & settings);
#endif

View File

@ -15,6 +15,11 @@ void dispatchSetup()
void dispatchLoop()
{}
void dispatchStatusUpdate()
{
mqttStatusUpdate();
}
// objectattribute=value
void IRAM_ATTR dispatchAttribute(String & strTopic, const char * payload)
{
@ -76,19 +81,20 @@ void IRAM_ATTR dispatchCommand(String cmnd)
} else if(cmnd == F("wakeup")) {
haspWakeUp();
} else if(cmnd == F("screenshot")) {
guiTakeScreenshot("/screenhot.bmp");
// guiTakeScreenshot("/screenhot.bmp");
} else if(cmnd == F("reboot") || cmnd == F("restart")) {
dispatchReboot(true);
} else if(cmnd == "" || cmnd == F("statusupdate")) {
mqttStatusUpdate();
dispatchStatusUpdate();
} else {
int pos = cmnd.indexOf("=");
if(pos > 0) {
String strTopic = cmnd.substring(0, pos);
String strPayload = cmnd.substring(pos + 1, cmnd.length());
// debugPrintln("CMND: '" + strTopic + "'='" + strPayload + "'");
dispatchAttribute(strTopic, strPayload.c_str());
} else {
dispatchAttribute(cmnd, "");
}
}
}
@ -134,4 +140,11 @@ void dispatchReboot(bool saveConfig)
debugPrintln(F("-------------------------------------"));
ESP.restart();
delay(5000);
}
void dispatchButton(uint8_t i, bool pressed)
{
char buffer[127];
snprintf_P(buffer, sizeof(buffer), PSTR("INPUT%d"), i);
mqttSendState(buffer, String(pressed ? F("ON") : F("OFF")).c_str());
}

View File

@ -1,7 +1,7 @@
#ifndef HASP_DISPATCH_H
#define HASP_DISPATCH_H
#include <Arduino.h>
#include "ArduinoJson.h"
void dispatchSetup(void);
void dispatchLoop(void);
@ -15,5 +15,8 @@ void dispatchDim(String strDimLevel);
void dispatchIdle(const __FlashStringHelper * state);
void dispatchReboot(bool saveConfig);
void dispatchStatusUpdate(void);
void dispatchButton(uint8_t i, bool pressed);
#endif

View File

@ -26,46 +26,64 @@
#include <FS.h> // Include the SPIFFS library
#endif
/* ---------- Screenshot Variables ---------- */
File pFileOut;
uint8_t guiSnapshot = 0;
#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WebServer.h>
static ESP8266WebServer * webClient; // for snatshot
ESP8266WebServer * webClient; // for snatshot
#endif
#if defined(ARDUINO_ARCH_ESP32)
#include <WebServer.h>
static WebServer * webClient; // for snatshot
#endif // ESP32
WebServer * webClient; // for snatshot
#endif // ESP32
/* ------------------------------------------- */
#define LVGL_TICK_PERIOD 30 // 30
// #define LVGL_TICK_PERIOD 30
#ifndef TFT_BCKL
#define TFT_BCKL -1 // No Backlight Control
#endif
#ifndef TFT_ROTATION
#define TFT_ROTATION 0
#endif
bool guiBacklightIsOn = true;
int8_t guiDimLevel = -1;
int8_t guiBacklightPin = TFT_BCKL;
bool guiAutoCalibrate = true;
uint16_t guiSleepTime = 150; // 0.1 second resolution
bool guiSleeping = false;
uint16_t guiSleepTime1 = 60; // 1 second resolution
uint16_t guiSleepTime2 = 120; // 1 second resolution
uint8_t guiSleeping = 0; // 0 = off, 1 = short, 2 = long
uint8_t guiTickPeriod = 50;
static Ticker tick; /* timer for interrupt handler */
static TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
uint8_t guiRotation = TFT_ROTATION;
static Ticker tick; /* timer for interrupt handler */
static TFT_eSPI tft; // = TFT_eSPI(); /* TFT instance */
static uint16_t calData[5] = {0, 65535, 0, 65535, 0};
static File pFileOut;
static uint8_t guiSnapshot = 0;
bool IRAM_ATTR guiCheckSleep()
{
bool shouldSleep = lv_disp_get_inactive_time(NULL) > guiSleepTime * 100;
if(shouldSleep && !guiSleeping) {
dispatchIdle(F("LONG"));
guiSleeping = true;
} else if(!shouldSleep && guiSleeping) {
dispatchIdle(F("OFF"));
guiSleeping = false;
if(lv_disp_get_inactive_time(NULL) >= (guiSleepTime1 + guiSleepTime2) * 1000) {
if(guiSleeping != 2) {
dispatchIdle(F("LONG"));
guiSleeping = 2;
}
return true;
} else if(lv_disp_get_inactive_time(NULL) >= guiSleepTime1 * 1000) {
if(guiSleeping != 1) {
dispatchIdle(F("SHORT"));
guiSleeping = 1;
}
return true;
} else {
if(guiSleeping != 0) {
dispatchIdle(F("OFF"));
guiSleeping = 0;
}
return false;
}
return shouldSleep;
}
#if LV_USE_LOG != 0
@ -73,7 +91,7 @@ bool IRAM_ATTR guiCheckSleep()
void debugLvgl(lv_log_level_t level, const char * file, uint32_t line, const char * dsc)
{
char msg[127];
sprintf(msg, PSTR("LVGL: %s@%d->%s"), file, line, dsc);
snprintf(msg, sizeof(msg), PSTR("LVGL: %s@%d->%s"), file, line, dsc);
debugPrintln(msg);
}
#endif
@ -90,10 +108,21 @@ void tft_espi_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * c
/* Function for converting LittlevGL pixel format to RGB888 */
// data = DISP_IMPL_lvgl_formatPixel(*color_p);
pixel[i++] = (LV_COLOR_GET_B(*color_p) * 263 + 7) >> 5;
pixel[i++] = (LV_COLOR_GET_G(*color_p) * 259 + 3) >> 6;
pixel[i++] = (LV_COLOR_GET_R(*color_p) * 263 + 7) >> 5;
pixel[i++] = 0xFF;
// Complex 32 bpp
/* pixel[i++] = (LV_COLOR_GET_B(*color_p) * 263 + 7) >> 5;
pixel[i++] = (LV_COLOR_GET_G(*color_p) * 259 + 3) >> 6;
pixel[i++] = (LV_COLOR_GET_R(*color_p) * 263 + 7) >> 5;
pixel[i++] = 0xFF;*/
// Simple 32 bpp
pixel[i++] = (LV_COLOR_GET_B(*color_p) << 3);
pixel[i++] = (LV_COLOR_GET_G(*color_p) << 2);
pixel[i++] = (LV_COLOR_GET_R(*color_p) << 3);
// pixel[i++] = 0xFF;
// Simple 16 bpp
// pixel[i++] = color_p->full & 0xFF;
// pixel[i++] = (color_p->full >> 8) & 0xFF;
color_p++;
// i += 4;
@ -156,17 +185,17 @@ static void IRAM_ATTR lv_tick_handler(void)
}
/* Reading input device (simulated encoder here) */
bool read_encoder(lv_indev_drv_t * indev, lv_indev_data_t * data)
/*bool read_encoder(lv_indev_drv_t * indev, lv_indev_data_t * data)
{
static int32_t last_diff = 0;
int32_t diff = 0; /* Dummy - no movement */
int btn_state = LV_INDEV_STATE_REL; /* Dummy - no press */
int32_t diff = 0; // Dummy - no movement
int btn_state = LV_INDEV_STATE_REL; // Dummy - no press
data->enc_diff = diff - last_diff;
data->state = btn_state;
last_diff = diff;
return false;
}
}*/
void guiFirstCalibration()
{
@ -188,7 +217,7 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
return false;
}
bool shouldSleep = guiCheckSleep();
guiCheckSleep();
// Ignore first press?
@ -243,25 +272,37 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings)
tft = screen;
guiSetConfig(settings);
guiBacklightIsOn = guiDimLevel > 0;
tft.begin(); /* TFT init */
tft.setTouch(calData);
tft.setRotation(guiRotation); /* 1/3=Landscape or 0/2=Portrait orientation */
lv_init();
#if defined(ARDUINO_ARCH_ESP32)
/* allocate on iram (or psram ?) */
buffer_size = 19200; // 38 KBytes
buffer_size = 16 * 1024u; // 32 KBytes
static lv_color_t * guiVdbBuffer = (lv_color_t *)malloc(sizeof(lv_color_t) * buffer_size);
static lv_disp_buf_t disp_buf;
lv_disp_buf_init(&disp_buf, guiVdbBuffer, NULL, buffer_size);
#else
/* allocate on heap */
static lv_color_t guiVdbBuffer[1024 * 3]; // 6 KBytes
static lv_color_t guiVdbBuffer[3 * 1024u]; // 6 KBytes
buffer_size = sizeof(guiVdbBuffer) / sizeof(guiVdbBuffer[0]);
static lv_disp_buf_t disp_buf;
lv_disp_buf_init(&disp_buf, guiVdbBuffer, NULL, buffer_size);
#endif
debugPrintln(String(F("LVGL: MEM size : ")) + String(LV_MEM_SIZE));
debugPrintln(String(F("LVGL: VDB size : ")) + String((size_t)sizeof(lv_color_t) * buffer_size));
char buffer[127];
snprintf_P(buffer, sizeof(buffer), PSTR("LVGL: Rotation : %d"), guiRotation);
debugPrintln(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR("LVGL: MEM size : %d"), LV_MEM_SIZE);
debugPrintln(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR("LVGL: VFB size : %d"), (size_t)sizeof(lv_color_t) * buffer_size);
debugPrintln(buffer);
#if LV_USE_LOG != 0
debugPrintln(F("LVGL: Registering lvgl logging handler"));
@ -273,21 +314,25 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings)
png_decoder_init();
#endif
#if LV_USE_FS_IF != 0
lv_fs_if_init();
#endif
/* Initialize the display driver */
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = tft_espi_flush;
disp_drv.buffer = &disp_buf;
#if(TFT_ROTATION == 0 || TFT_ROTATION == 2 || TFT_ROTATION == 4 || TFT_ROTATION == 6)
/* 1/3=Landscape or 0/2=Portrait orientation */
// Normal width & height
disp_drv.hor_res = TFT_WIDTH; // From User_Setup.h
disp_drv.ver_res = TFT_HEIGHT; // From User_Setup.h
#else
// Swapped width & height
disp_drv.hor_res = TFT_HEIGHT; // From User_Setup.h
disp_drv.ver_res = TFT_WIDTH; // From User_Setup.h
#endif
if(guiRotation == 0 || guiRotation == 2 || guiRotation == 4 || guiRotation == 6) {
/* 1/3=Landscape or 0/2=Portrait orientation */
// Normal width & height
disp_drv.hor_res = TFT_WIDTH; // From User_Setup.h
disp_drv.ver_res = TFT_HEIGHT; // From User_Setup.h
} else {
// Swapped width & height
disp_drv.hor_res = TFT_HEIGHT; // From User_Setup.h
disp_drv.ver_res = TFT_WIDTH; // From User_Setup.h
}
lv_disp_drv_register(&disp_drv);
/*Initialize the touch pad*/
@ -336,22 +381,17 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings)
/*Initialize the graphics library's tick*/
tick.attach_ms(guiTickPeriod, lv_tick_handler);
#if LV_USE_FS_IF != 0
lv_fs_if_init();
#endif
/* Setup Backlight Control Pin */
if(guiBacklightPin >= 0) {
char msg[127];
sprintf(msg, PSTR("LVGL: Backlight Pin = %i"), guiBacklightPin);
debugPrintln(msg);
snprintf(buffer, sizeof(buffer), PSTR("LVGL: Backlight Pin = %i"), guiBacklightPin);
debugPrintln(buffer);
#if defined(ARDUINO_ARCH_ESP32)
// configure LED PWM functionalitites
ledcSetup(0, 1000, 10);
ledcSetup(100, 1000, 10);
// attach the channel to the GPIO to be controlled
pinMode(guiBacklightPin, OUTPUT);
ledcAttachPin(guiBacklightPin, 0);
ledcAttachPin(guiBacklightPin, 99);
#else
pinMode(guiBacklightPin, OUTPUT);
#endif
@ -366,17 +406,42 @@ void IRAM_ATTR guiLoop()
void guiStop()
{}
bool guiGetBacklight(bool lighton)
{
return guiBacklightIsOn;
}
void guiSetBacklight(bool lighton)
{
guiBacklightIsOn = lighton;
if(guiBacklightPin >= 0) {
#if defined(ARDUINO_ARCH_ESP32)
ledcWrite(99, lighton ? 1023 : 0); // ledChannel and value
#else
analogWrite(guiBacklightPin, lighton ? 1023 : 0);
#endif
} else {
guiBacklightIsOn = true;
}
}
void guiSetDim(uint8_t level)
{
if(guiBacklightPin >= 0) {
guiDimLevel = level >= 0 ? level : 0;
guiDimLevel = guiDimLevel <= 100 ? guiDimLevel : 100;
if(guiBacklightIsOn) { // The backlight is ON
#if defined(ARDUINO_ARCH_ESP32)
ledcWrite(0, map(guiDimLevel, 0, 100, 0, 1023)); // ledChannel and value
ledcWrite(99, map(guiDimLevel, 0, 100, 0, 1023)); // ledChannel and value
#else
analogWrite(guiBacklightPin, map(guiDimLevel, 0, 100, 0, 1023));
analogWrite(guiBacklightPin, map(guiDimLevel, 0, 100, 0, 1023));
#endif
}
} else {
guiDimLevel = -1;
}
@ -391,8 +456,10 @@ int8_t guiGetDim()
bool guiGetConfig(const JsonObject & settings)
{
settings[FPSTR(F_GUI_TICKPERIOD)] = guiTickPeriod;
settings[FPSTR(F_GUI_IDLEPERIOD)] = guiSleepTime;
settings[FPSTR(F_GUI_IDLEPERIOD1)] = guiSleepTime1;
settings[FPSTR(F_GUI_IDLEPERIOD2)] = guiSleepTime2;
settings[FPSTR(F_GUI_BACKLIGHTPIN)] = guiBacklightPin;
settings[FPSTR(F_GUI_ROTATION)] = guiRotation;
JsonArray array = settings[FPSTR(F_GUI_CALIBRATION)].to<JsonArray>();
for(int i = 0; i < 5; i++) {
@ -429,13 +496,31 @@ bool guiSetConfig(const JsonObject & settings)
guiBacklightPin = settings[FPSTR(F_GUI_BACKLIGHTPIN)].as<int8_t>();
}
if(!settings[FPSTR(F_GUI_IDLEPERIOD)].isNull()) {
if(guiSleepTime != settings[FPSTR(F_GUI_IDLEPERIOD)].as<uint8_t>()) {
debugPrintln(F("guiSleepTime set"));
if(!settings[FPSTR(F_GUI_IDLEPERIOD1)].isNull()) {
if(guiSleepTime1 != settings[FPSTR(F_GUI_IDLEPERIOD1)].as<uint8_t>()) {
debugPrintln(F("guiSleepTime1 set"));
}
changed |= guiSleepTime != settings[FPSTR(F_GUI_IDLEPERIOD)].as<uint8_t>();
changed |= guiSleepTime1 != settings[FPSTR(F_GUI_IDLEPERIOD1)].as<uint8_t>();
guiSleepTime = settings[FPSTR(F_GUI_IDLEPERIOD)].as<uint8_t>();
guiSleepTime1 = settings[FPSTR(F_GUI_IDLEPERIOD1)].as<uint8_t>();
}
if(!settings[FPSTR(F_GUI_IDLEPERIOD2)].isNull()) {
if(guiSleepTime2 != settings[FPSTR(F_GUI_IDLEPERIOD2)].as<uint8_t>()) {
debugPrintln(F("guiSleepTime2 set"));
}
changed |= guiSleepTime2 != settings[FPSTR(F_GUI_IDLEPERIOD2)].as<uint8_t>();
guiSleepTime2 = settings[FPSTR(F_GUI_IDLEPERIOD2)].as<uint8_t>();
}
if(!settings[FPSTR(F_GUI_ROTATION)].isNull()) {
if(guiRotation != settings[FPSTR(F_GUI_ROTATION)].as<uint8_t>()) {
debugPrintln(F("guiRotation set"));
}
changed |= guiRotation != settings[FPSTR(F_GUI_ROTATION)].as<uint8_t>();
guiRotation = settings[FPSTR(F_GUI_ROTATION)].as<uint8_t>();
}
if(!settings[FPSTR(F_GUI_CALIBRATION)].isNull()) {
@ -463,6 +548,66 @@ bool guiSetConfig(const JsonObject & settings)
return changed;
}
void guiSendBmpHeader()
{
uint8_t buffer[54];
memset(buffer, 0, sizeof(buffer));
lv_disp_t * disp = lv_disp_get_default();
buffer[0] = 0x42;
buffer[1] = 0x4D;
buffer[10 + 0] = sizeof(buffer); // full header size
buffer[14 + 0] = sizeof(buffer) - 14; // dib header size
buffer[26 + 0] = 1; // number of color planes
buffer[28 + 0] = 24; // bbp
buffer[30 + 0] = 0; // compression, 0 = RGB / 3 = RGBA
// file size
int32_t res = sizeof(buffer) + disp->driver.hor_res * disp->driver.ver_res * buffer[28] / 8;
buffer[2 + 3] = (res >> 24) & 0xFF;
buffer[2 + 2] = (res >> 16) & 0xFF;
buffer[2 + 1] = (res >> 8) & 0xFF;
buffer[2 + 0] = res & 0xFF;
// horizontal resolution
res = disp->driver.hor_res;
buffer[18 + 3] = (res >> 24) & 0xFF;
buffer[18 + 2] = (res >> 16) & 0xFF;
buffer[18 + 1] = (res >> 8) & 0xFF;
buffer[18 + 0] = res & 0xFF;
// vertical resolution
res = -disp->driver.ver_res; // top down lines
buffer[22 + 3] = (res >> 24) & 0xFF;
buffer[22 + 2] = (res >> 16) & 0xFF;
buffer[22 + 1] = (res >> 8) & 0xFF;
buffer[22 + 0] = res & 0xFF;
// bitmp size
res = disp->driver.hor_res * disp->driver.ver_res * buffer[28 + 0] / 8; //* 2;
buffer[34 + 3] = (res >> 24) & 0xFF;
buffer[34 + 2] = (res >> 16) & 0xFF;
buffer[34 + 1] = (res >> 8) & 0xFF;
buffer[34 + 0] = res & 0xFF;
if(guiSnapshot == 1) {
size_t len = pFileOut.write(buffer, sizeof(*buffer));
if(len != sizeof(buffer)) {
errorPrintln(F("GUI: %sData written does not match header size"));
} else {
debugPrintln(F("GUI: Bitmap header written"));
}
} else if(guiSnapshot == 2) {
if(webClient->client().write(buffer, sizeof(buffer)) != sizeof(buffer)) {
errorPrintln(F("GUI: %sData sent does not match header size"));
} else {
debugPrintln(F("GUI: Bitmap header sent"));
}
}
}
/** Flush buffer.
*
* Flush buffer into a binary file.
@ -476,20 +621,14 @@ void guiTakeScreenshot(const char * pFileName)
{
pFileOut = SPIFFS.open(pFileName, "w");
uint8_t bmpheader[138] = {0x42, 0x4D, 0x8A, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x20, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x42, 0x47, 0x52, 0x73};
pFileOut.write(bmpheader, sizeof(bmpheader));
if(pFileOut == NULL) {
printf("[Display] error: %s cannot be opened", pFileName);
return;
}
guiSnapshot = 1;
guiSendBmpHeader();
lv_obj_invalidate(lv_scr_act());
lv_refr_now(NULL); /* Will call our disp_drv.disp_flush function */
guiSnapshot = 0;
@ -507,19 +646,9 @@ void guiTakeScreenshot(ESP8266WebServer & client)
{
webClient = &client;
uint8_t bmpheader[138] = {0x42, 0x4D, 0x8A, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x20, 0x00,
0x03, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x42, 0x47, 0x52, 0x73};
if(webClient->client().write(bmpheader, sizeof(bmpheader)) != sizeof(bmpheader)) {
errorPrintln(F("GUI: %sData sent does not match header size"));
} else {
debugPrintln(F("GUI: Bitmap header sent"));
}
guiSnapshot = 2;
guiSendBmpHeader();
lv_obj_invalidate(lv_scr_act());
lv_refr_now(NULL); /* Will call our disp_drv.disp_flush function */
guiSnapshot = 0;

View File

@ -15,30 +15,7 @@ int8_t getPinName(int8_t pin);
void tftSetup(TFT_eSPI & tft, JsonObject settings)
{
uint8_t rotation = TFT_ROTATION;
if(settings[F_TFT_ROTATION]) rotation = settings[F_TFT_ROTATION];
uint32_t frequency = SPI_FREQUENCY;
if(settings[F_TFT_FREQUENCY]) frequency = settings[F_TFT_FREQUENCY];
char buffer[127];
sprintf_P(buffer, PSTR("TFT: %d rotation / %d frequency"), rotation, frequency);
debugPrintln(buffer);
tft.begin(); /* TFT init */
tft.setRotation(rotation); /* 1/3=Landscape or 0/2=Portrait orientation */
tftShowConfig(tft);
/* Load Calibration data */
#if defined(ARDUINO_ARCH_ESP8266)
uint16_t calData[5] = {238, 3529, 369, 3532, 6};
#else
uint16_t calData[5] = {294, 3410, 383, 3491, 4};
#endif
// uint16_t calData[5] = {0, 0, 0, 0, 0};
uint8_t calDataOK = 0;
tft.setTouch(calData);
}
void tftLoop()

View File

@ -63,10 +63,12 @@ void setup()
sdcardSetup();
#endif
// debugSetup(settings[F("debug")]);
/* Init Graphics */
TFT_eSPI screen = TFT_eSPI();
tftSetup(screen, settings[F("tft")]);
guiSetup(screen, settings[F("gui")]);
tftSetup(screen, settings[F("tft")]);
/* Init GUI Application */
haspSetup(settings[F("hasp")]);
@ -136,7 +138,8 @@ void loop()
#endif
// otaLoop(wifiIsConnected);
debugLoop();
#endif
delay(1);
// delay(1);
}