; *************************************************************************** ; copyright : (C) 2025 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. * ; *************************************************************************** .cseg ; --------------------------------------------------------------------------- ; @routine OBJ_Init @global ; ; @param Y pointer to object SRAM ; @param r17 options ; @clobbers X OBJ_Init: push r17 mov xl, yl mov xh, yh clr r16 ldi r17, OBJ_OFFS_SIZE bigcall Utils_FillSram ; (R17, X) bigcall Tree_InitObject ; (R16) pop r17 std Y+OBJ_OFFS_OPTIONS, r17 ldi r16, LOW(OBJ_DefaultHandler) std Y+OBJ_OFFS_HANDLERFN_LO, r16 ldi r16, HIGH(OBJ_DefaultHandler) std Y+OBJ_OFFS_HANDLERFN_HI, r16 ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_SetHandler @global ; ; @param Y pointer to object SRAM ; @param Z pointer to handler function (word address) ; @clobbers X OBJ_SetHandler: std Y+OBJ_OFFS_HANDLERFN_LO, zl std Y+OBJ_OFFS_HANDLERFN_HI, zh ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_GetHandler @global ; ; @param Y pointer to object SRAM ; @return Z pointer to handler function (word address) ; @clobbers none OBJ_GetHandler: ldd zl, Y+OBJ_OFFS_HANDLERFN_LO ldd zh, Y+OBJ_OFFS_HANDLERFN_HI ret ; @end OBJ_DefaultHandler: ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_free @global ; ; @param Y pointer to object in SRAM ; @clobbers any OBJ_free: ; free children push yl push yh rcall Tree_GetFirstChildObject ; (none) OBJ_free_loop: mov r16, xl or r16, xh breq OBJ_free_loopEnd mov yl, xl mov yh, xh rcall Tree_GetNextSibling push xl ; next push xh ; next rcall OBJ_free pop xh ; next pop xl ; next rjmp OBJ_free_loop OBJ_free_loopEnd: pop yh pop yl rcall Tree_UnlinkObject ; (r16, r17, x) push yl push yh ldi r16, OBJ_SIGNAL_DESTROY rcall OBJ_Handler pop yh pop yl rcall objFreeLinks rcall objFreeTimers mov xl, yl mov xh, yh rcall Heap_free clc ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_Handler ; ; Signal handler for an object. A signal can have up to 3 parameters ; conveyed in registers R18, R19 and X. ; ; @param Y pointer to object SRAM ; @param r16 signal ; @param R18 1st param ; @param R19 2nd param ; @param X 3rd param OBJ_Handler: ldd r17, Y+OBJ_OFFS_HANDLERFN_LO push r17 ldd r17, Y+OBJ_OFFS_HANDLERFN_HI push r17 ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_ForwardSignalToChildren ; ; Signal handler for an object. A signal can have up to 3 parameters ; conveyed in registers R18, R19 and X. ; ; @param Y pointer to object SRAM ; @param r16 signal ; @param R18 1st param ; @param R19 2nd param ; @param X 3rd param ; @clobbers any, !r16, !r18, !r19, !Y OBJ_ForwardSignalToChildren: push yl push yh rcall Tree_GetFirstChildObject ; (none) OBJ_ForwardSignalToChildren_loop: clc mov r17, xl or r17, xh breq OBJ_ForwardSignalToChildren_loopEnd mov yl, xl mov yh, xh push r16 push r18 push r19 push xl push xh push yl push yh rcall OBJ_Handler pop yh pop yl pop xh pop xl pop r19 pop r18 pop r16 rcall Tree_GetNextSibling rjmp OBJ_ForwardSignalToChildren_loop OBJ_ForwardSignalToChildren_loopEnd: pop yh pop yl ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_EmitSignal ; ; @param Y pointer to object SRAM ; @param r16 signal to emit ; @param R18 1st param ; @param R19 2nd param ; @param X 3rd param OBJ_EmitSignal: push yl push yh ldd r17, Y+OBJ_OFFS_LINKS_LO ldd yh, Y+OBJ_OFFS_LINKS_HI mov yl, r17 OBJ_EmitSignal_loop: push r16 rcall objCheckEmitSignalForLink ; (any, !X, !Y, !R18, !R19) pop r16 push xl push xh rcall List_GetNextObject ; (none) mov yl, xl mov yh, xh pop xh pop xl mov r17, yl or r17, yh brne OBJ_EmitSignal_loop OBJ_EmitSignal_popRet: pop yh pop yl ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_AddLink @global ; ; @param Y pointer to object SRAM ; @param X pointer to link ; @clobbers R16, R17 OBJ_AddLink: ldd r16, Y+OBJ_OFFS_LINKS_LO ldd r17, Y+OBJ_OFFS_LINKS_HI tst r16 brne OBJ_AddLink_addToExisting tst r17 brne OBJ_AddLink_addToExisting ; empty list, new link is first std Y+OBJ_OFFS_LINKS_LO, xl std Y+OBJ_OFFS_LINKS_HI, xh rjmp OBJ_AddLink_end OBJ_AddLink_addToExisting: push xl push xh push yl push yh mov yl, xl mov yh, xh mov xl, r16 mov xh, r17 rcall List_AddObject ; (r16, r17, x) pop yh pop yl pop xh pop xl OBJ_AddLink_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_RemoveLink @global ; ; @param Y pointer to object SRAM ; @param X pointer to link ; @clobbers R16, R17 OBJ_RemoveLink: ldd r16, Y+OBJ_OFFS_LINKS_LO ldd r17, Y+OBJ_OFFS_LINKS_HI cp r16, xl brne OBJ_RemoveLink_notFirst cp r17, xh brne OBJ_RemoveLink_notFirst clr r16 std Y+OBJ_OFFS_LINKS_LO, r16 std Y+OBJ_OFFS_LINKS_HI, r16 rjmp OBJ_RemoveLink_end OBJ_RemoveLink_notFirst: push xl push xh push yl push yh mov yl, xl mov yh, r17 mov xl, r16 mov xh, r17 rcall List_UnlinkObject ; (r16, r17, x) pop yh pop yl pop xh pop xl OBJ_RemoveLink_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_AddTimer @global ; ; @param Y pointer to object SRAM ; @param X pointer to timer ; @clobbers R16, R17 OBJ_AddTimer: ldd r16, Y+OBJ_OFFS_TIMERS_LO ldd r17, Y+OBJ_OFFS_TIMERS_HI tst r16 brne OBJ_AddTimer_addToExisting tst r17 brne OBJ_AddTimer_addToExisting ; empty list, new timer is first std Y+OBJ_OFFS_TIMERS_LO, xl std Y+OBJ_OFFS_TIMERS_HI, xh rjmp OBJ_AddTimer_end OBJ_AddTimer_addToExisting: push xl push xh push yl push yh mov yl, xl mov yh, xh mov xl, r16 mov xh, r17 rcall List_AddObject ; (r16, r17, x) pop yh pop yl pop xh pop xl OBJ_AddTimer_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_RemoveTimer @global ; ; @param Y pointer to object SRAM ; @param X pointer to timer ; @clobbers R16, R17 OBJ_RemoveTimer: ldd r16, Y+OBJ_OFFS_TIMERS_LO ldd r17, Y+OBJ_OFFS_TIMERS_HI cp r16, xl brne OBJ_RemoveTimer_notFirst cp r17, xh brne OBJ_RemoveTimer_notFirst clr r16 std Y+OBJ_OFFS_TIMERS_LO, r16 std Y+OBJ_OFFS_TIMERS_HI, r16 rjmp OBJ_RemoveTimer_end OBJ_RemoveTimer_notFirst: push xl push xh push yl push yh mov yl, xl mov yh, r17 mov xl, r16 mov xh, r17 rcall List_UnlinkObject ; (r16, r17, x) pop yh pop yl pop xh pop xl OBJ_RemoveTimer_end: ret ; @end ; --------------------------------------------------------------------------- ; @param r16 signal ; @param Y link ; @clobbers any, !X, !Y, !R18, !R19 objCheckEmitSignalForLink: ldd r17, Y+OBJ_LINK_OFFS_SIGNAL cp r16, r17 brne objCheckEmitSignalForLink_ret push yl push yh push xl push xh push r18 push r19 ldd r16, Y+OBJ_LINK_OFFS_SLOT ldd r17, Y+OBJ_LINK_OFFS_TARGET_LO ldd yh, Y+OBJ_LINK_OFFS_TARGET_HI mov yl, r17 rcall OBJ_Handler pop r19 pop r18 pop xh pop xl pop yh pop yl objCheckEmitSignalForLink_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine objFreeLinks ; ; @clobbers r16, r17, r18, r19, r24, r25, X objFreeLinks: push yl push yh ldd r16, Y+OBJ_OFFS_LINKS_LO ldd r17, Y+OBJ_OFFS_LINKS_HI clr r18 std Y+OBJ_OFFS_LINKS_LO, r18 std Y+OBJ_OFFS_LINKS_HI, r18 mov yl, r16 mov yh, r17 ldi zl, LOW(Obj_Link_free) ldi zh, HIGH(Obj_Link_free) rcall List_ForEveryObject ; (r16, r17, r18, r19, r24, r25, X, Y) pop yh pop yl ret ; @end ; --------------------------------------------------------------------------- ; @routine objFreeTimers ; ; @clobbers r16, r17, r18, r19, r24, r25, X objFreeTimers: push yl push yh ldd r16, Y+OBJ_OFFS_TIMERS_LO ldd r17, Y+OBJ_OFFS_TIMERS_HI clr r18 std Y+OBJ_OFFS_TIMERS_LO, r18 std Y+OBJ_OFFS_TIMERS_HI, r18 mov yl, r16 mov yh, r17 ldi zl, LOW(Obj_Timer_free) ldi zh, HIGH(Obj_Timer_free) rcall List_ForEveryObject ; (r16, r17, r18, r19, r24, r25, X, Y) pop yh pop yl ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_Link_new @global ; ; @return CF set if okay, cleared on error ; @return Y pointer to SRAM for link ; @clobbers r16, r17, X OBJ_Link_new: ldi r24, LOW(OBJ_LINK_SIZE) ldi r25, HIGH(OBJ_LINK_SIZE) bigcall Heap_Alloc brcc OBJ_Link_new_end mov yl, xl mov yh, xh clr r16 ldi r17, OBJ_LINK_SIZE bigcall Utils_FillSram ; (R17, X) rcall List_InitObject ; (R16) sec OBJ_Link_new_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_Link_free @global ; ; @param Y pointer to SRAM for link ; @clobbers r16, r17, r24, r25, X OBJ_Link_free: rcall List_FiniObject ; (R16) mov xl, yl mov xh, yh rcall Heap_free ; (r16, r17, r24, r25, X) clc ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_Timer_new @global ; ; @return CF set if okay, cleared on error ; @return Y pointer to SRAM for timer ; @clobbers r16, r17, X OBJ_Timer_new: ldi r24, LOW(TIMER_SIZE) ldi r25, HIGH(TIMER_SIZE) bigcall Heap_Alloc brcc OBJ_Timer_new_end mov yl, xl mov yh, xh clr r16 ldi r17, TIMER_SIZE bigcall Utils_FillSram ; (R17, X) rcall List_InitObject ; (R16) sec OBJ_Timer_new_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine OBJ_Timer_free @global ; ; @param Y pointer to SRAM for timer ; @clobbers r16, r17, r24, r25, X OBJ_Timer_free: rcall List_FiniObject ; (R16) mov xl, yl mov xh, yh bigcall Heap_free ; (r16, r17, r24, r25, X) clc ret ; @end