Projects Research & Design Hub

Making a Retro Dumb Terminal

Written by Brian Beard

8-bit Design for 8-bit Projects

Because he builds a lot of 8-bit MCU-based projects, Brian wanted a monitoring and debugging platform right-sized for 8-bit systems. With that in mind, he decided to build the Retro Dumb Terminal, a classic ASCII dumb terminal built with 8-bit MCUs, some programable logic and simple user interface gear.

  • How to build a classic ASCII dumb terminal built with 8-bit MCUs

  • How VGA displays work

  • What are the thee parts of the horizontal and vertical blanking signals?

  • How ASCII code translates to video pixels

  • How VGA creates colors and blanking

  • How to control the video SRAM

  • How to design the keyboard interface

  • How the software works

  • Microchip 8-bit PIC16F1823 MCU

  • Microchip 8-bit PIC16F1788 MCU

  • ATF16V8 generic array logic (GAL) chips


  • VGA monitor

  • PS/2 keyboard

  • Maxim Integrated MAX232 interface chip

  • Simco 150X75 case

Ialways have at least one 8-bit development project on my workbench. The first thing I get working on any new prototype is the serial port. Once that’s working, I use my suite of embedded assembly language routines to monitor and debug via the serial port. I don’t have a spare laptop I can dedicate to every development project, so I wanted another solution. All I need to do is enter selections to exercise different software routines and observe the results—I don’t need data storage or to transfer files. A PC is serious overkill for this. All I need is a dumb terminal, so I decided to build one.

Because I’m an 8-bit developer, it had to be an 8-bit system and not a Raspberry or other 32-bit board. The result is what I call the RDT64 (Retro Dumb Terminal): a classic ASCII dumb terminal. Thanks to modern components and programmable logic, it packs a lot of functionality into a small package. It contains five programmable chips: two 8-bit Microchip Technology PIC microcontrollers (MCUs), two ATF16V8 generic array logic (GAL) chips and an EPROM. It uses a VGA monitor for the display and a PS/2 keyboard for input. Several of the ideas for the RDT64 came from the first computer I built, a digital group Z80 and its TVC-64 video card.


Anyone who has worked with computer displays knows there is not one single VGA (Video Graphics Array) display format. So called “standard VGA” has an active region 640-pixels wide by 480-pixels high. DOS text mode’s active region is 640-pixels wide by 400-pixels high—80 characters × 25 lines. The RDT64 has an active region 512-pixels wide by 400-pixels high—64 characters × 25 lines.

The horizontal timing specifications for the Standard, Text mode and RDT64 VGA are shown in Table 1 and the accompanying diagram (Figure 1). The vertical timing specifications for the Standard, Text mode and RDT64 VGA are shown in Table 2 and the accompanying diagram (Figure 2).

TABLE 1 AND FIGURE 1 – Horizontal timing specs
TABLE 2 AND FIGURE 2 – Vertical timing specs

VGA controllers are based on two counters—a horizontal or pixel counter, and a vertical or line counter. For a good reference on this subject, see “Build a VGA Monitor Controller” by Enoch Hwang (Circuit Cellar 172, November, 2004) [1]. The horizontal counter (74HC4040, U11) counts the pixels in each line. Refer to the schematics in Figure 3. Programmable logic (ATF16V8, U12) starts and ends the horizontal blanking signal (HBLANK) and the horizontal synchronization signal (HSYNC) at specific values of the pixel count. Figure 4 shows the structure of a VGA frame and the signals that define it.

FIGURE 3 – RDT64 horizontal logic and ASCII to pixels schematic
FIGURE 4 – VGA frame diagram.

Both the horizontal and vertical blanking signals span three sub-parts: The Front Porch, the Sync and the Back Porch. At the upper left corner, both counters equal zero. As the first scan line is sent to the VGA monitor, the pixel counter increases. When the pixel counter equals 512, the HBLANK signal begins and the active (displayed) region of the line ends.

When the pixel count equals 528, the HSYNC pulse begins—it ends when the pixel count equals 600. Finally, when the pixel count reaches 640, the pixel counter is reset to zero, and the line counter is incremented. Note that the HBLANK signal does not go to the VGA monitor. It is used to disable the video output of the RDT64.

In a similar fashion, the vertical counter (74HC4040, U6) counts the scan lines in each screen. Refer to the schematics in Figure 5. Programmable logic (ATF16V8, U7) starts and ends the vertical blanking signal (VBLANK) and the vertical synchronization signal (VSYNC) at specific values of the line count. When the line counter equals 400, the VBLANK signal begins and the active (displayed) region of the frame ends.

FIGURE 5 – RDT64 vertical logic and address multiplexor schematic

When the line count equals 412, the VSYNC pulse begins, and it ends when the line count equals 414. Finally, the line counter is reset to zero, when the line count reaches 449. VBLANK does not go to the VGA monitor, HBLANK and VBLANK are ORed together in U7 to produce the BLANK signal. BLANK is used to gate the Red, Green and Blue video signals to the VGA connector (J3).


The ASCII code for each of the 1,600 characters on the screen are stored sequentially in the 6,116 (2k× 8) SRAM chip (U5), and the pixel map for each of the 256 possible ASCII codes is stored in the 2764 (8k×8) EPROM (U4). Refer to the schematics in Figure 3. The character EPROM stores a 16×8-pixel character map for each ASCII code. Therefore, each ASCII character occupies 16 addresses, which are the 16 rows, or scan lines, in each character.

Let’s look at what happens at the start of a new frame, where the pixel and line counters both equal zero. The 11 address inputs of the SRAM are controlled by the counters—pixel count bits 3 to 8 (PQ3-PQ8) connect to A0-A5, respectively. These six bits count the 64 (0-63) characters in each line. Line count bits 4 to 8 (LQ4-LQ8) connect to A6-A10 respectively. These 5 bits are the character lines, and each character line is composed of 16 scan lines. So, for the start of the first line, SRAM A0-A10 are all zero and the SRAM will output the ASCII code for the first character. We’ll deal with how that ASCII code gets into the SRAM later.

The 8-bit ASCII value from the SRAM connects to A4-A11 of the character EPROM. A0-A3 are connected to line count bits LQ0-LQ3, respectively. Essentially A4-A11 select the ASCII character, and A0-A3 select the scan line in that character’s map—0000 is the top row and 1111 is the bottom. The eight bits in the selected character row appear at the EPROM output, and are connected to the parallel data inputs of the 74HC165 parallel-to-serial shift register (U3). The data are loaded into the shift register by the parallel load (PLD\) signal from U12. PLD\ pulses on every eighth bit of the 20MHz clock, while an inverted clock signal clocks the bits out of the serial shift register. These serialized bits are the PIXELS seen on the VGA monitor.

At the end of the horizontal line, following the Horizontal Back Porch, U12 pulses PQ_CLR, which resets the pixel counter and increments the line counter. The process repeats, but this time LQ0-LQ3 is 0001, so the character EPROM will output the second row in the character map. This continues until the end of the video frame, when both the pixel and line counters are reset to zero.


VGA monitors have three video inputs—Red, Green and Blue. The RDT64 uses one bit per color, which can produce the eight colors: Red, Green, Blue, Yellow, Cyan, Magenta, Black and White. The RDT64 uses one color for the foreground (characters) and another for the background (blank space). The three bits that define the foreground color and the three that define the background color are six of the eight output bits from the 74HC595 SPI-parallel-port (U9). Refer to the schematics in Figure 6. The foreground color bits go to three B-inputs on the 74HC157 quad data-selector, U10—the background color bits go to the matching A-inputs. The PIXEL signal from shift-register U3 connects to the A/B select pin on the data-selector, Thus, when PIXEL is true, the foreground color bits appear on the data-selector outputs, and when PIXEL is false, the outputs are the background color bits.

FIGURE 6 – RDT64 video control, keyboard and sound schematic

The output of data-selector U10 is controlled by the BLANK signal connected to the output-enable pin. When BLANK is true, the outputs of the data-selector are forced low. When BLANK is false, the outputs follow the selected foreground or background color bits.

The input impedance of the Red, Green and Blue pins on a VGA monitor is nominally 75Ω, and the maximum voltage input is 0.7V. The 470Ω resistors on the Red, Green and Blue outputs of the data-selector form a voltage divider with the 75Ω input impedance, reducing the 5V logic signals to approximately 0.67V at the VGA connector.


The RDT64 video SRAM (U5) contains the characters displayed on the screen in the first 1,600 bytes of its available 2,048 bytes. During the active vertical portion of each frame, the address lines to the SRAM are connected as described above. However, during the vertical blanking portion of each frame, the SRAM address lines and data are controlled by the main PIC MCU (PIC16F1788, U2), shown in Figure 7.

FIGURE 7 – RDT64 clock, main PIC MCU and serial I/O schematic

When the vertical logic chip (U7) sets VBLANK high at line 400, several things happen in hardware. The VBLANK signal disables the video SRAM (U5) output and selects the B-inputs on the 74HC157 quad data-selectors (U13-U15), connecting the SRAM address lines to the 74HC4040 (U16) character-counter output. Data-selector U15 connects the video SRAM write control to a PIC output line (AC_WR\). U7 also sets VIRQ at the same time as VBLANK. VIRQ remains high until line 448, and VBLANK remains high until line 449.

The main PIC MCU (U2) maintains a copy of the ASCII characters on the screen in an internal buffer. VIRQ causes the PIC to branch to an interrupt service routine, which does the following:

• Changes port-B (RB0-RB7) from inputs to outputs. This is the ACD bus.
• Toggles the character-counter clear line (CC_CLR) which sets the SRAM address to zero
• Writes the next ASCII character data to port-B –the ACD data bus.
• Toggles the video SRAM write control (AC_WR\), which stores the character on the ACD bus in the video SRAM.
• Checks VIRQ still high, else [END OF LOOP].
• Checks for screen buffer remaining, else [END OF LOOP].
• Toggles the character-counter clock line (CC_CLK), which increments the address to the video SRAM.
• Changes port-B (RB0-RB7) from outputs to inputs.

VIRQ remains high for approximately 1.53ms. During this time, the PIC can transfer over half the characters to the video SRAM. The PIC only toggles CC_CLR on even numbered interrupts, and begins where it left off on odd-numbered interrupts. Therefore, it takes two VIRQ interrupts to transfer the entire screen buffer from the PIC MCU to the video SRAM. This means the RDT64 screen updates at half the frame rate, or approximately 35Hz.

The main PIC MCU’s internal clock runs at 32MHz, which makes the instruction cycle time 125ns. Video SRAM refresh takes approximately 1.5ms every frame, or 105ms out of every second. The remainder of the time the main PIC MCU polls the keyboard interface and serial port.


The RDT64 interfaces with a standard PS/2 keyboard via connector J1 (Figure 6). J1 is connected to a KB1 keyboard interface (U8) based on a PIC16F1823. The KB1 handles all signals between the RDT64 and the keyboard, decodes the keyboard scan codes and provides ASCII data to the main PIC MCU (U2). The KB1 can interface with a host via I2C, SPI or UART—the RDT64 uses the SPI interface. When keyboard data are available, the KB1 asserts KIRQ\. The KB1 key-stroke buffer is eight deep, so no keystrokes are lost if the main PIC MCU is busy refreshing the video SRAM.

The RDT64 interfaces with a Host via connector J40 (Figure 7). Standard RS232 voltage levels are provided by the Maxim Integrated MAX232 interface chip (U40). The Host UART should be set to operate with eight data bits, no parity and one stop bit (8N1). None of the handshake lines are actively controlled by the RDT64. DTR is not connected, and thus is ignored. DSR and DCD are hardwired to the ON condition (ON = spacing = +voltage) at all times. RTS is received, buffered and looped back to the Host as CTS—in this way, CTS tracks RTS.


On power-up, the PIC MCU computes the checksum of the settings data in its EEPROM. If the checksum is correct, it applies the settings and beeps twice. If the EEPROM data are corrupt, the MCU applies default settings and beeps six times. The opening screen displays the firmware version.

Holding the ALT key down and pressing F1 at any time will put the RDT64 in the setup mode and display the screen shown in Figure 8. Setup options are selected by typing the character in brackets. After a setting is changed, the setup menu will be displayed with the new setting. While in setup mode, the RDT64 does not communicate with the Host. To leave the setup menu and return to normal operation, type Q for Quit. The settings shown in Figure 8 are the default settings.

FIGURE 8 – RDT64 in case displaying SETUP MENU

Typing a 0 will bring up the Select Baud Rate sub-menu. Rates of 1200, 2400, 4800 or 9600 can be selected. The new rate is effective when you Quit the setup menu.

Typing a 1 will toggle the Local Echo setting. When local echo is on, any character you type will be displayed by the RDT64 and sent to the Host. If the Host then echos it back, the character will appear twice. When local echo is off, any character you type will be sent to the Host. It will not be displayed unless the Host echos it back to the RDT64.

Typing a 2 will toggle the CR In Translation setting. When this option is on, the RDT64 will treat any carriage return (CR) from the Host as a CR followed by a Line-Feed (LF). If this option is off, a CR from the Host will have no effect on the display.

Typing a 3 will toggle the CR Out Translation setting. When this option is on, the RDT64 will send a CR, LF combination to the Host whenever you type a Return. If this option is off, only a CR will be sent to the Host.

Typing a 4 will toggle the Bell Sound setting. If this option is on, the RDT64 will produce a bell sound when the Host sends a Ctl-G (0x07) character. If this option is off, no sound will be produced.

Typing a 5 will toggle the Cursor Blink setting. If this option is on, the cursor will blink at approximately 1.1Hz. If this option is off, the cursor will not blink.

Typing a C will bring up the Select Cursor submenu. The cursor may be an underscore (_), vertical bar ( | ), block (g) or there can be no cursor. If there is no cursor, character the cursor blink setting is irrelevant.

Typing a 6 will toggle the Font Selection between the Default and the Optional fonts. Font selection is controlled by the FONT1 signal from the 74HC595 SPI-parallel-port (U9). Font Selection is effective immediately.

Typing a V will cause the entire 256 characters in the selected font to be displayed. See Figure 9 for an example.

FIGURE 9 – RDT64 default font displayed

Typing a 7 will toggle the RDT64 between use of the Printable ASCII character set (0x20-0x7F) and the Extended ASCII character set (0x20-0xFF).

Typing an 8 will bring up the Select Color submenu for foreground color. Select one of the eight available colors. The RDT64 will not allow you to select the same color for foreground and background.

Typing a 9 will bring up the Select Color submenu for background color. Select one of the eight available colors. The RDT64 will not allow you to select the same color for foreground and background. Table 3 shows the foreground and background color digits.

TABLE 3 – Foreground and background color digits

Typing a D will toggle the Debug Mode. Debug mode is intended to help trouble-shoot problems between the RDT64 and the Host. In Debug Mode, characters to and from the Host are displayed as follows:

(XX) = the hex value XX sent to Host from RDT64

XX = the hex value XX sent to RDT64 from Host

For example, if you typed “Hi” followed by a Return and the Host responded with “Huh,” the display would look like: (48)(69)(0D)(0A) 48 75 68 0D 0A.

Most changes are effective immediately. That said, the settings will only be effective until power is removed. If you want your changes to be permanent, they must be stored in the main PIC MCU’s EEPROM. Typing an S will save the current settings in the EEPROM.

Although my original purpose was only to have a debugging tool, to be useful as a terminal, the RDT64 also should be able to process at least a limited vocabulary of control characters and escape sequences. Table 4 shows how the RDT64 processes control characters. Table 5 shows the escape sequences the RDT64 recognizes.


Advertise Here

TABLE 4 – Response to control characters (0x00-0x1F) from Host. Characters not listed are ignored.
TABLE 5 – Response to escape sequences from Host

The RDT64 was prototyped in wire wrap then converted to the PCB shown in Figure 10. The RDT64-1 PCB was designed to fit the Simco 150X75 case. A link [2] to that case is provided on Circuit Cellar’s article materials webpage. Figure 8 shows the RDT64 in its case, displaying the setup menu.

FIGURE 10 – RDT64 printed circuit board

The RDT64 is working fine as a simple serial ASCII input and output system for debugging. I plan to make it the terminal for a general purpose Z80 system in the near future. 

Authors Note: The RDT64 is for available for sale at:


[1] “Build a VGA Monitor Controller”, by Enoch Hwang. Circuit Cellar 172, November 2004[2] Simco 150X75 case.×75-desktop-plastic-enclosure.html

Purchase the Retro Dumb-Terminal (RDT64) at:

KB1 user manual, PS/2 keyboard interface:

Timing details about standard VGA cards:

Lucid Technologies |
Maxim Integrated |
Microchip Technology |
Simco |


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
+ posts

Brian Beard received his BSEE from the U.S. Air Force Academy in 1973, an MBA from UWF in 1989 and MS and PhD. degrees in biomedical engineering from Vanderbilt University in 1993 and 1995, respectively. He flew F-4 phantoms in southeast Asia, Europe and the USA. After flying, he worked for the Air Force designing test instrumentation at Eglin AFB in Florida. He designed analog computer systems, transistor and gate-level logic and worked with early 6800 and Z80 systems. He has been programming, mostly in assembly language, for over 40 years. He currently does medical device safety research at the FDA. One of these days he might actually retire and write more articles.

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Making a Retro Dumb Terminal

by Brian Beard time to read: 13 min