avr: started adding com2wn module (multiple com2w devices in one)
This commit is contained in:
242
avr/modules/com2w/com2wn_recv.asm
Normal file
242
avr/modules/com2w/com2wn_recv.asm
Normal file
@@ -0,0 +1,242 @@
|
||||
; ***************************************************************************
|
||||
; 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_COM2WN_RECV_H
|
||||
#define AVR_MODULES_COM2W_COM2WN_RECV_H
|
||||
|
||||
|
||||
; WORK IN PROGRESS
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wnActOnClock @global
|
||||
;
|
||||
; @param r16 CLK input (0 or !=0)
|
||||
; @param r17 DATA input (0 or !=0)
|
||||
; @param Y pointer to IFACE data
|
||||
; @clobbers r16 (r17, r18, X)
|
||||
|
||||
com2wnActOnClock:
|
||||
tst r16
|
||||
brne com2wnActOnClock_clockHigh
|
||||
; clock low
|
||||
ldd r18, Y+COM2W_IFACE_OFFS_MODE
|
||||
cpi r18, COM2W_MODE_IDLE
|
||||
breq com2wnActOnClock_startReading
|
||||
cpi r18, COM2W_MODE_SKIPPING
|
||||
breq com2wnActOnClock_skipping
|
||||
rjmp com2wnActOnClock_end
|
||||
com2wnActOnClock_skipping:
|
||||
; ldd r18, Y+COM2W_IFACE_OFFS_MODECOUNTER
|
||||
; cpi r18, COM2W_SKIPPING_MAXMODECOUNTER
|
||||
; brcc com2wnActOnClock_startReading
|
||||
rjmp com2wnActOnClock_end
|
||||
com2wnActOnClock_startReading:
|
||||
rcall com2wnStartReading ; (r16, r17, X)
|
||||
rjmp com2wnActOnClock_end
|
||||
com2wnActOnClock_clockHigh:
|
||||
ldd r18, Y+COM2W_IFACE_OFFS_MODE
|
||||
cpi r18, COM2W_MODE_READING
|
||||
brne com2wnActOnClock_end
|
||||
|
||||
push r20
|
||||
push r22
|
||||
rcall com2wnReadNextBit ; (r16, r17, r18, r20, r22)
|
||||
pop r22
|
||||
pop r20
|
||||
|
||||
com2wnActOnClock_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wnReadNextBit @global
|
||||
;
|
||||
; @param r17 DATA input (0 or !=0)
|
||||
; @clobbers r16, r17, r18, r20, r22
|
||||
|
||||
com2wnReadNextBit:
|
||||
; ldi r20, 50 ; wait for up to 250us for clock rise
|
||||
; rcall com2w0WaitForClockHighMulti5Us ; (R20, R22)
|
||||
; brcc com2wnReadNextBit_end
|
||||
; clock is high now, read bit
|
||||
; reset read timer (for leaving skipping mode)
|
||||
clr r16
|
||||
std Y+NET_IFACE_OFFS_READTIMER, r16
|
||||
; check mode
|
||||
ldd r16, Y+COM2W_IFACE_OFFS_MODE
|
||||
cpi r16, COM2W_MODE_READING
|
||||
brne com2wnReadNextBit_end
|
||||
; handle received bit
|
||||
ldd r16, Y+COM2W_IFACE_OFFS_CURRBYTE
|
||||
ldd r18, Y+COM2W_IFACE_OFFS_BITCOUNTER
|
||||
tst r17 ; data port input
|
||||
clc
|
||||
breq com2wnReadNextBit_clockData
|
||||
sec
|
||||
com2wnReadNextBit_clockData:
|
||||
ror r16
|
||||
std Y+COM2W_IFACE_OFFS_CURRBYTE, r16
|
||||
inc r18 ; bit counter
|
||||
std Y+COM2W_IFACE_OFFS_BITCOUNTER, r18
|
||||
cpi r18, 8
|
||||
brne com2wnReadNextBit_end
|
||||
; write byte into buffer
|
||||
push xl
|
||||
push xh
|
||||
rcall com2wnByteRecvd ; (r16, r17, r18, X)
|
||||
pop xh
|
||||
pop xl
|
||||
; prepare for next byte
|
||||
clr r16
|
||||
std Y+COM2W_IFACE_OFFS_BITCOUNTER, r16
|
||||
std Y+COM2W_IFACE_OFFS_CURRBYTE, r16
|
||||
com2wnReadNextBit_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wnByteRecvd
|
||||
;
|
||||
; @param r16 byte received
|
||||
; @param Y pointer to interface data
|
||||
; @return CFLAG set if okay, cleared on error
|
||||
; @clobbers r16, r17, r18, X
|
||||
|
||||
com2wnByteRecvd:
|
||||
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 com2wnByteRecvd_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 com2wnByteRecvd_msgComplete
|
||||
cpi r18, 2
|
||||
sec
|
||||
brne com2wnByteRecvd_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 com2wnByteRecvd_eMsgSize
|
||||
std Y+COM2W_IFACE_OFFS_BUFLEFT, r16
|
||||
tst r16
|
||||
sec
|
||||
brne com2wnByteRecvd_end
|
||||
com2wnByteRecvd_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 com2wnMsgReceived ; (R16, R17, R18, R19, R20, R24, R25, X, Z)
|
||||
pop zh
|
||||
pop zl
|
||||
pop r25
|
||||
pop r24
|
||||
pop r20
|
||||
pop r19
|
||||
rjmp com2wnByteRecvd_end
|
||||
com2wnByteRecvd_overflow:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
|
||||
rjmp com2wnByteRecvd_error
|
||||
com2wnByteRecvd_eMsgSize:
|
||||
|
||||
ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW
|
||||
com2wnByteRecvd_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
|
||||
com2wnByteRecvd_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wnMsgReceived
|
||||
;
|
||||
; @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)
|
||||
|
||||
com2wnMsgReceived:
|
||||
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 com2wnMsgReceived_econtent
|
||||
; msg valid, alloc buffer
|
||||
rcall NET_Buffer_Alloc ; X=buffer, R16=bufnum (R16, R17, X)
|
||||
brcc com2wnMsgReceived_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
|
||||
com2wnMsgReceived_copyLoop:
|
||||
ld r16, Z+
|
||||
st X+, r16
|
||||
dec r17
|
||||
brne com2wnMsgReceived_copyLoop
|
||||
mov r16, r18 ; buffer num
|
||||
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
|
||||
brcc com2wnMsgReceived_enoadd
|
||||
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
sec
|
||||
rjmp com2wnMsgReceived_setIdleAndEnd
|
||||
com2wnMsgReceived_enoadd:
|
||||
rcall NET_Buffer_ReleaseByNum
|
||||
rjmp com2wnMsgReceived_enobuf
|
||||
com2wnMsgReceived_enobuf:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
|
||||
rjmp com2wnMsgReceived_err
|
||||
com2wnMsgReceived_econtent:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
|
||||
com2wnMsgReceived_err:
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
clc
|
||||
com2wnMsgReceived_setIdleAndEnd:
|
||||
ldi r16, COM2W_MODE_IDLE
|
||||
rcall com2wSetMode ; (R17, doesn't change CFLAG!)
|
||||
com2wnMsgReceived_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif ; AVR_MODULES_COM2W_COM2WN_RECV_H
|
||||
|
||||
Reference in New Issue
Block a user