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 -- ;