bchiha / Z80_LCD_128x64_Graphics_Library

Full native Z80 Graphics Library for the 128x64 Pixel LCD Screen

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Z80 LCD 128x64 Graphics Library

Full native Z80 Graphics Library for the 128x64 Pixel LCD Screen

The above image demonstrates most of the graphical routines. This includes line drawing, circles, filled shapes, text and pixel drawing.


Files in this repository

  • lcd_128x64_glib.z80 - Z80 Graphics library for the ST7920 Controller
  • lcd_3d_demo.z80 - 3D Frame rotation program
  • lcd_mad_program.z80 - MAD Magazine face drawing
  • lcd_maze_gen.z80 - Maze Generation program
  • ST7920.pdf - ST7920 Datasheet
  • QC12864B.pdf - LCD Screen Datasheet
  • 3D_Fundamentals.JPG - Amstrad Basic 3D Frame article
  • add_on_PCB directory - Add-on Board for the TEC-1 Computer

LCD Screens

There are a few variants of these LCD screens, but all typically use the ST7920 LCD Controller. The LCD Screen that I used is the QC12864B. This screen has two ST7921 Panels (128 x 32) stacked one above the other. Other LCD boards might not do this. If so, the PLOT_TO_LCD function will need to be modified. (future work)

These screens have Graphics Display RAM (GDRAM) and Display Data RAM (DDRAM) areas. GDRAM is for drawing pixels and DDRAM is for displaying text or characters. Both RAM areas __can be__ displayed at the same time.

The Pinout and connection to the Z80 for the QC12864B board is as follows:

Pin Name Description Serial1 Parallel
1 VSS Ground GND GND
2 VDD Power 5v 5v
3 V0 Contrast N/A N/A
4 D/I IR/DR (CS) 5v A74
5 R/W R/W (SID) D0 RD (inverted)2
6 E Enable (SCLK) D1 Port 7 4 (inverted)2
7 DB0 Data N/A D0
8 DB1 Data N/A D1
9 DB2 Data N/A D2
10 DB3 Data N/A D3
11 DB4 Data N/A D4
12 DB5 Data N/A D5
13 DB6 Data N/A D6
14 DB7 Data N/A D7
15 PSB Serial/Para GND 5v
16 NC
17 RST Reset RST RST
18 VEE LCD Drive N/A N/A
19 A Backlight 5v/NC 5v/NC
20 K Backlight GND/NC GND/NC

1 Three communication lines are need for Serial SPI transfer. Pin 4 is Chip Select (CS). As there is only one peripheral connected, this can just be tied high at 5v. Pin 5 is Serial Input Data (SID) and Pin 6 is Serial Clock (SCLK). Pin 5 and 6 are to be latched via a 74HC74 Dual D-Flip Flop. The inputs to the latch are D0 (SID) and D1 (SCLK). Have a look at the schematic below.

2 A CMOS CD4049 Inverter Buffer is needed to invert the input

3 Some 128x64 LCD Screens have different Pinouts than in the table above.

4 I use Port 7 and A7 to connect the LCD screen to the TEC computer. You will need to modify these two constants if connecting the LCD in a different way. See the header part of the lcd_128x64_glib.z80 file to modify these values.

Example Code

To see the library working, have a look at the example code provided. The LDC_3D_demo.z80 has a DISPLAY_MENU label that displays the above picture. Look at this piece of code for better understanding.

Also, see the library and these files in action on YouTube and YouTube!

Thanks to PCBWay for sponsoring this video. ** For $5 off your first order at PCBWay, click here **. PCBWay Printed Circuit Boards the Easy Way.

Programming Guide

The Graphics Library has routines that interact with the LCD Screen. Routines are called via a Jumpblock. These routines are at the start of the Graphics Library. By default the library is placed at location 0x3000. If this location is changed, the start locations of the functions are also to be changed.

For example, to initalise the LCD, do something like this:

    CALL 3000H

Or to make it more readable create a label and do this:

    G_INIT_LCD:	EQU 3000H
    CALL G_INIT_LCD

In summary, here are the routines and their default address locations:

Address Routine Description
3000H INIT_LCD Initalise the LCD
3003H CLEAR_GBUF Clear the Graphics Buffer
3006H CLEAR_GR_LCD Clear the Graphics LCD Screen
3009H CLEAR_TXT_LCD Clear the Text LCD Screen
300CH SET_GR_MODE Set Graphics Mode
300FH SET_TXT_MODE Set Text Mode
3012H DRAW_BOX Draw a rectangle between two points
3015H DRAW_LINE Draw a line between two points
3018H DRAW_CIRCLE Draw a circle from Mid X,Y to Radius
301BH DRAW_PIXEL Draw one pixel at X,Y
301EH FILL_BOX Draw a filled rectangle between two points
3021H FILL_CIRCLE Draw a filled circle from Mid X,Y to Radius
3024H PLOT_TO_LCD Display the Graphics Buffer to the LCD Screen
3027H PRINT_STRING Print Text on the screen in a given row
302AH PRINT_CHARS Print Characters on the screen in a given row and column
302DH DELAY_US Microsecond delay for LCD updates
3030H DELAY_MS Millisecond delay for LCD updates
3033H SET_BUF_CLEAR Clear the Graphics buffer on after Plotting to the screen
3036H SET_BUF_NO_CLEAR Retain the Graphics buffer on after Plotting to the screen
3039H CLEAR_PIXEL Clear one pixel at X,Y
303CH FLIP_PIXEL Invert one pixel at X,Y
303FH LCD_INST Send a parallel or serial instruction to LCD
3042H LCD_DATA Send a parallel or serial data to LCD
3045H SER_SYNC Send serial synchronize byte to LCD

Here is the detailed routine descriptions with examples

INIT_LCD

Initalise the LCD Screen. Needed to be called before any other routine

  • Entry: No conditions
  • Exit: All registers corrupt
    CALL INIT_LCD       ;Initalise the LCD Screen

CLEAR_GBUF

Clear the Graphics Buffer. The Graphics Buffer or GBUF is the internal memory area that contains pixel data for the LCD. The drawing routines write to the GBUF. Once all pixels are set, this buffer is then plotted to the LCD with the PLOT_TO_LCD Routine. Clearing the GBUF is a good way to ensure the pixel area is empty.

  • Entry: No conditions
  • Exit: All registers corrupt
    CALL CLEAR_GBUF     ;Clears the Graphics Buffer

CLEAR_GR_LCD

Clear the Graphics LCD Screen. This routine clears the GDRAM or Graphics screen on the LCD.

  • Entry: No conditions
  • Exit: All registers corrupt
    CALL CLEAR_GR_LCD     ;Clears the Graphics LCD Screen

CLEAR_TXT_LCD

Clear the Text LCD Screen. This routine clears the DDRAM or Text screen on the LCD.

  • Entry: No conditions
  • Exit: All registers corrupt
    CALL CLEAR_TXT_LCD    ;Clear the Text LCD Screen

SET_GR_MODE

Set the LCD to Graphics Mode. This routine puts the LCD in Graphics mode (Extended Instructions) and any further instructions to the LCD will be for the graphics screen. It only needs to be called once if multiple graphics routines are used.

  • Entry: No conditions
  • Exit: AF, DE corrupt
    CALL SET_GR_MODE      ;Set Graphics Mode

SET_TXT_MODE

Set the LCD to Text Mode. This routine puts the LCD in Text mode (Basic Instructions) and any further instructions to the LCD will be for the text screen. It only needs to be called once if multiple text routines are used.

  • Entry: No conditions
  • Exit: AF, DE corrupt
    CALL SET_TXT_MODE     ;Set Text Mode

DRAW_BOX

Draws a single-line box between two points X1,Y1 and X2,Y2.

  • Entry:
    • B = X1-coordinate (0-127)
    • C = Y1-coordinate (0-63)
    • D = X2-coordinate (0-127)
    • E = Y2-coordinate (0-63)
  • Exit: AF, HL corrupt
    LD BC, 0020H 	;X0, Y0
    LD DE, 7F3FH 	;X1, Y1
    CALL DRAW_BOX ;Draw a outline box from X0,Y0 to X1,Y1

DRAW_LINE

Draws a straight line between X1,Y1 and X2,Y2. Uses Bresenham Line drawing algorithm

  • Entry:
    • B = X1-coordinate (0-127)
    • C = Y1-coordinate (0-63)
    • D = X2-coordinate (0-127)
    • E = Y2-coordinate (0-63)
  • Exit: All registers corrupt
    LD BC, 0010H 	;X0, Y0
    LD DE, 7F30H 	;X1, Y1
    CALL DRAW_LINE

DRAW_CIRCLE

Draws a circle from a mid point to a radius. Uses Bresenham Circle drawing algorithm

  • Entry:
    • B = Mid-X-coordinate (0-127)
    • C = Mid-Y-coordinate (0-63)
    • E = Radius (1-63)
  • Exit: All registers corrupt
    LD BC, 0818H 	;Mid X, Mid Y
    LD E, 08H 		;Radius
    CALL DRAW_CIRCLE

DRAW_PIXEL

Draws a single Pixel.

  • Entry:
    • B = X-coordinate (0-127)
    • C = Y-coordinate (0-63)
  • Exit: AF, HL corrupt
    LD BC, 4020H 	;X,Y
    CALL DRAW_PIXEL

FILL_BOX

Draws a filled box between X1,Y1 and X2,Y2.

  • Entry:
    • B = X1-coordinate (0-127)
    • C = Y1-coordinate (0-63)
    • D = X2-coordinate (0-127)
    • E = Y2-coordinate (0-63)
  • Exit: AF, HL corrupt
    LD BC, 0020H 	;X0, Y0
    LD DE, 7F3FH 	;X1, Y1
    CALL FILL_BOX ;Draw a filled box from X0,Y0 to X1,Y1

FILL_CIRCLE

Draws a filled circle from a mid point to a radius. This routine iteratively calls the DRAW_CIRCLE routine increasing the radius until is equals the register E. There might be gaps in the filled circle, but hey it looks just like what you get on a BASIC program.

  • Entry:
    • B = Mid-X-coordinate (0-127)
    • C = Mid-Y-coordinate (0-63)
    • E = Radius (0-63)
  • Exit: All registers corrupt
    LD BC, 1018H 	;Mid X, Mid Y
    LD E, 08H 		;Radius
    CALL FILL_CIRCLE

PLOT_TO_LCD

This routine draws the Graphics Buffer or GBUF to the Graphics LDC screen. It is usually called after one of the drawing routines is called.

  • Entry: No conditions
  • Exit: All registers corrupt
    CALL PLOT_TO_LCD     ;Display the Graphics Buffer to the LCD Screen

PRINT_STRING

Prints ASCII text on the screen on a given row. There are 4 text rows on the LCD screen. The text to be displayed is to be defined directly after the CALL routine and is to be terminated with a zero.

Here are the 128 characters that are available. Conveniently, Alphanumeric characters align with the ASCII table.

  • Entry:
    • A = row number (0-3)
    • Text = "String" on the next line, terminate with 0
  • Exit: All registers corrupt
    LD A,2
    CALL PRINT_STRING
    DB 02H, " This Text ", 1BH ,00H

    ; This will display a smiley face, "This Text" 
    ; and a left arrow on row 2 of the LCD screen.

PRINT_CHARS

Print Characters on the screen in a given row and column. This routine is similar to the one above but character row and column placement can be made. Characters to be printed are to be terminated with a zero.

Note: Even though there are 16 columns, only every second column can be written to and two characters are to be printed. IE: if one character is to be printed in column 2, then set B=0 and print " x", putting a space before the character.

  • Entry:
    • B = column (0-7)
    • C = row (0-3)
    • HL = start address of text data
  • Exit: All registers corrupt. HL will be at the end of the text data table.
    LD HL, MENU_DATA ;Load HL with Menu data table
    LD BC, 0102H 	;Column 1, Row 2
    CALL PRINT_CHARS ;Display Text
    ...
    MENU_DATA:
    DB "Hello!",0

DELAY_US

Delay loop for LCD to complete its instruction. Every time a command is sent to the LDC, it requires a small amount of time to complete that operation. IE: setting extended instruction mode. Time needed for most operations is defined in the LDC specification. It is usually around 72us. This routine is used internally, but can also be used here. The delay time depends on how fast the CPU is running at. A variable V_DELAY_US can be changed to suit your LDC setup. I found that my LDC can handle a delay of 0004H.

This routine will delay the cpu by V_DELAY_US and can be used if outputting instructions to the LDC directly.

  • Entry: No conditions
  • Exit: DE, AF corrupt
    LD A, 02H       ;Home command
    OUT (LCD_IR), A ;Move the cursor to the top of LCD
    CALL DELAY_US   ;Delay the CPU by V_DELAY_US

DELAY_MS:

This is the same as the above routine, but the delay can be software controlled.

  • Entry: DE = delay value
  • Exit: DE, AF corrupt
    LD A, 01H       ;Clear command
    OUT (LCD_IR), A ;Clear the LCD screen
    LD DE, 0050H    ;Longer Delay
    CALL DELAY_MS   ;Delay the CPU by DE

SET_BUF_CLEAR

On every PLOT_TO_LCD, Clear the graphics buffer GBUF. Calling this routine will clear the graphics buffer on every draw to LCD. This is useful if doing animation that require a new drawing to be display on every plot or frame.

  • Entry: No conditions
  • Exit: AF corrupt
    CALL SET_BUF_CLEAR    ;Clear GBUF on plot

SET_BUF_NO_CLEAR

Do not clear the graphics buffer on every PLOT_TO_LCD. Calling this routine will not clear the graphics buffer on every draw to LCD. This is useful adding graphics data to an existing drawing. This is used in the MAD example, where lines are being continually drawn to the screen until the whole picture is complete.

  • Entry: No conditions
  • Exit: AF corrupt
    CALL SET_BUF_NO_CLEAR    ;Do not clear GBUF on plot

CLEAR_PIXEL

Removes or clears a single Pixel.

  • Entry:
    • B = X-coordinate (0-127)
    • C = Y-coordinate (0-63)
  • Exit: AF, HL corrupt
    LD BC, 4020H 	;X,Y
    CALL CLEAR_PIXEL

FLIP_PIXEL

Inverts a single Pixel. If the Pixel is on, it will turn off and if the Pixel is off, it will turn on.

  • Entry:
    • B = X-coordinate (0-127)
    • C = Y-coordinate (0-63)
  • Exit: AF, HL corrupt
    LD BC, 4020H 	;X,Y
    CALL FLIP_PIXEL

LCD_INST

Send an instruction to the LCD. This routine will send the value of Register A to the Instruction Register of the LCD Screen. The routine is universal regardless of Serial or Parallel connection. For Serial connection, this will also send the Synchronization Byte.

  • Entry:
    • A = Value to send
  • Exit: AF, DE (Parallel only) corrupt
    LD A, 38H   ; Clear Screen 
    CALL LCD_INST

LCD_DATA

Send data to the LCD. This routine will send the value of Register A to the Data Register of the LCD Screen. The routine is universal regardless of Serial or Parallel connection.
For Serial connection, a call to SER_SYNC is to be done prior. This is because only one Synchronization Byte is needed for multiple (up to 256) Data bytes.

  • Entry:
    • A = Value to send
  • Exit: AF, DE (Parallel only) corrupt
    ;Parallel example
    LD A, "B"   ; The letter B
    CALL LCD_DATA

SER_SYNC

Send a Serial Synchronization Byte to the LCD. This routine is only needed for Serial connection AND prior to an LCD_DATA call. The Register A must be 02H

  • Entry:
    • A = 02H
  • Exit: AF corrupt
    LD A, 02H 
    CALL SER_SYNC   ;Data Block Sync
    LD A,  "T"      ;Letter T
    CALL LCD_DATA
    LD A,  "E"      ;Letter E
    CALL LCD_DATA
    LD A,  "C"      ;Letter C
    CALL LCD_DATA

Future Work

Displaying Text on this screen is clumsy as text can only be placed at defined locations. I plan to make a graphics font of 128 characters that is smaller in size, possibly 5x7 and can be placed anywhere on the screen.

Some LCD screens have a slightly different way data is written to them in terms of how the screens are laid out. The QC12864B as two ST9721 screens placed on top of each other, but are connected in series. Plotting to the LCD routine will need to be changed for other LCD screen layouts.

About

Full native Z80 Graphics Library for the 128x64 Pixel LCD Screen

License:MIT License