;  ------ DS1990A program simulator ------
;  ------ Processor  AT89C2051 24PC ------
;  ------ Clock 12 MHZ              ------

#INCLUDE "LIBREG.ASM"	;8051 SFR set

#DEFINE LO(XXX) XXX & 0FFH
#DEFINE HI(XXX) (XXX >> 8) & 0FFH

;  ------ Constantes ------

STACK	.EQU 050H		;stack location
R_DEL	.EQU 10000H-300	;reset delay (300uS min)

;  ------ Bit Addressing Memory ------

RXF	.EQU M_20H.1	;RX flag

;  ------ Internal Memory ------

FAM_CODE	.EQU 030H		;DS1990 family code (01H)
SER_NUM1	.EQU 031H		;DS1990 serial number, byte 1
SER_NUM2	.EQU 032H		;DS1990 serial number, byte 2
SER_NUM3	.EQU 033H		;DS1990 serial number, byte 3
SER_NUM4	.EQU 034H		;DS1990 serial number, byte 4
SER_NUM5	.EQU 035H		;DS1990 serial number, byte 5
SER_NUM6	.EQU 036H		;DS1990 serial number, byte 6
CRC_BYTE	.EQU 037H		;DS1990 CRC byte

TEMP	.EQU 038H		;CRC temporary value

;  ------ Ports Set ------

DATA	.EQU INT0		;serial port data line

;  ------ Vectors Area ------

	.ORG 0000H	;reset vector
	AJMP INIT		;program init

	.ORG 000BH	;INT TIMER 0 vector
	AJMP TIMER	;jump to the timer int. holder

	.ORG 0010H
SN	.DB 000H,000H,002H,0D6H,0B4H,01FH ;serial number
FC	.DB 001H			    ;family code (001H - DS1990A)

;  ------ Main Program ------

INIT:	MOV SP,#STACK	;stack init
	CLR TR0          	;timer 0 stop
	CLR TR1          	;timer 1 stop
	MOV TMOD,#00010001B	;timer 0 and 1 init
	CLR PT0          	;timer 0 int low priority
	SETB ET0		;timer 0 int enable
	SETB PX0 		;high  INT0 priority
	SETB IT0 		;fall  INT0 activating
	SETB EA

;Copy 7 bytes RAM <- ROM
;from SN and FC
;to   SER_NUM6 .. SER_NUM1, FAM_CODE

	MOV DPTR,#SN	;source pointer
	MOV R0,#SER_NUM6	;destination pointer
	MOV R1,#7		;bytes number

DO_COPY:  CLR A
	MOVC A,@A+DPTR
	MOV @R0,A
	INC DPTR
	DEC R0
	DJNZ R1,DO_COPY

;Calculate CRC

	MOV TEMP,#0	;CRC init
	MOV R0,#FAM_CODE
	MOV R1,#7
DO_CRC:	MOV A,@R0
	ACALL DOW_CRC
	INC R0
	DJNZ R1,DO_CRC

	MOV CRC_BYTE,TEMP	;save CRC

	AJMP TERM		;go to simulate Touch Memory

;  The assembly language procedure DOW_CRC given below
;  calculates the cumulative CRC of all the bytes passed
;  to it in the accumulator. Before it is used to calculate
;  the CRC of a data stream, it should be initialized by
;  setting the variable TEMP to zero. Each byte of the data
;  is then placed in the accumulator and DOW_CRC is called
;  to update the CRC. After all the data has been passed
;  to DOW_CRC, the variable TEMP will contain the result.

DOW_CRC:	PUSH ACC         	;Save the Accumulator.
	PUSH B           	;Save the B register.
	PUSH ACC         	;Save bits to be shifted.
	MOV  B,#8        	;Set to shift eight bits.
CRC_LOOP:	XRL  A,TEMP      	;Calculate DQIN xor CRCT0.
	RRC  A           	;Move it to the carry.
	MOV  A,TEMP      	;Get the last CRC value.
	JNC  ZERO        	;Skip if DQIN xor CRCT0 = 0.
	XRL  A,#18H      	;Update the CRC value.
ZERO:	RRC  A           	;Position the new CRC.
	MOV  TEMP,A      	;Store the new CRC.
	POP  ACC         	;Get the remaining bits.
	RR   A           	;Position next bit in LSB.
	PUSH ACC         	;Save the remaining bits.
	DJNZ B,CRC_LOOP  	;Repeat for eight bits.
	POP  ACC         	;Clean up the stack.
	POP  B           	;Restore the B register.
	POP  ACC         	;Restore the Accumulator.
	RET              	;Return.

;  Touch Memory Simulation Part:
;  If RX code is 33H or 0FH then TX byffer.
;  The code is timed for a 12 MHz crystal.

TERM:	CLR TR0
	JB DATA,$
	MOV TH0,#HI(R_DEL)
	MOV TL0,#LO(R_DEL)
	SETB TR0
WAIT:	JNB DATA,$
	SJMP TERM

RES:      JNB DATA,$

	MOV R3,#14
	DJNZ R3,$		;delay 30 uS
	CLR DATA		;presence pulse begin

	MOV R3,#58
	DJNZ R3,$		;delay 120 uS
	SETB DATA		;presence pulse end

	MOV R0,#FAM_CODE-1	;pointer load
	MOV R1,#9		;load number of bytes (1 RX + 8 TX)
	MOV R2,#8		;load number of bits
	SETB RXF		;set RX flag
	MOV A,#0FFH	;perform RX
	RRC A		;C <- first TX bit
	CLR IE0		;clear interrupt flag

;1-Wire RX-TX Loop:

LOOPH:	JNB IE0,$		;wait for interrupt flag

	MOV DATA,C	;DATA <- C
	MOV TH0,#HI(R_DEL)
	MOV TL0,#LO(R_DEL)
	SETB TR0		;start timer 0 (reset timeout)
	MOV R3,#9
	DJNZ R3,$		;delay
	MOV C,DATA	;receive data bit
	SETB DATA		;DATA <- 1 (30uS is over)
	RRC A		;save received bit in ACC

	CLR IE0		;clear interrupt flag
	DJNZ R2,LOOP	;advance bit counter
	JNB RXF,NEXT	;jump if TX cycle

	CLR RXF
	CJNE A,#033H,MISM	;RX complete, check command code
	SJMP NEXT
MISM:	CJNE A,#00FH,TERM

NEXT:	INC R0		;advance pointer
	MOV R2,#8		;bits counter reload
	MOV A,@R0
	RRC A
	DJNZ R1,LOOP
	SJMP TERM

LOOP:     JNB DATA,$	;wait for DATA = 1
	CLR TR0
	SJMP LOOPH

;TIMER0 Interrupt Holder:
;Timer terminates process if reset pulse detected

TIMER:	CLR TR0		;timer 0 stop
	MOV SP,#STACK
	MOV A,#LO(RES)
	PUSH ACC
	MOV A,#HI(RES)
	PUSH ACC
	RETI		;return to RES

	.END
