diff --git a/avr/modules/lcd2/gui/base/cwidget.asm b/avr/modules/lcd2/gui/base/cwidget.asm new file mode 100644 index 0000000..e21a60e --- /dev/null +++ b/avr/modules/lcd2/gui/base/cwidget.asm @@ -0,0 +1,351 @@ +; *************************************************************************** +; 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_GUI_BASE_CWIDGET_ASM +#define AQH_AVR_GUI_BASE_CWIDGET_ASM + + +; *************************************************************************** +; defines + + +; CWIDGET dialog configuration +.equ CWIDGETCFG_MAINWIDGET_TYPE_HLAYOUT = 1 +.equ CWIDGETCFG_MAINWIDGET_TYPE_VLAYOUT = 2 +.equ CWIDGETCFG_MAINWIDGET_TYPE_MLAYOUT = 3 +.equ CWIDGETCFG_MAINWIDGET_TYPE_NEXT = 4 + +.equ CWIDGETCFG_WIDGET_TYPE_LABEL = 1 +.equ CWIDGETCFG_WIDGET_TYPE_VALUELABEL = 2 +.equ CWIDGETCFG_WIDGET_TYPE_IMAGEVIEW = 3 +.equ CWIDGETCFG_WIDGET_TYPE_HSPINNER = 4 +.equ CWIDGETCFG_WIDGET_TYPE_TEXTBUTTON = 5 +.equ CWIDGETCFG_WIDGET_TYPE_IMAGEBUTTON = 6 +.equ CWIDGETCFG_WIDGET_TYPE_NEXT = 7 + +.equ CWIDGETCFG_WIDGET_FLAGS_MINMAXVALUES_BIT = 0 + +.equ CWIDGETCFG_OFFS_HEADER_TYPE = 0 ; HLAYOUT, VLAYOUT, MLAYOUT +.equ CWIDGETCFG_OFFS_HEADER_FLAGS = 1 +.equ CWIDGETCFG_OFFS_HEADER_PARAM1 = 2 ; R20 +.equ CWIDGETCFG_OFFS_HEADER_PARAM2 = 3 ; R21 +.equ CWIDGETCFG_HEADER_SIZE = 4 + +.equ CWIDGETCFG_OFFS_WIDGET_TYPE = 0 ; 0=end +.equ CWIDGETCFG_OFFS_WIDGET_FLAGS = 1 +.equ CWIDGETCFG_OFFS_WIDGET_SELECTOR = 2 +.equ CWIDGETCFG_OFFS_WIDGET_RESERVED = 3 +.equ CWIDGETCFG_OFFS_WIDGET_OPTS = 4 +.equ CWIDGETCFG_OFFS_WIDGET_PACK = 5 +.equ CWIDGETCFG_OFFS_WIDGET_STYLE_LO = 6 +.equ CWIDGETCFG_OFFS_WIDGET_STYLE_HI = 7 +.equ CWIDGETCFG_OFFS_WIDGET_PARAM1 = 8 ; R20 +.equ CWIDGETCFG_OFFS_WIDGET_PARAM2 = 9 ; R21 +.equ CWIDGETCFG_OFFS_WIDGET_PARAM3 = 10 ; R22 +.equ CWIDGETCFG_OFFS_WIDGET_PARAM4 = 11 ; R23 +.equ CWIDGETCFG_OFFS_WIDGET_MINVALUE_LO = 12 +.equ CWIDGETCFG_OFFS_WIDGET_MINVALUE_HI = 13 +.equ CWIDGETCFG_OFFS_WIDGET_MAXVALUE_LO = 14 +.equ CWIDGETCFG_OFFS_WIDGET_MAXVALUE_HI = 15 +.equ CWIDGETCFG_WIDGET_SIZE = 16 + + + +; *************************************************************************** +; code + +.cseg + + + +; --------------------------------------------------------------------------- +; @routine CWidget_Create +; +; @param Y pointer to target object for signals emitted by child widgets +; @param X pointer to window to become parent for the new widget +; @param Z pointer to dialog configuration +; @return CFLAG set of okay, cleared otherwise +; @return Y pointer to created content widget + +CWidget_Create: + push yl ; target + push yh + rcall cWidgetMkMainWidget + mov xl, yl ; layout widget + mov xh, yh + pop yh ; target + pop yl + brcc CWidget_Create_ret + + adiw zh:zl, CWIDGETCFG_HEADER_SIZE ; go to first child widget + rcall CWidget_CreateChildWidgets +CWidget_Create_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine CWidget_GetChildBySelector +; +; @param Y pointer to widget created by @ref CWidget_Create +; @param Z pointer to dialog configuration +; @param r16 selector to search for +; @return CFLAG set if widget found, cleared otherwise +; @return r19:r18 resulting widget +; @clobbers R16, R18, R19 + +CWidget_GetChildBySelector: + push zl + push zh + adiw zh:zl, CWIDGETCFG_HEADER_SIZE + ; determine child index + clr r18 +CWidget_GetChildBySelector_loop: + lpm r19, Z ; CWIDGETCFG_OFFS_WIDGET_TYPE + tst r19 + clc + breq CWidget_GetChildBySelector_popRet + adiw zh:zl, CWIDGETCFG_OFFS_WIDGET_SELECTOR + lpm r19, Z + sbiw zh:zl, CWIDGETCFG_OFFS_WIDGET_SELECTOR + cp r19, r16 + breq CWidget_GetChildBySelector_found + inc r18 + adiw zh:zl, CWIDGETCFG_WIDGET_SIZE + rjmp CWidget_GetChildBySelector_loop +CWidget_GetChildBySelector_found: + mov r16, r18 + bigcall OBJ_GetChildAt ; (r16) +CWidget_GetChildBySelector_popRet: + pop zh + pop zl + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine CWidget_CreateChildWidgets @global +; +; @param Y pointer to target window for signals emitted by created widgets +; @param X pointer to window to become parent to created widgets +; @param Z pointer to dialog configuration (ptr to first widget, not to header!) +; @return CFLAG set of okay, cleared otherwise +; @clobbers any, !X, !Y + +CWidget_CreateChildWidgets: +CWidget_CreateChildWidgets_loop: + lpm r16, Z + tst r16 + breq CWidget_CreateChildWidgets_done + push yl + push yh + push xl + push xh + rcall cWidgetMkChildWidget + pop xh + pop xl + pop yh + pop yl + brcc CWidget_CreateChildWidgets_ret + adiw zh:zl, CWIDGETCFG_WIDGET_SIZE + rjmp CWidget_CreateChildWidgets_loop +CWidget_CreateChildWidgets_done: + sec +CWidget_CreateChildWidgets_ret: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine cWidgetMkMainWidget +; +; @param Y pointer to main window +; @param X pointer to content window of MainWindow (is a VLayout, becomes parent) +; @param Z pointer to dialog configuration +; @return CFLAG set of okay, cleared otherwise +; @return Y pointer to created content widget +; @clobbers any, !Z + +cWidgetMkMainWidget: + lpm r16, Z + cpi r16, CWIDGETCFG_MAINWIDGET_TYPE_NEXT + brcc cWidgetMkMainWidget_ret + dec r16 + + clr r17 + ldi r18, LOW(cWidgetMkMainWidget_table) + ldi r19, HIGH(cWidgetMkMainWidget_table) + add r18, r16 + adc r19, r17 + + ; prepare params, opts and pack + adiw zh:zl, CWIDGETCFG_OFFS_HEADER_PARAM1 + lpm r20, Z+ + lpm r21, Z + sbiw zh:zl, (CWIDGETCFG_OFFS_HEADER_PARAM1+1) + ldi r16, 0 ; OPTS + ldi r17, (WIDGET_PACK_FILLED<