	include "P16F877.inc"
	LIST P=PIC16F877

; Speicherstellen
CommandData		equ	0x50
StatusMask		equ	0x51
disp_Temp		equ	0x52


; PORTA-SteuerAusgänge zum Display
Display_WR	equ	3		; ^Data Write	_5_
Display_RD	equ	2		; ^Data Read	_6_
Display_CE	equ	1		; ^Chip Enable	_7_
Display_CD	equ	0		; Command/Data	_8_

; Konstanten
Display_Width	equ	0x78	;=120
Display_Height	equ	0x40	;=64
Display_FWidth	equ	0x06	;=6 da FS=high


; Luxus-Makros
bank0	macro
	bcf	STATUS,RP0
	bcf	STATUS,RP1
	endm

bank1	macro
	bsf	STATUS,RP0
	bcf	STATUS,RP1
	endm

fcall	macro subroutine_name
	local here
	lcall subroutine_name
	pagesel here
here:
	endm

ffunc	macro	Funktion, Parameter
	movlw	Parameter
	fcall	Funktion
	endm

func	macro	Funktion, Parameter
	movlw	Parameter
	call	Funktion
	endm

movlf	macro	Value, Destination
	movlw	Value
	movwf	Destination
	endm

; **********************************
; ** PIC-Einspruenge
; **********************************
	org 0000h
reset:
	goto	init

	org 0004h
	goto	interrupt

; **********************************
; ** Interrupt-Routine
; **********************************
interrupt:
	retfie

; ********************************************************************
	org 0010h

init:
	call	display_init

	func	disp_writeChar, #'X'

mainlp:
	goto	mainlp
; ********************************************************************


; -------------------------------------------------
; - Display Initialisierung
display_init:
	bank1
	clrf	TRISA			; PortA (Steuerbus zum Display) = Output
	clrf	TRISB			; PortB (Datenbus zum Display) = Output

	bcf	OPTION_REG, 7	; Pullups von PORTB an
	bcf	INTCON, 7		; Global Interupt aus

	movlf	#0x06, ADCON1	; (0000-0110)
	bank0
	movlf	#0x20, ADCON0


	movlf	#0x0F, PORTA	; damit ist die Verbindung zum Display unterbrochen, bis
					; Daten oder Kommandos bereitstehen und übertragen werden sollen

	func	disp_sendD, #0x00
	func	disp_sendD, #0x00	; Text Home Adresse 0x0000
	func	disp_sendC, #0x40	; SET CONTROL WORD (0100-0000)

	func	disp_sendD, #(Display_Width/Display_FWidth)
	func	disp_sendD, #0x00	; Text Spalten
	func	disp_sendC, #0x41	; SET CONTROL WORD (0100-0001)

	func	disp_sendD, #0x00
	func	disp_sendD, #0x04	; Grafik Home Adresse 0x0400
	func	disp_sendC, #0x42	; SET CONTROL WORD (0100-0010)

	func	disp_sendD, #(Display_Width/Display_FWidth)
	func	disp_sendD, #0x00	; Grafik Spalten
	func	disp_sendC, #0x43	; SET CONTROL WORD (0100-0011)

	func	disp_sendC, #0xA2	; CURSOR PATTERN SELECT (1010-0100)

	func	disp_sendC, #0x80	; MODESET (1000-0000)
					; OR Mode und int. CG RAM Mode

	func	disp_sendD, #0x00
	func	disp_sendD, #0x00	; Cursor Pointer X=0,Y=0
	func	disp_sendC, #0x21	; REGISTERS SETTING (0010-0001)

	func	disp_sendD, #0x00
	func	disp_sendD, #0x00	; Address Pointer auf 0x0000
	func	disp_sendC, #0x24	; REGISTERS SETTING (0010-0100)

	func	disp_sendC, #0x9F	; DISPLAY MODE (1001-1111)
					; Grafik an, Text an, Cursor an, Cursor blinkt

	return

; *************************************************
; * Unterprogramme

; -------------------------------------------------
; - Buchstabe ausgeben
; - W = ASCII-Charakter
disp_writeChar:
	movwf	disp_Temp
	bcf	STATUS, C
	movlw	#0x20			; \
	subwf	disp_Temp, W	;  \ Mapping von ASCII
	andlw	#0x7F			;  / auf 7Bit-LCD-CharSet
	movwf	disp_Temp		; /

	func	disp_sendD, #0x00
	func	disp_sendD, #0x00
	func	disp_sendC, #0x24	; AdressPointer

	movf	disp_Temp, W
	call	disp_sendD		; Zeigs mir...

	func	disp_sendC, #0xC0	; (1100-0000) Data Write

	return


; *************************************************
; - W = Datenbyte
disp_sendD:
	movwf	CommandData
	func	disp_getStatus, #0x03	;Testen von STA0,STA1
	movf	CommandData, W
	call	disp_sendData
	return

; *************************************************
; - W = Kommandobyte
disp_sendC:
	movwf	CommandData
	func	disp_getStatus, #0x03	;Testen von STA0,STA1
	movf	CommandData, W
	call	disp_sendCmd
	return

; -------------------------------------------------
; - Kommando senden
; - W = Kommandobyte
disp_sendCmd:
	movwf	PORTB

	bsf	PORTA, Display_CD	; Kommando soll übertragen werden
 	bsf	PORTA, Display_RD	; nicht lesen, daher RD auf H
	bcf	PORTA, Display_CE	; CE L bei Kommunikation mit dem Display
	bcf	PORTA, Display_WR	; Schreiben

	; bissl Warten
	nop
	nop
	nop
	nop

	bsf	PORTA, Display_WR
	bsf	PORTA, Display_CE	; Kommando ist übertragen

	return

; -------------------------------------------------
; - Daten senden
; - W = Datenbyte
disp_sendData:
	movwf	PORTB

	bcf	PORTA, Display_CD	; Daten sollen übertragen werden
 	bsf	PORTA, Display_RD	; nicht lesen, daher RD auf H
	bcf	PORTA, Display_CE	; CE L bei Kommunikation mit dem Display
	bcf	PORTA, Display_WR	; Schreiben

	; bissl Warten
	nop
	nop
	nop
	nop

	bsf	PORTA, Display_WR
	bsf	PORTA, Display_CD
	bsf	PORTA, Display_CE	; Daten sind übertragen

	return

; -------------------------------------------------
; - Status des Displays abfragen
; - W = Maskierung der Statusbits
disp_getStatus:
	movwf	StatusMask

	clrf	PORTB

	bank1
	bsf	OPTION_REG, 7	; Pullups von PORTB aus
	movlf	#0xFF, TRISB	; Eingänge
	bank0

	bsf	PORTA, Display_CD
	bsf	PORTA, Display_WR

disp_gSLoop:
	bsf	PORTA, Display_RD
	bsf	PORTA, Display_CE

	nop
	nop

	bcf	PORTA, Display_CE
	bcf	PORTA, Display_RD

	nop
	nop

	movf	PORTB, W
	andwf	StatusMask, W
	bcf	STATUS, C
	subwf	StatusMask, W

	btfss	STATUS, Z
	goto	disp_gSLoop

	bsf	PORTA, Display_RD
	bsf	PORTA, Display_CE

	bank1
	clrf	TRISB			; Ausgänge
	bcf	OPTION_REG, 7	; Pullups von PORTB an
	bank0

	return

; -------------------------------------------------

