home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
utils
/
asmutl
/
hd64180a.lbr
/
IOLCD.AZM
/
IOLCD.ASM
Wrap
Assembly Source File
|
1991-08-04
|
8KB
|
325 lines
title 'CORE Board LCD Drivers'
;----------------------------------------------------------------
; LCD Drivers for CORE Board
;
; This module provides all the LCD Support for CORE-BOARD
; and is separate to the I/O driver main module because
; different LCDs' will definately require different
; I/O drivers.
;
; Written by Richard Holmes 17-12-86
; Last Update by Richard Holmes 16-04-87
;----------------------------------------------------------------
; Routines in this module
;
; ini$lcd Initialize the LCD display
; clr$lcd Clear LCD and home cursor
; hom$lcd Home cursor to top L.H. corner
; cur$lcd Cursor address lcd. D = X, E = Y
; eol$lcd Clear LCD to end of line.
; put$lcd Write character in A to LCD.
; str$lcd Print string at DE to LCD till a null or $
;----------------------------------------------------------------
; This version suits the Sharp LM16255. It is a 16 character by 2
; line display.
; PA 0..7 are data bits into the chip
;
; PB 0 = Enable to display. 1 = enabled
; 1 = R/W-. 1 = write to LCD
; 2 = Register select 1 = Data, 0 = control register
;----------------------------------------------------------------
;
maclib z80
maclib core
;
public ini$lcd,hom$lcd,clr$lcd
public put$lcd,cur$lcd,eol$lcd
public str$lcd
;
extrn ori$led ; Restore LED status
extrn clrwdt ; Stop watchdog
;
; Equates
;
data equ 044h ; Data port of LCD
cntl equ 045h ; Control port of LCD
;
;----------------------------------------------------------------
; Return LCD Status. This is tricky as it must re-initialize
; the LCD control port and read the LCD status flag BF. It
; will return a 00 if idling or an FF if busy. NOTE the
; need to re-load the CS2 line to the ram chip and clock
; and LED return when finished.
;----------------------------------------------------------------
;
lcd$status:
di ; STOP interrupts when checking LCD status
push h ; Save a register to use as a scratch pad
mvi a,090h ; Port A inputs
out @ledmd ; LED mode port
mvi a,0c0h
out @ledd ; Re-assert ram as soon as possible
;
; OK, Port A inputs, B and C outputs. Dangerous. No RAM now.
; Note the need to set R/W pin high for a time before the E pin (bit 0).
;
mvi a,0000$0010b ; Read status. E = 0, R/W- = 1, RS = 0
out @lcdc ; LCD Control sent.
mvi a,0000$0011b ; Enable high now
out @lcdc ; LCD now ready to be read.
nop
nop ; 2uS settling time
in @lcdd ; Read the LCD data
mov l,a ; Save here. Can't see stack can we....
; Restore 8255 mode
mvi a,080h ; ALL outputs
out @ledmd ; LED mode port
; Re-load ram control signals
mvi a,0C0h ; Bit 6 and 7 for ram and clock on
out @ledd ; Sends to led port to turn on ram again.
;
nop
nop
nop
nop
xra a ; Load a null so that ORI will work
;
ei ; Restore interrupts after LCD write
;
call ori$led ; Restore previous LED status
mov a,l ; Restore data
pop h ; Restore register
;Now. Determine basic state of 00 = idle or FF = busy.
ani 1000$0000b ; Leave busy flag
rz
mvi a,0ffh ; Else load an FF for very busy still.
ret
;
;------------------------------------------------
; Latch the command in A into the LCD
;------------------------------------------------
;
lch$cmd:
push h
push psw ; Save registers
; Now setup timeout counter in HL and look for LCD idle
lxi h,200 ; Big delay
lch$cmd$loop:
call clrwdt
call lcd$status ; Get LCD status
ora a
jrz lch$cmd$ok
dcx h
mov a,l
ora h ; Done ?
jrnz lch$cmd$loop ; Loop on till IDLE (busy flag = 0)
; ERROR here
pop psw
pop h
stc ; Carry flag = error
ret
;
; Restore registers and do job
;
lch$cmd$ok:
pop psw
pop h
;
fast$lch$cmd: ; Here to latch a command W/O busy checking
out data
push psw
mvi a,1
lch$comm: ; Common latching code for both command and data
out cntl
xra a
out cntl ; Latch HIGH then low
pop psw
ora a ; Clear carry
ret
;
;------------------------------------------------
; Latch the DATA in A into the LCD
; Note the status check to wait for idle (BF = 0).
;------------------------------------------------
;
lch$dat:
push h
push psw ; Save registers
; Now setup timeout counter in HL and look for LCD idle
lxi h,200 ; Big delay
lch$dat$loop:
call clrwdt
call lcd$status ; Get LCD status
ora a
jrz lch$dat$ok
dcx h
mov a,l
ora h ; Done ?
jrnz lch$dat$loop ; Loop on till IDLE (busy flag = 0)
; ERROR here
pop psw
pop h
stc ; Carry flag = error
ret
;
; Restore registers and do job
;
lch$dat$ok:
pop psw
pop h
;
out data
push psw
mvi a,5 ; Data selector
jr lch$comm ; Note the use of command common code
;
;----------------------------------------------------------------
; Initialize the LCD.
;
; 1. Data path 8 bits, 2 line display
; 2. Enable cursor. Blink. Enable display
; 4. Clear and home cursor.
; 3. Display stationary, auto increment, right
;----------------------------------------------------------------
;
ini$lcd:
push psw
; 1. Enable 8 bit bus, 2 line display
mvi a,038h
call lch$cmd ; Latch 8 bit, 2 line display
; 2. Enable display on, cursor on, blink
mvi a,0fh
call lch$cmd
; 3. Display stationary, auto increment, right
mvi a,6
call lch$cmd
; 4. Display stationary, Right cursor
mvi a,014h
call lch$cmd
; Done.
call clr$lcd
pop psw
ret
;
;----------------------------------------------------------------
; Clear LCD and home cursor.
;----------------------------------------------------------------
;
clr$lcd:
push psw
mvi a,1 ; Clear display totally
call lch$cmd
;
xra a ; Clear cursor address
sta lcd$x
sta lcd$y
pop psw
ret
;
;----------------------------------------------------------------
; Home the cursor
;----------------------------------------------------------------
;
hom$lcd:
push psw
;
mvi a,2 ; Home only
call lch$cmd ; Latch home command
;
xra a
sta lcd$x
sta lcd$y
pop psw
ret
;
;----------------------------------------------------------------
; Cursor address.
;
; On Entry D = X in the range 0..F (characters per line)
; E = Y in the range 0..1 (lines)
;
; If out of range, no change is made
; All registers preserved
;----------------------------------------------------------------
;
cur$lcd:
push psw
; Check if X > possible range.
mov a,d
cpi 16 ; Error if > 16
jrnc cur$err
; Check Line number
mov a,e
cpi 2
jrnc cur$err ; Error if > 1
; Now do the addressing
sta lcd$y ; Save LCD address
;
push b ; Save all registers always, makes easy later.
mvi c,080h ; Top bit = cursor address
ora a ; At top row (A = 0 ?)
jrz cur$not$1 ; Top row is address 80h..8fh
mvi c,0C0h ; If second row the offset if 0C0h
;
cur$not$1:
mov a,c ; Address
add d ; Add in the X address
call lch$cmd ; Command in A built up
; Save the X address also
mov a,d ; X
sta lcd$x
;
pop b
cur$err:
pop psw
ret
;
;----------------------------------------------------------------
; Clear LCD to end of line
;----------------------------------------------------------------
;
eol$lcd:
ret
;
;----------------------------------------------------------------
;
; Send character in A to the LCD
;
;----------------------------------------------------------------
;
put$lcd:
jmp lch$dat
;
;----------------------------------------------------------------
; Print string till null or $
;----------------------------------------------------------------
;
str$lcd:
push psw
str$loop:
call clrwdt
ldax d
cpi '$' ; $ = end
jrz str$end
ora a ; 00 = end
jrz str$end
call put$lcd ; Send
inx d ; -> next
jr str$loop
;
;
str$end:
pop psw
ret
;
; ----oooo----
;
dseg
;
lcd$x: ds 1
lcd$y: ds 1
end
;
; -- End of module --
;