NOTE: Expect updates after the TT04 datasheet is made. Check tt04-raybox-zero’s README (https://github.com/algofoogle/tt04-raybox-zero) for latest info.
This framebuffer-less VGA display generator is ‘racing the beam’ to yield a simple realtime “3D”-like render of a game map using ray casting. It’s inspired by Wolf3D and based on Lode’s Raycasting tutorial (https://lodev.org/cgtutor/raycasting.html). Think of it as a primitive ‘GPU’ using a grid map of wall blocks, with basic texture mapping and flat-coloured floor/ceiling. No doors or sprites – but maybe in TT05? In TT04’s 130nm process we use 4x2 tiles (~0.16mm²) at ~48% density.
Without a framebuffer, rendering/animation occurs at full speed. Registers store the
‘POV’ (Point of View) to render. It’s expected that a host controller
implements game/motion logic and calculates the POV, then sending it to the chip via SPI
mosi). An MCU or low-spec CPU should do. I’ve been bit-banging
SPI with a Raspberry Pi Pico.
At reset the POV registers are set to an angled view of the inbuilt 16x16 grid map.
NOTE: “FPS games” like Wolf3D use a landscape display, i.e. normal desktop monitor orientation. I designed this as a portrait display (rotated 90° clockwise) for silicon area optimisations that come with rendering by scanline instead of by column. If you don’t want a sideways monitor, design a game/demo using this different perspective. For example, image Mario’s 1st-person view of his 2D platform world…
As stated, this is designed to drive a display with a portrait orientation when used as a “first person shooter” but BEWARE: The backlights failed on two old flat panel VGA displays (from circa 2003) not long after I turned them on their sides. Coincidence? Age? A CCFL failure mode? Not sure. I’m using a monitor from 2008 now.
Attach a VGA connector’s HSYNC and VSYNC to the chip’s respective outs with (say) inline 100R resistors
for protection. Connect at least
blue with inline 270R resistors,
or better yet use an R2R DAC on each colour output pair. Make sure VGA GND is connected, of course.
reg to select ‘registered outputs’. Without this, you will get the unregistered versions, which
might be murky or have some timing issues – I included this option for testing purposes.
In the actual ASIC version of this, I expect the registered outputs will be much cleaner, but we’ll see.
Supply a 25MHz clock (or ideally 25.175MHz), and assert the
reset signal, and you should get a
clockwise-90°-rotated display of textured walls with dark grey ceiling (right-hand side)
and light grey floor (left-hand side).
Pull up the
debug input and you should see little squares show up in the corner of the screen that
represent the current state of the POV registers.
Pull up either/both of
inc_px/py and the view should drift along slowly.
This is ‘demo mode’. Don’t be alarmed when it goes through walls, or for periods when you see half the
screen is just grey and the other half is flickering different colours – this just means you’re moving
through a wall block.
|0||SPI in: sclk||hsync_n||Out: o_hblank|
|1||SPI in: mosi||vsync_n||Out: o_vblank|
|2||SPI in: ss_n||red||SPI2 in: reg_sclk|
|3||debug||red||SPI2 in: reg_mosi|
|4||inc_px||green||SPI2 in: reg_ss_n|