Module #3: LCD Output Code

$NOMOD51 ; omit assembler micro definitions

$Include(reg515.inc) ; define 515 micro

Name LCD

 

PUBLIC LCDOUT, LCDINIT

EXTRN CODE (KPD)

LCD_DRV SEGMENT CODE

RSEG LCD_DRV ; switch to this code segment

USING 0 ; use register_bank 0

;*************************************************************************************

; definitions

escflag equ psw.5 ; LCD equate

lcdcmd equ 28h ; value for P2 to select lcd command port

initdata:

db 38h,08,01,06,0eh,80h,0

LCDOUT:

MOV R2,A ; SAVE CHAR IN R2

MOV P2,#LCDCMD ; POINT TO COMMAND PORT

jnb ESCflag,lcdnt5 ; skip if no ESC

clr escflag

sjmp reg0out ; write directly to lcd reg 0

lcdnt5:

ANL A,#11100000B ; SEE IF ANY OF UPPER 3 BITS SET

JNZ REG1OUT ; IF YES, PRINT IT

MOV A,R2 ; RESTORE CHAR

ANL A,#11111000B ; SEE IF CHAR IS < 7

JZ REG1OUT ; IF LESS, A=0 SO PRINT USER DEF CHAR 0-7

MOV A,R2 ; SEE IF CONTROL CHAR

CJNE A,#0DH,LCNT1 ; IF NOT CR, SKIP

MOVX A,@R1 ; READ COMMAND PORT TO FIND CURSOR POS

SETB ACC.7 ; SET BIT 7 FOR DDRAM ADDR

ANL A,#11100000B ; MOVE TO LEFT (ONLY VALID ON 2 LINE DISPL)

MOV R2,A

SJMP REG0OUT

LCNT1:

CJNE A,#0AH,LCNT2 ; IF NOT LF, SKIP

MOVX A,@R1 ; READ COMMAND PORT TO FIND CURSOR POS

CPL ACC.6 ; SWITCH LINE (ONLY VALID ON 2 LINE DISPL)

SETB ACC.7 ; SET BIT 7 FOR DDRAM ADDR

MOV R2,A

SJMP REG0OUT

LCNT2:

CJNE A,#1BH,LCNT3 ; IF NOT ESC, SKIP

setb ESCflag ; indicate ESC received

JMP LCDEXIT

LCNT3:

CJNE A,#1AH,LCNT4 ; EXIT IF NOT CLEAR SCREEN

MOV R2,#1 ; CLEAR COMMAND

SJMP REG0OUT

; OUTPUT THE CHAR IN R2 TO REG 1

REG1OUT:

MOVX A,@R1 ; READ LCD COMMAND PORT

JB ACC.7,REG1OUT ; LOOP IF BUSY FLAG SET

INC P2 ; POINT TO LCD DATA PORT

MOV A,R2 ; RESTORE CHAR

MOVX @R1,A ; OUTPUT IT

LCNT4:

JMP LCDEXIT

; OUTPUT THE CHAR IN R2 TO REG 0

REG0OUT:

MOVX A,@R1 ; READ LCD COMMAND PORT

JB ACC.7,REG0OUT ; LOOP IF BUSY FLAG SET

MOV A,R2 ; RESTORE CHAR

MOVX @R1,A ; OUTPUT IT

JMP LCDEXIT

;

; LCDINIT: Init the LCD

;

LCDINIT:

clr ESCflag ; indicate no esc found

MOV P2,#LCDCMD ; POINT TO COMMAND PORT

LCALL DLAYA ; 5MS DELAY

LCALL DLAYA ; 5MS DELAY

LCALL DLAYA ; 5MS DELAY

LCALL DLAYA ; 5MS DELAY

MOV A,#30H

MOVX @R1,A ; OUT TO LCD COMMAND PORT

LCALL DLAYA ; 5MS DELAY

MOVX @R1,A ; OUT TO LCD COMMAND PORT

LCALL DLAYA ; 5MS DELAY

MOVX @R1,A ; OUT TO LCD COMMAND PORT

MOV DPTR,#INITDATA ; POINT TO INIT DATA

; the last command should take no more than 40 uS.

mov b,#80 ; for timeout of 80*3 * (12/clock)

LCDINIT2:

movx a,@r1 ; read lcd command port

jnb acc.7,LCDINIT1 ; exit if not busy

djnz b,LCDINIT2 ; loop till timeout

sjmp lcdexit ; exit if timeout

LCDINIT1:

MOVX A,@R1 ; READ LCD COMMAND PORT

JB ACC.7,LCDINIT1 ; LOOP IF BUSY FLAG SET

CLR A

MOVC A,@A+DPTR ; GET BYTE FROM INIT TABLE

JZ LCDEXIT ; EXIT IF 0

INC DPTR ; POINT TO NEXT BYTE

MOVX @R1,A ; OUTPUT BYTE

SJMP LCDINIT1 ; LOOP

LCDEXIT:

RET

 

 

 

;

; MISCELLANEOUS DELAYS added to keep the LCD from scrolling

; when the buttons are held down

DLAYA:

PUSH ACC

MOV A,#100

AJMP DLAYA2

DLAYB:

PUSH ACC

MOV A,#128

AJMP DLAYA2

DLAYC:

PUSH ACC

MOV A,#255

AJMP DLAYA2

dlayd:

PUSH ACC

MOV A,#8

 

DLAYA2:

PUSH ACC

MOV A,#0FFH

DLAYA1:

MOV A,#0FFH

DJNZ ACC,$ ; LEVEL 3 LOOP

POP ACC

DJNZ ACC,DLAYA2 ; LEVEL 1 LOOP

POP ACC

RET

END