Files
aqhomecontrol/avr/common/tree.asm
2025-06-02 21:13:01 +02:00

227 lines
5.8 KiB
NASM

; ***************************************************************************
; 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. *
; ***************************************************************************
#ifndef AQH_AVR_COMMON_TREE_H
#define AQH_AVR_COMMON_TREE_H
; ***************************************************************************
; defs
.equ TREE_OFFS_LIST = 0
.equ TREE_OFFS_PARENT_LO = TREE_OFFS_LIST+LIST_SIZE
.equ TREE_OFFS_PARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1
.equ TREE_OFFS_CHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2
.equ TREE_OFFS_CHILD_HI = TREE_OFFS_LIST+LIST_SIZE+3
.equ TREE_SIZE = TREE_OFFS_LIST+LIST_SIZE+4
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine Tree_InitObject @global
; @param Y pointer to object to add
; @clobbers r16
Tree_InitObject:
rcall List_InitObject ; (R16)
clr r16 ; clear this->TREE data
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_PARENT_HI, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_LO, r16
std Y+TREE_OFFS_LIST+TREE_OFFS_CHILD_HI, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetParentObject @global
; @param Y pointer to object
; @return X pointer to parent object
; @clobbers none
Tree_GetParentObject:
ldd xl, Y+TREE_OFFS_PARENT_LO
ldd xh, Y+TREE_OFFS_PARENT_HI
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetFirstChildObject @global
; @param Y pointer to object
; @return X pointer to first child object
; @clobbers none
Tree_GetFirstChildObject:
ldd xl, Y+TREE_OFFS_CHILD_LO
ldd xh, Y+TREE_OFFS_CHILD_HI
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetLastChildObject @global
; @param Y pointer to object
; @return X pointer to last child object
; @clobbers none
Tree_GetLastChildObject:
ldd xl, Y+TREE_OFFS_CHILD_LO
ldd xh, Y+TREE_OFFS_CHILD_HI
mov r16, xl
or r16, xh
breq Tree_GetLastChildObject_ret
rcall List_GetLastObject
Tree_GetLastChildObject_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetNextSibling @global
; @param Y pointer to object
; @return X pointer to successor object
; @clobbers none
Tree_GetNextSibling:
rjmp List_GetNextObject
; @end
; ---------------------------------------------------------------------------
; @routine Tree_GetObjectBelow @global
; @param Y pointer to object
; @return X pointer to object below (or NULL)
; @clobbers r16
Tree_GetObjectBelow:
push yl
push yh
rcall treeGetObjectBelow
pop yh
pop yl
ret
treeGetObjectBelow:
rcall Tree_GetFirstChildObject
mov r16, xl
or r16, xh
brne treeGetObjectBelow_ret ; got one
rcall Tree_GetNextSibling
mov r16, xl
or r16, xh
brne treeGetObjectBelow_ret ; got one
rcall Tree_GetParentObject
mov r16, xl
or r16, xh
breq treeGetObjectBelow_ret ; no parent
mov yl, xl
mov yh, xh
rjmp treeGetObjectBelow ; try with parent
treeGetObjectBelow_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Tree_AddChildObject @global
; @param Y pointer to object to add
; @param X pointer to parent to add to
; @clobbers r16, r17, r18, x
Tree_AddChildObject:
std Y+TREE_OFFS_PARENT_LO, xl ; immediately store parent pointer
std Y+TREE_OFFS_PARENT_HI, xh
adiw xh:xl, TREE_OFFS_CHILD_LO ; read pointer to first child
ld r16, X+
ld r17, X
mov r18, r16
or r18, r17
brne Tree_AddChildObject_addToChildList
st X, yh ; no child, set THIS as first
st -X, yl
sbiw xh:xl, TREE_OFFS_CHILD_LO
ret
Tree_AddChildObject_addToChildList:
mov xl, r16 ; X=first child
mov xh, r17
rjmp List_AddObject ; add Y as new object
; @end
; ---------------------------------------------------------------------------
; @routine Tree_UnlinkObject @global
; @param Y pointer to object to remove
; @clobbers r16, r17, x
Tree_UnlinkObject:
ldd xl, Y+TREE_OFFS_PARENT_LO
ldd xh, Y+TREE_OFFS_PARENT_HI
mov r16, xl
or r16, xh
breq Tree_UnlinkObject_ret ; not part of a tree
adiw xh:xl, TREE_OFFS_CHILD_LO ; get parent's first child to R17:R16
ld r16, X+
ld r17, X
cp r16, yl ; same as THIS?
brne Tree_UnlinkObject_inList ; nope, need to check childList
cp r17, yh ; same as THIS?
brne Tree_UnlinkObject_inList ; nope, need to check childList
ldd r16, Y+TREE_OFFS_LIST+LIST_OFFS_NEXT_HI ; is first child, set this->NEXT as new first child
st X, r16
ldd r16, Y+TREE_OFFS_LIST+LIST_OFFS_NEXT_LO
st -X, r16
rjmp Tree_UnlinkObject_clrParentAndSibling
Tree_UnlinkObject_inList:
mov xl, r16
mov xh, r17
rcall List_UnlinkObject ; (R16, R17, X)
Tree_UnlinkObject_clrParentAndSibling:
clr r16 ; clear this->PARENT
std Y+TREE_OFFS_PARENT_LO, r16
std Y+TREE_OFFS_PARENT_HI, r16
std Y+LIST_OFFS_NEXT_LO, r16
std Y+LIST_OFFS_NEXT_HI, r16 ; clear this->NEXT
Tree_UnlinkObject_ret:
ret
; @end
#endif ; AQH_AVR_COMMON_TREE_H