Skip to content

Commit d41a969

Browse files
authored
Merge pull request #20 from rejunity/vga
Update VGA peripheral 12 docs
2 parents fdf0dc2 + 8b0a770 commit d41a969

File tree

1 file changed

+76
-4
lines changed

1 file changed

+76
-4
lines changed

docs/user_peripherals/12_vga.md

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,65 @@ You can also include images in this folder and reference them in the markdown. E
1111
512 kb in size, and the combined size of all images must be less than 1 MB.
1212
-->
1313

14-
# VGA adapter for TinyQV
14+
# 4 color flexible resolution VGA adapter for TinyQV
1515

1616
Author: ReJ aka Renaldas Zioma
1717

1818
Peripheral index: 12
1919

2020
## What it does
2121

22-
TODO: Explain what your peripheral does and how it works
22+
Flexible VGA framebuffer that allows multiple resolutions, up to 4 colors per scanline, 64 unique colors per frame and provides 1024x768 60Hz video signal (64 MHz pixel clock) suitable for a [TinyVGA PMOD](https://github.com/mole99/tiny-vga).
23+
24+
By default it is configured to display **20 x 16 pixels** choosing colors from a 2 entrees palette. Each pixel is 1 bit where 0 selects background and 1 foreground color. In this configuration CPU is completely free to attend to other tasks.
25+
26+
### Racing the Beam
27+
28+
This peripheral is inspired by the 8-bit era designs when Video RAM (VRAM) was prohibitively expensive and there was not enough memory worth of the whole screen resolution - frankly the situation is similar with Tiny Tapeout and TinyQV peripherals where the amount of memory bits is very limited.
29+
30+
Instead of large framebuffers, **Racing the Beam** technique was utilised to synchronize CPU with video signal and allow CPU to modify pixels in VRAM immediately after they have been displayed, forming the image of high resolution line by line.
31+
32+
**Racing the Beam** means that CPU has to run in tandem with video signal:
33+
- **interrupts** can be used for a coarse wait - for the start of the frame or scanline,
34+
- **blocking reads** for precise syncronisation - for scanline or even in the middle of the scanline.
35+
36+
Racing the Beam requires high CPU utilisation to support high screen resolutions. In the case of game, CPU could be processing game-pad inputs and executing gameplay logic only during the vertical blanking. The vertical blanking happens between scanlines 768 and 804 - roughly just 5% of the whole frame.
37+
38+
Of course sacrifice up to 95% of CPU time is significant, but it might be worth for games or graphical demos. With this peripheral, it is up to you to decide!
39+
40+
### Technical capabilities
41+
42+
A very wide range of possible resolutions:
43+
- from 16 x 10 4-color to 1024 x 768 2-color modes,
44+
- vertical and horizontal counters define the size of the pixel,
45+
- visible portion of the horizontal line can be set to 960 or 1024 clock cycles.
46+
47+
The resolution of the screen, as well as 2 or 4 color mode can be changed at any point of the frame providing extra flexibility.
48+
49+
Video RAM and color palette:
50+
- **320 bit** of Video RAM worth of 320 or 160 pixels depending on the color mode,
51+
- configurable stride in bits for each new row of visible pixels,
52+
- up to 4 color palette, can be modified at any point of the frame.
53+
54+
**Coarse** and **precise** syncronisation primitives:
55+
- interrupts,
56+
- cycle accurate blocking of the CPU,
57+
- register to read out the current scanline number of the video signal.
58+
59+
### Syncronisation primitives
60+
61+
Syncronisation between CPU and video signal can be used either to update
62+
63+
User interrupts can be triggered by:
64+
- end of the frame,
65+
- end of the visible portion of the scanline,
66+
- end of the row of pixels
67+
68+
CPU can be blocked with cycle level precision until:
69+
- end of the visible portion of the scanline and start of the horizontal blanking is reached - `WAIT_HBLANK`
70+
- the first pixel of the Video RAM was visualized and can be safely be modified by CPU again - `WAIT_PIXEL0`
71+
72+
Read-only register to access the current scanline number - `SCANLINE`.
2373

2474
## Register map
2575

@@ -45,8 +95,30 @@ TODO: Explain what your peripheral does and how it works
4595

4696
## How to test
4797

48-
TODO: Explain how to use your project
98+
### Default 20 x 16 pixels
99+
100+
By default VGA peripheral is configured to display screen resolution of 20 x 16 pixels.
101+
Write to `PIXELS` register to change the pixels. Each pixel is 1 bit and CPU is free to attend to other tasks.
102+
103+
### 4-color 160 x 192
104+
105+
By default VGA peripheral will count 1024 cycles per visible line, however 1024 is not divisible by intended resolution of 160 pixels. You can shorten the screen width to 960 clocks instead since 960 are nicely divisible by 320. This is achieved by setting the **5th bit** of `MODE` register.
106+
107+
4 colors mode is enabled by setting the **6th bit** of `MODE` register.
108+
109+
The whole 160 pixel row nicely fits into the 320-bit VRAM and every new row of pixels will start from the very beginning of VRAM, therefore `VRAM_STRIDE` will be 0 (-1 will have the same effect reseting VRAM address to 0 at every row).
110+
111+
Finally, calculated pixel horizontal and vertical counters dividing 960x768 the visible VGA resolution by the inteded frame resolution 160x192 and subtract 1. Write counter values in `PIXEL_SIZE` register.
112+
113+
register[MODE] = 0b0011_0000
114+
register[VRAM_STRIDE] = 0
115+
register[PIXEL_SIZE] = (960 // 320 - 1) | ((768 // 192 - 1) << 16)
116+
117+
To **Race the Beam** block CPU until the next horizontal blank reading from `WAIT_HBLANK` registe, then write into the `PIXELS` as fast you can!
118+
119+
y = register[WAIT_HBLANK]
120+
register[PIXELS] = ...
49121

50122
## External hardware
51123

52-
Tiny VGA Pmod
124+
[TinyVGA PMOD](https://github.com/mole99/tiny-vga)

0 commit comments

Comments
 (0)