
;PROCESSOR: Atmel 89S8253
;CRYSTAL: 12 MHz
;FILENAME: LCD-TEST.A51
;DATE: 17/10/07
;REVISIONS: 0.2
;AUTHOR: BRUCE MONEY
;HARDWARE REQUIREMENTS: LCD AT89S8253 WITH DEBUG LED and 40 x 2 lcd.
$INCLUDE (REG8252.INC)

;LED EQUATES
LED	equ	P3.7

;************** Hardware Equates ******************
EN	EQU	P2.7			;LCD ENABLE
RW	EQU	P2.6			;LCD READ/WRITE
RS	EQU	P2.5			;LCD REGISTER SELECT
BUSY	EQU	P0.7			;LCD BUSY PORT (0.7)
LCDDATA	EQU	P0			;LCD DATA PORT (0)

;************** Memory Equates ******************
;MCOUNT	EQU	45h			;LCD DIGIT COUNTER

;************** Vector Addresses ******************
	org	0000h
	sjmp	start

;************** Initital Setup ******************
start:
        CALL    TEST
	sjmp	$
;************** Welcome Message ******************
;	ORG	0200h             <b><--- unnecessary waist of space</b>
TEST:	db	'BRUCE RULES',0   <b><--- note the extra zero at the end</b>
;	MOV	MCOUNT,#0Bh       <b><--- there's a better way</b>
	MOV	DPTR,#TEST
	LCALL	WRITE_LCD
	RET
	
;************** LCD SUB ROUTINES ******************

WRITE_LCD:
	LCALL	CLEAR_LCD 
LCD_NEXT:
	CLR	A
	MOVC	A,@A+DPTR
        JZ      WRITE_END          <b><--- This is looking for the extra zero at the end of string</b>
	LCALL	WRITE_LCD_TEXT
	INC	DPTR
        AJMP    LCD_NEXT
;	DJNZ	MCOUNT,LCD_NEXT
WRITE_END:
	RET
WAIT_LCD:
        CLR	RS
        SETB	RW
	SETB	EN
	MOV	LCDDATA, #0FFh
	MOV	A,LCDDATA 
;	JB	P0.7,WAIT_LCD	<b> <--- You can't check busy flag until after init </b>
        MOV     R0,#255         <b> <--- simply delay</b>
        DJNZ    R0,$
	CLR	EN
	CLR	RW
	RET
INIT_LCD:
	MOV	A,#3Ch
	LCALL	LCD_COMMAND
	MOV	A,#0Fh
	LCALL	LCD_COMMAND
        LCALL	CLEAR_LCD
	MOV	A,#06h
	LCALL	LCD_COMMAND
	RET
LCD_COMMAND:
	CLR	RS		;RS LOW TO INDICATE A COMMAND
	CLR	RW		;RW LOW TO INDICATE WRITE
	MOV	LCDDATA,A	;MOVE COMMAND IN ACCUMULATOR TO DATA PORT
	SETB	EN		;RAISE EN TO INITIATE LCD COMMAND
	NOP			;WAIT 4 CYCLES TO GIVE LCD TIME TO PROCESS
	NOP
	NOP
	NOP
	CLR	EN		;LOWER EN LINE
	LCALL	WAIT_LCD	;WAIT FOR THE PREVIOUS COMMAND TO EXECUTE
	RET			;RETURN TO CALLING PROGRAM CODE
CLEAR_LCD:
	MOV	A,#01h		;SET ACCUMULATOR TO CLEAR SCREEN COMMAND
	LCALL	LCD_COMMAND	;EXECUTE COMMAND
	RET
WRITE_LCD_TEXT:
	SETB	RS		;RS HIGH TO INDICATE TEXT DATA
	CLR	RW		;RW LOW TO INDICATE WRITE
	MOV	LCDDATA,A	;MOVE CHARACTER IN ACCUMULATOR TO DATA PORT
	SETB	EN		;RAISE EN TO INITIATE LCD COMMAND
	NOP			;WAIT 4 CYCLES TO GIVE LCD TIME TO PROCESS
	NOP
	NOP
	NOP
	CLR	EN		;LOWER EN LINE
	LCALL	WAIT_LCD	;WAIT FOR THE PREVIOUS COMMAND TO EXECUTE
	RET			;RETURN TO CALLING PROGRAM CODE
	
	end
