Files
aqhomecontrol/avr/modules/owimaster/main.asm
2024-09-18 00:14:08 +02:00

177 lines
4.7 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 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
; if present slave pulls line low for 60 usecs (we check after 30 usecs)
Utils_WaitNanoSecs 30000, 0, r22
clr r16
sbic OWI_PORTIN, OWI_PINNUM
rjmp OwiMaster_Reset_done
dec r16
rcall owiWaitForDataState1ms ; wait for line pulled up
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
lsr r16 ; bit to send -> CARRY
brcs OwiMaster_SendByte_setHigh
OwiMaster_SendByte_setLow:
Utils_WaitNanoSecs 60000, 0, r22 ; set to low for 60 usecs ("0")
cbi OWI_DDR, OWI_PINNUM ; set to output
Utils_WaitNanoSecs 5000, 0, r22 ; set to low for 5 usecs ("1")
rjmp OwiMaster_SendByte_loopEnd
OwiMaster_SendByte_setHigh:
Utils_WaitNanoSecs 5000, 0, r22 ; set to low for 5 usecs ("1")
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