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