Files
aqhomecontrol/avr/modules/com2/main.asm
2024-12-15 18:20:54 +01:00

349 lines
8.8 KiB
NASM

; ***************************************************************************
; copyright : (C) 2023 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. *
; ***************************************************************************
.include "modules/com2/buffer.asm"
; ***************************************************************************
; data
.dseg
com2DataBegin:
com2Address: .byte 1
com2Interrupts: .byte 2
com2LastMsgId: .byte 2
com2RecvStatsBegin: ; 12 bytes
com2StatsPacketsIn: .byte 2
com2StatsContentError: .byte 2
com2StatsIoError: .byte 2
com2StatsNoBufferError: .byte 2
com2StatsHandled: .byte 2
com2StatsMissed: .byte 2 ; currently not used
com2RecvStatsEnd:
com2SendStatsBegin: ; 6 bytes
com2StatsPacketsOut: .byte 2
com2StatsCollisions: .byte 2
com2StatsBusyError: .byte 2
com2SendStatsEnd:
com2StatsNotForMe: .byte 2
com2StatsIgnored: .byte 2
com2MaxSendBuffersUsed: .byte 1
com2MaxRecvBuffersUsed: .byte 1
com2SendBuffer: .byte COM2_BUFFER_SIZE
com2DataEnd:
; ***************************************************************************
; code
.cseg
COM2_BEGIN:
; ---------------------------------------------------------------------------
; @routine Com2_Init @global
;
; @return CFLAG set if okay, clear on error
; @clobbers R16, R17, X, Y
Com2_Init:
; preset SRAM data area
ldi xh, HIGH(com2DataBegin)
ldi xl, LOW(com2DataBegin)
clr r16
ldi r17, (com2DataEnd-com2DataBegin)
rcall Utils_FillSram
; set address to 0 (will be updated later)
clr r16
sts com2Address, r16
rjmp COMIO_Init
; @end
; ---------------------------------------------------------------------------
; @routine Com2_Run @global
;
; @return CFLAG set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry)
; @clobbers (R1, R3, R16, R17, R18, R19, R22, X)
COM2_Run:
rcall COMIO_Run
brcs COM2_Run_carrySet
rjmp com2HandleNextPacketInQueue ; return CFLAG from com2HandleNextPacketInQueue
COM2_Run_carrySet:
rcall com2HandleNextPacketInQueue
sec ; return CFLAG set regardless of com2HandleNextPacketInQueue
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2HandleNextPacketInQueue
;
; Get next received packet, call onPacketReceived on it and release it
; @return CFLAG set if something done
; @clobbers any
com2HandleNextPacketInQueue:
rcall COMIO_GetNextReceivedPacket
brcc com2HandleNextPacketInQueue_retNc
push xl
push xh
rcall com2CheckMessageInBuffer
pop xh
pop xl
brcs com2HandleNextPacketInQueue_crcOk
ldi xl, LOW(com2StatsContentError)
ldi xh, HIGH(com2StatsContentError)
rjmp com2HandleNextPacketInQueue_incCounterDeallocBuffer
com2HandleNextPacketInQueue_crcOk:
rcall onPacketReceived
brcs com2HandleNextPacketInQueue_handled
ldi xl, LOW(com2StatsIgnored)
ldi xh, HIGH(com2StatsIgnored)
rjmp com2HandleNextPacketInQueue_incCounterDeallocBuffer
com2HandleNextPacketInQueue_handled:
ldi xl, LOW(com2StatsHandled)
ldi xh, HIGH(com2StatsHandled)
com2HandleNextPacketInQueue_incCounterDeallocBuffer:
rcall Utils_IncrementCounter16 ; (r18, r19, r22)
rcall COMIO_ReleaseReceivedPacket
sec
ret
com2HandleNextPacketInQueue_retNc:
clc
ret
; @end
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Preparing messages
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; @routine COM2_WriteMsgWithCmdAndSrcAddr @global
;
; Write a simple packet into the given buffer with payload being only CMD and source address.
;
; IN:
; @param R16 destination address
; @param R18 command (e.g. CPRO_CMD_PING or CPRO_CMD_PONG)
; @param X pointer to buffer to write to
; @return CFLAG set if okay, clear otherwise
; @clobbers R16, R17, X, Y (R3, R4, R15, R16, R17, R18, R19, R20, R21)
COM2_WriteMsgWithCmdAndSrcAddr:
ldi r17, COM2_PAYLOAD_FLAGS_SECONDS
push xh
push xl
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
pop xl
pop xh
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
sec
ret
COM2_WriteMsgWithCmdAndSrcAddr_error:
clc
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2_BeginMsgWithVariablePayload @global
;
; begin packet with variable payload.
;
; @param R16 destination address
; @param R17 flags
; @param R18 command (e.g. CPRO_CMD_PING)
; @param X pointer to packet buffer
; @return X points to end of packet as it was written so far
; @clobbers R3, R16, R17, R18, R19, R20, R21, X (R4)
COM2_BeginMsgWithVariablePayload:
; write header (dest address, msg length)
st X+, r16 ; destination address
mov r16, r17 ; calculate payload size
mov r3, r17
rcall com2CalcPayloadSize ; (R4, R16, R17)
inc r16 ; add CMD byte
inc r16 ; add source address byte
st X+, r16
; write payload
st X+, r18 ; 0: CMD
lds r16, com2Address ; 1: source address
st X+, r16
lsr r3 ; shift out COM2_PAYLOAD_FLAGS_SECONDS
brcc COM2_BeginMsgWithVariablePayload_l1
; write seconds
rcall COM2_AddSecsToBuffer
COM2_BeginMsgWithVariablePayload_l1:
lsr r3 ; shift out COM2_PAYLOAD_FLAGS_UID
brcc COM2_BeginMsgWithVariablePayload_l2
; write uid
rcall COM2_AddUidToBuffer
COM2_BeginMsgWithVariablePayload_l2:
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2_AddUidToBuffer @global
;
; Write UID into buffer given by X.
;
; @return X points to behind written uid
; @param X pointer to packet buffer
; @clobbers: r18, r19, r20, r21 (r16)
COM2_AddUidToBuffer:
push xh
push xl
rcall Utils_ReadUid ; (R16, X)
pop xl
pop xh
st X+, r18
st X+, r19
st X+, r20
st X+, r21
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2_AddSecsToBuffer @global
;
; Write current seconds counter (4 bytes) into buffer given by X, advance X.
;
; @return X points to behind written seconds
; @param X pointer to packet buffer
; @clobbers r16
COM2_AddSecsToBuffer:
lds r16, timerModuleCounterSecs ; add current seconds counter
st X+, r16
lds r16, timerModuleCounterSecs+1
st X+, r16
lds r16, timerModuleCounterSecs+2
st X+, r16
lds r16, timerModuleCounterSecs+3
st X+, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2_AddNextMsgIdToBuffer @global
;
; Write next message id (2 bytes) into buffer given by X, advance X.
;
; @return X points to behind written message id
; @param X pointer to packet buffer
; @clobbers: r16, r17, r18
COM2_AddNextMsgIdToBuffer:
ldi r18, 1
lds r16, com2LastMsgId
lds r17, com2LastMsgId+1
add r16, r18
dec r18
adc r17, r18
sts com2LastMsgId, r16
sts com2LastMsgId+1, r17
st X+, r16
st X+, r17
ret
; @end
; ---------------------------------------------------------------------------
; com2CalcPayloadSize
;
; Calculate payload size from given flags
;
; @param R16 flags
; @return R16 payload size
; @clobbers R4, R16, R17
com2CalcPayloadSize:
clr r4
ldi r17, 4
lsr r16 ; shift out COM2_PAYLOAD_FLAGS_SECONDS
brcc com2CalcPayloadSize_l1
add r4, r17 ; add 4 bytes
com2CalcPayloadSize_l1:
lsr r16 ; shift out COM2_PAYLOAD_FLAGS_UID
brcc com2CalcPayloadSize_l2
add r4, r17 ; add 4 bytes
com2CalcPayloadSize_l2:
lsr r16 ; shift out reserved1, after this R16 contains COM2_PAYLOAD_FLAGS_NUM0-4
add r16, r4 ; add previous bytes to R16
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2_SendPacket
;
; send packet from sendBuffer, if line free.
;
; @return CFLAG set if okay (packet sent), cleared on error
; @clobbers any (depending on io implementation)
COM2_SendPacket:
ldi xl, LOW(com2SendBuffer)
ldi xh, HIGH(com2SendBuffer)
rjmp COMIO_SendPacket
; @end
.include "modules/com2/crc.asm"
COM2_END:
.equ MODULE_SIZE_COM2 = COM2_END-COM2_BEGIN