diff --git a/avr/devices/n15/n15_defs.asm b/avr/devices/n15/n15_defs.asm index 8a14660..562563d 100644 --- a/avr/devices/n15/n15_defs.asm +++ b/avr/devices/n15/n15_defs.asm @@ -170,3 +170,18 @@ +; --------------------------------------------------------------------------- +; ValueMgr +; + +.equ VALMGR_SRC_MAX_LINKS = 5 +.equ VALMGR_SRC_TIMEOUT_SENDVALUE = 10 +.equ VALMGR_SRC_TIMEOUT_RECVACK = 12 +.equ VALMGR_SRC_MAX_RESEND = 3 + +.equ VALMGR_DST_MAX_LINKS = 2 +.equ VALMGR_DST_TIMEOUT_SENDRESULT = 20 + + + + diff --git a/avr/devices/n15/n15_main.asm b/avr/devices/n15/n15_main.asm index 8cba870..81bca7e 100644 --- a/avr/devices/n15/n15_main.asm +++ b/avr/devices/n15/n15_main.asm @@ -68,6 +68,9 @@ ;#define MODULES_OWI_MASTER ;#define MODULES_DS18B20 #define MODULES_MOTION +#define MODULES_VALMGR_SRC +#define MODULES_VALMGR_DST + ; --------------------------------------------------------------------------- ; defines for values @@ -164,6 +167,7 @@ firmwareStart: rjmp main .include "modules/comproto/msg_memstats.asm" .include "modules/comproto/msg_pong.asm" .include "modules/comproto/msg_value.asm" + .include "modules/comproto/msg_result.asm" .include "modules/comproto/msg_device.asm" .include "modules/comproto/msg_reboot.asm" #endif @@ -172,6 +176,12 @@ firmwareStart: rjmp main .include "modules/comproto/screen.asm" #endif #endif +#ifdef MODULES_VALMGR_SRC + .include "modules/valuemgr/src.asm" +#endif +#ifdef MODULES_VALMGR_DST + .include "modules/valuemgr/dst.asm" +#endif #ifdef MODULES_TWI_MASTER .include "modules/twimaster/main.asm" #endif diff --git a/avr/main.asm b/avr/main.asm index 3a2780d..80cd004 100644 --- a/avr/main.asm +++ b/avr/main.asm @@ -116,6 +116,15 @@ initModules: rcall Com2_Init ; init COM module rcall CPRO_Init ; init COM protocol module #endif + +#ifdef MODULES_VALMGR_SRC + rcall VALMGR_Src_Init +#endif + +#ifdef MODULES_VALMGR_DST + rcall VALMGR_Dst_Init +#endif + #ifdef MODULES_TWI_MASTER rcall TWI_Master_Init #endif @@ -191,6 +200,14 @@ runModules_ComEnd: #endif +#ifdef MODULES_VALMGR_SRC +; rcall VALMGR_Src_Run +#endif + +#ifdef MODULES_VALMGR_DST +; rcall VALMGR_Dst_Run +#endif + #ifdef MODULES_STATS rcall Stats_Run #endif diff --git a/avr/modules/valuemgr/0BUILD b/avr/modules/valuemgr/0BUILD new file mode 100644 index 0000000..15a1e16 --- /dev/null +++ b/avr/modules/valuemgr/0BUILD @@ -0,0 +1,11 @@ + + + + + + src.asm + + + + + diff --git a/avr/modules/valuemgr/dst.asm b/avr/modules/valuemgr/dst.asm new file mode 100644 index 0000000..012776d --- /dev/null +++ b/avr/modules/valuemgr/dst.asm @@ -0,0 +1,218 @@ +; *************************************************************************** +; copyright : (C) 2024 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. * +; *************************************************************************** + + +; *************************************************************************** +; defs + +.equ VALMGR_DSTLINK_OFFS_PEERADDR = 0 ; 1 byte (0=unused) +.equ VALMGR_DSTLINK_OFFS_TIMERSEND = 1 ; 1 byte +.equ VALMGR_DSTLINK_OFFS_MSGID = 2 ; 2 bytes +.equ VALMGR_DSTLINK_OFFS_RESULT = 4 ; 1 byte +.equ VALMGR_DSTLINK_SIZE = 5 + + + +; *************************************************************************** +; data + +.dseg + +valMgrDstDataBegin: +valMgrDstLinks: .byte VALMGR_DST_MAX_LINKS*VALMGR_DSTLINK_SIZE +valMgrDstNoSendErrors: .byte 1 +valMgrDstDataEnd: + + + +; *************************************************************************** +; code + +.cseg + +VALMGR_DST_BEGIN: + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Dst_Init + +VALMGR_Dst_Init: + ; preset SRAM data area + ldi xh, HIGH(valMgrDstDataBegin) + ldi xl, LOW(valMgrDstDataBegin) + clr r16 + ldi r17, (valMgrDstDataEnd-valMgrDstDataBegin) + rcall Utils_FillSram + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Dst_Fini + +VALMGR_Dst_Fini: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Dst_SendResult @global +; +; @param r16 peer address +; @param r17 result +; @param r19:r18 message id +; @clobbers any + +VALMGR_Dst_SendResult: + rcall valMgrDstFindFreeLink ; (r20, r21, y) + brcs VALMGR_Dst_SendResult_gotfreelink + ret +VALMGR_Dst_SendResult_gotfreelink: + std Y+VALMGR_DSTLINK_OFFS_PEERADDR, r16 + std Y+VALMGR_DSTLINK_OFFS_MSGID, r18 + std Y+VALMGR_DSTLINK_OFFS_MSGID+1, r19 + std Y+VALMGR_DSTLINK_OFFS_RESULT, r17 + ldi r16, VALMGR_DST_TIMEOUT_SENDRESULT + std Y+VALMGR_DSTLINK_OFFS_TIMERSEND, r16 + rcall valMgrDstSendResult ; (any except Y) + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Dst_Every100ms @global +; +; @param Y pointer to VALMGR_VAR object +; @clobbers any + +VALMGR_Dst_Every100ms: + ldd r16, Y+VALMGR_DSTLINK_OFFS_PEERADDR + tst r16 + brne VALMGR_Dst_Every100ms_active + ret +VALMGR_Dst_Every100ms_active: + rjmp valMgrDstCheckSendTimer +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrDstFindFreeLink +; +; @return CFLAG set if free link found, cleared otherwise +; @return Y pointer to free entry +; @clobbers r20, r21, y + +valMgrDstFindFreeLink: + ldi yl, LOW(valMgrDstLinks) + ldi yh, HIGH(valMgrDstLinks) + ldi r20, VALMGR_DST_MAX_LINKS +valMgrDstFindFreeLink_loop: + ld r21, Y + tst r21 + brne valMgrDstFindFreeLink_next + sec + ret +valMgrDstFindFreeLink_next: + adiw yh:yl, VALMGR_DSTLINK_SIZE + dec r20 + brne valMgrDstFindFreeLink_loop + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrDstSendResult +; +; Try to send a value +; +; @return CFLAG set if message sent, cleared otherwise +; @param Y pointer to VALMGR_VAR object +; @clobbers any, -Y + +valMgrDstSendResult: + ldi xl, LOW(com2SendBuffer) + ldi xh, HIGH(com2SendBuffer) + ldd r16, Y+VALMGR_DSTLINK_OFFS_PEERADDR + ldd r17, Y+VALMGR_DSTLINK_OFFS_RESULT + ldd r18, Y+VALMGR_DSTLINK_OFFS_MSGID + ldd r19, Y+VALMGR_DSTLINK_OFFS_MSGID+1 + rcall CPRO_WriteResult + rcall COM2_SendPacket ; (any) + brcs valMgrDstSendResult_reset + ret +valMgrDstSendResult_reset: + rcall valMgrDstResetValue + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrDstResetValue +; +; Reset value data (e.g. set timers, msgid and priority to 0) +; +; @return CFLAG set if message sent, cleared otherwise +; @param Y pointer to VALMGR_VAR object +; @clobbers r16 + +valMgrDstResetValue: + clr r16 + std Y+VALMGR_DSTLINK_OFFS_PEERADDR, r16 + std Y+VALMGR_DSTLINK_OFFS_TIMERSEND, r16 + std Y+VALMGR_DSTLINK_OFFS_MSGID, r16 + std Y+VALMGR_DSTLINK_OFFS_MSGID+1, r16 + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrDstCheckSendTimer +; +; Set MSB in value id of all matching link entries +; @param R16 valueId to activate +; @clobbers any, -Y + +valMgrDstCheckSendTimer: + ldd r16, Y+VALMGR_DSTLINK_OFFS_TIMERSEND + tst r16 + brne valMgrDstCheckSendTimer_dec + ret +valMgrDstCheckSendTimer_dec: + dec r16 + std Y+VALMGR_DSTLINK_OFFS_TIMERSEND, r16 + breq valMgrDstCheckSendTimer_timeout + rjmp valMgrDstSendResult ; (any except Y) +valMgrDstCheckSendTimer_timeout: + lds r16, valMgrDstNoSendErrors + inc r16 + breq valMgrDstCheckSendTimer_dontCountUp + sts valMgrSrcNoSendErrors, r16 +valMgrDstCheckSendTimer_dontCountUp: + rjmp valMgrSrcResetValue +; @end + + + + + + +VALMGR_DST_END: +.equ MODULE_SIZE_VALMGR_DST = VALMGR_DST_END-VALMGR_DST_BEGIN diff --git a/avr/modules/valuemgr/src.asm b/avr/modules/valuemgr/src.asm new file mode 100644 index 0000000..4bf5159 --- /dev/null +++ b/avr/modules/valuemgr/src.asm @@ -0,0 +1,540 @@ +; *************************************************************************** +; copyright : (C) 2024 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. * +; *************************************************************************** + + +; *************************************************************************** +; defs + +.equ VALMGR_VAR_OFFS_VALUEID = 0 ; 1 byte +.equ VALMGR_VAR_OFFS_PRIORITY = 1 ; 1 byte (1=lowest, reset to 0 when done with msg) +.equ VALMGR_VAR_OFFS_CURRVAL = 2 ; 4 bytes +.equ VALMGR_VAR_OFFS_TIMERSEND = 6 ; 1 byte +.equ VALMGR_VAR_OFFS_COUNTERRESEND = 7 ; 1 byte +.equ VALMGR_VAR_OFFS_MSGID = 8 ; 2 bytes +.equ VALMGR_VAR_OFFS_TIMERACK = 10 ; 1 byte +.equ VALMGR_VAR_OFFS_VALUETYPE = 11 ; 1 byte +.equ VALMGR_VAR_SIZE = 12 + + +.equ VALMGR_SRCLINK_OFFS_VALUEID = 0 ; 1 byte +.equ VALMGR_SRCLINK_OFFS_PEERADDR = 1 ; 1 byte +.equ VALMGR_SRCLINK_SIZE = 2 + + +; *************************************************************************** +; data + +.dseg + +valMgrSrcDataBegin: +valMgrSrcLinks: .byte VALMGR_SRC_MAX_LINKS*VALMGR_SRCLINK_SIZE +valMgrSrcNoSendErrors: .byte 1 +valMgrSrcOverflowErrors: .byte 1 +valMgrSrcNoAckErrors: .byte 1 +valMgrSrcDataEnd: + + +; *************************************************************************** +; code + +.cseg + +VALMGR_SRC_BEGIN: + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_Init + +VALMGR_Src_Init: + ; preset SRAM data area + ldi xh, HIGH(valMgrSrcDataBegin) + ldi xl, LOW(valMgrSrcDataBegin) + clr r16 + ldi r17, (valMgrSrcDataEnd-valMgrSrcDataBegin) + rcall Utils_FillSram + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_Fini + +VALMGR_Src_Fini: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_ValueInit +; +; @param R16 value id +; @param R17 value type +; @param Y pointer to VALMGR_VAR object +; @clobbers R16 + +VALMGR_Src_ValueInit: + std Y+VALMGR_VAR_OFFS_VALUEID, r16 + std Y+VALMGR_VAR_OFFS_VALUETYPE, r17 + rjmp valMgrSrcResetValue ; (R16) +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_AddSrcLink @global +; +; @return CFLAG set if link found and deleted, cleared otherwise +; @param R16 value id +; @param R17 peer address +; @clobbers (R18, R19, X) + +VALMGR_Src_AddSrcLink: + rcall valMgrSrcFindLink ; (R18, R19, X) + brcs VALMGR_Src_AddSrcLink_retnc ; exists, jmp + rcall valMgrSrcFindFreeLink ; (R18, R19, X) + brcc VALMGR_Src_AddSrcLink_retnc ; no free link + st X+, r16 ; value id + st X+, r17 ; peer address + sec + ret +VALMGR_Src_AddSrcLink_retnc: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_DelSrcLink @global +; +; @return CFLAG set if link found and deleted, cleared otherwise +; @param R16 value id +; @param R17 peer address +; @clobbers R18 (R19, X) + +VALMGR_Src_DelSrcLink: + rcall valMgrSrcFindLink ; (R18, R19, X) + brcs VALMGR_Src_DelSrcLink_retnc ; exists, jmp + clr r18 + st X+, r18 ; value id + st X+, r18 ; peer address + sec + ret +VALMGR_Src_DelSrcLink_retnc: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_ValueSend @global +; Handle sending a REPORT_VALUE packet. +; +; @return CFLAG set if enqueued, cleared on error +; @param R19:R18 value +; @param R21:R20 denom (e.g. 100, meaning value must be divided by 100) +; @param R22 priority +; @param Y pointer to VALMGR_VAR object +; @clobbers any, -Y + +VALMGR_Src_ValueSend: + ldd r16, Y+VALMGR_VAR_OFFS_PRIORITY + tst r16 ; prio==0 (inactive)? + breq VALMGR_Src_ValueSend_setnew ; yes, free to go + cp r22, r16 ; old prio higher? + brcc VALMGR_Src_ValueSend_setnew + ; overflow (buffer still in use with higher priority msg) + lds r16, valMgrSrcOverflowErrors + inc r16 + breq VALMGR_Src_ValueSend_dontCountUp + sts valMgrSrcOverflowErrors, r16 +VALMGR_Src_ValueSend_dontCountUp: + clc + ret +VALMGR_Src_ValueSend_setnew: + std Y+VALMGR_VAR_OFFS_PRIORITY, r22 + std Y+VALMGR_VAR_OFFS_CURRVAL, r18 + std Y+VALMGR_VAR_OFFS_CURRVAL+1, r19 + std Y+VALMGR_VAR_OFFS_CURRVAL+2, r20 + std Y+VALMGR_VAR_OFFS_CURRVAL+3, r21 + ldi r16, VALMGR_SRC_TIMEOUT_SENDVALUE + std Y+VALMGR_VAR_OFFS_TIMERSEND, r16 + ldi r16, VALMGR_SRC_MAX_RESEND + std Y+VALMGR_VAR_OFFS_COUNTERRESEND, r16 + clr r16 + std Y+VALMGR_VAR_OFFS_TIMERACK, r16 + std Y+VALMGR_VAR_OFFS_MSGID, r16 + std Y+VALMGR_VAR_OFFS_MSGID+1, r16 + + ldd r16, Y+VALMGR_VAR_OFFS_VALUEID + rcall valMgrSrcMarkLinks + rcall valMgrSrcSendValue +VALMGR_Src_ValueSend_end: + sec + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_ValueHandleResponse @global +; Handle sending a REPORT_VALUE packet. +; +; @return CFLAG set if handled, cleared otherwise +; @param R17 peer address (sender of the response) +; @param R19:R18 msg id +; @param Y pointer to VALMGR_VAR object +; @clobbers R16 (R18, R19, X) + +VALMGR_Src_ValueHandleResponse: + ldd r16, Y+VALMGR_VAR_OFFS_MSGID + cp r16, r18 + brne VALMGR_Src_ValueHandleResponse_retnc + ldd r16, Y+VALMGR_VAR_OFFS_MSGID+1 + cp r16, r19 + brne VALMGR_Src_ValueHandleResponse_retnc + ldd r16, Y+VALMGR_VAR_OFFS_VALUEID + rcall valMgrSrcUnmarkLink ; (R18, R19, X) + rcall valMgrSrcHasMarkedLinks + brcc VALMGR_Src_ValueHandleResponse_retc + rcall valMgrSrcResetValue ; (R16) +VALMGR_Src_ValueHandleResponse_retc: + sec + ret +VALMGR_Src_ValueHandleResponse_retnc: + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine VALMGR_Src_ValueEvery100ms +; +; @param Y pointer to VALMGR_VAR object +; @clobbers R16 + +VALMGR_Src_ValueEvery100ms: + ldd r16, Y+VALMGR_VAR_OFFS_PRIORITY + tst r16 + brne VALMGR_Src_ValueEvery100ms_active + ret +VALMGR_Src_ValueEvery100ms_active: + rcall valMgrSrcCheckSendTimer + rcall valMgrSrcCheckAckTimer + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcCheckSendTimer +; +; Set MSB in value id of all matching link entries +; @param R16 valueId to activate +; @clobbers any, -Y + +valMgrSrcCheckSendTimer: + ldd r16, Y+VALMGR_VAR_OFFS_TIMERSEND + tst r16 + brne valMgrSrcCheckSendTimer_dec + ret +valMgrSrcCheckSendTimer_dec: + dec r16 + std Y+VALMGR_VAR_OFFS_TIMERSEND, r16 + breq valMgrSrcCheckSendTimer_timeout + rjmp valMgrSrcSendValue ; (any except Y) +valMgrSrcCheckSendTimer_timeout: + lds r16, valMgrSrcNoSendErrors + inc r16 + breq valMgrSrcCheckSendTimer_dontCountUp + sts valMgrSrcNoSendErrors, r16 +valMgrSrcCheckSendTimer_dontCountUp: + rjmp valMgrSrcResetValue +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcCheckAckTimer +; +; Set MSB in value id of all matching link entries +; @param R16 valueId to activate +; @clobbers any, -Y + +valMgrSrcCheckAckTimer: + ldd r16, Y+VALMGR_VAR_OFFS_TIMERACK + tst r16 + brne valMgrSrcCheckAckTimer_dec + ret +valMgrSrcCheckAckTimer_dec: + dec r16 + std Y+VALMGR_VAR_OFFS_TIMERACK, r16 + breq valMgrSrcCheckAckTimer_timeout + ret +valMgrSrcCheckAckTimer_timeout: + lds r16, valMgrSrcNoAckErrors ; inc error counter + inc r16 + breq valMgrSrcCheckAckTimer_tryresend + sts valMgrSrcNoAckErrors, r16 +valMgrSrcCheckAckTimer_tryresend: + ldd r16, Y+VALMGR_VAR_OFFS_COUNTERRESEND + dec r16 + brne valMgrSrcCheckAckTimer_resend + ; resend counter reached zero, abort + ldd r16, Y+VALMGR_VAR_OFFS_VALUEID + rcall valMgrSrcUnmarkLinks ; (R17, R18, X) + rjmp valMgrSrcResetValue ; (R16) +valMgrSrcCheckAckTimer_resend: + std Y+VALMGR_VAR_OFFS_COUNTERRESEND, r16 + ldi r16, VALMGR_SRC_TIMEOUT_SENDVALUE + std Y+VALMGR_VAR_OFFS_TIMERSEND, r16 + rjmp valMgrSrcSendValue ; (any except Y) +; @end + + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcMarkLinks +; +; Set MSB in value id of all matching link entries +; @param R16 valueId to activate +; @clobbers R17, R18, X + +valMgrSrcMarkLinks: + ldi xl, LOW(valMgrSrcLinks) + ldi xh, HIGH(valMgrSrcLinks) + ldi r17, VALMGR_SRC_MAX_LINKS +valMgrSrcMarkLinks_loop: + ld r18, X + andi r18, 0x7f + cp r18, r16 + brne valMgrSrcMarkLinks_next + ori r18, 0x80 + st X, r18 +valMgrSrcMarkLinks_next: + adiw xh:xl, VALMGR_SRCLINK_SIZE + dec r17 + brne valMgrSrcMarkLinks_loop + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcUnmarkLink +; +; Find matching link entry and unmark it (i.e. clear MSB) +; @param R16 valueId to find +; @param R17 source address to find +; @clobbers R18, R19, X + +valMgrSrcUnmarkLink: + rcall valMgrSrcFindLink ; (R18, R19, X) + brcc valMgrMarkSrcLink_end + st X, r16 +valMgrMarkSrcLink_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcFindLink +; +; Find matching link entries +; @return CFLAG set if found, cleared otherwise +; @return X points to link +; @param R16 valueId to find +; @param R17 source address to find +; @clobbers R18, R19, X + +valMgrSrcFindLink: + ldi xl, LOW(valMgrSrcLinks) + ldi xh, HIGH(valMgrSrcLinks) + ldi r19, VALMGR_SRC_MAX_LINKS +valMgrSrcFindLink_loop: + ld r18, X+ + andi r18, 0x7f + cp r18, r16 + brne valMgrSrcFindLink_next1 + ld r18, X+ + cp r18, r17 + brne valMgrSrcFindLink_next2 + sbiw xh:xl, 2 + sec + ret +valMgrSrcFindLink_next1: + adiw xh:xl, VALMGR_SRCLINK_SIZE-1 +valMgrSrcFindLink_next2: + dec r19 + brne valMgrSrcFindLink_loop + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcFindFreeLink +; +; Find matching link entries +; @return CFLAG set if found, cleared otherwise +; @return X points to link +; @clobbers R18, R19, X + +valMgrSrcFindFreeLink: + ldi xl, LOW(valMgrSrcLinks) + ldi xh, HIGH(valMgrSrcLinks) + ldi r19, VALMGR_SRC_MAX_LINKS +valMgrSrcFindFreeLink_loop: + ld r18, X + andi r18, 0x7f + brne valMgrSrcFindFreeLink_next + sec + ret +valMgrSrcFindFreeLink_next: + adiw xh:xl, VALMGR_SRCLINK_SIZE + dec r19 + brne valMgrSrcFindFreeLink_loop + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcUnmarkLinks +; +; Clear MSB in value id of all matching link entries +; @param R16 valueId to activate +; @clobbers R17, R18, X + +valMgrSrcUnmarkLinks: + ldi xl, LOW(valMgrSrcLinks) + ldi xh, HIGH(valMgrSrcLinks) + ldi r17, VALMGR_SRC_MAX_LINKS +valMgrSrcUnmarkLinks_loop: + ld r18, X + andi r18, 0x7f + cp r18, r16 + brne valMgrSrcUnmarkLinks_next + st X, r18 +valMgrSrcUnmarkLinks_next: + adiw xh:xl, VALMGR_SRCLINK_SIZE + dec r17 + brne valMgrSrcUnmarkLinks_loop + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcHasMarkedLinks +; +; Set MSB in value id of all matching link entries +; @param R16 valueId to activate +; @clobbers R17, R18, X + +valMgrSrcHasMarkedLinks: + ldi xl, LOW(valMgrSrcLinks) + ldi xh, HIGH(valMgrSrcLinks) + ldi r17, VALMGR_SRC_MAX_LINKS +valMgrSrcHasMarkedLinks_loop: + ld r18, X + andi r18, 0x7f + cp r18, r16 + brne valMgrSrcHasMarkedLinks_next + sec + ret +valMgrSrcHasMarkedLinks_next: + adiw xh:xl, VALMGR_SRCLINK_SIZE + dec r17 + brne valMgrSrcHasMarkedLinks_loop + clc + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcSendValue +; +; Try to send a value +; +; @return CFLAG set if message sent, cleared otherwise +; @param Y pointer to VALMGR_VAR object +; @clobbers any, -Y + +valMgrSrcSendValue: + ldi xl, LOW(com2SendBuffer) + ldi xh, HIGH(com2SendBuffer) + ldi r16, 0xff ; broadcast + ldd r17, Y+VALMGR_VAR_OFFS_VALUEID + ldd r18, Y+VALMGR_VAR_OFFS_CURRVAL + ldd r19, Y+VALMGR_VAR_OFFS_CURRVAL+1 + ldd r20, Y+VALMGR_VAR_OFFS_CURRVAL+2 + ldd r21, Y+VALMGR_VAR_OFFS_CURRVAL+3 + ldd r22, Y+VALMGR_VAR_OFFS_VALUETYPE + rcall CPRO_WriteReportValue ; (R16, R17, R18, R19, R20, R21) + rcall COM2_SendPacket ; (any) + brcc valMgrSrcSendValue_end ; could not send + ; successfully sent, check for active links for this var + ldd r16, Y+VALMGR_VAR_OFFS_VALUEID + rcall valMgrSrcHasMarkedLinks + brcs valMgrSrcSendValue_prepareWaitForAck + rcall valMgrSrcResetValue + sec + ret +valMgrSrcSendValue_prepareWaitForAck: + clr r16 ; clear timer + std Y+VALMGR_VAR_OFFS_TIMERSEND, r16 + lds r16, com2LastMsgId ; copy last used msg id (we will wait for ACK on this msg) + std Y+VALMGR_VAR_OFFS_MSGID, r16 + lds r16, com2LastMsgId+1 + std Y+VALMGR_VAR_OFFS_MSGID+1, r16 + ldi r16, VALMGR_SRC_TIMEOUT_RECVACK ; start ACK timer + std Y+VALMGR_VAR_OFFS_TIMERACK, r16 + sec +valMgrSrcSendValue_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine valMgrSrcResetValue +; +; Reset value data (e.g. set timers, msgid and priority to 0) +; +; @return CFLAG set if message sent, cleared otherwise +; @param Y pointer to VALMGR_VAR object +; @clobbers r16 + +valMgrSrcResetValue: + clr r16 + std Y+VALMGR_VAR_OFFS_PRIORITY, r16 + std Y+VALMGR_VAR_OFFS_TIMERSEND, r16 + std Y+VALMGR_VAR_OFFS_COUNTERRESEND, r16 + std Y+VALMGR_VAR_OFFS_MSGID, r16 + std Y+VALMGR_VAR_OFFS_MSGID+1, r16 + ret +; @end + + + +VALMGR_SRC_END: +.equ MODULE_SIZE_VALMGR_SRC = VALMGR_SRC_END-VALMGR_SRC_BEGIN +