Files
aqhomecontrol/avr/modules/lcd2/gui/generic/guiapp.asm
2026-02-16 01:09:39 +01:00

594 lines
14 KiB
NASM

; ***************************************************************************
; 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_GUIAPP_ASM
#define AQH_AVR_GUI2_GUIAPP_ASM
; ***************************************************************************
; defines
; GuiApp in flash
.equ GUIAPP_OFFS_GUIAPP = OBJECT_SIZE
.equ GUIAPP_OFFS_SDRAM_LO = GUIAPP_OFFS_GUIAPP+0
.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_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
.equ GUIAPP_SIGNAL_SHOW = OBJECT_SIGNAL_NEXTFREE+1 ; cntrl->app
.equ GUIAPP_SIGNAL_HIDE = OBJECT_SIGNAL_NEXTFREE+2 ; cntrl->app
.equ GUIAPP_SIGNAL_DEBUG = OBJECT_SIGNAL_NEXTFREE+3
.equ GUIAPP_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+4
; SDRAM data for guiapp
.equ GUIAPP_SD_OFFS_FLAGS = 0
.equ GUIAPP_SD_OFFS_DRAWTIMER = 1
.equ GUIAPP_SD_OFFS_CURRENTWIDGET_LO = 2
.equ GUIAPP_SD_OFFS_CURRENTWIDGET_HI = 3
.equ GUIAPP_SD_OFFS_TOUCHWIDGET_LO = 4
.equ GUIAPP_SD_OFFS_TOUCHWIDGET_HI = 5
.equ GUIAPP_SD_SIZE = 6
.equ GUIAPP_DRAWTIMER = 2
; ***************************************************************************
; data
.dseg
guiapp_touch_event:
.byte WIDGET_DATA_TOUCH_SIZE
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine GuiApp_Init
;
; @param Z byte address of guiapp object (for LPM!)
GuiApp_Init:
ldi r16, OBJECT_SIGNAL_CREATE
clr r17
bigcall OBJ_HandleSignal
rcall GuiApp_ShowFirstView
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_Every100ms @global
;
; @param Z byte address of guiapp object (for LPM!)
GuiApp_Every100ms:
ldi r16, OBJECT_SIGNAL_TIMER
clr r17
bigcall OBJ_HandleSignal
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_MsgReceived @global
;
; @param Z byte address of guiapp object (for LPM!)
GuiApp_MsgReceived:
ldi r16, OBJECT_SIGNAL_RECVMSG
clr r17
bigcall OBJ_HandleSignal
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_OnTimer
;
; @param Z byte address of guiapp object (for LPM!)
GuiApp_OnTimer:
; check for touch event
rcall guiAppCheckTouch
; send timer signal to all accepting widgets
push zl
push zh
adiw zh:zl, GUIAPP_OFFS_ROOTWIDGET_LO
lpm r16, Z+
lpm zh, Z
mov zl, r16
or r17, zh
breq GuiApp_OnTimer_l1
bigcall Widget_Tree_SendTimerSignal
GuiApp_OnTimer_l1:
pop zh
pop zl
; possibly draw widgets
rcall GuiApp_GetSdramPtr
ldd r16, Y+GUIAPP_SD_OFFS_DRAWTIMER
tst r16
breq GuiApp_OnTimer_ret
dec r16
brne GuiApp_OnTimer_writeDrawTimer
push yl
push yh
rcall guiAppDrawWidgets
pop yh
pop yl
ldi r16, GUIAPP_DRAWTIMER
GuiApp_OnTimer_writeDrawTimer:
std Y+GUIAPP_SD_OFFS_DRAWTIMER, r16
GuiApp_OnTimer_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_OnTouch
;
; @param Z byte address of guiapp object (for LPM!)
; @param X pointer to touch event in SDRAM
GuiApp_OnTouch:
push zl
push zh
rcall GuiApp_GetSdramPtr
ldd r18, Y+GUIAPP_SD_OFFS_TOUCHWIDGET_LO
ldd r19, Y+GUIAPP_SD_OFFS_TOUCHWIDGET_HI
mov r16, r18
or r16, r19
breq GuiApp_OnTouch_sendToAll
mov zl, r18
mov zh, r19
ldi r16, WIDGET_SIGNAL_TOUCH
clr r17
bigcall OBJ_HandleSignal
rjmp GuiApp_OnTouch_done
GuiApp_OnTouch_sendToAll:
rcall GuiApp_GetRootWidgetToZ
brcc GuiApp_OnTouch_done
; 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
;
; @param Z byte address of guiapp object (for LPM!)
; @param X pointer to message received in SDRAM
GuiApp_OnMsgReceived:
push zl
push zh
rcall GuiApp_GetRootWidgetToZ
brcc GuiApp_OnMsgReceived_done
bigcall Widget_Tree_SendMsgRecvSignal
GuiApp_OnMsgReceived_done:
pop zh
pop zl
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_OnCreate @global
;
; @param Z byte address of object (for LPM!)
; @return CFLAG set if signal handled
; @clobbers any, !Z
GuiApp_OnCreate:
; init sdram data
rcall GuiApp_GetSdramPtr
ldi r17, GUIAPP_SD_SIZE
clr r16
push yl
push yh
GuiApp_OnCreate_loop:
st Y+, r16
dec r17
brne GuiApp_OnCreate_loop
pop yh
pop yl
clr r16
std Y+GUIAPP_SD_OFFS_FLAGS, r16
ldi r16, GUIAPP_DRAWTIMER
std Y+GUIAPP_SD_OFFS_DRAWTIMER, r16
rcall guiAppInitWidgets
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_GetSdramPtr @global
;
; @param Z byte address of object (for LPM!)
; @return Y pointer to SDRAM data for widget
; @clobbers none
GuiApp_GetSdramPtr:
adiw zh:zl, GUIAPP_OFFS_SDRAM_LO
lpm yl, Z+
lpm yh, Z
sbiw zh:zl, GUIAPP_OFFS_SDRAM_LO+1
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_GetRootWidgetToZ @global
;
; @param Z byte address of object (for LPM!)
; @return CFLAG set if there is a root widget, cleared otherwise
; @return Z byte address pointer to root widget (for LPM!), if CFLAG set, garbage otherwise
; @clobbers none
GuiApp_GetRootWidgetToZ:
rcall OBJ_IsObject
brcc GuiApp_GetRootWidgetToZ_ret
adiw zh:zl, GUIAPP_OFFS_ROOTWIDGET_LO
lpm r16, Z+
lpm zh, Z
mov zl, r16
rcall OBJ_IsObject
GuiApp_GetRootWidgetToZ_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_ShowFirstView @global
;
; @param Z byte address of guiapp object (for LPM!)
GuiApp_ShowFirstView:
push zl
push zh
rcall GuiApp_GetRootWidgetToZ
brcc GuiApp_ShowFirstView_error
bigcall OBJ_GetFirstChild
brcc GuiApp_ShowFirstView_error
mov xl, r18
mov xh, r19
pop zh
pop zl
rcall GuiApp_ShowView
rjmp GuiApp_ShowFirstView_ret
GuiApp_ShowFirstView_error:
pop zh
pop zl
GuiApp_ShowFirstView_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_ShowView @global
;
; @param Z byte address of object (for LPM!)
; @param X byte address of object to show (for LPM!)
; @return CFLAG set if signal handled
; @clobbers any, !Z
GuiApp_ShowView:
rcall GuiApp_GetSdramPtr ; Y=SDRAM
ldd r18, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_LO
ldd r19, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_HI
eor r18, xl ; 0 if same
eor r19, xh ; 0 if same
or r18, r19 ; 0 if r19:r18==X
breq GuiApp_ShowView_ret ; same, no change
push yl
push yh
rcall guiAppHideCurrent ; (any, !X, !Z)
pop yh
pop yl
; store new view
std Y+GUIAPP_SD_OFFS_CURRENTWIDGET_LO, xl
std Y+GUIAPP_SD_OFFS_CURRENTWIDGET_HI, xh
; show new (if any)
rcall guiAppShowCurrent
GuiApp_ShowView_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @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
;
; @param Z byte address of gui app object (for LPM!)
; @param X byte address of widget grabbing touch events
; @return CFLAG set if grabbed, cleared otherwise
; @clobbers R16, R17, Y
GuiApp_GrabTouchEvents:
rcall OBJ_IsObject ; (none)
brcc GuiApp_GrabTouchEvents_ret
rcall GuiApp_GetSdramPtr ; (none)
ldd r16, Y+GUIAPP_SD_OFFS_TOUCHWIDGET_LO
ldd r17, Y+GUIAPP_SD_OFFS_TOUCHWIDGET_HI
or r16, r17
clc
brne GuiApp_GrabTouchEvents_ret ; only grab if not already grabbed!
std Y+GUIAPP_SD_OFFS_TOUCHWIDGET_LO, xl
std Y+GUIAPP_SD_OFFS_TOUCHWIDGET_HI, xh
sec
GuiApp_GrabTouchEvents_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine GuiApp_UngrabTouchEvents
;
; @param Z byte address of gui app object (for LPM!)
; @param X byte address of widget ungrabbing touch events
; @return CFLAG set if ungrabbed, cleared otherwise
; @clobbers R16, R17
GuiApp_UngrabTouchEvents:
rcall OBJ_IsObject ; (none)
brcc GuiApp_UngrabTouchEvents_ret
rcall GuiApp_GetSdramPtr ; (none)
ldd r16, Y+GUIAPP_SD_OFFS_TOUCHWIDGET_LO
ldd r17, Y+GUIAPP_SD_OFFS_TOUCHWIDGET_HI
eor r16, xl
eor r17, xh
or r16, r17
clc
brne GuiApp_UngrabTouchEvents_ret ; only ungrab same widget!
clr r16
std Y+GUIAPP_SD_OFFS_TOUCHWIDGET_LO, r16
std Y+GUIAPP_SD_OFFS_TOUCHWIDGET_HI, r16
sec
GuiApp_UngrabTouchEvents_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine guiAppHideCurrent
;
; @param Z byte address of gui app object (for LPM!)
; @clobbers any, !X, !Z
guiAppHideCurrent:
push zl
push zh
rcall GuiApp_GetSdramPtr ; Y=SDRAM
ldd zl, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_LO
ldd zh, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_HI
mov r16, zl
or r16, zh
breq guiAppHideCurrent_done
ldi r16, WIDGET_SIGNAL_HIDE
clr r17
bigcall OBJ_HandleSignal ; (any, !X, !Y. !Z)
ldi r16, (1<<WIDGET_FLAGS_ACTIVE_BIT)
bigcall Widget_SubFlagsDown ; (R17, R18, R19, R22, R23)
guiAppHideCurrent_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine guiAppShowCurrent
;
; @param Z byte address of gui app object (for LPM!)
; @clobbers any, !X, !Z
guiAppShowCurrent:
push zl
push zh
rcall GuiApp_GetSdramPtr ; Y=SDRAM
ldd zl, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_LO
ldd zh, Y+GUIAPP_SD_OFFS_CURRENTWIDGET_HI
mov r16, zl
or r16, zh
breq guiAppShowCurrent_done
ldi r16, (1<<WIDGET_FLAGS_ACTIVE_BIT) | (1<<WIDGET_FLAGS_DIRTY_BIT)
bigcall Widget_AddFlagsDown
ldi r16, WIDGET_SIGNAL_SHOW
clr r17
bigcall OBJ_HandleSignal ; (any, !X, !Y. !Z)
guiAppShowCurrent_done:
pop zh
pop zl
rcall guiAppDrawWidgets ; (any, !Z)
ret
; @end
; ---------------------------------------------------------------------------
; @routine guiAppInitWidgets
;
; @param Z byte address of guiapp object (for LPM!)
guiAppInitWidgets:
; init widgets
push zl
push zh
rcall GuiApp_GetRootWidgetToZ
brcc guiAppInitWidgets_done
ldi r16, OBJECT_SIGNAL_CREATE
clr r17
bigcall OBJ_TreeAllHandleSignal
ldi r16, (1<<WIDGET_FLAGS_ACTIVE_BIT) | (1<<WIDGET_FLAGS_DIRTY_BIT) ; root window is always active
rcall Widget_AddFlags
guiAppInitWidgets_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine guiAppDrawWidgets
;
; @param Z byte address of guiapp object (for LPM!)
guiAppDrawWidgets:
push zl
push zh
rcall GuiApp_GetRootWidgetToZ
brcc guiAppDrawWidgets_done
bigcall Widget_Tree_SendDrawSignal
guiAppDrawWidgets_done:
pop zh
pop zl
guiAppDrawWidgets_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine guiAppCheckTouch
;
; @param Z byte address of guiapp object (for LPM!)
guiAppCheckTouch:
bigcall Display_InputGetState ; r16=flags, r5:r4=x, r7:r6=y
mov r17, r16
andi r17, (1<<DISPLAY_IFLAGS_CHGCOORD_BIT) | (1<<DISPLAY_IFLAGS_CHGPRESS_BIT)
breq guiAppCheckTouch_ret
ldi xl, LOW(guiapp_touch_event)
ldi xh, HIGH(guiapp_touch_event)
st X+, r4 ; X
st X+, r5
st X+, r6 ; Y
st X+, r7
st X, r16 ; flags
sbiw xh:xl, 4 ; (4 times incremented)
; send touch signal
ldi r16, WIDGET_SIGNAL_TOUCH
clr r17
bigcall OBJ_HandleSignal
guiAppCheckTouch_ret:
ret
; @end
guiAbortIfNotObject:
bigcall OBJ_IsObject
brcs guiAbortIfNotObject_ret
rcall DEBUG2
guiAbortIfNotObject_ret:
ret
; @end
#endif