From fa5acddcbe0c39e10889593c55ec609535643170 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Thu, 22 May 2025 23:19:33 +0200 Subject: [PATCH] avr: started working on prerequisites for a window gui system. --- avr/common/0BUILD | 2 + avr/common/list.asm | 166 ++++++++++++++++++++++ avr/common/tree.asm | 192 ++++++++++++++++++++++++++ avr/modules/lcd2/ili9341/graphops.asm | 1 - avr/modules/lcd2/win/defs.asm | 62 +++++++++ 5 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 avr/common/list.asm create mode 100644 avr/common/tree.asm create mode 100644 avr/modules/lcd2/win/defs.asm diff --git a/avr/common/0BUILD b/avr/common/0BUILD index 26bb9eb..6c79831 100644 --- a/avr/common/0BUILD +++ b/avr/common/0BUILD @@ -22,6 +22,8 @@ utils_wait_fixed.asm utils_wait_pin.asm watchdog.asm + list.asm + tree.asm diff --git a/avr/common/list.asm b/avr/common/list.asm new file mode 100644 index 0000000..93240ed --- /dev/null +++ b/avr/common/list.asm @@ -0,0 +1,166 @@ +; *************************************************************************** +; 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_LIST_H +#define AQH_AVR_COMMON_LIST_H + + +; --------------------------------------------------------------------------- +; This code implements a simple single-linked list. +; It assumes that the first 2 bytes of an object managed by this code contain +; a 2 byte pointer to the next object. +; --------------------------------------------------------------------------- + + + + +; *************************************************************************** +; defs + +.equ LIST_OFFS_NEXT_LO = 0 +.equ LIST_OFFS_NEXT_HI = 1 +.equ LIST_SIZE = 2 + + + + + +; *************************************************************************** +; code + +.cseg + + + +; --------------------------------------------------------------------------- +; @routine List_InitObject @global +; +; Reset list object fields. +; @param Y pointer to object +; @clobbers r16 + +List_InitObject: + clr r16 ; set this->NEXT to NULL + std Y+LIST_OFFS_NEXT_LO, r16 + std Y+LIST_OFFS_NEXT_HI, r16 + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine List_GetNextObject @global + +; @param Y pointer to object +; @return X pointer to parent object +; @clobbers none + +List_GetNextObject: + ldd xl, Y+LIST_OFFS_NEXT_LO + ldd xh, Y+LIST_OFFS_NEXT_HI + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine List_GetLastObject + +; @param X pointer to one object in a list +; @return X pointer to last object which has an empty NEXT pointer +; @clobbers r16, r17, X, Y + +List_GetLastObject: + clr yl + clr yh + rjmp List_GetPredecessorFor +; @end + + + +; --------------------------------------------------------------------------- +; @routine List_GetPredecessorFor + +; @param Y pointer to this object +; @param X pointer to first object in a list +; @return X pointer to object whose NEXT pointer points to the given object (or NULL) +; @clobbers r16, r17, X + +List_GetPredecessorFor: + mov r16, xl + or r16, xh + breq List_GetPredecessorFor_ret + ld r16, X+ + ld r17, X+ + cp r16, yl + brne List_GetPredecessorFor_next + cp r17, yh + breq List_GetLastObject_haveIt +List_GetPredecessorFor_next: + mov xl, r16 + mov xh, r17 + rjmp List_GetPredecessorFor +List_GetPredecessorFor_haveIt: + sbiw xh:xl, 1 +List_GetPredecessorFor_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine List_AddObject + +; @param X pointer to first object in a list +; @param Y pointer to object to add +; @clobbers r16, r17, x + +List_AddObject: + push yl + push yh + rcall List_GetLastObject ; (r16, r17, X, Y) + pop yh + pop yl + st X+, yl ; WID_OFFS_WNEXT_LO + st X+, yh ; WID_OFFS_WNEXT_HI + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine List_UnlinkObject + +; @param X pointer to first object in a list +; @param Y pointer to object to remove +; @clobbers r16, r17, x + +List_UnlinkObject: + push yl + push yh + rcall List_GetPredecessorFor ; (r16, r17, X) + pop yh + pop yl + mov r16, xl + or r16, xh + breq List_UnlinkObject_ret + ldd r16, Y+LIST_OFFS_NEXT_LO ; get this->NEXT + ldd r17, Y+LIST_OFFS_NEXT_HI + st X+, r16 ; store as NEXT in predecessor + st X, r17 + clr r16 ; set this->NEXT to NULL + std Y+LIST_OFFS_NEXT_LO, r16 + std Y+LIST_OFFS_NEXT_HI, r16 +List_UnlinkObject_ret: + ret +; @end + + + +#endif ; AQH_AVR_COMMON_LIST_H diff --git a/avr/common/tree.asm b/avr/common/tree.asm new file mode 100644 index 0000000..38e197a --- /dev/null +++ b/avr/common/tree.asm @@ -0,0 +1,192 @@ +; *************************************************************************** +; 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_WPARENT_LO = TREE_OFFS_LIST+LIST_SIZE +.equ TREE_OFFS_WPARENT_HI = TREE_OFFS_LIST+LIST_SIZE+1 +.equ TREE_OFFS_WCHILD_LO = TREE_OFFS_LIST+LIST_SIZE+2 +.equ TREE_OFFS_WCHILD_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_WPARENT_LO, r16 + std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_HI, r16 + std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_LO, r16 + std Y+TREE_OFFS_LIST+TREE_OFFS_WCHILD_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_WPARENT_LO + ldd xh, Y+TREE_OFFS_WPARENT_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_WCHILD_LO + ldd xh, Y+TREE_OFFS_WCHILD_HI + ret +; @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 List_GetNextObject + 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 X pointer to parent to add to +; @param Y pointer to object to add +; @clobbers r16, r17, r18, x + +Tree_AddChildObject: + std Y+TREE_OFFS_WPARENT_LO, xl ; immediately store parent pointer + std Y+TREE_OFFS_WPARENT_HI, xh + adiw xh:xl, TREE_OFFS_WCHILD_LO + 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, WID_OFFS_TREE+TREE_OFFS_WCHILD_LO + ret +Tree_AddChildObject_addToChildList: + mov xl, r16 + mov xh, r17 + rjmp List_AddObject +; @end + + + +; --------------------------------------------------------------------------- +; @routine Tree_UnlinkObject @global + +; @param Y pointer to object to remove +; @clobbers r16, r17, x + +Tree_UnlinkObject: + ldd xl, Y+TREE_OFFS_WPARENT_LO + ldd xh, Y+TREE_OFFS_WPARENT_HI + mov r16, xl + or r16, xh + breq Tree_UnlinkObject_ret ; not part of a tree + adiw xh:xl, TREE_OFFS_WCHILD_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 + 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_LIST+TREE_OFFS_WPARENT_LO, r16 + std Y+TREE_OFFS_LIST+TREE_OFFS_WPARENT_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 + diff --git a/avr/modules/lcd2/ili9341/graphops.asm b/avr/modules/lcd2/ili9341/graphops.asm index f280508..22aa62a 100644 --- a/avr/modules/lcd2/ili9341/graphops.asm +++ b/avr/modules/lcd2/ili9341/graphops.asm @@ -334,4 +334,3 @@ ili9341BitBlitStretchNWriteLine_loop2: - diff --git a/avr/modules/lcd2/win/defs.asm b/avr/modules/lcd2/win/defs.asm new file mode 100644 index 0000000..47092ed --- /dev/null +++ b/avr/modules/lcd2/win/defs.asm @@ -0,0 +1,62 @@ +; *************************************************************************** +; 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_WIN_H +#define AQH_AVR_WIN_H + + +; tree/list info +.equ WID_OFFS_TREE = 0 + +; signal handler +.equ WID_OFFS_HANDLERFN_LO = WID_OFFS_TREE+TREE_SIZE +.equ WID_OFFS_HANDLERFN_HI = WID_OFFS_HANDLERFN_LO+1 + +; widget description +.equ WID_OFFS_WIDGET_INFO = WID_OFFS_HANDLERFN_HI+1 +.equ WID_OFFS_OPTIONS1 = WID_OFFS_WIDGET_INFO+0 +.equ WID_OFFS_OPTIONS2 = WID_OFFS_WIDGET_INFO+1 +.equ WID_OFFS_ABS_X_LO = WID_OFFS_WIDGET_INFO+2 +.equ WID_OFFS_ABS_X_HI = WID_OFFS_WIDGET_INFO+3 +.equ WID_OFFS_ABS_Y_LO = WID_OFFS_WIDGET_INFO+4 +.equ WID_OFFS_ABS_Y_HI = WID_OFFS_WIDGET_INFO+5 +.equ WID_OFFS_REL_X_LO = WID_OFFS_WIDGET_INFO+6 +.equ WID_OFFS_REL_X_HI = WID_OFFS_WIDGET_INFO+7 +.equ WID_OFFS_REL_Y_LO = WID_OFFS_WIDGET_INFO+8 +.equ WID_OFFS_REL_Y_HI = WID_OFFS_WIDGET_INFO+9 +.equ WID_OFFS_WIDTH_LO = WID_OFFS_WIDGET_INFO+10 +.equ WID_OFFS_WIDTH_HI = WID_OFFS_WIDGET_INFO+11 +.equ WID_OFFS_HEIGHT_LO = WID_OFFS_WIDGET_INFO+12 +.equ WID_OFFS_HEIGHT_HI = WID_OFFS_WIDGET_INFO+13 +.equ WID_OFFS_BG_COL_LO = WID_OFFS_WIDGET_INFO+14 +.equ WID_OFFS_BG_COL_HI = WID_OFFS_WIDGET_INFO+15 +.equ WID_OFFS_FG_COL_LO = WID_OFFS_WIDGET_INFO+16 +.equ WID_OFFS_FG_COL_HI = WID_OFFS_WIDGET_INFO+17 +.equ WID_OFFS_FONT_LO = WID_OFFS_WIDGET_INFO+18 +.equ WID_OFFS_FONT_HI = WID_OFFS_WIDGET_INFO+19 + +.equ WID_SIZE = WID_OFFS_WIDGET_INFO+20 + + + +.equ WID_OPTIONS1_BIT_DIRTY = 0 +.equ WID_OPTIONS1_BIT_LAYOUT = 1 + +.equ WID_OPTIONS1_BIT_STRETCH_X = 2 +.equ WID_OPTIONS1_BIT_STRETCH_Y = 3 + +.equ WID_OPTIONS1_BIT_ALIGN_LEFT = 4 +.equ WID_OPTIONS1_BIT_ALIGN_RIGHT = 5 + +.equ WID_OPTIONS1_BIT_ALIGN_TOP = 6 +.equ WID_OPTIONS1_BIT_ALIGN_BOTTOM = 7 + + +#endif ; AQH_AVR_WIN_H +