avr/gui2: added screen saver app

screen saver can be turned off by:
- touching and releasing the display
- specific messages (e.g. motion detection msg from other nodes)
This commit is contained in:
Martin Preuss
2026-02-07 16:09:31 +01:00
parent 39d1060334
commit 28deb9c591
10 changed files with 738 additions and 25 deletions

View File

@@ -20,7 +20,9 @@
.equ GUIAPP_OFFS_SDRAM_HI = GUIAPP_OFFS_GUIAPP+1
.equ GUIAPP_OFFS_ROOTWIDGET_LO = GUIAPP_OFFS_GUIAPP+2
.equ GUIAPP_OFFS_ROOTWIDGET_HI = GUIAPP_OFFS_GUIAPP+3
.equ GUIAPP_SIZE = GUIAPP_OFFS_GUIAPP+4
.equ GUIAPP_OFFS_SCREENSAVER_LO = GUIAPP_OFFS_GUIAPP+4
.equ GUIAPP_OFFS_SCREENSAVER_HI = GUIAPP_OFFS_GUIAPP+5
.equ GUIAPP_SIZE = GUIAPP_OFFS_GUIAPP+6
; signals
.equ GUIAPP_SIGNAL_RAISE = OBJECT_SIGNAL_NEXTFREE+0 ; app->cntrl: X=WIDGET to raise
@@ -172,17 +174,51 @@ GuiApp_OnTouch:
GuiApp_OnTouch_sendToAll:
rcall GuiApp_GetRootWidgetToZ
brcc GuiApp_OnTouch_done
; send touch signal (TODO: check for grabbed touch)
; send touch signal
bigcall Widget_Tree_SendTouchSignal
GuiApp_OnTouch_done:
pop zh
pop zl
; send keepAlive to screensaver (if not active!)
rcall guiAppSendKeepAliveIfScreenSaverInactive
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine guiAppSendKeepAliveIfScreenSaverInactive
;
; @param Z byte address of guiapp object (for LPM!)
; @clobbers any
guiAppSendKeepAliveIfScreenSaverInactive:
push zl
push zh
rcall GuiApp_GetSdramPtr
adiw zh:zl, GUIAPP_OFFS_SCREENSAVER_LO
lpm r20, Z+
lpm r21, Z
sbiw zh:zl, GUIAPP_OFFS_SCREENSAVER_LO+1
ldd r16, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_LO
cp r16, r20
brne guiAppSendKeepAliveIfScreenSaverInactive_send
ldd r16, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_HI
cp r16, r21
breq guiAppSendKeepAliveIfScreenSaverInactive_end
guiAppSendKeepAliveIfScreenSaverInactive_send:
mov zl, r20
mov zh, r21
bigcall ScreenSaver_KeepAlive
guiAppSendKeepAliveIfScreenSaverInactive_end:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_OnMsgReceived @global
;
@@ -336,6 +372,22 @@ GuiApp_ShowView_ret:
; ---------------------------------------------------------------------------
; @routine GuiApp_GetCurrentView @global
;
; @param Z byte address of object (for LPM!)
; @return X byte address of current view object (for LPM!)
; @clobbers Y
GuiApp_GetCurrentView:
rcall GuiApp_GetSdramPtr ; Y=SDRAM
ldd xl, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_LO
ldd xh, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_HI
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_GrabTouchEvents

View File

@@ -0,0 +1,462 @@
; ***************************************************************************
; copyright : (C) 2026 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef AQH_AVR_GUI2_SCREENSAVER_ASM
#define AQH_AVR_GUI2_SCREENSAVER_ASM
; ***************************************************************************
; defines
;.equ SCREENSAVER_TIMER100ms = 6000 ; 10mins
.equ SCREENSAVER_TIMER100ms = 300 ; 30 secs
; SDRAM data
.equ SCREENSAVER_SD_OFFS_BEGIN = WIDGET_SD_SIZE
.equ SCREENSAVER_SD_OFFS_TIMER_LO = SCREENSAVER_SD_OFFS_BEGIN+0
.equ SCREENSAVER_SD_OFFS_TIMER_HI = SCREENSAVER_SD_OFFS_BEGIN+1
.equ SCREENSAVER_SD_OFFS_PREV_VIEW_LO = SCREENSAVER_SD_OFFS_BEGIN+2
.equ SCREENSAVER_SD_OFFS_PREV_VIEW_HI = SCREENSAVER_SD_OFFS_BEGIN+3
.equ SCREENSAVER_SD_OFFS_NODEADDR1 = SCREENSAVER_SD_OFFS_BEGIN+4
.equ SCREENSAVER_SD_OFFS_VALUEID1 = SCREENSAVER_SD_OFFS_BEGIN+5
.equ SCREENSAVER_SD_OFFS_NODEADDR2 = SCREENSAVER_SD_OFFS_BEGIN+6
.equ SCREENSAVER_SD_OFFS_VALUEID2 = SCREENSAVER_SD_OFFS_BEGIN+7
.equ SCREENSAVER_SD_SIZE = SCREENSAVER_SD_OFFS_BEGIN+8
; EEPROM data
.equ SCREENSAVER_EE_OFFS_NODEADDR1 = 0
.equ SCREENSAVER_EE_OFFS_VALUEID1 = 1
.equ SCREENSAVER_EE_OFFS_NODEADDR2 = 2
.equ SCREENSAVER_EE_OFFS_VALUEID2 = 3
.equ SCREENSAVER_EE_SIZE = 4
; signals
.equ SCREENSAVER_SIGNAL_SETSOURCE1 = WIDGET_SIGNAL_NEXTFREE+0
.equ SCREENSAVER_SIGNAL_SETSOURCE2 = WIDGET_SIGNAL_NEXTFREE+1
.equ SCREENSAVER_SIGNAL_NEXTFREE = WIDGET_SIGNAL_NEXTFREE+2
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine ScreenSaver_KeepAlive @global
;
; @param Z byte address of widget object (for LPM!)
; @clobbers any, !Y, !Z
ScreenSaver_KeepAlive:
push yl
push yh
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget (none)
ldd r24, Y+SCREENSAVER_SD_OFFS_TIMER_LO
ldd r25, Y+SCREENSAVER_SD_OFFS_TIMER_HI
mov r16, r24
or r16, r25
brne ScreenSaver_KeepAlive_restartCounter
; counter is 0, screen saver active, leave
rcall ScreenSaver_Leave ; (any, !Z)
ScreenSaver_KeepAlive_restartCounter:
ldi r16, LOW(SCREENSAVER_TIMER100ms)
std Y+SCREENSAVER_SD_OFFS_TIMER_LO, r16
ldi r16, HIGH(SCREENSAVER_TIMER100ms)
std Y+SCREENSAVER_SD_OFFS_TIMER_HI, r16
ScreenSaver_KeepAlive_ret:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine ScreenSaver_Enter @global
;
; @param Z byte address of widget object (for LPM!)
; @clobbers any, !Z
ScreenSaver_Enter:
bigcall Widget_GetApp ; r19;r18=app
push zl
push zh
mov zl, r18
mov zh, r19
bigcall GuiApp_GetCurrentView ; X=current view (Y)
pop zh
pop zl
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget (none)
std Y+SCREENSAVER_SD_OFFS_PREV_VIEW_LO, xl
std Y+SCREENSAVER_SD_OFFS_PREV_VIEW_HI, xh
push zl
push zh
mov xl, zl
mov xh, zh
mov zl, r18
mov zh, r19
bigcall GuiApp_ShowView ; select view: screensaver
pop zh
pop zl
clr r16
bigcall Display_SetBacklight
ret
; @end
; ---------------------------------------------------------------------------
; @routine ScreenSaver_Leave @global
;
; @param Z byte address of widget object (for LPM!)
; @clobbers any, !Z
ScreenSaver_Leave:
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget (none)
ldd xl, Y+SCREENSAVER_SD_OFFS_PREV_VIEW_LO
ldd xh, Y+SCREENSAVER_SD_OFFS_PREV_VIEW_HI
; restart screen saver timer
ldi r16, LOW(SCREENSAVER_TIMER100ms)
std Y+SCREENSAVER_SD_OFFS_TIMER_LO, r16
ldi r16, HIGH(SCREENSAVER_TIMER100ms)
std Y+SCREENSAVER_SD_OFFS_TIMER_HI, r16
; show previous view
bigcall Widget_GetApp ; r19;r18=app
push zl
push zh
mov zl, r18
mov zh, r19
bigcall GuiApp_ShowView
pop zh
pop zl
ldi r16, 0xff
bigcall Display_SetBacklight
ret
; @end
; ---------------------------------------------------------------------------
; @routine ScreenSaver_OnTimer @global
;
; @param Z byte address of widget object (for LPM!)
; @clobbers any, !Z
ScreenSaver_OnTimer:
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget (none)
ldd r24, Y+SCREENSAVER_SD_OFFS_TIMER_LO
ldd r25, Y+SCREENSAVER_SD_OFFS_TIMER_HI
mov r16, r24
or r16, r25
breq ScreenSaver_OnTimer_ret
sbiw r25:r24, 1
std Y+SCREENSAVER_SD_OFFS_TIMER_LO, r24
std Y+SCREENSAVER_SD_OFFS_TIMER_HI, r25
brne ScreenSaver_OnTimer_ret
rcall ScreenSaver_Enter ; (any, !Z)
ScreenSaver_OnTimer_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine ScreenSaver_OnCreate @global
;
; @param Z byte address of widget object (for LPM!)
; @return CFLAG set if signal handled
; @clobbers any, !Z
ScreenSaver_OnCreate:
bigcall OBJ_IsObject ; (none)
brcc ScreenSaver_OnCreate_ret
; preset SDRAM
bigcall Widget_GetSdramPtr ; (none)
clr r16
ldi r17, SCREENSAVER_SD_SIZE
push yl
push yh
ScreenSaver_OnCreate_loop:
st Y+, r16
dec r17
brne ScreenSaver_OnCreate_loop
pop yh
pop yl
push yl
push yh
bigcall Widget_OnCreate
pop yh
pop yl
ldi r16, LOW(SCREENSAVER_TIMER100ms)
std Y+SCREENSAVER_SD_OFFS_TIMER_LO, r16
ldi r16, HIGH(SCREENSAVER_TIMER100ms)
std Y+SCREENSAVER_SD_OFFS_TIMER_HI, r16
ldi r16, 0xff
bigcall Display_SetBacklight
rcall screenSaverReadFromEeprom
ScreenSaver_OnCreate_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine ScreenSaver_OnTouch @global
;
; @param Z byte address of widget object (for LPM!)
; @param X pointer to TOUCH event (see @ref WIDGET_DATA_TOUCH_OFFS_X_LO)
; @return CFLAG set if signal handled
; @clobbers any, !Z
ScreenSaver_OnTouch:
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget
; read touch signal data from X
adiw xh:xl, WIDGET_DATA_TOUCH_OFFS_STATE
ld r22, X ; WIDGET_DATA_TOUCH_OFFS_STATE
sbiw xh:xl, WIDGET_DATA_TOUCH_OFFS_STATE
sbrs r22, DISPLAY_IFLAGS_PRESSED_BIT
rjmp ScreenSaver_OnTouch_up
; down (active touch), switch display on
ldi r16, 0xff
bigcall Display_SetBacklight
rjmp ScreenSaver_OnTouch_ret
ScreenSaver_OnTouch_up:
rcall ScreenSaver_Leave
ScreenSaver_OnTouch_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine ScreenSaver_OnMsgReceived @global
;
; @param Z byte address of widget object (for LPM!)
; @param XL node addr
; @param XH value id
; @return CFLAG set if signal handled
; @clobbers any, !Z
ScreenSaver_OnMsgReceived:
push zl
push zh
mov yl, zl
mov yh, zh
ldi zl, LOW(ScreenSaver_MsgTable*2)
ldi zh, HIGH(ScreenSaver_MsgTable*2)
bigcall Main_HandleValueMsg ; (any)
pop zh
pop zl
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine screenSaverHandleSetSource1
;
; @param Y byte address of widget object (for LPM!)
; @param R17 value id
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 source address
; @param R23 command
; @param R25:R24 message id
; @return CFLAG set if ACK/NACK requested
; @return R23 command value for ACK/NACK message
; @clobbers R16, R17, R18, R20, R21, X, Y, Z
screenSaverHandleSetSource1:
mov zl, yl
mov zh, yh
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget
std Y+SCREENSAVER_SD_OFFS_NODEADDR1, r18
std Y+SCREENSAVER_SD_OFFS_VALUEID1, r19
rcall screenSaverWriteToEeprom ; (R16, R17, R18, R20, R21, X, Y)
ldi r23, NETMSG_CMD_VALUE_SET_ACK
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine screenSaverHandleSetSource2
;
; @param Y byte address of widget object (for LPM!)
; @param R17 value id
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 source address
; @param R23 command
; @param R25:R24 message id
; @return CFLAG set if ACK/NACK requested
; @return R23 command value for ACK/NACK message
; @clobbers R16, R17, R18, R20, R21, X, Y, Z
screenSaverHandleSetSource2:
mov zl, yl
mov zh, yh
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget
std Y+SCREENSAVER_SD_OFFS_NODEADDR1, r18
std Y+SCREENSAVER_SD_OFFS_VALUEID1, r19
rcall screenSaverWriteToEeprom ; (R16, R17, R18, R20, R21, X, Y)
ldi r23, NETMSG_CMD_VALUE_SET_ACK
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine screenSaverHandleReport
;
; @param Y byte address of widget object (for LPM!)
; @param R17 value id
; @param R19:R18 value
; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100)
; @param R22 source address
; @param R23 command
; @param R25:R24 message id
; @return CFLAG cleared (no ACK/NACK requested)
; @clobbers any
screenSaverHandleReport:
mov zl, yl
mov zh, yh
bigcall Widget_GetSdramPtr ; Y:=SDRAM data for widget
mov r16, r18 ; check for non-zero value
or r16, r19
breq screenSaverHandleReport_end
ldd r16, Y+SCREENSAVER_SD_OFFS_NODEADDR1
cp r16, r22
brne screenSaverHandleReport_l1
ldd r16, Y+SCREENSAVER_SD_OFFS_VALUEID1
cp r16, r17
breq screenSaverHandleReport_matches
screenSaverHandleReport_l1:
ldd r16, Y+SCREENSAVER_SD_OFFS_NODEADDR2
cp r16, r22
brne screenSaverHandleReport_end
ldd r16, Y+SCREENSAVER_SD_OFFS_VALUEID2
cp r16, r17
brne screenSaverHandleReport_end
screenSaverHandleReport_matches:
rcall ScreenSaver_KeepAlive
screenSaverHandleReport_end:
clc ; no ACK needed
ret
; @end
; ---------------------------------------------------------------------------
; @routine screenSaverWriteToEeprom
;
; @param Z byte address of widget object (for LPM!)
; @return CFLAG set if data found and read, cleared on error
; @clobbers R16, R17, R18, R20, R21, X, Y
screenSaverWriteToEeprom:
ldi r16, EEID_SCREENSAVER
bigcall EepromTlv_FindFirst ; (R18)
brcs screenSaverWriteToEeprom_write
ldi r16, EEID_SCREENSAVER
ldi r17, SCREENSAVER_EE_SIZE
bigcall EepromTlv_AddTlv ; X=pointer to EEPROM data (R16, R18, R20, R21)
brcc screenSaverWriteToEeprom_ret
screenSaverWriteToEeprom_write:
bigcall Widget_GetSdramPtr ; (none)
adiw yh:yl, SCREENSAVER_SD_OFFS_NODEADDR1
ldi r18, SCREENSAVER_EE_SIZE
screenSaverWriteToEeprom_loop:
ld r16, Y+
bigcall Eeprom_WriteByteIfChanged ; (R17)
brcc screenSaverWriteToEeprom_ret
adiw xh:xl, 1
dec r18
brne screenSaverWriteToEeprom_loop
sec
screenSaverWriteToEeprom_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine screenSaverReadFromEeprom
;
; @param Z byte address of widget object (for LPM!)
; @return CFLAG set if data found and read, cleared on error
; @clobbers R16, R18, X, Y
screenSaverReadFromEeprom:
ldi r16, EEID_SCREENSAVER
bigcall EepromTlv_FindFirst ; (R18)
brcc screenSaverReadFromEeprom_ret
bigcall Widget_GetSdramPtr ; (none)
adiw yh:yl, SCREENSAVER_SD_OFFS_NODEADDR1
ldi r18, SCREENSAVER_EE_SIZE
screenSaverReadFromEeprom_loop:
bigcall Eeprom_ReadByte ; R16=byte (none)
brcc screenSaverReadFromEeprom_ret
st Y+, r16
adiw xh:xl, 1
dec r18
brne screenSaverReadFromEeprom_loop
sec
screenSaverReadFromEeprom_ret:
ret
; @end
ScreenSaver_MsgTable:
.dw NETMSG_CMD_VALUE_SET | (VALUE_ID_SCREENSAVER_SETSOURCE1<<8), screenSaverHandleSetSource1
.dw NETMSG_CMD_VALUE_SET | (VALUE_ID_SCREENSAVER_SETSOURCE2<<8), screenSaverHandleSetSource2
.dw NETMSG_CMD_VALUE_REPORT, screenSaverHandleReport
.dw 0, 0
ScreenSaver_DefaultSignalmap:
.db 0, OBJECT_SIGNAL_TIMER, LOW(ScreenSaver_OnTimer), HIGH(ScreenSaver_OnTimer)
.db 0, WIDGET_SIGNAL_TOUCH, LOW(ScreenSaver_OnTouch), HIGH(ScreenSaver_OnTouch)
.db 0, OBJECT_SIGNAL_RECVMSG, LOW(ScreenSaver_OnMsgReceived), HIGH(ScreenSaver_OnMsgReceived)
.db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDraw), HIGH(Widget_OnDraw)
.db 0, OBJECT_SIGNAL_CREATE, LOW(ScreenSaver_OnCreate), HIGH(ScreenSaver_OnCreate)
.db 0, 0, 0, 0 ; end of table
#endif

View File

@@ -47,7 +47,7 @@ ILI9341_Init:
rcall ILI9341_LeaveSleepMode
ldi r16, 0x20
rcall ILI9341_SetBacklight
rcall Display_SetBacklight
sec
ret
@@ -133,17 +133,17 @@ ILI9341_Reset:
; ---------------------------------------------------------------------------
; @routine ILI9341_SetBacklight @global
; @routine Display_SetBacklight @global
;
; @param r16 0=off, on otherwise
; @clobbers r16, r17
ILI9341_SetBacklight:
Display_SetBacklight:
tst r16
brne ILI9341_SetBacklight_on
brne Display_SetBacklight_on
cbi ILI9341_LED_OUTPUT, ILI9341_LED_PIN
ret
ILI9341_SetBacklight_on:
Display_SetBacklight_on:
sbi ILI9341_LED_OUTPUT, ILI9341_LED_PIN
ret ; DEBUG