avr: added com2w2 (slightly improved version of com2w).

- move IRQ control to main code (only the main code knows exactly which
  combination of pins is used for com2)
- split one big module into multiple smaller files (easier to maintain)
This commit is contained in:
Martin Preuss
2026-07-05 20:06:00 +02:00
parent b863e29612
commit db3f88f3af
11 changed files with 992 additions and 0 deletions

View File

@@ -12,6 +12,7 @@
clock clock
cny70 cny70
com2w com2w
com2w2
com2w_router com2w_router
ds18b20 ds18b20
eeprom eeprom

11
avr/modules/com2w2/0BUILD Normal file
View File

@@ -0,0 +1,11 @@
<?xml?>
<gwbuild>
<extradist>
com2w.asm
</extradist>
</gwbuild>

View File

@@ -0,0 +1,81 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_BYTEREAD_H
#define AVR_MODULES_COM2W2_BYTEREAD_H
.cseg
; ---------------------------------------------------------------------------
; @routine com2w2RecvByteWaitForQuietClk
;
; Wait until the clock line is consistently high for 1ms.
;
; @clobbers r18, r20, r22
com2w2RecvByteWaitForQuietClk:
ldi r18, 200
com2w2RecvByteWaitForQuietClk_loop:
ldi r20, 100 ; wait up to 1ms for clock high (R20, R22)
rcall com2w2WaitForClockLowMulti10Us ; (r20, r22)
brcs com2w2RecvByteWaitForQuietClk_waitForLow
dec r18
brne com2w2RecvByteWaitForQuietClk_loop
rjmp com2w2RecvByteWaitForQuietClk_ret
com2w2RecvByteWaitForQuietClk_waitForLow:
ldi r20, 100 ; wait up to 1ms for clock low (R20, R22)
rcall com2w2WaitForClockLowMulti10Us
brcc com2w2RecvByteWaitForQuietClk_ret ; not low within 1ms, assume line is quiet
brne com2w2RecvByteWaitForQuietClk_loop
com2w2RecvByteWaitForQuietClk_ret:
ret
; ---------------------------------------------------------------------------
; @routine com2w2RecvByte
;
; @return CFLAG set if byte received, cleared on error
; @return r16 byte received
; @clobbers r17, r18, r20, r22
com2w2RecvByte:
ldi r17, 8
clr r16
com2w2RecvByte_loop:
ldi r20, 100 ; wait up to 1ms for clock low
rcall com2w2WaitForClockLowMulti10Us ; (R20, R22)
brcc com2w2RecvByte_end
ldi r20, 100 ; wait up to 1ms for clock high
rcall com2w2WaitForClockHighMulti10Us ; (R20, R22)
brcc com2w2RecvByte_end
; handle received bit
inr r18, COM_DATA_INPUT
andi r18, (1<<COM_DATA_PIN)
clc
breq com2w2RecvByte_clockData
sec
com2w2RecvByte_clockData:
ror r16
dec r17
brne com2w2RecvByte_loop
sec
com2w2RecvByte_end:
ret
; @end
#endif

View File

@@ -0,0 +1,76 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_BYTEWRITE_H
#define AVR_MODULES_COM2W2_BYTEWRITE_H
.cseg
; ---------------------------------------------------------------------------
; @routine com2w2SendBytes
;
; @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)
com2w2SendBytes:
com2w2SendBytes_loop:
rcall com2w2ClkSetLow ; (none)
rcall com2w2WaitTime1 ; longer wait period (R22)
ld r16, X+
rcall com2w2SendByte ; (R16, R17, R22)
dec r18
brne com2w2SendBytes_loop
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2SendByte
;
; @param R16 byte to send
; @clobbers: r16, r17 (r22)
com2w2SendByte:
push r15
in r15, SREG
ldi r17, 8
com2w2SendByte_loop:
M_COM2WCLKSETLOW
out SREG, r15 ; probably enable irqs
rcall com2w2WaitTime1 ; wait for longer time (R22)
lsr r16
brcs com2w2SendByte_send1
M_COM2WDATASETLOW
rjmp com2w2SendByte_sent
com2w2SendByte_send1:
M_COM2WDATASETHIGH
com2w2SendByte_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 com2w2WaitTime2 ; wait for shorter time (R22)
dec r17
brne com2w2SendByte_loop
out SREG, r15
pop r15
rcall com2w2WaitTime2 ; wait for shorter time (R22)
M_COM2WDATASETHIGH ; ensure data line is high
ret
; @end
#endif

View File

@@ -0,0 +1,20 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_DATA_H
#define AVR_MODULES_COM2W2_DATA_H
.dseg
com2w2_iface: .byte COM2W2_IFACE_SIZE
#endif

View File

@@ -0,0 +1,26 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_DEFS_H
#define AVR_MODULES_COM2W2_DEFS_H
.equ COM2W2_WAITTIME1 = 25000
.equ COM2W2_WAITTIME2 = 15000
.equ COM2W2_BUFFER_SIZE = NET_BUFFERS_SIZE-1
.equ COM2W2_IFACE_OFFS_BEGIN = NET_IFACE_SIZE
.equ COM2W2_IFACE_OFFS_BUFFER = COM2W2_IFACE_OFFS_BEGIN+0
.equ COM2W2_IFACE_SIZE = COM2W2_IFACE_OFFS_BUFFER+COM2W2_BUFFER_SIZE
#endif

317
avr/modules/com2w2/io.asm Normal file
View File

@@ -0,0 +1,317 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_IO_H
#define AVR_MODULES_COM2W2_IO_H
.cseg
; ---------------------------------------------------------------------------
; @routine com2w2EnableClkIrq
;
; @clobbers
com2w2EnableClkIrq:
.ifdef COM_ENABLEIRQ_FN
bigcall COM_ENABLEIRQ_FN
.else
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
.endif
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2DisableClkIrq
;
; @clobbers none
com2w2DisableClkIrq:
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 com2w2ClkSetHigh
;
; @clobbers none
com2w2ClkSetHigh:
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 com2w2ClkSetLow
;
; @clobbers none
com2w2ClkSetLow:
sbi COM_CLK_DDR, COM_CLK_PIN ; set CLK as output
cbi COM_CLK_OUTPUT, COM_CLK_PIN ; set CLK low
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2DataSetHigh
;
; @clobbers none
com2w2DataSetHigh:
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 com2w2DataSetLow
;
; @clobbers none
com2w2DataSetLow:
sbi COM_DATA_DDR, COM_DATA_PIN ; set DATA as output
cbi COM_DATA_OUTPUT, COM_DATA_PIN ; set DATA low
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2WaitForClockHighMulti10Us
;
; 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
com2w2WaitForClockHighMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
ldi r22, clock/1000000
com2w2WaitForClockHighMulti10Us_loop0:
push r20
com2w2WaitForClockHighMulti10Us_loop: ; 10 cycles per loop
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockHighMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2w2WaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20
dec r22 ; +1
brne com2w2WaitForClockHighMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
clc ; +1
ret ; +4
com2w2WaitForClockHighMulti10Us_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
com2w2WaitForClockHighMulti10Us_loop: ; 10 cycles per loop
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockHighMulti10Us_stateReached ; (+2 if taken)
sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockHighMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2w2WaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE
clc ; +1
ret ; +4
com2w2WaitForClockHighMulti10Us_stateReached:
sec ; +1
ret ; +4
; end version for 1000000 Hz
.endif
; @end
; ---------------------------------------------------------------------------
; @routine com2w2WaitForClockLowMulti10Us
;
; 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
com2w2WaitForClockLowMulti10Us:
.if clock > 1000000
; begin version for > 1000000 Hz
ldi r22, clock/1000000
com2w2WaitForClockLowMulti10Us_loop0:
push r20
com2w2WaitForClockLowMulti10Us_loop: ; 10 cycles per loop
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockLowMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2w2WaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
pop r20
dec r22 ; +1
brne com2w2WaitForClockLowMulti10Us_loop0 ; +1 if FALSE, +2 if TRUE
clc ; +1
ret ; +4
com2w2WaitForClockLowMulti10Us_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
com2w2WaitForClockLowMulti10Us_loop: ; 10 cycles per loop
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockLowMulti10Us_stateReached ; (+2 if taken)
sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken
rjmp com2w2WaitForClockLowMulti10Us_stateReached ; (+2 if taken)
nop ; +1
dec r20 ; +1
brne com2w2WaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE
clc ; +1
ret ; +4
com2w2WaitForClockLowMulti10Us_stateReached:
sec ; +1
ret ; +4
; end version for 1000000 Hz
.endif
; @end
; ---------------------------------------------------------------------------
; @routine com2w2WaitTime1
;
; waits for longer period (e.g. 30ns)
;
; @clobbers R22
com2w2WaitTime1:
Utils_WaitNanoSecs COM2W2_WAITTIME1, 7, r22 ; wait for longer time (minus RCALL and RET)
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2WaitTime2
;
; waits for shorter period (e.g. 10ns)
;
; @clobbers R22
com2w2WaitTime2:
Utils_WaitNanoSecs COM2W2_WAITTIME2, 7, r22 ; wait for shorter time (minus RCALL and RET)
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2PcintIsr @global @isr
;
; ISR for PCINT0/1
;
; @clobbers: none
com2w2PcintIsr:
push r15
in r15, SREG
sbic COM_CLK_INPUT, COM_CLK_PIN
rjmp com2w2PcintIsr_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(com2w2_iface)
ldi yh, HIGH(com2w2_iface)
rcall com2w2ReceiveNextPkg ; (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
com2w2PcintIsr_end:
out SREG, r15
pop r15
reti
; @end
#endif

View File

@@ -0,0 +1,90 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_MACROS_H
#define AVR_MODULES_COM2W2_MACROS_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
.macro M_COM2WSETUPINT0
inr r16, MCUCR
cbr r16, (1<<ISC01) | (1<<ISC00)
sbr r16, (1<<ISC01) | (0<<ISC00) ; falling edge of ATTN
outr MCUCR, r16
; sbr r16, (0<<ISC01) | (0<<ISC00) ; low level triggers
inr r16, COM_IRQ_ADDR_CLK ; enable irq for ATTN line
sbr r16, (1<<COM_IRQ_BIT_CLK)
outr COM_IRQ_ADDR_CLK, r16
.endmacro
.macro M_COM2WSETUPPCI
inr r16, COM_IRQ_ADDR_CLK ; enable pin change irq for CLK line
ori r16, (1<<COM_IRQ_BIT_CLK)
outr COM_IRQ_ADDR_CLK, r16
; sbi COM_IRQ_ADDR_CLK, COM_IRQ_BIT_CLK ; enable pin change irq for CLK line
in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
ori r16, (1<<COM_IRQ_GIMSK_CLK)
out GIMSK, R16
ldi r16, (1<<COM_IRQ_GIFR_CLK) ; clear pending irq by writing 1 to CLK bit
out GIFR, r16
.endmacro
.macro M_COM2WSETUPPCICR
inr r16, COM_IRQ_ADDR_CLK ; enable pin change irq for CLK line
ori r16, (1<<COM_IRQ_BIT_CLK)
outr COM_IRQ_ADDR_CLK, r16
inr r16, COM_IRQ_ICR_ADDR ; enable pin change irq in PCICR
ori r16, (1<<COM_IRQ_ICR_BIT)
outr COM_IRQ_ICR_ADDR, R16
ldi r16, (1<<COM_IRQ_IFR_BIT) ; clear pending irq by writing 1 to CLK bit
out COM_IRQ_IFR_ADDR, r16
.endmacro
#endif

234
avr/modules/com2w2/main.asm Normal file
View File

@@ -0,0 +1,234 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_MAIN_H
#define AVR_MODULES_COM2W2_MAIN_H
.cseg
; ---------------------------------------------------------------------------
; @routine COM2W2_Init
;
; @clobbers
COM2W2_Init:
ldi yl, LOW(com2w2_iface)
ldi yh, HIGH(com2w2_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
.ifdef COM_SETUPIRQ_FN
bigcall COM_SETUPIRQ_FN
.endif
; setup pin-change interrupt for CLK
rcall com2w2EnableClkIrq
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2W2_Every100ms @global
;
; @clobbers R16, Y
COM2W2_Every100ms:
ldi yl, LOW(com2w2_iface)
ldi yh, HIGH(com2w2_iface)
push r15
in r15, SREG
cli
rcall NET_Interface_Periodically ; (R16)
out SREG, r15
pop r15
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2W2_Run @global
;
; @clobbers (R16, R17, R18, R20, R22, R24, R25, X)
COM2W2_Run:
push r15
in r15, SREG
cli
ldi yl, LOW(com2w2_iface)
ldi yh, HIGH(com2w2_iface)
rcall com2w2SendNextPkg ; (R16, R17, R18, R20, R22, R24, R25, X)
brcs COM2W2_Run_ok
pop r15
clc
rjmp COM2W2_Run_ret
COM2W2_Run_ok:
pop r15
sec
COM2W2_Run_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2ReceiveNextPkg
;
; Receive packet.
;
; @param Y pointer to start of interface data
; @clobbers R16, R17, R18, R19, R20, R22, R24, R25, X
com2w2ReceiveNextPkg:
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
ldi r19, COM2W2_BUFFER_SIZE
rcall com2w2RecvMsg ; (r16, r17, r18, r19, r20, r22, r24, r25, X)
brcc com2w2ReceiveNextPkg_end
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
brcc com2w2ReceiveNextPkg_eCrc
#ifndef COM_ACCEPT_ALL_DEST
; check destination addr
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W2_IFACE_OFFS_BUFFER
adiw xh:xl, NETMSG_OFFS_DESTADDR
ld r16, X ; read destination address
cpi r16, 0xff
breq com2w2ReceiveNextPkg_forMe
ldd r17, Y+NET_IFACE_OFFS_ADDRESS
cp r16, r17
breq com2w2ReceiveNextPkg_forMe
; packet not for me, but correctly received, inc counter, but don't light LED
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_forMe:
#endif
; msg received, alloc buffer for it
rcall NET_Buffer_Alloc ; R16=buffer num (R16, R17, X)
brcs com2w2ReceiveNextPkg_gotBuffer
; out of memory
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2w2ReceiveNextPkg_end
; copy received message into allocated buffer
com2w2ReceiveNextPkg_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, COM2W2_IFACE_OFFS_BUFFER ; Z=SRC
adiw xh:xl, 1 ; X=DEST
ldd r18, Z+NETMSG_OFFS_MSGLEN
inc r18
inc r18
inc r18
com2w2ReceiveNextPkg_copyLoop:
ld r17, Z+
st X+, r17
dec r18
brne com2w2ReceiveNextPkg_copyLoop
pop zh
pop zl
; add to incoming msg pool
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
brcc com2w2ReceiveNextPkg_eMissed
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
#ifdef LED1_NETWORK_ACTIVITY
bigcall LED1_SetActivityTiming
#endif
rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_eCrc:
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2w2ReceiveNextPkg_end
com2w2ReceiveNextPkg_eMissed:
push r16
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
pop r16
; fall-through to release buffer
com2w2ReceiveNextPkg_relBuffer:
rcall NET_Buffer_ReleaseByNum ; (R16, X)
com2w2ReceiveNextPkg_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2w2SendNextPkg @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)
com2w2SendNextPkg:
rcall NET_Interface_PeekNextOutgoingMsgNum ; (R17, R18, X)
brcc com2w2SendNextPkg_end
rcall NET_Buffer_Locate ; get pointer to buffer (R17)
brcc com2w2SendNextPkg_end
adiw xh:xl, 1 ; skip buffer header
rcall com2w2SendMsg ; (R16, R18, R20, R22, R24, R25, X)
brcc com2w2SendNextPkg_end
rcall NET_Interface_GetNextOutgoingMsgNum ; remove from stack (R17, R18, X)
rcall NET_Buffer_ReleaseByNum ; release buffer (R16, X)
sec
com2w2SendNextPkg_end:
ret
; @end
#endif

View File

@@ -0,0 +1,71 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_MSGREAD_H
#define AVR_MODULES_COM2W2_MSGREAD_H
.cseg
; ---------------------------------------------------------------------------
; @routine com2w2RecvMsg
;
; Receive a packet into buffer pointed to by X.
; Expects interrupts to be disabled.
;
; @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
com2w2RecvMsg:
; check buffer size
subi r19, 2
brcs com2w2RecvMsg_eBadSize
; read destination address
rcall com2w2RecvByte ; (r17, r18, r20, r22)
brcc com2w2RecvMsg_eIo
st X+, r16
; read remaining msg size
rcall com2w2RecvByte ; (r17, r18, r20, r22)
brcc com2w2RecvMsg_eIo
st X+, r16
inc r16 ; account for CRC byte
sub r19, r16
brcs com2w2RecvMsg_eBadSize
mov r19, r16
com2w2RecvMsg_loop:
rcall com2w2RecvByte ; (r17, r18, r20, r22)
brcc com2w2RecvMsg_eIo
st X+, r16
dec r19
brne com2w2RecvMsg_loop
sec
rjmp com2w2RecvMsg_end
com2w2RecvMsg_eBadSize:
ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW
rjmp com2w2RecvMsg_incCounterRet
com2w2RecvMsg_eIo:
ldi r16, NET_IFACE_OFFS_ERR_IO_LOW
com2w2RecvMsg_incCounterRet:
rcall NET_Interface_IncCounter16 ; (R24, R25)
rcall com2w2RecvByteWaitForQuietClk ; (r18, r20, r22)
com2w2RecvMsg_clcRet:
clc
com2w2RecvMsg_end:
ret
; @end
#endif

View File

@@ -0,0 +1,65 @@
; ***************************************************************************
; copyright : (C) 2026 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_COM2W2_MSGWRITE_H
#define AVR_MODULES_COM2W2_MSGWRITE_H
.cseg
; ---------------------------------------------------------------------------
; @routine com2w2SendMsg
;
; @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)
com2w2SendMsg:
ldi r20, 6 ; wait for about 60us for clock low
rcall com2w2WaitForClockLowMulti10Us ; (R16, R20, R22)
brcs com2w2SendMsg_busy ; CLK got low while waiting, so line is busy
push r15
in r15, SREG
cli ; atomic disable irq and set CLK low
rcall com2w2DisableClkIrq ; (none)
rcall com2w2ClkSetLow ; 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 com2w2WaitTime1 ; longer wait period (R22)
rcall com2w2SendBytes ; (r16, r17, r18, r22, X)
rcall com2w2ClkSetHigh ; make sure bus is released
rcall com2w2DataSetHigh
rcall com2w2EnableClkIrq ; (none)
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
sec
ret
com2w2SendMsg_busy:
ldi r16, NET_IFACE_OFFS_ERR_BUSY_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
clc
ret
; @end
#endif