;*****************************************************************************
; 	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, wird durch INCLUDE eingebunden
;
;       Autor: Andreas Hoeger
;       Datum: 11.02.2002		
;
;	Aenderungen:
;	11_02_02: Initial version from 1.18
;	12_02_02: LED Hintergrundbeleuchtung einschalten ab Init
;	03_03_02: Mailbox initialisieren mit 00H statt 0FFH
;	07_05_02: Initialisierung neuer Mailboxen eingefuegt
;	16_07_02: Bugfix EEPROM konsistency check routine
;	19_07_02: Bugfix EEPROM correction routine, jmp was missing
;	09_09_02: CAN Mailbox Nummer 7 initialisieren
;	27_09_02: CAN Mailbox Nummer 8 initialisieren
;
;*****************************************************************************
	
ini_system:
	
	mov     R0,#00H			; Register loeschen
        mov     R1,#00H
        mov     R2,#00H                  
        mov     R3,#00H                 
        mov     R4,#00H
        mov     R5,#00H                 
        mov     R6,#00H 
	mov	R7,#00H                

	;****** Sonstige Einstellungen am ATMEL- Controller

	mov	8EH,#01H		; Bit 0 von SFR 8Eh setzen, damit
					; ALE- Pin nicht auf 1/6 osz-freq. 
					; schwingt

	;****** Parallelports initialisieren (1=Eingang 0=Ausgang) ***********

        mov	P0,#00H		; Port 0 an CAN- Controller
				; P0.0 bis P0.7 = AD- Bus
				; alle OUTPUT = 0 (Grundzustand)
				
	mov     P1,#04H		; Port 1 digital inputs / SPI
				; P1.0 = SH/LD 	= Bit DIG_SH 	= OUTPUT = 0
				; P1.1 = CLK   	= Bit DIG_CLK	= OUTPUT = 0
				; P1.2 = QH(IC6,2)= Bit DIG_QH6_2 = INPUT  = 1
				; P1.3 = DS(IC16) = Bit DIG_DS	= OUTPUT = 0
				; P1.4 = SS/	= Bit SPI_SS	= OUTPUT = 0
				; P1.5 = MOSI	= Bit MOSI	= OUTPUT = 0
				; P1.6 = MISO   = Bit MISO	= OUTPUT = 0
				; P1.7 = SCK	= Bit SPI_CLK	= OUTPUT = 0
	
	mov	P2,#00H		; Port 2 LCD und LED
				; P2.0 = DB4 	= Bit DB4 	= OUTPUT = 0
				; P2.1 = DB5   	= Bit DB5	= OUTPUT = 0
				; P2.2 = DB6	= Bit DB6	= OUTPUT = 0
				; P2.3 = DB7	= Bit DB7	= OUTPUT = 0
				; P2.4 = E	= Bit LCD_E	= OUTPUT = 0
				; P2.5 = R/W	= Bit LCD_RW	= OUTPUT = 0
				; P2.6 = RS     = Bit LCD_RS	= OUTPUT = 0
				; P2.7 = LED	= Bit LED	= OUTPUT = 0

        mov     P3,#04H		; Port 3 CAN-Steuerltg. und I2C-Bus
				; P3.0 = SDA 	= Bit SDA 	= OUTPUT = 0
				; P3.1 = SCL   	= Bit SCL	= OUTPUT = 0
				; P3.2 = INT/	= Bit ---	= INPUT  = 1
				; P3.3 = CS/EEPOT = Bit EEPOT_CS = OUTPUT = 0
				; P3.4 = ALE	= Bit CAN_ALE	= OUTPUT = 0
				; P3.5 = CS/	= Bit CAN_CS	= OUTPUT = 0
				; P3.6 = RD/    = Bit CAN_RD	= OUTPUT = 0
				; P3.7 = WR/	= Bit CAN_WR	= OUTPUT = 0
	
	;****** Init EEPOT ***************************************************
	; Achtung! vor LCD durchführen und damit CS/ auf high setzen
	; sonst geht die LCD- Initialisierung auch aufs EEPOT da selber Bus

	setb	EEPOT_CS	; Grundzustand CS/ des EEPOT = high

	;****** Init LCD- Modul **********************************************

	call	ini_lcd	

	clr	LED		; LCD Hintergrundbeleuchtung aus
;	setb	LED		; LCD Hintergrundbeleuchtung einschalten

	;****** TEXT: POWER-ON SELF CHECK	... RUNNING

	mov	A,#LCD_LINE1
	call	instr_out
	mov	DPTR,#MSG002		
	call	print_lcd

	mov	A,#LCD_LINE2
	call	instr_out
	mov	DPTR,#MSG003		 
	call	print_lcd

	mov	A,#LCD_LINE3
	call	instr_out
	mov	DPTR,#MSG000			; loeschen		 
	call	print_lcd

	mov	A,#LCD_LINE4			; loeschen
	call	instr_out
	mov	DPTR,#MSG000		 
	call	print_lcd

	;call	sek_1
	call	sek_1
		
	;****** Init I2C- Bus ************************************************
	
	setb	SDA		; Grundzustand I2C-Bus = HIGH
	setb	SCL		; Grundzustand I2C-Bus = HIGH

	;****** Init DS 1621 *************************************************
	
	call	ini_ds1621

	;****** Uebertragen der gueltigen EEPROM Page ************************
	
	; Diese Angabe befindet sich in jedem Fall, also unabhaengig davon 
	; welche Page gerade gueltig ist, in der Page 0

	mov	I2C_ADR_H,#00H			 ; Page 0
	mov	I2C_ADR_L,#EE_VALID_PAGE	 ; Adresse des Nutzbytes
	mov	I2C_ID,#EE_ID
	call	read_random_internal		 ; Ergebnis in I2C_DATA

	; Nur das LSB ist gueltig und zeigt die momentan gueltige Seite an;
	; Diese Info muss in Bit06 uebertragen werden.

	mov	A,I2C_DATA
	rrc	A
	jc	page_one_valid

	clr	BIT06
	jmp	page_end

page_one_valid:

	setb	BIT06		; Seite 1 enthaelt momentan den gueltigen 
				; Datensatz
page_end:
	
	;****** Vergleich der beiden EEPROM Pages ****************************

	; Vergleich aller Bytes in den EEPROM pages, evtl. korruptes Byte in
	; der momentan ungueltigen Seite durch das in der gueltigen ersetzen
	
	; Ausnahme: Byte FFh braucht nicht gespiegelt zu werden.

	mov	I2C_ID,#EE_ID
	mov	I2C_ADR_L,#00H	 		; Adresse des Nutzbytes

	mov	CNT2,#EE_DOUBLE_DATA_LENGTH	; Laenge der doppelt 
						; vorhandenen Datenpage
						; laden fuer Counter
testloop:

	mov	I2C_ADR_H,#00H			; Page 0
	call	read_random_internal		; Ergebnis in I2C_DATA
	push	I2C_DATA		; sichern bis zum Vergleich

	mov	I2C_ADR_H,#01H			; Page 1
	call	read_random_internal		; Ergebnis in I2C_DATA
	pop	ACC			; I2C_DATA von Page 0 in A laden

	inc	I2C_ADR_L
	cjne	A,I2C_DATA,correct_byte
	djnz	CNT2,testloop

	jmp	ee_compare_end

correct_byte:

	; gueltige Seite feststellen durch lesen von BIT06
	jb	BIT06,pageone_valid

pagezero_valid:
	; Seite 0 gueltig, also gueltige Daten im Akku
	; diese nach Page 1 kopieren
	
	dec	I2C_ADR_L		; war schon hochgezaehlt !!
	mov	I2C_ADR_H,#01H		; Page 1
	mov	I2C_DATA,A		; aktueller Zelleninhalt in A
	call	write_byte_internal	; aufrufen ohne Pageverwaltung 
					; sondern mit festem Pageeintrag
	inc	I2C_ADR_L		; wieder hochzaehlen
	jmp	correct_byte_end

pageone_valid:
	; Seite 1 gueltig, also gueltige Daten in I2C_DATA
	; diese nach Page 0 kopieren

	dec	I2C_ADR_L		; war schon hochgezaehlt !!
	mov	I2C_ADR_H,#00H		; Page 0
	;mov	I2C_DATA,A		; aktueller Zelleninhalt schon drin
	call	write_byte_internal	; aufrufen ohne Pageverwaltung 
					; sondern mit festem Pageeintrag
	inc	I2C_ADR_L		; wieder hochzaehlen

correct_byte_end:
	
	mov	ERROR,#EW_EEPROM_COMPARE
	call	errorcode_out		; Fehlermeldung generieren

	djnz	CNT2,testloop

ee_compare_end:

	;****** Init Schieberegister (digital Input) *************************
	
	clr	DIG_CLK		; Grundzustand CLK = LOW
	setb	DIG_SH		; Grundzustand SH/LD = HIGH
	clr	DIG_DS		; Grundzustand DS = LOW

	;****** Init CAN Controller ******************************************
	
	setb	CAN_WR		; Grundzustand WR/ = HIGH
	setb	CAN_RD		; Grundzustand RD/ = HIGH
	setb	CAN_CS		; Grundzustand CS/ = HIGH
	clr	CAN_ALE		; Grundzustand ALE = LOW

	call	ein_ms		; Einschwingzeit
	call	ini_can_basic   ; Initialisierung CAN-Controller Register

	;****** Init CAN Mailboxen *******************************************

	; Mailbox- Layout am Beispiel Box3:	

	; BOX3_C: 	CAN Mailbox 3	Controlbyte
	; BOX3_IH: 	CAN High Byte Botschaftsnumer [HEX]
	; BOX3_IL: 	CAN Low Byte Botschaftsnumer [HEX]
	; BOX3_0:	CAN Botschaft Mailbox 3 	Datenbyte 0
	; BOX3_1:	CAN Botschaft Mailbox 3 	Datenbyte 1
	; BOX3_2:	CAN Botschaft Mailbox 3 	Datenbyte 2
	; BOX3_3:	CAN Botschaft Mailbox 3 	Datenbyte 3
	; BOX3_4:	CAN Botschaft Mailbox 3 	Datenbyte 4
	; BOX3_5:	CAN Botschaft Mailbox 3 	Datenbyte 5
	; BOX3_6:	CAN Botschaft Mailbox 3 	Datenbyte 6
	; BOX3_7:	CAN Botschaft Mailbox 3 	Datenbyte 7

	; Box 0 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX0_C		; indirect adressing
initb0:
	mov	@R0,#0FFH		
	inc	R0
	djnz	CNT0,initb0

	; Box 1 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX1_C		; indirect adressing
initb1:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb1

	; Box 2 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX2_C		; indirect adressing
initb2:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb2

	; Box 3 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX3_C		; indirect adressing
initb3:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb3

	; Box 4 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX4_C		; indirect adressing
initb4:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb4

	; Box 5 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX5_C		; indirect adressing
initb5:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb5

	; Box 6 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX6_C		; indirect adressing
initb6:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb6

	; Box 7 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX7_C		; indirect adressing
initb7:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb7

	; Box 8 initialisieren:

	mov	CNT0,#0BH
	mov	R0,#BOX8_C		; indirect adressing
initb8:
	mov	@R0,#00H		
	inc	R0
	djnz	CNT0,initb8



	;****** TEXT: POWER-ON SELF CHECK	... PASSED

	mov	A,#LCD_LINE1		
	call	instr_out
	mov	DPTR,#MSG002		 
	call	print_lcd

	mov	A,#LCD_LINE2		
	call	instr_out		
	mov	DPTR,#MSG004		 
	call	print_lcd

	call	sek_1

	;****** TEXT: Softwareversion		Copyrights

	mov	A,#LCD_LINE1		; Software Version	
	call	instr_out
	mov	DPTR,#MSG005		 
	call	print_lcd

;******

	mov	A,#LCD_LINE2		; Hardware Version	
	call	instr_out
	mov	DPTR,#MSX010		; Textausgabe ohne Zahlen		 
	call	print_lcd

	; Hardwareversion Vorkommastelle aus EEPROM holen

	mov	I2C_ADR_H,#00H			 ; Page 0
	mov	I2C_ADR_L,#EE_HARDWARE_VERSION_H ; Adresse des Nutzbytes
	mov	I2C_ID,#EE_ID
	call	read_random			 ; Ergebnis in I2C_DATA
	
	; Umwandlung eines HEX- Wertes in zwei am LCD- Modul darstellbare
	; ASCII- Zeichen; Wertuebergabe in Akku A
	; Rueckgabe in ASCII_L (low nibble) und ASCII_H (high nibble)
 
	mov	A,I2C_DATA
	call	hex_in_ascii

	mov	A,ASCII_H
	cjne	A,#30H,giveout_2nib	; statt ASCII 30H (Nullzeichen)
					; ein Leerzeichen
	mov	A,#20H			; Leerzeichen ausgeben als Abstand
	call	char_out		; und dann nur low nibble
	jmp	giveout_lnib

giveout_2nib:
	mov	A,#20H			; Leerzeichen ausgeben als Abstand
	call	char_out		; und dann beide nibble

	mov	A,ASCII_H
	call	char_out		; Version Vorkommastelle high nibble

giveout_lnib:
	mov	A,ASCII_L
	call	char_out		; Version Vorkommastelle low nibble

	mov	A,#2EH			; Punkt ausgeben
	call	char_out

	; Hardwareversion Nachkommastelle aus EEPROM holen

	mov	I2C_ADR_H,#00H			 ; Page 0
	mov	I2C_ADR_L,#EE_HARDWARE_VERSION_L ; Adresse des Nutzbytes
	mov	I2C_ID,#EE_ID
	call	read_random			 ; Ergebnis in I2C_DATA

	; Umwandlung eines HEX- Wertes in zwei am LCD- Modul darstellbare
	; ASCII- Zeichen; Wertuebergabe in Akku A
	; Rueckgabe in ASCII_L (low nibble) und ASCII_H (high nibble)
 
	mov	A,I2C_DATA
	call	hex_in_ascii

	mov	A,ASCII_H
	call	char_out		; Version Nachkommastelle high nibble
	mov	A,ASCII_L
	call	char_out		; Version Nachkommastelle low nibble

;******

;	mov	A,#LCD_LINE3		; Zeile 3 leer	
;	call	instr_out
;	mov	DPTR,#MSG000		 
;	call	print_lcd

	mov	A,#LCD_LINE4		; Copyrights	
	call	instr_out		
	mov	DPTR,#MSG006		 
	call	print_lcd

	call	sek_1
	call	sek_1

	mov	A,#LCD_LINE1		; Zeile 1 loeschen	
	call	instr_out
	mov	DPTR,#MSG000		 
	call	print_lcd

	mov	A,#LCD_LINE2		; Zeile 2 loeschen	
	call	instr_out
	mov	DPTR,#MSG000		 
	call	print_lcd

	mov	A,#LCD_LINE4		; Zeile 4 loeschen	
	call	instr_out
	mov	DPTR,#MSG000		 
	call	print_lcd

	ret

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

