-
1Software: 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
BIT NAME DESCRIPTION 0 Data Ready The CPU can now read at least a byte from uPD7220 port 1 1 FIFO Full The command/parameter FIFO is full, do not write 2 FIFO Empty The command/parameter FIFO is empty 3 Drawing in progress The uPD7220 is currently executing a drawing operation 4 DMA Execute The uPD7220 thinks a DMA operation is in progress 5 Vertical Sync Indicates that vertical retrace is active 6 Horizontal Blank Indicates that horizontal blanking is active 7 Light Pen Detect Indicates 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.
-
2Initializing the uPD7220
You can read the programming manual to get a detailed understanding of how to program the uPD7220, but I will also provide an abridged version here. Once the card's configuration register is set, the uPD7220 must be initialized. The uPD7220 requires a sequence of commands to be sent to set it up:
- A reset command (write 0x00 to address 0x01)
- This must be followed by parameter bytes, described below
- Setting the video mode to master (write 0x6f to address 0x01)
- Configuring the pitch
- Initializing the PRAM
- PRAM is some internal memory in the uPD7220, which configures how it accesses memory, and probably some other things
- CCHAR command to configure the character characteristics
- Disabling zoom (write 0x46 to 0x01, then 0x00 to 0x00)
- Starting the display (write 0x6B to 0x01)
- Disable blanking (write 0x0D to 0x01)
My driver also seems to issue a FIGS command at the end of startup, but this may not be necessary.
Each command starts with a write to address 0x01, and for each parameter a write to address 0x00 follows. Each command I describe will proceed this way, with the first byte being the command byte written to address 0x01, and all following bytes being parameters written to address 0x00. At the end I will have some example code in C which provides as both an example and an additional explanation.
The first command is the reset command; here is the format:
The Reset Command Address Value / Description 1 0x00 0 Operation mode. Discussed below. 0 Horizontal display words minus two. Must be an even number. This is equal to ((horizontal_pixels / 4) - 2). Wide mode does not affect this. 0 Lower 5 bits are the HSync width minus 1, in words. Upper 3 bits are the lower 3 bits of the VSync width. 0 Lower 2 bits are the upper 2 bits of the VSync width. Upper 6 bits are the horizontal front porch width minus 1. 0 Horizontal back porch width minus one. Upper two bits must be zero. 0 Vertical front porch width minus one. Upper two bits must be zero. 0 Number of display lines per frame, lower 8 bits. 0 Lower 2 bits are the upper 2 bits of the number of display lines per frame. Upper 6 bits are the vertical back porch length. Note that the vertical field sizes do not have numbers subtracted from them, but the horizontal field sizes have one or two subtracted from them. If this description is confusing, the uPD7220 manual provided above does contain a nice illustration you may consider looking at.
The operation mode is a bitmask, which controls interlacing, character or graphic mode, as well as DRAM refresh and if drawing is allowed during an active display cycle. Here are some of the options that one can OR together to control the operation mode:
Operation control bits Bitmask Selected Option 0x00 Leave bits 5 and 1 zero to have mixed character and graphics mode. 0x02 Enables just graphics mode 0x20 Enables just character mode 0x00 Leave bits 3 and 0 zero to disable interlacing 0x08 Enables interlacing 0x09 Enables "Interlaced repeat field for character displays". Read the manual for more information. 0x04 Enables DRAM refresh cycles - not used on this uPD7220 card, as static RAM is used. 0x10 Disables drawing during active display time. Enabling this is recommended. Generally 0x12 is a good setting for this card, unless you intend on using character mode. 0x10 will also work as a good mode.
The second command one must send is 0x6f, again written to address 0x01, and it does not take any parameters. The third command is the PITCH command:
The Pitch Command Address Value / Description 1 0x47 0 Number of memory words per line. Usually the same as the number of display words per line. Generally equal to (horizontal_pixels / 4). The only reason it would differ, is if the The fourth command is a PRAM command, which writes data to the uPD7220 parameter RAM. Here is a recommended usage of the command (although other usages are possible, again read the manual for more info):
The PRAM Command Address Value / Description 1 0x70 (starts PRAM write at PRAM byte 0) 0 Display partition 1 starting address (lower 8 bits) - it is recommended to leave this as zero. 0 Display partition 1 starting address (bits 8-16) - it is recommended to leave this as zero. 0 Lower 2 bits are the display partition 1 starting address (upper 2 bits). Upper 4 bits are the lower 4 bits of the display partition length, in horizontal lines (NOT words). Bits 2 and 3 should be left as zeros. 0 Lower 6 bits are the upper 6 bits of the image partition length, in horizontal lines (NOT words). Bit 6 (0x40) indicates it is a graphics area, otherwise it is a character area if in mixed mode. Bit 7 (0x80) enables wide mode - ensure to set this bit if you are using wide mode. The parameter RAM has more variables, but only these really need to be specified. There is another display partition that one can use, and configuration options for drawing and characters, later in the PRAM.
If your display mode uses wide mode, then be sure to set the MSB of the fourth parameter byte of this command, otherwise the memory access will be incorrect for wide mode.
Next, the CCHAR command is used to define the cursor and character characteristics:
The CCHAR Command Address Value / Description 1 0x4B 0 Setting the MSB will enable the cursor in character mode. The lower 5 bits are the number of lines per character row minus one. My driver leaves this byte as zero. 0 Lower 5 bits define the cursor top line number in the row. Bit 5 makes the cursor steady if set, or blinking if reset. Upper two bits are the lower two bits of the blink rate. My driver leaves this byte as 0xC0. This is sufficient for non-interlaced modes, but interlaced modes require this command to get a third byte.
Zoom must be disabled with a 0x46 write to address 0x01, followed by writing 0x00 to address 0x00. At this point we can finally enable the display and disable blanking by writing commands 0x6B, then 0x0D, to address 0x01.
My driver executes a FIGS command last, although this probably is not necessary. Just in case, here is the command sequence:
- 0x4C to address 0x01
- 0x02 to address 0x00
- 0x00 to address 0x00
- 0x00 to address 0x00
Here is my code which executes this exact sequence:
void setup_upd7220() { // Reset command write(1, 0); write(0, 0x10); // operation mode: draw only during blanking write(0, HORIZ_WORDS - 2); write(0, (VERT_SYNC << 5) | (HORIZ_SYNC - 1)); write(0, ((HORIZ_FRONT_PORCH - 1) << 2) | (VERT_SYNC >> 3)); write(0, (HORIZ_BACK_PORCH - 1) & 63); write(0, VERT_FRONT_PORCH & 63); write(0, VERT_PIXELS & 255); write(0, (VERT_BACK_PORCH << 2) | (VERT_PIXELS >> 8)); // set master video mode write(1, 0x6f); // set pitch write(1, 0x47); write(0, HORIZ_WORDS); // set some PRAM values write(1, 0x70); write(0, 0x00); write(0, 0x00); write(0, (VERT_PIXELS << 4) & 255); write(0, (VERT_PIXELS >> 4) | (WIDE_MODE ? 8 : 0)); // Set character and cursor characteristics write(1, 0x4B); write(0, 0x00); write(0, 0xC0); // set zoom write(1, 0x46); write(0, 0x00); // Enable the display write(1, 0x6b); // Disable blanking write(1, 0x0D); // This is probably not necessary write(1, 0x4c); write(0, 0x02); write(0, 0x00); write(0, 0x00); }
- A reset command (write 0x00 to address 0x01)
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.