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<