Close
0%
0%

uPD7220 Retro Graphics Card (and VGA hack)

Making an 80s GDC run for the first time in decades, and my first real hack on hackaday.io

Public Chat
Similar projects worth following
The uPD7220 is a fascinating chip from the 1980s. It was meant to control CRT displays and provide graphics capabilities, but I have found a way to make it output a valid VGA signal.

It is really complex, so understanding it takes a lot of studying of the sparse available information (and virtually no example code), but most certainly worth it. I intend on sharing my understanding and lessons here so more people can more easily use thise awesome chip!!!

I plan on posting more on this when I can!

Resources

Datasheet: http://www.vintagecomputer.net/fjkraan/comp/qx10/doc/nec7220.pdf

This is best used for designing a circuit with the uPD7220 and for understanding how to initialize and draw with it.

Programming Manual? : http://www.vintagecomputer.net/fjkraan/comp/qx10/doc/nec7220.pdf

This will explain how to send commands and generally how the CPU to uPD7220 interface works.

My Z80 code: https://github.com/NuclearManD/z80-code/blob/master/G00nOS/upd7220.z80

This is the graphics driver I am writing for my Z80 computer.  It's good example code, but it currently has numerous limitations, so look at the arduino sketch I uploaded to this project as well.

Why?

I want a graphics card for my Z80 computer so it can operate completely independently, as in, without a serial monitor.

I don't want to use a propeller chip or other powerful microcontroller because those chips don't go with the rest of my Z80 computer.  Besides, something about this design just feels really... pure, I suppose.  Clean.

NOTE: The information provided in this details section is very condensed.  There is much, much more to be understood.  I recommend STUDYING the documents I linked and uploaded.  The following information is just a brief overview.

How does the hardware work?

The uPD7220 generates VSYNC, HSYNC, and BLANK signals.  It generates a few other signals for the memory interface, but these must be interpreted.  The uPD7220 address and data lines share a bus, so the address has to be latched.  Also, to write to memory, there are special cycles which require external hardware to generate a write enable.

There are two clocks.  The pixel clock, which is currently 8Mhz, is used to output pixels.  The uPD7220 takes lower frequencies, so the pixel clock is halved to make the 2xWCLK clock, which is sent to the uPD7220.

The uPD7220 reads the pixel data onto the data bus, where it is latched every fourth pixel clock rising edge.  The shift registers output pixel data while the uPD7220 prepares for the next set of pixels.

The port which goes to the system microprocessor is directly connected to the uPD7220, except for two OR gates which generate the WE and RD signals.

How does the software work?

There are two ports that can be written/read on the uPD7220:

READWRITE
0Status registerParameter load
1Data to CPU FIFOCommand load

Before each write, the status register FIFO full flag must be checked first.  If the FIFO is full, then a write will create undefined behaviour.

The uPD7220 must be initialized properly first.  If it is not initiallized right, then random commands will crash it when it is least expected.  These commands all must be used in initialization:

0x00 : reset (followed by graphics parameters)

0x47 : pitch (aka tell the GDC the number of horizontal words there are per line)

0x70 : set up PRAM so drawing operations work

0x4B : CCHAR : set up character parameters.  

0x46 : set the zoom.  Otherwise zoom may be random.

0x6B : start the display!  YEET!

video_timing_calculator.py

Python3 program to create valid VGA video timings for the uPD7220. Use it to generate values to plug into videoconf.h

plain - 5.11 kB - 04/04/2019 at 06:05

Download

uPD7220_card_ctrl.ino

An arduino sketch used to control my graphics card. Use it as example code, a test program, or as a base for your own driver!

ino - 3.77 kB - 04/04/2019 at 06:04

Download

videoconf.h

Video configuration settings for the uPD7220. Goes with uPD7220_card_ctrl.ino

plain - 1.45 kB - 04/04/2019 at 06:04

Download

graphics_card_design.zip

This design partially works. The output from the shift registers should be q3, but q0 is used instead (a mistake). Before using either be prepated to modify the PCB or fix the design.

x-zip-compressed - 797.96 kB - 04/04/2019 at 05:30

Download

uPD7220-uPD7220A_User_Manual_Dec85.pdf

In case this disappears from the rest of the Internet

Adobe Portable Document Format - 3.54 MB - 04/04/2019 at 01:40

Preview
Download

  • 1 × uPD7220 Super Rad 1980s GDC
  • 4 × 74173 Logic ICs / Flip-Flops, Latches, Registers
  • 4 × 1k Resistor
  • 1 × 10k Resistor
  • 1 × 8,10, or 12 Mhz DIP8 Oscillator

View all 13 components

  • Zilog Made a Clone!

    Dylan Brophy04/18/2019 at 01:47 0 comments

    I bought this chip off of Ebay.  It seems that Zilog created a uPD7220 clone - and it works!  These chips seem to be rather rare and information on them is scarce.  I did manage to deduce that there were two variants of chips:  one operating at 6Mhz, and one at 8Mhz.  I got the 8Mhz one and tried doubling my pixel clock to 16Mhz (the GDC uses a halved clock).  That worked too, and that allowed me to make a more stable video signal.  I had a problem with the 8Mhz pixel clock where there was not time to output a valid video signal.  Now I can output more pixels than I have VRAM for.

    The chip is also a super pretty Zilog gem <3

  • Rendering characters!

    Dylan Brophy04/05/2019 at 19:41 0 comments

    I've managed to make my card render characters!  I used the Z80 computer this project was originally intended for this time, instead of the Arduino testbench.

    There is not a font yet, so I just rendered a bunch of smiley faces and tested that the program could keep track of the cursor position.

    Smiley faces are a good way to do testing.

    It's working very well, but I would like to render things a bit faster.  I think the Z80 math routines run slow however, for calculating cursor positions and colors.

    It doesn't help that my card has 16 colors - it appears that the uPD7220 was designed to just do black and white.  This means that I have to send a few more commands to the uPD7220 to select a group of bits for a pixel (multiple colors) instead of just one bit (black and white).  The uPD7220 automatically selects a single bit when a command is sent to set the VRAM address, but my program must select multiple.

    Here is my graphics driver for the Z80: https://github.com/NuclearManD/z80-code/blob/master/G00nOS/upd7220.z80

    You may need to look at some of the other files, but all graphics functions are there (er, rather, the ones I've written thus far).

  • Finally on HaD after more than a year! And finally working!

    Dylan Brophy04/04/2019 at 06:29 0 comments

    Over a year ago I wanted a graphics card for my Z80 computer.  I made a prototype with the uPD7220, but I never got it working.  Until...

    As it turned out, I made TONS on mistakes in the original design.  There are issues with the new design too, but it works well enough (after a hack, more on that later). Anyway, after playing with the first prototype and trying various hacks, I ended up with a valid VGA signal!

    I don't think the uPD7220 was ever supposed to output VGA, considering VGA was introduced about four years after the uPD was, so it's awesome that it can output a VGA signal.

    After studying the uPD datasheet and my schematic in depth, I eventually found most of the problems and ended up with my second prototype (which I am using now).  I've managed to get it to do the basic things I need it to do.  Getting from basic initialization to drawing pixels was very difficult, especially with such a complex device and no example code/libraries, but it was definately worth it.  I now want to share what I've learned about it so that more people can use this GDC (GDC = Graphic Display Controller).

    I plan on adding more and more information to this project so others can use my work as a reference.  I also am going to create a Z80 driver, which I will post here as well.

View all 3 project logs

  • 1
    Software: Understanding the interface between the uPD7220 and the CPU

    I am writing this expecting the reader to have a strong knowledge of computer hardware.  You have been warned.

    The uPD7220 occupies two addresses in IO space and has an 8-bit data bus.  There are also the WE and RD enables, but there is no chip select (WE and RD should be generated with that in mind).

    uPD7220 write ports:

    0: Parameters

    1 : Commands

    uPD7220 read ports:

    0: Status register

    1 : Data to CPU

    Internal FIFO, and properly writing to it

    The two write ports both go to the same FIFO inside the uPD7220.  This FIFO can fill up, but there are bits in the status register which indicate if the FIFO is empty or full.  When writing to the uPD7220, the program must ALWAYS first check if that FIFO is full - if it is, then the program has to wait for there to be space.

    Sending commands

    The command byte is always sent first, into port 1.  After this, parameters are sent to port 0.  Some commands have quirks and nuances, and need some extra attention.  For instance, my uPD7220 can crash if my program does not wait for the FIFO to empty after sending a WDAT command.  I have not had this issue with any other command.  More on commands later, just introducing the proper way to send them.

    Reading data

    There is a flag in the status register to indicate that data is ready to be read.  When a command is sent to read data, this flag will be set shortly after, and then it is safe to read from port 1 (Data to CPU).  Always check the data ready flag before reading from port 1

    A quick word on the DMA flag

    If you are not using DMA or have not sent a DMA command and this flag is set, then something probably went wrong.  A command was likely sent incorrectly, or setup skipped a step.  If that is the case, the uPD7220 will probably crash in the next few commands (if it hasn't already).  Basically this means your program is doing something wrong, as in not sending a command needed for initialization or sending a command incorrectly.

    Status Register Flags

    BITNAMEDESCRIPTION
    0Data ReadyThe CPU can now read at least a byte from uPD7220 port 1
    1FIFO FullThe command/parameter FIFO is full, do not write
    2FIFO EmptyThe command/parameter FIFO is empty
    3Drawing in progressThe uPD7220 is currently executing a drawing operation
    4DMA ExecuteThe uPD7220 thinks a DMA operation is in progress
    5Vertical SyncIndicates that vertical retrace is active
    6Horizontal BlankIndicates that horizontal blanking is active
    7Light Pen DetectIndicates that a valid Light Pen address can be read

    I'm not sure that anyone would use the light pen feature, and I myself am not really researching it.

View all instructions

Enjoy this project?

Share

Discussions

Ken Yap wrote 04/04/2019 at 13:30 point

👍 Good on you for tackling this old chip. I have one (D2) in its very distinctive ceramic package. I must have pulled it from a microcomputer. If anybody wants it for the cost of postage, PM me.

  Are you sure? yes | no

Dylan Brophy wrote 04/04/2019 at 17:49 point

Thanks!  The D2s are really good too, can reach 8Mhz if I remember correctly (mine can only reach 6Mhz), so maximum 16Mhz pixel clock.  Where does one get old microcomputers?

  Are you sure? yes | no

Ken Yap wrote 04/04/2019 at 21:54 point

I used to go dumpster diving.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates