; *************************************************************************** ; 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 ; EEPROM data for SensorWatch .equ SENSORWATCH_EE_OFFS_NODEADDR = 0 .equ SENSORWATCH_EE_OFFS_VALUEID = 1 .equ SENSORWATCH_EE_OFFS_UPPER_LIMIT_WARN_LO = 2 .equ SENSORWATCH_EE_OFFS_UPPER_LIMIT_WARN_HI = 3 .equ SENSORWATCH_EE_OFFS_LOWER_LIMIT_WARN_LO = 4 .equ SENSORWATCH_EE_OFFS_LOWER_LIMIT_WARN_HI = 5 .equ SENSORWATCH_EE_OFFS_UPPER_LIMIT_CRIT_LO = 6 .equ SENSORWATCH_EE_OFFS_UPPER_LIMIT_CRIT_HI = 7 .equ SENSORWATCH_EE_OFFS_LOWER_LIMIT_CRIT_LO = 8 .equ SENSORWATCH_EE_OFFS_LOWER_LIMIT_CRIT_HI = 9 .equ SENSORWATCH_EE_SIZE = 10 ; 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 rcall sensorWatchReadFromEeprom ; (R16, R18, X, Y) 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 (none) adiw zh:zl, SENSORWATCH_OFFS_BASEVALUEID lpm r16, Z sbiw zh:zl, SENSORWATCH_OFFS_BASEVALUEID sub r17, r16 brcs SensorWatch_OnMsgReceived_ret ; not my value cpi r17, 3 brcc SensorWatch_OnMsgReceived_ret ; not my value cpi r17, 0 breq SensorWatch_OnMsgReceived_setSource cpi r17, 1 breq SensorWatch_OnMsgReceived_setLimWarn cpi r17, 2 breq SensorWatch_OnMsgReceived_setLimCrit rjmp SensorWatch_OnMsgReceived_ret SensorWatch_OnMsgReceived_setSource: std Y+SENSORWATCH_SD_OFFS_NODEADDR, r18 std Y+SENSORWATCH_SD_OFFS_VALUEID, r19 rjmp SensorWatch_OnMsgReceived_sendACK SensorWatch_OnMsgReceived_setLimWarn: std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_WARN_LO, r18 std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_WARN_HI, r19 std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO, r20 std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_HI, r21 rjmp SensorWatch_OnMsgReceived_sendACK SensorWatch_OnMsgReceived_setLimCrit: std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_CRIT_LO, r18 std Y+SENSORWATCH_SD_OFFS_LOWER_LIMIT_CRIT_HI, r19 std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_LO, r20 std Y+SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_HI, r21 SensorWatch_OnMsgReceived_sendACK: add r17, r16 ; restore valueId push xl push xh push yl push yh ldi r23, NETMSG_CMD_VALUE_SET_ACK bigcall Main_SendValueResponse ; (clobbers all except Z) pop yh pop yl rcall sensorWatchSetColor ; (any, !Y, !Z) rcall sensorWatchWriteToEeprom ; (R16, R17, R18, R20, R21, X, Y) pop xh pop xl 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: push yl push yh ; 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) brcs sensorWatchSetColor_setRed sbiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_CRIT_LO ; check against warning limits adiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO rcall sensorWatchCheckAgainstLimit ; (r16, r17, r22, r23) brcs sensorWatchSetColor_setYellow sbiw yh:yl, SENSORWATCH_SD_OFFS_UPPER_LIMIT_WARN_LO ; 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: pop yh pop yl 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 ; --------------------------------------------------------------------------- ; @routine sensorWatchWriteToEeprom ; ; @param Z byte address of widget object (for LPM!) ; @return CFLAG set if data found and read, cleared on error ; @clobbers R16, R17, R18, R20, R21, X, Y sensorWatchWriteToEeprom: adiw zh:zl, SENSORWATCH_OFFS_EEPROMID lpm r16, Z sbiw zh:zl, SENSORWATCH_OFFS_EEPROMID tst r16 clc breq sensorWatchWriteToEeprom_ret push r16 bigcall EepromTlv_FindFirst ; (R18) pop r16 brcs sensorWatchWriteToEeprom_write ldi r17, SENSORWATCH_EE_SIZE bigcall EepromTlv_AddTlv ; X=pointer to EEPROM data (R16, R18, R20, R21) brcc sensorWatchWriteToEeprom_ret sensorWatchWriteToEeprom_write: bigcall Widget_GetSdramPtr ; (none) adiw yh:yl, SENSORWATCH_SD_OFFS_NODEADDR ldi r18, SENSORWATCH_EE_SIZE sensorWatchWriteToEeprom_loop: ld r16, Y+ bigcall Eeprom_WriteByteIfChanged ; (R17) brcc sensorWatchWriteToEeprom_ret adiw xh:xl, 1 dec r18 brne sensorWatchWriteToEeprom_loop sec sensorWatchWriteToEeprom_ret: ret ; @end ; --------------------------------------------------------------------------- ; @routine sensorWatchReadFromEeprom ; ; @param Z byte address of widget object (for LPM!) ; @return CFLAG set if data found and read, cleared on error ; @clobbers R16, R18, X, Y sensorWatchReadFromEeprom: adiw zh:zl, SENSORWATCH_OFFS_EEPROMID lpm r16, Z sbiw zh:zl, SENSORWATCH_OFFS_EEPROMID bigcall EepromTlv_FindFirst ; (R18) brcc sensorWatchReadFromEeprom_ret bigcall Widget_GetSdramPtr ; (none) adiw yh:yl, SENSORWATCH_SD_OFFS_NODEADDR ldi r18, SENSORWATCH_EE_SIZE sensorWatchReadFromEeprom_loop: bigcall Eeprom_ReadByte ; R16=byte (none) brcc sensorWatchReadFromEeprom_ret st Y+, r16 adiw xh:xl, 1 dec r18 brne sensorWatchReadFromEeprom_loop sec sensorWatchReadFromEeprom_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