diff --git a/avr/modules/0BUILD b/avr/modules/0BUILD
index 9d728109..0e8c5771 100644
--- a/avr/modules/0BUILD
+++ b/avr/modules/0BUILD
@@ -12,6 +12,7 @@
clock
cny70
com2w
+ com2w2
com2w_router
ds18b20
eeprom
diff --git a/avr/modules/com2w2/0BUILD b/avr/modules/com2w2/0BUILD
new file mode 100644
index 00000000..b836b93f
--- /dev/null
+++ b/avr/modules/com2w2/0BUILD
@@ -0,0 +1,11 @@
+
+
+
+
+
+ com2w.asm
+
+
+
+
+
diff --git a/avr/modules/com2w2/byteread.asm b/avr/modules/com2w2/byteread.asm
new file mode 100644
index 00000000..0ac71c25
--- /dev/null
+++ b/avr/modules/com2w2/byteread.asm
@@ -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< 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
+
diff --git a/avr/modules/com2w2/macros.asm b/avr/modules/com2w2/macros.asm
new file mode 100644
index 00000000..f6f48e8d
--- /dev/null
+++ b/avr/modules/com2w2/macros.asm
@@ -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<