;; Dallas DS1820 multidrop routines using timer 0 in mode 3 for MCS51

;; External power for DS1820 assumed

;; Clock is 11.0592 MHz -> one cycle is 1.0850694 us

;; Copyright 1999, Leon Kos, University of Ljubljana

;; TODO: Initial check routines for external power on each device

;; $Id: ds1820.asm,v 1.2 2003/09/13 15:31:57 leon Exp $

	NAME DS1820

	APD	BIT 0F8h	; P5.0 driving gate of the DMOS for 

	READ	BIT 0EFh	; P4.7 reading response from slaves

	
ds1820_routines	SEGMENT CODE		
T1_interrupt	SEGMENT CODE
ds1820rom	SEGMENT CODE
dowcrc		SEGMENT CODE
ds1820data	SEGMENT DATA
bitvar		SEGMENT BIT
	

	public	ds1820_init
	public	_ds1820_start
	public	touch_byte
	public	convert_time
	public	ds1820error
	public	scratchpad
	public	ds1820crc_ok
	public	errornum
        public  ds1820device
					
CSEG    AT      0001BH
	jmp    timer1

	RSEG  T1_interrupt

timer1:
	push    acc		; 2

	push    psw		; 2

	push	dpl		; 2

	push	dph		; 2

	jnb	bit_state, matchROM_loop
	
bit_loop:			; bit writing/reading loop

	clr	APD
	setb	bit_state	; enable this state

	mov	c, read_slot
	mov	a, touch_byte
	rrc	a
	mov	touch_byte, a
	djnz	bitcnt, touch_bit
	mov	bitcnt, #9
	clr	bit_state
	jmp	exit_t1
	
touch_bit:
	setb	APD		;  1T

	nop			;  1T

	nop
	nop
	nop			;  1T

	cpl	c		;  1T

	mov	APD, c		;  1T

	nop
	nop
	nop
	nop
	nop
	nop
	nop
	mov	c, READ
	mov	read_slot, c
	mov	TH0, #(0FFh - 30)
	pop	dph		; 2

	pop	dpl		; 2

        pop     psw		; 2

	pop     acc		; 2

	reti
	
matchROM_loop:
	jnb	matchROM_state, reset_state_loop
	mov	a, loop		; test the loop counter

	clr	C		; clear for one byte substraction

	subb	a, #8		; loop couner in incrementing

	jz	_rom_end	; substract to match zero at end

	mov	dptr, #rom_table; point to in CODE device table

	mov	a, ds1820device	; which device

	rl	a		; address 

	rl	a		; is multiple of

	rl	a		; 8 offset

	add	a, loop		; select byte from table

	movc	a, @a+dptr
	mov	touch_byte, a
	inc	loop
	jmp	bit_loop
_rom_end:
	clr	matchROM_state
	inc	state		
	jmp	state_loop
	
reset_state_loop:
	jnb	reset_state, state_loop
	mov	a, loop
	dec	a
	jz	_reset_end
	mov	loop, a
	add	a, #254
	jnz	_rst0
	clr	APD
_rst0:	jmp	exit_t1
	
_reset_end:
	clr	reset_state
	inc	state
	
state_loop:			; Main state machine loop

	mov	a, state	; must be in the middle

	mov	dptr, #jump_table; of the code

	movc	a, @a+dptr
	jmp	@a+dptr
	
jump_table:	
	db	reset0		- jump_table
	db	match_rom0	- jump_table
	db	convertT	- jump_table
	db	readbusy	- jump_table
	db	reset1		- jump_table
	db	match_rom1	- jump_table
	db	read_scratchpad	- jump_table
	db	temp_lsb	- jump_table
	db	temp_msb	- jump_table
	db	user_byte1	- jump_table
	db	user_byte2	- jump_table
	db	reserved1	- jump_table
	db	reserved2	- jump_table
	db	count_remain	- jump_table
	db	count_per_c	- jump_table
	db	crc		- jump_table
	db	stop		- jump_table
	
reset0:
	mov	loop, #4
	setb	reset_state
	mov	TH0, #(255-200)	; first half of the reset time

	setb	APD
	jmp	exit_t1
match_rom0:
	mov	touch_byte, #55h
	mov	loop, #0
	setb	matchROM_state
	jmp	bit_loop
convertT:
	mov	touch_byte, #44h
	inc	state
	mov	convert_time, #00h
	mov	convert_time + 1, #00h
	jmp	bit_loop
		
readbusy:	; check every 280us

	inc	convert_time + 1; 

	mov	a, convert_time + 1
	jnz	_noinc
	inc	convert_time
	mov	a, #12h		; 12*72ms=860ms overrun

	anl	a, convert_time
	jz	_noinc
	setb	ds1820error	; short circuit

	mov	errornum, #1	; to long zero resonse

	jmp	end_t1
_noinc:	mov	a, touch_byte
	mov	touch_byte, #0FFh
	inc	a
	jz	converted
	jmp	bit_loop
converted:
	clr	C
	inc	state		
reset1:
	mov	loop, #4
	setb	reset_state
	mov	TH0, #(255-200)	; first half of the reset time

	setb	APD
	jmp	exit_t1
match_rom1:
	mov	touch_byte, #55h
	mov	loop, #0
	setb	matchROM_state
	jmp	bit_loop
read_scratchpad:
	mov	touch_byte, #0BEh
	inc	state
	jmp	bit_loop
temp_lsb:			; larger but easy to fetch bytes

	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
temp_msb:
	mov	scratchpad, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop

user_byte1:			
	mov	scratchpad + 1, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
user_byte2:
	mov	scratchpad + 2, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
reserved1:
	mov	scratchpad + 3, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
reserved2:
	mov	scratchpad + 4, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
count_remain:
	mov	scratchpad + 5, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
count_per_c:
	mov	scratchpad + 6, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
crc:
	mov	scratchpad + 7, touch_byte
	mov	touch_byte, #0FFh
	inc	state
	jmp	bit_loop
stop:
	mov	scratchpad + 8, touch_byte
end_t1:	
	clr	ET1		; disable interrupt

	clr	TR1		; stop the timer

	mov	state, #0	; reset the machine state

	clr	APD		; power the line

exit_t1:			; exit from interrupt

	pop	dph		; 2

	pop	dpl		; 2

        pop     psw		; 2

	pop     acc		; 2

	reti    

	RSEG ds1820_routines
ds1820_init:			; initialize the variables

	mov	bitcnt, #9	; bit counter

	clr	APD		; power the devices on line

	setb	READ		; enable reading

	clr	matchROM_state	; not sending match ROM to ds1820

	clr	bit_state	; not in the bit delay state

	clr	reset_state	; not in the reset state

	mov	state, #0	; clear machine state

	mov	ds1820device,#0	; default is reading device0

	anl	TMOD, #0f0h	; timer 0

	orl	TMOD, #03h	; in mode 3

	setb	EA		; Enable interrupts

	ret

_ds1820_start:			; R7 has the device number to read

	mov	ds1820device,R7
	mov	TH0,#0FAh
	clr	ds1820error	; no error at beginning

	mov	errornum, #0
	setb	ET1
	setb	TR1
	ret     


	RSEG dowcrc
ds1820crc_ok:			; extern bit ds1820crc_ok(void);

	mov	loop, #9	; 8+1 byte CRC

	mov	ds1820crc, #0	; clear CRC register

	mov	dptr, #dowcrc_table
	mov	r0, #scratchpad

_crc:		
	mov	a, @r0		; scratchad value

	xrl	a, ds1820crc
	movc	a, @a+dptr
	mov	ds1820crc, a
	inc	r0
	djnz	loop, _crc
	jz	_ok
	clr	CY
	ret
_ok:	setb	CY
	ret
	
dowcrc_table:	DB	0, 94, 188, 226, 97, 63, 221, 131
		DB	194, 156, 126, 32, 163, 253, 31, 65
		DB	157, 195, 33, 127, 252, 162, 64, 30
		DB	95, 1, 227, 189, 62, 96, 130, 220
		DB	35, 125, 159, 193, 66, 28, 254, 160
		DB	225, 191, 93, 3, 128, 222, 60, 98
		DB	190, 224, 2, 92, 223, 129, 99, 61 
		DB	124, 34, 192, 158, 29, 67, 161, 255
		DB	70, 24, 250, 164, 39, 121, 155, 197 
		DB	132, 218, 56, 102, 229, 187, 89, 7
		DB	219, 133, 103, 57, 186, 228, 6, 88 
		DB	25, 71, 165, 251, 120, 38, 196, 154
		DB	101, 59, 217, 135, 4, 90, 184, 230 
		DB	167, 249, 27, 69, 198, 152, 122, 36
		DB	248, 166, 68, 26, 153, 199, 37, 123 
		DB	58, 100, 134, 216, 91, 5, 231, 185
		DB	140, 210, 48, 110, 237, 179, 81, 15 
		DB	78, 16, 242, 172, 47, 113, 147, 205
		DB	17, 79, 173, 243, 112, 46, 204, 146 
		DB	211, 141, 111, 49, 178, 236, 14, 80
		DB	175, 241, 19, 77, 206, 144, 114, 44 
		DB	109, 51, 209, 143, 12, 82, 176, 238
		DB	50, 108, 142, 208, 83, 13, 239, 177 
		DB	240, 174, 76, 18, 145, 207, 45, 115
		DB	202, 148, 118, 40, 171, 245, 23, 73 
		DB	8, 86, 180, 234, 105, 55, 213, 139
		DB	87, 9, 235, 181, 54, 104, 138, 212 
		DB	149, 203, 41, 119, 244, 170, 72, 22
		DB	233, 183, 85, 11, 136, 214, 52, 106 
		DB	43, 117, 151, 201, 74, 20, 246, 168
		DB	116, 42, 200, 150, 21, 75, 169, 247 
		DB	182, 232, 10, 84, 215, 137, 107, 53
		
alternate_dowcrc:		; slower and thus not used

	mov	ds1820crc, #0
	mov	loop, #8	; 8 bytes

	mov	r0, #scratchpad

_dcrc:	mov	a, @r0
	call	do_crc
	inc	r0
	djnz	loop, _dcrc
	ret
	
do_crc:	push	acc
	push	b
	push	acc
	mov	b, #8
crc_loop:
	xrl	a, ds1820crc
	rrc	a
	mov	a, ds1820crc
	jnc	zero
	xrl	a, #18h
zero:	rrc	a
	mov	ds1820crc, a
	pop	acc
	rr	a
	push	acc
	djnz	b, crc_loop
	pop	acc
	pop	b
	pop	acc
	ret	
	
	RSEG ds1820data
bitcnt:		ds	1	; bit couter

touch_byte:	ds	1	; touch byte

scratchpad:	ds	9	; DS1820 scratchpad

convert_time:	ds	2	; time required for conversion

state:		ds	1	; machine state

loop:		ds	1	; shared byte for loops

errornum:	ds	1	; error number

ds1820device:	ds	1	; which device number 0,1,...

ds1820crc:	ds	1	; DOW 8 bit CRC value

		
	RSEG bitvar
read_slot:	DBIT	1	; read bit from ds1820

bit_state:	DBIT	1	; delaying one bit state

matchROM_state:	DBIT	1	; sending MATCH ROM state

reset_state:	DBIT	1	; resetting the bus state

ds1820error:	DBIT	1	; error getting temperature


	
	RSEG ds1820rom		
rom_table:	; avalable devices on the 1-wire net


device0:	DB	10h, 09Ah, 4Bh, 09h, 00h, 00h, 00h, 08Fh
device1:	DB	10h, 088h, 3Dh, 0Ch, 00h, 00h, 00h, 0CAh
device2:	DB	10h, 05Bh, 49h, 09h, 00h, 00h, 00h, 0A4h	
device3:	DB	10h, 022h, 49h, 09h, 00h, 00h, 00h, 0AAh
device4:	DB	10h, 0DAh, 4Ah, 09h, 00h, 00h, 00h, 037h
device5:	DB	10h, 099h, 48h, 09h, 00h, 00h, 00h, 098h
device6:	DB	10h, 021h, 47h, 09h, 00h, 00h, 00h, 051h
device7:	DB	10h, 0EEh, 47h, 09h, 00h, 00h, 00h, 0EAh
device8:	DB	10h, 06Eh, 47h, 09h, 00h, 00h, 00h, 000h
device9:	DB	10h, 0D3h, 49h, 09h, 00h, 00h, 00h, 0EFh
device10:	DB	10h, 09Ah, 47h, 09h, 00h, 00h, 00h, 0AEh
device11:	DB	10h, 0B1h, 4Ah, 09h, 00h, 00h, 00h, 00Ch
device12:	DB	10h, 08Bh, 4Ah, 09h, 00h, 00h, 00h, 02Eh
device13:	DB	10h, 03Ch, 4Bh, 09h, 00h, 00h, 00h, 061h
device14:	DB	10h, 074h, 49h, 09h, 00h, 00h, 00h, 036h
device15:	DB	10h, 024h, 48h, 09h, 00h, 00h, 00h, 0D5h
device16:	DB	10h, 057h, 49h, 09h, 00h, 00h, 00h, 0D9h	
device17:	DB	10h, 050h, 04h, 0B0h,90h, 00h, 00h, 0DFh


END