15KHz Video generation - makapuf/bitbox GitHub Wiki
The default bitbox video modes are compatible with VGA timings. This can be used with any PC monitor from the last 3 decades. This page is about getting the bitbox to work in a way that's compatible with RGB signals as used on the SCART/Péritel connector, which was used for most of the 1980s.
Why would we do that?
There are actually several reasons:
- Ability to use 15KHz displays (Commodore 1084s, Amstrad CTM640, Arcade monitors) and anything with a SCART input. No need to unplug the monitor from your PC each time you want to test something with the bitbox ; and you can use these lovely CRT displays with clear picture and beatiful scanlines (who don't love scanlines?) for a true oldschool feel.
- More CPU time: since the horizontal frequency is about half of the VGA one, the same pixel clock gives twice as much horizontal resolution. This means the DMA uses the memory bus a lot less, leaving more time for the CPU to run.
- No need for "line doubling" hacks. The vertical resolution is 271 lines, which is low enough to not need line doubling. Interlacing can be used to get 542 lines, of which only half need to be rendered each frame. Modern LCD TVs will deinterlace this, which means we can get a rather high resolution (up to 1200x542 or so) without overclocking. In VGA, the vertical resolution will be twice as high, and most games and "simple" video modes actually display each line twice so they have enough CPU time to do everything they need for each line.
- More video resolutions. From the base config of 168MHz, 11 "reasonable" resolutions are possible, ranging from 144x271 to 1002x271 pixels. They all can have an alternate interleaved version, with doubled vertical resolution. There are some modes with higher and lower resolutions possible, too.
- And finally, this article helps everyone get more knowledge of video signals in general and how the bitbox generates them in particular.
How does it works?
Video generation basics
You may have read the "racing the beam" articles already. The generation of the video signal is actually pretty simple, and quite similar for VGA and RGB-SCART.
The display data is sent from the bitbox to the display line by line, starting from the top of the screen. At the end of each line, there is a synchronization pulse on the HSYNC pin. The last few lines of a frame are used for synchronization, which is marked with a pulse on the VSYNC line. Then we start over with the next frame.
Video timings and resolution
The resolution and timings in the video signal are always linked together. We will base our computations on the "pixel clock". This defines the time it takes for one pixel to be sent to the display. A faster pixel clock means a higher resolution, at constant frame rate, or a higher frame rate, at constant resolution.
The frame rate is the number of frames we can display in one second. It is defined by the time between two VSync pulses.
One frame is of course made of several lines. The frame duration is shared evenly between these lines. This means, with a constant pixel clock, that increasing the horizontal resolution will make each line take more time, this needs to be compensated by having less lines displayed.
VGA versus RGB-Scart
The main difference between the two formats is in the video timing. VGA is quite flexible, especially with modern displays. The constraints are roughly these:
- Horizontal synchronization (new line) at 30KHz or more,
- Vertical synchronization (new frame) at 50Hz or more. The timing of the pixels within a line are completely free (you can have just one pixel per line, or you can have several thousands if you can send them fast enough). The number of lines is constrained by the ratio between the chosen horizontal and vertical synchronization (or rather, you usually pick a desired vertical resolution and frame rate, and see if you can find an horizontal sync rate that matches).
For RGB-SCART, the timings are derived from the PAL standard. They are as follows:
- Horizontal synchronization at exactly 15625Hz (one pulse every 64µs)
- Vertical synchronization every 312.5 lines for interlaced mode. We won't use interlaced mode for now, so we can use 312 lines, which gives a refresh rate slightly above 50.08Hz. This is how it is done in all PAL devices using progressive scan, and TVs have no trouble with it.
Unlike VGA, the timing of the horizontal and vertical resolution are fixed. This means the vertical resolution is also fixed to 312 lines. Of these, not all are visible. As already mentionned, some are used for vertical synchronization, and before and after that there must be an area filled with black. In the end, we get about 271 lines of useable display area.
We are still free to change the pixel clock, which will have an effect on the horizontal resolution, only.
Signal generation on the bitbox
The bitbox uses a timer to generate the horizontal synchronization. This timer fires various events used to sequence all the video generation logic. The horizontal sync signal is entirely handled in hardware as a PWM output. Basically, it marks the start of each line and we can only configure its width (more on that later).
The timer also triggers an interrupt, which in turn is used to run the pixel DMA. A short delay after the horizontal pulse end, the DMA starts putting pixel data on the RGB outputs (at the speed defined by the pixel clock). It stops after sending one whole line, by outputting black. Shortly after that, the next pulse happens and the cycle starts over.
The interrupt handler also checks which line is being scanned. If it is a "display" line, things are done as described above. If it is a "porch" line, it works the same, but the DMA isn't triggered (so the line is black). If it is a vsync line, the VSYNC pin is also pulled low.
Composite synchronization
This is the other key difference between VGA and RGB-SCART. Instead of using two pins for the synchronization, a single "composite" pin is shared. To signal the vertical sync, we have to send "long" pulses of almost the full frame width for horizontal synchronization. For all other lines, we use a short pulse. The TV detects the long pulses and knows it needs to start a new frame.
Configuring it
The composite sync requires changes to new_vga.c (see the patch linked at the end of the article). The timings, however, can be adjusted in kconf.h where we define all video modes. The modified kconf.h included in the patch let you play with two settings: the main CPU clock speed, and the divider for DMA. These together define our pixel clock, from which we then derive the other timings.
There is one more thing we can control: we can use larger "porch" areas, effectively adding a black border around the screen. This can be used to reduce the video resolution and round it to any convenient size (powers of two, or anythin small enough it can be rendered in the allocated time).
Available modes
The default CPU speed of 168MHz gives us a good choice of modes. Remember that we need the horizontal sync to happen exactly every 64 microseconds, so the timer must run at a multiple of 15625Hz. At 168MHz, this means a sync pulse every 10752 clock cycles.
We can then run the DMA at any speed we want. For the VGA modes, we were using the highest possible DMA speed settings to get a reasonable resolution. This also meant the gap between two DMA speeds was huge (going from 6 to 7 cycles is a 15% decrease in resolution!). In PAL timings, we are much more relaxed: the highest speed of 6 cycles would give a horizontal resolution of 1344px, which is far too small to be readable. At a setting of 10, we are close to the Atari ST "medium" resolution, or Amstrad CPC "mode 2". the pixels have a 2:1 aspect ratio (vertical rectangles), and our resolution is 806x271. At a speed setting of 21, we have a resolution of 384x271, with the same pixel aspect ratio as Amstrad CPC "mode 1" or Atari ST "low" resolution (almost square). A speed setting of 22 can be used, getting almost square pixels on a 4:3 screen and a resolution of 366x271.
We can also get much lower resolutions. A DMA divider of 42 will give us the same resolution as Amstrad CPC mode 0, with 1:2 pixel aspect ratio (wide pixels). We can go further down from there, until there is only 1 pixel left on each line. This means almost any sensible or crazy resolution can be achieved, and instead of the DMA interrupting the CPU every 6 cycles to get a byte from the RAM, it will be doing so only every 22, or 42 cycles, leaving more time for the CPU to do useful stuff.
Wiring
| VGA | SCART | CTM | Name |
|---|---|---|---|
| 1 | 15 | 1 | Red |
| 2 | 11 | 2 | Green |
| 3 | 7 | 3 | Blue |
| 5 | * | 5 | GND |
| 13 | 20 | 4 | Sync |
| 14 | 16** | N/C | (VSync) |
Notes:
- Scart ground is on pins 18,5,9,13, and a few more.
- VGA pin 14 is normally vertical sync. We don't use that because our sync is composite. The SCART standard says we should put 1 to 3 volts on pin 16 to force it to RGB mode. Since the TV should have 75ohm impedence, we use a 160ohm resistor, giving us 1.05 volts. This gives us a 14mA load on the pin, which is ok (the STM32 can source up to 25mA). An higher resistor would sink less current but we would be below 1V. A lower resistor will result in more current going there, and the bitbox heating more (it become dangerous with values below 57 ohms).
Compatibility
This has been tested on various devices:
- Commodore 1084s (CRT): ok
- Gonbes GBS8200 scandoubler: ok
- Amstrad CTM 640 (CRT): ok, picture is a bit dark
- Beko LCD TV: ok
- Linetech LCD TV: ok
- Philips "Hotel TV" (CRT): does not sync - should try with a resistor on the hsync line to lower the voltage?
Next steps
- Integrate into the kernel
- Convert games and other software so they support these new video modes
- Try to generate an interlaced picture and support interlaced modes in software (render even lines in one frame, odd lines in the next)
- Try to generate a full composite output signal (with PAL color bursts and all the fun stuff)
Where is the code!
You can get the patch to the bitbox kernel here: http://pulkomandy.tk/drop/bitbox_15KHz.diff This has been integrated in mainkernel since commit 22587f0