
IIt’s that time of the year. The leaves try to figure out what is the best color to wear for the funeral of the summer, the rain can’t decide which way is best to fall, they days are getting shorter and children are soon heading out to collect more candy than they should ever eat.
It’s also the time for scary stories, so let me share one. It involves apples, lightning (well, sparks at least), glowing objects and Frankenstein monsters.
It also involves electronics and some digging in the past.
The orchard
Some time ago, when the sun was bright and grass was young, I decided a good quarantine project would be to restore an old Macintosh computer.
Soon I entered the club of Apple product owners. I got a Macintosh SE.
Not exactly the newest PC from the company, but it’s a cute little box with a 9″ monitor. Who could ask for more?
Well, as it turns out, I was. One thing let to another and pretty soon our basement was flooded with old Macs in various sorry shapes.
Eventually I managed to bring almost all of them back to life (there’s another story there for another day), but I was left with one Macintosh Plus, that I couldn’t repair.
It had some shorts in the transformer for its power supply, which essentially meant that the machine was toast.
Two computers walk into the bar
Then I had an idea: what if I removed the digital board from the machine, stuck an ATX power supply and a mini-ITX motherboard in it and turn it into a PC?
Sounds like a fun little project, with one problem: I would need to interface the monitor part of the old Mac to the PC. So, let’s start: let’s turn a Mac display into a VGA monitor!
In this journey, I relied heavily on the excellent description of the internals of these old machines, written up in the ‘Classic Mac Tech Info’ document.
Following in those footsteps, we can separate the innards of (almost any) CRT display into three main portions:
- The video amplifier
- The horizontal deflection circuit (which is also responsible for generating all the high-voltages needed to operate the CRT)
- The vertical deflection circuit
Let’s go through them one by one!
The video circuit
The original video circuit in the Mac Plus was very simple. It could only deal with TTL logic levels, black-and-white signals:

This circuit has important trick in there: the inductor L4 is used to generate nice, sharp edges, but it’s operation (especially with CR12) is non-linear. While it works for black-and-white images, it won’t cut it for gray-scale.
I needed something more. I needed a proper video amplifier, something that can accept an analog input between 0 and 0.7V and translate that to the 30…0V range (yes, we need inverting operation. 30V is black, 0V is bright white). I also needed to be able to do this from DC all the way to ~30MHz (VGA pixel clock rate). I needed to do it with only a few components, because I didn’t feel like spending a lot of money on designing PCBs, buying components etc.
Also, I haven’t done anything like this ever before. Sound fun!
My first attempt was to try to modify the above circuit to my needs. I’ve modeled it in LTSpice and started changing things. Obviously the first thing to go was the input gate (U2) but I didn’t get too far after that: I couldn’t get the frequency response of the amplifier stage (Q7) to even remotely what I needed. Large signal response was also rather problematic.
Next, I turned to another tried and true approach: what did others do? After all there used to be hundreds of CRT monitor models out there not to even mention the thousands of TV sets designed. This must be a known problem with known solutions. I scoured the web for monitor schematics. It turned out harder then I thought. Apparently it wasn’t established practice to publish monitor schematic, or maybe it’s just too old tech and no one cares anymore? I did find a few, but they were for ‘modern’ multi-sync, color monitors, which employed integrated circuit video-amplifiers. Which are long dis-continued. Sigh… After a while, I did find a few designs, which showed discrete circuits and I also found some datasheets and application notes for the integrated video amplifiers of the yore. Eventually a curious pattern emerged:

That circuit in the highlight! That seemed to be a quite common section of all solutions. What is that? After some Googling, I came to understand that that’s a cascode amplifier. It’s usually drawn as the above, but it’s essentially a common-emitter first stage, followed by a common-base second stage. It apparently offers both high voltage gain and wide bandwidth. Just what I need!
I’ve started playing around with it (again, in simulation) and I came up with the following circuit:

You see my comments in the schematic, and they don’t even capture half of the problems. It’s enough to look at the DC transfer function of the amplifier over temperature to realize, it’s not going to work:

At 25 degrees, it’s not horrible, actually. I would love it to be more linear, but that’s something that maybe some gamma-correction in SW can mitigate. But the temperature dependence? Ouch!
Another problem is the input biasing: the base of Q1 would need to be about 0.7V above ground to open it up. My input voltage range however is 0…0.7V. I needed to apply a DC bias (R1, R12) to make it work, but that of course is a fantasy: this circuit would back-bias the output stage of the VGA card, which is generally frowned upon and for good reason.
AC coupling the input is not an option either: that would not allow me to display black or white images, only a ghostly gray relief.
What I really want is the emitter of Q1 to be below ground by about 0.7V. Or one PN transition forward bias voltage worth. I know! That’s what diodes do! So, here’s the second version of the circuit:

The idea is to grab on to a negative power supply (-12V is what I have on the ATX supply) and use that to forward-bias D1. This drops the potential at the bottom of R7 to about -0.7V, which in turn would mean that (by adjusting the values of R1, R2 and R7) I can set the biasing such that 0V input just barely opens Q1. This fixes the input problem. I have something I can certainly drive with a VGA card. But how does it behave? Let’s first look at the DC transfer function:

Much nicer! Not only it’s way more linear, but look at the temperature dependence! It’s almost non-existent. This is thanks to the diode voltage counter-acting the PN junction voltage drift in Q1. As long as they’re more or less at the same temperature of course. There’s still a little problem with blacks, I expect those shades to blend together a little. Still, for two generic transistors (2N3904 is pretty much as generic as you can get), it’s not bad at all.
What about frequency response? The be precise, large-signal response and rise-time. Here’s what the amp would do with a checker pattern at 1024×768@60Hz:

Pretty decent! Certainly would look sharp even at that high resolution, if reality matches simulation. It of course won’t, but this gives me a lot of bandwidth to lose to implementation and still get decent performance. Also, look at how little any of this changes with temperature. This really seems like a rather solid little circuit.
Now, you might ask, why I make such a big deal about temperature. Well, this circuit will go into a closed box with other things, close to a 100W of total power consumption. I will add a fan of course, but things will get worm. Also, if you look at my notes about resistor wattages on the schematic, you’ll see that this circuit isn’t exactly low power. There will be some worm-to-hot components around.
I’ve built the circuit on a bread-board:

I’m bending the timeline here a little. This is the current shape of the circuit, it didn’t start out this way exactly (but more on that later).
I’ve turned it on, and I’ve been greeted by the following:

Yeah, don’t try, you can’t really read it. But it’s certainly an image and it’s certainly … well … letters!
The horizontal circuit
This is my next nemesis. The circuit diagram of it is the following:

Now, this is where the sparks fly. This guy not only is responsible for generating the deflection coil current, but all the high voltages for the CRT tube. The highest of them all of course is the ~12kV for the anode. But there are three other control voltages needed: one for brightness, one for focus and one for contrast. These are all generated using the same fly-back transformer and some reach hundreds of volts. The 30V power for the video amplifier is also generated here.
The theory of this type of circuit is described here: http://repairfaq.cis.upenn.edu/sam/deflfaq.htm.
Notice something important: there’s no horizontal oscillator of any sort. The sync pulses are directly driving the circuit. There are a few consequences of this:
- The circuit is shut down without any sync pulses. There simply are no high voltages, no deflection, the monitor is essentially off
- As long as we stay within some safe limits for the pulses, this circuit ‘just works’.
- Except that all the voltages and currents depend on the timing of the sync pulses.
As it turns out, the last point is the important one. The original Mac used 22kHz line frequency. The VGA standard uses 31KHz. That’s a pretty large difference. In this circuit, the current-ramp on the deflection coil – and consequently the speed of the electron ray – is constant, set by the circuit components. The change in horizontal timing means that the ray has significantly less time to scan a horizontal line, so – due to the constant speed – I should expect the image to be squashed horizontally. Now, this can be somewhat compensated by L2 (width setting inductor) but there are limits.
The other consequence is that – since we spend less time ramping the current in the deflection system – we end up building up less energy in that coil. This energy is converted into a voltage ‘bump’ during retrace (that’s what C4 and CR5 are doing), so the peak of this bump will be lower. This in turn means that I should expect all other generated voltages to drop. I should see a darker picture for example, I might even have focus problems. Now all of these are adjustable to a certain degree, but will I have enough range?
Finally, the retrace time is also determined by component values alone. It actually doesn’t matter all that much what I set the sync pulse width to (though it might change power consumption) but it also means that I have to adjust timing such that I properly wait for the cathode ray to reach the left-side of the screen. Otherwise, my displayed image would fold-in.
You can see all these effects here:

Side-track: EDID
Now, to get this far, I needed to do something else. You see, all modern systems assume that they have a decent monitor hooked up to them. At least 1024×768, if not higher resolutions. Even the BIOS on my motherboard assumes that! Linux of course tries to boot into the highest resolution possible. How can I fix this? How can I convince these pieces of SW that I want to stay at VGA resolutions?
Monitors have a small EEPROM inside them, containing information about their supported modes and timings. It’s called EDID. I needed to add that to my design. That’s the little surface-mounted component on the top-left corner of my circuit and that’s the piece that I added later.
It of course is relatively easy to bolt that chip into the circuit but it only does any good if it contains the right information. That means:
- Authoring the right content
- Programming the content into the chip
There are nice EDID editors out there, I managed to find a few and ended up using Phoenix, shown here running under Wine on Linux:

This program can generate a raw dump file with all the values to be programmed. I needed to get them to the device though and I don’t have any I2C programmer. I have however my trusty old JTAG programmer. This uses an FTDI chip, which can talk I2C. Or so it seems. The trouble is, I’ve added level-shifters to the design, which are push-pull outputs. I2C needs open-drain ones. No worries, a couple of diodes can fix that. This still doesn’t solve the problem of actually getting all the pieces to talk to each other. This is where snakes enter the story and Python comes to the rescue:
from pyftdi.i2c import *
import sys
bus = I2cController()
bus.force_clock_mode(True) # Needed for 2232D devices
bus.configure('ftdi://ftdi:2232/1')
mem = bus.get_port(0x50)
file_name = sys.argv[1]
size = 128
block_size = 8
print(f"Starting programming from file {file_name}")
full_content = []
with open(file_name, 'rb') as file_handle:
total_size = 0
while total_size < size:
raw_data = file_handle.read(block_size)
if len(raw_data) != block_size:
print("Incorrect file size: should be 128 bytes")
else:
transaction = [total_size] + list(raw_data)
full_content += list(raw_data)
mem.write(transaction)
print("w", end="")
mem.write([total_size])
content = mem.read(block_size)
for i in range(len(content)):
if raw_data[i] != content[i]:
print(f"Write error at offset {total_size+i}: expected: {raw_data[i]:02x}, actual: {content[i]:02x}")
exit()
print("r", end="")
total_size += block_size
print("")
print("verifying")
mem.write([0x00])
content = mem.read(total_size)
for i in range(len(content)):
if full_content[i] != content[i]:
print(f"Read-back error at offset {i}: expected: {full_content[i]:02x}, actual: {content[i]:02x}")
exit()
print("All done")
The formatting is horrible, but you get the idea: grab the right I2C library with FTDI support, coerce it to work with my FTDI chip (because it doesn’t like these old chips for I2C), then follow the datesheet of the memory chip to program the content.
Here’s the actual content:
EDID BYTES:
0x 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------------------------------------------------
00 | 00 FF FF FF FF FF FF 00 34 23 00 00 00 00 00 00
10 | 01 00 01 03 68 00 00 00 00 00 00 00 00 00 00 00
20 | 00 00 00 20 00 00 31 41 01 01 01 01 01 01 01 01
30 | 01 01 01 01 01 01 64 00 00 00 00 00 00 00 00 00
40 | 00 00 00 00 00 00 00 00 00 00 00 10 00 00 00 00
50 | 00 00 00 00 00 00 00 00 00 00 00 00 00 10 00 00
60 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10
70 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0E
This tells the computer that the only mode the monitor supports is VGA.
Good enough to at least get a picture and boot into the OS, which is what you see above.
Vertical deflection
The vertical circuit in this Mac is build out of op-amps and a bunch of discretes:

This is strange for the era, after all, the TDA1170 was around and simplified things quite a bit (the Mac SE for example switched to using that chip). At any rate, this decision actually helps me: the vertical circuit is quite a bit forgiving about its timing. Notice that there’s no oscillator here either: the sync pulse directly determines when the deflection happens. It however is sensitive to the polarity of the sync pulse. As luck would have it, VGA monitor timings used both positive and negative hsync pulses and happily swapped them around seemingly randomly.
This caused me quite a bit of headache. I thought I fried my deflection circuit only to realize that I had the wrong polarity. After days of trouble-shooting of course. Grrr…
If you look carefully at the image I’ve shown you above already, you’ll see that it’s not only folded in the horizontal, but also in the vertical direction.

This is partly due to the fact that I can’t set the vertical retrace to arbitrarily short times (the JFET Q5 above needs some time to discharge the capacitor, plus there’s just so much drive-strength in the driver stage Q1, Q2 to invert the field in the coil). There’s another reason though: the standard timing starts driving video signals too close to the falling edge of the sync pulse.
Timing
I obviously need to fix these timing problems, but first, let’s see how things work!
This was very exciting! I didn’t have an OS installed at this point, but I got a stable image!
After this, I installed an OS on the hard drive, because the next step was going to be adjusting the video timing to get rid of the folding artifacts and get the best possible picture.
Linux has great tools for this: xvidtune from the old days for interactively changing timings. cvt and xrandr to generate and apply timings on the fly are more modern, command-line replacements. And of course the Xorg server supports ‘modeline’ configurations, to statically set things once I know what I want.
Side-track 2: video cards
None of these tools worked. None! xvidtune refused to change any of the parameters with a strange error message, saying the timings are invalid. Even the ones, that were already applied! xrandr was willing to entertain the idea of introducing new timing modes, but was unwilling to apply them.
For a while, I thought that the EDID I programmed was too restrictive, and that was causing the problems (it could still be the case by the way), but I needed it to be restrictive to get through the boot with something to look at.
Then came the idea, that maybe the video card driver is the culprit. Luckily, the hoarder I am, I have a stack of old video cards in a box. nVidia and AMD, old and even older. I started swapping things out. One didn’t boot at all. One booted, but was not displaying an image. Probably ignored the EDID settings altogether.
The third one though, a FirePro V3900 did the trick though! Not only did it boot up with a visible image, it allowed me to set and apply settings with xrandr. xvidtune still refused to work, which slowed things down considerably, but at least I had a way to experiment.
And experimenting I did. Eventually, I’ve realized that the phosphor in the monitor is really tuned for 60Hz displays. Anything below 55 is eye-bleach and 50Hz visibly flickers. This is not a problem for the vertical circuit, it’s happy with either settings. It is a problem for the horizontal one though: due to the fixed aspect ratio (4:3), the horizontal and vertical timings are tied together. This means even higher horizontal rates, which means even narrower and darker image.
Eventually, I managed to find a reasonable compromise:

Still, look at how narrow the image is (and that’s with the width setting at the max).
Moar!
I am greedy. I want more. More! Now, that I could get VGA resolution going, could I get even higher? Maybe 800×600?
Now, this means of course even higher horizontal timing, even darker and narrower image. I would only stand a chance if I can do something about it.
Looking back at the horizontal schematic I noticed something.

True, the timing, the speed of the trace and re-trace is set by components, but they also depend on the power supply voltage. The one marked as +12F. This is – originally – a filtered version of the 12V that runs all over the place. What if I increased that? Now, as I mentioned, this circuit is responsible for all the high-voltage stuff, so monkeying around with it is potentially dangerous.
The first thing I did was to verify that with these new timings, all the voltages get lower then their normal values. That was indeed the case, which seems to mean it’s safe to increase the 12V to something higher. At least to certain degree of course. There are some other components (Q2, T2) which see this voltage, one can’t go all bonkers. But something, slightly higher might work?
Of course, the ATX supply doesn’t have anything higher then 12, but I happened to have a 19V power brick lying around. Not exactly nice, but will do for a quick experiment. I’ve hooked it up, and voila:

SVGA resolution at 55Hz (some flicker, but border-line acceptable), relatively nicely filling the whole screen.
This particular setting uses 44MHz pixel clock. Pretty neat for a 2-transistor amplifier, rigged up on a piece of bread-board.
After doing this, I managed to fix a few things. First, I realized that the dark image is partly due to the power supply of the video amp drifting with the changed timing and supply voltages to higher levels: 48V instead of 30. That means that more of the range displays as black since higher voltages don’t become more ‘black’. Once the electron beam is cut off, no increase in cathode voltage results in any change. Then, I realized that I can more or less counter-act this effect by adjusting the gamma setting in SW. This in turn changes the mapping on the video card to use more white levels and brightens the image up. Probably not the ‘proper’ thing to do, but, hey, it works:

It might be a little hard to read, but this setting is beautiful 800×600 resolution at full 60Hz, with relatively good fill of the screen and most of the gray-scale range differentiable.
Greed
Can I get to even higher resolutions? I actually tried 1024×768. It showed an image, but it was very dark or very low refresh rate. It also covered only a small section of the display due to the ever-higher horizontal sync frequency. At that resolution either the video amp, the tube itself or the focus circuit is just not up to the task: the image is very fuzzy. I might be able to fix some of these problems, but, honestly, 800×600 is already pretty amazing from something of this age and this much outside its original design targets.
Should I increase the voltage to maybe 24V? That would allow me to get the image fully fill the screen, maybe even get back some width adjustment ability. More crucially though, it would lift the high voltages back into their normal range, which in turn would allow me to set brightness and focus properly.
Well, this is where I got too greedy. When I tried that, the screen started getting brighter and brighter after a few seconds of operation. I suspected some runaway thermal problem, most likely on Q3 which already runs pretty damn hot.
I realized that a few components were getting out of their rated ranges, such as the C2 filter cap, so I replaced that with a higher rated one. I’ve separated the supply for the video amp to an independently generated voltage to avoid frying the 2N3904 transistors. I moved the heater to another 12V supply (I was fed from +12F, which I was jacking higher and higher) not wanting to burn the CRT out.
With all those changes, I felt more comfortable trying higher voltages and went all the way to 20V. At this point I got a stable image, but after a minute or so, the whole image started shrinking in size. I quickly turned off the machine, but apparently not quickly enough. I never got an image, or to be more precise high voltage from out of the circuit ever again. I certainly fried Q3, but replacing it didn’t fix the problem. In fact I just got it fried again. Scoping around shows that the fly-back transformer doesn’t act like an inductor anymore. It acts like a very low value resistor. So, my diagnosis is that I shorted the fly-back. That’s not a component that’s easy to replace 30 years after manufacturing stopped.
So, this is the point I called it quits: it was fun while it lasted and now, in the spirit of Halloween, I have some bodies to bury. R.I.P old boy!