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).
This commit is contained in:
@@ -96,6 +96,21 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef MODULES_COM2W
|
||||
.include "modules/com2w/defs.asm"
|
||||
.include "modules/com2w/com2w.asm"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef MODULES_COM2W1
|
||||
.include "modules/com2w/defs.asm"
|
||||
.include "modules/com2w/common.asm"
|
||||
.include "modules/com2w/com2w1.asm"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODULES_CLOCK
|
||||
.include "modules/clock/main.asm"
|
||||
#endif
|
||||
|
||||
@@ -135,6 +135,19 @@ onSystemTimerTick:
|
||||
bigcall ComOnUart1_Periodically
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W
|
||||
bigcall COM2W_Every100ms
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODULES_COM2W0
|
||||
bigcall COM2W0_Periodically
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W1
|
||||
bigcall COM2W1_Periodically
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_TCRT1000
|
||||
bigcall TCRT1K_Every100ms
|
||||
#endif
|
||||
|
||||
@@ -81,6 +81,18 @@ initModules:
|
||||
bigcall ComOnUart1_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W
|
||||
bigcall COM2W_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W0
|
||||
bigcall COM2W0_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W1
|
||||
bigcall COM2W1_Init
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_MOTION
|
||||
bigcall Motion_Init
|
||||
#endif
|
||||
@@ -223,6 +235,21 @@ runComModules_loop:
|
||||
pop r16
|
||||
sbci r16, 0
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W0
|
||||
push r16
|
||||
bigcall COM2W0_Run
|
||||
pop r16
|
||||
sbci r16, 0
|
||||
#endif
|
||||
|
||||
#ifdef MODULES_COM2W1
|
||||
push r16
|
||||
bigcall COM2W1_Run
|
||||
pop r16
|
||||
sbci r16, 0
|
||||
#endif
|
||||
|
||||
pop r17
|
||||
; check for repeat request
|
||||
tst r16
|
||||
|
||||
664
avr/modules/com2w/com2w.asm
Normal file
664
avr/modules/com2w/com2w.asm
Normal file
@@ -0,0 +1,664 @@
|
||||
; ***************************************************************************
|
||||
; 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_COM2W_H
|
||||
#define AVR_MODULES_COM2W_COM2W_H
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
com2w_iface: .byte COM2W_IFACE_SIZE
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W_Init
|
||||
;
|
||||
; @clobbers
|
||||
|
||||
COM2W_Init:
|
||||
ldi yl, LOW(com2w_iface)
|
||||
ldi yh, HIGH(com2w_iface)
|
||||
rcall NET_Interface_Init ; (R16, R17, X)
|
||||
|
||||
; setup CLK line (as input, disable internal pull-up resistor)
|
||||
cbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as input
|
||||
.ifdef COM_CLK_PUE
|
||||
inr r16, COM_CLK_PUE
|
||||
cbr r16, (1<<COM_CLK_PIN) ; disable pullup on CLK
|
||||
outr COM_CLK_PUE, r16
|
||||
.else
|
||||
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; disable pullup on CLK
|
||||
.endif
|
||||
|
||||
; setup DATA line (as input, disable internal pull-up resistor)
|
||||
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as input
|
||||
.ifdef COM_DATA_PUE
|
||||
inr r16, COM_DATA_PUE
|
||||
cbr r16, (1<<COM_DATA_PIN) ; disable pullup on DATA
|
||||
outr COM_DATA_PUE, r16
|
||||
.else
|
||||
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable pullup on DATA
|
||||
.endif
|
||||
|
||||
; setup pin-change interrupt for CLK
|
||||
rcall com2wEnableClkIrq
|
||||
|
||||
inr r16, COM_IRQ_ADDR_CLK
|
||||
sbr r16, (1<<COM_IRQ_BIT_CLK) ; enable pin change irq for ATTN line
|
||||
outr COM_IRQ_ADDR_CLK, r16
|
||||
|
||||
inr r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
|
||||
sbr r16, (1<<COM_IRQ_GIMSK_CLK)
|
||||
outr GIMSK, r16
|
||||
ldi r16, (1<<COM_IRQ_GIFR_CLK) ; clear pending irq by writing 1 to ATTN bit
|
||||
outr GIFR, r16
|
||||
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W_Every100ms @global
|
||||
;
|
||||
; @clobbers R16, Y
|
||||
|
||||
COM2W_Every100ms:
|
||||
ldi yl, LOW(com2w_iface)
|
||||
ldi yh, HIGH(com2w_iface)
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
rcall NET_Interface_Periodically ; (R16)
|
||||
rcall com2wSendNextPkg
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wReceiveNextPkg
|
||||
;
|
||||
; Receive packet.
|
||||
;
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers R16, R17, R18, R19, R20, R22, R24, R25, X
|
||||
|
||||
com2wReceiveNextPkg:
|
||||
; ldi r20, 3 ; make sure clock remains low for at least 15us
|
||||
; rcall com2wWaitForClockHighMulti5Us ; (R20, R22)
|
||||
; brcs com2wReceiveNextPkg_end ; clock got high quite soon, maybe just flaky line
|
||||
|
||||
rcall NET_Buffer_Alloc ; R16=buffer num (R16, R17, X)
|
||||
brcs com2wReceiveNextPkg_gotBuffer
|
||||
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
rjmp com2wReceiveNextPkg_end
|
||||
com2wReceiveNextPkg_gotBuffer:
|
||||
push r16 ; buffer number
|
||||
rcall NET_Interface_SetIfaceNumInBuffer ; (R16, R17)
|
||||
adiw xh:xl, 1
|
||||
ldd r18, Y+NET_IFACE_OFFS_ADDRESS
|
||||
ldi r19, NET_BUFFERS_SIZE-1
|
||||
rcall com2wReceiveAndCheckMsg ; (R16, R17, R18, R19, R20, R22, R24, R25)
|
||||
pop r16
|
||||
brcc com2wReceiveNextPkg_relBuffer
|
||||
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
|
||||
brcs com2wReceiveNextPkg_end
|
||||
|
||||
; debug
|
||||
push r18
|
||||
push r19
|
||||
rcall LedSimple_SetFastTiming
|
||||
pop r19
|
||||
pop r18
|
||||
|
||||
push r16
|
||||
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
pop r16
|
||||
; fall-through to release buffer
|
||||
com2wReceiveNextPkg_relBuffer:
|
||||
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||
com2wReceiveNextPkg_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wReceiveAndCheckMsg
|
||||
;
|
||||
; Receive a packet into buffer pointed to by X.
|
||||
; Expects interrupts to be disabled.
|
||||
;
|
||||
; @param R18 COM address to listen to
|
||||
; @param R19 max buffer size
|
||||
; @param X buffer to receive to
|
||||
; @return CFLAG set if msg received, cleared on error
|
||||
; @clobbers R16 (R17, R18, R19, R20, R22, R24, R25)
|
||||
|
||||
com2wReceiveAndCheckMsg:
|
||||
push xl
|
||||
push xh
|
||||
rcall com2wRecvMsg ; (r16, r17, r18, r19, r20, r22, r24, r25, X)
|
||||
pop xh
|
||||
pop xl
|
||||
brcs com2wReceiveAndCheckMsg_recvd
|
||||
; fall-through, return with CF cleared (from com2wRecvMsg)
|
||||
ret
|
||||
com2wReceiveAndCheckMsg_recvd:
|
||||
push xl
|
||||
push xh
|
||||
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
|
||||
pop xh
|
||||
pop xl
|
||||
brcs com2wReceiveAndCheckMsg_msgOk
|
||||
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
clc
|
||||
ret
|
||||
com2wReceiveAndCheckMsg_msgOk:
|
||||
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
sec
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wSendNextPkg @global
|
||||
;
|
||||
; Check whether there is an outgoing message in interface data
|
||||
; and send it if possible.
|
||||
;
|
||||
; @return CFLAG set if okay, clear on error
|
||||
; @param Y pointer to start of interface data
|
||||
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)
|
||||
|
||||
com2wSendNextPkg:
|
||||
rcall NET_Interface_PeekNextOutgoingMsgNum ; (R17, R18, X)
|
||||
brcc com2wSendNextPkg_end
|
||||
rcall NET_Buffer_Locate ; get pointer to buffer (R17)
|
||||
brcc com2wSendNextPkg_end
|
||||
adiw xh:xl, 1 ; skip buffer header
|
||||
rcall com2wSendMsg ; (R16, R18, R20, R22, R24, R25, X)
|
||||
brcc com2wSendNextPkg_end
|
||||
rcall NET_Interface_GetNextOutgoingMsgNum ; remove from stack (R17, R18, X)
|
||||
rcall NET_Buffer_ReleaseByNum ; release buffer (R16, X)
|
||||
sec
|
||||
com2wSendNextPkg_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wSendMsg
|
||||
;
|
||||
; @param X pointer to bytes to send
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @return CFLAG set if message sent, cleared otherwise
|
||||
; @clobbers R16, R18 (R20, R22, R24, R25, X)
|
||||
|
||||
com2wSendMsg:
|
||||
ldi r20, 11 ; wait for about 55us for clock low
|
||||
rcall com2wWaitForClockLowMulti5Us
|
||||
brcs com2wSendMsg_busy ; CLK got low while waiting, so line is busy
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli ; atomic disable irq and set CLK low
|
||||
rcall com2wDisableClkIrq ; (none)
|
||||
rcall com2wClkSetLow ; reserve bus (none)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
adiw xh:xl, NETMSG_OFFS_MSGLEN
|
||||
ld r18, X
|
||||
sbiw xh:xl, NETMSG_OFFS_MSGLEN
|
||||
inc r18 ; adjust for DESTADDR
|
||||
inc r18 ; adjust for MSGLEN
|
||||
inc r18 ; adjust for CRCBYTE
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
rcall com2wSendBytes ; (r16, r17, r18, r22, X)
|
||||
rcall com2wClkSetHigh ; make sure bus is released
|
||||
rcall com2wDataSetHigh
|
||||
|
||||
rcall com2wEnableClkIrq ; (none)
|
||||
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
sec
|
||||
ret
|
||||
com2wSendMsg_busy:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wSendBytes
|
||||
;
|
||||
; @param R18 number of bytes to send
|
||||
; @param X pointer to bytes to send
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @clobbers: r16, r18, X (r17, r22)
|
||||
|
||||
com2wSendBytes:
|
||||
com2wSendBytes_loop:
|
||||
rcall com2wClkSetLow ; (none)
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
ld r16, X+
|
||||
rcall com2wSendByte ; (R16, R17, R22)
|
||||
dec r18
|
||||
brne com2wSendBytes_loop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wSendByte
|
||||
;
|
||||
; @param R16 byte to send
|
||||
; @clobbers: r16, r17 (r22)
|
||||
|
||||
com2wSendByte:
|
||||
ldi r17, 8
|
||||
com2wSendByte_loop:
|
||||
rcall com2wClkSetLow
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
lsr r16
|
||||
brcs com2wSendByte_send1
|
||||
rcall com2wDataSetLow
|
||||
rjmp com2wSendByte_sent
|
||||
com2wSendByte_send1:
|
||||
rcall com2wDataSetHigh
|
||||
com2wSendByte_sent:
|
||||
rcall com2wWaitTime2 ; shorter wait period (R22)
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli ; ensure time period by disabling irqs
|
||||
rcall com2wClkSetHigh
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
dec r17
|
||||
brne com2wSendByte_loop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wRecvMsg
|
||||
;
|
||||
; Receive a packet into buffer pointed to by X.
|
||||
; Expects interrupts to be disabled.
|
||||
;
|
||||
; @param R18 COM address to listen to
|
||||
; @param R19 max buffer size
|
||||
; @param X buffer to receive to
|
||||
; @return CFLAG set if msg received, cleared on error (see R16)
|
||||
; @return R16 if CFLAG cleared: 0=message not for this node, otherwise error
|
||||
; @clobbers r16, r17, r18, r19, r20, r22, r24, r25, X
|
||||
|
||||
com2wRecvMsg:
|
||||
mov r21, r18 ; address
|
||||
; read destination address
|
||||
rcall com2wRecvByte ; (r17, r18, r20, r22)
|
||||
brcc com2wRecvMsg_eIo
|
||||
; check destination address
|
||||
rjmp com2wRecvMsg_forMe ; DEBUG: don't check address
|
||||
cp r16, r21
|
||||
breq com2wRecvMsg_forMe
|
||||
cpi r16, 0xff
|
||||
breq com2wRecvMsg_forMe
|
||||
clr r16
|
||||
rjmp com2wRecvMsg_clcRet
|
||||
com2wRecvMsg_forMe:
|
||||
; store in buffer
|
||||
subi r19, 1
|
||||
brcs com2wRecvMsg_eBadSize
|
||||
st X+, r16
|
||||
|
||||
; read remaining msg size
|
||||
rcall com2wRecvByte ; (r17, r18, r20, r22)
|
||||
brcc com2wRecvMsg_eIo
|
||||
; store in buffer
|
||||
subi r19, 1
|
||||
brcs com2wRecvMsg_eBadSize
|
||||
st X+, r16
|
||||
inc r16 ; account for CRC byte
|
||||
sub r19, r16
|
||||
brcs com2wRecvMsg_eBadSize
|
||||
mov r19, r16
|
||||
com2wRecvMsg_loop:
|
||||
rcall com2wRecvByte ; (r17, r18, r20, r22)
|
||||
brcc com2wRecvMsg_eIo
|
||||
st X+, r16
|
||||
dec r19
|
||||
brne com2wRecvMsg_loop
|
||||
sec
|
||||
rjmp com2wRecvMsg_end
|
||||
com2wRecvMsg_eBadSize:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW
|
||||
rjmp com2wRecvMsg_incCounterRet
|
||||
com2wRecvMsg_eIo:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_IO_LOW
|
||||
com2wRecvMsg_incCounterRet:
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
com2wRecvMsg_clcRet:
|
||||
clc
|
||||
com2wRecvMsg_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wRecvByte
|
||||
;
|
||||
; @return CFLAG set if byte received, cleared on error
|
||||
; @return r16 byte received
|
||||
; @clobbers r17, r18, r20, r22
|
||||
|
||||
com2wRecvByte:
|
||||
ldi r17, 8
|
||||
clr r16
|
||||
com2wRecvByte_loop:
|
||||
ldi r20, 31 ; wait up to 155us for clock low
|
||||
rcall com2wWaitForClockLowMulti5Us ; (R20, R22)
|
||||
brcs com2wRecvByte_waitForClkHigh
|
||||
ldi r20, 31 ; wait up to 155us for clock low
|
||||
rcall com2wWaitForClockLowMulti5Us ; (R20, R22)
|
||||
brcc com2wRecvByte_end
|
||||
com2wRecvByte_waitForClkHigh:
|
||||
ldi r20, 31 ; wait up to 155us for clock high
|
||||
rcall com2wWaitForClockHighMulti5Us ; (R20, R22)
|
||||
brcs com2wRecvByte_readBit
|
||||
ldi r20, 31 ; wait up to 155us for clock high
|
||||
rcall com2wWaitForClockHighMulti5Us ; (R20, R22)
|
||||
brcc com2wRecvByte_end
|
||||
|
||||
com2wRecvByte_readBit:
|
||||
; handle received bit
|
||||
inr r18, COM_DATA_INPUT
|
||||
andi r18, (1<<COM_DATA_PIN)
|
||||
clc
|
||||
breq com2wRecvByte_clockData
|
||||
sec
|
||||
com2wRecvByte_clockData:
|
||||
ror r16
|
||||
dec r17
|
||||
brne com2wRecvByte_loop
|
||||
sec
|
||||
com2wRecvByte_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wEnableClkIrq
|
||||
;
|
||||
; @clobbers
|
||||
|
||||
com2wEnableClkIrq:
|
||||
push r16
|
||||
inr r16, COM_IRQ_ADDR_CLK
|
||||
sbr r16, (1<<COM_IRQ_BIT_CLK) ; enable pin change irq for CLK line
|
||||
outr COM_IRQ_ADDR_CLK, r16
|
||||
pop r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wDisableClkIrq
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2wDisableClkIrq:
|
||||
push r16
|
||||
inr r16, COM_IRQ_ADDR_CLK
|
||||
cbr r16, (1<<COM_IRQ_BIT_CLK) ; disable pin change irq for CLK line
|
||||
outr COM_IRQ_ADDR_CLK, r16
|
||||
pop r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wClkSetHigh
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2wClkSetHigh:
|
||||
cbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as input
|
||||
.ifdef COM_CLK_PUE
|
||||
; cbi COM_CLK_PUE, COM_CLK_PIN ; disable pullup on CLK
|
||||
.else
|
||||
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; disable pullup on CLK
|
||||
.endif
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wClkSetLow
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2wClkSetLow:
|
||||
sbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as output
|
||||
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; set CLK low
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wDataSetHigh
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2wDataSetHigh:
|
||||
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as input
|
||||
.ifdef COM_DATA_PUE
|
||||
; cbi COM_DATA_PUE, COM_CLK_PIN ; disable pullup on DATA
|
||||
.else
|
||||
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable pullup on DATA
|
||||
.endif
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wDataSetLow
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2wDataSetLow:
|
||||
sbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as output
|
||||
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; set DATA low
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wWaitForClockHighMulti5Us
|
||||
;
|
||||
; Wait for high CLK
|
||||
;
|
||||
; @param R20 multiple of 5us to wait (e.g. "2" for "10" us, max: 64)
|
||||
; @return CFLAG set if okay (state reached), cleared on error
|
||||
; @clobbers: r20, r22
|
||||
|
||||
com2wWaitForClockHighMulti5Us:
|
||||
.if clock == 8000000
|
||||
add r20, r20 ; *2
|
||||
add r20, r20 ; *4
|
||||
add r20, r20 ; *8
|
||||
.endif
|
||||
.elif clock == 1000000
|
||||
; nothing to do
|
||||
.else
|
||||
.error "Unhandled clock speed"
|
||||
.endif
|
||||
|
||||
com2wWaitForClockHighMulti5Us_loop: ; 5 cycles per loop
|
||||
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if not
|
||||
rjmp com2wWaitForClockHighMulti5Us_stateReached ; +2
|
||||
dec r20 ; +1
|
||||
brne com2wWaitForClockHighMulti5Us_loop ; +2
|
||||
clc ; +1
|
||||
ret ; +4
|
||||
com2wWaitForClockHighMulti5Us_stateReached:
|
||||
sec ; +1
|
||||
ret ; +4
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wWaitForClockLowMulti5Us
|
||||
;
|
||||
; Wait for low CLK
|
||||
;
|
||||
; @param R20 multiple of 5us to wait (e.g. "2" for "10" us, max: 64)
|
||||
; @return CFLAG set if okay (state reached), cleared on error
|
||||
; @clobbers: r20, r22
|
||||
|
||||
com2wWaitForClockLowMulti5Us:
|
||||
.if clock == 8000000
|
||||
add r20, r20 ; *2
|
||||
add r20, r20 ; *4
|
||||
add r20, r20 ; *8
|
||||
.endif
|
||||
.elif clock == 1000000
|
||||
; nothing to do
|
||||
.else
|
||||
.error "Unhandled clock speed"
|
||||
.endif
|
||||
|
||||
com2wWaitForClockLowMulti5Us_loop: ; 5 cycles per loop
|
||||
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if not
|
||||
rjmp com2wWaitForClockLowMulti5Us_stateReached ; +2
|
||||
dec r20 ; +1
|
||||
brne com2wWaitForClockLowMulti5Us_loop ; +2
|
||||
clc ; +1
|
||||
ret ; +4
|
||||
com2wWaitForClockLowMulti5Us_stateReached:
|
||||
sec ; +1
|
||||
ret ; +4
|
||||
; @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
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2wPcintIsr @global @isr
|
||||
;
|
||||
; ISR for PCINT0/1
|
||||
;
|
||||
; @clobbers: none
|
||||
|
||||
com2wPcintIsr:
|
||||
push r15
|
||||
in r15, SREG
|
||||
sbic COM_CLK_INPUT, COM_CLK_PIN
|
||||
rjmp com2wPcintIsr_end
|
||||
; low, read packet
|
||||
push r16
|
||||
push r17
|
||||
push r18
|
||||
push r19
|
||||
push r20
|
||||
push r21
|
||||
push r22
|
||||
push r24
|
||||
push r25
|
||||
push xl
|
||||
push xh
|
||||
push yl
|
||||
push yh
|
||||
ldi yl, LOW(com2w_iface)
|
||||
ldi yh, HIGH(com2w_iface)
|
||||
rcall com2wReceiveNextPkg ; (R16, R17, R18, R19, R20, R21, R22, R24, R25, X)
|
||||
pop yh
|
||||
pop yl
|
||||
pop xh
|
||||
pop xl
|
||||
pop r25
|
||||
pop r24
|
||||
pop r22
|
||||
pop r21
|
||||
pop r20
|
||||
pop r19
|
||||
pop r18
|
||||
pop r17
|
||||
pop r16
|
||||
com2wPcintIsr_end:
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
#endif ; AVR_MODULES_COM2W_COM2W_H
|
||||
|
||||
638
avr/modules/com2w/com2w1.asm
Normal file
638
avr/modules/com2w/com2w1.asm
Normal file
@@ -0,0 +1,638 @@
|
||||
; ***************************************************************************
|
||||
; 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_COM2W1_H
|
||||
#define AVR_MODULES_COM2W_COM2W1_H
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
com2w1_iface: .byte COM2W_IFACE_SIZE
|
||||
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W1_Init
|
||||
;
|
||||
; @clobbers
|
||||
|
||||
COM2W1_Init:
|
||||
ldi yl, LOW(com2w1_iface)
|
||||
ldi yh, HIGH(com2w1_iface)
|
||||
rcall NET_Interface_Init ; (R16, R17, X)
|
||||
ldi r16, COM2W_MODE_IDLE
|
||||
rcall com2wSetMode ; (R17)
|
||||
|
||||
; setup CLK line (as input, disable internal pull-up resistor)
|
||||
cbi COM_CLK1_DDR, COM_CLK1_PIN ; set CLK as input
|
||||
.ifdef COM_CLK1_PUE
|
||||
inr r16, COM_CLK1_PUE
|
||||
cbr r16, (1<<COM_CLK1_PIN) ; disable pullup on CLK
|
||||
outr COM_CLK1_PUE, r16
|
||||
.else
|
||||
cbi COM_CLK1_OUTPUT, COM_CLK1_PIN ; disable pullup on CLK
|
||||
.endif
|
||||
|
||||
; setup DATA line (as input, disable internal pull-up resistor)
|
||||
cbi COM_DATA1_DDR, COM_DATA1_PIN ; set DATA as input
|
||||
.ifdef COM_DATA1_PUE
|
||||
inr r16, COM_DATA1_PUE
|
||||
cbr r16, (1<<COM_DATA1_PIN) ; disable pullup on DATA
|
||||
outr COM_DATA1_PUE, r16
|
||||
.else
|
||||
cbi COM_DATA1_OUTPUT, COM_DATA1_PIN ; disable pullup on DATA
|
||||
.endif
|
||||
|
||||
; setup pin-change interrupt for CLK
|
||||
rcall com2w1EnableClkIrq
|
||||
|
||||
inr r16, COM_IRQ_ADDR_CLK1
|
||||
sbr r16, (1<<COM_IRQ_BIT_CLK1) ; enable pin change irq for ATTN line
|
||||
outr COM_IRQ_ADDR_CLK1, r16
|
||||
|
||||
inr r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
|
||||
sbr r16, (1<<COM_IRQ_GIMSK_CLK1)
|
||||
outr GIMSK, r16
|
||||
ldi r16, (1<<COM_IRQ_GIFR_CLK1) ; clear pending irq by writing 1 to ATTN bit
|
||||
outr GIFR, r16
|
||||
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W1_Periodically @global
|
||||
;
|
||||
; @clobbers R16, Y
|
||||
|
||||
COM2W1_Periodically:
|
||||
ldi yl, LOW(com2w1_iface)
|
||||
ldi yh, HIGH(com2w1_iface)
|
||||
rcall com2wPeriodically
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1EnableClkIrq
|
||||
;
|
||||
; @clobbers
|
||||
|
||||
com2w1EnableClkIrq:
|
||||
push r16
|
||||
inr r16, COM_IRQ_ADDR_CLK1
|
||||
sbr r16, (1<<COM_IRQ_BIT_CLK1) ; enable pin change irq for CLK line
|
||||
outr COM_IRQ_ADDR_CLK1, r16
|
||||
pop r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1DisableClkIrq
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2w1DisableClkIrq:
|
||||
push r16
|
||||
inr r16, COM_IRQ_ADDR_CLK1
|
||||
cbr r16, (1<<COM_IRQ_BIT_CLK1) ; disable pin change irq for CLK line
|
||||
outr COM_IRQ_ADDR_CLK1, r16
|
||||
pop r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1ClkSetHigh
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2w1ClkSetHigh:
|
||||
cbi COM_CLK1_DDR, COM_CLK1_PIN ; set CLK as input
|
||||
.ifdef COM_CLK1_PUE
|
||||
; cbi COM_CLK1_PUE, COM_CLK1_PIN ; disable pullup on CLK
|
||||
.else
|
||||
cbi COM_CLK1_OUTPUT, COM_CLK1_PIN ; disable pullup on CLK
|
||||
.endif
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1ClkSetLow
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2w1ClkSetLow:
|
||||
sbi COM_CLK1_DDR, COM_CLK1_PIN ; set CLK as output
|
||||
cbi COM_CLK1_OUTPUT, COM_CLK1_PIN ; set CLK low
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1DataSetHigh
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2w1DataSetHigh:
|
||||
cbi COM_DATA1_DDR, COM_DATA1_PIN ; set DATA as input
|
||||
.ifdef COM_DATA1_PUE
|
||||
; cbi COM_DATA1_PUE, COM_CLK1_PIN ; disable pullup on DATA
|
||||
.else
|
||||
cbi COM_DATA1_OUTPUT, COM_DATA1_PIN ; disable pullup on DATA
|
||||
.endif
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1DataSetLow
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
com2w1DataSetLow:
|
||||
sbi COM_DATA1_DDR, COM_DATA1_PIN ; set DATA as output
|
||||
cbi COM_DATA1_OUTPUT, COM_DATA1_PIN ; set DATA low
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1ReadNextBit
|
||||
;
|
||||
; @clobbers r16, r17, r18, r20, r22
|
||||
|
||||
com2w1ReadNextBit:
|
||||
ldi r20, 50 ; wait for up to 250us for clock rise
|
||||
rcall com2w1WaitForClockHighMulti5Us ; (R20, R22)
|
||||
brcc com2w1ReadNextBit_end
|
||||
; clock is high now, read bit
|
||||
inr r17, COM_DATA1_INPUT
|
||||
; 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 com2w1ReadNextBit_end
|
||||
; handle received bit
|
||||
ldd r16, Y+COM2W_IFACE_OFFS_CURRBYTE
|
||||
ldd r18, Y+COM2W_IFACE_OFFS_BITCOUNTER
|
||||
andi r17, (1<<COM_DATA1_PIN)
|
||||
clc
|
||||
breq com2w1ReadNextBit_clockData
|
||||
sec
|
||||
com2w1ReadNextBit_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 com2w1ReadNextBit_end
|
||||
; write byte into buffer
|
||||
push xl
|
||||
push xh
|
||||
rcall com2wByteRecvd ; (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
|
||||
com2w1ReadNextBit_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1WaitForClockHighMulti5Us
|
||||
;
|
||||
; Wait for high CLK
|
||||
;
|
||||
; @param R20 multiple of 5us to wait (e.g. "2" for "10" us, max: 64)
|
||||
; @return CFLAG set if okay (state reached), cleared on error
|
||||
; @clobbers: r20, r22
|
||||
|
||||
com2w1WaitForClockHighMulti5Us:
|
||||
.if clock == 8000000
|
||||
add r20, r20 ; *2
|
||||
add r20, r20 ; *4
|
||||
add r20, r20 ; *8
|
||||
.endif
|
||||
.elif clock == 1000000
|
||||
; nothing to do
|
||||
.else
|
||||
.error "Unhandled clock speed"
|
||||
.endif
|
||||
|
||||
com2w1WaitForClockHighMulti5Us_loop: ; 5 cycles per loop
|
||||
sbic COM_CLK1_INPUT, COM_CLK1_PIN ; +2 if skipped, +1 if not
|
||||
rjmp com2w1WaitForClockHighMulti5Us_stateReached ; +2
|
||||
dec r20 ; +1
|
||||
brne com2w1WaitForClockHighMulti5Us_loop ; +2
|
||||
clc ; +1
|
||||
ret ; +4
|
||||
com2w1WaitForClockHighMulti5Us_stateReached:
|
||||
sec ; +1
|
||||
ret ; +4
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1WaitForClockLowMulti5Us
|
||||
;
|
||||
; Wait for low CLK
|
||||
;
|
||||
; @param R20 multiple of 5us to wait (e.g. "2" for "10" us, max: 64)
|
||||
; @return CFLAG set if okay (state reached), cleared on error
|
||||
; @clobbers: r20, r22
|
||||
|
||||
com2w1WaitForClockLowMulti5Us:
|
||||
.if clock == 8000000
|
||||
add r20, r20 ; *2
|
||||
add r20, r20 ; *4
|
||||
add r20, r20 ; *8
|
||||
.endif
|
||||
.elif clock == 1000000
|
||||
; nothing to do
|
||||
.else
|
||||
.error "Unhandled clock speed"
|
||||
.endif
|
||||
|
||||
com2w1WaitForClockLowMulti5Us_loop: ; 5 cycles per loop
|
||||
sbis COM_CLK1_INPUT, COM_CLK1_PIN ; +2 if skipped, +1 if not
|
||||
rjmp com2w1WaitForClockLowMulti5Us_stateReached ; +2
|
||||
dec r20 ; +1
|
||||
brne com2w1WaitForClockLowMulti5Us_loop ; +2
|
||||
clc ; +1
|
||||
ret ; +4
|
||||
com2w1WaitForClockLowMulti5Us_stateReached:
|
||||
sec ; +1
|
||||
ret ; +4
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1SendMsg
|
||||
;
|
||||
; @param X pointer to bytes to send
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @return CFLAG set if message sent, cleared otherwise
|
||||
; @clobbers R16, R18 (R20, R22, R24, R25, X)
|
||||
|
||||
com2w1SendMsg:
|
||||
ldi r20, 11 ; wait for about 55us for clock low
|
||||
rcall com2w1WaitForClockLowMulti5Us
|
||||
brcs com2w1SendMsg_busy ; CLK got low while waiting, so line is busy
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli ; atomic disable irq and set CLK low
|
||||
rcall com2w1DisableClkIrq ; (none)
|
||||
rcall com2w1ClkSetLow ; reserve bus (none)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
adiw xh:xl, NETMSG_OFFS_MSGLEN
|
||||
ld r18, X
|
||||
sbiw xh:xl, NETMSG_OFFS_MSGLEN
|
||||
inc r18 ; adjust for DESTADDR
|
||||
inc r18 ; adjust for MSGLEN
|
||||
inc r18 ; adjust for CRCBYTE
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
rcall com2w1SendBytes ; (r16, r17, r18, r22, X)
|
||||
rcall com2w1ClkSetHigh ; make sure bus is released
|
||||
rcall com2w1DataSetHigh
|
||||
|
||||
rcall com2w1EnableClkIrq ; (none)
|
||||
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
sec
|
||||
ret
|
||||
com2w1SendMsg_busy:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1SendBytes
|
||||
;
|
||||
; @param R18 number of bytes to send
|
||||
; @param X pointer to bytes to send
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @clobbers: r16, r18, X (r17, r22)
|
||||
|
||||
com2w1SendBytes:
|
||||
com2w1SendBytes_loop:
|
||||
rcall com2w1ClkSetLow ; (none)
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
ld r16, X+
|
||||
rcall com2w1SendByte ; (R16, R17, R22)
|
||||
dec r18
|
||||
brne com2w1SendBytes_loop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1SendByte
|
||||
;
|
||||
; @param R16 byte to send
|
||||
; @clobbers: r16, r17 (r22)
|
||||
|
||||
com2w1SendByte:
|
||||
ldi r17, 8
|
||||
com2w1SendByte_loop:
|
||||
rcall com2w1ClkSetLow
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
lsr r16
|
||||
brcs com2w1SendByte_send1
|
||||
rcall com2w1DataSetLow
|
||||
rjmp com2w1SendByte_sent
|
||||
com2w1SendByte_send1:
|
||||
rcall com2w1DataSetHigh
|
||||
com2w1SendByte_sent:
|
||||
rcall com2wWaitTime2 ; shorter wait period (R22)
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli ; ensure time period by disabling irqs
|
||||
rcall com2w1ClkSetHigh
|
||||
rcall com2wWaitTime1 ; longer wait period (R22)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
dec r17
|
||||
brne com2w1SendByte_loop
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W1_Run @global
|
||||
;
|
||||
; @return CFLAG set if something done, cleared otherwise
|
||||
; @clobbers all
|
||||
|
||||
COM2W1_Run:
|
||||
ldi yl, LOW(com2w1_iface)
|
||||
ldi yh, HIGH(com2w1_iface)
|
||||
rjmp com2w1RunMode ; (all but Y)
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1RunMode
|
||||
;
|
||||
; @clobbers all
|
||||
|
||||
com2w1RunMode:
|
||||
cpi r16, COM2W_MODE_NUM
|
||||
brcs COM2W1_Run_jump
|
||||
ldi r16, COM2W_MODE_IDLE ; unknown mode, set to idle
|
||||
rcall com2wSetMode ; (R17)
|
||||
sec
|
||||
ret
|
||||
COM2W1_Run_jump:
|
||||
ldi zl, LOW(com2w1ModeJumpTable)
|
||||
ldi zh, HIGH(com2w1ModeJumpTable)
|
||||
add zl, r16
|
||||
adc zh, r16
|
||||
sub zh, r16
|
||||
ijmp
|
||||
com2w1ModeJumpTable:
|
||||
rjmp com2w1RunIdle
|
||||
rjmp com2w1RunReading
|
||||
rjmp com2w1RunSkipping
|
||||
rjmp com2w1RunWriting
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1RunIdle
|
||||
;
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @clobbers R16, R17, R22, R24, R25, X
|
||||
|
||||
com2w1RunIdle:
|
||||
rjmp com2w1RunIdle_end ; DEBUG
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
; look for outbound message
|
||||
rcall NET_Interface_PeekNextOutgoingMsgNum ; r16=msgNum
|
||||
brcs com2w1RunIdle_haveMsg
|
||||
out SREG, r15
|
||||
pop r15
|
||||
clc
|
||||
rjmp com2w1RunIdle_end
|
||||
|
||||
com2w1RunIdle_haveMsg:
|
||||
mov r24, r16
|
||||
ldi r16, COM2W_MODE_WRITING
|
||||
rcall com2wSetMode ; (R17)
|
||||
mov r16, r24
|
||||
out SREG, r15
|
||||
pop r15
|
||||
|
||||
push r16
|
||||
rcall NET_Buffer_Locate ; (R17)
|
||||
adiw xh:xl, 1
|
||||
rcall com2w1SendMsg ; (R16, R17, R22, R24, R25, X)
|
||||
push r15
|
||||
inr r15, SREG ; save SREG (no CLI, we want to save CFLAG only)
|
||||
ldi r16, COM2W_MODE_IDLE
|
||||
rcall com2wSetMode ; (R17)
|
||||
out SREG, r15 ; restore SREG
|
||||
pop r15
|
||||
pop r16
|
||||
brcc com2w1RunIdle_end
|
||||
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
rcall NET_Interface_GetNextOutgoingMsgNum ; take current msg off the queue
|
||||
rcall NET_Buffer_ReleaseByNum ; (R16, X)
|
||||
out SREG, r15
|
||||
pop r15
|
||||
sec
|
||||
com2w1RunIdle_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1RunReading
|
||||
;
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @clobbers none
|
||||
|
||||
com2w1RunReading:
|
||||
; check for timeout (Y+NET_IFACE_OFFS_READTIMER)
|
||||
ldd r16, Y+NET_IFACE_OFFS_READTIMER
|
||||
cpi r16, COM2W_READING_MAXREADCOUNTER
|
||||
brcc com2w1RunReading_goIdle
|
||||
ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER
|
||||
cpi r16, COM2W_READING_MAXMODECOUNTER
|
||||
brcc com2w1RunReading_goIdle
|
||||
clc
|
||||
rjmp com2w1RunReading_end
|
||||
com2w1RunReading_goIdle:
|
||||
ldi r16, NET_IFACE_OFFS_ERR_IO_LOW
|
||||
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
||||
ldi r16, COM2W_MODE_IDLE
|
||||
rcall com2wSetMode ; (r17)
|
||||
sec
|
||||
com2w1RunReading_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1RunSkipping
|
||||
;
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @clobbers r16 (r17)
|
||||
|
||||
com2w1RunSkipping:
|
||||
; check for timeout (Y+NET_IFACE_OFFS_READTIMER)
|
||||
ldd r16, Y+NET_IFACE_OFFS_READTIMER
|
||||
cpi r16, COM2W_SKIPPING_MAXREADCOUNTER
|
||||
brcc com2w1RunSkipping_goIdle
|
||||
ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER
|
||||
cpi r16, COM2W_SKIPPING_MAXMODECOUNTER
|
||||
brcc com2w1RunSkipping_goIdle
|
||||
clc
|
||||
rjmp com2w1RunSkipping_end
|
||||
com2w1RunSkipping_goIdle:
|
||||
ldi r16, COM2W_MODE_IDLE
|
||||
rcall com2wSetMode ; (r17)
|
||||
sec
|
||||
com2w1RunSkipping_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1RunWriting
|
||||
;
|
||||
; @param Y pointer to interface data in SRAM
|
||||
; @clobbers none
|
||||
|
||||
com2w1RunWriting:
|
||||
; TODO: check for timeout
|
||||
clc
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W1_ClkChangeIsr @global @isr
|
||||
;
|
||||
; @clobbers none
|
||||
|
||||
COM2W1_ClkChangeIsr:
|
||||
push r15
|
||||
in r15, SREG
|
||||
push r16
|
||||
inr r16, COM_CLK1_INPUT ; read clk state early
|
||||
rcall COM2W1_HandleClockInterrupt
|
||||
pop r16
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine COM2W1_HandleClockInterrupt @global
|
||||
;
|
||||
; @param r16 data from COM_CLKn_INPUT
|
||||
; @clobbers none
|
||||
|
||||
COM2W1_HandleClockInterrupt:
|
||||
push r16
|
||||
push r17
|
||||
push r18
|
||||
push xl
|
||||
push xh
|
||||
push yl
|
||||
push yh
|
||||
ldi yl, LOW(com2w1_iface)
|
||||
ldi yh, HIGH(com2w1_iface)
|
||||
rcall com2w1ActOnClock ; (r16, r17, r18, X)
|
||||
pop yh
|
||||
pop yl
|
||||
pop xh
|
||||
pop xl
|
||||
pop r18
|
||||
pop r17
|
||||
pop r16
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; @routine com2w1ActOnClock
|
||||
;
|
||||
; @param r16 data from COM_CLKn_INPUT
|
||||
; @clobbers r16 (r17, r18, X)
|
||||
|
||||
com2w1ActOnClock:
|
||||
andi r16, (1<<COM_CLK1_PIN)
|
||||
brne com2w1ActOnClock_end
|
||||
ldd r17, Y+COM2W_IFACE_OFFS_MODE
|
||||
cpi r17, COM2W_MODE_READING
|
||||
breq com2w1ActOnClock_readBit
|
||||
cpi r17, COM2W_MODE_IDLE
|
||||
brne com2w1ActOnClock_end
|
||||
rcall com2wStartReading ; (r16, r17, X)
|
||||
com2w1ActOnClock_readBit:
|
||||
push r20
|
||||
push r22
|
||||
rcall com2w1ReadNextBit ; (r16, r17, r18, r20, r22)
|
||||
pop r22
|
||||
pop r20
|
||||
com2w1ActOnClock_end:
|
||||
ret
|
||||
; @end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif ; AVR_MODULES_COM2W_COM2W1_H
|
||||
|
||||
244
avr/modules/com2w/common.asm
Normal file
244
avr/modules/com2w/common.asm
Normal file
@@ -0,0 +1,244 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
74
avr/modules/com2w/defs.asm
Normal file
74
avr/modules/com2w/defs.asm
Normal file
@@ -0,0 +1,74 @@
|
||||
; ***************************************************************************
|
||||
; 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_DEFS_H
|
||||
#define AVR_MODULES_COM2W_DEFS_H
|
||||
|
||||
|
||||
.equ COM2W_WAITTIME1 = 30000
|
||||
.equ COM2W_WAITTIME2 = 10000
|
||||
|
||||
.equ COM2W_SKIPPING_MAXREADCOUNTER = 1
|
||||
.equ COM2W_SKIPPING_MAXMODECOUNTER = 20 ; stay max 2s in skipping mode
|
||||
|
||||
.equ COM2W_READING_MAXREADCOUNTER = 1
|
||||
.equ COM2W_READING_MAXMODECOUNTER = 20 ; stay max 2s in reading mode
|
||||
|
||||
|
||||
;
|
||||
; .equ COM2W_DATA0_DDR = DDRA
|
||||
; .equ COM2W_DATA0_INPUT = PINA
|
||||
; .equ COM2W_DATA0_OUTPUT = PORTA
|
||||
; .equ COM2W_DATA0_PUE = PUEA
|
||||
; .equ COM2W_DATA0_PIN = PORTA2
|
||||
;
|
||||
; .equ COM2W_CLK0_DDR = DDRA
|
||||
; .equ COM2W_CLK0_INPUT = PINA
|
||||
; .equ COM2W_CLK0_OUTPUT = PORTA
|
||||
; .equ COM2W_CLK0_PUE = PUEA
|
||||
; .equ COM2W_CLK0_PIN = PORTA0
|
||||
|
||||
; .equ COM2W_IRQ_ADDR_CLK0 = PCMSK0
|
||||
; .equ COM2W_IRQ_BIT_CLK0 = PCINT0 ; bit 0 in PCMSK0
|
||||
; .equ COM2W_IRQ_GIFR_CLK0 = PCIF0
|
||||
; .equ COM2W_IRQ_GIMSK_CLK0 = PCIE0
|
||||
|
||||
|
||||
|
||||
|
||||
.equ COM2W_BUFFER_SIZE = NET_BUFFERS_SIZE-1
|
||||
|
||||
|
||||
|
||||
.equ COM2W_MODE_IDLE = 0
|
||||
.equ COM2W_MODE_READING = 1
|
||||
.equ COM2W_MODE_SKIPPING = 2
|
||||
.equ COM2W_MODE_WRITING = 3
|
||||
.equ COM2W_MODE_NUM = 4
|
||||
|
||||
|
||||
.equ COM2W_IFACE_OFFS_BEGIN = NET_IFACE_SIZE
|
||||
.equ COM2W_IFACE_OFFS_CURRBYTE = COM2W_IFACE_OFFS_BEGIN
|
||||
.equ COM2W_IFACE_OFFS_BITCOUNTER = COM2W_IFACE_OFFS_BEGIN+1
|
||||
.equ COM2W_IFACE_OFFS_MODE = COM2W_IFACE_OFFS_BEGIN+2
|
||||
.equ COM2W_IFACE_OFFS_MODECOUNTER = COM2W_IFACE_OFFS_BEGIN+3
|
||||
.equ COM2W_IFACE_OFFS_BUFPOS_LOW = COM2W_IFACE_OFFS_BEGIN+4
|
||||
.equ COM2W_IFACE_OFFS_BUFPOS_HIGH = COM2W_IFACE_OFFS_BEGIN+5
|
||||
.equ COM2W_IFACE_OFFS_BUFUSED = COM2W_IFACE_OFFS_BEGIN+6
|
||||
.equ COM2W_IFACE_OFFS_BUFLEFT = COM2W_IFACE_OFFS_BEGIN+7
|
||||
.equ COM2W_IFACE_OFFS_BUFFER = COM2W_IFACE_OFFS_BEGIN+8
|
||||
|
||||
.equ COM2W_IFACE_SIZE = COM2W_IFACE_OFFS_BUFFER+COM2W_BUFFER_SIZE
|
||||
|
||||
|
||||
|
||||
|
||||
#endif ; AVR_MODULES_COM2W_DEFS_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user