Files
aqhomecontrol/avr/modules/lcd2/gui2/base/object.asm
2026-03-07 13:47:05 +01:00

992 lines
24 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_OBJECT_ASM
#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
; Object in flash
.equ OBJECT_OFFS_NEXT_LO = 0
.equ OBJECT_OFFS_NEXT_HI = 1
.equ OBJECT_OFFS_PARENT_LO = 2
.equ OBJECT_OFFS_PARENT_HI = 3
.equ OBJECT_OFFS_CHILD_LO = 4
.equ OBJECT_OFFS_CHILD_HI = 5
.equ OBJECT_OFFS_FLAGS = 6
.equ OBJECT_OFFS_SELECTOR = 7
.equ OBJECT_OFFS_TARGET_LO = 8
.equ OBJECT_OFFS_TARGET_HI = 9
.equ OBJECT_OFFS_OPTS_LO = 10
.equ OBJECT_OFFS_OPTS_HI = 11
.equ OBJECT_OFFS_SIGNALMAP_LO = 12 ; byte address (for LPM!)
.equ OBJECT_OFFS_SIGNALMAP_HI = 13
.equ OBJECT_SIZE = 14
; object opts_lo
.equ OBJECT_OPTSLO_TIMER_BIT = 7
.equ OBJECT_OPTSLO_MSGRECV_BIT = 6
; SignalMap entries
.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
.equ OBJECT_SIGNAL_DESTROY = 1
.equ OBJECT_SIGNAL_TIMER = 2
.equ OBJECT_SIGNAL_RECVMSG = 3 ; X=msg
.equ OBJECT_SIGNAL_NEXTFREE = 4
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine Object_Alloc @global
;
; @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, !X
Object_Alloc:
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
; ---------------------------------------------------------------------------
; @routine OBJ_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
OBJ_Init:
push r16
push r17
mov xl, yl
mov xh, yh
clr r16
ldi r17, OBJECT_SIZE
bigcall Utils_FillSram ; (r17, X)
pop r17
pop r16
; set opts
std Y+OBJECT_OFFS_OPTS_LO, r16
std Y+OBJECT_OFFS_OPTS_HI, r17
; set default signal map
ldi r16, LOW(Object_DefaultSignalmap*2)
std Y+OBJECT_OFFS_SIGNALMAP_LO, r16
ldi r16, HIGH(Object_DefaultSignalmap*2)
std Y+OBJECT_OFFS_SIGNALMAP_HI, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_Fini @global
;
; @param Y address of object in SDRAM
; @clobbers none
OBJ_Fini:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_Free @global
;
; Sends a OBJECT_SIGNAL_DESTROY signal to all children and to the given
; object which frees all objects from the Heap.
; CAVEAT: Y is invalid after return!
;
; @param Y address of object in SDRAM
; @clobbers none
OBJ_Free:
tst yl
brne OBJ_Free_notNull
tst yh
brne OBJ_Free_notNull
rjmp OBJ_Free_ret
OBJ_Free_notNull:
ldi r16, OBJECT_SIGNAL_DESTROY
clr r17
rcall OBJ_TreeHandleSignalChildenFirst ; (any, !R16, !R17, !X, !Y)
OBJ_Free_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_OnDestroy @global
;
; Releases given object from heap.
; CAVEAT: Y is invalid after return!
;
; @param Y address of object in SDRAM
; @return CFLAG set if signal handled
; @clobbers r16, r17, r18, r19, r20, r21, r24, r25, X
OBJ_OnDestroy:
rcall OBJ_Unlink ; (r16, r17, r18, r19, r20, r21, X)
mov xl, yl
mov xh, yh
bigcall Heap_Free ; (r16, r17, r24, r25, X)
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_GetNext @global
;
; @param Y address of object
; @return CFLAG set, if found, cleared otherwise
; @return r19:r18 resulting object
; @clobbers none
OBJ_GetNext:
tst yl
brne OBJ_GetNext_notNull
tst yh
brne OBJ_GetNext_notNull
rjmp OBJ_GetNext_clcRet
OBJ_GetNext_notNull:
ldd r18, Y+OBJECT_OFFS_NEXT_LO
ldd r19, Y+OBJECT_OFFS_NEXT_HI
tst r18
brne OBJ_GetNext_secRet
tst r19
brne OBJ_GetNext_secRet
OBJ_GetNext_clcRet:
clc
rjmp OBJ_GetNext_ret
OBJ_GetNext_secRet:
sec
OBJ_GetNext_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_GetParent @global
;
; @param Y address of object
; @return CFLAG set, if found, cleared otherwise
; @return r19:r18 resulting object
; @clobbers none
OBJ_GetParent:
tst yl
brne OBJ_GetParent_notNull
tst yh
brne OBJ_GetParent_notNull
rjmp OBJ_GetParent_clcRet
OBJ_GetParent_notNull:
ldd r18, Y+OBJECT_OFFS_PARENT_LO
ldd r19, Y+OBJECT_OFFS_PARENT_HI
tst r18
brne OBJ_GetParent_secRet
tst r19
brne OBJ_GetParent_secRet
OBJ_GetParent_clcRet:
clc
rjmp OBJ_GetParent_ret
OBJ_GetParent_secRet:
sec
OBJ_GetParent_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_GetFirstChild @global
;
; @param Y address of object
; @return CFLAG set, if found, cleared otherwise
; @return r19:r18 resulting object
; @clobbers none
OBJ_GetFirstChild:
tst yl
brne OBJ_GetFirstChild_notNull
tst yh
brne OBJ_GetFirstChild_notNull
rjmp OBJ_GetFirstChild_clcRet
OBJ_GetFirstChild_notNull:
ldd r18, Y+OBJECT_OFFS_PARENT_LO
ldd r19, Y+OBJECT_OFFS_PARENT_HI
tst r18
brne OBJ_GetFirstChild_secRet
tst r19
brne OBJ_GetFirstChild_secRet
OBJ_GetFirstChild_clcRet:
clc
rjmp OBJ_GetFirstChild_ret
OBJ_GetFirstChild_secRet:
sec
OBJ_GetFirstChild_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_GetLastChild @global
;
; @param Y address of object
; @return CFLAG set, if found, cleared otherwise
; @return r19:r18 resulting object
; @clobbers none
OBJ_GetLastChild:
push yl
push yh
rcall OBJ_GetFirstChild ; R19:R18=obj (none)
brcc OBJ_GetLastChild_ret
OBJ_GetLastChild_loop:
mov yl, r18
mov yh, r19
rcall OBJ_GetNext ; R19:R18=obj (none)
brcs OBJ_GetLastChild_loop
mov r18, yl
mov r19, yh
sec
OBJ_GetLastChild_ret:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_GetChildAt @global
;
; @param Y address of object
; @param R16 idx of child to get (starting at 0)
; @return CFLAG set, if found, cleared otherwise
; @return r19:r18 resulting object
; @clobbers none
OBJ_GetChildAt:
push yl
push yh
rcall OBJ_GetFirstChild ; R19:R18=obj (none)
brcc OBJ_GetChildAt_ret
OBJ_GetChildAt_loop:
tst r16
breq OBJ_GetChildAt_secRet
mov yl, r18
mov yh, r19
rcall OBJ_GetNext ; R19:R18=obj (none)
brcs OBJ_GetChildAt_loop
rjmp OBJ_GetChildAt_ret ; idx too high, not found
OBJ_GetChildAt_secRet:
sec
OBJ_GetChildAt_ret:
pop yh
pop yl
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
objAddObjXAsChildToY:
rcall OBJ_GetLastChild ; r19:r18=last child (r18, r19)
brcc objAddObjXAsChildToY_setAsFirstChild
; append to last child
push yl
push yh
mov yl, r18
mov yh, r19
std Y+OBJECT_OFFS_NEXT_LO, xl
std Y+OBJECT_OFFS_NEXT_HI, xh
pop yh
pop yl
rjmp objAddObjXAsChildToY_setParent
objAddObjXAsChildToY_setAsFirstChild:
std Y+OBJECT_OFFS_CHILD_LO, xl
std Y+OBJECT_OFFS_CHILD_HI, xh
objAddObjXAsChildToY_setParent:
adiw xh:xl, OBJECT_OFFS_PARENT_LO
st X+, yl
st X, yh
sbiw xh:xl, (OBJECT_OFFS_PARENT_LO+1)
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_Unlink @global
;
; @param Y object to unlink
; @clobbers r16, r17, r18, r19, r20, r21, X
OBJ_Unlink:
mov xl, yl
mov xh, yh
adiw xh:xl, OBJECT_OFFS_NEXT_LO ; r21:r20=next
ld r20, X+
ld r21, X
sbiw xh:xl, (OBJECT_OFFS_NEXT_LO+1)
push yl
push yh
rcall objGetPredecessor ; Y=predecessor (r16, r17, Y)
brcc OBJ_Unlink_l1
; unlink from predecessor
std Y+OBJECT_OFFS_NEXT_LO, r20 ; copy NEXT to predecessor
std Y+OBJECT_OFFS_NEXT_HI, r21
rjmp OBJ_Unlink_l2
OBJ_Unlink_l1: ; no predecessor, unlink from parent
pop yh
pop yl
rcall OBJ_GetParent
brcc OBJ_Unlink_clearTreePtrs
push yl
push yh
mov yl, r18
mov yh, r19
std Y+OBJECT_OFFS_CHILD_LO, r20
std Y+OBJECT_OFFS_CHILD_HI, r21
OBJ_Unlink_l2:
pop yh
pop yl
OBJ_Unlink_clearTreePtrs:
clr r16
std Y+OBJECT_OFFS_NEXT_LO, r16
std Y+OBJECT_OFFS_NEXT_HI, r16
std Y+OBJECT_OFFS_PARENT_LO, r16
std Y+OBJECT_OFFS_PARENT_HI, r16
OBJ_Unlink_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_GetRootToY @global
;
; @param Y address of object
; @return Y address pointer to root object
; @clobbers r18, r19
OBJ_GetRootToY:
OBJ_GetRootToY_loop:
rcall OBJ_GetParent ; (none)
brcc OBJ_GetRootToY_found ; no parent, return current Y
mov yl, r18
mov yh, r19
rjmp OBJ_GetRootToY_loop
OBJ_GetRootToY_found:
sec
OBJ_GetRootToY_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_EmitSignal @global
;
; @param Z byte address of object (for LPM!)
; @param R16 signal number
; @param xl param1
; @param xh param2
; @clobbers any, !Y
OBJ_EmitSignal:
push yl
push yh
ldd r17, Y+OBJECT_OFFS_SELECTOR
ldd r23, Y+OBJECT_OFFS_TARGET_LO
ldd yh, Y+OBJECT_OFFS_TARGET_HI
mov yl, r23
rcall OBJ_HandleSignal ; (any, !Y)
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_HandleSignal @global
;
; @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:
; 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
; ---------------------------------------------------------------------------
; @routine OBJ_TreeHandleSignal @global @recursive
;
; @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
; @clobbers any, !R16, !R17, !X, !Y
OBJ_TreeHandleSignal:
push yl
push yh
; call signal handler
push r16
push r17
push xl
push xh
rcall OBJ_HandleSignal ; (any, !Y)
pop xh
pop xl
pop r17
pop r16
; handle children
rcall OBJ_GetFirstChild ; r19:r18=object (none)
OBJ_TreeHandleSignal_loop:
brcc OBJ_TreeHandleSignal_done
mov yl, r18
mov yh, r19
rcall OBJ_TreeHandleSignal ; recursion!
rcall OBJ_GetNext ; r19:r18=object (none)
rjmp OBJ_TreeHandleSignal_loop
OBJ_TreeHandleSignal_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @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
; @clobbers any, !R16, !R17, !X, !Y
OBJ_TreeHandleSignalIfMatchingOptsLo:
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_TreeHandleSignalIfMatchingOptsLo_l1
push r20
push r21
rcall OBJ_HandleSignal ; (any, !Y)
pop r21
pop r20
OBJ_TreeHandleSignalIfMatchingOptsLo_l1:
pop xh
pop xl
pop r17
pop r16
; handle children
rcall OBJ_GetFirstChild ; r19:r18=object (none)
OBJ_TreeHandleSignalIfMatchingOptsLo_loop:
brcc OBJ_TreeHandleSignalIfMatchingOptsLo_done
mov yl, r18
mov yh, r19
rcall OBJ_TreeHandleSignalIfMatchingOptsLo ; recursion!
rcall OBJ_GetNext ; r19:r18=object (none)
rjmp OBJ_TreeHandleSignalIfMatchingOptsLo_loop
OBJ_TreeHandleSignalIfMatchingOptsLo_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_TreeHandleSignalIfFlagsSet @global @recursive
;
; @param Y address of object
; @param R16 signal number
; @param R17 selector
; @param xl param1
; @param xh param2
; @param r20 flags to match
; @clobbers any, !R16, !R17, !X, !Y
OBJ_TreeHandleSignalIfFlagsSet:
push yl
push yh
; call signal handler
push r16
push r17
push xl
push xh
ldd r18, Y+OBJECT_OFFS_FLAGS
and r18, r20
eor r18, r20
brne OBJ_TreeHandleSignalIfFlagsSet_l1
push r20
rcall OBJ_HandleSignal ; (any, !Y)
pop r20
OBJ_TreeHandleSignalIfFlagsSet_l1:
pop xh
pop xl
pop r17
pop r16
; handle children
rcall OBJ_GetFirstChild ; r19:r18=object (none)
OBJ_TreeHandleSignalIfFlagsSet_loop:
brcc OBJ_TreeHandleSignalIfFlagsSet_done
mov yl, r18
mov yh, r19
rcall OBJ_TreeHandleSignalIfFlagsSet ; recursion!
rcall OBJ_GetNext ; r19:r18=object (none)
rjmp OBJ_TreeHandleSignalIfFlagsSet_loop
OBJ_TreeHandleSignalIfFlagsSet_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_TreeHandleSignalChildenFirst @global @recursive
;
; Sends a given signal to a tree of objects, handling children first.
; After sending a signal to a child object that object is no longer accessed
; from within this routine, so it can be used to send a DESTROY signal which
; frees the object from the memory heap.
;
; @param Y address of object
; @param R16 signal number
; @param R17 selector
; @param xl param1
; @param xh param2
; @clobbers any, !R16, !R17, !X, !Y
OBJ_TreeHandleSignalChildenFirst:
push yl
push yh
; handle children first
rcall OBJ_GetFirstChild ; r19:r18=object (none)
brcc OBJ_TreeHandleSignalChildenFirst_done
OBJ_TreeHandleSignalChildenFirst_loop:
mov yl, r18
mov yh, r19
rcall OBJ_GetNext ; r19:r18=object (none)
ldi r20, 0
sbci r20, 0
push r18
push r19
push r20
rcall OBJ_TreeHandleSignalChildenFirst ; recursion!
pop r20
pop r19
pop r18
tst r20 ; result of OBJ_GetNext (0=no next)
brne OBJ_TreeHandleSignalChildenFirst_loop
OBJ_TreeHandleSignalChildenFirst_done:
pop yh
pop yl
; call signal handler on self
push r16
push r17
push xl
push xh
rcall OBJ_HandleSignal ; (any, !Y)
pop xh
pop xl
pop r17
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_AddFlagsDown @global
;
; @param Y address of object
; @param R16 flags to add
; @clobbers r17, r18, r19
OBJ_AddFlagsDown:
push yl
push yh
ldd r17, Y+OBJECT_OFFS_FLAGS
or r17, r16
std Y+OBJECT_OFFS_FLAGS, r17
; handle children
rcall OBJ_GetFirstChild ; r19:r18=object (none)
OBJ_AddFlagsDown_loop:
brcc OBJ_AddFlagsDown_done
mov yl, r18
mov yh, r19
rcall OBJ_AddFlagsDown ; recursion!
rcall OBJ_GetNext ; r19:r18=object (none)
rjmp OBJ_AddFlagsDown_loop
OBJ_AddFlagsDown_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_SubFlagsDown @global
;
; @param Y address of object
; @param R16 flags to subtract
; @clobbers r17, r18, r19
OBJ_SubFlagsDown:
push yl
push yh
ldd r17, Y+OBJECT_OFFS_FLAGS
com r16
and r17, r16
com r16
std Y+OBJECT_OFFS_FLAGS, r17
; handle children
rcall OBJ_GetFirstChild ; r19:r18=object (none)
OBJ_SubFlagsDown_loop:
brcc OBJ_SubFlagsDown_done
mov yl, r18
mov yh, r19
rcall OBJ_SubFlagsDown ; recursion!
rcall OBJ_GetNext ; r19:r18=object (none)
rjmp OBJ_SubFlagsDown_loop
OBJ_SubFlagsDown_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine OBJ_AddFlagsUp @global @recursive
;
; @param Y address of object
; @param R16 flags to add
; @clobbers r17, r18, r19
OBJ_AddFlagsUp:
push yl
push yh
ldd r17, Y+OBJECT_OFFS_FLAGS
or r17, r16
std Y+OBJECT_OFFS_FLAGS, r17
; handle parents
OBJ_AddFlagsUp_loop:
rcall OBJ_GetParent ; r19:r18=object (none)
brcc OBJ_AddFlagsUp_done
mov yl, r18
mov yh, r19
rcall OBJ_AddFlagsUp ; recursion!
rjmp OBJ_AddFlagsUp_loop
OBJ_AddFlagsUp_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @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
; @param xh param2
; @return CFLAG set if found, cleared otherwise
; @return R19:R18 handler found
; @clobbers r22, r23, Z
objGetHandlerFromSignalMap:
mov r23, zl
or r23, zh
clc
breq objGetHandlerFromSignalMap_done
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)
lpm r18, Z+ ; handler LOW
lpm r19, Z+ ; handler HIGH
tst r23 ; end of table?
clc
breq objGetHandlerFromSignalMap_done ; yes, jmp
cp r16, r23 ; signal match?
brne objGetHandlerFromSignalMap_next ; no, next
tst r22
breq objGetHandlerFromSignalMap_checkHandler ; accept any selector if it is 0 in table
cp r17, r22 ; selector match?
brne objGetHandlerFromSignalMap_next ; no, next
objGetHandlerFromSignalMap_checkHandler:
mov r23, r18 ; handler==NULL?
or r23, r19
clc
breq objGetHandlerFromSignalMap_done ; yes, done
sec ; found handler, return in r19:r18
rjmp objGetHandlerFromSignalMap_done
objGetHandlerFromSignalMap_next:
rjmp objGetHandlerFromSignalMap_loop
objGetHandlerFromSignalMap_done:
ret
; @end
; ---------------------------------------------------------------------------
; @routine objGetPredecessor
;
; @param Y address of object whose predecessor is to be found
; @return CFLAG set if predecessor found, cleared otherwise
; @return Y pointer to predecessor (if CFLAG set)
; @clobbers r16, r17, Y
objGetPredecessor:
rcall OBJ_GetParent
brcc objGetPredecessor_ret
mov r16, yl
mov r17, yh
rcall OBJ_GetFirstChild ; R19:R18=obj
brcc objGetPredecessor_ret
mov yl, r18
mov yh, r19
objGetPredecessor_loop:
rcall OBJ_GetNext
brcc objGetPredecessor_ret
cp r18, r16
brne objGetPredecessor_next
cp r19, r17
brne objGetPredecessor_next
sec
rjmp objGetPredecessor_ret
objGetPredecessor_next:
mov yl, r18
mov yh, r19
rjmp objGetPredecessor_loop
objGetPredecessor_ret:
ret
; @end
; ***************************************************************************
; 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