Files
aqhomecontrol/avr/modules/lcd2/gui2/base/widget.asm
2026-03-07 01:17:38 +01:00

1051 lines
27 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_WIDGET_ASM
#define AQH_AVR_GUI2_WIDGET_ASM
; ***************************************************************************
; defines
; Widget in flash
.equ WIDGET_OFFS_BEGIN = OBJECT_SIZE
.equ WIDGET_OFFS_X_LO = WIDGET_OFFS_BEGIN+0
.equ WIDGET_OFFS_X_HI = WIDGET_OFFS_BEGIN+1
.equ WIDGET_OFFS_Y_LO = WIDGET_OFFS_BEGIN+2
.equ WIDGET_OFFS_Y_HI = WIDGET_OFFS_BEGIN+3
.equ WIDGET_OFFS_WIDTH_LO = WIDGET_OFFS_BEGIN+4
.equ WIDGET_OFFS_WIDTH_HI = WIDGET_OFFS_BEGIN+5
.equ WIDGET_OFFS_HEIGHT_LO = WIDGET_OFFS_BEGIN+6
.equ WIDGET_OFFS_HEIGHT_HI = WIDGET_OFFS_BEGIN+7
.equ WIDGET_OFFS_STYLE_LO = WIDGET_OFFS_BEGIN+8 ; byte address (for LPM!)
.equ WIDGET_OFFS_STYLE_HI = WIDGET_OFFS_BEGIN+9
.equ WIDGET_OFFS_TMP_LO = WIDGET_OFFS_BEGIN+10
.equ WIDGET_OFFS_TMP_HI = WIDGET_OFFS_BEGIN+11
.equ WIDGET_SIZE = WIDGET_OFFS_BEGIN+12
; widget style object
.equ WIDGET_STYLE_OFFS_FRONTCOL_NORM = 0
.equ WIDGET_STYLE_OFFS_BACKCOL_NORM = 1
.equ WIDGET_STYLE_OFFS_BORDERCOL_NORM = 2
.equ WIDGET_STYLE_OFFS_SHADOWCOL_NORM = 3
.equ WIDGET_STYLE_OFFS_FRONTCOL_ACTIVATED = 4
.equ WIDGET_STYLE_OFFS_BACKCOL_ACTIVATED = 5
.equ WIDGET_STYLE_OFFS_BORDERCOL_ACTIVATED = 6
.equ WIDGET_STYLE_OFFS_SHADOWCOL_ACTIVATED = 7
.equ WIDGET_STYLE_OFFS_OUTERBORDERSIZE = 8
.equ WIDGET_STYLE_OFFS_SPACING = 9
.equ WIDGET_STYLE_OFFS_FONT_LO = 10
.equ WIDGET_STYLE_OFFS_FONT_HI = 11
.equ WIDGET_STYLE_OFFS_CHARWIDTH = 12
.equ WIDGET_STYLE_OFFS_CHARHEIGHT = 13
.equ WIDGET_STYLE_SIZE = 14
; widget opts_lo (bits 7 and 6 used by OBJECT_OPTSLO)
.equ WIDGET_OPTSLO_INPUT_BIT = 5 ; TOUCH, KEY
.equ WIDGET_OPTSLO_BORDER_BIT = 4
.equ WIDGET_OPTSLO_FILLX_BIT = 3
.equ WIDGET_OPTSLO_FILLY_BIT = 2
; widget opts_hi
.equ WIDGET_OPTSHI_CONTENT_XALIGN1_BIT = 7 ; (2 bit: left, right, center, filled)
.equ WIDGET_OPTSHI_CONTENT_XALIGN0_BIT = 6
.equ WIDGET_OPTSHI_CONTENT_YALIGN1_BIT = 5 ; (2 bit: top, bottom, center, filled)
.equ WIDGET_OPTSHI_CONTENT_YALIGN0_BIT = 4
; values for WIDGET_OPTSHI_CONTENT_XALIGN (2 bits)
.equ WIDGET_XALIGN_LEFT = 0
.equ WIDGET_XALIGN_RIGHT = 1
.equ WIDGET_XALIGN_CENTER = 2
.equ WIDGET_XALIGN_FILLED = 3
; values for WIDGET_OPTSHI_CONTENT_YALIGN (2 bits)
.equ WIDGET_YALIGN_TOP = 0
.equ WIDGET_YALIGN_BOTTOM = 1
.equ WIDGET_YALIGN_CENTER = 2
.equ WIDGET_YALIGN_FILLED = 3
; widget flags
.equ WIDGET_FLAGS_VISIBLE_BIT = 7
.equ WIDGET_FLAGS_TOUCH_BIT = 6
.equ WIDGET_FLAGS_DIRTY_BIT = 5
.equ WIDGET_FLAGS_LAYOUT_BIT = 4
.equ WIDGET_FLAGS_ACTIVATED_BIT = 3
.equ WIDGET_FLAGS_SELECTED_BIT = 2
; SDRAM data for signal WIDGET_SIGNAL_TOUCH
.equ WIDGET_TOUCH_OFFS_X_LO = 0
.equ WIDGET_TOUCH_OFFS_X_HI = 1
.equ WIDGET_TOUCH_OFFS_Y_LO = 2
.equ WIDGET_TOUCH_OFFS_Y_HI = 3
.equ WIDGET_TOUCH_OFFS_STATE = 4
.equ WIDGET_TOUCH_SIZE = 5
; signals
.equ WIDGET_SIGNAL_SHOW = OBJECT_SIGNAL_NEXTFREE+0
.equ WIDGET_SIGNAL_HIDE = OBJECT_SIGNAL_NEXTFREE+1
.equ WIDGET_SIGNAL_LAYOUT = OBJECT_SIGNAL_NEXTFREE+2
.equ WIDGET_SIGNAL_DRAW = OBJECT_SIGNAL_NEXTFREE+3
.equ WIDGET_SIGNAL_TOUCH = OBJECT_SIGNAL_NEXTFREE+4
.equ WIDGET_SIGNAL_CLICKED = OBJECT_SIGNAL_NEXTFREE+5
.equ WIDGET_SIGNAL_SETVALUE = OBJECT_SIGNAL_NEXTFREE+6
.equ WIDGET_SIGNAL_GETVALUE = OBJECT_SIGNAL_NEXTFREE+7
.equ WIDGET_SIGNAL_KEEPALIVE = OBJECT_SIGNAL_NEXTFREE+8
.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+9
; values for signals WIDGET_SIGNAL_SETVALUE and WIDGET_SIGNAL_GETVALUE
.equ WIDGET_VALUE_DEFAULT_WIDTH = 1
.equ WIDGET_VALUE_DEFAULT_HEIGHT = 2
.equ WIDGET_VALUE_NEXTFREE = 3
; args to Widget_AlignPos
.equ WIDGET_1DALIGN_END_BIT = 0
.equ WIDGET_1DALIGN_CENTER_BIT = 1
.equ WIDGET_1DALIGN_BORDER_BIT = 2
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine Widget_new @global
;
; @return CFLAG set of okay, cleared otherwise
; @return Y address of newly created object
; @param X parent widget
; @param r16 value for OBJECT_OFFS_OPTS_LO
; @param r17 value for OBJECT_OFFS_OPTS_HI
; @clobbers any
Widget_new:
ldi r24, LOW(WIDGET_SIZE)
ldi r25, HIGH(WIDGET_SIZE)
bigcall Object_Alloc ; (!r16, !r17, !X)
brcc Widget_new_ret
rcall Widget_Init ; (r16, r17, X)
sec
Widget_new_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Init @global
;
; @param Y address of object in SDRAM
; @param r16 value for OBJECT_OFFS_OPTS_LO
; @param r17 value for OBJECT_OFFS_OPTS_HI
; @param X parent widget (if any)
; @clobbers r16, r17, X
Widget_Init:
push xl
push xh
; call base class
bigcall OBJ_Init ; (r16, r17, X)
; clear widget-specific data
mov xl, yl
mov xh, yh
adiw xh:xl, WIDGET_OFFS_BEGIN
clr r16
ldi r17, (WIDGET_SIZE-WIDGET_OFFS_BEGIN)
bigcall Utils_FillSram ; (r17, X)
pop xh
pop xl
; set default signal map
ldi r16, LOW(Widget_DefaultSignalmap*2)
std Y+OBJECT_OFFS_SIGNALMAP_LO, r16
ldi r16, HIGH(Widget_DefaultSignalmap*2)
std Y+OBJECT_OFFS_SIGNALMAP_HI, r16
; set style
mov r16, xl
or r16, xh
breq Widget_Init_setDefaultStyle
; use style from parent
adiw xh:xl, WIDGET_OFFS_STYLE_LO
ld r16, X+
std Y+WIDGET_OFFS_STYLE_LO, r16
ld r16, X
std Y+WIDGET_OFFS_STYLE_HI, r16
sbiw xh:xl, (WIDGET_OFFS_STYLE_LO+1)
rjmp Widget_Init_setDefaultSize
Widget_Init_setDefaultStyle:
ldi r16, LOW(Widget_DefaultStyle*2)
std Y+WIDGET_OFFS_STYLE_LO, r16
ldi r16, HIGH(Widget_DefaultStyle*2)
std Y+WIDGET_OFFS_STYLE_HI, r16
Widget_Init_setDefaultSize:
; initial size: 1x1 px
ldi r16, 1
clr r17
std Y+WIDGET_OFFS_WIDTH_LO, r16
std Y+WIDGET_OFFS_WIDTH_HI, r17
std Y+WIDGET_OFFS_HEIGHT_LO, r16
std Y+WIDGET_OFFS_HEIGHT_HI, r17
; add to parent (if any)
mov r16, xl
or r16, xh
breq Widget_Init_ret
bigcall OBJ_AddChild ; (r18, r19)
; preset flags
ldd r16, Y+OBJECT_OFFS_FLAGS
sbr r16, (1<<WIDGET_FLAGS_DIRTY_BIT) | (1<<WIDGET_FLAGS_LAYOUT_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
Widget_Init_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Fini @global
;
; @param Y address of object in SDRAM
; @clobbers none
Widget_Fini:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Resize @global
;
; @param Y address of widget
; @param r9:r8 W
; @param r11:r10 H
; @clobbers r16
Widget_Resize:
std Y+WIDGET_OFFS_WIDTH_LO, r8
std Y+WIDGET_OFFS_WIDTH_HI, r9
std Y+WIDGET_OFFS_HEIGHT_LO, r10
std Y+WIDGET_OFFS_HEIGHT_HI, r11
ldd r16, Y+OBJECT_OFFS_FLAGS
ori r16, (1<<WIDGET_FLAGS_LAYOUT_BIT) | (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Move @global
;
; @param Y address of widget
; @param r5:r4 X0
; @param r7:r6 Y0
; @clobbers r16
Widget_Move:
std Y+WIDGET_OFFS_X_LO, r4
std Y+WIDGET_OFFS_X_HI, r5
std Y+WIDGET_OFFS_Y_LO, r6
std Y+WIDGET_OFFS_Y_HI, r7
ldd r16, Y+OBJECT_OFFS_FLAGS
ori r16, (1<<WIDGET_FLAGS_LAYOUT_BIT) | (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+OBJECT_OFFS_FLAGS, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetDefaultWidth @global
;
; @param Y address of widget
; @return r19:r18 default width of the widget
; @clobbers any, !Y
Widget_GetDefaultWidth:
ldi r16, WIDGET_SIGNAL_GETVALUE
ldi r17, WIDGET_VALUE_DEFAULT_WIDTH
bigcall OBJ_HandleSignal
brcs Widget_GetDefaultWidth_ret
ldi r18, 1
clr r19
Widget_GetDefaultWidth_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetDefaultHeight @global
;
; @param Y address of widget
; @return r19:r18 default height of the widget
; @clobbers any, !Y
Widget_GetDefaultHeight:
ldi r16, WIDGET_SIGNAL_GETVALUE
ldi r17, WIDGET_VALUE_DEFAULT_HEIGHT
bigcall OBJ_HandleSignal
brcs Widget_GetDefaultHeight_ret
ldi r18, 1
clr r19
Widget_GetDefaultHeight_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnDraw @global
;
; @param Y address of widget
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @clobbers any, !Y
Widget_OnDraw:
ldd r17, Y+OBJECT_OFFS_FLAGS
; check whether widget is visible
sbrs r17, WIDGET_FLAGS_VISIBLE_BIT
rjmp Widget_OnDraw_ret
; check whether widget is dirty
sbrs r17, WIDGET_FLAGS_DIRTY_BIT
rjmp Widget_OnDraw_ret
; clear dirty bit
cbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+OBJECT_OFFS_FLAGS, r17
; clear widget background
rcall Widget_Clear ; (any, !Y)
Widget_OnDraw_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnDrawNop @global
;
; @param Y address of widget
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @clobbers any, !Y
Widget_OnDrawNop:
ldd r17, Y+OBJECT_OFFS_FLAGS
; only clear dirty bit
cbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+OBJECT_OFFS_FLAGS, r17
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnLayout @global
;
; @param Y address of widget
; @return CFLAG set if signal handled
; @clobbers any, !Y
Widget_OnLayout:
ldd r17, Y+OBJECT_OFFS_FLAGS
; only clear layout bit
cbr r17, (1<<WIDGET_FLAGS_LAYOUT_BIT)
std Y+OBJECT_OFFS_FLAGS, r17
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnGetValue @global
;
; @param Y address of widget
; @param r17 value requested
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @return r19:r18 value
; @clobbers any, !Y
Widget_OnGetValue:
cpi r17, WIDGET_VALUE_DEFAULT_WIDTH
breq Widget_OnGetValue_getDefaultWidth
cpi r17, WIDGET_VALUE_DEFAULT_HEIGHT
breq Widget_OnGetValue_getDefaultHeight
clc
rjmp Widget_OnGetValue_ret
Widget_OnGetValue_getDefaultWidth:
Widget_OnGetValue_getDefaultHeight:
ldi r18, 1
clr r19
sec
Widget_OnGetValue_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Clear @global
;
; @param Y address of widget
; @clobbers any, !Y
Widget_Clear:
rcall widgetLoadDimsForFullWidget ; (none)
rcall Widget_MakeAbsPos ; (r16, r17, r18, r19)
rcall Widget_SelectColors ; (R16)
mov r2, r0 ; use background
mov r3, r1
bigcall Display_FillRect
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawBorder @global
;
; @param Y address of widget
; @clobbers any, !Y
Widget_DrawBorder:
rcall widgetLoadDimsForFullWidget ; (none)
rcall Widget_MakeAbsPos ; (R16, R17)
rcall Widget_SelectBorderColors ; (R16)
bigcall Display_DrawRect
Widget_DrawBorder_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_FillRect @global
;
; @param Y address of widget
; @param r3:r2 color
; @param r5:r4 X0
; @param r7:r6 Y0
; @param r9:r8 X1/W
; @param r11:r10 Y1/H
; @clobbers any, !Z
Widget_FillRect:
rcall Widget_MakeAbsPos ; (r16, r17, r18, r19)
mov r2, r0 ; use background
mov r3, r1
bigcall Display_FillRect
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawImage @global
;
; @param Y address of widget
; @param R1:R0 background color
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @param Z byte address pointer to image in FLASH (for LPM!)
; @clobbers all, !Y
Widget_DrawImage:
push yl
push yh
rcall widgetCalcAbsPosAndBorders ; (R16, R17)
bigcall ili9341ImageDraw
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawTextFlash @global
;
; @param Y address of widget
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @return Z pointer to next char to write if CFLAG clear
; @clobbers any, !Y
Widget_DrawTextFlash:
rcall Widget_SelectColors ; (R16)
rjmp Widget_DrawColoredTextFlash
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawTextRam @global
;
; @param Y address of widget
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @param X pointer to text in SDRAM
; @return CFLAG set if completely written
; @return X pointer to next char to write if CFLAG clear
; @clobbers any, !Y
Widget_DrawTextRam:
rcall Widget_SelectColors ; (R16)
rjmp Widget_DrawColoredTextRam
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawColoredTextFlash @global
;
; @param Y address of widget
; @param R1:R0 background color
; @param R3:R2 foreground color
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @param Z byte address pointer to text in flash (for LPM!)
; @return CFLAG set if completely written
; @return Z pointer to next char to write if CFLAG clear
; @clobbers any, !Y
Widget_DrawColoredTextFlash:
rcall widgetCalcAbsPosAndBorders ; (R16, R17)
Widget_DrawColoredTextFlash_loop:
lpm r16, Z
tst r16
sec
breq Widget_DrawColoredTextFlash_loopEnd
push zl
push zh
rcall widgetDrawChar ; (any, !Y, !R6, !R7, !R8, !R9, !R10, !R11)
pop zh
pop zl
brcc Widget_DrawColoredTextFlash_loopEnd
adiw zh:zl, 1
rjmp Widget_DrawColoredTextFlash_loop
Widget_DrawColoredTextFlash_loopEnd:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawColoredTextRam @global
;
; @param Y address of widget
; @param R1:R0 background color
; @param R3:R2 foreground color
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @param X pointer to text in SDRAM
; @return CFLAG set if completely written
; @clobbers any, !Y
Widget_DrawColoredTextRam:
rcall widgetCalcAbsPosAndBorders ; (R16, R17)
Widget_DrawColoredTextRam_loop:
ld r16, X
tst r16
sec
breq Widget_DrawColoredTextRam_loopEnd
push xl
push xh
rcall widgetDrawChar ; (any, !Y, !R6, !R7, !R8, !R9, !R10, !R11)
pop xh
pop xl
brcc Widget_DrawColoredTextRam_loopEnd
adiw xh:xl, 1
rjmp Widget_DrawColoredTextRam_loop
Widget_DrawColoredTextRam_loopEnd:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_MakeAbsPos @global
;
; @param Y address of widget
; @param r5:r4 X
; @param r7:r6 Y
; @clobbers r16, r17, r18, r19
Widget_MakeAbsPos:
push yl
push yh
Widget_MakeAbsPos_loop:
; adjust X
ldd r16, Y+WIDGET_OFFS_X_LO
ldd r17, Y+WIDGET_OFFS_X_HI
add r4, r16
adc r5, r17
; adjust Y
ldd r16, Y+WIDGET_OFFS_Y_LO
ldd r17, Y+WIDGET_OFFS_Y_HI
add r6, r16
adc r7, r17
; continue with parent
rcall OBJ_GetParent ; r19:r18=parent widget (none)
brcc Widget_MakeAbsPos_loopEnd
mov yl, r18
mov yh, r19
rjmp Widget_MakeAbsPos_loop
Widget_MakeAbsPos_loopEnd:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_SelectColors @global
;
; @param Y address of widget
; @return r1:r0 background color
; @return r3:r2 foreground color
; @clobbers R16
Widget_SelectColors:
push zl
push zh
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
ldd r16, Y+OBJECT_OFFS_FLAGS
sbrc r16, WIDGET_FLAGS_ACTIVATED_BIT
rjmp Widget_SelectColors_activated
adiw zh:zl, WIDGET_STYLE_OFFS_FRONTCOL_NORM
rjmp Widget_SelectColors_readColors
Widget_SelectColors_activated:
adiw zh:zl, WIDGET_STYLE_OFFS_FRONTCOL_ACTIVATED
Widget_SelectColors_readColors:
lpm r2, Z+ ; read foreground color
lpm r3, Z+
lpm r0, Z+ ; read background color
lpm r1, Z
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_SelectBorderColors @global
;
; @param Y address of widget
; @return r1:r0 border color
; @return r3:r2 shadow color
; @clobbers R16
Widget_SelectBorderColors:
push zl
push zh
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
ldd r16, Y+OBJECT_OFFS_FLAGS
sbrc r16, WIDGET_FLAGS_ACTIVATED_BIT
rjmp Widget_SelectBorderColors_activated
adiw zh:zl, WIDGET_STYLE_OFFS_BORDERCOL_NORM
rjmp Widget_SelectBorderColors_readColors
Widget_SelectBorderColors_activated:
adiw zh:zl, WIDGET_STYLE_OFFS_BORDERCOL_ACTIVATED
Widget_SelectBorderColors_readColors:
lpm r2, Z+ ; read border color
lpm r3, Z+
lpm r0, Z+ ; read shadow color
lpm r1, Z
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_CalcStringWidthFLASH
;
; @param Z pointer to text in FLASH
; @param R18 char width in px
; @return r13:r12 width of string
; @clobbers r16
Widget_CalcStringWidthFLASH:
clr r12
clr r13
push zl
push zh
Widget_CalcStringWidthFLASH_loop:
lpm r16, Z+
tst r16
breq Widget_CalcStringWidthFLASH_done
add r12, r18
adc r13, r18
sub r13, r18
rjmp Widget_CalcStringWidthFLASH_loop
Widget_CalcStringWidthFLASH_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AlignContentX @global
;
; @param Y address of widget
; @param R13:R12 width of object to align
; @return R5:R4 X
; @clobbers r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25
Widget_AlignContentX:
ldd r8, Y+WIDGET_OFFS_WIDTH_LO
ldd r9, Y+WIDGET_OFFS_WIDTH_HI
ldd r24, Y+OBJECT_OFFS_OPTS_LO
ldd r25, Y+OBJECT_OFFS_OPTS_HI
; align horizontally
clr r17
sbrc r24, WIDGET_OPTSLO_BORDER_BIT
ori r17, (1<<WIDGET_1DALIGN_BORDER_BIT)
mov r16, r25
andi r16, (1<<WIDGET_OPTSHI_CONTENT_XALIGN1_BIT) | (1<<WIDGET_OPTSHI_CONTENT_XALIGN0_BIT)
cpi r16, (WIDGET_XALIGN_RIGHT<<WIDGET_OPTSHI_CONTENT_XALIGN0_BIT)
brne Widget_AlignContentX_h1
ori r17, (1<<WIDGET_1DALIGN_END_BIT)
Widget_AlignContentX_h1:
cpi r16, (WIDGET_XALIGN_CENTER<<WIDGET_OPTSHI_CONTENT_XALIGN0_BIT)
brne Widget_AlignContentX_h2
ori r17, (1<<WIDGET_1DALIGN_CENTER_BIT)
Widget_AlignContentX_h2:
mov r18, r8 ; widget width
mov r19, r9
rcall Widget_AlignPos1D ; (r16, r18, r19)
mov r4, r22
mov r5, r23
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AlignContentY @global
;
; @param Y address of widget
; @param R13:R12 height of object to align
; @return R7:R6 Y
; @clobbers r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, r22, r23, r24, r25
Widget_AlignContentY:
ldd r10, Y+WIDGET_OFFS_HEIGHT_LO
ldd r11, Y+WIDGET_OFFS_HEIGHT_HI
ldd r24, Y+OBJECT_OFFS_OPTS_LO
ldd r25, Y+OBJECT_OFFS_OPTS_HI
; align vertically
clr r17
sbrc r24, WIDGET_OPTSLO_BORDER_BIT
ori r17, (1<<WIDGET_1DALIGN_BORDER_BIT)
mov r16, r24
andi r16, (1<<WIDGET_OPTSHI_CONTENT_YALIGN1_BIT) | (1<<WIDGET_OPTSHI_CONTENT_YALIGN0_BIT)
cpi r16, (WIDGET_YALIGN_BOTTOM<<WIDGET_OPTSHI_CONTENT_YALIGN0_BIT)
brne Widget_AlignContentY_v1
ori r17, (1<<WIDGET_1DALIGN_END_BIT)
Widget_AlignContentY_v1:
cpi r16, (WIDGET_YALIGN_CENTER<<WIDGET_OPTSHI_CONTENT_YALIGN0_BIT)
brne Widget_AlignContentY_v2
ori r17, (1<<WIDGET_1DALIGN_CENTER_BIT)
Widget_AlignContentY_v2:
mov r18, r10 ; widget height
mov r19, r11
rcall Widget_AlignPos1D ; (r16, r18, r19)
mov r6, r22
mov r7, r23
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AlignPos1D
;
; one-dimensional routine.
;
; @param R19:R18 size of target
; @param R13:R12 size of object to align
; @param
; @param R17 opts (bit 0: align end, bit 1: align center, bit 2: account for border)
; @return R23:R22 pos
; @clobbers r16, r18, r19
Widget_AlignPos1D:
clr r22
clr r23
sbrc r17, WIDGET_1DALIGN_BORDER_BIT
rcall Widget_AlignPos1D_subBordersFromSize
sbrc r17, WIDGET_1DALIGN_END_BIT
rcall Widget_AlignPos1D_alignEnd
sbrc r17, WIDGET_1DALIGN_CENTER_BIT
rcall Widget_AlignPos1D_alignCenter
sbrc r17, WIDGET_1DALIGN_BORDER_BIT
rcall Widget_AlignPos1D_addBordersToPos
Widget_AlignPos1D_ret:
ret
Widget_AlignPos1D_alignEnd:
mov r22, r18
mov r23, r19
sub r22, r12
sbc r23, r13
brcc Widget_AlignPos1D_ret
clr r22
clr r23
ret
Widget_AlignPos1D_alignCenter:
rcall Widget_AlignPos1D_alignEnd
lsr r23
ror r22
ret
Widget_AlignPos1D_subBordersFromSize:
subi r18, 4
sbci r19, 0
ret
Widget_AlignPos1D_addBordersToPos:
ldi r16, 2
add r22, r16
adc r23, r16
sub r23, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetCharWidth @global
;
; @param Y address of widget
; @return R16 character width with current font (in pixels)
; @clobbers none
Widget_GetCharWidth:
push zl
push zh
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
adiw zh:zl, WIDGET_STYLE_OFFS_CHARWIDTH
lpm r16, Z
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetCharHeight @global
;
; @param Y address of widget
; @return R16 character height with current font (in pixels)
; @clobbers none
Widget_GetCharHeight:
push zl
push zh
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
adiw zh:zl, WIDGET_STYLE_OFFS_CHARHEIGHT
lpm r16, Z
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine widgetDrawChar
;
; @param Y address of widget
; @param R16 char to write
; @param R5:R4 absolute X on screen (in display coords)
; @param R7:R6 absolute Y on screen (in display coords)
; @param R9:R8 first X pos right of windows (in display coords)
; @return CFLAG set if char printed, cleared otherwise
; @return R5:R4 X pos behind char
; @clobbers any, !Y, !R6, !R7, !R8, !R9, !R10, !R11
widgetDrawChar:
push yl
push yh
push r16
; get font and charWidth
ldd zl, Y+WIDGET_OFFS_STYLE_LO
ldd zh, Y+WIDGET_OFFS_STYLE_HI
adiw zh:zl, WIDGET_STYLE_OFFS_CHARWIDTH
lpm r18, Z
sbiw zh:zl, WIDGET_STYLE_OFFS_CHARWIDTH
adiw zh:zl, WIDGET_STYLE_OFFS_FONT_LO
lpm r19, Z+
lpm zh, Z
mov zl, r19
; check whether char fits into widget
clr r17
add r16, r4 ; char width+X
adc r17, r5
sub r16, r8 ; check against window width
sbc r17, r9
pop r16
brcc widgetDrawChar_done ; not fit, jmp
; draw char
push r8
push r9
push r10
push r11
push r18 ; save char width
bigcall Display_DrawChar
pop r18
pop r11
pop r10
pop r9
pop r8
; increment X
clr r16
add r4, r18
adc r5, r16
sec
widgetDrawChar_done:
pop yh
pop yl
ret
; @end
; ---------------------------------------------------------------------------
; @routine widgetLoadDimsForFullWidget
;
; @param Y address of widget
; @return r5:r4 X (0)
; @return r7:r6 Y (0)
; @return r9:r8 widget width
; @return r11:R10 widget height
; @clobbers none
widgetLoadDimsForFullWidget:
clr r4
clr r5
clr r6
clr r7
ldd r8, Y+WIDGET_OFFS_WIDTH_LO
ldd r9, Y+WIDGET_OFFS_WIDTH_HI
ldd r10, Y+WIDGET_OFFS_HEIGHT_LO
ldd r11, Y+WIDGET_OFFS_HEIGHT_HI
ret
; @end
; ---------------------------------------------------------------------------
; @routine widgetCalcAbsPosAndBorders
;
; @param Y address of widget
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @return R9:R8 first X pos right of widget
; @return R5:R4 X relative to screen
; @return R7:R6 Y relative to screen
; @return R9:R8 first X pos right of widget (abs)
; @return R11:R10 first Y pos below widget (abs)
; @clobbers r16, r17
widgetCalcAbsPosAndBorders:
rcall Widget_MakeAbsPos ; (R16, R17)
ldd r8, Y+WIDGET_OFFS_WIDTH_LO
ldd r9, Y+WIDGET_OFFS_WIDTH_HI
add r8, r4 ; convert width to first pos right of widget
adc r9, r5
ldd r10, Y+WIDGET_OFFS_HEIGHT_LO
ldd r11, Y+WIDGET_OFFS_HEIGHT_HI
add r10, r6
adc r11, r7 ; convert height to first pos below widget
ret
; @end
; ***************************************************************************
; data in FLASH
Widget_DefaultSignalmap:
; header
.dw Object_DefaultSignalmap ; next table to use
; entries
.db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDraw), HIGH(Widget_OnDraw)
.db 0, WIDGET_SIGNAL_LAYOUT, LOW(Widget_OnLayout), HIGH(Widget_OnLayout)
.db 0, WIDGET_SIGNAL_GETVALUE, LOW(Widget_OnGetValue), HIGH(Widget_OnGetValue) ; handle any value here
.db 0, 0, 0, 0 ; end of table
Widget_DefaultStyle:
.dw DISPLAY_COLOR_BLACK ; frontCol_norm
.dw DISPLAY_COLOR_LIGHTGREY ; backCol_norm
.dw DISPLAY_COLOR_BLACK ; borderCol_norm
.dw DISPLAY_COLOR_WHITE ; shadowCol_norm
.dw DISPLAY_COLOR_WHITE ; frontCol_activated
.dw DISPLAY_COLOR_NAVY ; backCol_activated
.dw DISPLAY_COLOR_BLACK ; borderCol_activated
.dw DISPLAY_COLOR_WHITE ; shadowCol_activated
.db 0, 1 ; outerBorderSize, innerBorderSize
.dw ili9341Font12x16_1*2 ; font
.db 12, 16 ; charWidth, charHeight
#endif