Files
aqhomecontrol/avr/modules/com2w/common.asm
Martin Preuss bdd710fc5c avr: started working on new SPI-like COM protocol.
use a clock and a data line to introduce synchronisation into the
protocol to be able to work with the wide range of mcu speeds (no need for
exact timing, no need for exact calibration).
2025-07-19 09:42:02 +02:00

245 lines
6.4 KiB
NASM

; ***************************************************************************
; copyright : (C) 2025 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 AVR_MODULES_COM2W_COMMON_H
#define AVR_MODULES_COM2W_COMMON_H
; ---------------------------------------------------------------------------
; @routine com2wPeriodically @global
;
; @clobbers R16, Y
com2wPeriodically:
push r15
in r15, SREG
cli
rcall NET_Interface_Periodically
ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER
inc r16
breq com2wPeriodically_end
std Y+COM2W_IFACE_OFFS_MODECOUNTER, r16
com2wPeriodically_end:
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wSetMode
;
; Doesn't change processor status flags!
;
; @param R16 mode
; @clobbers R17
com2wSetMode:
push r15
in r15, SREG
cli
ldd r17, Y+COM2W_IFACE_OFFS_MODE
cp r16, r17
breq com2wSetMode_end
std Y+COM2W_IFACE_OFFS_MODE, r16
clr r17
std Y+COM2W_IFACE_OFFS_MODECOUNTER, r17
com2wSetMode_end:
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wStartReading
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, X
com2wStartReading:
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
std Y+COM2W_IFACE_OFFS_BUFPOS_LOW, xl
std Y+COM2W_IFACE_OFFS_BUFPOS_HIGH, xh
ldi r16, COM2W_BUFFER_SIZE
std Y+COM2W_IFACE_OFFS_BUFLEFT, r16
clr r16
std Y+COM2W_IFACE_OFFS_BUFUSED, r16
ldi r16, COM2W_MODE_READING
rcall com2wSetMode ; (R17)
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wByteRecvd
;
; @param r16 byte received
; @param Y pointer to interface data
; @return CFLAG set if okay, cleared on error
; @clobbers r16, r17, r18, X
com2wByteRecvd:
ldd xl, Y+COM2W_IFACE_OFFS_BUFPOS_LOW
ldd xh, Y+COM2W_IFACE_OFFS_BUFPOS_HIGH
ldd r17, Y+COM2W_IFACE_OFFS_BUFLEFT
ldd r18, Y+COM2W_IFACE_OFFS_BUFUSED
tst r17
breq com2wByteRecvd_overflow
st X+, r16
std Y+COM2W_IFACE_OFFS_BUFPOS_LOW, xl
std Y+COM2W_IFACE_OFFS_BUFPOS_HIGH, xh
inc r18
std Y+COM2W_IFACE_OFFS_BUFUSED, r18
dec r17
std Y+COM2W_IFACE_OFFS_BUFLEFT, r17
breq com2wByteRecvd_msgComplete
cpi r18, 2
sec
brne com2wByteRecvd_end
; determine msg size
inc r16 ; last byte was payload length, add byte for crc
cp r17, r16 ; compare remaining length against remaining space
brcs com2wByteRecvd_eMsgSize
std Y+COM2W_IFACE_OFFS_BUFLEFT, r16
tst r16
sec
brne com2wByteRecvd_end
com2wByteRecvd_msgComplete:
push r19 ; pushing these registers is now only needed *here* for every
push r20 ; message received. Otherwise they would have been pushed
push r24 ; on every bit adding much more execution time to the
push r25 ; irq service routine
push zl
push zh
rcall com2wMsgReceived ; (R16, R17, R18, R19, R20, R24, R25, X, Z)
pop zh
pop zl
pop r25
pop r24
pop r20
pop r19
rjmp com2wByteRecvd_end
com2wByteRecvd_overflow:
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
rjmp com2wByteRecvd_error
com2wByteRecvd_eMsgSize:
ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW
com2wByteRecvd_error:
push r24
push r25
rcall NET_Interface_IncCounter16 ; (R24, R25)
pop r25
pop r24
ldi r16, COM2W_MODE_SKIPPING ; error, enter skipping mode
rcall com2wSetMode
clc
com2wByteRecvd_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wMsgReceived
;
; @param Y pointer to interface data in SRAM
; @return CFLAG set if okay, cleared on error
; @clobbers R16, R17, R18, X, Z (R19, R20, R24, R25)
com2wMsgReceived:
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
mov zl, xl ; Z=buffer in IFACE
mov zh, xh
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
brcc com2wMsgReceived_econtent
; msg valid, alloc buffer
rcall NET_Buffer_Alloc ; X=buffer, R16=bufnum (R16, R17, X)
brcc com2wMsgReceived_enobuf
mov r18, r16 ; buffer num
rcall NET_Interface_SetIfaceNumInBuffer ; (R16, R17)
adiw xh:xl, 1 ; skip buffer header
ldd r17, Y+COM2W_IFACE_OFFS_BUFUSED ; always is at least 2 here
com2wMsgReceived_copyLoop:
ld r16, Z+
st X+, r16
dec r17
brne com2wMsgReceived_copyLoop
mov r16, r18 ; buffer num
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
brcc com2wMsgReceived_enoadd
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
sec
rjmp com2wMsgReceived_setIdleAndEnd
com2wMsgReceived_enoadd:
rcall NET_Buffer_ReleaseByNum
rjmp com2wMsgReceived_enobuf
com2wMsgReceived_enobuf:
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rjmp com2wMsgReceived_err
com2wMsgReceived_econtent:
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
com2wMsgReceived_err:
rcall NET_Interface_IncCounter16 ; (R24, R25)
clc
com2wMsgReceived_setIdleAndEnd:
ldi r16, COM2W_MODE_IDLE
rcall com2wSetMode ; (R17, doesn't change CFLAG!)
com2wMsgReceived_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wWaitTime1
;
; waits for longer period (e.g. 30ns)
;
; @clobbers R22
com2wWaitTime1:
Utils_WaitNanoSecs COM2W_WAITTIME1, 7, r22 ; wait for longer time (minus RCALL and RET)
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wWaitTime2
;
; waits for shorter period (e.g. 10ns)
;
; @clobbers R22
com2wWaitTime2:
Utils_WaitNanoSecs COM2W_WAITTIME2, 7, r22 ; wait for shorter time (minus RCALL and RET)
ret
; @end
#endif ; AVR_MODULES_COM2W_COMMON_H