;
; Dallas TouchMemory routines
; (c) 1997 Pavel Korensky <pavelk@dator3.anet.cz> 
;
; Freely usable for non-commercional use. 
; Commercional use strictly prohibited
;
;


DS_PORT			equ	PORTA			; Dallas port
DS_BIT			equ	4			; Dallas bit


;
; Dallas TouchMemory commands - Touch Multikey specifically
;

READ_ROM		equ	0x33
SKIP_ROM		equ	0xCC
MATCH_ROM		equ	0x55
WRITE_SCR		equ	0x96
READ_SCR		equ	0x69
COPY_SCR		equ	0x3C
WRITE_PSW		equ	0x5A
WRITE_SUB		equ	0x99
READ_SUB		equ	0x66

FAM_MULTIKEY		equ	0x02




;*****************************************************************
;
; Some macros
;
;*****************************************************************

DSIN		macro					; Set Dallas as input
		bsf	STATUS, RP0
		bsf	TRISA,DS_BIT
		bcf	STATUS, RP0
		endm
		
DSOUT		macro					; Set Dallas as output - 1
		bsf	STATUS, RP0
		bcf	TRISA, DS_BIT
		bcf	STATUS, RP0
		bsf	DS_PORT, DS_BIT
		endm


;************************************************************
;
; Touch Memory routines
;
;************************************************************



;************************************************************
;
; Delay 67 us - For PRESENCE routine
;
;************************************************************

D67us:	
		movlw	6
		movwf	del4
D67l_4		movlw	1
		movwf	del3
D67l_3		movlw	1
		movwf	del2
D67l_2		movlw	5
		movwf	del1
D67l_1		decfsz	del1
		goto	D67l_1
		decfsz	del2
		goto	D67l_2
		decfsz	del3
		goto	D67l_3
		decfsz	del4
		goto	D67l_4
		retlw	0

;************************************************************
;
; Delay 498 us - For RESET pulse
;
;************************************************************

D498us:	
		movlw	1
		movwf	del4
D498l_4		movlw	1
		movwf	del3
D498l_3		movlw	0x4d
		movwf	del2
D498l_2		movlw	4
		movwf	del1
D498l_1		decfsz	del1
		goto	D498l_1
		decfsz	del2
		goto	D498l_2
		decfsz	del3
		goto	D498l_3
		decfsz	del4
		goto	D498l_4
		retlw	0

;************************************************************
;
; Delay 2 us - Recovery time etc.
;
;************************************************************

D2us:	
		nop
		retlw	0


;************************************************************
;
; Touch_Reset - Reset memory and check presence
;
; Return: 0 if memory not present, 1 if present, 3 if short circuit

;
;************************************************************

Touch_Reset	DSOUT				; Set DS for output
		bcf	DS_PORT, DS_BIT		; 0 to 1-wire
		call	D498us			; wait tRSTL
		bsf	DS_PORT, DS_BIT		; 1 to 1-wire
		DSIN				; Set DS for input
		call	D67us			; wait tPDH
		btfsc	DS_PORT, DS_BIT		; Presence pulse ?
		retlw	0			; Return 0 if not
		call	D498us			; Wait some time
		btfsc	DS_PORT, DS_BIT		; 1-wire back HI ?
		retlw	1			; return 1 if so
		retlw	2			; Probably short circuit

;*************************************************************
;
; Write_DS_Byte - write byte from W to 1-wire
;
;*************************************************************

Write_DS_Byte	DSOUT				; Set DS for output
		movwf	Temp1			; store W
		movlw	8
		movwf	Temp			; 8 bits
wdsb1:		bcf	DS_PORT, DS_BIT		; 0 to 1-wire
		call	D2us			; wait 2 usec
		rrf	Temp1,F			; rotate right
		skpnc				; if not carry, 0 to 1-wire
		bsf	DS_PORT, DS_BIT
		call	D67us			; wait 67 usec
		bsf	DS_PORT, DS_BIT		; 1 to 1-wire
		call	D2us			; wait tREC
		decfsz	Temp
		goto	wdsb1			; loop for 8 bits
		DSIN				; Set DS for input
		retlw	0		

;**************************************************************
;
; Read_DS_Byte - read byte from DS to W 
;
;**************************************************************

Read_DS_Byte	movlw	8
		movwf	Temp
		clrf	Temp1
rdsb1:		DSOUT				; set DS for output
		bcf	DS_PORT, DS_BIT		; Start pulse
		call	D2us			; wait
		DSIN
		nop
		nop				; wait a bit
		clrc				; clear carry
		btfsc	DS_PORT, DS_BIT		; bit is 0 ?
		setc				; set carry if not
		rrf	Temp1,F			; carry to Temp1
		call	D67us			; wait 67 usec
		decfsz	Temp			; cycle for 8 bits
		goto	rdsb1
		movf	Temp1,W			; byte to W
		return

;************************************************************************
;
; DS_CRC8 - 	Will calculate 8 bit CRC for DALLAS DS components
;
;		Input: 	Byte for CRC in W
;		Return: Byte in W, CRC in CRC8
;************************************************************************

DS_CRC8		movwf	del2
		movwf	Temp			; Save byte
		movlw	8			; 8 bits
		movwf	Temp1			; store counter
		movf	Temp,W			; byte to W
CRC8_L1		xorwf	CRC8,W			; xor
		movwf	del1			; temp store
		rrf	del1,W
		movf	CRC8,W			; fetch last CRC
		skpnc				; if not C, skip
		xorlw	0x18			; xor with fixed
		movwf	CRC8			; store new CRC
		rrf	CRC8,F			; update new CRC
		clrc				; clear carry
		rrf	Temp,F			; next bit
		movf	Temp,W
		decfsz	Temp1			; count bits
		goto	CRC8_L1			;
		movf	del2,W			; fetch original to W
		return

;*************************************************************************
;
; DS_CRC16 -	Will calculate 16bit CRC for DALLAS DS components
;
;		Input: 	Byte for CRC in W
;		Output:	Original byte in W, 
;			CRC16_HI and CRC16_LO new value of CRC16
;
;*************************************************************************

DS_CRC16	movwf	del1
		movwf	Temp			; store W
		movlw	8			; 8 bits
		movwf	Temp1
		movf	Temp,W			; fetch W
Crc_Get_Bit	rrf	Temp,F			; bit in C
		movf	Temp,W			; value to W
		skpnc
		goto	Crc_In_1
		btfss	CRC16_LO,0		; lowest bit set ?
		goto	Crc_Cont		; goto count with C=0
		setc
		goto	Crc_Cont		; goto count with C=1
Crc_In_1	btfsc	CRC16_LO,0		; lowest bit zero ?
		clrc				; if no, C=0 = complement
Crc_Cont	skpc
		goto	Crc_Shift		; if C=0 only shift
		btfsc	CRC16_HI,6		; complement 15th bit of CRC
		goto	Crc1
		bsf	CRC16_HI,6		; if clear, set
		goto	Crc2
Crc1		bcf	CRC16_HI,6		; if set, clear
Crc2		btfsc	CRC16_LO,1		; complement 2nd bit of CRC
		goto	Crc3
		bsf	CRC16_LO,1
		goto	Crc_Shift
Crc3		bcf	CRC16_LO,1
Crc_Shift	rrf	CRC16_HI,F		; 16bit rotate
		rrf	CRC16_LO,F
		movf	Temp,W
		decfsz	Temp1
		goto	Crc_Get_Bit
		movf	del1,W			; fetch the original byte
		return
		
		
		
;****************************************************************************
;
; Get_DS_Serial - Get Key serial number to buffer
;
; Argument - W=start of buffer
; Return - W=0x01 OK, W=0x02 bad button
;
;****************************************************************************
Get_DS_Serial
		movwf	FSR
		clrf	CRC8			; clear CRC8
		movlw	READ_ROM
		call	Write_DS_Byte		; Read ROM
		call	Read_DS_Byte		; Fam. code
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; Ser 1
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; Ser 2
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; Ser 3
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; ser 4
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; ser 5
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; ser 6
		call	DS_CRC8
		movwf	INDF
		incf	FSR
		call	Read_DS_Byte		; CRC
		call	DS_CRC8
		movf	CRC8,W			; CRC to W
		iorlw	0			; is 0 ?
		skpz
		retlw	2			; if not, error
		retlw	1			; else OK


