Files
aqhomecontrol/avr/modules/lcd2/gui2/base/layout2.asm
Martin Preuss 87c2314c2d avr: started working on another iteration of the layout modules.
This will become a base module for other layout modules (like hlayout,
vlayout and mlayout). All those modules will share the playment code.
2026-04-07 23:57:28 +02:00

718 lines
18 KiB
NASM

; ***************************************************************************
; 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_LAYOUT2_ASM
#define AQH_AVR_GUI2_LAYOUT2_ASM
; ***************************************************************************
; defines
.equ LAYOUT_CTX_OFFS_TOTALSIZE_LO = 0
.equ LAYOUT_CTX_OFFS_TOTALSIZE_HI = 1
.equ LAYOUT_CTX_OFFS_BORDERS = 2
.equ LAYOUT_CTX_OFFS_SPACING = 3
.equ LAYOUT_CTX_OFFS_NUMITEMS = 4
.equ LAYOUT_CTX_OFFS_ITEMS = 6
.equ LAYOUT_CTX_ITEM_OFFS_POS_LO = 0
.equ LAYOUT_CTX_ITEM_OFFS_POS_HI = 1
.equ LAYOUT_CTX_ITEM_OFFS_SIZE_LO = 2
.equ LAYOUT_CTX_ITEM_OFFS_SIZE_HI = 3
.equ LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO = 4
.equ LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_HI = 5
.equ LAYOUT_CTX_ITEM_OFFS_FLAGS = 6
.equ LAYOUT_CTX_ITEM_SIZE = 7 ; CAVEAT: change code in LayoutCtx_new if size changed!
; ***************************************************************************
; macros
.macro M_LAYOUT_FOREVERY_CONT
push yl
push yh
ldi zl, LOW(@0)
ldi zh, HIGH(@0)
rcall layoutForEveryObjectContiguous
pop yh
pop yl
.endmacro
.macro M_LAYOUT_FOREVERY_SKIPPED
push yl
push yh
ldi zl, LOW(@0)
ldi zh, HIGH(@0)
rcall layoutForEveryObjectSkipped
pop yh
pop yl
.endmacro
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine LayoutCtx_new @global
;
; @param r16 number of entries to reserve
; @return X pointer to new layout context
; @clobbers r16, r17, r18, r19, r24, r25
LayoutCtx_new:
push r16
clr r17
mov r24, r16
mov r25, r17
lsl r24 ; x2
rol r25
add r24, r16
adc r25, r17 ; x3
lsl r24 ; x6
rol r25
add r24, r16
adc r25, r17 ; x7
ldi r16, LOW(LAYOUT_CTX_OFFS_ITEMS)
ldi r17, HIGH(LAYOUT_CTX_OFFS_ITEMS)
add r24, r16
adc r25, r17
; alloc on heap
push r24
push r25
bigcall Heap_Alloc ; (r16, r17, r18, r19, r24, r25)
pop r25
pop r24
pop r16
brcc LayoutCtx_new_ret
; preset with 0
push xl
push xh
clr r17
LayoutCtx_new_loop:
st X+, r17
sbiw r25:r24, 1
brne LayoutCtx_new_loop
pop xh
pop xl
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
st X, r16 ; store number of items
sbiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
sec
LayoutCtx_new_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_free @global
;
; @param X pointer to layout context
; @clobbers r16, r17, r24, r25, X
LayoutCtx_free:
bigjmp Heap_Free ; (r16, r17, r24, r25, X)
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_CalcMinimumSize
;
; Calculate minimum size needed for the given items (containing borders and
; spacings) by using the defaultSize fields of the items.
;
; @param X pointer to layout ctx object
; @return r19:r18 calculated size (including borders and spacings)
; @clobbers r16, r17, r22, r23, r24
LayoutCtx_CalcMinimumSize:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_BORDERS
ld r18, X+ ; borders (start calculated size with one border)
clr r19
ld r22, X+ ; spacing
clr r23
ld r24, X+ ; number of items (X now points to first item)
lsl r18 ; add border at beginning and end
rol r19
LayoutCtx_CalcMinimumSize_loop:
adiw xh:xl, LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO
ld r17, X ; LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_HI
adiw xh:xl, (LAYOUT_CTX_ITEM_SIZE-LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_HI)
add r18, r16 ; add size
adc r19, r17
add r18, r22 ; add spacing
adc r19, r23
dec r24
brne LayoutCtx_CalcMinimumSize_loop
sub r18, r22 ; sub last spacing
sbc r19, r23
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_ReadXDimsContiguous
;
; @param X pointer to ctx
; @param r25 number of widgets to handle
LayoutCtx_ReadXDimsContiguous:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_CONT layoutCtxCbCopyWidgetXToItem
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_ReadXDimsSkipped
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to skip in each round
LayoutCtx_ReadXDimsSkipped:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_SKIPPED layoutCtxCbCopyWidgetXToItem
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_WriteXDimsContiguous
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to handle
LayoutCtx_WriteXDimsContiguous:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_CONT layoutCtxCbCopyItemToWidgetX
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_WriteXDimsSkipped
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to skip in each round
LayoutCtx_WriteXDimsSkipped:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_SKIPPED layoutCtxCbCopyItemToWidgetX
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_ReadYDimsContiguous
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to handle
LayoutCtx_ReadYDimsContiguous:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_CONT layoutCtxCbCopyWidgetYToItem
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_ReadYDimsSkipped
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to skip in each round
LayoutCtx_ReadYDimsSkipped:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_SKIPPED layoutCtxCbCopyWidgetYToItem
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_WriteYDimsContiguous
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to handle
LayoutCtx_WriteYDimsContiguous:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_CONT layoutCtxCbCopyItemToWidgetY
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_WriteYDimsSkipped
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to skip in each round
LayoutCtx_WriteYDimsSkipped:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_SKIPPED layoutCtxCbCopyItemToWidgetY
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_SetDefaultWidthContiguous
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to handle
LayoutCtx_SetDefaultWidthContiguous:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_CONT layoutCtxCbsetDefaultWidth
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_SetDefaultWidthSkipped
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to skip in each round
LayoutCtx_SetDefaultWidthSkipped:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_SKIPPED layoutCtxCbsetDefaultWidth
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_SetDefaultHeightContiguous
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to handle
LayoutCtx_SetDefaultHeightContiguous:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_CONT layoutCtxCbsetDefaultHeight
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine LayoutCtx_SetDefaultHeightSkipped
;
; @param X pointer to ctx
; @param Y pointer to first widget to handle
; @param r25 number of widgets to skip in each round
LayoutCtx_SetDefaultHeightSkipped:
push xl
push xh
adiw xh:xl, LAYOUT_CTX_OFFS_NUMITEMS
ld r24, X+ ; X now points to first item
M_LAYOUT_FOREVERY_SKIPPED layoutCtxCbsetDefaultHeight
pop xh
pop xl
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutCtxCbCopyWidgetXToItem
;
; @param Y widget
; @param X item
; @param r24 number of items left in layout context
layoutCtxCbCopyWidgetXToItem:
tst r24
sec
breq layoutCtxCbCopyWidgetXToItem_ret
ldd r16, Y+WIDGET_OFFS_X_LO
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_POS_LO
ldd r16, Y+WIDGET_OFFS_X_HI
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_POS_HI
ldd r16, Y+WIDGET_OFFS_WIDTH_LO
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_SIZE_LO
ldd r16, Y+WIDGET_OFFS_WIDTH_HI
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_SIZE_HI
clr r16
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_HI
ldd r16, Y+WIDGET_OFFS_PACK
andi r16, (1<<WIDGET_PACK_HSELF0_BIT) | (1<<WIDGET_PACK_HSELF1_BIT)
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_FLAGS
dec r24
clc
layoutCtxCbCopyWidgetXToItem_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutCtxCbCopyItemToWidgetX
;
; @param Y widget
; @param X item
; @param r24 number of items left in layout context
layoutCtxCbCopyItemToWidgetX:
tst r24
sec
breq layoutCtxCbCopyItemToWidgetX_ret
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_POS_LO
std Y+WIDGET_OFFS_X_LO, r16
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_POS_HI
std Y+WIDGET_OFFS_X_HI, r16
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_SIZE_LO
std Y+WIDGET_OFFS_WIDTH_LO, r16
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_SIZE_HI
std Y+WIDGET_OFFS_WIDTH_HI, r16
adiw xh:xl, 3
dec r24
clc
layoutCtxCbCopyItemToWidgetX_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutCtxCbCopyWidgetYToItem
;
; @param Y widget
; @param X item
; @param r24 number of items left in layout context
layoutCtxCbCopyWidgetYToItem:
tst r24
sec
breq layoutCtxCbCopyWidgetYToItem_ret
ldd r16, Y+WIDGET_OFFS_Y_LO
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_POS_LO
ldd r16, Y+WIDGET_OFFS_Y_HI
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_POS_HI
ldd r16, Y+WIDGET_OFFS_HEIGHT_LO
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_SIZE_LO
ldd r16, Y+WIDGET_OFFS_HEIGHT_HI
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_SIZE_HI
clr r16
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_HI
ldd r16, Y+WIDGET_OFFS_PACK
andi r16, (1<<WIDGET_PACK_VSELF0_BIT) | (1<<WIDGET_PACK_VSELF1_BIT)
lsr r16
lsr r16
st X+, r16 ; LAYOUT_CTX_ITEM_OFFS_FLAGS
dec r24
clc
layoutCtxCbCopyWidgetYToItem_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutCtxCbCopyItemToWidgetY
;
; @param Y widget
; @param X item
; @param r24 number of items left in layout context
layoutCtxCbCopyItemToWidgetY:
tst r24
sec
breq layoutCtxCbCopyItemToWidgetY_ret
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_POS_LO
std Y+WIDGET_OFFS_Y_LO, r16
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_POS_HI
std Y+WIDGET_OFFS_Y_HI, r16
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_SIZE_LO
std Y+WIDGET_OFFS_HEIGHT_LO, r16
ld r16, X+ ; LAYOUT_CTX_ITEM_OFFS_SIZE_HI
std Y+WIDGET_OFFS_HEIGHT_HI, r16
adiw xh:xl, 3
dec r24
clc
layoutCtxCbCopyItemToWidgetY_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutCtxCbsetDefaultWidth
;
; @param Y widget
; @param X item
; @param r24 number of items left in layout context
layoutCtxCbsetDefaultWidth:
tst r24
sec
breq layoutCtxCbsetDefaultWidth_ret
push xl
push xh
push r24
bigcall Widget_GetDefaultWidth ; r19:r18=result
pop r24
pop xh
pop xl
adiw xh:xl, LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO
st X+, r18
st X, r19
adiw xh:xl, 2
dec r24
clc
layoutCtxCbsetDefaultWidth_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutCtxCbsetDefaultHeight
;
; @param Y widget
; @param X item
; @param r24 number of items left in layout context
layoutCtxCbsetDefaultHeight:
tst r24
sec
breq layoutCtxCbsetDefaultHeight_ret
push xl
push xh
push r24
bigcall Widget_GetDefaultHeight ; r19:r18=result
pop r24
pop xh
pop xl
adiw xh:xl, LAYOUT_CTX_ITEM_OFFS_DEFAULTSIZE_LO
st X+, r18
st X, r19
adiw xh:xl, 2
dec r24
clc
layoutCtxCbsetDefaultHeight_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutForEveryObjectContiguous
;
; This routine itself uses R18, R19, R25 and Y. All other registers may be
; passed to the callback routine.
; However, the callback function must make sure that it doesn't modify registers
; which are to be passed to next objects later!
;
; This routine traverses the given number of contiguous objects until there is no
; next object.
;
; Y and R25 are preserved around the callback. Z MUST NOT be modified by the callback!
;
; @param Y object to start with
; @param r25 number of widgets to handle (0=all)
; @param Z pointer to routine to call (using ICALL)
; @return CFLAG set if the callback returned with CFLAG set on any widget
; @return Y object on which the call returned with CFLAG set (otherwise last object handled)
; @clobbers r18, r19, Y {any}
layoutForEveryObjectContiguous:
push r25
mov r18, r25
layoutForEveryObjectContiguous_loop:
push r18
push r25
push yl
push yh
icall
pop yh
pop yl
pop r25
pop r18
brcs layoutForEveryObjectContiguous_ret
tst r18
breq layoutForEveryObjectContiguous_next
dec r18
clc
breq layoutForEveryObjectContiguous_ret
layoutForEveryObjectContiguous_next:
push r18
bigcall OBJ_GetNext
brcs layoutForEveryObjectContiguous_loopEnd
pop r18
rjmp layoutForEveryObjectContiguous_ret
layoutForEveryObjectContiguous_loopEnd:
mov yl, r18
mov yh, r19
pop r18
rjmp layoutForEveryObjectContiguous_loop
layoutForEveryObjectContiguous_ret:
pop r25
ret
; @end
; ---------------------------------------------------------------------------
; @routine layoutForEveryObjectSkipped
;
; This routine itself uses R18, R19, R25 and Y. All other registers may be
; passed to the callback routine.
; However, the callback function must make sure that it doesn't modify registers
; which are to be passed to next objects later!
;
; This routine traverses the given objects skipping [R25] objects after each round
; until there is no next object.
;
; Y and R25 are preserved around the callback. Z MUST NOT be modified by the callback!
;
; @param Y object to start with
; @param r25 number of widgets to skip per round
; @param Z pointer to routine to call (using ICALL)
; @return CFLAG set if the callback returned with CFLAG set on any widget
; @return Y object on which the call returned with CFLAG set (garbage otherwise)
; @clobbers r18, r19, Y {any}
layoutForEveryObjectSkipped:
layoutForEveryObjectSkipped_loop:
push r25
push yl
push yh
icall
pop yh
pop yl
pop r25
brcs layoutForEveryObjectSkipped_ret
push r16
mov r16, r25
bigcall OBJ_SkipObjects ; (R16)
pop r16
brcc layoutForEveryObjectSkipped_ret
mov yl, r18
mov yh, r19
rjmp layoutForEveryObjectSkipped_loop
layoutForEveryObjectSkipped_ret:
ret
; @end
#endif