;*****************************************************************************
; 	All rights reserved by Dipl.-Ing (FH) Andreas Hoeger
;	Ditzenbrunner Str. 64, 71254 Ditzingen, Germany
;	Telefon: (+497156)490980	Telefax: (+497156)490981
;	E-Mail: ingbuero@andreas-hoeger.de
;*****************************************************************************
;
;       8051- Programm fuer ATMEL Flash- Mikrocontroller AT89S53
;	
;	Teilprogramm für XSTG, wird durch INCLUDE eingebunden
;
;       Autor: Andreas Hoeger
;       Datum: 26.08.2002		
;
;	Aenderungen:
;	07_09_02: adapted for ZSTG from MSTG 
;	27_09_02: added FIELDCONVERT
;	03_10_02: interrupts disabled during 1-wire datatransfer
;
;*****************************************************************************
;
; The following 8051 code uses a bi-directional port pin (specified by
; ONE_WIRE) for 1-wire I/O. 
;
;*****************************************************************************

READ_DEVICE_ID:	; !! can only be used with one single device on bus
		; otherwise SEARCH ROM is necessary
		; The ID is put on CAN
		
		; use this function to find out the device IDs on new boards
		; and write the result in DSEG_EQU.asm

	;****** transmit reset pulse and wait for presence pulse

	call 	RESETPULSE

	;****** search for ID of device on bus
	;       use READ ROM command (33h)
	; 	- 08 bit family code (20h) 	at the LSBs
	;	- 48 bit serial number
	;	- 08 bit CRC			at the MSBs

	mov	ACC,#READROM		; search for device on bus
	call	SENDBYTE		; ROM command 33h
	
	call	DATA_IN			; get family code
	mov	CAN_D0,ACC
	call	DATA_IN			; get serial number
	mov	CAN_D1,ACC
	call	DATA_IN			; get serial number
	mov	CAN_D2,ACC
	call	DATA_IN			; get serial number
	mov	CAN_D3,ACC
	call	DATA_IN			; get serial number
	mov	CAN_D4,ACC
	call	DATA_IN			; get serial number
	mov	CAN_D5,ACC
	call	DATA_IN			; get serial number
	mov	CAN_D6,ACC
	call	DATA_IN			; get CRC code
	mov	CAN_D7,ACC

	;****** put first ID on CAN for debugging
	;****** CAN- Botschaftsausgabe 527

	mov	CAN_I1,#0A4H		; Botschaft definieren
	mov	CAN_I2,#0E8H		; 527h senden
					
	call	can_tx

	;****** transmit reset pulse and wait for presence pulse

	call 	RESETPULSE

	ret

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

ONEWIRE_INIT:

	;****** transmit reset pulse and wait for presence pulse

	call	RESETPULSE

	;****** address first device on bus (ADC temperature)

	call	ADDR_DEVICE

	;****** write configuration data of first device
	; 	config data
	;	reset "power on bit" of first device
	;	write 40h --> address 1Ch because VCC powered 

	; write config data for all channels, begin at adr. 08

	mov	ACC,#WRITEMEMORY	; command 55h
	call	SENDBYTE
	mov	ACC,#08h		; adress low
	call	SENDBYTE
	mov	ACC,#00h		; address high
	call	SENDBYTE

	mov	ACC,#DEV1_P1_A_08	; data
	call	SENDBYTE

	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy 8 bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 
	mov	A,#DEV1_P1_A_09	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy 9 bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 

	mov	A,#DEV1_P1_B_0A	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy A bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 

	mov	A,#DEV1_P1_B_0B	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy B bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 

	mov	A,#DEV1_P1_C_0C	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy C bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 

	mov	A,#DEV1_P1_C_0D	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy D bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 

	mov	A,#DEV1_P1_D_0E	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy E bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 

	mov	A,#DEV1_P1_D_0F	; data
	call	SENDBYTE
	; read back 16 bit CRC to confirm
	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away
	; read back memory copy F bit to confirm data
	call	DATA_IN			; 
	;mov	...			; 
 
	;****** transmit reset pulse at the end

	call	RESETPULSE

	RET

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

ADDR_DEVICE:	; to be called after resetpulse to send 
		; MATCH ROM command of device 1 and address of device 1

		; DEVICE 1 = VOLTAMP		

		; TX ROM command "MATCH ROM"

		; DCF77_Interrupts blocked because of 1-wire timing
		
		; --> interrupts globally disabled during this function


	mov	IE,#02H			; global Interrupt disable

	mov	ACC,#MATCHROM		; command 55h
	call	SENDBYTE

	mov	ACC,#DEV_ID_0		; ID LSBs
	call	SENDBYTE
	mov	ACC,#DEV_ID_1		; ID
	call	SENDBYTE
	mov	ACC,#DEV_ID_2		; ID
	call	SENDBYTE
	mov	ACC,#DEV_ID_3		; ID
	call	SENDBYTE
	mov	ACC,#DEV_ID_4		; ID
	call	SENDBYTE
	mov	ACC,#DEV_ID_5		; ID
	call	SENDBYTE
	mov	ACC,#DEV_ID_6		; ID
	call	SENDBYTE
	mov	ACC,#DEV_ID_7		; ID MSBs
	call	SENDBYTE
	
	mov	IE,#82H			; global Interrupt enable again

	; go back and be ready for memory functions

	ret

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

ADC_VOLTAMP:

	; --> interrupts partially disabled during this function
	;     RESETPULSE and ADDR_DEVICE also disable interrupts

	;****** transmit reset pulse and wait for presence pulse

	call	RESETPULSE

	;****** address device on bus

	call	ADDR_DEVICE

	;****** transmit CONVERT command and parameters
	;	- input select
	;	- read out control


	mov	IE,#02H			; global Interrupt disable


	mov	ACC,#CONVERT		; command 3Ch
	call	SENDBYTE
	mov	ACC,#0Ch		; input select mask
	call	SENDBYTE		; only channel C,D
	mov	ACC,#55h		; read out control
	call	SENDBYTE		; preset all channels to zero

	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away


	mov	IE,#82H			; global Interrupt enable again

	;****** wait until conversion finished (some millisek)

	call	zehn_ms

	;****** transmit reset pulse and wait for presence pulse

	call	RESETPULSE

	;****** address device on bus

	call	ADDR_DEVICE

	;****** transmit READ MEMORY command and parameters
	;	- address low
	;	- address high
	;       channel C and D used --> start at address 04h
	;			     --> get four bytes


	mov	IE,#02H			; global Interrupt disable


	mov	ACC,#READMEMORY		; command AAh
	call	SENDBYTE
	mov	ACC,#04h		; adress low
	call	SENDBYTE
	mov	ACC,#00h		; address high
	call	SENDBYTE


	call	DATA_IN			; get channel C low
	;mov	...			; throw away
	call	DATA_IN			; get channel C high
	mov	ADC_AMP,ACC

	call	DATA_IN			; get channel D low
	;mov	...			; throw away
	call	DATA_IN			; get channel D high
	mov	ADC_VOLT,ACC

	call	DATA_IN			; get CRC first 8 bit
	;mov	...			; throw away
	call	DATA_IN			; get CRC second 8 bit
	mov	A,#00H			; throw away


	mov	IE,#82H			; global Interrupt enable again

	;****** transmit reset pulse and wait for presence pulse

	call	RESETPULSE

	RET

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

ADC_FIELDCONVERT:	

	;****** takes the ADC results
	;	- ADC_VOLT
	;       and converts the data according to the "Kennlinienfeld"
	; 	input and output in same variable

	;****** ADC_VOLT

	mov	A,ADC_VOLT	; lade den urspruenglichen Messwert
				; und nehme ihn als index (Offset)
				; im Kennlinienfeld
	mov	DPTR,#U_00	; lade Beginn des Kennlinienfeldes
				; mit Index 00h (von 00h ... FFh)
	movc	A,@A+DPTR	; lade das korrigierte Byte in Akku
	mov	ADC_VOLT,A	; speichere zurueck

	RET	

;*****************************************************************************
;         Procedure Resetpulse
;
;         This procedure transmits the Reset signal to the ADC
;         and watches for a presence pulse. On return,
;         the Carry bit is set if a presence pulse was detected,
;         otherwise the Carry is cleared.
;
;	  --> interrupts globally disabled during this function
;
;
RESETPULSE:

	  mov	    IE,#02H		  ; global Interrupt disable


          PUSH      B                     ;       Save the B register.
          PUSH      ACC                   ;       Save the accumulator.
          MOV       A,        #4          ;       Load outer loop variable.
          CLR       ONEWIRE               ;       Start the reset pulse.
;---- min 640 cycles LOW bei 16MHz
          MOV       B,        #180        ;   2.  Set time interval.
          DJNZ      B,        $           ; 360.  Wait with Data low.
          MOV       B,        #180        ;   2.  Set time interval.
          DJNZ      B,        $           ; 360.  Wait with Data low.
;----
          SETB      ONEWIRE               ;   1.  Release Data line.
          MOV       B,        #6          ;   2.  Set time interval.
          CLR       C                     ;   1.  Clear presence flag.
WAITLOW:
          JB        ONEWIRE, WH           ;       Exit loop if line high.
          DJNZ      B,        WAITLOW     ;       Hang around if line is low.
          DJNZ      ACC,      WAITLOW     ; 
          SJMP      SHORT                 ;       Line could not go high.
WH:
          MOV       B,        #160        ;       Delay for presence detect.
HL:
          ORL       C,        /ONEWIRE    ; 320.  Catch presence pulse.
          DJNZ      B,        HL          ; 320.  Wait with Data high.
SHORT:
          POP       ACC                   ;       Restore accumulator.
          POP       B                     ;       Restore B register.

	  mov	    IE,#82H		  ; global Interrupt enable again


          RET                             ;       Return.

;*****************************************************************************
;         Procedure DATA_IN: returns byte from 1-wire device in ACC
;	  Procedure SENDBYTE: sends byte in ACC to 1-wire device
;         Timing for 16MHz
;
;BIT_IO:
;          RRC       A                     ; Get bit to send in carry.
;          CALL      TOUCHBIT              ; Send bit.
;          RLC       A                     ; Collect returned bit in ACC.
;          RET                             ; Return to caller.

DATA_IN:
          MOV       A,        #0FFH       ;       Initialize for input.
SENDBYTE:
          PUSH      B                     ;       Save the B register.
          MOV       B,        #8          ;       Setup for 8 bits.
BIT_LOOP:
          RRC       A                     ;   1.  Get bit in carry.
          CALL      TOUCHBIT              ;   2.  Send bit.
          DJNZ      B,        BIT_LOOP    ;   2.  Get next bit.
          RRC       A                     ;       Get final bit in ACC.
          POP       B                     ;       Restore B register.
          RET                             ;       Return to caller.
TOUCHBIT:
          CLR       ONEWIRE               ;   1.  Start the time slot.
          NOP                             ;   1.  Delay to make sure
          NOP                             ;   1.    that the 1-wire device
          NOP                             ;   1.      sees a low for at
          NOP                             ;   1.        least 1 microsecond.
	  NOP				; added for 16 MHz
	  NOP				; added for 16 MHz
          MOV       ONEWIRE, C            ;   2.  Send out the data bit.
          NOP                             ;   1.  Delay to give the
          NOP                             ;   1.    data returned from
          NOP                             ;   1.      the 1-wire device
          NOP                             ;   1.        time to settle
          NOP                             ;   1.          before reading
          NOP                             ;   1.            the bit.
	  NOP				; added for 16 MHz
	  NOP				; added for 16 MHz
          MOV       C,        ONEWIRE     ;   1.  Sample input data bit.
          PUSH      B                     ;   2.  Save B register.
          MOV       B,        #18H        ;   2.  Delay until the end
          DJNZ      B,        $           ;   54.   of the time slot.
          POP       B                     ;       Restore B register.
          SETB      ONEWIRE               ;       Terminate time slot.
          RET                             ;       Return to caller.

;*****************************************************************************
; ENDE DES QUELLTEXTES
;*****************************************************************************

