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