;$PROC(80517)   
;$XREF
;***************************************************************
;
;   BUG-420  Monitor fÜr 89C420-Systeme
;
;   Copyright : SYSTEM-CLINCH AG         Mail: MMagnin@Clinch.ch
;               Manuel Magnin            Web:  www.clinch.ch/clinch/MCS420
;               CH-8355 Aadorf
;
;
;  BUG-537  V 0.0  vom  09.02.2000  - Grund Version
;  BUG-420  V 0.1  vom  28.09.2004  - 
;       
;  Taktfrequenz: 357:12MHz, 420:32mhZ
;  537:Serielle Schnittstelle COM1 9600 Baud 8N1
;  420:Serielle Schnittstelle COM1 9600 Baud 8N1
;
;  Der Debuger ERLAUBT folgende BEFEHLE:
;							
;               * G XXXX GO TO ADDRESS
;               * D XXXX MEMORY DISPLAY
;               * M XXXX MEMORY CHANGE
;
;      
;
;***************************************************************


$MOD51
$TITLE(BYTE SIGNED MULTIPLY)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING


; 537 Befehls Erweiterung:
S0CON	DATA	098H
S0BUF	DATA	099H
S1CON	DATA	09BH
S1BUF	DATA	09CH
S1REL	DATA	09DH
EAL	BIT	0AFH
ADCON   DATA    0D8H
ADDAT   DATA    0D9H
DAPR    DATA    0DAH
BSY     BIT     0DCH
BD      BIT     0DFH

P4      DATA    0E8H
P5      DATA    0F8H
P6      DATA    0FAH

; Konstanten & Abkürzungen
STACK		EQU	60h	; Stack für RAM Mode
LCDCOMWR	EQU	0FFC0h
LCDDATAWR	EQU	0FFC1h
LCDCOMRD	EQU	0FFC2h
LCDDATARD	EQU	0FFC3h
XON		EQU      11h
XOFF		EQU      13h
CR		EQU      0Dh
LF		EQU      0Ah   
SPACE		EQU	020h


	 org 0000H
	 ;#include 80535.SFR
	 ;#include MOD515

RESET_:  ajmp START           ;Programmanfang nach Reset

	 org 0003H            ;Externer Interrupt 0, INT0
	 ljmp 8003H
	 org 000BH            ;šberlauf Counter/Timer 0
	 ljmp 800BH
	 org 0013H            ;Externer Interrupt 1, INT1
	 ljmp 8013H
	 org 001BH            ;šberlauf Counter/Timer 1
	 ljmp 801BH
	 org 0023H            ;Serieller Interrupt
	 ljmp 8023H

	 org  0030H           ;Reserviert fr BASIC-Vectoren
	 ljmp  2030H           ;Vektor fr UO 1
	 org  003CH
	 ljmp  203CH           ;Vektor fr PRINT@

	 org 0043H            ;AD-Wandler Interrupt
	 ljmp 8043H
	 org 004BH            ;Externer Interrupt 2
	 ljmp 804BH
	 org 0053H            ;Externer Interrupt 3
	 ljmp 8053H
	 org 005BH            ;Externer Interrupt 4
	 ljmp 805BH
	 org 0063H            ;Externer Interrupt 5
	 ljmp 8063H
	 org 006BH            ;Externer Interrupt 6
	 ljmp 806BH


	 org 0100H            ;Hauptprogramm

; Sprung Tabelle für System Routinen
		LJMP	Start			; Debuger starten und initialisieren
		LJMP	LCDInit			; LCD initialisieren
		LJMP	Read			; Lies in Zeichen ab Ser. Schnittselle 0=kein Zeichen da
		LJMP	Write			; Ausgabe Accu auf die Serielle Schnittstelle
		LJMP	WriteLCD		; Ausgabe Accu auf LCD B=Pos
		LJMP	WriteLn			; Ausgabe Text an Pos DPTR, ende mit 0
		LJMP	WriteLnLCD		; Ausgabe Text an Pos DPTR, B=Pos, ende mit 0

		LJMP	Upper			; Zeichen im Accu auf Grossschreibweise
		LJMP	Wait			; Warte 100mS

;*****************************
;* Programm Start nach Reset *
;*****************************
		org	0200h
START:	;	mov   SP,#STACK-1    ;Stackpointer setzten

InitRS:	
		; RS232 mit Baudratengenerator: 9,6 Kilobaud bei  12 MHz 80C537
;		setb  BD             		; ADCON.7, Baudratengenerator
;		mov   PCON,#80H      		; SMOD=1
;		mov   SCON,#50H      		; InitRS232 
;		setb  TI             		; SCON.1, sendebereit

		; RS232 mit Baudratengenerator: 9,6 Kilobaud bei  32 MHz 89C420
		mov	psw,#00			; Reset Register Banks
		mov	pcon,#080h		; SMOD=1
		mov	tmod,#022h		; Modes are Timer
		MOV	TH1,#0FDH		; PreLoad Value
		MOV	TL1,#0FDH		; FD=19200 (32MHz), FA=9600(32MHz)
		SETB	TCON.6			; Start Counter
		MOV	SCON,#052H		; Mode=1

		mov	dptr,#BOOTTXT		; Boot-Text Seriell ausgeben
		call	writeln

;InitLCD:	call	lcdinit			; LCD initialisieren
		MOV	DPTR,#BootTXT		; Boot-text ausgeben
		MOV	B,#00h			; Start Cursor im LCD
;		CALL	WriteLnLCD          

;***************************************************************
;* PROGRAMM EINGABE LOOP MENU
;***************************************************************
Menu:		mov	dptr,#PromptTxt		; Prompt ausgeben
		call	writeln

MenuRead:	call	Read			; Kommando holen
		jz	MenuRead		; Kein Zeichen
		call	upper			; UpCase 
		call	Write			; Echo Ausgeben
		cjne	A,#'?',MenuNo?		; Help
		ajmp	MHelp
MenuNo?:	cjne	A,#'H',MenuNoH		; Help
		ajmp	MHelp
MenuNoH:	cjne	A,#'A',MenuNoA		; AD-Converter ausgeben
		ajmp	MADC
MenuNoA:	cjne	A,#'M',MenuNoM
		mov	b,1			; Disp Code
		ajmp	MDisp
MenuNoM:	cjne	A,#'D',MenuNoD
		mov	b,0			; Disp xData
		ajmp	MDisp
MenuNoD:	cjne	A,#'E',MenuNoE		; Edit Code
		mov	b,1			
		ajmp	MEdit
MenuNoE:	cjne	A,#'I',MenuNoI		; Edit xData
		mov	b,0			
		ajmp	MEdit
MenuNoI:	cjne	A,#'S',MenuNoS		; Save Intel Hex
		ajmp	MSaveHex
MenuNoS:	cjne	A,#'L',MenuNoL		; Load Intel Hex
		ajmp	MLoadHex
MenuNoL:	cjne	A,#':',MenuNoL_		; Load Intel Hex
		ajmp	MLoadHex
MenuNoL_:	cjne	A,#'G',MenuNoG		; Sprung an Code
		ajmp  	MGo
MenuNoG:	cjne	A,#'Z',MenuNoZ		; für Test Zwecke
		ajmp  	MTest
MenuNoZ:
		ajmp	Menu			; kein Befehl gefunden


;***************************************************************
MHelp:		mov	dptr,#HelpTxt		; Help ausgeben
		call	writeln
		ajmp	Menu			; Zurück zum Menu

;***************************************************************
MGo:		call	ReadHex			; High Byte holen
		mov	dph,a			; Sichern
		call	ReadHex			; Low Byte holen
		mov	dpl,a			; Sichern
		jmp	@A+DPTR			; Sprung zum Ziehl

;***************************************************************
MEdit:		call	ReadHex			; Anfang High Byte holen
		mov	dph,a			; Sichern Anfang Hi
		call	ReadHex			; Anfang Low Byte holen
		mov	dpl,a			; Sichern Anfang Lo
MEdit2:		Call	writeCRLF
		mov	a,dph			; Aktuelle Adresse ausgeben
		call	writeHex
		mov	a,dpl
		call	writeHex
		call	Write2Sp		; etwas nach rechts

		movx	a,@dptr			; Aktuelles Zeichen holen xdata
		jb	B.0,MEdit4		; B=1 für code B=0 für XDATA
		clr	a
		movc	a,@a+dptr		; Aktuelles Zeichen holen code

MEdit4:		call	writeHex		; Zeigen was jetzt drinn steht
MEdit1:		Call	Read			; eingabe neues zeichen
		jz	MEdit1			; noch kein Zeichen da
		Call	Write
		subb	a,#CR		
		jz	MEdit3			; CR dann neuer Hex Wert
		subb	a,#SPACE-CR		; bei  Space weiter
		jnz	MEditE			; und ende
		Call	ReadHex			; Neuer wert holen

		jb	B.0,MEdit5		; B=1 für code B=0 für XDATA
		mov	@R1,a			; Aktuelles Zeichen code ablegen
		sjmp	MEdit3
MEdit5:		movx	@dptr,a			; Aktuelles Zeichen xdata ablegen

MEdit3:		inc	dptr			; und weiter
		jmp	MEdit2		
MEditE:		ajmp	Menu	
;***************************************************************
MDisp:		call	ReadHex			; Anfang High Byte holen
		mov	dph,a			; Sichern Anfang Hi
		call	ReadHex			; Anfang Low Byte holen
		anl	a,0f0h			; immer mit letzer hexziffer 0 beginnen
		mov	dpl,a			; Sichern Anfang Lo
		CALL	ReadHex			; Ende Hi Byte holen
		mov	R6,A
		CALL	ReadHex			; Ende Lo Byte holen
		ADD	A,#1			; Die 16bit Endadresse muss inkrementiert werden
		MOV	R7,A    		; da sonst das letzte Datenbyte nicht gesendet wird
		MOV	A,R6			; übertrag mitnehmen
		ADDC	A,#0               	; 
		MOV	R6,A           
		call	WriteCRLF		; Neue Zeile erzwingen

MDispLine:	mov	a,dph			; Aktuelle Adresse ausgeben
		call	WriteHex
		mov	a,dpl
		call	WriteHex
MDispByte:	mov	a,#space
		call	Write			; Leer Zeichen wischen durch
		movx	a,@dptr			; Aktuelles Zeichen holen xdata
		jb	B.0,MDispByte2		; B=1 für code B=0 für XDATA
		clr	a
		movc	a,@a+dptr		; Aktuelles Zeichen holen code
MDispByte2:	call	WriteHex
		Inc	DPTR			; Nächstes Byte
		mov	a,dpl
		anl	a,#00Fh			; 16 Hex-Bytes pro Zeile
		jnz	MDispByte
		call	writeCRLF		; Neue Linie

						; Vergleich ob Ende
		CLR	C			; übertrag löschen
		MOV	A,R7			; berechne R7 - DPL = R3
		SUBB	A,DPL               
		MOV	R3,A
		MOV	A,R6			; berechne R6 - DPH = ACC
		SUBB	A,DPH			; Auswertung :
		JC	MDispByteE		; EA > AA also Fehler                          
		JNZ	MDispByteE		; high(EA-AA) <> 0 ?
		CJNE	R3,#0,MDispLine		; Endadr. = Anfangsadr. ?

						; Ja, Abschlussmeldung
MDispByteE:	ajmp	Menu			; Zurück zum Menu

;***************************************************************
MADC:		call	ReadHex			; Kanal holen
		call	Write2SP
		push	acc			; Analag-Kanal
		anl	A,#08H			; Bit gesetzt: Aufl”sung 10 Bit
		jz	MADC8			; 0..7= 8 Bit
		pop	acc
		acall 	ReadADC			; 10-Bit Messung
		mov   	R2,A           		; Lowbyte sichern
		mov   	A,B
		acall	WriteHex       		; Highbyte senden
;??		acall	Read           		; Lowbyte muss abgeholt werden
		mov	A,R2			; Gesichetes LowByte abholen
		acall	WriteHex		; Lowbyte senden
		ajmp	Menu

MADC8:		pop	acc			; 8-Bit-Messung 0...5V
		anl   	A,#7           		; Kanal
		acall	ReadADCx
		acall	WriteHex
		acall	Write2SP
		ajmp	Menu

;***************************************************************
MLoadHex:	CALL	ReadHex			; Anzahl Datenbytes 
		MOV	R0,A			; R0 = Anzahl
		MOV	R1,A			; 1.Wert der Prüfsumme
		CALL	ReadHex			; highbyte Zieladresse
		MOV	DPH,A
		ADD	A,R1			; zur Prüfsumme aufaddieren
		MOV	R1,A
		CALL	ReadHex			; lowbyte Zieladresse
		MOV	DPL,A
		ADD	A,R1			; zur Prüfsumme aufaddieren
		MOV	R1,A
		CALL	ReadHex			; Datentyp
		JNZ	MLoadHex2		; 00 = Daten  01 = ENDE
MLoadHex1:	CALL	ReadHex			; Datenbyte lesen und 
		MOVX	@DPTR,A			; in Zieladresse schreiben
		INC	DPTR			; Zielzeiger erhöhen
		ADD	A,R1			; Datenbytes aufaddieren
		MOV	R1,A			; Summe in R1 retten
		DJNZ	R0,MLoadHex1 
		MOV	A,R1			; berechne (0 - Prüfsumme)
		CPL	A
		ADD	A,#1
		MOV	R1,A
		CALL	ReadHex			; Prüfsumme
		XRL	A,R1			;
		JZ	MLoadHex2 
MLoadHex2:	JMP	MenuRead		; nicht Prompt ausgeben (zeit für 4 Zeichen?)

;***************************************************************
; Save - Daten senden im INTEL-HEX-Format
; Die Routine fordert Anfangs- und Endadresse des Bereichs des 
; Datenspeichers an der gesendet werden soll.
; Bemerkung : Hinter Save1 wird die Differenz aus End- und 
;             Anfangsadresse berechnet. Ist die EA gr”áer als 
; die AA wird gleich abgebrochen. Ist das Ergebnis > 255 werden
; 16 Bytes gesendet. Ist das Ergebnis = 0 wird der Schluá-Rec.
; gesendet. Ist das Ergebnis < 16 werden nur noch diese Bytes ge-
; sendet.
;---------------------------------------------------------------
MSaveHex:   	CALL	ReadHex			; Bereich holen
		mov	DPH,A
		CALL	ReadHex
		mov	DPL,A
		CALL	ReadHex
		mov	R6,A
		CALL	ReadHex
		ADD	A,#1			; Die 16bit Endadresse muss inkrementiert werden
		MOV	R7,A    		; da sonst das letzte Datenbyte nicht gesendet wird
		MOV	A,R6			; übertrag mitnehmen
		ADDC	A,#0               	; 
		MOV	R6,A           

		Call	WriteCRLF		; Ausgabe auf neue Zeile
				 
MSaveHex1:	MOV	A,#':'			; Hex-Record beginnen
		CALL	Write   
			
		CLR	C			; übertrag löschen
		MOV	A,R7			; berechne R7 - DPL = R3
		SUBB	A,DPL               
		MOV	R3,A
		MOV	A,R6			; berechne R6 - DPH = ACC
		SUBB	A,DPH			; Auswertung :
		JC	MSaveHexErr		; EA > AA also Fehler                          
		JNZ	MSaveHex3		; high(EA-AA) <> 0 ?

		CJNE  R3,#0,MSaveHex2		; Endadr. = Anfangsadr. ?
		CLR   A				; Ja, Abschluámeldung
		CALL  WriteHex			; 00 Datenbytes
		CALL  WriteHex           	; 00 Adresse highbyte
		CALL  WriteHex           	; 00 Adresse lowbyte
		MOV   A,#01
		CALL  WriteHex			; 01 Datentyp 
		MOV   A,#0FFh            	; FF Prfsumme
		CALL  WriteHex
		CALL  WriteCRLF
		JMP   Menu
MSaveHexErr:       			   	; AA > EA
		JMP   Menu
MSaveHexErr1:					; Parameter fehlt
		JMP   Menu
			
MSaveHex2:	CJNE  R3,#16,$+3		; Bereich > 16 byte ?  
		JC    MSaveHex4              	; CY=0 -> R0 <= 16
MSaveHex3:	MOV   R3,#16			; Anzahl Daten auf 16 begrenzen
MSaveHex4:	MOV   A,R3
		MOV   R2,A			; 1.Wert der Prfsumme
		CALL  WriteHex           	; Anzahl Daten senden
		MOV   A,DPH
		CALL  WriteHex			; Highbyte Adresse senden
		ADD   A,R2			; Prüfsumme bilden
		MOV   R2,A
		MOV   A,DPL
		CALL  WriteHex			; Lowbyte Adresse senden
		ADD   A,R2			; Prüfsumme bilden
		MOV   R2,A
		MOV   A,#0               	; Datentyp 0 senden
		CALL  WriteHex

MSaveHex5:	MOVX  A,@DPTR            	; Zeichen holen
		CALL  WriteHex           	; und senden
		ADD   A,R2               	; Prüfsumme bilden
		MOV   R2,A
		INC   DPTR
		DJNZ  R3,MSaveHex5
				
		MOV   A,R2      		; berechne (0 - Prüfsumme)
		CPL   A
		ADD   A,#1
		CALL  WriteHex       
		CALL  WriteCRLF			; Neue Linie
		JMP   MSaveHex1           

;***************************************************************
MTest:		clr	a
mtest2:		Mov	DPTR,#0FFC0h
		Movx	@DPTR,A
		call	wait
		inc	a
		jnz	mtest2
		ajmp	Menu

;MTest:		call	readHex
;		call	writehex
;		ajmp	menu

;***************************************************************
;***************************************************************








;***************************************************************
; Read   Einzelnes Zeichen lesen falls vorhanden Acc
;        über STDIO (COM1)
;        kein Zeichen vorhanden gibt ein 0 zurück
;
; Eingabeparameter : -
; Ver„nderte Reg.  : A,PSW
; Aufruf           : -
;***************************************************************
Read:		MOV   A,SCON		; Status laden      
		JNB   ACC.0,Read1	; RI-Bit testen
		MOV   A,SBUF		; Zeichen lesen
		ANL   SCON,#11111110B	; RI-Bit löschen
		add	a,#0		; Flaggs Setzen
		RET                      
Read1:		CLR	A		; Kein Zeichen vorhanden!
		RET

;***************************************************************
; ReadHEX   Einzelnes Zeichen lesen und von Hex umwandeln in Accu
;           wartet auf Zeichen vorhanden
;
; Eingabeparameter : -
; Ver„nderte Reg.  : A
; Aufruf           : Read2Hex, Read
;***************************************************************
ReadHEX:	push	dpl
ReadHex2:	call	read			; 1. Byte Laden
		jz	ReadHex2
		call	upper			; Zeichen in gross
		call	write			; Echo senden
		subb	a,#' '			; Space ignorieren
		jz	ReadHex2
		add	a,#' '
		call	Read2Hex		; Umwandeln (lower Nibble)
		swap	a			; Nibble wechseln
		mov	dpl,a			; Sichern
ReadHex3:	call	read			; 2. Byte Laden
		jz	ReadHex3
		call	upper			; Zeichen in gross
		call	write			; Echo senden
		subb	a,#' '			; Space ignorieren
		jz	ReadHex3
		add	a,#' '
		call	Read2Hex		; Umwandeln (lower Nibble)
		add	a,dpl			; Low und Hi Nibbele zusammen fügen
		pop	dpl
		add	a,#0			; Z-Föagg setzen
		RET

Read2Hex:	push	acc
		Subb	a,#'9'+1		; ist grösser als 9?
		jc	Read2Hex2
		pop	acc
		Subb	a,#'A'-10
		Ret		
Read2Hex2:	pop	acc
		subb	a,#'0'-1
		Ret

;***************************************************************
; Write   Einzelzeichenausgabe ber STDIO (COM1)
;
; Eingabeparameter : Zeichen im Akku
; Ver„nderte Reg.  : A,PSW
; Aufruf           : -
;***************************************************************
Write:		JNB	SCON.1,WRITE
		CLR	SCON.1
		MOV	SBUF,A
		RET

;Write:  		PUSH  ACC      
;Write1:   		MOV   A,SCON		; Empfangs-Status laden      
;			JNB   ACC.0,Write2	; Zeichen vorhanden ?      
;			MOV   A,SBUF		; Ja, Zeichen lesen
;			ANL   S1CON,#11111110B	; RI-Bit l”schen
;			CJNE  A,#XOFF,Write2	; XOFF ?      
;			Call  Read		; Ja, auf XON warten
;			CJNE  A,#XON,Write3	; XON gekommen ?
;Write2:        		JNB   ACC.1,Write1	; Sendepuffer leer ?
;			ANL   SCON,#11111101B	; TI-Bit l”schen
;			POP   ACC
;			MOV   SBUF,A		; Zeichen senden
;			RET

;***************************************************************
; WriteCRLF     Neue Zeile Zeichenausgeben
;
; Eingabeparameter : -
; Ver„nderte Reg.  : -
; Aufruf           : Write
;***************************************************************
WriteCRLF:	PUSH	ACC                ; Akku retten
		mov	a,#LF
		call	Write
		mov	a,#cr
		call	Write
		POP	ACC
		RET

;***************************************************************
; Write2SP     Zwei Leerzeichen Senden
;
; Eingabeparameter : -
; Ver„nderte Reg.  : -
; Aufruf           : Write
;***************************************************************
Write2SP:	PUSH	ACC                ; Akku retten
		mov	a,#SPACE
		call	Write
		mov	a,#SPACE
		call	Write
		POP	ACC
		RET

;***************************************************************
; WriteHex      Hexadezimale Zeichenausgabe über STDIO.
;
; Eingabeparameter : Zeichen im Akku
; Ver„nderte Reg.  : -
; Aufruf           : Hex2Asc,Write
;***************************************************************
WriteHex:	PUSH  ACC                ; Akku retten
		PUSH  ACC
		SWAP  A                  ; High Nibble zuerst
		CALL  Hex2Asc            ; konvertieren
		CALL  Write      
		POP   ACC                ; Akku zurück 
		CALL  Hex2Asc            ; Low Nibble
		CALL  Write      
		POP   ACC
		RET

Hex2Asc:	anl	a,#0fh		; Unteres Nibbel Abmskieren
		add	a,#246		; übertrag im Carry
		jnc	Hex2Asc2	; grösser 9
		add	a,#07		; 'A'-'9'
Hex2Asc2:	add	a,#58		; '9'+1
		RET
				
;***************************************************************
; WriteLn
; Gibt eine mit Null terminierte Zeichenkette ber STDIO aus.
; Die Zeichenkette muá sich im Programmspeicher befinden !
;
; Eingabeparameter : DPTR - Zeiger auf Daten
; Ver„nderte Reg.  : A,PSW,DPTR
; UP Aufruf        : Write
;***************************************************************
WriteLn:		CLR   A             
			MOVC  A,@A+DPTR          ;Zeichen holen
			JZ    WriteLn1           ;Ende wenn ACC = 0
			CALL  Write              ;Zeichen senden
			INC   DPTR               ;Datenzeiger erh”hen
			JMP   WriteLn        
WriteLn1:      		RET

;***************************************************************
; LCDInit
; Initialisiert das LCD Display
;
; Eingabeparameter : -
; Ver„nderte Reg.  : A,PSW,DPTR
; Aufruf           : -
;***************************************************************
LCDINIT:	acall LCDBusy
		mov   DPTR,#LCDCOMWR
		mov   A,#38H
		movx  @DPTR,A
		acall LCDBusy
		mov   DPTR,#LCDCOMWR
		mov   A,#06H
		movx  @DPTR,A
		acall LCDBusy
		mov   DPTR,#LCDCOMWR
		mov   A,#0CH
		movx  @DPTR,A
		acall LCDBusy
		mov   DPTR,#LCDCOMWR
		mov   A,#01H
		movx  @DPTR,A
		ret
LCDBusy:	mov   DPTR,#LCDCOMRD
		movx  A,@DPTR
		jb    ACC.7,LCDBusy
		ret

;***************************************************************
; WriteLCD
; Zeichen im accu auf das LCD ausgeben
;
; Eingabeparameter : A
; Ver„nderte Reg.  : A,PSW,DPTR
; Aufruf           : LCDBusy
;***************************************************************
WriteLCD:	PUSH  ACC			; Zeichen Retten
		acall LCDBusy			; Warte Bis LCD Ready
		mov   A,B  			; Cusorposition
		jz    WriteLCDNoCurs
		orl   A,#128
		mov   DPTR,#LCDCOMWR
		movx  @DPTR,A			; Cursor setzen
		acall LCDBusy			; Warte Bis LCD Ready
WriteLCDNoCurs: POP   ACC       		; Zeichen holen
		cjne  A,#CR,WriteLCD1 	 	; = CR?
		ljmp  WriteLCDEnd		; CR ausführen
WriteLCD1:	cjne  A,#LF,WriteLCD2 		; = LF?
		sjmp  WriteLCDEnd		; LF ausführen
WriteLCD2:	mov   DPTR,#LCDDATAWR
		movx  @DPTR,A  		        ; Zeichen ausgeben
WriteLCDEnd:	ret


;***************************************************************
; WriteLNLCD
; Gibt eine mit Null terminierte Zeichenkette ber STDIO aus.
; Die Zeichenkette muá sich im Programmspeicher befinden !
;
; Eingabeparameter : DPTR - Zeiger auf Daten
; Ver„nderte Reg.  : A,PSW,DPTR
; UP Aufruf        : Write
;***************************************************************
WriteLnLCD:	CLR   A             
		MOVC  A,@A+DPTR          ;Zeichen holen
		JZ    WriteLnLCD1        ;Ende wenn ACC = 0
		PUSH  DPL
		PUSH  DPH
		CALL  WriteLCD           ;Zeichen senden
		POP	DPH
		POP	DPL
		INC   DPTR               ;Datenzeiger erh”hen
		JMP   WriteLnLCD
WriteLnLCD1:    RET


;***************************************************************
; Upper
; Wandelt Acc in gross Buchstaben
;
; Eingabeparameter : A
; Ver„nderte Reg.  : A
; UP Aufruf        : -
;***************************************************************
Upper:		Push	ACC
		anl	a,#0C0h		; ist ein Zeichen
		add	a,#0		; Flaggs Setzen
		Jz	UpperNoZei	; < 64 = Kein Zeichen a-z
		POP	ACC
		Anl	A,#0DFh		; UpCase
		RET
UpperNoZei:	POP	ACC		; Altes Zeichen restaurieren
		RET

;***************************************************************
; Wait
; Warte 100mSek
;
; Eingabeparameter : -
; Ver„nderte Reg.  : -
; UP Aufruf        : -
;***************************************************************
Wait:		push	acc		; Register retten
		mov	a,#0F0h		; Zeit ?????
Wait3:		Dec	a
		push	acc
		clr	a
Wait4:		Dec	a
		jnz	Wait4
		pop	acc
		jnz	Wait3
		pop	acc
		Ret

;***************************************************************
; Vergleiche DPTR mit R6/R7
;
; Eingabeparameter : DPTR,R6,R7
; Ver„nderte Reg.  : A
; UP Aufruf        : -
; Ergebnis :
; Akku =  0 bei DPTR =  R6/R7
; Akku <> 0 bei DPTR <> R6/R7
; CY   =  1 bei DPTR >  R6/R7
; CY   =  0 bei DPTR <= R6/R7
;***************************************************************
CMPDPTR:	CLR   C                  ;Carry l”schen
		MOV   A,R6               ;High Byte testen
		SUBB  A,DPH              ;R6 = DPH ?
		JNZ   CMPDPTR1           ;Nein, Ende!
		MOV   A,R7               ;Low Byte testen
		SUBB  A,DPL                
CMPDPTR1:	RET       


;***************************************************************
; RaedADC
; Lesen des AD-Wandler Kanal im Accu 0-7
;
; Eingabeparameter : A
; Ver„nderte Reg.  : -
; UP Aufruf        : -
;***************************************************************
ReadADC:	anl	A,#07h			; Kanal 0..7 abmaskieren
		acall	ReadADCx
		anl	A,#0C0H			; Bits 9,10
		mov	R2,A
		rl	A
		rl	A
		mov	B,A            		; Highbyte in B
		rl	A
		rl	A
		ADD	A,R2			; DA-Byte berechnen
		ADD	A,#40H
		mov	DAPR,A			; Messung Starten
		acall	ReadADCx1		; Lowbyte in A
		ret

ReadADCx:	anl   A,#07H          ; Kanal 0...7 abmskieren
		orl   A,#80H          ; BD = 1
		mov   ADCON,A
		mov   DAPR,#00H       ; 5V
ReadADCx1:  	jb    BSY,ReadADCx1
		mov   A,ADDAT
		ret

;***************************************************************
;***************************************************************


HELPTXT:	DB   10,13
		DB   '** BUG-89C420 V0.1 Hilfe **',LF,CR,LF,CR
		DB   '   H oder ?     Hilfe',LF,CR
		DB   '   M AAAA EEEE  Speicher Anzeigen Code',LF,CR
		DB   '   D AAAA EEEE  Speicher Anzeigen xData',LF,CR
		DB   '   E AAAA       Aendern von Speicher Code',LF,CR
		DB   '   I AAAA       Aendern von Speicher xData',LF,CR
		DB   '   G AAAA       Ausfuehren',LF,CR
		DB   '   L AAAA       Laden von Hex Files',LF,CR
		DB   '   :HEXRECORD   Laden von Hex Files',LF,CR
		DB   '   S AAAA EEEE  Speichern',LF,CR
		DB   '   A NN         AD-Wandler lesen 0-7=8Bit 8-F=10Bit',LF,CR
		DB   '   R NN         Port lesen',LF,CR
		DB   '   W NN         Port schreiben',LF,CR
		DB   '                AAAA=Anfang, EEEE=Ende, NN=Nummer',LF,CR,0

BOOTTXT:	DB   LF,CR
		DB   'BUG420              SYSTEM-CLINCH V0.0 ',LF,CR,0

PromptTXT:      DB   LF,CR,'#',0


end
