; *************************************************************************** ; 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