; *************************************************************************** ; copyright : (C) 2024 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. * ; *************************************************************************** ; *************************************************************************** ; code .cseg OWIMASTER_BEGIN: ; --------------------------------------------------------------------------- ; @routine OwiMaster_Init @global ; ; @return CFLAG set if okay, clear on error OwiMaster_Init: cbi OWI_DDR, OWI_PINNUM ; set to input cbi OWI_PORTOUT, OWI_PINNUM ; disable internal pullup sec ret ; @end ; --------------------------------------------------------------------------- ; @routine OwiMaster_Reset @global ; ; Cave: Needs interrupts to be disabled! ; ; @return r16 0xff if slave presence signal received, 0x00 otherwise ; @clobbers r21, r22 OwiMaster_Reset: ; send RESET pulse (min. 480usec) sbi OWI_DDR, OWI_PINNUM ; set to output cbi OWI_PORTOUT, OWI_PINNUM ; set value to zero rcall Utils_WaitFor100MicroSecs ; wait for about 500 usecs rcall Utils_WaitFor100MicroSecs rcall Utils_WaitFor100MicroSecs rcall Utils_WaitFor100MicroSecs rcall Utils_WaitFor100MicroSecs cbi OWI_DDR, OWI_PINNUM ; set to input ; after 16-60 uS slave pulls line low for 60-240 uS ; if present slave pulls line low for 60 usecs (we check after 30 usecs) ldi r21, 100 OwiMaster_Reset_LoopWaitForLow: ; wait for line low Utils_WaitNanoSecs 5000, 0, r22 sbis OWI_PORTIN, OWI_PINNUM rjmp OwiMaster_Reset_isLow dec r21 brne OwiMaster_Reset_LoopWaitForLow clr r16 ; not present rjmp OwiMaster_Reset_done OwiMaster_Reset_isLow: ldi r21, 160 OwiMaster_Reset_LoopWaitForHigh: ; wait for line high Utils_WaitNanoSecs 5000, 0, r22 sbic OWI_PORTIN, OWI_PINNUM rjmp OwiMaster_Reset_isHigh dec r21 brne OwiMaster_Reset_LoopWaitForHigh clr r16 ; not present rjmp OwiMaster_Reset_done OwiMaster_Reset_isHigh: ldi r16, 0xff ; presence detected OwiMaster_Reset_done: ret ; @end ; --------------------------------------------------------------------------- ; @routine OwiMaster_SendByte @global ; Cave: Needs interrupts to be disabled! ; ; @param r16 byte to send ; @clobbers r16, r21, r22 OwiMaster_SendByte: cbi OWI_DDR, OWI_PINNUM ; set to input cbi OWI_PORTOUT, OWI_PINNUM ; set value to zero ldi r21, 8 OwiMaster_SendByte_loop: sbi OWI_DDR, OWI_PINNUM ; set to output (pull line low) lsr r16 ; +1 bit to send -> CARRY brcs OwiMaster_SendByte_setHigh ; +1 / +2 OwiMaster_SendByte_setLow: Utils_WaitNanoSecs 60000, 0, r22 ; low for 60 usecs cbi OWI_DDR, OWI_PINNUM ; set to input (pulls line high) Utils_WaitNanoSecs 5000, 0, r22 ; wait for 5 usecs rjmp OwiMaster_SendByte_loopEnd OwiMaster_SendByte_setHigh: Utils_WaitNanoSecs 5000, 0, r22 ; keep low for 5 usecs cbi OWI_DDR, OWI_PINNUM ; set to output Utils_WaitNanoSecs 60000, 0, r22 ; keep high for remainder of write slot OwiMaster_SendByte_loopEnd: dec r21 brne OwiMaster_SendByte_loop ret ; @end ; --------------------------------------------------------------------------- ; @routine OwiMaster_RecvByte @global ; ; Receive a byte (slot size about 70 usecs) ; Cave: Needs interrupts to be disabled! ; ; @return r16 byte received ; @return CFLAG set if okay, cleared on error ; @clobbers r17, r20, r21, r22 OwiMaster_RecvByte: cbi OWI_DDR, OWI_PINNUM ; set to input cbi OWI_PORTOUT, OWI_PINNUM ; set value to zero clr r17 ldi r20, 8 OwiMaster_RecvByte_loop: sbi OWI_DDR, OWI_PINNUM ; set to output Utils_WaitNanoSecs 5000, 0, r22 ; set to low for 5 usecs ("1") cbi OWI_DDR, OWI_PINNUM ; set to input Utils_WaitNanoSecs 5000, 0, r22 ; wait for 5 usecs sec sbic OWI_PORTIN, OWI_PINNUM ; sample line rjmp OwiMaster_RecvByte_recv1 Utils_WaitNanoSecs 55000, 0, r22 clc ; shift-in ZERO rjmp OwiMaster_RecvByte_shiftIn OwiMaster_RecvByte_recv1: Utils_WaitNanoSecs 55000, 0, r22 sec OwiMaster_RecvByte_shiftIn: ror r17 Utils_WaitNanoSecs 5000, 0, r22 ; time between bits OwiMaster_RecvByte_loopEnd: dec r20 brne OwiMaster_RecvByte_loop mov r16, r17 sec ret OwiMaster_RecvByte_error: clc ret ; @end ; --------------------------------------------------------------------------- ; @routine owiWaitForDataState1ms ; ; @return CFLAG set if state reached, cleared otherwise ; @param r16 state to wait for (00 for low, 0xff for high) ; @clobbers r21, r22 owiWaitForDataState1ms: ldi r21, 10 owiWaitForDataState1ms_loop: in r22, OWI_PORTIN eor r22, r16 andi r22, (1<