408 lines
9.3 KiB
NASM
408 lines
9.3 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
|
|
|
|
|
|
; ***************************************************************************
|
|
; defines
|
|
|
|
; Object in flash
|
|
.equ OBJECT_OFFS_NEXT_LO = 0 ; byte address (for LPM!)
|
|
.equ OBJECT_OFFS_NEXT_HI = 1
|
|
.equ OBJECT_OFFS_PARENT_LO = 2 ; byte address (for LPM!)
|
|
.equ OBJECT_OFFS_PARENT_HI = 3
|
|
.equ OBJECT_OFFS_CHILD_LO = 4 ; byte address (for LPM!)
|
|
.equ OBJECT_OFFS_CHILD_HI = 5
|
|
.equ OBJECT_OFFS_TARGET_LO = 6 ; byte address (for LPM!)
|
|
.equ OBJECT_OFFS_TARGET_HI = 7
|
|
.equ OBJECT_OFFS_SELECTOR = 8
|
|
.equ OBJECT_OFFS_UNUSED = 9
|
|
.equ OBJECT_OFFS_SIGNALMAP_LO = 10 ; byte address (for LPM!)
|
|
.equ OBJECT_OFFS_SIGNALMAP_HI = 11
|
|
.equ OBJECT_SIZE = 12
|
|
|
|
; 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
|
|
|
|
; signals
|
|
.equ OBJECT_SIGNAL_NONE = 0
|
|
.equ OBJECT_SIGNAL_CREATE = 1
|
|
.equ OBJECT_SIGNAL_DESTROY = 2
|
|
.equ OBJECT_SIGNAL_TIMER = 3
|
|
.equ OBJECT_SIGNAL_RECVMSG = 4 ; X=msg
|
|
.equ OBJECT_SIGNAL_NEXTFREE = 5
|
|
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_GetParent @global
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @return CFLAG set, if found, cleared otherwise
|
|
; @return r19:r18 resulting object (byte address for LPM!), NULL otherwise
|
|
; @clobbers none
|
|
|
|
OBJ_GetParent:
|
|
tst zh
|
|
brne OBJ_GetParent_get
|
|
tst zl
|
|
brne OBJ_GetParent_get
|
|
clc
|
|
rjmp OBJ_GetParent_ret
|
|
OBJ_GetParent_get:
|
|
adiw zh:zl, OBJECT_OFFS_PARENT_LO
|
|
lpm r18, Z+
|
|
lpm r19, Z
|
|
sbiw zh:zl, (OBJECT_OFFS_PARENT_LO+1)
|
|
tst r18
|
|
brne OBJ_GetParent_secRet
|
|
tst r19
|
|
clc
|
|
breq OBJ_GetParent_ret
|
|
OBJ_GetParent_secRet:
|
|
sec
|
|
OBJ_GetParent_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_GetFirstChild @global
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @return CFLAG set, if found, cleared otherwise
|
|
; @return r19:r18 resulting object (byte address for LPM!), NULL otherwise
|
|
; @clobbers none
|
|
|
|
OBJ_GetFirstChild:
|
|
tst zh
|
|
brne OBJ_GetFirstChild_get
|
|
tst zl
|
|
brne OBJ_GetFirstChild_get
|
|
clc
|
|
rjmp OBJ_GetFirstChild_ret
|
|
OBJ_GetFirstChild_get:
|
|
adiw zh:zl, OBJECT_OFFS_CHILD_LO
|
|
lpm r18, Z+
|
|
lpm r19, Z
|
|
sbiw zh:zl, OBJECT_OFFS_CHILD_LO+1
|
|
tst r18
|
|
brne OBJ_GetFirstChild_secRet
|
|
tst r19
|
|
clc
|
|
breq OBJ_GetFirstChild_ret
|
|
OBJ_GetFirstChild_secRet:
|
|
sec
|
|
OBJ_GetFirstChild_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_GetNext @global
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @return CFLAG set, if found, cleared otherwise
|
|
; @return r19:r18 resulting object (byte address for LPM!), NULL otherwise
|
|
; @clobbers none
|
|
|
|
OBJ_GetNext:
|
|
tst zh
|
|
brne OBJ_GetNext_get
|
|
tst zl
|
|
brne OBJ_GetNext_get
|
|
clc
|
|
rjmp OBJ_GetNext_ret
|
|
OBJ_GetNext_get:
|
|
adiw zh:zl, OBJECT_OFFS_NEXT_LO
|
|
lpm r18, Z+
|
|
lpm r19, Z
|
|
sbiw zh:zl, OBJECT_OFFS_NEXT_LO+1
|
|
tst r18
|
|
brne OBJ_GetNext_secRet
|
|
tst r19
|
|
clc
|
|
breq OBJ_GetNext_ret
|
|
OBJ_GetNext_secRet:
|
|
sec
|
|
OBJ_GetNext_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_GetBelow @global
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @return CFLAG set, if found, cleared otherwise
|
|
; @return r19:r18 resulting object (byte address for LPM!), NULL otherwise
|
|
; @clobbers r16
|
|
|
|
OBJ_GetBelow:
|
|
tst zh
|
|
brne OBJ_GetBelow_get
|
|
tst zl
|
|
breq OBJ_GetBelow_ret
|
|
OBJ_GetBelow_get:
|
|
rcall OBJ_GetFirstChild
|
|
brcs OBJ_GetBelow_ret ; jmp if found
|
|
rcall OBJ_GetNext
|
|
brcs OBJ_GetBelow_ret ; jmp if found
|
|
|
|
OBJ_GetBelow_loop:
|
|
rcall OBJ_GetParent
|
|
brcc OBJ_GetBelow_ret ; jmp if no parent
|
|
; use parent
|
|
mov zl, r18
|
|
mov zh, r19
|
|
; don't check for first child here, we came from there!
|
|
rcall OBJ_GetNext
|
|
brcs OBJ_GetBelow_ret
|
|
rjmp OBJ_GetBelow_loop
|
|
OBJ_GetBelow_ret:
|
|
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, !Z
|
|
|
|
OBJ_EmitSignal:
|
|
push zl
|
|
push zh
|
|
rcall OBJ_EmitSignal_savedZ
|
|
pop zh
|
|
pop zl
|
|
rjmp OBJ_EmitSignal_ret
|
|
|
|
OBJ_EmitSignal_savedZ:
|
|
adiw zh:zl, OBJECT_OFFS_SELECTOR
|
|
lpm r17, Z
|
|
sbiw zh:zl, OBJECT_OFFS_SELECTOR
|
|
adiw zh:zl, OBJECT_OFFS_TARGET_LO
|
|
lpm r23, Z+
|
|
lpm zh, Z
|
|
mov zl, r23
|
|
rjmp OBJ_HandleSignal ; (any, !Z)
|
|
|
|
OBJ_EmitSignal_ret:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_TreeHandleSignal @global
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @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, !Z
|
|
|
|
OBJ_TreeHandleSignal:
|
|
push zl
|
|
push zh
|
|
mov r18, zl
|
|
or r18, zh
|
|
clc
|
|
breq OBJ_TreeHandleSignal_done
|
|
rcall objectHandleSignalSaveInRegs
|
|
brcs OBJ_TreeHandleSignal_done
|
|
|
|
rcall OBJ_GetFirstChild
|
|
OBJ_TreeHandleSignal_loop:
|
|
mov zl, r18
|
|
mov zh, r19
|
|
or r18, r19
|
|
clc
|
|
breq OBJ_TreeHandleSignal_done
|
|
rcall OBJ_TreeHandleSignal ; recursion
|
|
;rcall objectHandleSignalSaveInRegs
|
|
brcs OBJ_TreeHandleSignal_done
|
|
rcall OBJ_GetNext
|
|
rjmp OBJ_TreeHandleSignal_loop
|
|
|
|
OBJ_TreeHandleSignal_done:
|
|
pop zh
|
|
pop zl
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_TreeAllHandleSignal @global
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @param R16 signal number
|
|
; @param R17 selector
|
|
; @param xl param1
|
|
; @param xh param2
|
|
; @clobbers any, !R16, !R17, !X, !Z
|
|
|
|
OBJ_TreeAllHandleSignal:
|
|
push zl
|
|
push zh
|
|
|
|
OBJ_TreeAllHandleSignal_loop:
|
|
mov r18, zl
|
|
or r18, zh
|
|
breq OBJ_TreeAllHandleSignal_done
|
|
rcall objectHandleSignalSaveInRegs
|
|
push r16
|
|
rcall OBJ_GetBelow ; (R16)
|
|
pop r16
|
|
brcc OBJ_TreeAllHandleSignal_done
|
|
mov zl, r18
|
|
mov zh, r19
|
|
rjmp OBJ_TreeAllHandleSignal_loop
|
|
OBJ_TreeAllHandleSignal_done:
|
|
pop zh
|
|
pop zl
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine objectHandleSignalSaveInRegs
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @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, !Z
|
|
|
|
objectHandleSignalSaveInRegs:
|
|
push r16
|
|
push r17
|
|
push xl
|
|
push xh
|
|
rcall OBJ_HandleSignal
|
|
pop xh
|
|
pop xl
|
|
pop r17
|
|
pop r16
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine OBJ_HandleSignal
|
|
;
|
|
; @param Z byte address of object (for LPM!)
|
|
; @param R16 signal number
|
|
; @param R17 selector
|
|
; @param xl param1
|
|
; @param xh param2
|
|
; @return CFLAG set if handled, cleared otherwise
|
|
; @clobbers any, !Z
|
|
|
|
OBJ_HandleSignal:
|
|
push zl
|
|
push zh
|
|
rcall objGetHandlerFromSignalMap
|
|
brcc OBJ_HandleSignal_done
|
|
rcall OBJ_HandleSignal_jmpR19R18
|
|
OBJ_HandleSignal_done:
|
|
pop zh
|
|
pop zl
|
|
ret
|
|
OBJ_HandleSignal_jmpR19R18:
|
|
; jmp to r19:r18 via stack
|
|
push r18
|
|
push r19
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine objGetHandlerFromSignalMap
|
|
;
|
|
; @param Z byte address of object (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 any, !Z
|
|
|
|
objGetHandlerFromSignalMap:
|
|
push zl
|
|
push zh
|
|
adiw zh:zl, OBJECT_OFFS_SIGNALMAP_LO
|
|
lpm r23, Z+
|
|
lpm zh, Z
|
|
mov zl, r23
|
|
or r23, zh
|
|
clc
|
|
breq objGetHandlerFromSignalMap_done ; no signal map
|
|
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
|
|
clc
|
|
breq objGetHandlerFromSignalMap_done
|
|
cp r16, r23
|
|
brne objGetHandlerFromSignalMap_next
|
|
cp r17, r22
|
|
brne objGetHandlerFromSignalMap_next
|
|
mov r23, r18
|
|
or r23, r19
|
|
clc
|
|
breq objGetHandlerFromSignalMap_done
|
|
sec ; found handler
|
|
rjmp objGetHandlerFromSignalMap_done
|
|
objGetHandlerFromSignalMap_next:
|
|
rjmp objGetHandlerFromSignalMap_loop
|
|
|
|
objGetHandlerFromSignalMap_done:
|
|
pop zh
|
|
pop zl
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
|
|
#endif
|