com2w*: allow for higher frequencies than 8MHz

to be used with node S03, which is run at 20MHz.
This commit is contained in:
Martin Preuss
2025-08-18 18:04:30 +02:00
parent 9b1badb310
commit d9e7d4df81
7 changed files with 412 additions and 172 deletions

View File

@@ -100,7 +100,7 @@ com2wnInit:
rcall com2wSetMode ; (R17) rcall com2wSetMode ; (R17)
rcall com2wSetupLines rcall com2wSetupLines
rcall com2wSetupIrq rcall com2wnSetupIrq
ret ret
; @end ; @end

View File

@@ -34,7 +34,7 @@ com2wSetupLines:
.endif .endif
; setup DATA line (as input, disable internal pull-up resistor) ; setup DATA line (as input, disable internal pull-up resistor)
rcall com2wDataSetHigh rcall com2wnDataSetHigh
.ifdef COM_DATA_PUE .ifdef COM_DATA_PUE
ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_DATA ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_DATA
com r16 com r16
@@ -75,12 +75,12 @@ com2wClkSetHigh:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wClkSetLow ; @routine com2wnClkSetLow
; ;
; @param Y pointer to interface data in SRAM ; @param Y pointer to interface data in SRAM
; @clobbers none ; @clobbers none
com2wClkSetLow: com2wnClkSetLow:
push r16 push r16
push r17 push r17
ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_CLK ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_CLK
@@ -102,12 +102,12 @@ com2wClkSetLow:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wDataSetHigh ; @routine com2wnDataSetHigh
; ;
; @param Y pointer to interface data in SRAM ; @param Y pointer to interface data in SRAM
; @clobbers none ; @clobbers none
com2wDataSetHigh: com2wnDataSetHigh:
push r16 push r16
push r17 push r17
ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_DATA ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_DATA
@@ -129,12 +129,12 @@ com2wDataSetHigh:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wDataSetLow ; @routine com2wnDataSetLow
; ;
; @param Y pointer to interface data in SRAM ; @param Y pointer to interface data in SRAM
; @clobbers none ; @clobbers none
com2wDataSetLow: com2wnDataSetLow:
push r16 push r16
push r17 push r17
ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_DATA ldd r16, Y+COM2W_IFACE_OFFS_PINMASK_DATA

View File

@@ -23,12 +23,16 @@ com2wnSetupIrq:
; setup pin-change interrupt for CLK ; setup pin-change interrupt for CLK
rcall com2wnEnableClkIrq rcall com2wnEnableClkIrq
; enable and clear PCIE0/1 (@TODO put later into general setup) ; enable PCIEn irq
inr r16, GIMSK ; enable pin change irq PCIE0 or PCIE1 inr r16, COM_IRQ_ADDR_M_CLK ; enable pin change irq PCIEn
sbr r16, (1<<COM_IRQ_GIMSK_CLK) sbr r16, (1<<COM_IRQ_BIT_M_CLK)
outr GIMSK, r16 outr COM_IRQ_ADDR_M_CLK, r16
ldi r16, (1<<COM_IRQ_GIFR_CLK) ; clear pending irq by writing 1 to GIFR bit
outr GIFR, r16 ; clear PCIEn interrupt flag
inr r16, COM_IRQ_ADDR_F_CLK ; enable pin change irq PCIEn
sbr r16, (1<<COM_IRQ_BIT_F_CLK)
outr COM_IRQ_ADDR_F_CLK, r16
ret ret
; @end ; @end
@@ -74,14 +78,16 @@ com2wnDisableClkIrq:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine COM2WN_ClkChangeOnePortIsr @global @isr ; @routine COM2WN_ClkChangeIsr @global @isr
; ;
; Interrupt service routine for single port (i.e. one port contains all ; Interrupt service routine for dual or single port (i.e. one port contains all
; CLOCK and DATA bits like in node R05). ; CLOCK and DATA bits like in node R05 and R06).
; ;
; @clobbers none ; @clobbers none
COM2WN_ClkChangeOnePortIsr: COM2WN_ClkChangeIsr:
.if COM_DATA_INPUT == COM_CLK_INPUT
; routine for single port
push r15 push r15
in r15, SREG in r15, SREG
push r16 push r16
@@ -95,11 +101,11 @@ COM2WN_ClkChangeOnePortIsr:
ldi yl, LOW(com2wnIoRingBuffer) ldi yl, LOW(com2wnIoRingBuffer)
ldi yh, HIGH(com2wnIoRingBuffer) ldi yh, HIGH(com2wnIoRingBuffer)
rcall RingBufferY_WriteByte ; (R17, R18, X) rcall RingBufferY_WriteByte ; (R17, R18, X)
brcs COM2WN_ClkChangeOnePortIsr_popRet brcs COM2WN_ClkChangeIsr_popRet
lds r16, com2wnIoFlags lds r16, com2wnIoFlags
ori r16, (1<<COM2W_IO_FLAGS_BIT_OVR) ori r16, (1<<COM2W_IO_FLAGS_BIT_OVR)
sts com2wnIoFlags, r16 sts com2wnIoFlags, r16
COM2WN_ClkChangeOnePortIsr_popRet: COM2WN_ClkChangeIsr_popRet:
pop yh pop yh
pop yl pop yl
pop xh pop xh
@@ -110,19 +116,8 @@ COM2WN_ClkChangeOnePortIsr_popRet:
out SREG, r15 out SREG, r15
pop r15 pop r15
reti reti
; @end .else
; routine for two port
; ---------------------------------------------------------------------------
; @routine COM2WN_ClkChangeTwoPortIsr @global @isr
;
; Interrupt service routine for single port (i.e. one port contains all
; CLOCK and DATA bits like in node R05).
;
; @clobbers none
COM2WN_ClkChangeTwoPortIsr:
push r15 push r15
in r15, SREG in r15, SREG
push r16 push r16
@@ -139,14 +134,14 @@ COM2WN_ClkChangeTwoPortIsr:
push r17 push r17
rcall RingBufferY_WriteByte ; push clk state (R17, R18, X) rcall RingBufferY_WriteByte ; push clk state (R17, R18, X)
pop r16 ; pop DATA input into r16 (from r17) pop r16 ; pop DATA input into r16 (from r17)
brcc COM2WN_ClkChangeTwoPortIsr_ovr brcc COM2WN_ClkChangeIsr_ovr
rcall RingBufferY_WriteByte ; push data state (R17, R18, X) rcall RingBufferY_WriteByte ; push data state (R17, R18, X)
brcs COM2WN_ClkChangeTwoPortIsr_popRet brcs COM2WN_ClkChangeIsr_popRet
COM2WN_ClkChangeTwoPortIsr_ovr: COM2WN_ClkChangeIsr_ovr:
lds r16, com2wnIoFlags lds r16, com2wnIoFlags
ori r16, (1<<COM2W_IO_FLAGS_BIT_OVR) ori r16, (1<<COM2W_IO_FLAGS_BIT_OVR)
sts com2wnIoFlags, r16 sts com2wnIoFlags, r16
COM2WN_ClkChangeTwoPortIsr_popRet: COM2WN_ClkChangeIsr_popRet:
pop yh pop yh
pop yl pop yl
pop xh pop xh
@@ -157,6 +152,8 @@ COM2WN_ClkChangeTwoPortIsr_popRet:
out SREG, r15 out SREG, r15
pop r15 pop r15
reti reti
.endif
; @end ; @end

View File

@@ -18,15 +18,97 @@
; ---------------------------------------------------------------------------
; @routine COM2WN_Run
;
; @return CFLAG set if something done, cleared otherwise
; @clobbers all
COM2WN_Run:
clr r16
; first handle lowlevel (e.g. handle all CLK changes and DATA from ringbuffer)
COM2WN_Run_loop1:
push r16
rcall com2wnLowLevelRun
pop r16
brcc COM2WN_Run_handleRunModes
rcall com2wnSetR16OnCarrySet
rjmp COM2WN_Run_loop1
; then handle messages etc
COM2WN_Run_handleRunModes:
ldi r19, COM_PORTS
ldi yl, LOW(com2w0_iface) ; first interface
ldi yh, HIGH(com2w0_iface)
COM2WN_Run_loop2:
push r16
push r19
rcall com2wnRunMode ; (clobbers possibly all but Y)
pop r19
pop r16
rcall com2wnSetR16OnCarrySet
ldi r20, COM2W_IFACE_SIZE
add yl, r20
adc yh, r20
sub yh, r20
dec r19
brne COM2WN_Run_loop2
tst r16
clc
breq COM2WN_Run_ret
sec
COM2WN_Run_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wnSetR16OnCarrySet
;
com2wnSetR16OnCarrySet:
brcc com2wnSetR16OnCarrySet_ret
ldi r16, 1
com2wnSetR16OnCarrySet_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2WN_Periodically
;
COM2WN_Periodically:
ldi r19, COM_PORTS
ldi yl, LOW(com2w0_iface) ; first interface
ldi yh, HIGH(com2w0_iface)
COM2WN_Periodically_loop: ; loop through all interfaces
push r19
rcall com2wPeriodically ; (R16)
pop r19
ldi r20, COM2W_IFACE_SIZE
add yl, r20
adc yh, r20
sub yh, r20
dec r19
brne COM2WN_Periodically_loop
ret
; @end
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wnLowLevelRun ; @routine com2wnLowLevelRun
; ;
com2wnLowLevelRunOnePort: com2wnLowLevelRun:
.if COM_DATA_INPUT == COM_CLK_INPUT
; begin routine for single port
ldi yl, LOW(com2wnIoRingBuffer) ldi yl, LOW(com2wnIoRingBuffer)
ldi yh, HIGH(com2wnIoRingBuffer) ldi yh, HIGH(com2wnIoRingBuffer)
rcall RingBufferY_ReadByteGuarded ; (R17, R18, X) rcall RingBufferY_ReadByteGuarded ; (R17, R18, X)
brcc com2wnLowLevelRunOnePort_ret brcc com2wnLowLevelRun_ret
lds r18, com2wnIoCurrentClockStates lds r18, com2wnIoCurrentClockStates
eor r18, r16 ; r18: changed bits in clk states eor r18, r16 ; r18: changed bits in clk states
@@ -35,11 +117,11 @@ com2wnLowLevelRunOnePort:
ldi r19, COM_PORTS ldi r19, COM_PORTS
ldi yl, LOW(com2w0_iface) ; first interface ldi yl, LOW(com2w0_iface) ; first interface
ldi yh, HIGH(com2w0_iface) ldi yh, HIGH(com2w0_iface)
com2wnLowLevelRunOnePort_loop: ; loop through all interfaces com2wnLowLevelRun_loop: ; loop through all interfaces
ldd r20, Y+COM2W_IFACE_OFFS_PINMASK_CLK ldd r20, Y+COM2W_IFACE_OFFS_PINMASK_CLK
mov r21, r20 mov r21, r20
and r21, r18 ; CLK for interface changed? and r21, r18 ; CLK for interface changed?
breq com2wnLowLevelRunOnePort_nextIface breq com2wnLowLevelRun_nextIface
push r16 push r16
push r18 push r18
push r19 push r19
@@ -48,29 +130,85 @@ com2wnLowLevelRunOnePort_loop: ; loop through all interfaces
pop r19 pop r19
pop r18 pop r18
pop r16 pop r16
com2wnLowLevelRunOnePort_nextIface: com2wnLowLevelRun_nextIface:
adiw yh:yl, COM2W_IFACE_SIZE ldi r20, COM2W_IFACE_SIZE
add yl, r20
adc yh, r20
sub yh, r20
dec r19 dec r19
brne com2wnLowLevelRunOnePort_loop brne com2wnLowLevelRun_loop
sec sec
com2wnLowLevelRunOnePort_ret: com2wnLowLevelRun_ret:
ret ret
; end routine for single port
.else
; begin routine for double port
ldi yl, LOW(com2wnIoRingBuffer)
ldi yh, HIGH(com2wnIoRingBuffer)
push r15
in r15, SREG
cli
rcall RingBufferY_ReadByte ; (R17, R18, X)
brcc com2wnLowLevelRun_popr15Ret
push r16
rcall RingBufferY_ReadByte ; (R17, R18, X)
mov r17, r16
pop r16
out SREG, r15
pop r15
lds r18, com2wnIoCurrentClockStates
eor r18, r16 ; r18: changed bits in clk states
sts com2wnIoCurrentClockStates, r16 ; store new state
; r16=clock byte, r17=data byte, r18=clock change byte
ldi r19, COM_PORTS
ldi yl, LOW(com2w0_iface) ; first interface
ldi yh, HIGH(com2w0_iface)
com2wnLowLevelRun_loop: ; loop through all interfaces
ldd r20, Y+COM2W_IFACE_OFFS_PINMASK_CLK
mov r21, r20
and r21, r18 ; CLK for interface changed?
breq com2wnLowLevelRun_nextIface
push r16
push r18
push r19
rcall com2wnActOnClock ; (r16, r17, r18, X)
pop r19
pop r18
pop r16
com2wnLowLevelRun_nextIface:
ldi r20, COM2W_IFACE_SIZE
add yl, r20
adc yh, r20
sub yh, r20
dec r19
brne com2wnLowLevelRun_loop
sec
rjmp com2wnLowLevelRun_ret
com2wnLowLevelRun_popr15Ret:
out SREG, r15
pop r15
clc
com2wnLowLevelRun_ret:
ret
; end routine for double port
.endif
; @end ; @end
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wPeriodically @global ; @routine com2wPeriodically @global
; ;
; @clobbers R16, Y ; @param Y pointer to interface data
; @clobbers R16
com2wPeriodically: com2wPeriodically:
push r15 push r15
in r15, SREG in r15, SREG
cli cli
rcall NET_Interface_Periodically rcall NET_Interface_Periodically ; (R16)
ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER
inc r16 inc r16
breq com2wPeriodically_end breq com2wPeriodically_end
@@ -193,7 +331,7 @@ com2wnRunIdle_haveMsg:
push r16 push r16
rcall NET_Buffer_Locate ; (R17) rcall NET_Buffer_Locate ; (R17)
adiw xh:xl, 1 adiw xh:xl, 1
rcall com2w0SendMsg ; (R16, R17, R22, R24, R25, X) rcall com2wnSendMsg ; (R16, R17, R22, R24, R25, X)
push r15 push r15
in r15, SREG ; save SREG (no CLI, we want to save CFLAG only) in r15, SREG ; save SREG (no CLI, we want to save CFLAG only)
ldi r16, COM2W_MODE_IDLE ldi r16, COM2W_MODE_IDLE

View File

@@ -20,22 +20,22 @@
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wSendMsg ; @routine com2wnSendMsg
; ;
; @param X pointer to bytes to send ; @param X pointer to bytes to send
; @param Y pointer to interface data in SRAM ; @param Y pointer to interface data in SRAM
; @return CFLAG set if message sent, cleared otherwise ; @return CFLAG set if message sent, cleared otherwise
; @clobbers R16, R18 (R20, R22, R24, R25, X) ; @clobbers R16, R18 (R20, R22, R24, R25, X)
com2wSendMsg: com2wnSendMsg:
ldi r20, 6 ; wait for about 60us for clock low ldi r20, 6 ; wait for about 60us for clock low
rcall com2wWaitForClockLowMulti10Us ; (R17, R20, R22) rcall com2wWaitForClockLowMulti10Us ; (R17, R20, R22)
brcs com2wSendMsg_busy ; CLK got low while waiting, so line is busy brcs com2wnSendMsg_busy ; CLK got low while waiting, so line is busy
push r15 push r15
in r15, SREG in r15, SREG
cli ; atomic disable irq and set CLK low cli ; atomic disable irq and set CLK low
rcall com2wDisableClkIrq ; (none) rcall com2wnDisableClkIrq ; (none)
rcall com2wClkSetLow ; reserve bus (none) rcall com2wnClkSetLow ; reserve bus (none)
out SREG, r15 out SREG, r15
pop r15 pop r15
adiw xh:xl, NETMSG_OFFS_MSGLEN adiw xh:xl, NETMSG_OFFS_MSGLEN
@@ -44,17 +44,17 @@ com2wSendMsg:
inc r18 ; adjust for DESTADDR inc r18 ; adjust for DESTADDR
inc r18 ; adjust for MSGLEN inc r18 ; adjust for MSGLEN
inc r18 ; adjust for CRCBYTE inc r18 ; adjust for CRCBYTE
rcall com2wWaitTime1 ; longer wait period (R22) rcall com2wnWaitTime1 ; longer wait period (R22)
rcall com2wSendBytes ; (r16, r17, r18, r22, X) rcall com2wnSendBytes ; (r16, r17, r18, r22, X)
rcall com2wClkSetHigh ; make sure bus is released rcall com2wClkSetHigh ; make sure bus is released
rcall com2wDataSetHigh rcall com2wnDataSetHigh
rcall com2wEnableClkIrq ; (none) rcall com2wnEnableClkIrq ; (none)
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25) rcall NET_Interface_IncCounter16 ; (R24, R25)
sec sec
ret ret
com2wSendMsg_busy: com2wnSendMsg_busy:
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25) rcall NET_Interface_IncCounter16 ; (R24, R25)
clc clc
@@ -64,68 +64,68 @@ com2wSendMsg_busy:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wSendBytes ; @routine com2wnSendBytes
; ;
; @param R18 number of bytes to send ; @param R18 number of bytes to send
; @param X pointer to bytes to send ; @param X pointer to bytes to send
; @param Y pointer to interface data in SRAM ; @param Y pointer to interface data in SRAM
; @clobbers: r16, r18, X (r17, r22) ; @clobbers: r16, r18, X (r17, r22)
com2wSendBytes: com2wnSendBytes:
com2wSendBytes_loop: com2wnSendBytes_loop:
rcall com2wClkSetLow ; (none) rcall com2wnClkSetLow ; (none)
rcall com2wWaitTime1 ; longer wait period (R22) rcall com2wnWaitTime1 ; longer wait period (R22)
ld r16, X+ ld r16, X+
rcall com2wSendByte ; (R16, R17, R22) rcall com2wnSendByte ; (R16, R17, R22)
dec r18 dec r18
brne com2wSendBytes_loop brne com2wnSendBytes_loop
ret ret
; @end ; @end
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wSendByte ; @routine com2wnSendByte
; ;
; @param R16 byte to send ; @param R16 byte to send
; @param Y pointer to interface data in SRAM ; @param Y pointer to interface data in SRAM
; @clobbers r16, r17 (r22) ; @clobbers r16, r17 (r22)
com2wSendByte: com2wnSendByte:
ldi r17, 8 ldi r17, 8
com2wSendByte_loop: com2wnSendByte_loop:
rcall com2wClkSetLow rcall com2wnClkSetLow
rcall com2wWaitTime1 ; longer wait period (R22) rcall com2wnWaitTime1 ; longer wait period (R22)
lsr r16 lsr r16
brcs com2wSendByte_send1 brcs com2wnSendByte_send1
rcall com2wDataSetLow rcall com2wnDataSetLow
rjmp com2wSendByte_sent rjmp com2wnSendByte_sent
com2wSendByte_send1: com2wnSendByte_send1:
rcall com2wDataSetHigh rcall com2wnDataSetHigh
com2wSendByte_sent: com2wnSendByte_sent:
rcall com2wWaitTime2 ; shorter wait period (R22) rcall com2wnWaitTime2 ; shorter wait period (R22)
push r15 push r15
in r15, SREG in r15, SREG
cli ; ensure time period by disabling irqs cli ; ensure time period by disabling irqs
rcall com2wClkSetHigh rcall com2wClkSetHigh
rcall com2wWaitTime1 ; longer wait period (R22) rcall com2wnWaitTime1 ; longer wait period (R22)
out SREG, r15 out SREG, r15
pop r15 pop r15
dec r17 dec r17
brne com2wSendByte_loop brne com2wnSendByte_loop
ret ret
; @end ; @end
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wWaitTime1 ; @routine com2wnWaitTime1
; ;
; waits for longer period (e.g. 30ns) ; waits for longer period (e.g. 30ns)
; ;
; @clobbers R22 ; @clobbers R22
com2wWaitTime1: com2wnWaitTime1:
Utils_WaitNanoSecs COM2W_WAITTIME1, 7, r22 ; wait for longer time (minus RCALL and RET) Utils_WaitNanoSecs COM2W_WAITTIME1, 7, r22 ; wait for longer time (minus RCALL and RET)
ret ret
; @end ; @end
@@ -133,13 +133,13 @@ com2wWaitTime1:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wWaitTime2 ; @routine com2wnWaitTime2
; ;
; waits for shorter period (e.g. 10ns) ; waits for shorter period (e.g. 10ns)
; ;
; @clobbers R22 ; @clobbers R22
com2wWaitTime2: com2wnWaitTime2:
Utils_WaitNanoSecs COM2W_WAITTIME2, 7, r22 ; wait for shorter time (minus RCALL and RET) Utils_WaitNanoSecs COM2W_WAITTIME2, 7, r22 ; wait for shorter time (minus RCALL and RET)
ret ret
; @end ; @end

View File

@@ -29,22 +29,44 @@
; @clobbers: r16, r20, r22 ; @clobbers: r16, r20, r22
com2wWaitForClockHighMulti10Us: com2wWaitForClockHighMulti10Us:
.if clock == 8000000 .if clock > 1000000
add r20, r20 ; *2 ; begin version for > 1000000 Hz
add r20, r20 ; *4 ldi r20, LOW(clock/1000000)
add r20, r20 ; *8 ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
.endif com2wWaitForClockHighMulti10Us_loop0:
.elif clock == 1000000 push r20 ; +2
; nothing to do 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
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
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 .else
.error "Unhandled clock speed" ; begin version for 1000000 Hz
.endif
ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2 ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port) inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1 and r16, r22 ; +1
brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE breq com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port) inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
and r16, r22 ; +1 and r16, r22 ; +1
@@ -53,12 +75,14 @@ com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop
nop ; +1 nop ; +1
dec r20 ; +1 dec r20 ; +1
brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
clc ; +1 clc ; +1
ret ; +4 ret ; +4
com2wWaitForClockHighMulti10Us_stateReached: com2wWaitForClockHighMulti10Us_stateReached:
sec ; +1 sec ; +1
ret ; +4 ret ; +4
; end version for 1000000 Hz
.endif
; @end ; @end
@@ -68,22 +92,44 @@ com2wWaitForClockHighMulti10Us_stateReached:
; ;
; Wait for low CLK ; Wait for low CLK
; ;
; @param R20 multiple of 10us to wait (e.g. "2" for "20" us, max: 32) ; @param R20 multiple of 10us to wait (e.g. "2" for "20" us)
; @return CFLAG set if okay (state reached), cleared on error ; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r16, r20, r22 ; @clobbers: r16, r20, r22
com2wWaitForClockLowMulti10Us: com2wWaitForClockLowMulti10Us:
.if clock == 8000000 .if clock > 1000000
add r20, r20 ; *2 ; begin version for > 1000000 Hz
add r20, r20 ; *4 ldi r20, LOW(clock/1000000)
add r20, r20 ; *8 ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
.endif com2wWaitForClockLowMulti10Us_loop0:
.elif clock == 1000000 push r20 ; +2
; nothing to do 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 ; +2
dec r20 ; +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 .else
.error "Unhandled clock speed" ; begin version for 1000000 Hz
.endif
ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2 ldd r22, Y+COM2W_IFACE_OFFS_PINMASK_CLK ; +2
com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port) inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
@@ -103,6 +149,8 @@ com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop
com2wWaitForClockLowMulti10Us_stateReached: com2wWaitForClockLowMulti10Us_stateReached:
sec ; +1 sec ; +1
ret ; +4 ret ; +4
; end version for 1000000 Hz
.endif
; @end ; @end

View File

@@ -92,8 +92,8 @@ ioRawWaitForValidMsg_waitLowLoop1:
.endif .endif
ldi r18, 5 ldi r18, 5
ioRawWaitForValidMsg_waitLowLoop2: ioRawWaitForValidMsg_waitLowLoop2:
ldi r20, 20 ; wait for about 100us for clock low ldi r20, 10 ; wait for about 100us for clock low
rcall com2wWaitForClockLowMulti5Us ; R20, R22 rcall com2wWaitForClockLowMulti10Us ; R20, R22
brcs ioRawWaitForValidMsg_recvMsg brcs ioRawWaitForValidMsg_recvMsg
dec r18 dec r18
brne ioRawWaitForValidMsg_waitLowLoop2 brne ioRawWaitForValidMsg_waitLowLoop2
@@ -132,8 +132,8 @@ ioRawWaitForValidMsg_end:
; @clobbers R18, R20 (R16, R17, R20, R22, X) ; @clobbers R18, R20 (R16, R17, R20, R22, X)
com2wSendMsg: com2wSendMsg:
ldi r20, 11 ; wait for about 55us for clock low ldi r20, 6 ; wait for about 60us for clock low
rcall com2wWaitForClockLowMulti5Us rcall com2wWaitForClockLowMulti10Us
brcs com2wSendMsg_busy ; CLK got low while waiting, so line is busy brcs com2wSendMsg_busy ; CLK got low while waiting, so line is busy
rcall com2wClkSetLow ; reserve bus (none) rcall com2wClkSetLow ; reserve bus (none)
adiw xh:xl, NETMSG_OFFS_MSGLEN adiw xh:xl, NETMSG_OFFS_MSGLEN
@@ -267,21 +267,12 @@ com2wRecvByte:
ldi r17, 8 ldi r17, 8
clr r16 clr r16
com2wRecvByte_loop: com2wRecvByte_loop:
ldi r20, 31 ; wait up to 155us for clock low ldi r20, 30 ; wait up to 300us for clock low
rcall com2wWaitForClockLowMulti5Us ; (R20, R22) rcall com2wWaitForClockLowMulti10Us ; (R20, R22)
brcs com2wRecvByte_waitForClkHigh
ldi r20, 31 ; wait up to 155us for clock low
rcall com2wWaitForClockLowMulti5Us ; (R20, R22)
brcc com2wRecvByte_end brcc com2wRecvByte_end
com2wRecvByte_waitForClkHigh: ldi r20, 30 ; wait up to 300us for clock high
ldi r20, 31 ; wait up to 155us for clock high rcall com2wWaitForClockHighMulti10Us ; (R20, R22)
rcall com2wWaitForClockHighMulti5Us ; (R20, R22)
brcs com2wRecvByte_readBit
ldi r20, 31 ; wait up to 155us for clock high
rcall com2wWaitForClockHighMulti5Us ; (R20, R22)
brcc com2wRecvByte_end brcc com2wRecvByte_end
com2wRecvByte_readBit:
; handle received bit ; handle received bit
inr r18, COM_DATA_INPUT inr r18, COM_DATA_INPUT
andi r18, (1<<COM_DATA_PIN) andi r18, (1<<COM_DATA_PIN)
@@ -360,71 +351,137 @@ com2wDataSetLow:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wWaitForClockHighMulti5Us ; @routine com2wWaitForClockLowMulti10Us
; ;
; Wait for high CLK ; 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 ; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r20, r22 ; @clobbers: r16, r20, r22
com2wWaitForClockHighMulti5Us: com2wWaitForClockLowMulti10Us:
.if clock == 8000000 .if clock > 1000000
add r20, r20 ; *2 ; begin version for > 1000000 Hz
add r20, r20 ; *4 ldi r20, LOW(clock/1000000)
add r20, r20 ; *8 ldi r22, (1<<COM_CLK_PIN)
.endif com2wWaitForClockLowMulti10Us_loop0:
.elif clock == 1000000 push r20 ; +2
; nothing to do 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 ; +2
dec r20 ; +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 .else
.error "Unhandled clock speed" ; begin version for 1000000 Hz
.endif ldi r22, (1<<COM_CLK_PIN)
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
com2wWaitForClockHighMulti5Us_loop: ; 5 cycles per loop inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if not and r16, r22 ; +1
rjmp com2wWaitForClockHighMulti5Us_stateReached ; +2 breq com2wWaitForClockLowMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
dec r20 ; +1
brne com2wWaitForClockHighMulti5Us_loop ; +2 nop ; +1
clc ; +1
ret ; +4 dec r20 ; +1
com2wWaitForClockHighMulti5Us_stateReached: brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
sec ; +1 clc ; +1
ret ; +4 ret ; +4
com2wWaitForClockLowMulti10Us_stateReached:
sec ; +1
ret ; +4
; end version for 1000000 Hz
.endif
; @end ; @end
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; @routine com2wWaitForClockLowMulti5Us ; @routine com2wWaitForClockHighMulti10Us
; ;
; Wait for low CLK ; 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 ; @return CFLAG set if okay (state reached), cleared on error
; @clobbers: r20, r22 ; @clobbers: r16, r20, r22
com2wWaitForClockLowMulti5Us: com2wWaitForClockHighMulti10Us:
.if clock == 8000000 .if clock > 1000000
add r20, r20 ; *2 ; begin version for > 1000000 Hz
add r20, r20 ; *4 ldi r20, LOW(clock/1000000)
add r20, r20 ; *8 ldi r22, (1<<COM_CLK_PIN)
.endif com2wWaitForClockHighMulti10Us_loop0:
.elif clock == 1000000 push r20 ; +2
; nothing to do 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
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 ; +2
dec r20 ; +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 .else
.error "Unhandled clock speed" ; begin version for 1000000 Hz
.endif ldi r22, (1<<COM_CLK_PIN)
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
com2wWaitForClockLowMulti5Us_loop: ; 5 cycles per loop inr r16, COM_CLK_INPUT ; +1 (if low port, +2 if high port)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if not and r16, r22 ; +1
rjmp com2wWaitForClockLowMulti5Us_stateReached ; +2 brne com2wWaitForClockHighMulti10Us_stateReached ; +1 if FALSE, +2 if TRUE
dec r20 ; +1
brne com2wWaitForClockLowMulti5Us_loop ; +2 nop ; +1
clc ; +1
ret ; +4 dec r20 ; +1
com2wWaitForClockLowMulti5Us_stateReached: brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
sec ; +1 clc ; +1
ret ; +4 ret ; +4
com2wWaitForClockHighMulti10Us_stateReached:
sec ; +1
ret ; +4
; end version for 1000000 Hz
.endif
; @end ; @end