The concept is to have a LCD screen on an IAS card. This gives me the ability to have a screen for my motherboard projects when I don't have options such as a CGA or VGA card.
This is designed for the 20x4 screen. The 16x2 screen could be easily added with some minor modification to the code.
The 8255 is used to communicate with the LCD screen. It is setup in mode 2.
-Port A is bidirectional and connected to the data lines of the LCD screen.
-Port B is used as an Output.
-PB0->LCD EN
-PB1-> LCD RW
-PB2->LCD RS
-Port C is used in conjunction with Port B for the bidirectional hand shake lines.
-PB4->PC4 STBA (Pulled low to read data from the LCD)
-PB5->PC6 ACKA (Pulled low to write data to the LCD
I wrote the code to be implemented as an interrupt. The 8255 is on I/O port 0X0440.
Interrupt 0x10
AH = 0X00 Setup the 8255 and setup the LCD screen
AH = 0X0E, AL = Char Teletype out, Handles Backspace, Enter, Etc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;INTERRUPT 0X10 SOURCE CODE
;EMM COMPUTERS, 5-JUN-21
;FREE TO USE AND MODIFY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INT10:
CMP AH, 0X00
JZ .VIDEO_MODE
CMP AH, 0X0E
JZ .TELOTYPE
IRET
.LCD_PORT_DATA:
DW 0X0440
.LCD_PORT_CONTROL:
DW 0X0441
.PORT_8255_MODE:
DW 0X0443
.VIDEO_MODE:
PUSH DS
PUSH AX
PUSH DX
;Setup 8255
MOV AL, 0XC0 ;MODE 2 PORT B OUTPUT
MOV DX, [CS:.PORT_8255_MODE]
OUT DX, AL ;WRITE TO 8255 COMMAND PORT
MOV AL, 0X31 ;b00110001
MOV DX, [CS:.LCD_PORT_CONTROL]
OUT DX, AL ;PORT B IS THE LCD CONTROL PORT
;SETUP LCD
MOV AL, 0X06 ;Increment cursor (shift cursor to right)
CALL .WRITE_COMMAND
MOV AL, 0X0F ;Display on, cursor blinking
CALL .WRITE_COMMAND
MOV AL, 0X38 ;2 lines and 5Ă—7 matrix
CALL .WRITE_COMMAND
MOV AL, 0X01 ;Clear display screen
CALL .WRITE_COMMAND
MOV AX, 0X0040 ;BIOS DATA AREA SEGMENT
MOV DS, AX ;SET DS
MOV WORD [0X0050], 0X0000 ;WRITE ZERO TO COL, ROW
POP DX
POP AX
POP DS
IRET
.TELOTYPE:
PUSH CX
PUSH BX
PUSH AX
PUSH DS
CMP AL, 0X0D
JE .ENTER
CMP AL, 0X0A
JE .LINE_FEED
CMP AL, 0X08
JE .BACKSPACE
CALL .WRITE_CHAR
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DS
MOV AL, [0X0050] ;GET CURRENT COL
INC AL ;INC COL
CMP AL, 20 ;CHECK FOR END
JB .NOT_END_COLS ;JMP NOT END
MOV BYTE [0X0050], 0X00 ;IF END WRITE ZERO
MOV AL, [0X0051] ;GET CURRENT ROW
INC AL ;INC ROW
CMP AL, 4 ;CHECK FOR END
JB .NOT_END_ROWS ;JMP NOT END
CALL .SCROLL_UP
JMP .END_WRITE_CHAR
.NOT_END_COLS:
MOV [0X0050], AL
JMP .END_WRITE_CHAR
.NOT_END_ROWS:
MOV [0X0051], AL
JMP .END_WRITE_CHAR
.ROW_INDEX:
DB 0X80, 0XC0, 0X94, 0XD4
;;;;;;;;;;;WORK ING PROGRESS
.BACKSPACE:
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DS
MOV AL, [0X0050] ;GET CURRENT COL
CMP AL, 0X00 ;CHECK FOR COL 0, DONT WANT TO BACKSPACE PAST
JE .END_WRITE_CHAR ;JMP TO END IF 0
DEC AL ;DEC COL
MOV [0X0050], AL ;SAVE COL
MOV BX, .ROW_INDEX ;THIS MOVES THE CURSOR
ADD BL, [0X0051] ;
MOV AL, [CS:BX] ;
ADD AL, [0X0050] ;
CALL .WRITE_COMMAND ;
MOV AL, 0X20
CALL .WRITE_CHAR
JMP .END_WRITE_CHAR
.LINE_FEED:
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DS
MOV AL, [0X0051] ;GET CURRENT ROW
INC AL ;INC ROW
CMP AL, 4 ;CHECK FOR END
JB .NOT_END_ROWS ;JMP NOT END
CALL .SCROLL_UP
JMP .END_WRITE_CHAR
.ENTER:
MOV AX, 0X0040 ;BIOS DATA AREA
MOV DS, AX ;SET DS
MOV BYTE [0X0050], 0X00 ;GET CURRENT COL
JMP .END_WRITE_CHAR
.END_WRITE_CHAR:
MOV BX, .ROW_INDEX ;THIS MOVES THE CURSOR
ADD BL, [0X0051]
MOV AL, [CS:BX]
ADD AL, [0X0050]
CALL .WRITE_COMMAND
POP DS
POP AX
POP BX
POP CX
IRET
.READ_CHAR:
PUSH CX
PUSH DX
MOV DX, [CS:.LCD_PORT_CONTROL]
MOV AL, 0X37
OUT DX, AL
MOV AL, 0X36
OUT DX, AL
MOV AL, 0X27
OUT DX, AL
MOV AL, 0X37
OUT DX, AL
MOV CX, 0X0030
DB 0XE2, 0xFE ;LOOP HOLD FOR A BIT'
MOV DX, [CS:.LCD_PORT_DATA]
IN AL, DX
POP DX
POP CX
RET
.WRITE_CHAR:
PUSH CX
PUSH AX
PUSH DX
MOV DX, [CS:.LCD_PORT_DATA]
OUT DX, AL
MOV DX, [CS:.LCD_PORT_CONTROL]
MOV AL, 0X15
OUT DX, AL
MOV AL, 0X14
OUT DX, AL
MOV CX, 0X0030
DB 0XE2, 0xFE ;LOOP HOLD FOR A BIT'
MOV AL, 0X35
OUT DX, AL
POP DX
POP AX
POP CX
RET
.SCROLL_UP:
PUSH AX
PUSH CX
PUSH SI
PUSH DI
PUSH DS
MOV SI, 0XC0
MOV DI, 0X80
CALL .SCROLL_UP_SUB
MOV SI, 0X94
MOV DI, 0XC0
CALL .SCROLL_UP_SUB
MOV SI, 0XD4
MOV DI, 0X94
CALL .SCROLL_UP_SUB
MOV AL, 0XD4
CALL .WRITE_COMMAND
MOV CX, 20
MOV AL, 0X20
.LINE4:
CALL .WRITE_CHAR
LOOP .LINE4
JMP .END_SCROLL
.SCROLL_UP_SUB:
MOV CX, 20
.LOOP_LINES_1_3:
MOV AX, SI
CALL .WRITE_COMMAND
CALL .READ_CHAR
PUSH AX
MOV AX, DI
CALL .WRITE_COMMAND
POP AX
CALL .WRITE_CHAR
INC SI,
INC DI
LOOP .LOOP_LINES_1_3
RET
.END_SCROLL:
POP DS
POP DI
POP SI
POP CX
POP AX
RET
.WRITE_COMMAND:
PUSH CX
PUSH AX
PUSH DX
MOV DX, [CS:.LCD_PORT_DATA]
OUT DX, AL
MOV DX, [CS:.LCD_PORT_CONTROL]
MOV AL, 0X11
OUT DX, AL
MOV AL, 0X10
OUT DX, AL
MOV CX, 0x0500
DB 0XE2, 0xFE ;LOOP HOLD FOR A BIT'
MOV AL, 0X31
OUT DX, AL
POP DX
POP AX
POP CX
RET