; *************************************************************************** ; copyright : (C) 2025 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_COM2W_COM2W_H #define AVR_MODULES_COM2W_COM2W_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 .dseg com2w_iface: .byte COM2W_IFACE_SIZE .cseg ; --------------------------------------------------------------------------- ; @routine COM2W_Init ; ; @clobbers COM2W_Init: ldi yl, LOW(com2w_iface) ldi yh, HIGH(com2w_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< 1000000 ; begin version for > 1000000 Hz ldi r22, clock/1000000 com2wWaitForClockHighMulti10Us_loop0: push r20 com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken) sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken) sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken) nop ; +1 dec r20 ; +1 brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE pop r20 dec r22 ; +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 ; begin version for 1000000 Hz com2wWaitForClockHighMulti10Us_loop: ; 10 cycles per loop sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken) sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken) sbic COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockHighMulti10Us_stateReached ; (+2 if taken) nop ; +1 dec r20 ; +1 brne com2wWaitForClockHighMulti10Us_loop ; +2 if TRUE, +1 if FALSE clc ; +1 ret ; +4 com2wWaitForClockHighMulti10Us_stateReached: sec ; +1 ret ; +4 ; end version for 1000000 Hz .endif ; @end ; --------------------------------------------------------------------------- ; @routine com2wWaitForClockLowMulti10Us ; ; 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 com2wWaitForClockLowMulti10Us: .if clock > 1000000 ; begin version for > 1000000 Hz ldi r22, clock/1000000 com2wWaitForClockLowMulti10Us_loop0: push r20 com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken) sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken) sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken) nop ; +1 dec r20 ; +1 brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE pop r20 dec r22 ; +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 ; begin version for 1000000 Hz com2wWaitForClockLowMulti10Us_loop: ; 10 cycles per loop sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken) sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken) sbis COM_CLK_INPUT, COM_CLK_PIN ; +2 if skipped, +1 if taken rjmp com2wWaitForClockLowMulti10Us_stateReached ; (+2 if taken) nop ; +1 dec r20 ; +1 brne com2wWaitForClockLowMulti10Us_loop ; +2 if TRUE, +1 if FALSE clc ; +1 ret ; +4 com2wWaitForClockLowMulti10Us_stateReached: sec ; +1 ret ; +4 ; end version for 1000000 Hz .endif ; @end ; --------------------------------------------------------------------------- ; @routine com2wWaitTime1 ; ; waits for longer period (e.g. 30ns) ; ; @clobbers R22 com2wWaitTime1: Utils_WaitNanoSecs COM2W_WAITTIME1, 7, r22 ; wait for longer time (minus RCALL and RET) ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wWaitTime2 ; ; waits for shorter period (e.g. 10ns) ; ; @clobbers R22 com2wWaitTime2: Utils_WaitNanoSecs COM2W_WAITTIME2, 7, r22 ; wait for shorter time (minus RCALL and RET) ret ; @end ; --------------------------------------------------------------------------- ; @routine com2wPcintIsr @global @isr ; ; ISR for PCINT0/1 ; ; @clobbers: none com2wPcintIsr: push r15 in r15, SREG sbic COM_CLK_INPUT, COM_CLK_PIN rjmp com2wPcintIsr_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(com2w_iface) ldi yh, HIGH(com2w_iface) rcall com2wReceiveNextPkg ; (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 com2wPcintIsr_end: out SREG, r15 pop r15 reti ; @end #endif ; AVR_MODULES_COM2W_COM2W_H