@Kai Robinson suggested I share this here, originally posted to Tumblr on May 25, 2021 --
I’m using a similar approach to the [bbraun] project, which used an stm32f4 to watch the SE’s CPU bus for writes to the SE frame buffer memory addresses. Instead of using a microcontroller I’m using an Atmel ATF1508AS CPLD to monitor the SE CPU bus for writes to the frame buffer addresses and storing the data in a pair of 32kB SRAM chips. The CPLD then reads back the video data to generate a 640x480 monochrome VGA signal with the SE video in letterboxed in its original 512x342 resolution.
The circuit itself is fairly straightforward. The CPLD runs everything off a single clock signal from a can oscillator, and uses the pair of SRAM chips for video memory. Other than those four chips, there are a few passive components. It’s simple enough I could have built one with point-to-point wiring or even wire-wrap. But, to reduce debugging and the potential for noise disrupting the SE’s normal operation, I decided to lay out and order some small PCBs.
I got these from JLC for $2 plus shipping and they arrived in just under two weeks. Build was easy enough. I used the drag solder technique with a lot of flux to solder on the 100 pin QFP package CPLD and it went on with no problems. Everything else is through-hole.
I tried to take a methodical approach to build and debug. I started with just the CPLD and clock to make sure it could generate a proper sync signal that was recognized by my monitor. That much worked without issue, so I moved on to testing if it could read data from its VRAM bus and display it. This part took some work with a logic analyzer and a few rounds of updates, but eventually I was able to tie one VRAM Data pin high and get it to display lines.
From there, I added the VRAM sockets to test if it could properly read from VRAM and display its contents. SRAM powers on to random contents, and when I added the SRAM to the board and powered it on, I was greeted with a screen of random pixels. VRAM was working, and the video generator was displaying a stable, consistent image.
At this point there was only one thing left to do — solder on the (expensive!) DIN 41612 connector and test it out in the SE.
Well, it was half working.
I had half of the image on screen, so it was clearly recognizing CPU write cycles, storing it in VRAM, and recalling it in sequence. I quickly found and corrected a bug in the code looking for the 68000 lower data strobe (!LDS), and inverted the final output and tried again.
It … Wasn’t quite right. It started out fine while Mac OS was booting. There was a little noise in the image, but not too bad … until it reached the Finder. By the time it was finished booting, it was flashing, alternating between valid video data and a garbage data. The garbage data seemed to be encroaching on the valid data as well, the longer the system ran.
The first bug didn’t take long to find. The classic Macs, including the SE actually support double-buffered video. They have a primary frame buffer and an alternate frame buffer, selected by setting or clearing one output bit on the VIA chip. I designed the card to support both frame buffers, and to also watch the CPU bus for writes to the specific VIA bit that controls frame buffer selection. I had calculated the VIA address wrong though, so it was swapping between frame buffers when it shouldn’t have and that’s what was causing the flashing.
I still had the problem of garbage data being displayed however. This one took a while to figure out, and I’m actually still not sure how it was happening to begin with.
The logic analyzer showed that every so often a VRAM write cycle would overlap with a VRAM read cycle. The VRAM write state machine shouldn’t have allowed that to happen, but it was. Unable to find anything that would cause the cycles to overlap, o added a test to delay the write cycle if it detected a current read cycle.
The result?
No more garbage data.
I really can’t believe it. I wasn’t sure I could get this to work, and I wasn’t sure it would fit into a CPLD with only 128 macrocells. To top it off, this is my first real project using System Verilog instead of VHDL.
It’s not perfect yet. There is one column of garbage data being displayed on the left of the image, and it looks like the last column off the right is also ending up on the left. But, it is completely useable.
I’m not finished with this project yet. I want to bump it up to XGA resolution (1024x768), which would allow the SE video to be pixel doubled and take up more of the screen. The 65MHz clock necessary for XGA is hard to come by, so I’m thinking about spinning up a rev 2 board that uses an FPGA instead of a small CPLD.
This has been a fun project. It’s always so exciting for a project to have visible results.
I have the project on GitHub if anyone is interested in taking a closer look.
SE-VGA
Inspired by recent work on creating modern reproductions of the Mac SE logic board and following my previous CPLD VGA generator project, I’ve been working on a PDS card for the Mac SE that mirrors its video on a VGA monitor.I’m using a similar approach to the [bbraun] project, which used an stm32f4 to watch the SE’s CPU bus for writes to the SE frame buffer memory addresses. Instead of using a microcontroller I’m using an Atmel ATF1508AS CPLD to monitor the SE CPU bus for writes to the frame buffer addresses and storing the data in a pair of 32kB SRAM chips. The CPLD then reads back the video data to generate a 640x480 monochrome VGA signal with the SE video in letterboxed in its original 512x342 resolution.
The circuit itself is fairly straightforward. The CPLD runs everything off a single clock signal from a can oscillator, and uses the pair of SRAM chips for video memory. Other than those four chips, there are a few passive components. It’s simple enough I could have built one with point-to-point wiring or even wire-wrap. But, to reduce debugging and the potential for noise disrupting the SE’s normal operation, I decided to lay out and order some small PCBs.
I got these from JLC for $2 plus shipping and they arrived in just under two weeks. Build was easy enough. I used the drag solder technique with a lot of flux to solder on the 100 pin QFP package CPLD and it went on with no problems. Everything else is through-hole.
I tried to take a methodical approach to build and debug. I started with just the CPLD and clock to make sure it could generate a proper sync signal that was recognized by my monitor. That much worked without issue, so I moved on to testing if it could read data from its VRAM bus and display it. This part took some work with a logic analyzer and a few rounds of updates, but eventually I was able to tie one VRAM Data pin high and get it to display lines.
From there, I added the VRAM sockets to test if it could properly read from VRAM and display its contents. SRAM powers on to random contents, and when I added the SRAM to the board and powered it on, I was greeted with a screen of random pixels. VRAM was working, and the video generator was displaying a stable, consistent image.
At this point there was only one thing left to do — solder on the (expensive!) DIN 41612 connector and test it out in the SE.
Well, it was half working.
I had half of the image on screen, so it was clearly recognizing CPU write cycles, storing it in VRAM, and recalling it in sequence. I quickly found and corrected a bug in the code looking for the 68000 lower data strobe (!LDS), and inverted the final output and tried again.
It … Wasn’t quite right. It started out fine while Mac OS was booting. There was a little noise in the image, but not too bad … until it reached the Finder. By the time it was finished booting, it was flashing, alternating between valid video data and a garbage data. The garbage data seemed to be encroaching on the valid data as well, the longer the system ran.
The first bug didn’t take long to find. The classic Macs, including the SE actually support double-buffered video. They have a primary frame buffer and an alternate frame buffer, selected by setting or clearing one output bit on the VIA chip. I designed the card to support both frame buffers, and to also watch the CPU bus for writes to the specific VIA bit that controls frame buffer selection. I had calculated the VIA address wrong though, so it was swapping between frame buffers when it shouldn’t have and that’s what was causing the flashing.
I still had the problem of garbage data being displayed however. This one took a while to figure out, and I’m actually still not sure how it was happening to begin with.
The logic analyzer showed that every so often a VRAM write cycle would overlap with a VRAM read cycle. The VRAM write state machine shouldn’t have allowed that to happen, but it was. Unable to find anything that would cause the cycles to overlap, o added a test to delay the write cycle if it detected a current read cycle.
The result?
No more garbage data.
I really can’t believe it. I wasn’t sure I could get this to work, and I wasn’t sure it would fit into a CPLD with only 128 macrocells. To top it off, this is my first real project using System Verilog instead of VHDL.
It’s not perfect yet. There is one column of garbage data being displayed on the left of the image, and it looks like the last column off the right is also ending up on the left. But, it is completely useable.
I’m not finished with this project yet. I want to bump it up to XGA resolution (1024x768), which would allow the SE video to be pixel doubled and take up more of the screen. The 65MHz clock necessary for XGA is hard to come by, so I’m thinking about spinning up a rev 2 board that uses an FPGA instead of a small CPLD.
This has been a fun project. It’s always so exciting for a project to have visible results.
I have the project on GitHub if anyone is interested in taking a closer look.