Files
aqhomecontrol/avr/modules/lcd2/gui2/widget.asm
2026-01-17 17:15:48 +01:00

1033 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_WIDGET = OBJECT_SIZE
.equ WIDGET_OFFS_OPTS_LO = WIDGET_OFFS_WIDGET+0
.equ WIDGET_OFFS_OPTS_HI = WIDGET_OFFS_WIDGET+1
.equ WIDGET_OFFS_X_LO = WIDGET_OFFS_WIDGET+2
.equ WIDGET_OFFS_X_HI = WIDGET_OFFS_WIDGET+3
.equ WIDGET_OFFS_Y_LO = WIDGET_OFFS_WIDGET+4
.equ WIDGET_OFFS_Y_HI = WIDGET_OFFS_WIDGET+5
.equ WIDGET_OFFS_WIDTH_LO = WIDGET_OFFS_WIDGET+6
.equ WIDGET_OFFS_WIDTH_HI = WIDGET_OFFS_WIDGET+7
.equ WIDGET_OFFS_HEIGHT_LO = WIDGET_OFFS_WIDGET+8
.equ WIDGET_OFFS_HEIGHT_HI = WIDGET_OFFS_WIDGET+9
.equ WIDGET_OFFS_FRONTCOL_LO = WIDGET_OFFS_WIDGET+10
.equ WIDGET_OFFS_FRONTCOL_HI = WIDGET_OFFS_WIDGET+11
.equ WIDGET_OFFS_BACKCOL_LO = WIDGET_OFFS_WIDGET+12
.equ WIDGET_OFFS_BACKCOL_HI = WIDGET_OFFS_WIDGET+13
.equ WIDGET_OFFS_FONT_LO = WIDGET_OFFS_WIDGET+14
.equ WIDGET_OFFS_FONT_HI = WIDGET_OFFS_WIDGET+15
.equ WIDGET_OFFS_SDRAM_LO = WIDGET_OFFS_WIDGET+16
.equ WIDGET_OFFS_SDRAM_HI = WIDGET_OFFS_WIDGET+17
.equ WIDGET_SIZE = WIDGET_OFFS_WIDGET+18
; SDRAM data for widget
.equ WIDGET_SD_OFFS_FLAGS = 0
.equ WIDGET_SD_SIZE = 1
; widget opts_lo
.equ WIDGETS_OPTSLO_BORDER_BIT = 7
.equ WIDGETS_OPTSLO_INPUT_BIT = 6 ; TOUCH, KEY
.equ WIDGETS_OPTSLO_TIMER_BIT = 5
.equ WIDGETS_OPTSLO_MSGRECV_BIT = 4
; widget flags
.equ WIDGET_FLAGS_ACTIVE_BIT = 7
.equ WIDGET_FLAGS_TOUCH_BIT = 6
.equ WIDGET_FLAGS_DIRTY_BIT = 5
.equ WIDGET_FLAGS_PRESSED_BIT = 4
; SDRAM data for signal WIDGET_SIGNAL_TOUCH
.equ WIDGET_DATA_TOUCH_OFFS_X_LO = 0
.equ WIDGET_DATA_TOUCH_OFFS_X_HI = 1
.equ WIDGET_DATA_TOUCH_OFFS_Y_LO = 2
.equ WIDGET_DATA_TOUCH_OFFS_Y_HI = 3
.equ WIDGET_DATA_TOUCH_OFFS_STATE = 4
.equ WIDGET_DATA_TOUCH_SIZE = 5
; signals
.equ WIDGET_SIGNAL_SHOW = OBJECT_SIGNAL_NEXTFREE+0
.equ WIDGET_SIGNAL_HIDE = OBJECT_SIGNAL_NEXTFREE+1
.equ WIDGET_SIGNAL_DRAW = OBJECT_SIGNAL_NEXTFREE+2
.equ WIDGET_SIGNAL_TOUCH = OBJECT_SIGNAL_NEXTFREE+3
.equ WIDGET_SIGNAL_CLICKED = OBJECT_SIGNAL_NEXTFREE+4
.equ WIDGET_SIGNAL_NEXTFREE = OBJECT_SIGNAL_NEXTFREE+5
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine Widget_Init @global
;
; @param Z byte address of widget object (for LPM!)
Widget_Init:
rcall Widget_GetSdramPtr ; (none)
clr r16
ori r16, (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+WIDGET_SD_OFFS_FLAGS, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnCreate @global
;
; @param Z byte address of widget object (for LPM!)
; @return CFLAG set if signal handled
; @clobbers any, !Z
Widget_OnCreate:
rcall Widget_Init
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnTouch @global
;
; @param Z byte address of widget object (for LPM!)
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @clobbers any, !Z
Widget_OnTouch:
; check whether inputs are handled by this widget
adiw zh:zl, WIDGET_OFFS_OPTS_LO
lpm r16, Z
sbiw zh:zl, WIDGET_OFFS_OPTS_LO
andi r16, (1<<WIDGETS_OPTSLO_INPUT_BIT)
clc
breq Widget_OnTouch_ret
rcall Widget_GetSdramPtr
; check whether widget is active
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
andi r17, (1<<WIDGET_FLAGS_ACTIVE_BIT)
breq Widget_OnTouch_secRet ; nope, jmp
; read touch signal data from X
ld r18, X+ ; WIDGET_DATA_TOUCH_OFFS_X_LO
ld r19, X+ ; WIDGET_DATA_TOUCH_OFFS_X_HI
ld r20, X+ ; WIDGET_DATA_TOUCH_OFFS_Y_LO
ld r21, X+ ; WIDGET_DATA_TOUCH_OFFS_Z_HI
ld r22, X+ ; WIDGET_DATA_TOUCH_OFFS_STATE
; check for change of touch press
mov r16, r22
andi r16, (1<<DISPLAY_IFLAGS_CHGPRESS_BIT)
breq Widget_OnTouch_secRet ; no press change, jmp
; check for position inside this widget
rcall Widget_LoadDisplayRegs ; (R0-R11)
rcall Widget_IsPointInRect ; (R16, R17)
sbci r16, 0 ; r16=ff if touched inside, 0 otherwise
; touch changed, check whether touch came down or up
mov r18, r22
andi r18, (1<<DISPLAY_IFLAGS_PRESSED_BIT)
breq Widget_OnTouch_up
; touch came down
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
andi r17, (1<<WIDGET_FLAGS_PRESSED_BIT)
brne Widget_OnTouch_secRet ; already down
tst r16 ; down inside this widget?
brne Widget_OnTouch_secRet ; nope, jmp
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
ori r17, (1<<WIDGET_FLAGS_PRESSED_BIT) | (1<<WIDGET_FLAGS_DIRTY_BIT) ; up, dirty
std Y+WIDGET_SD_OFFS_FLAGS, r17
rjmp Widget_OnTouch_secRet
Widget_OnTouch_up:
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
andi r17, (1<<WIDGET_FLAGS_PRESSED_BIT)
breq Widget_OnTouch_secRet ; already up
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
cbr r17, (1<<WIDGET_FLAGS_PRESSED_BIT) ; up
ori r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+WIDGET_SD_OFFS_FLAGS, r17
tst r16 ; was touch lost inside this widget?
brne Widget_OnTouch_secRet ; nope, jmp
; emit "CLICKED" signal
ldi r16, WIDGET_SIGNAL_CLICKED
rcall OBJ_EmitSignal
Widget_OnTouch_secRet:
sec
Widget_OnTouch_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnDraw @global
;
; @param Z byte address of widget object (for LPM!)
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @clobbers any, !Z
Widget_OnDraw:
rcall Widget_GetSdramPtr
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
; check whether widget is active
clc
sbrs r17, WIDGET_FLAGS_ACTIVE_BIT
rjmp Widget_OnDraw_ret
; check whether widget is dirty
sec
sbrs r17, WIDGET_FLAGS_DIRTY_BIT
rjmp Widget_OnDraw_ret
; clear dirty bit
cbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+WIDGET_SD_OFFS_FLAGS, r17
; clear widget background
rcall Widget_Clear
Widget_OnDraw_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_OnDrawNop @global
;
; this routine only clears the DIRTY bit
;
; @param Z byte address of widget object (for LPM!)
; @param xl param1
; @param xh param2
; @return CFLAG set if signal handled
; @clobbers any, !Z
Widget_OnDrawNop:
rcall Widget_GetSdramPtr
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
cbr r17, (1<<WIDGET_FLAGS_DIRTY_BIT)
std Y+WIDGET_SD_OFFS_FLAGS, r17
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_IsPointInRect @global
;
; @param R19:R18 check X
; @param R21:R20 check Y
; @param R5:R4 widget X
; @param R7:R6 widget Y
; @param R9:R8 widget width
; @param R11:R10 widget height
; @return CFLAG set if inside rect, cleared otherwise
; @clobbers R16, R17
Widget_IsPointInRect:
; check X
mov r16, r18 ; checkX-widgetX
mov r17, r19
sub r16, r4
sbc r17, r5
brcs Widget_IsPointInRect_no
sub r16, r8 ; sub width
sbc r17, r9
brcc Widget_IsPointInRect_no
mov r16, r20 ; checkY-widgetY
mov r17, r21
sub r16, r8
sbc r17, r9
brcs Widget_IsPointInRect_no
sub r16, r10 ; sub height
sbc r17, r11
brcc Widget_IsPointInRect_no
sec ; is inside rect
rjmp Widget_IsPointInRect_ret
Widget_IsPointInRect_no:
clc
Widget_IsPointInRect_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_LoadDisplayRegs @global
;
; @param Z byte address of widget object (for LPM!)
; @return R1:R0 background color
; @return R3:R2 foreground color
; @return R5:R4 X
; @return R7:R6 Y
; @return R9:R8 widget width
; @return R11:R10 widget height
; @clobbers none
Widget_LoadDisplayRegs:
push zl
push zh
adiw zh:zl, WIDGET_OFFS_X_LO
lpm r4, Z+ ; X_LO
lpm r5, Z+
lpm r6, Z+ ; Y_LO
lpm r7, Z+
lpm r8, Z+ ; WIDTH_LO
lpm r9, Z+
lpm r10, Z+ ; HEIGHT_LO
lpm r11, Z+
lpm r2, Z+ ; FRONTCOL_LO
lpm r3, Z+
lpm r0, Z+ ; BACKCOL_LO
lpm r1, Z+
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_GetSdramPtr @global
;
; @param Z byte address of widget object (for LPM!)
; @return Y pointer to SDRAM data for widget
; @clobbers none
Widget_GetSdramPtr:
adiw zh:zl, WIDGET_OFFS_SDRAM_LO
lpm yl, Z+
lpm yh, Z
sbiw zh:zl, WIDGET_OFFS_SDRAM_LO+1
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AddFlagsDown @global
;
; @param Z byte address of widget object (for LPM!)
; @param R16 flags to add
; @clobbers R17, R18, R19, R22, R23, Y
Widget_AddFlagsDown:
rcall OBJ_IsObject
brcc Widget_AddFlagsDown_ret
rcall Widget_AddFlags ; (R17, R22, R23)
push zl
push zh
bigcall OBJ_GetFirstChild ; R19:R18=next object
Widget_AddFlagsDown_loop:
brcc Widget_AddFlagsDown_loopEnd
mov zl, r18
mov zh, r19
rcall Widget_AddFlagsDown
rcall OBJ_GetNext
rjmp Widget_AddFlagsDown_loop
Widget_AddFlagsDown_loopEnd:
pop zh
pop zl
Widget_AddFlagsDown_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_SubFlagsDown @global
;
; @param Z byte address of widget object (for LPM!)
; @param R16 flags to add
; @clobbers R17, R18, R19, R22, R23
Widget_SubFlagsDown:
rcall OBJ_IsObject ; (none)
brcc Widget_SubFlagsDown_ret
rcall Widget_SubFlags ; (R17)
push zl
push zh
bigcall OBJ_GetFirstChild ; R19:R18=next object
Widget_SubFlagsDown_loop:
brcc Widget_SubFlagsDown_loopEnd
mov zl, r18
mov zh, r19
rcall Widget_SubFlagsDown
rcall OBJ_GetNext
rjmp Widget_SubFlagsDown_loop
Widget_SubFlagsDown_loopEnd:
pop zh
pop zl
Widget_SubFlagsDown_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_AddFlags @global
;
; @param Z byte address of widget object (for LPM!)
; @param R16 flags to add
; @clobbers R17, R22, R23
Widget_AddFlags:
rcall OBJ_IsObject
brcc Widget_AddFlags_ret
push yl
push yh
rcall Widget_GetSdramPtr ; (none)
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
or r17, r16
std Y+WIDGET_SD_OFFS_FLAGS, r17
pop yh
pop yl
Widget_AddFlags_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_SubFlags @global
;
; @param Z byte address of widget object (for LPM!)
; @param R16 flags to clear
; @clobbers R17
Widget_SubFlags:
mov r17, zl
or r17, zh
breq Widget_SubFlags_ret
push yl
push yh
rcall Widget_GetSdramPtr ; (none)
ldd r17, Y+WIDGET_SD_OFFS_FLAGS
com r16 ; one's-complement
and r17, r16
com r16
std Y+WIDGET_SD_OFFS_FLAGS, r17
pop yh
pop yl
Widget_SubFlags_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Clear @global
;
; @param Z byte address of widget object (for LPM!)
Widget_Clear:
rcall Widget_LoadDisplayRegs
rcall Widget_GetSdramPtr ; (none)
adiw zh:zl, WIDGET_OFFS_OPTS_LO ; get OPTS low
lpm r14, Z
sbiw zh:zl, WIDGET_OFFS_OPTS_LO
rcall Widget_SelectColors ; (R16)
mov r2, r0 ; use background
mov r3, r1
bigcall Display_FillRect
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_SelectColors @global
;
; @param Z byte address of widget object (for LPM!)
; @param Y pointer to Widget data in SDRAM
; @return r1:r0 background color
; @return r3:r2 foreground color
; @clobbers R16
Widget_SelectColors:
ldd r16, Y+WIDGET_SD_OFFS_FLAGS ; flags
andi r16, (1<<WIDGET_FLAGS_PRESSED_BIT)
brne Widget_SelectColors_pressed
push zl
push zh
adiw zh:zl, WIDGET_OFFS_FRONTCOL_LO
lpm r2, Z+
lpm r3, Z+
lpm r0, Z+
lpm r1, Z
pop zh
pop zl
rjmp Widget_SelectColors_ret
Widget_SelectColors_pressed:
; background color
ldi r16, LOW(STYLE_BUTTON_COL_BG_PRESSED)
mov r0, r16
ldi r16, HIGH(STYLE_BUTTON_COL_BG_PRESSED)
mov r1, r16
; foreground color
ldi r16, LOW(STYLE_BUTTON_COL_FG_PRESSED)
mov r2, r16
ldi r16, HIGH(STYLE_BUTTON_COL_FG_PRESSED)
mov r3, r16
Widget_SelectColors_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_MakeAbsPos @global
;
; @param Z byte address of widget object (for LPM!)
; @param r5:r4 X0
; @param r7:r6 Y0
; @clobbers r16, r17
Widget_MakeAbsPos:
push zl
push zh
push r18
push r19
Widget_MakeAbsPos_loop:
adiw zh:zl, WIDGET_OFFS_X_LO
lpm r16, Z+
lpm r17, Z+
add r4, r16 ; adjust X
adc r5, r17
lpm r16, Z+
lpm r17, Z
add r6, r16 ; adjust Y
adc r7, r17
sbiw zh:zl, WIDGET_OFFS_X_LO+3
rcall OBJ_GetParent
brcc Widget_MakeAbsPos_loopEnd
mov zl, r18
mov zh, r19
rjmp Widget_MakeAbsPos_loop
Widget_MakeAbsPos_loopEnd:
pop r19
pop r18
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_FillRect @global
;
; @param Z byte address of widget object (for LPM!)
; @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)
bigcall Display_FillRect ; directly call graphics function
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawBorder @global
;
; @param Z byte address of widget object (for LPM!)
; @param r3:r2 color
; @clobbers any, !Z
Widget_DrawBorder:
clr r6
clr r7
clr r8
clr r9
rcall Widget_MakeAbsPos ; (R16, R17)
bigcall Display_DrawRect
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawImage @global
;
; @param Z byte address of widget object (for LPM!)
; @param R1:R0 background color
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @param R13:R12 byte address pointer to image in FLASH (for LPM!)
Widget_DrawImage:
rcall widgetCalcAbsPosAndBorders
push zl
push zh
mov zl, r12
mov zh, r13
bigcall ili9341ImageDraw
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawTextFlash @global
;
; @param Z byte address of widget object (for LPM!)
; @param R5:R4 X relative to widget
; @param R7:R6 Y relative to widget
; @param R13:R12 byte address pointer to text in flash (for LPM!)
; @clobbers any, !Z
Widget_DrawTextFlash:
rcall Widget_GetSdramPtr ; (none)
rcall Widget_SelectColors
rjmp Widget_DrawColoredTextFlash
; @end
; ---------------------------------------------------------------------------
; @routine Widget_DrawColoredTextFlash @global
;
; @param Z byte address of widget object (for LPM!)
; @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 R13:R12 byte address pointer to text in flash (for LPM!)
; @clobbers any, !Z
Widget_DrawColoredTextFlash:
rcall widgetCalcAbsPosAndBorders
Widget_DrawColoredTextFlash_loop:
push zl
push zh
mov zl, r12
mov zh, r13
lpm r16, Z
pop zh
pop zl
tst r16
breq Widget_DrawColoredTextFlash_loopEnd
rcall widgetDrawChar
brcc Widget_DrawColoredTextFlash_loopEnd
ldi r16, 1
add r12, r16
adc r13, r12
sub r13, r12
rjmp Widget_DrawColoredTextFlash_loop
Widget_DrawColoredTextFlash_loopEnd:
ret
; @end
; ---------------------------------------------------------------------------
; @routine widgetCalcAbsPosAndBorders
;
; @param Z byte address of widget object (for LPM!)
; @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:
push zl
push zh
rcall Widget_MakeAbsPos ; (R16, R17)
adiw zh:zl, WIDGET_OFFS_WIDTH_LO
lpm r8, Z+ ; WIDTH_LO
lpm r9, Z+
add r8, r4 ; convert width to first pos right of widget
adc r9, r5
lpm r10, Z+ ; HEIGHT_LO
lpm r11, Z+
add r10, r6 ; convert height to first pos below widget
adc r11, r7
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine widgetDrawChar
;
; @param Z byte address of widget object (for LPM!)
; @param R16 char to write
; @param R5:R4 absolute X on screen
; @param R7:R6 absolute Y on screen
; @param R9:R8 first X pos right of windows
; @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 zl
push zh
; save R16 (char to write)
mov r14, r16
; get font to Z
adiw zh:zl, WIDGET_OFFS_FONT_LO
lpm r18, Z+
lpm zh, Z
mov zl, r18
or r18, zh
clc
breq widgetDrawChar_done
; check whether the char fits inside window
bigcall FONT_GetCharWidth ; r16=char width
clr r17
add r16, r4 ; char width+X
adc r17, r5
sub r16, r8 ; check against window width
sbc r17, r9
brcc widgetDrawChar_done ; not fit, jmp
; actually draw char
mov r16, r14
push r8
push r9
push r10
push r11
bigcall Display_DrawChar
pop r11
pop r10
pop r9
pop r8
clr r16
add r4, r18 ; increment X
adc r5, r16
sec ; write succeeded
widgetDrawChar_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Tree_Init @global
;
; @param Z byte address of root widget object (for LPM!)
Widget_Tree_Init:
push zl
push zh
Widget_Tree_Init_loop:
mov r16, zl
or r16, zh
breq Widget_Tree_Init_loopEnd
rcall Widget_Init
bigcall OBJ_GetBelow
mov zl, r18
mov zh, r19
rjmp Widget_Tree_Init_loop
Widget_Tree_Init_loopEnd:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Tree_SendDrawSignal @global
;
; @param Z byte address of root widget object (for LPM!)
Widget_Tree_SendDrawSignal:
ldi r16, WIDGET_SIGNAL_DRAW
clr r17
; only let active and dirty widgets draw
ldi r20, (1<<WIDGET_FLAGS_DIRTY_BIT)
ldi r21, (1<<WIDGET_FLAGS_DIRTY_BIT)
rcall Widget_TreeMatchFlagsAndSendSignalToActive
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Tree_SendTouchSignal @global
;
; @param Z byte address of root widget object (for LPM!)
; @param X pointer to touch event datain SDRAM
Widget_Tree_SendTouchSignal:
ldi r16, WIDGET_SIGNAL_TOUCH
clr r17
; only check active widgets
ldi r20, (1<<WIDGETS_OPTSLO_INPUT_BIT)
ldi r21, (1<<WIDGETS_OPTSLO_INPUT_BIT)
rcall Widget_TreeMatchOptsAndSendSignal
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Tree_SendTimerSignal @global
;
; @param Z byte address of root widget object (for LPM!)
Widget_Tree_SendTimerSignal:
ldi r16, OBJECT_SIGNAL_TIMER
clr r17
; only check active widgets
ldi r20, (1<<WIDGETS_OPTSLO_TIMER_BIT)
ldi r21, (1<<WIDGETS_OPTSLO_TIMER_BIT)
rcall Widget_TreeMatchOptsAndSendSignal
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_Tree_SendMsgRecvSignal @global
;
; @param Z byte address of root widget object (for LPM!)
; @param X pointer to received message in SDRAM
Widget_Tree_SendMsgRecvSignal:
ldi r16, OBJECT_SIGNAL_RECVMSG
clr r17
; only check active widgets
ldi r20, (1<<WIDGETS_OPTSLO_MSGRECV_BIT)
ldi r21, (1<<WIDGETS_OPTSLO_MSGRECV_BIT)
rcall Widget_TreeMatchOptsAndSendSignal
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_TreeMatchOptsAndSendSignal @global
;
; Send signal to all widgets whose WIDGET_OFFS_OPTS_LO matches the given mask/value.
; Widgets which don't match will not be called, but there children will still be checked
; (as opposed to Widget_TreeMatchingHandleSignal which would also skip the children).
;
; @param Z byte address of object (for LPM!)
; @param R16 signal number
; @param R17 selector
; @param R20 mask for WIDGET_OFFS_OPTS_LO to match
; @param R21 value for WIDGET_OFFS_OPTS_LO to match
; @param xl param1
; @param xh param2
; @clobbers any, !R16, !R17, !X, !Z
Widget_TreeMatchOptsAndSendSignal:
push zl
push zh
Widget_TreeMatchOptsAndSendSignal_loop:
mov r18, zl
or r18, zh
breq Widget_TreeMatchOptsAndSendSignal_done
adiw zh:zl, WIDGET_OFFS_OPTS_LO
lpm r18, Z
sbiw zh:zl, WIDGET_OFFS_OPTS_LO
eor r18, r21 ; XOR with value (1 if different)
and r18, r20 ; AND with mask
brne Widget_TreeMatchOptsAndSendSignal_next
push r20
push r21
rcall OBJ_HandleSignalSaveInRegs
pop r21
pop r20
Widget_TreeMatchOptsAndSendSignal_next:
push r16
rcall OBJ_GetBelow ; (R16)
pop r16
brcc Widget_TreeMatchOptsAndSendSignal_done
mov zl, r18
mov zh, r19
rjmp Widget_TreeMatchOptsAndSendSignal_loop
Widget_TreeMatchOptsAndSendSignal_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_TreeMatchOptsAndSendSignalToActive @global
;
; Send signal to all widgets whose WIDGET_OFFS_OPTS_LO matches the given mask/value.
; Inactive branches are skipped.
;
; @param Z byte address of object (for LPM!)
; @param R16 signal number
; @param R17 selector
; @param R20 mask for WIDGET_OFFS_OPTS_LO to match
; @param R21 value for WIDGET_OFFS_OPTS_LO to match
; @param xl param1
; @param xh param2
; @clobbers any, !R16, !R17, !X, !Z
Widget_TreeMatchOptsAndSendSignalToActive:
push zl
push zh
Widget_TreeMatchOptsAndSendSignalToActive_loop:
mov r18, zl
or r18, zh
breq Widget_TreeMatchOptsAndSendSignalToActive_done
; check flags
rcall Widget_GetSdramPtr ; (none)
ldd r18, Y+WIDGET_SD_OFFS_FLAGS
sbrc r18, WIDGET_FLAGS_ACTIVE_BIT
rjmp Widget_TreeMatchOptsAndSendSignalToActive_checkOpts
push r16
rcall OBJ_GetBelowSkipChildren ; (R16)
pop r16
rjmp Widget_TreeMatchOptsAndSendSignalToActive_next
Widget_TreeMatchOptsAndSendSignalToActive_checkOpts:
adiw zh:zl, WIDGET_OFFS_OPTS_LO
lpm r18, Z
sbiw zh:zl, WIDGET_OFFS_OPTS_LO
eor r18, r21 ; XOR with value (1 if different)
and r18, r20 ; AND with mask
brne Widget_TreeMatchOptsAndSendSignalToActive_below
push r20
push r21
rcall OBJ_HandleSignalSaveInRegs
pop r21
pop r20
Widget_TreeMatchOptsAndSendSignalToActive_below:
push r16
rcall OBJ_GetBelow ; (R16)
pop r16
Widget_TreeMatchOptsAndSendSignalToActive_next:
brcc Widget_TreeMatchOptsAndSendSignalToActive_done
mov zl, r18
mov zh, r19
rjmp Widget_TreeMatchOptsAndSendSignalToActive_loop
Widget_TreeMatchOptsAndSendSignalToActive_done:
pop zh
pop zl
ret
; @end
; ---------------------------------------------------------------------------
; @routine Widget_TreeMatchFlagsAndSendSignalToActive @global
;
; Send signal to all widgets whose WIDGET_SD_OFFS_FLAGS matches the given mask/value.
; Inactive branches are skipped.
;
; @param Z byte address of object (for LPM!)
; @param R16 signal number
; @param R17 selector
; @param R20 mask for WIDGET_SD_OFFS_FLAGS to match
; @param R21 value for WIDGET_SD_OFFS_FLAGS to match
; @param xl param1
; @param xh param2
; @clobbers any, !R16, !R17, !X, !Z
Widget_TreeMatchFlagsAndSendSignalToActive:
push zl
push zh
Widget_TreeMatchFlagsAndSendSignalToActive_loop:
mov r18, zl
or r18, zh
breq Widget_TreeMatchFlagsAndSendSignalToActive_done
; check flags
rcall Widget_GetSdramPtr ; (none)
ldd r18, Y+WIDGET_SD_OFFS_FLAGS
sbrc r18, WIDGET_FLAGS_ACTIVE_BIT
rjmp Widget_TreeMatchFlagsAndSendSignalToActive_checkFlags
push r16
rcall OBJ_GetBelowSkipChildren ; (R16)
pop r16
rjmp Widget_TreeMatchFlagsAndSendSignalToActive_next
Widget_TreeMatchFlagsAndSendSignalToActive_checkFlags:
ldd r18, Y+WIDGET_SD_OFFS_FLAGS
eor r18, r21 ; XOR with value (1 if different)
and r18, r20 ; AND with mask
brne Widget_TreeMatchFlagsAndSendSignalToActive_below
push r20
push r21
rcall OBJ_HandleSignalSaveInRegs
pop r21
pop r20
Widget_TreeMatchFlagsAndSendSignalToActive_below:
push r16
rcall OBJ_GetBelow ; (R16)
pop r16
Widget_TreeMatchFlagsAndSendSignalToActive_next:
brcc Widget_TreeMatchFlagsAndSendSignalToActive_done
mov zl, r18
mov zh, r19
rjmp Widget_TreeMatchFlagsAndSendSignalToActive_loop
Widget_TreeMatchFlagsAndSendSignalToActive_done:
pop zh
pop zl
ret
; @end
#endif