;
; Library Ansteuerung LCD mit c504
; Display nach Datenblatt ks066u
; 8Bit Ansteuerung, Bus P1
; E P3.4		Display Enable
; RS P3.2		Display Daten/Kommandomodus
; RW P3.3		Display Read/Write
;

	
; Bibliotheken k�nnen mit dem Kommando $INCLUDE "lib.asm" im Quelltext
; eingebunden werden.

		
DISP_E	BIT	P3.4
DISP_RS	BIT	P3.2
DISP_RW	BIT	P3.3

DISP_DATA EQU	P1

DISP_WRAP	DATA	2Dh		; ggfs anpassen!


ORG 100h

	; ** ein kleines Testprogramm f�r das Display **
main:
	
	acall init_display	
	
	mov dptr,#teststring
loop:
	mov A,#00h
	movc a,@a+dptr
	jz outloop
	inc dptr
	acall out_char_display
	sjmp loop
	
outloop:
	ljmp 918eh

	
	
	;--------------------------------------
	; Unterprogramm: Display initialisieren
	;--------------------------------------
init_display:
	clr DISP_E
	setb DISP_E		; enable "on"
	nop			; Flanke generieren
	clr DISP_E		; enable "off"
	
	acall wait_display	; einmal nach Power-On auf das Display warten....
	
	mov A,#38h		; 2 "Zeilen"Display einstellen
	acall send_cmd_display
	mov A,#0ch		; Display on, Cursor Off
	acall send_cmd_display
	mov A,#06h		; Entry Mode Set
	acall send_cmd_display
	
	acall clear_display
	
	ret
	
	;----------------------------------------
	; Unterprogramm: Zeichen auf LCD ausgeben
	;----------------------------------------
	; Dieses Unterprogramm abstrahiert die 2 Pseudozeilen
	; und l�sst �ber einen Terminalemulator das LCD als
	; einzeilig mit 16 Zeichen erscheinen
	;
	; auszugebendes ASCII Zeichen im Akku �bergeben
	
out_char_display:
	push ACC
	mov A,DISP_WRAP
	cjne A,#8,out_char_nowrap	; 8 von 16 Zeichen geschrieben?
	
	mov A,#0c0h			; ja -> dann Kommando "Zeilen"wechsel
	clr DISP_RW
	acall send_cmd_display
	
out_char_nowrap:
	pop ACC
	
	acall send_data_display		; eigentliches Zeichen ausgeben
	
	inc DISP_WRAP			; ausgegebene Zeichen mitz�hlen
	
	mov A,DISP_WRAP
	cjne A,#16,out_char_nonewline	; am LCD Ende angekommen?
	
	acall clear_display		; LCD l�schen
out_char_nonewline:	
	ret
	
	;--------------------------------------
	; Unterprogramm: LCD leeren und l�schen
	;--------------------------------------
clear_display:
	push ACC

	mov A,#01h		; clear display and cursor home
	acall send_cmd_display
	mov A,#02h		; home cursor
	acall send_cmd_display
	
	mov DISP_WRAP,#0
	
	pop ACC
	ret
	
	;------------------------------------------
	; Unterprogramm: Kommandobyte an LCD senden
	;------------------------------------------
	; zu sendendes Kommandobyte in A
send_cmd_display:
	clr DISP_RS		; RS aus (Kommandomodus)
	mov DISP_DATA,A		; Instruktion senden
	setb DISP_E
	nop
	acall wait_display	; auf Display warten
	ret

	;---------------------------------------
	; Unterprogramm: Datenbyte an LCD senden
	;---------------------------------------
	; zu sendendes Datenbyte in A
send_data_display:
	setb DISP_RS		; RS an (Datenmodus)
	mov DISP_DATA,A		; Datenbyte senden
	setb DISP_E
	nop
	acall wait_display	; auf Display warten
	ret
	
	;----------------------------------
	; Unterprogramm: auf Display warten
	;----------------------------------
	; Dieses Unterprogramm macht ein Busywaiting/Polling
	; auf ein spezifisches Bit vom Display.
	; Es wartet, ob das Dispaly bereit f�r neue Daten
	; und/oder Kommandos ist.
	
wait_display:
	push ACC
	
wait_display_loop:
        clr DISP_E			; LCD anstossen
	clr DISP_RS			; Kommando abgeben
	setb DISP_RW			; wir wollen lesen
	mov DISP_DATA,#0ffh		; alle Bits setzen
	setb DISP_E			; Display "Enable"
	mov A,DISP_DATA			; Daten vom LCD lesen
	jb ACC.7,wait_display_loop	; Busy-Bit gesetzt? ja -> wiederholen
	clr DISP_E
	clr DISP_RW
	
	pop ACC
	ret
	
teststring:
	db "Testausgabe"
	db 00h
END