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).
245 lines
6.4 KiB
NASM
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
|
|
|