From a8cb442502c953c87a518e5ca708aecdcc895427 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Fri, 6 Mar 2026 16:00:14 +0100 Subject: [PATCH] gui2: improved signal handling, make use of secondary signal maps. --- avr/devices/c03/test/main.asm | 1 + avr/modules/lcd2/gui2/base/guiapp.asm | 345 +++++++++++++++++++++- avr/modules/lcd2/gui2/base/mainwindow.asm | 4 +- avr/modules/lcd2/gui2/base/object.asm | 252 +++++++++++++--- avr/modules/lcd2/gui2/base/rootwindow.asm | 6 +- avr/modules/lcd2/gui2/base/widget.asm | 96 +++++- 6 files changed, 636 insertions(+), 68 deletions(-) diff --git a/avr/devices/c03/test/main.asm b/avr/devices/c03/test/main.asm index 68e3e73..ec11125 100644 --- a/avr/devices/c03/test/main.asm +++ b/avr/devices/c03/test/main.asm @@ -286,6 +286,7 @@ test: .include "modules/lcd2/gui2/base/object.asm" .include "modules/lcd2/gui2/base/widget.asm" +.include "modules/lcd2/gui2/base/guiapp.asm" diff --git a/avr/modules/lcd2/gui2/base/guiapp.asm b/avr/modules/lcd2/gui2/base/guiapp.asm index 5034125..97723c9 100644 --- a/avr/modules/lcd2/gui2/base/guiapp.asm +++ b/avr/modules/lcd2/gui2/base/guiapp.asm @@ -21,15 +21,16 @@ .equ GUIAPP_OFFS_ROOTWINDOW_HI = GUIAPP_OFFS_BEGIN+1 .equ GUIAPP_OFFS_SCREENSAVER_LO = GUIAPP_OFFS_BEGIN+2 .equ GUIAPP_OFFS_SCREENSAVER_HI = GUIAPP_OFFS_BEGIN+3 -.equ GUIAPP_OFFS_CURRENTWIDGET_LO = GUIAPP_OFFS_BEGIN+4 -.equ GUIAPP_OFFS_CURRENTWIDGET_HI = GUIAPP_OFFS_BEGIN+5 -.equ GUIAPP_OFFS_ROOTWINDOW_HI = GUIAPP_OFFS_BEGIN+6 -.equ GUIAPP_OFFS_TOUCHWIDGET_LO = GUIAPP_OFFS_BEGIN+7 -.equ GUIAPP_OFFS_TOUCHWIDGET_HI = GUIAPP_OFFS_BEGIN+8 -.equ GUIAPP_OFFS_DRAWTIMER = GUIAPP_OFFS_BEGIN+9 -.equ GUIAPP_SIZE = WIDGET_OFFS_BEGIN+10 +.equ GUIAPP_OFFS_CURRENTWINDOW_LO = GUIAPP_OFFS_BEGIN+4 +.equ GUIAPP_OFFS_CURRENTWINDOW_HI = GUIAPP_OFFS_BEGIN+5 +.equ GUIAPP_OFFS_TOUCHWIDGET_LO = GUIAPP_OFFS_BEGIN+6 +.equ GUIAPP_OFFS_TOUCHWIDGET_HI = GUIAPP_OFFS_BEGIN+7 +.equ GUIAPP_OFFS_DRAWTIMER = GUIAPP_OFFS_BEGIN+8 +.equ GUIAPP_SIZE = WIDGET_OFFS_BEGIN+9 +.equ GUIAPP_DRAWTIMER = 2 + ; *************************************************************************** @@ -39,4 +40,334 @@ +; --------------------------------------------------------------------------- +; @routine GuiApp_new @global +; +; @return CFLAG set of okay, cleared otherwise +; @return Y address of newly created object +; @param r16 value for OBJECT_OFFS_OPTS_LO +; @param r17 value for OBJECT_OFFS_OPTS_HI +; @clobbers any + +GuiApp_new: + ldi r24, LOW(GUIAPP_SIZE) + ldi r25, HIGH(GUIAPP_SIZE) + bigcall Object_Alloc ; (!r16, !r17) + brcc GuiApp_new_ret + rcall GuiApp_Init ; (r16, r17, X) + sec +GuiApp_new_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_Init @global +; +; @param Y address of object in SDRAM +; @param r16 value for OBJECT_OFFS_OPTS_LO +; @param r17 value for OBJECT_OFFS_OPTS_HI +; @clobbers r16, r17, X + +GuiApp_Init: + ; call base class + bigcall OBJ_Init ; (r16, r17, X) + + ; clear object-specific data + mov xl, yl + mov xh, yh + adiw xh:xl, GUIAPP_OFFS_BEGIN + clr r16 + ldi r17, (GUIAPP_SIZE-GUIAPP_OFFS_BEGIN) + bigcall Utils_FillSram ; (r17, X) + + ; set default signal map + ldi r16, LOW(GuiApp_DefaultSignalmap*2) + std Y+OBJECT_OFFS_SIGNALMAP_LO, r16 + ldi r16, HIGH(GuiApp_DefaultSignalmap*2) + std Y+OBJECT_OFFS_SIGNALMAP_HI, r16 + + ldi r16, GUIAPP_DRAWTIMER + std Y+GUIAPP_OFFS_DRAWTIMER, r16 + + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_Every100ms @global +; +; @param Y address of object in SDRAM + +GuiApp_Every100ms: + ldi r16, OBJECT_SIGNAL_TIMER + clr r17 + bigcall OBJ_HandleSignal + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_MsgReceived @global +; +; @param Y address of object in SDRAM + +GuiApp_MsgReceived: + ldi r16, OBJECT_SIGNAL_RECVMSG + clr r17 + bigcall OBJ_HandleSignal + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_PreventScreenSaver @global +; +; @param Y address of object in SDRAM +; @clobbers any, !Y + +GuiApp_PreventScreenSaver: + rcall GuiApp_GetScreenSaver + brcc GuiApp_PreventScreenSaver_ret + push yl + push yh + mov yl, r18 + mov yh, r19 + ldi r16, WIDGET_SIGNAL_KEEPALIVE + clr r17 + bigcall OBJ_HandleSignal + pop yh + pop yl +GuiApp_PreventScreenSaver_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_GrabTouchEvents +; +; @param Y address of object in SDRAM +; @param X byte address of widget grabbing touch events +; @return CFLAG set if grabbed, cleared otherwise +; @clobbers R16, R17, Y + +GuiApp_GrabTouchEvents: + ldd r16, Y+GUIAPP_OFFS_TOUCHWIDGET_LO + ldd r17, Y+GUIAPP_OFFS_TOUCHWIDGET_HI + or r16, r17 + clc + brne GuiApp_GrabTouchEvents_ret ; only grab if not already grabbed! + std Y+GUIAPP_OFFS_TOUCHWIDGET_LO, xl + std Y+GUIAPP_OFFS_TOUCHWIDGET_HI, xh + sec +GuiApp_GrabTouchEvents_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_UngrabTouchEvents +; +; @param Y address of object in SDRAM +; @param X byte address of widget ungrabbing touch events +; @return CFLAG set if ungrabbed, cleared otherwise +; @clobbers R16, R17 + +GuiApp_UngrabTouchEvents: + ldd r16, Y+GUIAPP_OFFS_TOUCHWIDGET_LO + ldd r17, Y+GUIAPP_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_OFFS_TOUCHWIDGET_LO, r16 + std Y+GUIAPP_OFFS_TOUCHWIDGET_HI, r16 + sec +GuiApp_UngrabTouchEvents_ret: + ret +; @end + + + + + +; *************************************************************************** +; getters and setters + +; --------------------------------------------------------------------------- +; @routine GuiApp_GetRootWindow @global +; +; @param Y address of object in SDRAM +; @param CFLAG set if response is not a NULL pointer + +GuiApp_GetRootWindow: + ldd r18, Y+GUIAPP_OFFS_ROOTWINDOW_LO + ldd r19, Y+GUIAPP_OFFS_ROOTWINDOW_HI + sec + tst r18 + brne GuiApp_GetRootWindow_ret + tst r19 + brne GuiApp_GetRootWindow_ret + clc +GuiApp_GetRootWindow_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_SetRootWindow @global +; +; @param Y address of object in SDRAM +; @param X address of new window + +GuiApp_SetRootWindow: + std Y+GUIAPP_OFFS_ROOTWINDOW_LO, xl + std Y+GUIAPP_OFFS_ROOTWINDOW_HI, xh + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_GetCurrentWindow @global +; +; @param Y address of object in SDRAM +; @param CFLAG set if response is not a NULL pointer + +GuiApp_GetCurrentWindow: + ldd r18, Y+GUIAPP_OFFS_CURRENTWINDOW_LO + ldd r19, Y+GUIAPP_OFFS_CURRENTWINDOW_HI + sec + tst r18 + brne GuiApp_GetCurrentWindow_ret + tst r19 + brne GuiApp_GetCurrentWindow_ret + clc +GuiApp_GetCurrentWindow_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_SetCurrentWindow @global +; +; @param Y address of object in SDRAM +; @param X address of new window + +GuiApp_SetCurrentWindow: + std Y+GUIAPP_OFFS_CURRENTWINDOW_LO, xl + std Y+GUIAPP_OFFS_CURRENTWINDOW_HI, xh + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_GetScreenSaver @global +; +; @param Y address of object in SDRAM +; @param CFLAG set if response is not a NULL pointer + +GuiApp_GetScreenSaver: + ldd r18, Y+GUIAPP_OFFS_SCREENSAVER_LO + ldd r19, Y+GUIAPP_OFFS_SCREENSAVER_HI + sec + tst r18 + brne GuiApp_GetScreenSaver_ret + tst r19 + brne GuiApp_GetScreenSaver_ret + clc +GuiApp_GetScreenSaver_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_SetScreenSaver @global +; +; @param Y address of object in SDRAM +; @param X address of new window + +GuiApp_SetScreenSaver: + std Y+GUIAPP_OFFS_SCREENSAVER_LO, xl + std Y+GUIAPP_OFFS_SCREENSAVER_HI, xh + ret +; @end + + + + + +; *************************************************************************** +; signal handlers + + +; --------------------------------------------------------------------------- +; @routine GuiApp_OnDestroy @global +; +; @param Y address of object in SDRAM +; @return CFLAG set if signal handled +; @clobbers any, !Y + +GuiApp_OnDestroy: + ; TODO (destroy rootWindow) + + ; Clear CFLAG so that destroy handlers of base classes are called + ; after this routine returns. This way the last routine called will be + ; OBJ_OnDestroy which then frees the whole SDRAM object on heap. + clc + ret +; @end + + +; --------------------------------------------------------------------------- +; @routine GuiApp_OnTimer +; +; @param Y address of object in SDRAM + +GuiApp_OnTimer: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine GuiApp_OnMsgReceived @global +; +; @param Y address of object in SDRAM +; @param X pointer to message received in SDRAM + +GuiApp_OnMsgReceived: + ret +; @end + + + + + + + +; *************************************************************************** +; data in FLASH + +GuiApp_DefaultSignalmap: + ; header + .dw Object_DefaultSignalmap ; next table to use + ; entries + .db 0, OBJECT_SIGNAL_DESTROY, LOW(GuiApp_OnDestroy), HIGH(GuiApp_OnDestroy) + .db 0, 0, 0, 0 ; end of table + + + #endif diff --git a/avr/modules/lcd2/gui2/base/mainwindow.asm b/avr/modules/lcd2/gui2/base/mainwindow.asm index ca78191..ea8dcca 100644 --- a/avr/modules/lcd2/gui2/base/mainwindow.asm +++ b/avr/modules/lcd2/gui2/base/mainwindow.asm @@ -34,12 +34,13 @@ ; @return Y address of newly created object ; @param r16 value for OBJECT_OFFS_OPTS_LO ; @param r17 value for OBJECT_OFFS_OPTS_HI +; @param X parent widget ; @clobbers any MainWindow_new: ldi r24, LOW(MAINWINDOW_SIZE) ldi r25, HIGH(MAINWINDOW_SIZE) - bigcall Object_Alloc ; (!r16, !r17) + bigcall Object_Alloc ; (!r16, !r17, !X) brcc MainWindow_new_ret rcall MainWindow_Init ; (r16, r17, X) sec @@ -53,6 +54,7 @@ MainWindow_new_ret: ; @routine MainWindow_Init @global ; ; @param Y address of widget +; @param X parent widget (if any) ; @clobbers r16, r17, X MainWindow_Init: diff --git a/avr/modules/lcd2/gui2/base/object.asm b/avr/modules/lcd2/gui2/base/object.asm index 2d69c0b..ec5ab07 100644 --- a/avr/modules/lcd2/gui2/base/object.asm +++ b/avr/modules/lcd2/gui2/base/object.asm @@ -11,6 +11,32 @@ #define AQH_AVR_GUI2_OBJECT_ASM +; *************************************************************************** +; @module OBJECT +; +; Central to this module is the signal handler (@ref OBJ_HandleSignal). +; +; Inputs: +; - Y: Pointer to the object to handle a signal +; - R16: Signal number (e.g. @ref OBJECT_SIGNAL_DESTROY) +; - R17: Selector +; Normally this comes from the object var OBJECT_OFFS_SELECTOR but it can +; have different meanings for different signals. +; For signals WIDGET_SIGNAL_SETVALUE and WIDGET_SIGNAL_GETVALUE from the +; @ref WIDGET module this contains the id of the value to reference, e.g. +; to set the X position of a widget R17 has the value WIDGET_VALUE_X. +; - X: Parameter for the signal (either as 16-bit value or as two 8-bit values +; in xl and xh). E.g. for signal WIDGET_SIGNAL_SETVALUE this would contain +; the value to assign +; +; Outputs: +; - CFLAG: Set if signal handled. +; - R19:R18: Response from the signal handler. Most signals do not have return values, but +; especially the signal WIDGET_SIGNAL_GETVALUE is expected to return a result. +; + + + ; *************************************************************************** ; defines @@ -36,10 +62,13 @@ .equ OBJECT_OPTSLO_MSGRECV_BIT = 6 ; SignalMap entries -.equ OBJECT_SIGNALMAP_OFFS_SELECTOR = 0 -.equ OBJECT_SIGNALMAP_OFFS_SIGNAL = 1 ; end if 0 -.equ OBJECT_SIGNALMAP_OFFS_HANDLER_LO = 2 -.equ OBJECT_SIGNALMAP_OFFS_HANDLER_HI = 3 +.equ OBJECT_SIGNALMAP_OFFS_HEADER = 0 +.equ OBJECT_SIGNALMAP_OFFS_ENTRIES = 2 + +.equ OBJECT_SIGNALMAPENTRY_OFFS_SELECTOR = 0 +.equ OBJECT_SIGNALMAPENTRY_OFFS_SIGNAL = 1 ; end if 0 +.equ OBJECT_SIGNALMAPENTRY_OFFS_HANDLER_LO = 2 +.equ OBJECT_SIGNALMAPENTRY_OFFS_HANDLER_HI = 3 ; signals .equ OBJECT_SIGNAL_NONE = 0 @@ -63,19 +92,23 @@ ; @return CFLAG set if object created, cleared otherwise ; @return Y address of created object in SDRAM (if CFLAG set) ; @param r25:r24 size of object to allocate -; @clobbers !r16, !r17 +; @clobbers !r16, !r17, !X Object_Alloc: - push r16 - push r17 - bigcall Heap_Alloc ; X=mem allocated (r16, r17, r18, r19, r24, r25, X) - pop r17 - pop r16 - brcc Object_Alloc_ret - mov yl, xl - mov yh, xh - sec + push xl + push xh + push r16 + push r17 + bigcall Heap_Alloc ; X=mem allocated (r16, r17, r18, r19, r24, r25, X) + pop r17 + pop r16 + brcc Object_Alloc_ret + mov yl, xl + mov yh, xh + sec Object_Alloc_ret: + pop xh + pop xl ret ; @end @@ -333,17 +366,41 @@ OBJ_GetChildAt_ret: ; @end - ; --------------------------------------------------------------------------- ; @routine OBJ_AddChild @global ; +; @param Y object to add +; @param X object to add to +; @clobbers r18, r19 + +OBJ_AddChild: + mov r18, yl ; switch X/Y + mov yl, xl + mov xl, r18 + mov r18, yh + mov yh, xh + mov xh, r18 + rcall objAddObjXAsChildToY + mov r18, yl ; switch X/Y + mov yl, xl + mov xl, r18 + mov r18, yh + mov yh, xh + mov xh, r18 + ret +; @end + + +; --------------------------------------------------------------------------- +; @routine objAddObjXAsChildToY +; ; @param Y object to add to ; @param X object to add ; @clobbers r18, r19 -OBJ_AddChild: +objAddObjXAsChildToY: rcall OBJ_GetLastChild ; r19:r18=last child (r18, r19) - brcc OBJ_AddChild_setAsFirstChild + brcc objAddObjXAsChildToY_setAsFirstChild ; append to last child push yl push yh @@ -353,11 +410,11 @@ OBJ_AddChild: std Y+OBJECT_OFFS_NEXT_HI, xh pop yh pop yl - rjmp OBJ_AddChild_setParent -OBJ_AddChild_setAsFirstChild: + rjmp objAddObjXAsChildToY_setParent +objAddObjXAsChildToY_setAsFirstChild: std Y+OBJECT_OFFS_CHILD_LO, xl std Y+OBJECT_OFFS_CHILD_HI, xh -OBJ_AddChild_setParent: +objAddObjXAsChildToY_setParent: adiw xh:xl, OBJECT_OFFS_PARENT_LO st X+, yl st X, yh @@ -417,22 +474,22 @@ OBJ_Unlink_ret: ; --------------------------------------------------------------------------- -; @routine OBJ_GetRoot @global +; @routine OBJ_GetRootToY @global ; ; @param Y address of object ; @return Y address pointer to root object ; @clobbers r18, r19 -OBJ_GetRoot: -OBJ_GetRoot_loop: +OBJ_GetRootToY: +OBJ_GetRootToY_loop: rcall OBJ_GetParent ; (none) - brcc OBJ_GetRoot_found ; no parent, return current Y + brcc OBJ_GetRootToY_found ; no parent, return current Y mov yl, r18 mov yh, r19 - rjmp OBJ_GetRoot_loop -OBJ_GetRoot_found: + rjmp OBJ_GetRootToY_loop +OBJ_GetRootToY_found: sec -OBJ_GetRoot_end: +OBJ_GetRootToY_end: ret ; @end @@ -465,28 +522,45 @@ OBJ_EmitSignal: ; --------------------------------------------------------------------------- ; @routine OBJ_HandleSignal @global ; -; @param Y byte address of object (for LPM!) +; @param Y address of object ; @param R16 signal number ; @param R17 selector ; @param xl param1 ; @param xh param2 ; @return CFLAG set if handled, cleared otherwise +; @return r19:r18 return value from signal handler ; @clobbers any, !Y OBJ_HandleSignal: - push yl - push yh - rcall objGetHandlerFromSignalMap ; r19:r18=handler (r22, r23, Z) - brcc OBJ_HandleSignal_done - rcall OBJ_HandleSignal_jmpR19R18 -OBJ_HandleSignal_done: - pop yh - pop yl - ret -OBJ_HandleSignal_jmpR19R18: - ; jmp to r19:r18 via stack - push r18 - push r19 + ; check pointer + mov r18, yl + or r18, yh + clc + breq OBJ_HandleSignal_ret + + ; start with objects signal map + ldd zl, Y+OBJECT_OFFS_SIGNALMAP_LO + ldd zh, Y+OBJECT_OFFS_SIGNALMAP_HI + +OBJ_HandleSignal_loop: + ; test table validity + mov r18, zl + or r18, zh + clc + breq OBJ_HandleSignal_ret + ; try this table + push zl + push zh + rcall objHandleSignalWithMap ; (any, !Y) + pop zh + pop zl + brcs OBJ_HandleSignal_ret + ; get next table + lpm r18, Z+ + lpm zh, Z + mov zl, r18 + rjmp OBJ_HandleSignal_loop ; try next table +OBJ_HandleSignal_ret: ret ; @end @@ -533,6 +607,58 @@ OBJ_TreeHandleSignal_done: +; --------------------------------------------------------------------------- +; @routine OBJ_TreeHandleSignalIfMatchingOptsLo @global @recursive +; +; @param Y address of object +; @param R16 signal number +; @param R17 selector +; @param xl param1 +; @param xh param2 +; @param r20 mask for OBJECT_OFFS_OPTS_LO +; @param r21 value for OBJECT_OFFS_OPTS_LO to match +; @return CFLAG set if handled, cleared otherwise +; @clobbers any, !R16, !R17, !X, !Y + +OBJ_TreeHandleSignalIfMatchingOpts: + push yl + push yh + ; call signal handler + push r16 + push r17 + push xl + push xh + ldd r18, Y+OBJECT_OFFS_OPTS_LO + eor r18, r21 + and r18, r20 + brne OBJ_TreeHandleSignalIfMatchingOpts_l1 + push r20 + push r21 + rcall OBJ_HandleSignal ; (any, !Y) + pop r21 + pop r20 +OBJ_TreeHandleSignalIfMatchingOpts_l1: + pop xh + pop xl + pop r17 + pop r16 + ; handle children + rcall OBJ_GetFirstChild ; r19:r18=object (none) +OBJ_TreeHandleSignalIfMatchingOpts_loop: + brcc OBJ_TreeHandleSignalIfMatchingOpts_done + mov yl, r18 + mov yh, r19 + rcall OBJ_TreeHandleSignalIfMatchingOpts ; recursion! + rcall OBJ_GetNext ; r19:r18=object (none) + rjmp OBJ_TreeHandleSignalIfMatchingOpts_loop +OBJ_TreeHandleSignalIfMatchingOpts_done: + pop yh + pop yl + ret +; @end + + + ; --------------------------------------------------------------------------- ; @routine OBJ_TreeHandleSignalChildenFirst @global @recursive ; @@ -650,10 +776,43 @@ OBJ_SubFlagsDown_done: +; --------------------------------------------------------------------------- +; @routine objHandleSignalWithMap +; +; @param Y byte address of object (for LPM!) +; @param Z signal map to use +; @param R16 signal number +; @param R17 selector +; @param xl param1 +; @param xh param2 +; @return CFLAG set if handled, cleared otherwise +; @return r19:r18 return value from signal handler +; @clobbers any, !Y + +objHandleSignalWithMap: + push yl + push yh + rcall objGetHandlerFromSignalMap ; r19:r18=handler (r22, r23, Z) + brcc objHandleSignalWithMap_done + rcall objHandleSignalWithMap_jmpR19R18 +objHandleSignalWithMap_done: + pop yh + pop yl + ret +objHandleSignalWithMap_jmpR19R18: + ; jmp to r19:r18 via stack + push r18 + push r19 + ret +; @end + + + ; --------------------------------------------------------------------------- ; @routine objGetHandlerFromSignalMap ; ; @param Y address of object +; @param Z signal map to use (byte address for LPM!) ; @param R16 signal number ; @param R17 selector ; @param xl param1 @@ -663,13 +822,11 @@ OBJ_SubFlagsDown_done: ; @clobbers r22, r23, Z objGetHandlerFromSignalMap: - ldd zl, Y+OBJECT_OFFS_SIGNALMAP_LO - ldd zh, Y+OBJECT_OFFS_SIGNALMAP_HI mov r23, zl or r23, zh clc breq objGetHandlerFromSignalMap_done - ; Z=signal map + adiw zh:zl, OBJECT_SIGNALMAP_OFFS_ENTRIES ; go straight to entries objGetHandlerFromSignalMap_loop: lpm r22, Z+ ; selector lpm r23, Z+ ; signal (0=end of table) @@ -743,10 +900,17 @@ objGetPredecessor_ret: ; data in FLASH Object_DefaultSignalmap: + ; header + .dw 0 ; next table to use (none here) + ; entries .db 0, OBJECT_SIGNAL_DESTROY, LOW(OBJ_OnDestroy), HIGH(OBJ_OnDestroy) .db 0, 0, 0, 0 ; end of table + +; @endmodule + + #endif diff --git a/avr/modules/lcd2/gui2/base/rootwindow.asm b/avr/modules/lcd2/gui2/base/rootwindow.asm index f08e4ab..4c7c0c8 100644 --- a/avr/modules/lcd2/gui2/base/rootwindow.asm +++ b/avr/modules/lcd2/gui2/base/rootwindow.asm @@ -128,8 +128,10 @@ RootWindow_SetApp: ; data in FLASH RootWindow_DefaultSignalmap: - .db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDrawNop), HIGH(Widget_OnDrawNop) - .db 0, OBJECT_SIGNAL_DESTROY, LOW(OBJ_OnDestroy), HIGH(OBJ_OnDestroy) + ; header + .dw Widget_DefaultSignalmap ; next table to use + ; entries + ; none for now .db 0, 0, 0, 0 ; end of table diff --git a/avr/modules/lcd2/gui2/base/widget.asm b/avr/modules/lcd2/gui2/base/widget.asm index fbfaec0..a5a12e2 100644 --- a/avr/modules/lcd2/gui2/base/widget.asm +++ b/avr/modules/lcd2/gui2/base/widget.asm @@ -89,7 +89,16 @@ .equ WIDGET_SIGNAL_DRAW = OBJECT_SIGNAL_NEXTFREE+3 .equ WIDGET_SIGNAL_TOUCH = OBJECT_SIGNAL_NEXTFREE+4 .equ WIDGET_SIGNAL_CLICKED = OBJECT_SIGNAL_NEXTFREE+5 -.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+6 +.equ WIDGET_SIGNAL_SETVALUE = OBJECT_SIGNAL_NEXTFREE+6 +.equ WIDGET_SIGNAL_GETVALUE = OBJECT_SIGNAL_NEXTFREE+7 +.equ WIDGET_SIGNAL_KEEPALIVE = OBJECT_SIGNAL_NEXTFREE+8 +.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+9 + + +; values for signals WIDGET_SIGNAL_SETVALUE and WIDGET_SIGNAL_GETVALUE +.equ WIDGET_VALUE_DEFAULT_WIDTH = 1 +.equ WIDGET_VALUE_DEFAULT_HEIGHT = 2 +.equ WIDGET_VALUE_NEXTFREE = 3 @@ -105,19 +114,24 @@ ; @param Y address of object in SDRAM ; @param r16 value for OBJECT_OFFS_OPTS_LO ; @param r17 value for OBJECT_OFFS_OPTS_HI +; @param X parent widget (if any) ; @clobbers r16, r17, X Widget_Init: - ; call base class - bigcall OBJ_Init ; (r16, r17, X) - - ; clear widget-specific data - mov xl, yl - mov xh, yh - adiw xh:xl, WIDGET_OFFS_BEGIN - clr r16 - ldi r17, (WIDGET_SIZE-WIDGET_OFFS_BEGIN) - bigcall Utils_FillSram ; (r17, X) + push xl + push xh + ; call base class + bigcall OBJ_Init ; (r16, r17, X) + + ; clear widget-specific data + mov xl, yl + mov xh, yh + adiw xh:xl, WIDGET_OFFS_BEGIN + clr r16 + ldi r17, (WIDGET_SIZE-WIDGET_OFFS_BEGIN) + bigcall Utils_FillSram ; (r17, X) + pop xh + pop xl ; set default signal map ldi r16, LOW(Widget_DefaultSignalmap*2) @@ -125,12 +139,26 @@ Widget_Init: ldi r16, HIGH(Widget_DefaultSignalmap*2) std Y+OBJECT_OFFS_SIGNALMAP_HI, r16 - ; set default style + ; set style + mov r16, xl + or r16, xh + breq Widget_Init_setDefaultStyle + ; use style from parent + adiw xh:xl, WIDGET_OFFS_STYLE_LO + ld r16, X+ + std Y+WIDGET_OFFS_STYLE_LO, r16 + ld r16, X + std Y+WIDGET_OFFS_STYLE_HI, r16 + sbiw xh:xl, (WIDGET_OFFS_STYLE_LO+1) + rjmp Widget_Init_setDefaultSize + +Widget_Init_setDefaultStyle: ldi r16, LOW(Widget_DefaultStyle*2) std Y+WIDGET_OFFS_STYLE_LO, r16 ldi r16, HIGH(Widget_DefaultStyle*2) std Y+WIDGET_OFFS_STYLE_HI, r16 +Widget_Init_setDefaultSize: ; initial size: 1x1 px ldi r16, 1 clr r17 @@ -139,6 +167,13 @@ Widget_Init: std Y+WIDGET_OFFS_HEIGHT_LO, r16 std Y+WIDGET_OFFS_HEIGHT_HI, r17 + ; add to parent (if any) + mov r16, xl + or r16, xh + breq Widget_Init_ret + bigcall OBJ_AddChild + +Widget_Init_ret: ret ; @end @@ -252,6 +287,36 @@ Widget_OnDrawNop: +; --------------------------------------------------------------------------- +; @routine Widget_OnGetValue @global +; +; @param Y address of widget +; @param r17 value requested +; @param xl param1 +; @param xh param2 +; @return CFLAG set if signal handled +; @return r19:r18 value +; @clobbers any, !Y + +Widget_OnGetValue: + cpi r17, WIDGET_VALUE_DEFAULT_WIDTH + breq Widget_OnGetValue_getDefaultWidth + cpi r17, WIDGET_VALUE_DEFAULT_HEIGHT + breq Widget_OnGetValue_getDefaultHeight + clc + rjmp Widget_OnGetValue_ret + +Widget_OnGetValue_getDefaultWidth: +Widget_OnGetValue_getDefaultHeight: + ldi r18, 1 + clr r19 + sec +Widget_OnGetValue_ret: + ret +; @end + + + ; --------------------------------------------------------------------------- ; @routine Widget_Clear @global ; @@ -656,8 +721,11 @@ widgetCalcAbsPosAndBorders: ; data in FLASH Widget_DefaultSignalmap: - .db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDraw), HIGH(Widget_OnDraw) - .db 0, OBJECT_SIGNAL_DESTROY, LOW(OBJ_OnDestroy), HIGH(OBJ_OnDestroy) + ; header + .dw Object_DefaultSignalmap ; next table to use + ; entries + .db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDraw), HIGH(Widget_OnDraw) + .db 0, WIDGET_SIGNAL_GETVALUE, LOW(Widget_OnGetValue), HIGH(Widget_OnGetValue) ; handle any value here .db 0, 0, 0, 0 ; end of table