192 lines
5.3 KiB
NASM
192 lines
5.3 KiB
NASM
; ***************************************************************************
|
|
; 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<<OWI_PINNUM)
|
|
breq owiWaitForDataState1ms_stateReached
|
|
nop
|
|
nop
|
|
nop
|
|
dec r21
|
|
brne owiWaitForDataState1ms_loop
|
|
clc
|
|
ret
|
|
owiWaitForDataState1ms_stateReached:
|
|
sec
|
|
ret
|
|
; @end
|
|
|
|
|
|
|
|
OWIMASTER_END:
|
|
.equ MODULE_SIZE_OWIMASTER = OWIMASTER_END-OWIMASTER_BEGIN
|
|
|
|
|
|
|
|
|