gui2: improved signal handling, make use of secondary signal maps.

This commit is contained in:
Martin Preuss
2026-03-06 16:00:14 +01:00
parent 16b820fae1
commit a8cb442502
6 changed files with 636 additions and 68 deletions

View File

@@ -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