Files
aqhomecontrol/avr/modules/lcd2/gui2/sensorwatch.asm
2026-01-21 00:56:49 +01:00

480 lines
14 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_SENSORWATCH_ASM
#define AQH_AVR_GUI2_SENSORWATCH_ASM
; ***************************************************************************
; SensorWatch
;
; This widget has three subwidgets:
; - Title (Label)
; - Image (ImageView)
; - Value (Label)
;
; It watches received messages and reacts on those matching the stored
; combination of NodeAddr and ValueId by colouring the image according to
; the value received and also shows the value beloe the image.
;
; Please note that this widget needs to have the option bit
; "WIDGET_OPTSLO_MSGRECV_BIT" set in order to receive MsgReceived signals.
;
; ***************************************************************************
; ***************************************************************************
; defines
; SensorWatch in flash
.equ SENSORWATCH_OFFS_BEGIN = WIDGET_SIZE
.equ SENSORWATCH_OFFS_BASEVALUEID = SENSORWATCH_OFFS_BEGIN+0
.equ SENSORWATCH_OFFS_EEPROMID = SENSORWATCH_OFFS_BEGIN+1
.equ SENSORWATCH_SIZE = SENSORWATCH_OFFS_BEGIN+2
; SDRAM data for SensorWatch
.equ SENSORWATCH_SD_OFFS_SENSORWATCH = WIDGET_SD_SIZE
.equ SENSORWATCH_SD_OFFS_NODEADDR = SENSORWATCH_SD_OFFS_SENSORWATCH+0
.equ SENSORWATCH_SD_OFFS_VALUEID = SENSORWATCH_SD_OFFS_SENSORWATCH+1
.equ SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO = SENSORWATCH_SD_OFFS_SENSORWATCH+2
.equ SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_HI = SENSORWATCH_SD_OFFS_SENSORWATCH+3
.equ SENSORWATCH_SD_OFFS_LOWER_LIMIT_WARN_LO = SENSORWATCH_SD_OFFS_SENSORWATCH+4
.equ SENSORWATCH_SD_OFFS_LOWER_LIMIT_WARN_HI = SENSORWATCH_SD_OFFS_SENSORWATCH+5
.equ SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_LO = SENSORWATCH_SD_OFFS_SENSORWATCH+6
.equ SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_HI = SENSORWATCH_SD_OFFS_SENSORWATCH+7
.equ SENSORWATCH_SD_OFFS_LOWER_LIMIT_CRIT_LO = SENSORWATCH_SD_OFFS_SENSORWATCH+8
.equ SENSORWATCH_SD_OFFS_LOWER_LIMIT_CRIT_HI = SENSORWATCH_SD_OFFS_SENSORWATCH+9
.equ SENSORWATCH_SD_OFFS_VALUE_LO = SENSORWATCH_SD_OFFS_SENSORWATCH+10
.equ SENSORWATCH_SD_OFFS_VALUE_HI = SENSORWATCH_SD_OFFS_SENSORWATCH+11
.equ SENSORWATCH_SD_SIZE = SENSORWATCH_SD_OFFS_SENSORWATCH+12
; signals
.equ SENSORWATCH_SIGNAL_SETSOURCE = WIDGET_SIGNAL_NEXTFREE+0
.equ SENSORWATCH_SIGNAL_SETUPPERLIMWARN = WIDGET_SIGNAL_NEXTFREE+1
.equ SENSORWATCH_SIGNAL_SETLOWERLIMWARN = WIDGET_SIGNAL_NEXTFREE+2
.equ SENSORWATCH_SIGNAL_SETUPPERLIMCRIT = WIDGET_SIGNAL_NEXTFREE+3
.equ SENSORWATCH_SIGNAL_SETLOWERLIMCRIT = WIDGET_SIGNAL_NEXTFREE+4
.equ SENSORWATCH_SIGNAL_NEXTFREE = WIDGET_SIGNAL_NEXTFREE+5
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnCreate @global
;
; @param Z byte address of widget object (for LPM!)
; @param XL node addr
; @param XH value id
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnCreate:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_OnCreate_ret
; preset SDRAM
bigcall Widget_GetSdramPtr ; (none)
clr r16
ldi r17, SENSORWATCH_SD_SIZE
push yl
push yh
SensorWatch_OnCreate_loop:
st Y+, r16
dec r17
brne SensorWatch_OnCreate_loop
pop yh
pop yl
bigcall Widget_OnCreate
SensorWatch_OnCreate_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnSetSource @global
;
; @param Z byte address of widget object (for LPM!)
; @param XL node addr
; @param XH value id
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnSetSource:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_OnSetSource_ret
push zl
push zh
bigcall Widget_GetSdramPtr ; (none)
std Y+SENSORWATCH_SD_OFFS_NODEADDR, xl
std Y+SENSORWATCH_SD_OFFS_VALUEID, xh
pop zh
pop zl
SensorWatch_OnSetSource_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnSetLowerLimitWarn @global
;
; @param Z byte address of widget object (for LPM!)
; @param X value
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnSetLowerLimitWarn:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_OnSetLowerLimitWarn_ret
bigcall Widget_GetSdramPtr ; (none)
std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_WARN_LO, xl
std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_WARN_HI, xh
rcall sensorWatchSetColor
SensorWatch_OnSetLowerLimitWarn_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnSetUpperLimitWarn @global
;
; @param Z byte address of widget object (for LPM!)
; @param X value
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnSetUpperLimitWarn:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_OnSetUpperLimitWarn_ret
bigcall Widget_GetSdramPtr ; (none)
std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO, xl
std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_HI, xh
rcall sensorWatchSetColor
SensorWatch_OnSetUpperLimitWarn_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnSetLimitCrit @global
;
; @param Z byte address of widget object (for LPM!)
; @param X value
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnSetLowerLimitCrit:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_OnSetLowerLimitCrit_ret
rcall Widget_GetSdramPtr ; (none)
std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_CRIT_LO, xl
std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_CRIT_HI, xh
rcall sensorWatchSetColor
SensorWatch_OnSetLowerLimitCrit_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnSetUpperLimitCrit @global
;
; @param Z byte address of widget object (for LPM!)
; @param X value
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnSetUpperLimitCrit:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_OnSetUpperLimitCrit_ret
rcall Widget_GetSdramPtr ; (none)
std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_LO, xl
std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_HI, xh
rcall sensorWatchSetColor
SensorWatch_OnSetUpperLimitCrit_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_OnMsgReceived @global
;
; @param Z byte address of widget object (for LPM!)
; @param XL node addr
; @param XH value id
; @return CFLAG set if signal handled
; @clobbers any, !Z
SensorWatch_OnMsgReceived:
adiw xh:xl, 2 ; command
ld r16, X
sbiw xh:xl, 2
cpi r16, NETMSG_CMD_VALUE_REPORT
breq SensorWatch_OnMsgReceived_report
cpi r16, NETMSG_CMD_VALUE_SET
breq SensorWatch_OnMsgReceived_set
rjmp SensorWatch_OnMsgReceived_ret
SensorWatch_OnMsgReceived_report:
bigcall Widget_GetSdramPtr ; (none)
bigcall NETMSG_ValueRead ; R17=valueId, R22=nodeAddr R19:R18=value (none)
; check node addr
ldd r16, Y+SENSORWATCH_SD_OFFS_NODEADDR
cp r16, r22
brne SensorWatch_OnMsgReceived_ret
; check value id
ldd r16, Y+SENSORWATCH_SD_OFFS_VALUEID
cp r16, r17
brne SensorWatch_OnMsgReceived_ret
; store value
std Y+SENSORWATCH_SD_OFFS_VALUE_LO, r18
std Y+SENSORWATCH_SD_OFFS_VALUE_HI, r19
; setup background color
rcall sensorWatchSetColor ; (any, !Y, !Z)
rcall sensorWatchSetValueLabel ; (any, !Y, !Z)
rjmp SensorWatch_OnMsgReceived_ret
SensorWatch_OnMsgReceived_set:
bigcall Widget_GetSdramPtr ; (none)
bigcall NETMSG_ValueRead ; R17=valueId, R22=nodeAddr R19:R18=value R21:R20=denom (none)
; TODO: check valueid, read and set value
SensorWatch_OnMsgReceived_ret:
sec
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_GetImageView @global
;
; @param Z byte address of widget object (for LPM!)
; @return CFLAG set if widget found, cleared otherwise
; @return R19:R18 byte address pointer to image view (for LPM!)
; @clobbers none
SensorWatch_GetImageView:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_GetImageView_ret
push zl
push zh
bigcall OBJ_GetFirstChild ; (none)
brcc SensorWatch_GetImageView_done
mov zl, r18
mov zh, r19
bigcall OBJ_GetNext ; 2nd child
SensorWatch_GetImageView_done:
pop zh
pop zl
SensorWatch_GetImageView_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine SensorWatch_GetValueLabel @global
;
; @param Z byte address of widget object (for LPM!)
; @return CFLAG set if widget found, cleared otherwise
; @return R19:R18 byte address pointer to image view (for LPM!)
; @clobbers none
SensorWatch_GetValueLabel:
bigcall OBJ_IsObject ; (none)
brcc SensorWatch_GetValueLabel_ret
push zl
push zh
bigcall OBJ_GetFirstChild ; (none)
brcc SensorWatch_GetValueLabel_done
mov zl, r18
mov zh, r19
bigcall OBJ_GetNext ; 2nd child
brcc SensorWatch_GetValueLabel_done
mov zl, r18
mov zh, r19
bigcall OBJ_GetNext ; 3nd child
SensorWatch_GetValueLabel_done:
pop zh
pop zl
SensorWatch_GetValueLabel_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine sensorWatchSetColor
;
; @param Z byte address of widget object (for LPM!)
; @param Y pointer to SDRAM data
; @clobbers any, !Y, !Z
sensorWatchSetColor:
; default color is green
ldi xl, LOW(DISPLAY_COLOR_DARKGREEN)
ldi xh, HIGH(DISPLAY_COLOR_DARKGREEN)
ldd r20, Y+SENSORWATCH_SD_OFFS_VALUE_LO
ldd r21, Y+SENSORWATCH_SD_OFFS_VALUE_HI
mov r16, r20
or r16, r21
breq sensorWatchSetColor_ret ; do nothing
; check against critical limits
adiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_LO
rcall sensorWatchCheckAgainstLimit ; (r16, r17, r22, r23)
sbiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_LO
brcs sensorWatchSetColor_setRed
; check against warning limits
adiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO
rcall sensorWatchCheckAgainstLimit ; (r16, r17, r22, r23)
sbiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO
brcs sensorWatchSetColor_setYellow
; set green background
rjmp sensorWatchSetColor_setColor
sensorWatchSetColor_setRed:
ldi xl, LOW(DISPLAY_COLOR_RED)
ldi xh, HIGH(DISPLAY_COLOR_RED)
rjmp sensorWatchSetColor_setColor
sensorWatchSetColor_setYellow:
ldi xl, LOW(DISPLAY_COLOR_YELLOW)
ldi xh, HIGH(DISPLAY_COLOR_YELLOW)
sensorWatchSetColor_setColor:
rcall SensorWatch_GetImageView ; (none)
brcc sensorWatchSetColor_ret
push zl
push zh
mov zl, r18
mov zh, r19
ldi r16, IMGVIEW_SIGNAL_SETBGCOL
clr r17
bigcall OBJ_HandleSignal ; (any, !X, !Y, !Z)
pop zh
pop zl
sensorWatchSetColor_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine sensorWatchCheckAgainstLimit
;
; @param R21:R20 value to check against limit
; @param Y points to upper limit (lo/hi), followed by lower limit (lo/hi)
; @return CFLAG set if limit triggered, cleared if between upper and lower limit
; @clobbers r16, r17, r22, r23
sensorWatchCheckAgainstLimit:
; check against upper limit (if any)
ldd r22, Y+0
ldd r23, Y+1
mov r16, r22
or r16, r23 ; zero?
clc
breq sensorWatchCheckAgainstLimit_ret ; yes, jmp
cp r20, r22
cpc r21, r23
brcc sensorWatchCheckAgainstLimit_secRet
; check against lower limit (if any)
ldd r22, Y+2
ldd r23, Y+3
mov r16, r22
or r16, r23 ; zero?
clc
breq sensorWatchCheckAgainstLimit_ret ; yes, jmp
cp r22, r20
cpc r23, r21
brcc sensorWatchCheckAgainstLimit_secRet
clc
rjmp sensorWatchCheckAgainstLimit_ret
sensorWatchCheckAgainstLimit_secRet:
sec
sensorWatchCheckAgainstLimit_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine sensorWatchSetValueLabel
;
; @param Z byte address of widget object (for LPM!)
; @param Y pointer to SDRAM data
; @clobbers any, !Y, !Z
sensorWatchSetValueLabel:
rcall SensorWatch_GetValueLabel ; (none)
brcc sensorWatchSetValueLabel_ret
push zl
push zh
mov zl, r18
mov zh, r19
ldd xl, Y+SENSORWATCH_SD_OFFS_VALUE_LO
ldd xh, Y+SENSORWATCH_SD_OFFS_VALUE_HI
ldi r16, VLABEL_SIGNAL_SETVALUE
clr r17
bigcall OBJ_HandleSignal ; (any, !X, !Y, !Z)
pop zh
pop zl
sensorWatchSetValueLabel_ret:
ret
; @end
SensorWatch_DefaultSignalmap:
.db 0, OBJECT_SIGNAL_CREATE, LOW(SensorWatch_OnCreate), HIGH(SensorWatch_OnCreate)
.db 0, WIDGET_SIGNAL_DRAW, LOW(Widget_OnDraw), HIGH(Widget_OnDraw)
.db 0, OBJECT_SIGNAL_RECVMSG, LOW(SensorWatch_OnMsgReceived), HIGH(SensorWatch_OnMsgReceived)
.db 0, SENSORWATCH_SIGNAL_SETSOURCE, LOW(SensorWatch_OnSetSource), HIGH(SensorWatch_OnSetSource)
.db 0, SENSORWATCH_SIGNAL_SETUPPERLIMWARN, LOW(SensorWatch_OnSetUpperLimitWarn), HIGH(SensorWatch_OnSetUpperLimitWarn)
.db 0, SENSORWATCH_SIGNAL_SETLOWERLIMWARN, LOW(SensorWatch_OnSetLowerLimitWarn), HIGH(SensorWatch_OnSetLowerLimitWarn)
.db 0, SENSORWATCH_SIGNAL_SETUPPERLIMCRIT, LOW(SensorWatch_OnSetUpperLimitCrit), HIGH(SensorWatch_OnSetUpperLimitCrit)
.db 0, SENSORWATCH_SIGNAL_SETLOWERLIMCRIT, LOW(SensorWatch_OnSetLowerLimitCrit), HIGH(SensorWatch_OnSetLowerLimitCrit)
.db 0, 0, 0, 0 ; end of table
#endif