[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)