
;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 ******************
LEDTICK	equ	40H
LCDTICK	equ	41H
;KEYPADTICK	equ	42h
;LOCK	equ	43h	
MCOUNT	EQU	45h			;LCD DIGIT COUNTER


;************** Vector Addresses ******************
	org	0000h
	sjmp	start
	org	000Bh
	jmp	TIMER0			;TIMER 0 ISR

;************** Initital Setup ******************
start:
	LCALL	INIT_LCD		;INITIAL LCD
	mov	TMOD,#01H		;16BIT TIMER MODE
	mov	TH0,#3Ch		;MOVE C3AF INTO THLO FOR 50ms tick
	mov	TL0,#10101111B		;10101111B - AF (SEE ABOVE) BUT HEX VALUE DOESNT WORK?
	mov	IE,#10000010B		
	SETB	TR0		
	MOV	LEDTICK,#10d		;UPDATE LED EVERY 10 TICKS 10 * 50ms = 500ms
	MOV	LCDTICK,#2d		;UPDATE LCD EVERY 2 TICKS 2 * 50ms = 100ms

	sjmp	$

;************** ISR For Timer 0 ******************
TIMER0:
	clr	TR0		;DISABLE TIMER 0
	mov	TH0,#3Ch		;RESET OF TIMER AFTER TICK
	mov	TL0,#10101111B		;RESET OF TIMER AFTER TICK
	SETB	TR0			;ENABLE TIMER 0
	jmp	TASK_SCHEDULER		;CALL TASK SCHEDULER

;************** Task Scheduler ******************
TASK_SCHEDULER:
LED_TICK:
	DJNZ	LEDTICK,LCD_TICK	;CHECK LEDTICK IF NOT ZERO MOVE TO LCD_TICK
	CPL	LED			;CHANGE LED STATE
	MOV	LEDTICK,#10d		;RELOAD LEDTICK
LCD_TICK:
	DJNZ	LCDTICK, RETURN		;CHECK LCDTICK IF NOT ZERO MOVE TO RETURN
	CALL	TEST			;CALL LCD TEST WRITE
	MOV	LCDTICK,#2d		;RELOAD LCDTICK
RETURN:	RETI

;************** Welcome Message ******************
TEST:	
	ORG	0200h
	db	'BRUCE RULES'
	MOV	MCOUNT,#0Bh
	MOV	DPTR,#0200h
	LCALL	WRITE_LCD
	RETI
	
;************** LCD SUB ROUTINES ******************

WRITE_LCD:
	LCALL	CLEAR_LCD 
LCD_NEXT:
	CLR	A
	MOVC	A,@A+DPTR
	LCALL	WRITE_LCD_TEXT
	INC	DPTR
	DJNZ	MCOUNT,LCD_NEXT
	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>
	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
