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

@@ -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
;
com2wnLowLevelRunOnePort:
com2wnLowLevelRun:
.if COM_DATA_INPUT == COM_CLK_INPUT
; begin routine for single port
ldi yl, LOW(com2wnIoRingBuffer)
ldi yh, HIGH(com2wnIoRingBuffer)
rcall RingBufferY_ReadByteGuarded ; (R17, R18, X)
brcc com2wnLowLevelRunOnePort_ret
brcc com2wnLowLevelRun_ret
lds r18, com2wnIoCurrentClockStates
eor r18, r16 ; r18: changed bits in clk states
@@ -35,11 +117,11 @@ com2wnLowLevelRunOnePort:
ldi r19, COM_PORTS
ldi yl, LOW(com2w0_iface) ; first interface
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
mov r21, r20
and r21, r18 ; CLK for interface changed?
breq com2wnLowLevelRunOnePort_nextIface
breq com2wnLowLevelRun_nextIface
push r16
push r18
push r19
@@ -48,29 +130,85 @@ com2wnLowLevelRunOnePort_loop: ; loop through all interfaces
pop r19
pop r18
pop r16
com2wnLowLevelRunOnePort_nextIface:
adiw yh:yl, COM2W_IFACE_SIZE
com2wnLowLevelRun_nextIface:
ldi r20, COM2W_IFACE_SIZE
add yl, r20
adc yh, r20
sub yh, r20
dec r19
brne com2wnLowLevelRunOnePort_loop
brne com2wnLowLevelRun_loop
sec
com2wnLowLevelRunOnePort_ret:
com2wnLowLevelRun_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
; ---------------------------------------------------------------------------
; @routine com2wPeriodically @global
;
; @clobbers R16, Y
; @param Y pointer to interface data
; @clobbers R16
com2wPeriodically:
push r15
in r15, SREG
cli
rcall NET_Interface_Periodically
rcall NET_Interface_Periodically ; (R16)
ldd r16, Y+COM2W_IFACE_OFFS_MODECOUNTER
inc r16
breq com2wPeriodically_end
@@ -193,7 +331,7 @@ com2wnRunIdle_haveMsg:
push r16
rcall NET_Buffer_Locate ; (R17)
adiw xh:xl, 1
rcall com2w0SendMsg ; (R16, R17, R22, R24, R25, X)
rcall com2wnSendMsg ; (R16, R17, R22, R24, R25, X)
push r15
in r15, SREG ; save SREG (no CLI, we want to save CFLAG only)
ldi r16, COM2W_MODE_IDLE