[HN Gopher] Building a 24-bit arcade CRT display adapter from sc...
       ___________________________________________________________________
        
       Building a 24-bit arcade CRT display adapter from scratch
        
       Author : evakhoury
       Score  : 196 points
       Date   : 2026-02-04 17:35 UTC (1 days ago)
        
 (HTM) web link (www.scd31.com)
 (TXT) w3m dump (www.scd31.com)
        
       | zahlman wrote:
       | > I like the Raspberry Pi RP2040 a lot. It's relatively cheap
       | (around $1 USD) and has tons of on-board RAM - 264 KB in fact! It
       | also has what is called Programmable IO, or PIO.
       | 
       | I wonder how benchmarks would compare between the RP2040 and,
       | say, a Z80.
        
         | burnte wrote:
         | It would destroy the Z80. It's a 32bit, dual core CPU running
         | at 133MHz. Even single cored it'll thrash a Z80. Heck, I bet
         | you could create a drop-in replacement board for the Z80 using
         | an RP2040.
        
           | ge96 wrote:
           | Crazy what you can buy nowadays like the Teensy 4.0 with
           | 600MHz base clock
           | 
           | Granted that's $20 not $1
        
             | fortran77 wrote:
             | The key here is the "PIO" which you won't find on a Teensy.
             | It lets you do extreme "bit banging" tricks including
             | generating video. People have even implemented Ethernet on
             | it. I've used it for some custom serial protocols
             | ("Weigand") used by alarm panels.
        
               | ge96 wrote:
               | Really I guess I don't know what that is then as I buy
               | the Teensy since it has so much IO, multiple UART,
               | multiple I2C busses, sd card reading, etc...
               | 
               | edit: interesting
               | 
               | (Teensy | Pico)
               | 
               | Special Features: CAN Bus (3x), SDIO, S/PDIF | PIO
               | (Programmable I/O) (8 SMs)
        
               | fortran77 wrote:
               | The Pico PIO has an instruction set and can be
               | programmed.
               | 
               | You write PIO assembly that runs autonomously on a state
               | machine, with explicit timing (e.g., out, in, set, mov,
               | jmp, wait) and cycle-accurate interfaces. The CPU
               | communicates via small FIFOs, and interrupts are
               | optional; the PIO can be "fire-and-forget" for many
               | protocols.
        
               | ge96 wrote:
               | That's cool, I'm not at that level right now, side note I
               | bought an FPGA like 5 years ago and still haven't used
               | it.
        
             | MPSimmons wrote:
             | My sweet spot of choice between power and price is the
             | ESP32 S3 (2x core @ 240mhz) at ~$6 per board, but yeah, the
             | power to dollar ratio is crazy these days, across the
             | board. And they are absolutely tiny and sip power if you
             | write the code well.
        
           | PaulHoule wrote:
           | Note it was possible to use a Z80 to function as a display
           | controller, people used to do it back in the day...
           | 
           | https://archive.org/details/Cheap_Video_Cookbook_Don_Lancast.
           | ..
        
             | TapamN wrote:
             | The Galaksija computer used it's Z80 to help generate the
             | video signal. I'm not sure how its implementation compares
             | to your link.
             | 
             | https://en.wikipedia.org/wiki/Galaksija_(computer)
             | 
             | https://media.ccc.de/v/29c3-5178-en-
             | the_ultimate_galaksija_t...
        
             | burnte wrote:
             | The Z80 was a very powerful CPU for the day. Its still used
             | here and there.
        
               | sgerenser wrote:
               | Apparently the Zilog Z80 _just_ stopped being produced in
               | 2024: https://www.techspot.com/news/102684-zilog-
               | discontinuing-z80...
        
               | zahlman wrote:
               | Yes, there was considerable HN discussion, and I chose it
               | for the example specifically because of its long reign.
        
           | zahlman wrote:
           | Yes, I understand that, but I wonder about the multiple
           | (obviously there is more to it than clock speed). I chose the
           | Z80 because of its long-standing reputation.
        
             | burnte wrote:
             | I know, I 'm just saying the RP would dominate the Z80 in
             | literally every way. You could design a Z80 replacement
             | with the RP as the CPU and it'd blow away everything.
        
         | ajross wrote:
         | The RP2040 is a Cortex-M0, which is about the smallest core you
         | find on modern systems but still a pipelined 32 bit RISC
         | machine running in the dozens of MHz.
         | 
         | Note though, that the article is really about the PIO device on
         | these SOCs', which isn't part of the main CPU at all. It's sort
         | of a very limited programmable hardware engine for the specific
         | task of doing PCB level interconnect using GPIO and lightly
         | buffered streaming. In some sense it's like a thematic midpoint
         | between an FPGA and a CPU.
         | 
         | It's... honestly it's just really weird. And IMHO has really,
         | really, REALLY limited application. It's for people who would
         | otherwise be tempted to bitbang an I2C or UART, but not for
         | ones who can put hardware on the board themselves, or who have
         | a FPGA handy, or even for people who want to do non-trivial
         | stuff like QSPI displays[1] or whatnot.
         | 
         | Basically PIO smells like a wart to me. I genuinely don't know
         | who wants it. Regular hackers aren't sophisticated enough to
         | use it productively and the snobby nerds have better options.
         | 
         | [1] The linked article appears to be doing a quarter-VGA
         | display in 3-bit/8-color, and is sort of right at the limit of
         | the power of the engine.
        
           | dmitrygr wrote:
           | >Basically PIO smells like a wart to me. I genuinely don't
           | know who wants it. Regular hackers aren't sophisticated
           | enough to use it productively and the snobby nerds have
           | better options.
           | 
           | what are you blathering on about, sir?
           | 
           | driving complex displays with no spu use: https://dmitry.gr/?
           | r=06.%20Thoughts&proj=09.ComplexPioMachin... (my work)
           | 
           | pretending to be memory stick and sd card at dozens of mhz as
           | a slave to a sync bus (my work)
           | 
           | ethernet: https://github.com/kingyoPiyo/Pico-10BASE-T (not my
           | work)
           | 
           | 68k bus slave (my work)
           | 
           | usb host https://github.com/sekigon-gonnoc/Pico-PIO-USB (not
           | my work)
           | 
           | all on a $1 chip
        
             | ajross wrote:
             | > what are you blathering on about, sir?
             | 
             | Please don't.
             | 
             | I mean, I applaud your work. But let's also be honest (in
             | the "tough love" sense): those are all toys with
             | significant limitations that preclude anyone shipping any
             | of them on an actual device to an actual consumer. I mean,
             | your SOC (maybe a $2 one) surely already includes a SPI
             | master and USB host!
             | 
             | Actual interconnects that solve real market problems have
             | big boring spec books and competing implementations and
             | silicon vendors. The application for PIO is basically
             | limited to "I have to connect to this crazy old junk and no
             | one makes the part I'd otherwise need".
        
               | Gracana wrote:
               | Having dealt with the errata sheets for microcontrollers
               | with all those fancy IO devices that solve real marketing
               | problems etc, I'd kill to fix those problems with a
               | software upgrade.
        
               | dmitrygr wrote:
               | if you find a SoC for $1 that has 2 Ethernet ports, and a
               | usb host on it, while also having two cores and
               | supporting 32MB of RAM you'll surprise me. rp2350 does
               | all of the above for $1
        
               | duskwuff wrote:
               | Have you tested out the 2x PSRAM configuration; if so,
               | have you written anything up about it? :) I've thought
               | about a configuration like that myself but haven't
               | committed to any hardware yet.
        
               | dmitrygr wrote:
               | yes i have tested it and no i have not written about it
               | (yet). it does work and with the new ISSI 16MB chips, it
               | gives 32MB of continuous memory!
        
               | duskwuff wrote:
               | Awesome - I might just have to try it.
               | 
               | How are you handling startup? The approach I had in mind
               | was putting boot flash on the second channel with a
               | separate CS pin from PSRAM and configuring that in OTP;
               | any idea if that would work?
        
               | dmitrygr wrote:
               | Yes, sort of. Basically a tiny loader in OTP that enables
               | nCS1 on some pin, copies code from there to ram on nCS0,
               | reconfigures nCS1 to point to second ram. This does break
               | usb flashing. Use swd.
        
               | duskwuff wrote:
               | Is there no way to do that without code in OTP? The
               | bootrom is supposed to scan for an IMAGE_DEF on both
               | memory banks, and can use nCS1 as specified in
               | FLASH_DEVINFO. Unless there's something I'm missing, that
               | should be sufficient.
        
               | dmitrygr wrote:
               | I have not disassembled the production RP2350 rom (last i
               | looked at it was ~year before release) so i do not know
               | if it does indeed check nCS1 address space, but even if
               | it did, which of the 4 possible pins would it configure
               | as nCS1? surely trying all would be dangerous (possibly
               | breaking customer logic attached to this pins that does
               | not expect them to wiggle at boot). This seems like it
               | could break customer designs so I would be worried if
               | this did happen. I could be wrong. You can read out the
               | rom with a debugger and look, of course :)
        
               | duskwuff wrote:
               | FLASH_DEVINFO (in OTP) has fields to set how large M1 is
               | and what nCS pin to use for it. It's off by default.
               | 
               | Yes, you still have to write to OTP - but a few bits of
               | configuration is a lot easier than an entire init
               | routine.
        
           | duskwuff wrote:
           | > The linked article appears to be doing a quarter-VGA
           | display in 3-bit/8-color, and is sort of right at the limit
           | of the power of the engine.
           | 
           | The resolution and color depth restrictions were the product
           | of the low data rate of USB FS (~12 Mbps), not inherent
           | limitations of PIO.
           | 
           | > It's... honestly it's just really weird. And IMHO has
           | really, really, REALLY limited application.
           | 
           | I'd agree with "weird". But it's _useful_ weird; it turns out
           | that there are a lot of situations where PIO can avoid the
           | need for an application-specific peripheral, and can provide
           | that function in a more flexible fashion than a fixed-
           | function peripheral could. Dmitry 's SDIO device emulator is
           | a great example - almost every other SDIO peripheral on the
           | market is host-only.
        
             | ajross wrote:
             | > it turns out that there are a lot of situations where PIO
             | can avoid the need for an application-specific peripheral
             | 
             | And I can only repeat: I think that's an aspirational
             | delusion. I'm not aware of anyone shipping a PIO solution
             | to anyone in volume. It's "useful weird" to Hackerspace
             | nerds like us, and that leads to some epistemological skew.
             | 
             | Hardware needs to be boring and reliably supported (by
             | people you can sue!) or else no one will bet a 10k unit PCB
             | run on it. This is anything but.
        
               | duskwuff wrote:
               | I don't know if it's quite at the volume you're looking
               | for, but ZuluSCSI [1] uses RP2350 (and, earlier, RP2040)
               | for SCSI <-> SD.
               | 
               | [1]: https://zuluscsi.com/
        
       | johsole wrote:
       | Cool project! I've been doing software for so long but originally
       | got an EE degree. I miss messing around with hardware.
        
       | ge96 wrote:
       | CRT tech is neat, the flat ones are cooler
       | 
       | https://www.youtube.com/watch?v=pjzK-Lppa1c
        
       | ge96 wrote:
       | Philosophical tangent
       | 
       | I also produce hardware projects and share them open source but
       | unfortunately at a certain level of complexity people don't
       | reproduce them. It's kind of sad but also I'm glad to be able to
       | give back as I've had people help me learn to code in the past,
       | sit down with me through video and yeah. Or people sharing
       | knowledge in question answer forums.
       | 
       | There is the inspiration aspect too I've had some of my repos get
       | forked/modded so that's something but yeah ultimately gotta do it
       | for yourself. Getting published in tech websites is cool though,
       | like I had a project get picked up by a Japanese website that was
       | neat.
        
       | tomstokes wrote:
       | Cool project. Thanks for doing a write-up that includes so much
       | detail.
       | 
       | I do a lot of PCB review for students and makers, so if you're
       | interested I wrote up some notes. Consider this an incomplete
       | review because I only had so much free time, but hopefully this
       | information can be helpful for your next rev or next project.
       | 
       | Design:
       | 
       | - Add ESD protection to all pins exposed by connectors and around
       | the buttons. A simple TVS will work. However, the capacitance of
       | the TVS needs to be small enough to minimize burden on your
       | higher speed lines like USB and VGA. I'd use a cheap TVS for the
       | low speed pins and then maybe look at some dedicated USB-HS
       | protection parts and then just re-use those on the VGA lines. The
       | USB3300 part you're using looks to have some minimal built-in ESD
       | protection but as you observed it's probably not enough for real
       | world use.
       | 
       | - Consider a buffer between your resistor DAC and the output.
       | This could be an op-amp or a dedicated buffer chip. This will let
       | the resistor DAC operate without significant load, isolated from
       | the cable. You can then put a 75 ohm resistor in series with the
       | buffer output to get optimal impedance matching with the 75-ohm
       | VGA cable and load. You can get away with resistors connected
       | straight to the VGA cable for demo purposes, but having it
       | properly buffered and impedance matched will clean up the edges
       | even further.
       | 
       | - Look into the design of an R-2R DAC as an alternative to the
       | weighted-summing configuration you've used. You would want 0.1%
       | resistors at 8-bit depth but you'd only have to buy and manage 2
       | resistor values (R and 2R) which is helpful when doing hand
       | assembly.
       | 
       | - Better yet: This project is a good place to use a real DAC
       | chip. Resistor DACs are cool to play with and useful for ultra-
       | cheap demo boards where manufacturing cost is a high priority
       | (Like the RP2040 VGA demo) but for a hand-assembled project like
       | this a good DAC chip is great choice. It would shrink your PCB,
       | reduce assembly time, and allow you to choose a physically
       | smaller MCU package because you don't need 24 IO pins for the
       | resistors.
       | 
       | Schematic:
       | 
       | - When using hierarchical schematics it's a good practice to
       | avoid putting ICs and components in the root sheet. I suggest
       | adding additional sheets for the MCU and other parts, then
       | connect the blocks in the root. Treat the root page like a block
       | diagram.
       | 
       | - KiCAD's bus functionality could help reduce a lot of the pins
       | going into your blocks, like USB_D[0:7] and VGA_R[0:7]
       | 
       | - Breaking up that big STM symbol into a couple parts would be a
       | good way to learn how to use KiCAD's symbol editor and would
       | allow everything to fit on standard A4 sheets
       | 
       | - Don't hesitate to add notes to the schematic that might be
       | helpful during debugging, assembly, or for your future self when
       | you return to the project.
       | 
       | - I like to do a cleanup pass on schematics to make sure all
       | labels are readable and there's enough space to comfortably see
       | everything. It's a good practice to get into and pays off when
       | you're tired from a long debugging session and trying to read a
       | schematic. I suggest using the empty space on some of your pages
       | to space components out more so no text is overlapping or hard to
       | read.
       | 
       | PCB:
       | 
       | - You used 0.15mm (5.9 mil) traces almost everywhere. It's best
       | to avoid using small traces unless you have to. You want to stay
       | away from the minimum trace/space of your PCB manufacturer by
       | default and reserve those for only the places where you need it.
       | It will improve yields and make rework easier. Many of your
       | traces could be 0.25mm or 0.5mm without any problem.
       | 
       | - Likewise, avoid letting traces run too close to pads unless you
       | really need to. It's okay when you need to squeeze a trace into a
       | narrow spot, but by default you should try to give as much room
       | between pads and traces and between adjacent traces as you can.
       | The tighter the spacing, the easier it becomes to accidentally
       | short something out during assembly.
       | 
       | - Similar story with vias: Try not to use the absolute smallest
       | vias everywhere when you have space.
       | 
       | - A lot of your vias are grouped together in a way that creates
       | large slots in your ground plane. This doesn't matter too much at
       | the low speeds you're working with, but it's good practice to
       | avoid creating large cutouts in ground planes. The return current
       | has to flow somewhere and those big slots will force it to take a
       | longer path, which increases emissions and distorts high speed
       | signals.
        
         | bananaboy wrote:
         | This is great advice! Thanks!
        
           | utopcell wrote:
           | Did you consider connecting the usb3300 to the PIO?
        
             | bananaboy wrote:
             | Sorry just to clarify - it isn't my project. I just thought
             | it was a great post with some really helpful tips!
        
         | esterna wrote:
         | Do you have advice how I could get someone to do a (possibly
         | paid) review of PCBs for small hobby projects?
         | 
         | Being new to this space, it's hard to learn quickly when the
         | feedback cycle involves having PCBs manufactured, shipped,
         | soldering them and then finding out what could have been
         | better. (Or it works and you never find out what you did wasn't
         | the right way to do it)
        
           | pjc50 wrote:
           | > someone to do a (possibly paid) review of PCBs for small
           | hobby projects?
           | 
           | This is one of those awkward things where if you post to
           | r/diyelectronics you might get someone doing it for free, but
           | as soon as you try to _pay_ for it both parties realize the
           | going rate for experienced EEs is somewhere around $100
           | /hour.
        
           | bschwindHN wrote:
           | You can post to the PrintedCircuitBoard subreddit to
           | (potentially) get a review:
           | 
           | https://old.reddit.com/r/PrintedCircuitBoard/comments/zj6ac8.
           | ..
        
           | alnwlsn wrote:
           | One of the Hackaday writers does a PCB review series. It's
           | probably worth reading through to learn from past mistakes.
        
         | jrmg wrote:
         | Thanks for posting this - love this kind of positive,
         | constructive criticism. Picked up a few tips for myself from it
         | to!
        
       | dylan604 wrote:
       | The example image for blanking from pyroelectro.com seems off to
       | me. The blanking was on all sides of the images, not just two
       | sides. The beam was off before reaching the end of the line,
       | during the retrace, and still partially at the beginning of the
       | line. The same for the retrace back to the top. The vertical
       | blanking at the top of the image was important as things like CC
       | and VITC were encoded there (as well as some other non-standard
       | uses). Essentially, the active picture was window boxed in the
       | blanking. This example image does not represent that well at all
        
         | duskwuff wrote:
         | The example isn't wrong, it's just looking at the timing a
         | little differently from how you're used to. It's treating the
         | blanking time as all occurring at the end of a line, instead of
         | splitting it into front porch / back porch. This is a common
         | pattern in video generators, since it means you can use a
         | single counter for display and blanking, and define the
         | blanking condition in terms of the counter exceeding the active
         | count, e.g.                  blanking := hcount >= 640 ||
         | vcount >= 480;        output := blanking ? 0 :
         | framebuffer[vcount][hcount];
        
       | retrac wrote:
       | The new RP 2350 has an enhanced PIO that relaxes some of the
       | constraints the author ran into here.
       | 
       | Also the new HSTX (high-speed serial transmit) unit is really
       | well suited for rapid line coding.
       | 
       | Here's a different project that generates a high resolution high
       | depth VGA signal from the RP 2350:
       | https://www.breatharian.eu/hw/disphstx/index_en.html
       | 
       | And here's NTSC composite using just the original PIO:
       | https://github.com/obstruse/pico-composite8
        
         | utopcell wrote:
         | The issue was not with PIO. It was with the fact that both
         | rp2040 and rp2350 only support usb1.1, which doesn't have
         | enough bandwidth to do uncompressed ~320x240x16bpp@60Hz.
        
       | lloydatkinson wrote:
       | > I have a full CI/CD pipeline set up for my PCBs
       | 
       | Oh more on this, please!
        
       | platevoltage wrote:
       | This looks really cool. I'm restoring an 80's SEGA candy cab with
       | a CRT and have been trying to figure out the best way to most
       | accurately utilize the 15khz display in it. I tried bit-banging
       | from a Raspberry Pi's GPIO, but landed on using an AMD GPU with
       | the capability outputting a usable signal. This also looks like
       | something I want to toy around with.
        
         | Nihilartikel wrote:
         | I took the easy way out, similarly - got an ArcadeVGA pci
         | board, which is basically an ancient Radeon that supports 15khz
         | well. I drive it with a groovy arcade Linux install and a
         | pc2Jamma adapter that maps jamma buttons to keyboard input and
         | VGA to the crt.
        
       | lawrenceyan wrote:
       | There's something deeply poetic about using modern engineering
       | knowledge to breathe new life into the warm, fuzzy glow of an
       | analog CRT.
        
       | pezezin wrote:
       | The article doesn't mention what games they are actually running
       | on the arcade machine. They mentioned the 18-bit DAC being a
       | limitation, but most 2D arcade games only output 15-bit color.
       | 
       | I don't know, as impressive as this is, I think using a MiSTeR
       | would be much easier.
        
         | nicholasjbs wrote:
         | All the games are custom ones built by people at the Recurse
         | Center!
        
       | eek2121 wrote:
       | Arcade machines were so weird (and amazing). Example: A TON of
       | effort was put into copy protection, for example. There are still
       | a few games that haven't completely been broken into, despite
       | being 30-40 years old.
       | 
       | The systems from the 80s-90s were also very odd/exotic. Some
       | systems (like certain variants of Street Fighter II) had
       | interesting bugs that needed to be worked around.
        
       | Neywiny wrote:
       | Pro tip: ST actually has a free tool called CubeMX that you can
       | use to avoid the USB mistake. I've used a few H7 parts in the
       | past and it's never been something we missed. I'm actually
       | surprised people were surprised. USB high speed has very
       | different voltage levels than full and low speed, and they're not
       | ones digital chips often use, so it's very common to need an
       | external PHY. Just like Ethernet.
       | 
       | My advice is to never shoot the board before you have all your IO
       | planned out in the tool. That's saved us a bunch of times.
       | 
       | Also, give the U5 series a look? Hyperram, internal HS phy, and
       | parallel display port.
       | 
       | Also also I'm pretty sure pis can put out parallel display on the
       | 40 pin header. Maybe not 24 bit, though.
        
       | BobbyTables2 wrote:
       | Wonder if doing everything with cheap FPGA would be practical.
        
       | bschwindHN wrote:
       | Some notes because I weirdly just went through almost the exact
       | same project for work:
       | 
       | * I also started with an RP2040 because the PIO is such a good
       | Swiss Army knife for working with custom digital protocols. An
       | RP2040 with a faster USB PHY would be killer!
       | 
       | * The STM32U5 series has variants with built-in High Speed USB
       | PHYs, along with 2.5 megabytes of SRAM, along with easily
       | solderable footprints (down to LQFP64) if you want to solder at
       | home instead of having a PCB fab do it.
       | 
       | * JLCPCB and/or PCBWay can assemble boards for quite cheap these
       | days
       | 
       | * ESD protection would be good to add to the board, as others
       | have noted and as you mention in the post
       | 
       | * Ideally all routed traces which have fast rise/fall times (most
       | digital signals) should have a solid reference plane under them
       | along the entire trace, to avoid cross-talk and EMI, along with
       | vias for your reference plane if your signal changes layers.
       | 
       | * If you control the rendering, and color banding is still an
       | issue, look into Interleaved Gradient Noise
       | 
       | * I hadn't heard of GUD before. I just made a simple USB Bulk Out
       | endpoint in the firmware and in my application code, took less
       | than a day. Sometimes a custom solution is quicker and easier but
       | it depends on where it's running and who you're distributing it
       | to. Obviously my custom solution isn't interoperable with other
       | things, but for now it doesn't need to be.
       | 
       | I plan to write up a blog post on the project I worked on, I'll
       | be sure to post it to HN when I do.
       | 
       | https://blog.demofox.org/2022/01/01/interleaved-gradient-noi...
        
       | watersb wrote:
       | _> The RP2040 can only do USB FS (full-speed), which is capable
       | of 11 Mbps. At the 320x240x16 bpp we were originally targeting,
       | every frame is 153.6 kB. At our maximum USB FS speed, that 's
       | less than 10 FPS! Embarrasingly, I had originally done the math
       | with a bandwidth of 11 MBps, not 11 Mbps, so I was off by a
       | factor of 8._
       | 
       | I wrote a book about Windows NT Server system administration, and
       | sustained this error through chapters discussing hard disk and
       | network bandwidth.
       | 
       | God bless my technical editor, who caught this before
       | publication.
        
       | account42 wrote:
       | > I actually made decent progress here, although I kernel
       | panicked many, many times. I never bothered to set up a proper
       | development environment (oops), so pretty much any bug would
       | require me to reboot my computer. This was super annoying and
       | tedious, although I did learn a lot. I found cursed things in the
       | official documentation, like interrobangs!
       | 
       | Wouldn't it be trivial to do this development in a VM with USB
       | pass-through?
        
       | tracker1 wrote:
       | Definitely a cool story and really happy to see people being
       | really open with their code, as well as hardware designs/plans.
       | It's an area that could/would be pretty easy to gatekeep and lock
       | away.
        
       | cactacea wrote:
       | > I did a lot of digging, before finding this hidden in the
       | datasheet
       | 
       | Ah yes, gotta love it when you get screwed because you missed one
       | sentence in a 642 page doc. I can relate
        
       ___________________________________________________________________
       (page generated 2026-02-05 23:01 UTC)