Control a Macintosh Classic CRT with a BeagleBone Black – Part 1


This article will explain how the timing of the Macintosh Classic CRT works and how I tried (and failed) to interface it with the Raspberry Pi, and how I interfaced it with the BeagleBone Black’s PRU. This is a multipart series, you can find the table of contents, as always, on the bottom of the page.

How does the CRT display an Image?

I will not write about how the CRT works in theory, other people have done that before. But I want to write about what signals are needed to compose an image on the CRT-display.

If you know how the screen works and you just want to know what the signals have to look like, skip to the next section.

Basically the screen’s hardware needs three signals: HSYNC, VSYNC and DATA (It might remind you of VGA). HSYNC stands for horizontal synchronization, VSYNC is for vertical sync, DATA sends the video data over to the display. Since the Macintosh Classic display is monochrome (black/white), there is only one DATA line. If it had more colors, there would be more separate lines (like one for red, one for blue and one line for green).

HSYNC triggers a new line on the display. At every falling edge of this signal, the CRT’s display graphics sets the screen’s electron beam to the beginning of the next line. The signal has a frequency of roughly 22.25kHz and it looks like this:

Fig. 1: The HSYNC signal for the CRT

Every time the HSYNC signal gets low, the screen get’s ready to display a new line of data. You can see that the period is about 45µs for one complete frame. But you should also see, that the signal is 59% of the time HIGH and 41% it is low.

The VSYNC signal triggers a new frame on the display. It has a frequency of about 60.15Hz, wich is also called the refresh rate of the screen. This bit was a bit harder to create, but I tried to sync it with the HSYNC signal, which works perfectly fine. So in my application the VSYNC signal occurs after 342 HSYNC edges. The HSYNC pulses continue during the VSYNC, but the video data doesn’t:

Fig. 2: HSYNC pulses (ch1, yellow) and VSYNC pulse (ch2, cyan)

You can clearly see that the HSYNC pulses continue while the VSYNC line get’s low. VSYNC is also triggered on the falling edge.

The last signal is the DATA line. This was the trickiest bit, and it was not possible to produce it with the raspberry pi. The problem is, that this signal is very time critical, it get’s basically useless if it is one nanosecond too fast or too slow. It always has to take exactly the same time to send this data to the CRT (and this is not possible to make with the raspberry pi by just writing code, however you can construct slower frequencies exactly with the Pi).

The data is sent by bit banging the pixels to the CRT with a dot clock frequency of around 16MHz (15.6672 MHz to be precise). Bit banging means that you send out the state of a pixel (HIGH = white, LOW = black pixel) via the DATA line in an exact timing, one bit after another:

Fig. 3: You can see the HSYNC signal (ch2, cyan) start a new frame and the DATA (ch1, yellow)

As you can see in fig. 3 the DATA does not start exactly at the falling edge of the HSYNC signal, it starts (roughly) 10µs after the falling edge. This time is needed by the CRT to position the electron beam at the start of the next line. There is also a time needed after a VSYNC to reposition it to point at the first pixel’s position on the screen. You can get a better understanding of the timings of these two signals by looking at fig. 4:

Fig 4: Sending completely white lines.

Note: The DATA line should be high while no pixels are sent to the CRT, fig. 3 and 4 show the DATA line getting low after the pixels were transmitted, to make the pulse duration visible.

This was basically everything that is needed to display an image to the CRT. The signals have to run synchronized and with exactly the frequencies they need to have, because the image gets distorted easily.

For example a wrong refresh rate (VSYNC frequency) makes the screen’s content hover up/downwards depending.

Important numbers

If you want to rebuild this or a similar project, here are some important numbers you have to find out for your display:

22.25kHz, 45µs period, 18.45µs low
59% PWM duty cycle

VSYNC-Frequency (Refresh rate)
60.15Hz, 16700µs period, 180µs low
99% PWM duty cycle

15.6672MHz, 512 pixels in roughly 32.8µs
Signal has to be high while no pixels are sent

If you can find a datasheet or a table with the exact timings for your display, you can read get the data from that, otherwise try to measure the signals produced by the original hardware’s video interface. Luckily most older computers had such documents and you can easily find them on the interweb. Macintosh Classic Developer NoteMacintosh Classic II Developer Note.

Create the signals with the Beaglebone’s PRU

Creating exactly timed signals is possible with the BeagleBone Black, how you can create the signals can be read here. This was not a big deal, the harder part was to create the DATA line. I’ll describe the method in the next parts of the series!

Table of contents

Part 0 – The story behind the project
Part 1 – The CRT (You are here)
Part 2 – The Software
Part 3 – Additional Thoughts



6 thoughts on “Control a Macintosh Classic CRT with a BeagleBone Black – Part 1

  1. It’s actually very easy to understand after one has understood how the image is made up on a crt. so basically you could use any crt right?


    1. You could, as long as you know the exact timings of the display. but it’s easier and safer to use a standard connector whenever possible. Controlling the CRT directly was necessary, because it had no standard connector.


Leave your two cents, comment here!

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s