You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

392 lines
8.6 KiB

;
;==================================================================================================
; HARDWARE SUPPORT FOR HITACHI HD44780 OR EQUIVALENT
;==================================================================================================
;
; CURRENTLY ASSUMES A 20X4 DISPLAY
;
; TYPICAL PORTS USED ON RCBUS ECOSYSTEM:
;
; PRIMARY ALT
; FUNCTION $DA $AA
; DATA $DB $AB
;
LCD_FUNC .EQU LCDBASE + 0 ; WRITE
LCD_STAT .EQU LCDBASE + 0 ; READ
LCD_DATA .EQU LCDBASE + 1 ; READ/WRITE
;
LCD_FUNC_CLEAR .EQU $01 ; CLEAR DISPLAY
LCD_FUNC_HOME .EQU $02 ; HOME CURSOR & REMOVE ALL SHIFTING
LCD_FUNC_ENTRY .EQU $04 ; SET CUR DIR AND DISPLAY SHIFT
LCD_FUNC_DISP .EQU $08 ; DISP, CUR, BLINK ON/OFF
LCD_FUNC_SHIFT .EQU $10 ; MOVE CUR / SHIFT DISP
LCD_FUNC_SET .EQU $20 ; SET INTERFACE PARAMS
LCD_FUNC_CGADR .EQU $40 ; SET CGRAM ADRESS
LCD_FUNC_DDADR .EQU $80 ; SET DDRAM ADDRESS
;
DEVECHO "LCD: IO="
DEVECHO LCDBASE
DEVECHO "\n"
;
; HARDWARE RESET PRIOR TO ROMWBW CONSOLE INITIALIZATION
;
LCD_PREINIT:
;
; RESET LCD CONTROLLER, DELAYS ARE FIXED, BUSY FLAG
; CANNOT BE USED YET, CONTROLLER MAY NOT EXIST!
LD A,LCD_FUNC_SET | %11000
OUT (LCD_FUNC),A
LD DE,50000/16 ; WAIT >40MS, WE USE 50MS
CALL VDELAY ; DO IT
LD A,LCD_FUNC_SET | %11000
OUT (LCD_FUNC),A
LD DE,5000/16 ; WAIT >4.1MS, WE USE 5MS
CALL VDELAY ; DO IT
LD A,LCD_FUNC_SET | %11000
OUT (LCD_FUNC),A
LD DE,5000/16 ; WAIT >4.1MS, WE USE 5MS
CALL VDELAY ; DO IT
;
; TEST FOR PRESENCE...
CALL LCD_DETECT ; PROBE FOR HARDWARE
LD A,(LCD_PRESENT) ; GET PRESENCE FLAG
OR A ; SET FLAGS
RET Z ; BAIL OUT IF NOT PRESENT
;
; WE CAN NOW DO NORMAL I/O W/ BUSY FLAG
LD DE,LCD_INIT_SEQ ; INIT SEQUENCE
CALL LCD_OUTFS ; SEND IT
;
; PUT SOMETHING ON THE DISPLAY
LD DE,LCD_STR_BAN
CALL LCD_OUTDS
;
; SECOND LINE
; CPU TYPE
LD HL,$0100 ; ROW 2, COL 0
CALL LCD_GOTORC
LD HL,LCD_CPU
LD A,(HB_CPUTYPE) ; GET CPU TYPE
RRCA ; WORD OFFSET
CALL ADDHLA ; ADD OFFSET
LD E,(HL) ; GET LSB
INC HL ; BUMP
LD D,(HL) ; GET MSB
CALL LCD_OUTDS
LD DE,LCD_STR_XPU
CALL LCD_OUTDS
;
; "12.345 MHz" RIGHT JUSTIFIED
LD HL,$010A ; ROW 2, COL 10
CALL LCD_GOTORC
LD HL,(CB_CPUKHZ)
PUSH HL
LD BC,10000 ; 10 MHZ
SBC HL,BC ; SUBTRACT
JR NC,LCD_PREINIT1
LD A,' ' ; EXTRA PAD
CALL LCD_OUTD
LCD_PREINIT1:
POP HL
CALL LCD_PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA
LD DE,LCD_STR_MHZ
CALL LCD_OUTDS
;
; THIRD LINE
LD HL,$0200 ; ROW 2, COL 0
CALL LCD_GOTORC
LD DE,LCD_STR_CFG
CALL LCD_OUTDS
;
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
; POST CONSOLE INITIALIZATION
;
LCD_INIT:
CALL NEWLINE ; FORMATTING
PRTS("LCD: IO=$")
LD A,LCDBASE
CALL PRTHEXBYTE
;
LD A,(LCD_PRESENT) ; GET PRESENCE FLAG
OR A ; SET FLAGS
JR Z,LCD_INIT1 ; HANDLE NOT PRESENT
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
LCD_INIT1:
PRTS(" NOT PRESENT$")
OR $FF
RET
;
; CALLED FROM HBIOS RIGHT BEFORE A DISK ACCESS
; HL: ADDRESS OF 32-BIT SECTOR NUMBER (LITTLE-ENDIAN)
;
; FORMAT: "Disk #99 R:12345678"
; 01234567890123456789
;
LCD_DSKACT:
; SAVE EVERYTHING
PUSH AF
PUSH BC
PUSH DE
PUSH HL
;
LD A,(LCD_PRESENT) ; GET PRESENCE FLAG
OR A ; SET FLAGS
JR Z,LCD_DSKACT_Z ; HANDLE NOT PRESENT
;
PUSH HL
LD HL,$0300 ; ROW 3, COL 0
CALL LCD_GOTORC ; SET DISPLAY ADDRESS
POP HL
;
LD DE,LCD_STR_IO ; PREFIX
CALL LCD_OUTDS ; SEND TO DISPLAY (COLS 0-5)
;
LD A,(HB_DSKUNIT) ; GET DISK UNIT NUM
CALL LCD_DSKACT_BYTE ; SEND TO DISPLAY (COLS 6-7) HEX???
;
LD A,' ' ; SEPARATOR
CALL LCD_OUTD ; SEND TO DISPLAY (COL 8)
CALL LCD_OUTD ; SEND TO DISPLAY (COL 9)
;
LD A,(HB_DSKFUNC) ; ACTIVE DISK FUNCTION
CP BF_DIOWRITE ; WRITE?
LD A,'W' ; ASSUME WRITE
JR Z,LCD_DSKACT0 ; GO AHEAD
LD A,'R' ; OTHERWISE READ
LCD_DSKACT0:
CALL LCD_OUTD ; SEND CHAR (COL 10)
;
LD A,':' ; SEPARATOR
CALL LCD_OUTD ; SEND TO DISPLAY (COL 11)
;
LD A,3 ; POINT TO
CALL ADDHLA ; END OF DWORD (MSB)
LD B,4 ; DO 4 BYTES
;
LCD_DSKACT1:
LD A,(HL) ; GET BYTE
CALL LCD_DSKACT_BYTE ; SEND TO DISPLAY (COLS 12-19)
DEC HL ; DEC PTR
DJNZ LCD_DSKACT1 ; DO ALL 4 BYTES
;
LCD_DSKACT_Z:
; CLEAN UP AND GO AWAY
POP HL
POP DE
POP BC
POP AF
RET
;
LCD_DSKACT_BYTE:
PUSH AF ; SAVE BYTE
RRCA ; DO TOP NIBBLE FIRST
RRCA
RRCA
RRCA
CALL HEXCONV ; CONVERT NIBBLE TO ASCII
CALL LCD_OUTD ; SEND TO DISPLAY
POP AF ; RECOVER CURRENT BYTE
CALL HEXCONV ; CONVERT NIBBLE TO ASCII
CALL LCD_OUTD ; SEND TO DISPLAY
RET ; DONE
;
; DETECT PRESENCE OF LCD CONTROLLER BY WRITING AND READING BACK
; TEST VALUES IN THE CONTROLLER RAM.
; WE DO NOT USE THE NORMAL READ/WRITE ROUTINES BECAUSE WE DO
; NOT WANT TO STALL WAITING ON THE BUSY FLAG IF THE CONTROLLER
; IS NOT PRESENT
;
LCD_DETECT:
; FIRST PASS W/ TEST VALUE $AA
LD C,$AA
CALL LCD_DETECT_PASS
JR NZ,LCD_DETECT1
;
; SECOND PASS W/ TEST VALUE $55
LD C,$55
CALL LCD_DETECT_PASS
JR NZ,LCD_DETECT1
;
; LCD PRESENT
OR $FF
JR LCD_DETECT_Z
;
LCD_DETECT1:
; LCD NOT PRESENT
XOR A
JR LCD_DETECT_Z
;
LCD_DETECT_Z:
LD (LCD_PRESENT),A
RET
;
; WRITE AND READBACK VALUE IN C TO THE FIRST BYTE OF DDRAM
; RETURN WITH COMPARE RESULT
;
LCD_DETECT_PASS:
CALL LCD_DELAY ; WAIT
LD A,LCD_FUNC_DDADR
OUT (LCD_FUNC),A ; POINT TO FIRST BYTE
CALL LCD_DELAY ; WAIT
LD A,C ; TEST VALUE
OUT (LCD_DATA),A ; WRITE IT
CALL LCD_DELAY ; WAIT
LD A,LCD_FUNC_DDADR
OUT (LCD_FUNC),A ; POINT TO FIRST BYTE
CALL LCD_DELAY
IN A,(LCD_DATA) ; GET VALUE
CP C ; AS WRITTEN?
RET
;
; DELAY USED DURING DETECT, >37US
;
LCD_DELAY:
CALL DELAY ; 16US
CALL DELAY ; 16US
JP DELAY ; 16US, TOTAL 48US
;
; SEND FUNCTION CODE IN A
;
LCD_OUTF:
PUSH AF ; SAVE CODE
LCD_OUTF1:
IN A,(LCD_STAT) ; GET STATUS
AND $80 ; ISOLATE BUSY FLAG
JR NZ,LCD_OUTF1 ; LOOP TILL NOT BUSY
POP AF ; RECOVER CODE
OUT (LCD_FUNC),A ; SEND IT
RET ; DONE
;
; SEND FUNCTION STRING
; DE=STRING ADDRESS, NULL TERMINATED
;
LCD_OUTFS:
LD A,(DE) ; NEXT BYTE TO SEND
OR A ; SET FLAGS
RET Z ; DONE WHEN NULL REACHED
INC DE ; BUMP POINTER
CALL LCD_OUTF ; SEND IT
JR LCD_OUTFS ; LOOP AS NEEDED
;
; SEND DATA BYTE IN A
;
LCD_OUTD:
PUSH AF ; SAVE BYTE
LCD_OUTD1:
IN A,(LCD_STAT) ; GET STATUS
AND $80 ; ISOLATE BUSY FLAG
JR NZ,LCD_OUTD1 ; LOOP TILL NOT BUSY
POP AF ; RECOVER BYTE
OUT (LCD_DATA),A ; SEND IT
RET ; DONE
;
; SEND DATA STRING
; DE=STRING ADDRESS, NULL TERMINATED
;
LCD_OUTDS:
LD A,(DE) ; NEXT BYTE TO SEND
OR A ; SET FLAGS
RET Z ; DONE WHEN NULL REACHED
INC DE ; BUMP POINTER
CALL LCD_OUTD ; SEND IT
JR LCD_OUTDS ; LOOP AS NEEDED
;
; GET DATA BYTE INTO A
;
LCD_IND:
IN A,(LCD_STAT) ; GET STATUS
AND $80 ; ISOLATE BUSY FLAG
JR NZ,LCD_IND ; LOOP TILL NOT BUSY
POP AF ; RECOVER BYTE
IN A,(LCD_DATA) ; GET IT
RET ; DONE
;
; GOTO ROW(H),COL(L)
;
LCD_GOTORC:
PUSH HL ; SAVE INCOMING
LD A,H ; ROW # TO A
LD HL,LCD_ROWS ; POINT TO ROWS TABLE
CALL ADDHLA ; INDEX TO ROW ENTRY
LD A,(HL) ; GET RWO START
POP HL ; RECOVER INCOMING
ADD A,L ; ADD COLUMN
ADD A,LCD_FUNC_DDADR ; APPLY FUNCTION BIT
JR LCD_OUTF ; AND SEND IT
;
; PRINT VALUE OF HL AS THOUSANDTHS, IE. 0.000
;
LCD_PRTD3M:
PUSH BC
PUSH DE
PUSH HL
LD E,'0'
LD BC,-10000
CALL LCD_PRTD3M1
LD E,0
LD BC,-1000
CALL LCD_PRTD3M1
LD A,'.'
CALL LCD_OUTD
LD BC,-100
CALL LCD_PRTD3M1
LD C,-10
CALL LCD_PRTD3M1
LD C,-1
CALL LCD_PRTD3M1
POP HL
POP DE
POP BC
RET
LCD_PRTD3M1:
LD A,'0' - 1
LCD_PRTD3M2:
INC A
ADD HL,BC
JR C,LCD_PRTD3M2
SBC HL,BC
CP E
JR Z,LCD_PRTD3M3
LD E,0
CALL LCD_OUTD
LCD_PRTD3M3:
RET
;
; DATA STORAGE
;
LCD_PRESENT .DB 0 ; NON-ZERO WHEN HARDWARE DETECTED
;
LCD_ROWS .DB $00,$40,$14,$54 ; ROW START INDEX
;
LCD_INIT_SEQ:
.DB LCD_FUNC_SET | %11000 ; FUNCTION SET, 2 LINES, 5X8 FONT
.DB LCD_FUNC_DISP ; DISPLAY OFF
.DB LCD_FUNC_CLEAR ; CLEAR DISPLAY, HOME CURSOR
.DB LCD_FUNC_ENTRY | $02 ; INCREMENT, NO SHIFT
.DB LCD_FUNC_DISP | $04 ; DISPLAY ON, NO CURSOR, NO BLINK
.DB $00 ; TERMINATOR
;
LCD_STR_BAN .DB "RomWBW v", BIOSVER, 0
LCD_STR_CFG .DB "Build: ", CONFIG, 0
LCD_STR_IO .DB "Disk #", 0
LCD_STR_XPU .DB " CPU",0
LCD_STR_SPD .DB "12.345",0
LCD_STR_MHZ .DB " MHz",0
;
LCD_CPU .DW LCD_CPU_Z80
.DW LCD_CPU_Z180
.DW LCD_CPU_Z180K
.DW LCD_CPU_Z180N
.DW LCD_CPU_Z280
;
LCD_CPU_Z80 .DB "Z80",0
LCD_CPU_Z180 .DB "Z180",0
LCD_CPU_Z180K .DB "Z180-K",0
LCD_CPU_Z180N .DB "Z180-N",0
LCD_CPU_Z280 .DB "Z280",0