I decided I needed to do something with an old Mac Classic II I had, which was the last of the monochrome Mac models. It was just too well built to throw out or make into a Macquarium. Even though I was able to get it working by washing the motherboard (the capacitors leak, a well-known problem) it was virtually useless since it can only access the Internet via a serial port, and cannot run a modern browser.

So I thought, in accordance with my new motto, why not stick a Pi in it? The video output of the Pi cannot drive the Mac CRT with the correct frequencies, but the Pi should be able to generate video using the I2S peripheral and generate the sync signals using the PWM peripheral.

NOTE June 2015: with the release of the the DPM specs, it is now possible to drive it directly. And it will be able to run X and therefore the Mac emulator. I will document these changes sometime soon.

Sounds simple, right? As is often the case, the devil is in the details.

The biggest problem is that the PWM and I2S peripherals cannot be started simultaneously: they are always off by a random amount of time since their clocks are both asynchronous to the CPU. The solution is to start them both then slow one peripheral clock down a small amount and wait for them to match up, kind of like a Phase Lock Loop. This violates the datasheet which says the clock dividers should not be changed when the clock is running, but the pifm project has demonstrated that this is permissible. (Thanks pifm folks, I don't think I would have tried this if you hadn't pointed the way). You can monitor the outputs for synchronization using a DMA channel: it has approximately 100 nanosecond sample time, and gets around the fact that Linux is not a real-time OS. This was mentioned in a discussion about the Panalyzer project, a logic analyzer using the Pi. You just have to set up the framebuffer contents to output a temporary video signal that is exactly the same timing and position as the desired sync signal.

Another difficulty is that the I2S port outputs data most significant bit first, the opposite of most real video hardware. So, the driver cannot use the generic Linux framebuffer bit manipulation routines and must supply it's own versions.

Finally, Unlike PWM0, PWM1 is not brought out to the GPIO header and is only available at the audio jack, at 1V signal level. Fortunately this model of the Mac uses a vertical deflection controller chip that was designed to work in both televisions and computer monitors, and only needs a single resistor change to set it to work at the normal television video sync signal level of 1V. So PWM0 can be used for horizontal sync, and PWM1 via the audio out jack can be used for vertical sync.

WARNING: I am not responsible if you injure/kill yourself, so know what you are doing. There are lethal voltages exposed when the cover of the Mac is removed. Read up on high-voltage precautions. The CRT can also implode if damaged, scattering glass fragments at high speed. You should read up on general CRT handling precautions and safety. Wear eye protection!

I unsoldered the cable from the CRT controller board that originally went to the motherboard, and connected the Pi signals there. The Pi is powered from the Mac hard drive power connector using an adapter cable I made. I mounted the Pi where the hard disk used to be, and I brought the USB and network signals from the Pi to the back of the Mac using bulkhead extensions from Adafruit and an aluminum plate where the motherboard used to be. I also put a dummy load on the 5V power line of the Mac to improve regulation, although this is probably not needed. The following pictures show the details:

Here are the connection and resistor replacement details for the CRT controller board:

Connection details for the audio plug:

What the Pi looks like all wired up.  Note the sync and video wires are twisted together with the ground wires to reduce emissions:

The new back panel with USB and network extensions installed.  They match up with existing holes in the enclosure:

I made no permanent modifications to the Mac other than drilling a few small holes inside. It can be restored to original condition easily.

The driver is split into two parts, the driver with basic initialization, teardown, and bit manipulation routines, and a user space program to do the video/sync synchronization. (I may re-write the userspace program in the future to be a kernel module.) The sync program can take up to 2 minutes to complete, and during this time there will be no video. When it finishes it activates the CRT and displays a test pattern. Here is what it looks like:

The driver must be built for your current kernel. I have step-by-step instructions on my site on the modules page. The fb_sys_fops and apfb modules must be loaded on boot, the apsync program run, then a con2fbmap 2 1 command run. I find the best place to put these commands is in the /etc/rc.local file. You also need to put disable_pvt=1 in the /boot/config.txt file to eliminate a block copy artifact.
Then, press ctl-alt-f2 on the keyboard, and you will get a login screen. You can map additional consoles, but do not map to console 1 or the Pi will segfault on shutdown. Here is what it looks like in use:

The Mac originally had motherboard-controlled brightness, so you now have to manually adjust brightness on the back:

Since this is a second display, the HDMI/composite outputs are still available.

Also, the Pi is directly connected to the CRT driver circuits. If the CRT driver circuitry fails, the Pi will be destroyed - probably spectacularly.


This circuit should work on an earlier model Mac, but will require that the vertical sync signal is boosted to at least 3.3v. A couple of resistors and a transistor should do it.

This circuit should also be adaptable to drive a VGA monitor in monochrome or single color, but will require transistor drivers on all signals and changes to the clock frequencies and sync waveforms.

There is no xwindow driver. I didn't bother since a 512 x 342 monochrome screen wouldn't be very useful to me since I mainly work at the console.

It would be possible to modify BasiliskII, the Mac emulator, to output to this framebuffer. I have looked at the code, and it should be fairly easy. Basilisk already keeps all Mac video in a memory mapped area, and copies it to screen memory periodically based on a timer. You would just have to reverse the bit order as you copy, and copy to the Mac framebuffer instead of to an Xwindow area. My testing indicates it would take less than 10% of the CPU to do this. I have verified that BasiliskII can be successfuly compiled and run on the pi using the normal framebuffer as a first step.

The framebuffer memory layout is not "normal". There are areas that must remain at a black level or the retraces will be visible. This means programs that write directly to the framebuffer (for example framebuffer graphic file viewers) will not work. It may be possible to overcome this by properly setting horizontal pan settings in the driver, but I have not tried it. Even if it could be made to work it would probably not be very useful because of the monochrome screen.

Sound output is not available since the PWM peripheral is used to generate sync signals. A usb sound card or usb speakers should work instead.

Here are some links to information that I found invaluable:

This site has been tested to display correctly using Epiphany on the Raspberry Pi