after sending a byte wait for the same time when sending the last bit as with the other bits (otherwise the last bit might get lost by slower devices).
804 lines
23 KiB
NASM
804 lines
23 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_COM2W_H
|
|
#define AVR_MODULES_COM2W_COM2W_H
|
|
|
|
|
|
|
|
.macro M_COM2WCLKSETLOW
|
|
sbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as output
|
|
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; set CLK low
|
|
.endmacro
|
|
|
|
|
|
|
|
.macro M_COM2WCLKSETHIGH
|
|
cbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as input
|
|
.ifndef COM_CLK_PUE
|
|
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; disable pullup on CLK
|
|
.endif
|
|
.endmacro
|
|
|
|
|
|
|
|
.macro M_COM2WDATASETLOW
|
|
sbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as output
|
|
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; set DATA low
|
|
.endmacro
|
|
|
|
|
|
|
|
.macro M_COM2WDATASETHIGH
|
|
cbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as input
|
|
.ifndef COM_DATA_PUE
|
|
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; disable pullup on DATA
|
|
.endif
|
|
.endmacro
|
|
|
|
|
|
|
|
|
|
|
|
.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:
|
|
mov xl, yl
|
|
mov xh, yh
|
|
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
|
|
ldd r18, Y+NET_IFACE_OFFS_ADDRESS
|
|
ldi r19, COM2W_BUFFER_SIZE
|
|
rcall com2wRecvMsg ; (r16, r17, r18, r19, r20, r22, r24, r25, X)
|
|
brcc com2wReceiveNextPkg_end
|
|
|
|
mov xl, yl
|
|
mov xh, yh
|
|
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
|
|
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
|
|
brcc com2wReceiveNextPkg_eCrc
|
|
|
|
; msg received, alloc buffer for it
|
|
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
|
|
|
|
; copy received message into allocated buffer
|
|
com2wReceiveNextPkg_gotBuffer:
|
|
mov r19, r16 ; save buffer num
|
|
rcall NET_Interface_SetIfaceNumInBuffer ; (R16, R17)
|
|
mov r16, r19 ; restore buffer num
|
|
push zl
|
|
push zh
|
|
mov zl, yl
|
|
mov zh, yh
|
|
adiw zh:zl, COM2W_IFACE_OFFS_BUFFER
|
|
adiw xh:xl, 1
|
|
ldd r18, Z+NETMSG_OFFS_MSGLEN
|
|
inc r18
|
|
inc r18
|
|
inc r18
|
|
com2wReceiveNextPkg_copyLoop:
|
|
ld r17, Z+
|
|
st X+, r17
|
|
dec r18
|
|
brne com2wReceiveNextPkg_copyLoop
|
|
pop zh
|
|
pop zl
|
|
|
|
; add to incoming msg pool
|
|
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
|
|
brcc com2wReceiveNextPkg_eMissed
|
|
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
|
|
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
|
sec
|
|
rjmp com2wReceiveNextPkg_end
|
|
com2wReceiveNextPkg_eCrc:
|
|
push r16
|
|
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
|
|
rcall NET_Interface_IncCounter16 ; (R24, R25)
|
|
pop r16
|
|
rjmp com2wReceiveNextPkg_relBuffer
|
|
com2wReceiveNextPkg_eMissed:
|
|
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)
|
|
clc
|
|
com2wReceiveNextPkg_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
#if 0
|
|
; ---------------------------------------------------------------------------
|
|
; @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
|
|
#endif
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @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, 6 ; wait for about 60us for clock low
|
|
rcall com2wWaitForClockLowMulti10Us ; (R16, R20, R22)
|
|
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:
|
|
push r15
|
|
in r15, SREG
|
|
ldi r17, 8
|
|
com2wSendByte_loop:
|
|
M_COM2WCLKSETLOW
|
|
out SREG, r15 ; probably enable irqs
|
|
rcall com2wWaitTime1 ; wait for longer time (R22)
|
|
lsr r16
|
|
brcs com2wSendByte_send1
|
|
M_COM2WDATASETLOW
|
|
rjmp com2wSendByte_sent
|
|
com2wSendByte_send1:
|
|
M_COM2WDATASETHIGH
|
|
com2wSendByte_sent:
|
|
Utils_WaitNanoSecs 5000, 0, r22 ; wait for very short time to ensure data is stable when clock rises
|
|
cli ; ensure time period by disabling irqs
|
|
M_COM2WCLKSETHIGH
|
|
rcall com2wWaitTime2 ; wait for shorter time (R22)
|
|
dec r17
|
|
brne com2wSendByte_loop
|
|
out SREG, r15
|
|
pop r15
|
|
rcall com2wWaitTime2 ; wait for shorter time (R22)
|
|
M_COM2WDATASETHIGH ; ensure data line is high
|
|
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)
|
|
rcall com2wRecvByteWaitForQuietClk ; (r18, r20, r22)
|
|
com2wRecvMsg_clcRet:
|
|
clc
|
|
com2wRecvMsg_end:
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine com2wRecvByteWaitForQuietClk
|
|
;
|
|
; Wait until the clock line is consistently high for 1ms.
|
|
;
|
|
; @clobbers r18, r20, r22
|
|
|
|
com2wRecvByteWaitForQuietClk:
|
|
ldi r18, 200
|
|
com2wRecvByteWaitForQuietClk_loop:
|
|
ldi r20, 100 ; wait up to 1ms for clock high (R20, R22)
|
|
rcall com2wWaitForClockLowMulti10Us
|
|
brcs com2wRecvByteWaitForQuietClk_waitForLow
|
|
dec r18
|
|
brne com2wRecvByteWaitForQuietClk_loop
|
|
rjmp com2wRecvByteWaitForQuietClk_ret
|
|
com2wRecvByteWaitForQuietClk_waitForLow:
|
|
ldi r20, 100 ; wait up to 1ms for clock low (R20, R22)
|
|
rcall com2wWaitForClockLowMulti10Us
|
|
brcc com2wRecvByteWaitForQuietClk_ret ; not low within 1ms, assume line is quiet
|
|
brne com2wRecvByteWaitForQuietClk_loop
|
|
com2wRecvByteWaitForQuietClk_ret:
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @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, 50 ; wait up to 500us for clock low
|
|
rcall com2wWaitForClockLowMulti10Us ; (R20, R22)
|
|
brcc com2wRecvByte_end
|
|
ldi r20, 100 ; wait up to 1ms for clock high
|
|
rcall com2wWaitForClockHighMulti10Us ; (R20, R22)
|
|
brcc com2wRecvByte_end
|
|
; 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 com2wWaitForClockHighMulti10Us
|
|
;
|
|
; Wait for high CLK
|
|
;
|
|
; @param R20 multiple of 10us to wait (e.g. "2" for "20" us)
|
|
; @return CFLAG set if okay (state reached), cleared on error
|
|
; @clobbers: r20, r22
|
|
|
|
com2wWaitForClockHighMulti10Us:
|
|
.if clock > 1000000
|
|
; begin version for > 1000000 Hz
|
|
ldi r22, clock/1000000
|
|
com2wWaitForClockHighMulti10Us_loop0:
|
|
push r20
|
|
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
|
|
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
|
|
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
|
|
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
|
|
nop ; +1
|
|
dec r20 ; +1
|
|
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
|
|
pop r20
|
|
dec r22 ; +1
|
|
brne com2wWaitForClockHighMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
|
|
clc ; +1
|
|
ret ; +4
|
|
com2wWaitForClockHighMulti10Us_stateReached:
|
|
pop r20
|
|
sec ; +1
|
|
ret ; +4
|
|
; end version for > 1000000 Hz
|
|
.elif clock < 1000000
|
|
.error "Clock speed too low"
|
|
.else
|
|
; begin version for 1000000 Hz
|
|
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
|
|
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
|
|
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
|
|
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken)
|
|
nop ; +1
|
|
dec r20 ; +1
|
|
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
|
|
clc ; +1
|
|
ret ; +4
|
|
com2wWaitForClockHighMulti10Us_stateReached:
|
|
sec ; +1
|
|
ret ; +4
|
|
; end version for 1000000 Hz
|
|
.endif
|
|
; @end
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; @routine com2wWaitForClockLowMulti10Us
|
|
;
|
|
; Wait for low CLK
|
|
;
|
|
; @param R20 multiple of 10us to wait (e.g. "2" for "20" us)
|
|
; @return CFLAG set if okay (state reached), cleared on error
|
|
; @clobbers: r20, r22
|
|
|
|
com2wWaitForClockLowMulti10Us:
|
|
.if clock > 1000000
|
|
; begin version for > 1000000 Hz
|
|
ldi r22, clock/1000000
|
|
com2wWaitForClockLowMulti10Us_loop0:
|
|
push r20
|
|
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
|
|
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
|
|
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
|
|
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
|
|
nop ; +1
|
|
dec r20 ; +1
|
|
brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
|
|
pop r20
|
|
dec r22 ; +1
|
|
brne com2wWaitForClockLowMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
|
|
clc ; +1
|
|
ret ; +4
|
|
com2wWaitForClockLowMulti10Us_stateReached:
|
|
pop r20
|
|
sec ; +1
|
|
ret ; +4
|
|
; end version for > 1000000 Hz
|
|
.elif clock < 1000000
|
|
.error "Clock speed too low"
|
|
.else
|
|
; begin version for 1000000 Hz
|
|
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
|
|
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
|
|
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
|
|
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
|
|
rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken)
|
|
nop ; +1
|
|
dec r20 ; +1
|
|
brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
|
|
clc ; +1
|
|
ret ; +4
|
|
com2wWaitForClockLowMulti10Us_stateReached:
|
|
sec ; +1
|
|
ret ; +4
|
|
; end version for 1000000 Hz
|
|
.endif
|
|
; @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
|
|
|