Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
- out: sunton
env: "esp32-2432s022c_4MB -e esp32-2432s028r_4MB -e esp32-2432s028r-ili9342_4MB -e esp32-2432s028r_v2_4MB -e esp32-2432s028r-st7789_4MB -e esp32-2432s032c_4MB -e esp32-3248s035c_4MB -e esp32-3248s035r_4MB -e sunton-4827s043c_16MB -e sunton-4827s043r_16MB -e sunton-8048s043c_16MB -e sunton-8048s050c_16MB -e sunton-8048s070c_16MB -e cyd-2424s012_4MB -e esp32-2432s024c_4MB -e esp32-2432s024r_4MB"
- out: waveshare
env: "esp32-one_ili9486 -e esp32-one_st7796 -e ws_esp32_s3_touch_lcd_4p3 -e ws_esp32_s3_touch_lcd_4 -e waveshare-esp32-s3-touch-lcd-7"
env: "esp32-one_ili9486 -e esp32-one_st7796 -e ws_esp32_s3_touch_lcd_4p3 -e ws_esp32_s3_touch_lcd_4 -e waveshare-esp32-s3-touch-lcd-2 -e waveshare-esp32-s3-touch-lcd-7"
- out: wireless-tag
env: "wt32-sc01_4MB -e wt32-sc01_16MB -e wt-86-32-3zw1 -e wt32-sc01-plus_8MB -e wt32-sc01-plus_16MB"
- out: yeacreate
Expand Down
3 changes: 3 additions & 0 deletions src/drv/touch/touch_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class BaseTouch {
#elif TOUCH_DRIVER == 0x3240
#warning Building for CST3240
#include "touch_driver_cst3240.h"
#elif TOUCH_DRIVER == 0x816 && defined(LGFX_USE_V1) && defined(HASP_USE_LGFX_TOUCH)
#warning Building for LovyanGFX CST816
#include "touch_driver_lovyangfx.h"
#elif TOUCH_DRIVER == 0x816
#warning Building for CST816S
#include "touch_driver_cst816.h"
Expand Down
4 changes: 2 additions & 2 deletions src/drv/touch/touch_driver_cst816.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* MIT License - Copyright (c) 2019-2024 Francis Van Roie
For full license information read the LICENSE file in the project folder */

#if defined(ARDUINO) && (TOUCH_DRIVER == 0x816)
#if defined(ARDUINO) && (TOUCH_DRIVER == 0x816) && !defined(HASP_USE_LGFX_TOUCH)
#include <Arduino.h>
#include "ArduinoLog.h"
#include "hasp_conf.h"
Expand Down Expand Up @@ -67,4 +67,4 @@ void TouchCst816::init(int w, int h)

dev::TouchCst816 haspTouch;

#endif // ARDUINO
#endif // ARDUINO && TOUCH_DRIVER == 0x816 && !HASP_USE_LGFX_TOUCH
209 changes: 208 additions & 1 deletion src/hasp/hasp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
* DEFINES
*********************/
#define PAGE_START_INDEX 1 // Page number of array index 0
#define HASP_IDLE_UNLOCK_HOLD_DEFAULT_MS 2000
#define HASP_IDLE_UNLOCK_HOLD_MIN_MS 250
#define HASP_IDLE_UNLOCK_HOLD_MAX_MS 60000
#define HASP_IDLE_LOCK_SCREEN_DEFAULT_SEC 10

/**********************
* TYPEDEFS
Expand Down Expand Up @@ -76,6 +80,17 @@ bool hasp_first_touch_state = false; // Track first touch state
static uint16_t sleepTimeShort = 60; // 1 second resolution
static uint16_t sleepTimeLong = 120; // 1 second resolution
static uint32_t sleepTimeOffset = 0; // 1 second resolution
static bool idleLockEnabled = false;
static bool idleLocked = false;
static bool idleUnlockActive = false;
static bool idleUnlockPending = false;
static uint32_t idleUnlockStart = 0;
static uint16_t idleUnlockHold = HASP_IDLE_UNLOCK_HOLD_DEFAULT_MS;
static uint16_t idleLockScreen = HASP_IDLE_LOCK_SCREEN_DEFAULT_SEC;
static uint32_t idleLockScreenStart = 0;
static lv_obj_t* idleLockOverlay;
static lv_obj_t* idleLockArc;
static lv_obj_t* idleLockLabel;

uint8_t haspStartDim = HASP_START_DIM;
uint8_t haspStartPage = HASP_START_PAGE;
Expand All @@ -94,6 +109,95 @@ lv_obj_t* kb;
static lv_font_t* haspFonts[12] = {nullptr};
uint8_t current_page = 1;

static void hasp_hide_idle_lock_overlay()
{
if(idleLockOverlay) lv_obj_set_hidden(idleLockOverlay, true);
}

static void hasp_show_idle_lock_overlay(uint8_t progress)
{
lv_obj_t* layer = lv_disp_get_layer_sys(NULL);
if(!layer) return;

if(!idleLockOverlay) {
idleLockOverlay = lv_obj_create(layer, NULL);
if(!idleLockOverlay) return;

lv_obj_set_click(idleLockOverlay, false);
lv_obj_set_style_local_bg_color(idleLockOverlay, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
lv_obj_set_style_local_bg_opa(idleLockOverlay, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
lv_obj_set_style_local_border_width(idleLockOverlay, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_style_local_radius(idleLockOverlay, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 0);

idleLockArc = lv_arc_create(idleLockOverlay, NULL);
if(idleLockArc) {
lv_obj_set_click(idleLockArc, false);
lv_obj_set_size(idleLockArc, 170, 170);
lv_arc_set_range(idleLockArc, 0, 100);
lv_arc_set_bg_angles(idleLockArc, 0, 360);
lv_arc_set_rotation(idleLockArc, 270);
lv_obj_set_style_local_line_width(idleLockArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 14);
lv_obj_set_style_local_line_color(idleLockArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, lv_color_hex(0x404040));
lv_obj_set_style_local_line_width(idleLockArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, 14);
lv_obj_set_style_local_line_color(idleLockArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_obj_set_style_local_bg_opa(idleLockArc, LV_ARC_PART_KNOB, LV_STATE_DEFAULT, LV_OPA_TRANSP);
lv_obj_set_style_local_border_opa(idleLockArc, LV_ARC_PART_KNOB, LV_STATE_DEFAULT, LV_OPA_TRANSP);
}

idleLockLabel = lv_label_create(idleLockOverlay, NULL);
if(idleLockLabel) {
lv_label_set_align(idleLockLabel, LV_LABEL_ALIGN_CENTER);
lv_label_set_long_mode(idleLockLabel, LV_LABEL_LONG_BREAK);
lv_obj_set_style_local_text_color(idleLockLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
if(haspFonts[3]) {
lv_obj_set_style_local_text_font(idleLockLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, haspFonts[3]);
}
}
}

lv_obj_set_size(idleLockOverlay, lv_obj_get_width(layer), lv_obj_get_height(layer));
lv_obj_align(idleLockOverlay, layer, LV_ALIGN_CENTER, 0, 0);
lv_obj_move_foreground(idleLockOverlay);
lv_obj_set_hidden(idleLockOverlay, false);

if(idleLockArc) {
lv_arc_set_value(idleLockArc, progress);
lv_obj_align(idleLockArc, idleLockOverlay, LV_ALIGN_CENTER, 0, 0);
}

if(idleLockLabel) {
lv_obj_set_width(idleLockLabel, lv_obj_get_width(idleLockOverlay) - 20);
if(idleUnlockPending) {
lv_label_set_text(idleLockLabel, LV_SYMBOL_EYE_OPEN "\nRelease to unlock");
} else {
lv_label_set_text(idleLockLabel, LV_SYMBOL_EYE_CLOSE "\nHold to unlock");
}
lv_obj_align(idleLockLabel, idleLockOverlay, LV_ALIGN_CENTER, 0, 0);
}
}

static void hasp_lock_idle()
{
if(idleLocked) return;

idleLocked = true;
idleUnlockActive = false;
idleUnlockPending = false;
dispatch_backlight(NULL, "on", TAG_HASP);
hasp_set_wakeup_touch(true);
hasp_show_idle_lock_overlay(100);
idleLockScreenStart = lv_tick_get();
}

static void hasp_update_idle_lock_screen()
{
if(!idleLocked || idleUnlockActive || idleLockScreen == 0 || !haspDevice.get_backlight_power()) return;

if(lv_tick_elaps(idleLockScreenStart) >= (uint32_t)idleLockScreen * 1000) {
dispatch_backlight(NULL, "off", TAG_HASP);
}
}

/**
* Get Font ID
*/
Expand All @@ -116,22 +220,25 @@ HASP_ATTRIBUTE_FAST_MEM void hasp_update_sleep_state()

uint32_t idle = lv_disp_get_inactive_time(lv_disp_get_default()) / 1000;
idle += sleepTimeOffset; // To force a specific state
hasp_update_idle_lock_screen();

if(sleepTimeLong > 0 && idle >= (sleepTimeShort + sleepTimeLong)) {
if(hasp_sleep_state != HASP_SLEEP_LONG) {
gui_hide_pointer(true);
hasp_sleep_state = HASP_SLEEP_LONG;
dispatch_idle_state(HASP_SLEEP_LONG);
dispatch_run_script(NULL, "L:/idle_long.cmd", TAG_HASP);
if(idleLockEnabled && sleepTimeShort > 0) hasp_lock_idle();
}
} else if(sleepTimeShort > 0 && idle >= sleepTimeShort) {
if(hasp_sleep_state != HASP_SLEEP_SHORT) {
gui_hide_pointer(true);
hasp_sleep_state = HASP_SLEEP_SHORT;
dispatch_idle_state(HASP_SLEEP_SHORT);
dispatch_run_script(NULL, "L:/idle_short.cmd", TAG_HASP);
if(idleLockEnabled) hasp_lock_idle();
}
} else {
} else if(!idleLocked) {
if(hasp_sleep_state != HASP_SLEEP_OFF) {
gui_hide_pointer(false);
hasp_sleep_state = HASP_SLEEP_OFF;
Expand Down Expand Up @@ -169,6 +276,10 @@ void hasp_set_sleep_state(uint8_t state)
}
lv_disp_trig_activity(NULL);
hasp_sleep_state = state;

if(idleLockEnabled && state != HASP_SLEEP_OFF && sleepTimeShort > 0) {
hasp_lock_idle();
}
}

void hasp_get_sleep_payload(uint8_t state, char* payload)
Expand Down Expand Up @@ -326,6 +437,12 @@ void hasp_set_wakeup_touch(bool en)
lv_obj_t* layer = lv_disp_get_layer_sys(NULL);
if(!layer) return;

// A latched idle lock owns the system layer until the long-press handler unlocks it.
if(idleLocked) {
if(!en) idleLockScreenStart = lv_tick_get();
en = true;
}

if(lv_obj_get_click(layer) != en) {
hasp_first_touch_state = en;
lv_obj_set_event_cb(layer, first_touch_event_handler);
Expand All @@ -352,6 +469,96 @@ void hasp_set_sleep_time(uint16_t short_time, uint16_t long_time)
sleepTimeLong = long_time;
}

bool hasp_get_idle_lock_enabled()
{
return idleLockEnabled;
}

void hasp_set_idle_lock_enabled(bool enabled)
{
if(idleLockEnabled == enabled) return;

idleLockEnabled = enabled;

if(!enabled) {
idleLocked = false;
idleUnlockActive = false;
idleUnlockPending = false;
hasp_hide_idle_lock_overlay();
hasp_set_wakeup_touch(!haspDevice.get_backlight_power());
} else if(hasp_sleep_state != HASP_SLEEP_OFF && sleepTimeShort > 0) {
hasp_lock_idle();
}
}

uint16_t hasp_get_idle_lock_hold_time()
{
return idleUnlockHold;
}

void hasp_set_idle_lock_hold_time(uint16_t hold_time)
{
if(hold_time < HASP_IDLE_UNLOCK_HOLD_MIN_MS) hold_time = HASP_IDLE_UNLOCK_HOLD_MIN_MS;
if(hold_time > HASP_IDLE_UNLOCK_HOLD_MAX_MS) hold_time = HASP_IDLE_UNLOCK_HOLD_MAX_MS;
idleUnlockHold = hold_time;
}

uint16_t hasp_get_idle_lock_screen_time()
{
return idleLockScreen;
}

void hasp_set_idle_lock_screen_time(uint16_t screen_time)
{
if(idleLockScreen == screen_time) return;

idleLockScreen = screen_time;
idleLockScreenStart = lv_tick_get();
if(idleLocked && screen_time == 0) dispatch_backlight(NULL, "on", TAG_HASP);
}

bool hasp_handle_idle_lock_event(lv_event_t event)
{
if(!idleLocked) return false;

if(event == LV_EVENT_PRESSED) {
idleUnlockStart = lv_tick_get();
idleUnlockActive = true;
idleUnlockPending = false;
dispatch_backlight(NULL, "on", TAG_EVENT);
hasp_show_idle_lock_overlay(100);
idleLockScreenStart = lv_tick_get();

} else if(event == LV_EVENT_PRESSING && idleUnlockActive) {
uint32_t elapsed = lv_tick_elaps(idleUnlockStart);
if(elapsed >= idleUnlockHold) {
idleUnlockPending = true;
hasp_show_idle_lock_overlay(0);
} else {
hasp_show_idle_lock_overlay(((uint32_t)idleUnlockHold - elapsed) * 100 / idleUnlockHold);
}

} else if((event == LV_EVENT_RELEASED || event == LV_EVENT_PRESS_LOST) && idleUnlockActive) {
if(lv_tick_elaps(idleUnlockStart) >= idleUnlockHold) idleUnlockPending = true;

idleUnlockActive = false;

if(idleUnlockPending && event == LV_EVENT_RELEASED) {
idleUnlockPending = false;
idleLocked = false;
hasp_hide_idle_lock_overlay();
hasp_set_wakeup_touch(false);
hasp_update_sleep_state();
} else {
idleUnlockPending = false;
hasp_show_idle_lock_overlay(100);
idleLockScreenStart = lv_tick_get();
}
}

return true;
}

/**
* Checks if we went to sleep, wake up is handled in the event handlers
*/
Expand Down
7 changes: 7 additions & 0 deletions src/hasp/hasp.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ void hasp_set_sleep_state(uint8_t state);
void hasp_get_sleep_time(uint16_t& short_time, uint16_t& long_time);
void hasp_set_sleep_time(uint16_t short_time, uint16_t long_time);
void hasp_set_sleep_offset(uint32_t offset);
bool hasp_get_idle_lock_enabled();
void hasp_set_idle_lock_enabled(bool enabled);
uint16_t hasp_get_idle_lock_hold_time();
void hasp_set_idle_lock_hold_time(uint16_t hold_time);
uint16_t hasp_get_idle_lock_screen_time();
void hasp_set_idle_lock_screen_time(uint16_t screen_time);
bool hasp_handle_idle_lock_event(lv_event_t event);
void hasp_set_wakeup_touch(bool en);
void hasp_set_antiburn(int32_t repeat_count, uint32_t period);
bool hasp_stop_antiburn();
Expand Down
1 change: 1 addition & 0 deletions src/hasp/hasp_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ void first_touch_event_handler(lv_obj_t* obj, lv_event_t event)
{
// log_event("wakeup", event);
if(obj != lv_disp_get_layer_sys(NULL)) return;
if(hasp_handle_idle_lock_event(event)) return;

if(event == LV_EVENT_RELEASED) {
bool changed = hasp_stop_antiburn(); // Disable antiburn task
Expand Down
3 changes: 3 additions & 0 deletions src/hasp_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ const char FP_GUI_INVERT[] PROGMEM = "invert";
const char FP_GUI_TICKPERIOD[] PROGMEM = "tick";
const char FP_GUI_IDLEPERIOD1[] PROGMEM = "idle1";
const char FP_GUI_IDLEPERIOD2[] PROGMEM = "idle2";
const char FP_GUI_IDLELOCK[] PROGMEM = "idlelock";
const char FP_GUI_IDLELOCKHOLD[] PROGMEM = "idlelockhold";
const char FP_GUI_IDLELOCKSCREEN[] PROGMEM = "idlelockscreen";
const char FP_GUI_CALIBRATION[] PROGMEM = "calibration";
const char FP_GUI_BACKLIGHTPIN[] PROGMEM = "bckl";
const char FP_GUI_BACKLIGHTINVERT[] PROGMEM = "bcklinv";
Expand Down
18 changes: 18 additions & 0 deletions src/hasp_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,15 @@ bool guiGetConfig(const JsonObject& settings)
if(guiSleepTime2 != settings[FPSTR(FP_GUI_IDLEPERIOD2)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_GUI_IDLEPERIOD2)] = guiSleepTime2;

if(hasp_get_idle_lock_enabled() != settings[FPSTR(FP_GUI_IDLELOCK)].as<bool>()) changed = true;
settings[FPSTR(FP_GUI_IDLELOCK)] = hasp_get_idle_lock_enabled();

if(hasp_get_idle_lock_hold_time() != settings[FPSTR(FP_GUI_IDLELOCKHOLD)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_GUI_IDLELOCKHOLD)] = hasp_get_idle_lock_hold_time();

if(hasp_get_idle_lock_screen_time() != settings[FPSTR(FP_GUI_IDLELOCKSCREEN)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_GUI_IDLELOCKSCREEN)] = hasp_get_idle_lock_screen_time();

if(gui_settings.backlight_pin != settings[FPSTR(FP_GUI_BACKLIGHTPIN)].as<int8_t>()) changed = true;
settings[FPSTR(FP_GUI_BACKLIGHTPIN)] = gui_settings.backlight_pin;

Expand Down Expand Up @@ -567,6 +576,9 @@ bool guiSetConfig(const JsonObject& settings)
uint8_t backlight_invert = haspDevice.get_backlight_invert();
uint16_t guiSleepTime1;
uint16_t guiSleepTime2;
bool guiIdleLock = hasp_get_idle_lock_enabled();
uint16_t guiIdleLockHold = hasp_get_idle_lock_hold_time();
uint16_t guiIdleLockScreen = hasp_get_idle_lock_screen_time();

hasp_get_sleep_time(guiSleepTime1, guiSleepTime2);

Expand All @@ -575,10 +587,16 @@ bool guiSetConfig(const JsonObject& settings)
changed |= configSet(backlight_invert, settings[FPSTR(FP_GUI_BACKLIGHTINVERT)], F("guiBacklightInvert"));
changed |= configSet(guiSleepTime1, settings[FPSTR(FP_GUI_IDLEPERIOD1)], F("guiSleepTime1"));
changed |= configSet(guiSleepTime2, settings[FPSTR(FP_GUI_IDLEPERIOD2)], F("guiSleepTime2"));
changed |= configSet(guiIdleLock, settings[FPSTR(FP_GUI_IDLELOCK)], F("guiIdleLock"));
changed |= configSet(guiIdleLockHold, settings[FPSTR(FP_GUI_IDLELOCKHOLD)], F("guiIdleLockHold"));
changed |= configSet(guiIdleLockScreen, settings[FPSTR(FP_GUI_IDLELOCKSCREEN)], F("guiIdleLockScreen"));
changed |= configSet(gui_settings.rotation, settings[FPSTR(FP_GUI_ROTATION)], F("gui_settings.rotation"));
changed |= configSet(gui_settings.invert_display, settings[FPSTR(FP_GUI_INVERT)], F("guiInvertDisplay"));

hasp_set_sleep_time(guiSleepTime1, guiSleepTime2);
hasp_set_idle_lock_enabled(guiIdleLock);
hasp_set_idle_lock_hold_time(guiIdleLockHold);
hasp_set_idle_lock_screen_time(guiIdleLockScreen);
haspDevice.set_backlight_invert(backlight_invert); // Update if changed

if(!settings[FPSTR(FP_GUI_POINTER)].isNull()) {
Expand Down
Loading