1152 lines
38 KiB
C++
1152 lines
38 KiB
C++
|
|
#include "HermitCrab.h"
|
|
#include "Config.h"
|
|
#include "ConnectWiFi.h"
|
|
#include "TimeManager.h"
|
|
#include "WiFiHost.h"
|
|
|
|
#include "UI.h"
|
|
#include <Fonts/FreeSansBold24pt7b.h> // 35
|
|
#include <Fonts/FreeSans18pt7b.h> // 25
|
|
#include <Fonts/FreeSans12pt7b.h>
|
|
#include <Fonts/FreeSans9pt7b.h>
|
|
|
|
#define TAG_UI "UI"
|
|
// Buttons
|
|
#define DEBOUNCE_DELAY 100
|
|
#define LONG_PRESS_DURATION 1500
|
|
|
|
// Display
|
|
#define SPACING 2
|
|
#define FONT_DESCENT 3
|
|
#define POS_X_UNIT 112
|
|
#define WIDTH_UNIT 16
|
|
#define HEIGHT_UNIT 16
|
|
|
|
#define POS_Y_BOTTOM (SCREEN_HEIGHT - 1)
|
|
#define WIDTH_D3 20
|
|
#define POS_X_D3 (POS_X_UNIT - WIDTH_D3 - SPACING)
|
|
#define HEIGHT_D3 26
|
|
|
|
#define WIDTH_DOT 7
|
|
#define POS_X_DOT (POS_X_D3 - WIDTH_DOT - SPACING)
|
|
#define HEIGHT_DOT 7
|
|
|
|
#define WIDTH_D2 26
|
|
#define POS_X_D2 (POS_X_DOT - WIDTH_D2 - SPACING)
|
|
#define HEIGHT_D2 36
|
|
|
|
#define WIDTH_D1 WIDTH_D2
|
|
#define POS_X_D1 (POS_X_D2 - WIDTH_D1 - SPACING)
|
|
#define HEIGHT_D1 HEIGHT_D2
|
|
|
|
#define WIDTH_D0 WIDTH_D1
|
|
#define POS_X_D0 (POS_X_D1 - WIDTH_D1 - SPACING)
|
|
#define HEIGHT_D0 HEIGHT_D1
|
|
|
|
enum MAIN_MODE {
|
|
MODE_TEMP,
|
|
MODE_HUMID,
|
|
MODE_CLOCK
|
|
};
|
|
|
|
//Adafruit_SSD1306 ssd1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
|
|
CUI ui;
|
|
|
|
const uint8_t logo[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x3F, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
|
|
0x02, 0x00, 0x01, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x26, 0x17, 0xC0, 0x00, 0x00, 0x00,
|
|
0x02, 0x00, 0x88, 0x20, 0x30, 0x00, 0x00, 0x80, 0x04, 0x02, 0x02, 0xC1, 0xFC, 0x00, 0x00, 0x80,
|
|
0x04, 0x06, 0x5E, 0x03, 0xC3, 0x00, 0x00, 0x80, 0x04, 0x04, 0xF8, 0x03, 0x00, 0xC0, 0x00, 0x80,
|
|
0x04, 0x00, 0xF0, 0x07, 0x00, 0x30, 0x00, 0x80, 0x08, 0x11, 0x18, 0x0D, 0x00, 0xC8, 0x03, 0x00,
|
|
0x08, 0x12, 0x20, 0x0C, 0x81, 0xFC, 0x05, 0x00, 0x10, 0x26, 0x50, 0x0F, 0x81, 0xFE, 0x0A, 0x00,
|
|
0x08, 0x64, 0xF0, 0x1D, 0x86, 0x67, 0x14, 0x00, 0x08, 0x41, 0x80, 0x18, 0xC7, 0x31, 0xF8, 0x00,
|
|
0x08, 0xCB, 0x80, 0x3B, 0xC6, 0x1B, 0x20, 0x00, 0x08, 0xCB, 0x80, 0x7C, 0x66, 0x1F, 0xE0, 0x00,
|
|
0x09, 0xDF, 0xB0, 0x10, 0x60, 0x39, 0xE0, 0x00, 0x09, 0x87, 0xE0, 0x38, 0xF8, 0x79, 0x90, 0x00,
|
|
0x0B, 0xAE, 0x00, 0x7C, 0x7C, 0xF1, 0xFF, 0x00, 0x13, 0x6E, 0x00, 0x3C, 0x60, 0x98, 0xFD, 0x80,
|
|
0x13, 0x08, 0x40, 0x7C, 0x01, 0x9E, 0xFD, 0xC0, 0x17, 0x1C, 0x00, 0xFC, 0x03, 0x8D, 0xFB, 0xC0,
|
|
0x16, 0x5C, 0x02, 0x3C, 0x0E, 0xFF, 0xFB, 0xE0, 0x0E, 0x5C, 0x04, 0x78, 0x1F, 0x9F, 0x99, 0xF0,
|
|
0x0C, 0x9C, 0x60, 0x78, 0x77, 0xFF, 0xFF, 0xF8, 0x04, 0x9F, 0xC0, 0xB3, 0xFF, 0xF6, 0x9F, 0x7C,
|
|
0x06, 0x9F, 0x01, 0x1F, 0x7E, 0xFF, 0xFF, 0xBC, 0x06, 0x1C, 0x00, 0x7F, 0xFB, 0x16, 0xEF, 0xFC,
|
|
0x02, 0x48, 0x01, 0xF7, 0xFF, 0xC7, 0xCF, 0xFE, 0x01, 0x08, 0x03, 0xBE, 0xF7, 0xF4, 0x0F, 0xFA,
|
|
0x00, 0x90, 0x0F, 0xFA, 0xFF, 0xB4, 0x07, 0x7E, 0x00, 0x40, 0x1D, 0xFF, 0x77, 0x42, 0x07, 0xBA,
|
|
0x00, 0x40, 0x2F, 0xF7, 0x7B, 0x41, 0x06, 0x5B, 0x00, 0x41, 0xFF, 0x6E, 0xDC, 0xC3, 0x07, 0x7F,
|
|
0x00, 0x27, 0x7D, 0x3C, 0xDF, 0xCB, 0x87, 0x5B, 0x00, 0x3F, 0xFF, 0xF6, 0xCE, 0x59, 0xC6, 0xF9,
|
|
0x00, 0x1E, 0xF7, 0x7A, 0xC7, 0xFB, 0xC7, 0x6D, 0x00, 0x0B, 0xFE, 0xDF, 0xE8, 0x9B, 0x86, 0x7D,
|
|
0x00, 0x0B, 0xC5, 0x8F, 0xF0, 0xC3, 0x80, 0x3F, 0x00, 0x17, 0x85, 0x85, 0xE8, 0xFB, 0xC0, 0x37,
|
|
0x00, 0x3E, 0x0B, 0x05, 0x68, 0xBE, 0xE0, 0x37, 0x00, 0x7C, 0x13, 0x05, 0xF8, 0xBF, 0xF0, 0x16,
|
|
0x00, 0xB8, 0x26, 0x09, 0x70, 0xFD, 0xF0, 0x1E, 0x01, 0x70, 0x24, 0x0A, 0x70, 0xFF, 0xF8, 0x1C,
|
|
0x03, 0xC0, 0x58, 0x0A, 0x50, 0xDF, 0xB8, 0x1C, 0x07, 0x80, 0x98, 0x0E, 0x50, 0xFB, 0xF8, 0x1C,
|
|
0x1F, 0x00, 0xB0, 0x16, 0x70, 0x7D, 0xF0, 0x18, 0x3C, 0x01, 0x60, 0x14, 0x60, 0x3D, 0xF0, 0x00,
|
|
0x78, 0x01, 0xE0, 0x14, 0x60, 0x1E, 0xF0, 0x00, 0xF0, 0x03, 0x80, 0x18, 0xE0, 0x07, 0xE0, 0x00,
|
|
0xC0, 0x07, 0x00, 0x38, 0xE0, 0x03, 0x80, 0x00, 0x00, 0x0E, 0x00, 0x31, 0xC0, 0x00, 0x00, 0x00,
|
|
0x00, 0x1E, 0x00, 0x71, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
const uint8_t degreeC[] = {
|
|
0x60, 0x00,
|
|
0x90, 0x00,
|
|
0x90, 0x00,
|
|
0x63, 0xE4,
|
|
0x0E, 0x1C,
|
|
0x1C, 0x04,
|
|
0x18, 0x00,
|
|
0x38, 0x00,
|
|
0x38, 0x00,
|
|
0x38, 0x00,
|
|
0x38, 0x00,
|
|
0x38, 0x00,
|
|
0x1C, 0x04,
|
|
0x0E, 0x08,
|
|
0x07, 0xF0,
|
|
0x00, 0x00
|
|
};
|
|
|
|
const uint8_t percentSign[] = {
|
|
0x00, 0x00,
|
|
0x38, 0x18,
|
|
0x7C, 0x30,
|
|
0xC6, 0x30,
|
|
0xC6, 0x60,
|
|
0xC6, 0xc0,
|
|
0x7C, 0xC0,
|
|
0x39, 0x80,
|
|
0x01, 0x9C,
|
|
0x03, 0x3E,
|
|
0x03, 0x63,
|
|
0x06, 0x63,
|
|
0x0C, 0x63,
|
|
0x0C, 0x3E,
|
|
0x18, 0x1C,
|
|
0x00, 0x00
|
|
};
|
|
|
|
|
|
enum UI_ITEM {
|
|
ITEM_CLOCK,
|
|
|
|
// Sensor
|
|
ITEM_TEMP1,
|
|
ITEM_TEMP2,
|
|
ITEM_TEMP3,
|
|
ITEM_HUMID,
|
|
ITEM_HUMID2,
|
|
|
|
// SV
|
|
ITEM_TEMP_TARGET,
|
|
ITEM_HUMID_TARGET,
|
|
|
|
// CV
|
|
ITEM_HEAT1,
|
|
ITEM_HEAT2,
|
|
ITEM_MIST,
|
|
ITEM_FAN,
|
|
ITEM_MOTOR,
|
|
ITEM_LIGHT,
|
|
|
|
ITEM_HEAT1_MANUAL,
|
|
ITEM_HEAT2_MANUAL,
|
|
ITEM_MIST_MANUAL,
|
|
ITEM_FAN_MANUAL,
|
|
ITEM_MOTOR_MANUAL,
|
|
ITEM_LIGHT_MANUAL,
|
|
ITEM_CHECK_AC,
|
|
|
|
ITEM_COUNT
|
|
};
|
|
|
|
const char *title[] = {
|
|
"Time:",
|
|
|
|
"Temp1", "Temp2", "Temp3",
|
|
|
|
"RH1", "RH2",
|
|
|
|
"TT", "RHT",
|
|
|
|
"Heat1", "Heat2", "Mist", "Fan", "Pump", "Lum",
|
|
|
|
"Ht1 M", "Ht2 M", "Mst M", "Fan M", "Pmp M", "Lum M",
|
|
|
|
"Chk AC" };
|
|
|
|
uint8_t *unit[] = { (uint8_t *) degreeC, (uint8_t *) percentSign, nullptr };
|
|
const uint16_t main_unit_idx[] = { 0, 1, 2 };
|
|
const uint16_t item_unit_idx[] = {
|
|
2, // Time
|
|
0, 0, 0, // Temp
|
|
1, 1, // Humid
|
|
0, 1, // SV
|
|
1, 1, 1, 1, 1, 1, // CV
|
|
2, 2, 2, 2, 2, 2, // Manual
|
|
2 };
|
|
|
|
const bool set_idx[] = {
|
|
false,
|
|
false, false, false,
|
|
false, false,
|
|
|
|
true, true,
|
|
|
|
true, true, true, true, true, true,
|
|
true, true, true, true, true, true,
|
|
|
|
true };
|
|
|
|
const bool fineControl[] = {
|
|
false,
|
|
false, false, false,
|
|
false, false,
|
|
|
|
true, true,
|
|
|
|
false, false, false, false, false, false,
|
|
true, true, true, true, true, true,
|
|
|
|
true };
|
|
|
|
//
|
|
// Buttons
|
|
//
|
|
void buttonSetISR();
|
|
void buttonUpISR();
|
|
void buttonDownISR();
|
|
|
|
|
|
// Constructor for CUI class
|
|
//CUI::CUI(Adafruit_SSD1306 &display)
|
|
CUI::CUI()
|
|
: SSD1306()
|
|
{}
|
|
|
|
void CUI::setup() {
|
|
// Initialize the display
|
|
ESP_LOGI(TAG_UI," UI - setup()");
|
|
bOK = false;
|
|
bDot = false;
|
|
bButtonChanged = false;
|
|
m_nMessageMode = 0;
|
|
m_nMainMode = 0;
|
|
m_nItemMode = 0;
|
|
m_nItem = 0;
|
|
m_nValue = 0;
|
|
m_pUnit = (uint8_t *) unit[item_unit_idx[m_nItem]];
|
|
m_nD0 = m_nD1 = m_nD2 = m_nD3 = 0;
|
|
m_pDUnit = nullptr;
|
|
|
|
lastMessageMode = 1;
|
|
lastMainMode = 1;
|
|
lastItemMode = 1;
|
|
lastItem = 999;
|
|
lastValue = 999;
|
|
lastUnit = nullptr;
|
|
|
|
lastD0 = 999;
|
|
lastD1 = 999;
|
|
lastD2 = 999;
|
|
lastD3 = 999;
|
|
lastpDUnit = nullptr;
|
|
|
|
// Check if device exists
|
|
for (int i = 0; i < 5; i++) {
|
|
Wire.beginTransmission(i2caddr);
|
|
if (Wire.endTransmission() == 0) {
|
|
bOK = true;
|
|
ESP_LOGI(TAG_UI," UI - device Found at 0x%02X\n", i2caddr);
|
|
break;
|
|
}
|
|
delay(50);
|
|
}
|
|
|
|
if (!bOK) {
|
|
ESP_LOGI(TAG_UI," UI - device NOT found at 0x%02X\n", i2caddr);
|
|
return;
|
|
}
|
|
|
|
// Init Display hardware
|
|
begin(SSD1306_SWITCHCAPVCC, i2caddr);
|
|
//setContrast(contrast / 2);
|
|
setTextColor(SSD1306_WHITE);
|
|
updateScreen();
|
|
|
|
// Display Logo
|
|
int x = (width() - 64);
|
|
int y = (height() - 64) / 2;
|
|
drawBitmap(x, y, logo, 64, 64, 1);
|
|
updateScreen();
|
|
ssd1306_hscroll(true, 0, 7, x, 32);
|
|
|
|
// Box
|
|
boxMode = { 0, HEIGHT_UNIT, 24, 8 };
|
|
boxTitle = { 0, 0, 64, 16 };
|
|
boxValue = { 0, 0, 0, 16 };
|
|
boxUnit = { POS_X_UNIT, 0, WIDTH_UNIT, HEIGHT_UNIT };
|
|
|
|
boxDUnit = {POS_X_UNIT, POS_Y_BOTTOM - HEIGHT_UNIT, WIDTH_UNIT, HEIGHT_UNIT}; // 16
|
|
boxD3 = {POS_X_D3, POS_Y_BOTTOM - HEIGHT_D3, WIDTH_D3, HEIGHT_D3}; // 17 + 2
|
|
boxDot = {POS_X_DOT, POS_Y_BOTTOM - HEIGHT_DOT, WIDTH_DOT, HEIGHT_DOT}; // 7 + 2
|
|
boxD2 = {POS_X_D2, POS_Y_BOTTOM - HEIGHT_D2, WIDTH_D2, HEIGHT_D2}; // 17 + 2
|
|
boxD1 = {POS_X_D1, POS_Y_BOTTOM - HEIGHT_D1, WIDTH_D1, HEIGHT_D1}; // 17 + 2
|
|
boxD0 = {POS_X_D0, POS_Y_BOTTOM - HEIGHT_D0, WIDTH_D0, HEIGHT_D0}; // 17 + 2
|
|
|
|
|
|
//
|
|
// Buttons
|
|
//
|
|
pinMode(PIN_SW_SET, INPUT_PULLUP);
|
|
pinMode(PIN_SW_UP, INPUT_PULLUP);
|
|
pinMode(PIN_SW_DOWN, INPUT_PULLUP);
|
|
attachInterrupt(digitalPinToInterrupt(PIN_SW_SET), buttonSetISR, CHANGE);
|
|
attachInterrupt(digitalPinToInterrupt(PIN_SW_UP), buttonUpISR, CHANGE);
|
|
attachInterrupt(digitalPinToInterrupt(PIN_SW_DOWN), buttonDownISR, CHANGE);
|
|
initButtonState();
|
|
}
|
|
|
|
void CUI::start() {
|
|
vTaskDelay(1500/portTICK_PERIOD_MS);
|
|
clearDisplayBuffer();
|
|
updateScreen();
|
|
initButtonState();
|
|
//getBoundaries();
|
|
}
|
|
|
|
void CUI::getBoundaries() {
|
|
// Display Boundary
|
|
{
|
|
int16_t x, y;
|
|
uint16_t w, h;
|
|
char sz[2];
|
|
sz[1] = 0;
|
|
int nMaxW24 = 0;
|
|
int nMaxH24 = 0;
|
|
int nMaxW18 = 0;
|
|
int nMaxH18 = 0;
|
|
int nMaxW9 = 0;
|
|
int nMaxH9 = 0;
|
|
int nMaxW24A = 0;
|
|
int nMaxH24A = 0;
|
|
int nMaxW18A = 0;
|
|
int nMaxH18A = 0;
|
|
int nMaxW9A = 0;
|
|
int nMaxH9A = 0;
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
sz[0] = 0x30 + i;
|
|
setFont(&FreeSansBold24pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound24 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
if (w > nMaxW24) nMaxW24 = w;
|
|
if (h > nMaxH24) nMaxH24 = h;
|
|
|
|
setFont(&FreeSans18pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
if (w > nMaxW18) nMaxW18 = w;
|
|
if (h > nMaxH18) nMaxH18 = h;
|
|
|
|
setFont(&FreeSans9pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
if (w > nMaxW9) nMaxW9 = w;
|
|
if (h > nMaxH9) nMaxH9 = h;
|
|
}
|
|
|
|
for (int i = 0; i < 26; i++) {
|
|
sz[0] = 'A' + i;
|
|
setFont(&FreeSansBold24pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound24 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
if (w > nMaxW24A) nMaxW24A = w;
|
|
if (h > nMaxH24A) nMaxH24A = h;
|
|
|
|
setFont(&FreeSans18pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
if (w > nMaxW18A) nMaxW18A = w;
|
|
if (h > nMaxH18A) nMaxH18A = h;
|
|
|
|
setFont(&FreeSans9pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
if (w > nMaxW9A) nMaxW9A = w;
|
|
if (h > nMaxH9A) nMaxH9A = h;
|
|
}
|
|
|
|
{
|
|
sz[0] = ':';
|
|
setFont(&FreeSansBold24pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound24 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
|
|
setFont(&FreeSans18pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
|
|
setFont(&FreeSans9pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
}
|
|
|
|
{
|
|
sz[0] = '.';
|
|
setFont(&FreeSansBold24pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound24 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
|
|
setFont(&FreeSans18pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
|
|
setFont(&FreeSans9pt7b);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
ESP_LOGI(TAG_UI,"TextBound18 - '%c' w(%d) h(%d)\n", sz[0], w, h);
|
|
}
|
|
|
|
ESP_LOGI(TAG_UI,"Font24 Max w(%d) h(%d)\n", nMaxW24, nMaxH24);
|
|
ESP_LOGI(TAG_UI,"Font24A Max w(%d) h(%d)\n", nMaxW24A, nMaxH24A);
|
|
|
|
ESP_LOGI(TAG_UI,"Font18 Max w(%d) h(%d)\n", nMaxW18, nMaxH18);
|
|
ESP_LOGI(TAG_UI,"Font18A Max w(%d) h(%d)\n", nMaxW18A, nMaxH18A);
|
|
|
|
ESP_LOGI(TAG_UI,"Font_9 Max w(%d) h(%d)\n", nMaxW9, nMaxH9);
|
|
ESP_LOGI(TAG_UI,"Font_9A Max w(%d) h(%d)\n", nMaxW9A, nMaxH9A);
|
|
}
|
|
}
|
|
|
|
MY_IRAM_ATTR void CUI::message(uint8_t lineNo, char *sz) {
|
|
int16_t x, y;
|
|
uint16_t w, h;
|
|
|
|
if (!bOK) return;
|
|
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
if (w > 128) w = 128;
|
|
fillRect(0,lineNo * 8,w,8, SSD1306_BLACK);
|
|
setFont(NULL);
|
|
setTextSize(1);
|
|
setCursor(0, lineNo * 8);
|
|
print(sz);
|
|
updateRegion(lineNo,lineNo,0,w);
|
|
}
|
|
|
|
// Main function to monitor and update display
|
|
MY_IRAM_ATTR void CUI::updateDisplay(unsigned long tickSecond) {
|
|
if (!bOK) return;
|
|
static unsigned long lastUpdate = 0;
|
|
static unsigned long lastMainModeChange = 0;
|
|
|
|
bool bUpdateTop = false;
|
|
bool bUpdateBottom = false;
|
|
|
|
bUpdateTop = displayTop();
|
|
if (tickSecond != lastUpdate) {
|
|
bUpdateBottom = displayBottom();
|
|
lastUpdate = tickSecond;
|
|
}
|
|
|
|
if (bUpdateTop && bUpdateBottom) {
|
|
updateScreen();
|
|
} else if (bUpdateTop) {
|
|
updateRegion(0, 1, 0, SCREEN_WIDTH - 1);
|
|
} else if (bUpdateBottom) {
|
|
updateRegion(3, 7, 0, SCREEN_WIDTH - 1);
|
|
}
|
|
|
|
if (tickSecond - lastMainModeChange >= 20) {
|
|
lastMainMode = m_nMainMode;
|
|
m_nMainMode = (m_nMainMode + 1) % 2;
|
|
lastMainModeChange = tickSecond;
|
|
}
|
|
}
|
|
|
|
MY_IRAM_ATTR void CUI::updateDisplayTop(unsigned long tick) {
|
|
if (!bOK) return;
|
|
|
|
if (displayTop()) {
|
|
updateRegion(0, 1, 0, SCREEN_WIDTH - 1);
|
|
}
|
|
}
|
|
|
|
MY_IRAM_ATTR void CUI::updateDisplayBottom(unsigned long tickSecond) {
|
|
if (!bOK) return;
|
|
|
|
static unsigned long lastMainModeChange = 0;
|
|
|
|
if (displayBottom()) {
|
|
updateRegion(3, 7, 0, SCREEN_WIDTH - 1);
|
|
}
|
|
|
|
if (tickSecond - lastMainModeChange >= 20) {
|
|
lastMainMode = m_nMainMode;
|
|
m_nMainMode = (m_nMainMode + 1) % 2;
|
|
lastMainModeChange = tickSecond;
|
|
}
|
|
}
|
|
|
|
MY_IRAM_ATTR bool CUI::displayTop() {
|
|
static uint8_t lastHour = 255, lastMin = 255, lastSec = 255;
|
|
bool bUpdateTop = false;
|
|
char sz[32];
|
|
int16_t x, y;
|
|
uint16_t w, h;
|
|
int16_t firstC = SCREEN_WIDTH - 1;
|
|
int16_t lastC = 0;
|
|
int16_t endX = SCREEN_WIDTH - WIDTH_UNIT - SPACING * 2;
|
|
|
|
// Message Mode
|
|
if (!bButtonChanged) {
|
|
if (config.bCheckAC && !isWiFiConnected()) m_nMessageMode = MESSAGE_MODE::MODE_NO_WIFI;
|
|
else if (config.bCheckAC && (status.nFlags & FLAG_ZCD_AC)) m_nMessageMode = MESSAGE_MODE::MODE_AC;
|
|
else if (config.bCheckAC && (status.nFlags & FLAG_ZCD_LOAD)) m_nMessageMode = MESSAGE_MODE::MODE_LOAD;
|
|
else m_nMessageMode = MESSAGE_MODE::MODE_NONE;
|
|
|
|
if (m_nMessageMode != lastMessageMode) {
|
|
char sz[32];
|
|
switch(m_nMessageMode) {
|
|
case MESSAGE_MODE::MODE_NO_WIFI:
|
|
strcpy(sz, "No WiFi! ");
|
|
break;
|
|
case MESSAGE_MODE::MODE_AC:
|
|
strcpy(sz, "Check AC! ");
|
|
break;
|
|
case MESSAGE_MODE::MODE_LOAD:
|
|
strcpy(sz, "Check Load! ");
|
|
break;
|
|
}
|
|
|
|
if (m_nMessageMode != MESSAGE_MODE::MODE_NONE) {
|
|
fillRect(0, 0, SCREEN_WIDTH, HEIGHT_UNIT, SSD1306_BLACK);
|
|
setFont(&FreeSans9pt7b);
|
|
setCursor(boxTitle.x, boxTitle.y + 15 - FONT_DESCENT);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
print(sz);
|
|
updateRegion(0, 1, 0, w - 1);
|
|
lastItemMode = 999;
|
|
lastMessageMode = m_nMessageMode;
|
|
return false;
|
|
}
|
|
} else {
|
|
if (m_nMessageMode != MESSAGE_MODE::MODE_NONE) {
|
|
//ESP_LOGI(TAG_UI,"UI - Message NOT CHANGED and MODE is NOT NORMAL");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
lastMessageMode = MESSAGE_MODE::MODE_NONE;
|
|
|
|
// ItemMode
|
|
if (m_nItemMode != lastItemMode) {
|
|
setFont(NULL);
|
|
setTextSize(1);
|
|
boxMode.w = 24;
|
|
fillRect(boxMode.x, boxMode.y, boxMode.w, boxMode.h, SSD1306_BLACK);
|
|
switch(m_nItemMode) {
|
|
case ITEM_MODE::MODE_SET:
|
|
setCursor(boxMode.x, boxMode.y);
|
|
print("SET");
|
|
//ESP_LOGI(TAG_UI,"UI - Item Mode Change - SET");
|
|
break;
|
|
case ITEM_MODE::MODE_CONFIG:
|
|
setCursor(boxMode.x, boxMode.y);
|
|
print("CFG");
|
|
//ESP_LOGI(TAG_UI,"UI - Item Mode Change - CONFIG");
|
|
break;
|
|
case ITEM_MODE::MODE_NORMAL:
|
|
//ESP_LOGI(TAG_UI,"UI - Item Mode Change - NORMAL");
|
|
break;
|
|
}
|
|
updateRegion(2,2,0,boxMode.w);
|
|
lastItemMode = m_nItemMode;
|
|
lastItem = 999;
|
|
lastValue = m_nValue + 1111;
|
|
}
|
|
|
|
// Top
|
|
setFont(&FreeSans9pt7b);
|
|
|
|
if (m_nItem != lastItem) {
|
|
|
|
// Title
|
|
fillRect(0, 0, SCREEN_WIDTH, HEIGHT_UNIT, SSD1306_BLACK);
|
|
setCursor(boxTitle.x, boxTitle.y + 15 - FONT_DESCENT);
|
|
getTextBounds((const char *)title[m_nItem], 0, 0, &x, &y, &w, &h);
|
|
boxTitle.w = w + 2;
|
|
print(title[m_nItem]);
|
|
|
|
// Value
|
|
if (m_nItem == UI_ITEM::ITEM_CLOCK) {
|
|
sprintf(sz, "%02d:%02d.%02d", g_nHour, g_nMinute, g_nSecond);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
boxValue.x = boxTitle.w + 8;
|
|
boxValue.w = SCREEN_WIDTH - boxValue.x;
|
|
lastHour = g_nHour;
|
|
lastMin = g_nMinute;
|
|
lastSec = g_nSecond;
|
|
} else {
|
|
if (m_nItem < ITEM_HEAT1_MANUAL) {
|
|
sprintf(sz, "%.1f", m_nValue / 10.0f);
|
|
}
|
|
else {
|
|
if (m_nItem < ITEM_CHECK_AC)
|
|
sprintf(sz, "%s", m_nValue ? "Manual" : "Auto");
|
|
else
|
|
sprintf(sz, "%s", m_nValue ? "Yes" : "No");
|
|
endX = SCREEN_WIDTH - 1;
|
|
}
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
int16_t newX = endX - w - SPACING;
|
|
uint16_t newW = endX - newX;
|
|
boxValue.x = newX;
|
|
boxValue.w = newW;
|
|
lastValue = m_nValue;
|
|
}
|
|
setCursor(boxValue.x, boxValue.y + 15 - FONT_DESCENT);
|
|
print(sz);
|
|
|
|
// Item Unit
|
|
if (m_nItem != UI_ITEM::ITEM_CLOCK && m_nItem < UI_ITEM::ITEM_HEAT1_MANUAL) {
|
|
m_pUnit = (uint8_t *) unit[item_unit_idx[m_nItem]];
|
|
drawBitmap(boxUnit.x, boxUnit.y, m_pUnit, boxUnit.w, boxUnit.h, SSD1306_WHITE);
|
|
lastUnit = m_pUnit;
|
|
} else {
|
|
m_pUnit = nullptr;
|
|
}
|
|
|
|
lastItem = m_nItem;
|
|
bUpdateTop = true;
|
|
firstC = 0;
|
|
lastC = 127;
|
|
return true;
|
|
}
|
|
|
|
// value
|
|
if (m_nItem == UI_ITEM::ITEM_CLOCK) {
|
|
if (lastHour != g_nHour || lastMin != g_nMinute || lastSec != g_nSecond) {
|
|
lastHour = g_nHour;
|
|
lastMin = g_nMinute;
|
|
lastSec = g_nSecond;
|
|
fillRect(boxValue.x, boxValue.y, boxValue.w, boxValue.h, SSD1306_BLACK);
|
|
sprintf(sz, "%02d:%02d.%02d", g_nHour, g_nMinute, g_nSecond);
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
boxValue.x = boxTitle.w + 8;
|
|
boxValue.w = SCREEN_WIDTH - boxValue.x;
|
|
|
|
setCursor(boxValue.x, boxValue.y + 15 - FONT_DESCENT);
|
|
print(sz);
|
|
|
|
bUpdateTop = true;
|
|
firstC = boxValue.x;
|
|
lastC = 127;
|
|
}
|
|
} else if (m_nValue != lastValue) {
|
|
fillRect(boxValue.x, boxValue.y, boxValue.w + SPACING, boxValue.h, SSD1306_BLACK);
|
|
if (m_nItem < ITEM_HEAT1_MANUAL) {
|
|
sprintf(sz, "%.1f", m_nValue / 10.0f);
|
|
}
|
|
else {
|
|
if (m_nItem < ITEM_CHECK_AC)
|
|
sprintf(sz, "%s", m_nValue ? "Manual" : "Auto");
|
|
else
|
|
sprintf(sz, "%s", m_nValue ? "Yes" : "No");
|
|
endX = SCREEN_WIDTH - SPACING - 1;
|
|
}
|
|
getTextBounds((const char *)sz, 0, 0, &x, &y, &w, &h);
|
|
int16_t newX = endX - w - SPACING;
|
|
uint16_t newW = endX - newX;
|
|
|
|
setCursor(newX, boxValue.y + 15 - FONT_DESCENT);
|
|
print(sz);
|
|
|
|
bUpdateTop = true;
|
|
firstC = boxValue.x < newX ? boxValue.x : newX;
|
|
lastC = endX + SPACING;
|
|
boxValue.x = newX;
|
|
boxValue.w = newW;
|
|
lastValue = m_nValue;
|
|
}
|
|
|
|
|
|
|
|
if (bUpdateTop && lastC - firstC > 0) {
|
|
//unsigned long m = millis();
|
|
updateRegion(0, 1, firstC, lastC);
|
|
//m = millis() - m;
|
|
//ESP_LOGI(TAG_UI,"UI - Update Top(%d~%d): %d msec\n", firstC, lastC, m);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
MY_IRAM_ATTR bool CUI::displayBottom() {
|
|
bool bUnitChange = false;
|
|
bool bD3Change = false;
|
|
bool bD2Change = false;
|
|
bool bD1Change = false;
|
|
bool bD0Change = false;
|
|
int firstC = SCREEN_WIDTH - 1;
|
|
int lastC = 0;
|
|
char sz[32];
|
|
static uint8_t bLastNTP = 0xFF;
|
|
static uint8_t bLastBLE = (uint8_t)(~FLAG_BLE_NODATA);
|
|
static uint8_t bLastConn = 0xFF;
|
|
static uint8_t bLastWiFi = 0xFF;
|
|
|
|
// Bottom
|
|
// Update temperature and humidity if they have changed
|
|
int16_t value;
|
|
switch (m_nMainMode) {
|
|
case MAIN_MODE::MODE_TEMP:
|
|
value = status.nTemp1;
|
|
if (value < 0) value = 0;
|
|
m_pDUnit = (uint8_t *) °reeC[0];
|
|
break;
|
|
case MAIN_MODE::MODE_HUMID:
|
|
value = status.nHumid1;
|
|
if (value < 0) value = 0;
|
|
m_pDUnit = (uint8_t *) &percentSign[0];
|
|
break;
|
|
default:
|
|
value = 0;
|
|
break;
|
|
}
|
|
|
|
// Unit
|
|
if (m_pDUnit != lastpDUnit) {
|
|
fillRect(boxDUnit.x, boxDUnit.y, boxDUnit.w, boxDUnit.h, SSD1306_BLACK);
|
|
drawBitmap( boxDUnit.x, boxDUnit.y,
|
|
m_pDUnit,
|
|
boxDUnit.w, boxDUnit.h, SSD1306_WHITE);
|
|
lastpDUnit = m_pDUnit;
|
|
bUnitChange = true;
|
|
firstC = boxDUnit.x;
|
|
lastC = boxDUnit.x + boxDUnit.w - 1;
|
|
}
|
|
|
|
// Value
|
|
m_nD3 = value % 10;
|
|
value /= 10;
|
|
m_nD2 = value % 10;
|
|
value /= 10;
|
|
m_nD1 = value % 10;
|
|
m_nD0 = value / 10;
|
|
|
|
// Update Tenths digit
|
|
if (m_nD3 != lastD3) {
|
|
fillRect(boxD3.x, boxD3.y, boxD3.w, boxD3.h, SSD1306_BLACK);
|
|
setFont(&FreeSans18pt7b); // 25 pixels high
|
|
sprintf(sz, "%d", m_nD3);
|
|
setCursor(boxD3.x, SCREEN_HEIGHT - FONT_DESCENT);
|
|
print(sz);
|
|
lastD3 = m_nD3;
|
|
bD3Change = true;
|
|
firstC = boxD3.x;
|
|
int end = boxD3.x + boxD3.w - 1;
|
|
if (lastC < end)
|
|
lastC = end;
|
|
}
|
|
|
|
setFont(&FreeSansBold24pt7b); // 35 pixels high
|
|
// Dot
|
|
if (!bDot)
|
|
{
|
|
setCursor(boxDot.x, SCREEN_HEIGHT - FONT_DESCENT);
|
|
print(".");
|
|
bDot = true;
|
|
firstC = boxDot.x;
|
|
int end = boxDot.x + boxDot.w - 1;
|
|
if (lastC < end)
|
|
lastC = end;
|
|
}
|
|
|
|
// Update One's digit
|
|
if (m_nD2 != lastD2) {
|
|
fillRect(boxD2.x, boxD2.y, boxD2.w, boxD2.h, SSD1306_BLACK);
|
|
sprintf(sz, "%d", m_nD2);
|
|
setCursor(boxD2.x, SCREEN_HEIGHT - FONT_DESCENT);
|
|
print(sz);
|
|
lastD2 = m_nD2;
|
|
bD2Change = true;
|
|
firstC = boxD2.x;
|
|
int end = boxD2.x + boxD2.w - 1;
|
|
if (lastC < end)
|
|
lastC = end;
|
|
}
|
|
|
|
// Update Ten's digit
|
|
if (m_nD1 != lastD1) {
|
|
fillRect(boxD1.x, boxD1.y, boxD1.w, boxD1.h, SSD1306_BLACK);
|
|
if (m_nD0 > 0 || m_nD1 > 0) {
|
|
sprintf(sz, "%d", m_nD1);
|
|
setCursor(boxD1.x, SCREEN_HEIGHT - FONT_DESCENT);
|
|
print(sz);
|
|
}
|
|
lastD1 = m_nD1;
|
|
bD1Change = true;
|
|
firstC = boxD1.x;
|
|
int end = boxD1.x + boxD1.w - 1;
|
|
if (lastC < end)
|
|
lastC = end;
|
|
}
|
|
|
|
// Update Hundred's digit
|
|
if (m_nD0 != lastD0) {
|
|
fillRect(boxD0.x, boxD0.y, boxD0.w, boxD0.h, SSD1306_BLACK);
|
|
if (m_nD0 > 0) {
|
|
sprintf(sz, "%d", m_nD0);
|
|
setCursor(boxD0.x, SCREEN_HEIGHT - FONT_DESCENT);
|
|
print(sz);
|
|
}
|
|
lastD0 = m_nD0;
|
|
bD0Change = true;
|
|
firstC = boxD0.x;
|
|
int end = boxD0.x + boxD0.w - 1;
|
|
if (lastC < end)
|
|
lastC = end;
|
|
}
|
|
|
|
uint8_t sp = (bD0Change || bD1Change || bD2Change) ? 3 : 4;
|
|
int updateWidth = lastC - firstC;
|
|
if (updateWidth > 96) {
|
|
return true;
|
|
}
|
|
else
|
|
if (updateWidth > 0) {
|
|
//unsigned long m = millis();
|
|
updateRegion(sp, 7, firstC, lastC);
|
|
//m = millis() - m;
|
|
//ESP_LOGI(TAG_UI,"UI - Update Bottom(%d~%d): %d msec\n", firstC, lastC, m);
|
|
}
|
|
|
|
// Bottom Left
|
|
{
|
|
bool bUpdate = false;
|
|
setFont(NULL);
|
|
setTextSize(1);
|
|
|
|
// WiFi Status
|
|
uint8_t bWiFi = isWiFiConnected();
|
|
if (bWiFi != bLastWiFi) {
|
|
if (!isWiFiConnected()) {
|
|
setCursor(0, 7 * 8);
|
|
print('W');
|
|
} else {
|
|
fillRect(0, 7 * 8, 8, 8, SSD1306_BLACK);
|
|
}
|
|
bLastWiFi = bWiFi;
|
|
bUpdate = true;
|
|
}
|
|
|
|
// Time Manager
|
|
uint8_t bNTP = timeManager.hasNTPUpdate() ? 1 : 0;
|
|
if (bNTP != bLastNTP) {
|
|
if (!timeManager.hasNTPUpdate()) {
|
|
setCursor(0, 6 * 8);
|
|
print('T');
|
|
}
|
|
else {
|
|
fillRect(0, 6 * 8, 8, 8, SSD1306_BLACK);
|
|
}
|
|
bLastNTP = bNTP;
|
|
bUpdate = true;
|
|
}
|
|
|
|
// Client Connection
|
|
uint8_t bConn = host.isConnected();
|
|
if (bConn != bLastConn) {
|
|
if (bConn) {
|
|
setCursor(0, 7 * 8);
|
|
print('C');
|
|
}
|
|
else {
|
|
fillRect(0, 7 * 8, 8, 8, SSD1306_BLACK);
|
|
}
|
|
bLastConn = bConn;
|
|
bUpdate = true;
|
|
}
|
|
|
|
if (bUpdate) {
|
|
updateRegion(6,7,0,7);
|
|
lastMainMode = m_nMainMode;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Buttons
|
|
//
|
|
MY_IRAM_ATTR void CUI::loopButton(unsigned long tickMillis) {
|
|
//if (host.isConnected()) {
|
|
// initButtonState();
|
|
// return;
|
|
//}
|
|
static unsigned long lastButtonAction = 0;
|
|
|
|
checkButtonStates(tickMillis);
|
|
if (bButtonSetDown || bButtonSetUp || bButtonUpDown || bButtonUpUp || bButtonDownDown || bButtonDownUp) {
|
|
bButtonChanged = true;
|
|
lastButtonAction = tickMillis;
|
|
} else
|
|
if (tickMillis - lastButtonAction > 20000) {
|
|
bButtonChanged = false;
|
|
}
|
|
|
|
if (bButtonSetUp) {
|
|
switch(m_nItemMode) {
|
|
case ITEM_MODE::MODE_NORMAL:
|
|
if (set_idx[m_nItem])
|
|
m_nItemMode = buttonSetDownDuration > 1000 ? MODE_CONFIG : MODE_SET;
|
|
break;
|
|
case ITEM_MODE::MODE_SET:
|
|
if (set_idx[m_nItem]) {
|
|
switch(m_nItem) {
|
|
case ITEM_TEMP_TARGET: config.nTempTarget = m_nValue; break;
|
|
case ITEM_HUMID_TARGET: config.nHumidTarget = m_nValue; break;
|
|
|
|
case ITEM_HEAT1: status.nHeater1Duty = m_nValue * 10; break;
|
|
case ITEM_HEAT2: status.nHeater2Duty = m_nValue * 10; break;
|
|
case ITEM_MIST:
|
|
status.nMistDuty = m_nValue * 10;
|
|
break;
|
|
case ITEM_FAN:
|
|
status.nFanDuty = m_nValue;
|
|
break;
|
|
case ITEM_MOTOR: status.nMotorDuty = m_nValue;
|
|
break;
|
|
case ITEM_LIGHT:
|
|
status.nLightTargetDuty = m_nValue;
|
|
break;
|
|
|
|
case ITEM_HEAT1_MANUAL:
|
|
status.nFlags = m_nValue ? status.nFlags | FLAG_MANUAL_HEATER1 : status.nFlags & ~FLAG_MANUAL_HEATER1;
|
|
break;
|
|
case ITEM_HEAT2_MANUAL:
|
|
status.nFlags = m_nValue ? status.nFlags | FLAG_MANUAL_HEATER2 : status.nFlags & ~FLAG_MANUAL_HEATER2;
|
|
break;
|
|
case ITEM_MIST_MANUAL:
|
|
status.nFlags = m_nValue ? status.nFlags | FLAG_MANUAL_MIST : status.nFlags & ~FLAG_MANUAL_MIST;
|
|
break;
|
|
case ITEM_FAN_MANUAL:
|
|
status.nFlags = m_nValue ? status.nFlags | FLAG_MANUAL_FAN : status.nFlags & ~FLAG_MANUAL_FAN;
|
|
break;
|
|
case ITEM_MOTOR_MANUAL:
|
|
status.nFlags = m_nValue ? status.nFlags | FLAG_MANUAL_MOTOR : status.nFlags & ~FLAG_MANUAL_MOTOR;
|
|
break;
|
|
case ITEM_LIGHT_MANUAL:
|
|
status.nFlags = m_nValue ? status.nFlags | FLAG_MANUAL_LIGHT : status.nFlags & ~FLAG_MANUAL_LIGHT;
|
|
break;
|
|
case ITEM_CHECK_AC:
|
|
config.bCheckAC = m_nValue ? true : false;
|
|
}
|
|
m_nItemMode = MODE_NORMAL;
|
|
}
|
|
break;
|
|
case ITEM_MODE::MODE_CONFIG:
|
|
m_nItemMode = MODE_NORMAL;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
switch (m_nItemMode) {
|
|
case MODE_NORMAL:
|
|
if (bButtonUpUp) {
|
|
m_nItem = m_nItem > 0 ? --m_nItem : UI_ITEM::ITEM_COUNT - 1;
|
|
lastValue = m_nValue + 1;
|
|
}
|
|
if (bButtonDownUp) {
|
|
m_nItem = m_nItem < ITEM_COUNT - 1 ? ++m_nItem : 0;
|
|
lastValue = m_nValue + 1;
|
|
}
|
|
break;
|
|
case MODE_SET:
|
|
if (bButtonUpUp) {
|
|
if (fineControl[m_nItem]) {
|
|
if (m_nItem >= ITEM_HEAT1_MANUAL) {
|
|
m_nValue = m_nValue ? 0 : 1;
|
|
} else if (m_nValue < 1000) {
|
|
m_nValue++;
|
|
}
|
|
}
|
|
else {
|
|
m_nValue = (m_nValue / 10 + 1) * 10;
|
|
if (m_nValue > 1000) m_nValue = 1000;
|
|
}
|
|
}
|
|
if (bButtonDownUp) {
|
|
if (fineControl[m_nItem]) {
|
|
if (m_nItem >= ITEM_HEAT1_MANUAL) {
|
|
m_nValue = m_nValue ? 0 : 1;
|
|
} else if (m_nValue > 0) {
|
|
m_nValue--;
|
|
}
|
|
}
|
|
else {
|
|
m_nValue = (m_nValue / 10 - 1) * 10;
|
|
if (m_nValue < 0) m_nValue = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (m_nItemMode == ITEM_MODE::MODE_NORMAL || !set_idx[m_nItem]) {
|
|
switch(m_nItem) {
|
|
case ITEM_TEMP1: m_nValue = status.nTemp1; break;
|
|
case ITEM_TEMP2: m_nValue = status.nTemp2; break;
|
|
case ITEM_TEMP3: m_nValue = status.nTemp3; break;
|
|
case ITEM_HUMID: m_nValue = status.nHumid1; break;
|
|
case ITEM_HUMID2:m_nValue = status.nHumid2; break;
|
|
|
|
case ITEM_TEMP_TARGET: m_nValue = config.nTempTarget; break;
|
|
case ITEM_HUMID_TARGET: m_nValue = config.nHumidTarget; break;
|
|
|
|
case ITEM_HEAT1: m_nValue = status.nHeater1Duty / 10; break;
|
|
case ITEM_HEAT2: m_nValue = status.nHeater2Duty / 10; break;
|
|
case ITEM_MIST: m_nValue = status.nMistDuty / 10; break;
|
|
case ITEM_FAN: m_nValue = status.nFanDuty; break;
|
|
case ITEM_MOTOR: m_nValue = status.nMotorDuty; break;
|
|
case ITEM_LIGHT: m_nValue = status.nLightTargetDuty; break;
|
|
|
|
case ITEM_HEAT1_MANUAL: m_nValue = status.nFlags & FLAG_MANUAL_HEATER1 ? 1 : 0; break;
|
|
case ITEM_HEAT2_MANUAL: m_nValue = status.nFlags & FLAG_MANUAL_HEATER2 ? 1 : 0; break;
|
|
case ITEM_MIST_MANUAL: m_nValue = status.nFlags & FLAG_MANUAL_MIST ? 1 : 0; break;
|
|
case ITEM_FAN_MANUAL: m_nValue = status.nFlags & FLAG_MANUAL_FAN ? 1 : 0; break;
|
|
case ITEM_MOTOR_MANUAL: m_nValue = status.nFlags & FLAG_MANUAL_MOTOR ? 1 : 0; break;
|
|
case ITEM_LIGHT_MANUAL: m_nValue = status.nFlags & FLAG_MANUAL_LIGHT ? 1 : 0; break;
|
|
|
|
case ITEM_CHECK_AC: m_nValue = config.bCheckAC ? 1 : 0; break;
|
|
}
|
|
}
|
|
|
|
bButtonSetUp = false;
|
|
bButtonUpUp = false;
|
|
bButtonDownUp = false;
|
|
}
|
|
|
|
void CUI::initButtonState() {
|
|
buttonSetChangeTime = 0; // Time when button was pressed
|
|
buttonUpChangeTime = 0; // Time when button was pressed
|
|
buttonDownChangeTime = 0; // Time when button was pressed
|
|
|
|
buttonSetDownTime = 0; // Time when button was pressed
|
|
buttonUpDownTime = 0; // Time when button was pressed
|
|
buttonDownDownTime = 0; // Time when button was pressed
|
|
|
|
buttonSetDownDuration = 0; // Time when button was pressed
|
|
buttonUpDownDuration = 0; // Time when button was pressed
|
|
buttonDownDownDuration = 0; // Time when button was pressed
|
|
|
|
bButtonSetChanged = false;
|
|
bButtonSetUp = false;
|
|
bButtonSetDown = false;
|
|
|
|
bButtonUpChanged = false;
|
|
bButtonUpUp = false;
|
|
bButtonUpDown = false;
|
|
|
|
bButtonDownChanged = false;
|
|
bButtonDownUp = false;
|
|
bButtonDownDown = false;
|
|
|
|
m_nMainMode = 0;
|
|
m_nItemMode = 0;
|
|
m_nItem = 0;
|
|
m_nValue = 0;
|
|
m_pUnit = (uint8_t *) unit[item_unit_idx[m_nItem]];
|
|
m_nD0 = m_nD1 = m_nD2 = m_nD3 = 0;
|
|
|
|
lastMainMode = 1;
|
|
lastItemMode = 1;
|
|
lastItem = UI_ITEM::ITEM_COUNT;
|
|
lastValue = 1;
|
|
lastUnit = nullptr;
|
|
lastD0 = lastD1 = lastD2 = lastD3 = 1;
|
|
}
|
|
|
|
void CUI::checkButtonStates(unsigned long currentMillis) {
|
|
if (bButtonSetChanged) {
|
|
// Compare with the last interrupt time to ensure debounce delay
|
|
if (currentMillis - buttonSetChangeTime > DEBOUNCE_DELAY) {
|
|
if (digitalRead(PIN_SW_SET) == LOW) {
|
|
// Button pressed
|
|
buttonSetDownTime = buttonSetChangeTime;
|
|
bButtonSetDown = true;
|
|
} else {
|
|
// Button released
|
|
if (bButtonSetDown) {
|
|
bButtonSetUp = true;
|
|
bButtonSetDown = false;
|
|
buttonSetDownDuration = currentMillis - buttonSetDownTime;
|
|
//ESP_LOGI(TAG_UI,"UI Button - SET button RELEASED. Down for %dms\n", buttonSetDownDuration);
|
|
}
|
|
}
|
|
//lastProcessedTime = currentMillis; // Update processed time
|
|
bButtonSetChanged = false; // Reset the flag
|
|
}
|
|
}
|
|
|
|
if (bButtonUpChanged) {
|
|
// Compare with the last interrupt time to ensure debounce delay
|
|
if (currentMillis - buttonUpChangeTime > DEBOUNCE_DELAY) {
|
|
if (digitalRead(PIN_SW_UP) == LOW) {
|
|
// Button pressed
|
|
buttonUpDownTime = buttonUpChangeTime;
|
|
bButtonUpDown = true;
|
|
} else {
|
|
// Button released
|
|
if (bButtonUpDown) {
|
|
bButtonUpUp = true;
|
|
bButtonUpDown = false;
|
|
buttonUpDownDuration = currentMillis - buttonUpDownTime;
|
|
//ESP_LOGI(TAG_UI,"UI Button - UP button RELEASED. Down for %dms\n", buttonUpDownDuration);
|
|
}
|
|
}
|
|
//lastProcessedTime = currentMillis; // Update processed time
|
|
bButtonUpChanged = false; // Reset the flag
|
|
}
|
|
}
|
|
|
|
if (bButtonDownChanged) {
|
|
// Compare with the last interrupt time to ensure debounce delay
|
|
if (currentMillis - buttonDownChangeTime > DEBOUNCE_DELAY) {
|
|
if (digitalRead(PIN_SW_DOWN) == LOW) {
|
|
// Button pressed
|
|
buttonDownDownTime = buttonDownChangeTime;
|
|
bButtonDownDown = true;
|
|
} else {
|
|
// Button released
|
|
if (bButtonDownDown) {
|
|
bButtonDownUp = true;
|
|
bButtonDownDown = false;
|
|
buttonDownDownDuration = currentMillis - buttonDownDownTime;
|
|
//ESP_LOGI(TAG_UI,"UI Button - DOWN button RELEASED. Down for %dms\n", buttonDownDownDuration);
|
|
}
|
|
}
|
|
//lastProcessedTime = currentMillis; // Update processed time
|
|
bButtonDownChanged = false; // Reset the flag
|
|
}
|
|
}
|
|
}
|
|
|
|
// ISR for the Set button handling
|
|
ARDUINO_ISR_ATTR void buttonSetISR() {
|
|
// Record the time of the button interrupt and set a flag
|
|
ui.buttonSetChangeTime = millis();
|
|
ui.bButtonSetChanged = true; // Flag for main loop to process
|
|
}
|
|
|
|
// ISR for the Up button handling
|
|
ARDUINO_ISR_ATTR void buttonUpISR() {
|
|
ui.buttonUpChangeTime = millis();
|
|
ui.bButtonUpChanged = true; // Flag for main loop to process
|
|
}
|
|
|
|
// ISR for the Down button handling
|
|
ARDUINO_ISR_ATTR void buttonDownISR() {
|
|
ui.buttonDownChangeTime = millis();
|
|
ui.bButtonDownChanged = true; // Flag for main loop to process
|
|
} |