avr: tweaked timing for com2w transport layer.

This commit is contained in:
Martin Preuss
2025-08-19 23:03:15 +02:00
parent 102996f69f
commit fc073696f8
15 changed files with 311 additions and 189 deletions

View File

@@ -170,6 +170,7 @@ com2wReceiveNextPkg_end:
#if 0
; ---------------------------------------------------------------------------
; @routine com2wReceiveAndCheckMsg
;
@@ -208,6 +209,7 @@ com2wReceiveAndCheckMsg_msgOk:
sec
ret
; @end
#endif
@@ -247,9 +249,9 @@ com2wSendNextPkg_end:
; @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
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
@@ -313,7 +315,7 @@ com2wSendByte:
ldi r17, 8
com2wSendByte_loop:
rcall com2wClkSetLow
rcall com2wWaitTime1 ; longer wait period (R22)
rcall com2wWaitTime2 ; shorter wait period (R22)
lsr r16
brcs com2wSendByte_send1
rcall com2wDataSetLow
@@ -321,12 +323,12 @@ com2wSendByte_loop:
com2wSendByte_send1:
rcall com2wDataSetHigh
com2wSendByte_sent:
rcall com2wWaitTime2 ; shorter wait period (R22)
Utils_WaitNanoSecs 5000, 0, r22 ; wait for very short time to ensure data is stable when clock rises
push r15
in r15, SREG
cli ; ensure time period by disabling irqs
rcall com2wClkSetHigh
rcall com2wWaitTime1 ; longer wait period (R22)
rcall com2wWaitTime2 ; shorter wait period (R22)
out SREG, r15
pop r15
dec r17
@@ -416,21 +418,12 @@ 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)
ldi r20, 50 ; wait up to 500us for clock low
rcall com2wWaitForClockLowMulti10Us ; (R16, 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)
ldi r20, 50 ; wait up to 500us for clock high
rcall com2wWaitForClockHighMulti10Us ; (R16, R20, R22)
brcc com2wRecvByte_end
com2wRecvByte_readBit:
; handle received bit
inr r18, COM_DATA_INPUT
andi r18, (1<<COM_DATA_PIN)
@@ -544,71 +537,121 @@ com2wDataSetLow:
; ---------------------------------------------------------------------------
; @routine com2wWaitForClockHighMulti5Us
; @routine com2wWaitForClockHighMulti10Us
;
; Wait for high CLK
;
; @param R20 multiple of 5us to wait (e.g. "2" for "10" us, max: 64)
; @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
com2wWaitForClockHighMulti5Us:
.if clock == 8000000
add r20, r20 ; *2
add r20, r20 ; *4
add r20, r20 ; *8
.endif
.elif clock == 1000000
; nothing to do
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
.error "Unhandled clock speed"
; 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
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
; @routine com2wWaitForClockLowMulti10Us
;
; Wait for low CLK
;
; @param R20 multiple of 5us to wait (e.g. "2" for "10" us, max: 64)
; @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
com2wWaitForClockLowMulti5Us:
.if clock == 8000000
add r20, r20 ; *2
add r20, r20 ; *4
add r20, r20 ; *8
.endif
.elif clock == 1000000
; nothing to do
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
.error "Unhandled clock speed"
; 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
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

View File

@@ -29,13 +29,13 @@
com2wnSendMsg:
ldi r20, 6 ; wait for about 60us for clock low
rcall com2wWaitForClockLowMulti10Us ; (R17, R20, R22)
brcs com2wnSendMsg_busy ; CLK got low while waiting, so line is busy
rcall com2wWaitForClockLowMulti10Us ; (R16, R20, R22)
brcs com2wnSendMsg_busy ; CLK got low while waiting, so line is busy
push r15
in r15, SREG
cli ; atomic disable irq and set CLK low
rcall com2wnDisableClkIrq ; (none)
rcall com2wnClkSetLow ; reserve bus (none)
rcall com2wnClkSetLow ; reserve bus (none)
out SREG, r15
pop r15
adiw xh:xl, NETMSG_OFFS_MSGLEN

View File

@@ -31,30 +31,33 @@
com2wWaitForClockHighMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
ldi r20, LOW(clock/1000000)
ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
push r19
ldi r19, LOW(clock/1000000)
ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
com2wWaitForClockHighMulti10Us_loop0:
push r20 ; +2
push r20
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
nop ; +1
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
dec r20 ; +1
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20 ; +2
dec r20 ; +1
brne com2wWaitForClockHighMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
nop ; +1
dec r20 ; +1
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20
dec r19 ; +1
brne com2wWaitForClockHighMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
pop r19
clc ; +1
ret ; +4
com2wWaitForClockHighMulti10Us_stateReached:
pop r20
pop r20
pop r19
sec ; +1
ret ; +4
; end version for > 1000000 Hz
@@ -66,11 +69,11 @@ com2wWaitForClockHighMulti10Us_stateReached:
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
nop ; +1
@@ -97,6 +100,79 @@ com2wWaitForClockHighMulti10Us_stateReached:
; @clobbers: r16, r20, r22
com2wWaitForClockLowMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
push r19
ldi r19, LOW(clock/1000000)
ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
com2wWaitForClockLowMulti10Us_loop0:
push r20
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
nop ; +1
dec r20 ; +1
brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20
dec r19 ; +1
brne com2wWaitForClockLowMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
pop r19
clc ; +1
ret ; +4
com2wWaitForClockLowMulti10Us_stateReached:
pop r20
pop r19
sec ; +1
ret ; +4
; end version for > 1000000 Hz
.elif clock < 1000000
.error "Clock speed too low"
.else
; begin version for 1000000 Hz
ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1
breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
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
.if clock > 1000000
; begin version for > 1000000 Hz
ldi r20, LOW(clock/1000000)

View File

@@ -11,7 +11,7 @@
#define AVR_MODULES_COM2W_DEFS_H
.equ COM2W_WAITTIME1 = 30000
.equ COM2W_WAITTIME1 = 17000
.equ COM2W_WAITTIME2 = 10000
.equ COM2W_SKIPPING_MAXREADCOUNTER = 1