I wanted to share a project I've been working on recently, which has today graduated from 'mess of wires' into a real PoC I'm building a digital video DVI/HDMI output adapter for the Archimedes:
This is a photo of my bench test monitor showing mode 23 from my A3000. (The monitor's confused; it really is 1152x896!) I like this shot both because the A3000 "cannot do mode 23", and because this is my trusty A3000 from back in the day, first used with a miserable 9" mono/green monitor. Quite the difference!
The approach taken is to passively snoop on VIDC's signals (with VIDC remaining in circuit), in order to capture the VIDC register state, and video, cursor (and eventually sound) DMA transfers. For this demo, a board clips onto the soldered VIDC using the upside-down PLCC socket trick:
The black board holds the socket and some 74'245-like 5V to 3.3V buffers, series termination. The data bus, VIDC clock, VIDRQ/VDAK, SDRQ/SDAK, flyback, HSYNC/VSYNC and VIDW strobes are exported over the ribbon cable to an FPGA board. Here, I'm prototyping using an ULX3S board (which handily has an HDMI-style socket on it). (I think approaches, such as using a CPLD/tiny FPGA to reformat suitable for a RPi's SMI, are also possible, but I <3 FPGAs so that's what I've used.)
Roughly, this is what the FPGA design does: This circuit is not software-visible/doesn't require any software changes. It is subordinate to VIDC, which RISC OS programs as usual, and "passively" observes VIDC going through the motions of generating syncs and doing DMA cycles. (VIDC's output is unused.)
The VIDC DMA transfers are captured directly into a double-buffered line buffer, which is scanned out. In this setup, the FPGA is directly generating the DVI signal (using Mike Field's vga2dvid module), from its own video timing. The internal video timing is synchronised to the Arc's VSYNC (FLYBK, actually) a bit like a genlock, so the DVI output is running exactly 1 line behind the Arc's output.
I wanted to choose the high-res mode 23 first, mostly because I'd never (for obvious reasons) seen my A3000 do it, but also as a limit case test (do the hard one first). Mode 23 has a 96MHz pixel clock, but that's because it was simpler for the Arc's designers to do integer clock multiple/divisors from the VIDC clock (x4): for the mode, it's got enormous borders/porches compared to VESA, and a pixel clock nearer 80MHz is much more appropriate for this mode. (shrug) That's an issue as 96MHz is much too quick for this FPGA + the "soft DVI" design.
So, this system uses a 78MHz pixel clock (derived from 24MHz VIDC clock x3.25). At 96MHz, the mode 23 1568 pixel horizontal cycle is output in the same period of time as 1274 pixels at 78MHz. A matching horizontal period is key here, so the scan-in and scan-out stay in exact sync without over- or under-run (given they ultimately run from the same VIDC clock). Even at 78MHz, the tools are struggling to meet timing on this FPGA part (a Lattice ECP5 with nextpnr-ecp5). I'll try with Diamond, which may help. Many of the failed-timing bitstream builds turn out like this:
You can still see some more minor artefacts on the first (grey, nice) screenshot that are due to the "soft DVI" core not (being compiled so it can be) meeting timing -- it's not my circuit, your honour.
Many caveats today:
- I got this fully working about an hour ago, so it's pretty raw But such fun! Thought y'all might like to see it.
- The palette registers are captured, but I haven't implemented video palette lookup, so it won't do regular colour modes yet. That's next.
- It doesn't yet support sound. There are multiple options here, e.g. a sigma-delta DAC, SP/DIF or even HDMI audio.
- The cursor/pointer is manky (but better than the black square I used for test ). There's some funny bit ordering that the data sheet doesn't explain. Easy to fix tho.
- The screen mode is hard-wired currently, but the idea is the embedded CPU will "notice" screen mode changes and configure the video output appropriately. Note it isn't necessarily just 1:1, some modes could have different output timing in order to accommodate DVI-compatible modes with the same resolution as the Arc mode.
Feature-wise, implementing the palette and being able to display the VGA modes is next, then I want to do line-/pixel-doubling. For example, DVI outputs 640x512 and mode 13 gets a 2x/2x scale, mode 12 gets a 1x/2x scale, mode 21 gets a 1x/1x scale.
Version 2: But then, I was thinking to add a 24-bit palette (by finding an unused VIDC reg to use as an extension reg, or port-knocking), for the 1/2/4BPP and 8BPP modes. The FPGA can easily store 256 palette entries instead of 16. I'll be asking all kinds of dumb ColourTrans questions at that point, I'm sure At this point it starts to look a little like a ColourCard in capability, e.g. display any mode that MEMC can address and VIDC can shuffle data for. For example, generate a 16BPP mode by programming VIDC like mode 15 (640x256 8BPP) but output it as 320x256 16BPP.
Version 3: THEN, the question comes up as to frame buffering and going "Full Colourcard" to decouple VIDC pixel clock from output pixel clock, e.g. get VIDC to output 1024x768 at 20Hz, and get ArcDVI to scan that out at 75Hz. This requires memory to buffer the frames.
Implementation-wise, these pictures/mess of wires are obviously just a PoC. As well as the A3000 board, I built another board (that I can't find to photograph right now ) which is an interposer for VIDC-socketed machines like A440. It plugs into the VIDC socket, then VIDC plugs into it. I see ArcDVI as a stacked 2-board solution, to cope with the different machines. Maintaining two designs of one-board solutions would get grim, I think. Aside from hack value, the "soft DVI" solution isn't ideal. IMHO using a dedicated DVI serialiser like a TFP410 is a good approach, except that's quite an expensive additional part, whereas the in-FPGA solution is free-ish. That said, it might enable a cheaper FPGA to be used. Eventually, it'd be cool to develop a plug-in "product" for this, but you can't even buy parts today so that's a while away.
I'll get the boards (~trivial) and FPGA design on GitHub at some point if there's interest. It's not very clean at the minute, but I do intend this to be an open source design.