Additional Documentation

This commit is contained in:
Wayne Venables
2023-03-10 23:17:15 -08:00
parent ebe6230f3e
commit 9ed187bfce
5 changed files with 297 additions and 2 deletions

87
GettingStarted.md Normal file
View File

@@ -0,0 +1,87 @@
# Getting Started {#gettingstarted}
## Installing PicoVGA
1. Make sure you have the [Pico SDK](https://github.com/raspberrypi/pico-sdk) installed.
2. Clone the PicoVGA repository
~~~
git clone https://github.com/codaris/picovga-cmake.git
~~~
3. Set `PICOVGA_PATH` to the PicoVGA directory in your environment, or pass it (`-DPICOVGA_PATH=`) to cmake later.
## Building the Examples
The PicoVGA project comes with a comprehensive set of example programs that demonstate many of the features of the library. These examples are located in the [`examples`](https://github.com/codaris/picovga-cmake/tree/main/examples) folder of the PicoVGA project.
To create the makefiles, run this CMake command from the main PicoVGA folder:
~~~
cmake .
~~~
Then to build all the example projects at once, you run make (please note this might take a long time):
~~~
make
~~~
This will generate a `.uf2` file for every example program in the root folder of each example.
If you want to build a single example program, you can run make for just that example:
~~~
cd examples/vga_hello
make
~~~
If you don't want to mix the build files with the rest of the code, you can specify a separate build folder when running CMake:
```
cmake . -Bbuild
```
This will generate all the makefiles and build outputs into the `build` folder.
After you build one or more example files, the compiled output will be generated as `program_name.uf2` file where `program_name` is the name of the example. They are compiled for a VGA monitor and USB serial keyboard input. Load them into the Pico by copying the `uf2` on the Pico when it's in bootloader mode (hold the bootsel button when connecting to your computer).
Many of the examples use a USB serial connection for controls.
## Integrating PicoVGA into Your Project
The easiest way to incorporate the PicoVGA library into a project is to examine or copy the [sample project](https://github.com/codaris/picovga-helloworld).
To add PicoVGA to an existing project you must do the following:
1. Copy the `picovga_import.cmake` file from the PicoVGA library folder into the root of your project.
2. Copy the `vga_config.h` file from the the PicoVGA library folder into the source or include files folder in your project.
3. Include that file in your `CMakeLists.txt` file:
~~~
include(picovga_import.cmake)
~~~
4. For every target that uses PicoVGA, add PicoVGA to that target with the `add_picovga()` macro in the `CMakeLists.txt` file:
~~~
# Add PicoVGA to the target (in this case "helloworld")
add_picovga(helloworld)
~~~
5. Ensure that the folder containing the `vga_config.h` is included in the target include directories in `CMakeLists.txt`:
~~~
target_include_directories(helloworld PRIVATE
${CMAKE_CURRENT_LIST_DIR}/src
)
~~~
Run the command `cmake .` to generate the makefiles for the project and `make` to build the project.
## Configuring PicoVGA
The `vga_config.h` contains the PicoVGA library settings, such as the size of the render buffers. You usually do not need to pay attention to this file. You usually only have to modify it in the following cases:
* When you use a display resolution greater than 640x480 pixels. Typically, the configuration file sets the maximum resolution to 640x480. This must be adjusted at higher resolutions to allow the library to reserve larger buffers for rendering functions.
* If there is not enough RAM. There is still some headroom where you can save some memory. First, you can reduce the MAXX, MAXY, and MAXLINE resolution settings down to a real values. Next, you can reduce the number of LAYERS down to the actual value used (in the range of 1 to 4). Finally, you can reduce the number of segments and stripes to the actual value SEGMAX and STRIPMAX (minimum is 1).
* The third case is to use of a large number of display stripes and segments. Normally, the values here are set to 8 stripes (=horizontal strips) and 8 segments (=vertical division of each strip).

View File

@@ -6,7 +6,7 @@ The library always runs on the second core of the processor and the program on t
If the second core is not very busy (e.g. when displaying 8-bit graphics that are simply transferred using DMA transfer), it can also be used for the main program work. However, some limitations should be taken into account - the program in the second core should not use interrupts (it would interfere with the rendering function), the interpolation unit should be used with caution (the rendering function does not save its state) and it must not disable interrupts.
An important rule is that all data to be accessed by the PicoVGA library must be stored in the RAM memory. External flash memory is slow and cannot be used for rendering functions. For example, if a flash image is to be displayed, it must first be copied to a buffer in RAM, and then a pointer to the RAM copy of the image will be passed to the rendering function. If a pointer to the image in flash were passed to it, slow access to flash would cause video dropouts. In addition to images, this also applies to fonts and tile patterns, for example.
An important rule is that all data to be accessed by the PicoVGA library **must be stored in the RAM memory**. External flash memory is slow and cannot be used for rendering functions. For example, if a flash image is to be displayed, it must first be copied to a buffer in RAM, and then a pointer to the RAM copy of the image will be passed to the rendering function. If a pointer to the image in flash were passed to it, slow access to flash would cause video dropouts. In addition to images, this also applies to fonts and tile patterns, for example.
The limited rendering speed must be taken into account when scheduling screen layout. Some modes render very fast (e.g. 8-bit graphics are just transferred from the frame buffer using DMA) and some modes are very rendering intensive - e.g. rendering sprites in slow mode. When using demanding rendering, some video lines may not render fast enough in the required time and the video image will break (drop out of sync). In such cases, it is necessary to use another mode, or to reduce the rendered area (add other modes, faster ones - e.g. add tile controls on the sides of the screen), reduce the screen resolution or increase the CPU clock speed. Video lines are rendered separately and therefore it is always just content on one video line about, video lines do not affect each other. For example, you can test the speed of sprite rendering by placing all the sprites horizontally next to each other (the most challenging case) and check if the video synchronization fails.

96
examples/Readme.md Normal file
View File

@@ -0,0 +1,96 @@
# PicoVGA Example Programs
### Ants
Card game (sound). Two anthills compete for supremacy. The goal is to build a higher castle. Controls: J left, L right, space select card, D discard, H help, Q quit. Can be played against another player or against the computer.
|![](../www/img/ants_m.jpg)
![](../www/img/ants2_m.jpg)
### Balloons
Demonstration of sprite use, flying balloons (43 sprites in total).
### Draw
Demonstration of drawing graphic elements. For the demonstration, alternate between slow rendering and drawing at maximum speed.
### Earth
Rotating globe. Software spherical image transformation.
### Eggs
Logic game (sound). Based on the game Reversi. The goal is to get as many of your own stones as possible. One player changes stones in the direction of hen-chicken-egg, the other player in the opposite direction. Controls: L right, I up, J left, K down, H help, Q end, P 2 players, D demo, space bar to place stone, Enter ok. Can be played against another player and against the computer.
### Fifteen
Logic game (sound). The objective is to sort the stones in order from 1 to 15. Controls: L right, I up, J left, K down, Q new game.
### Flag
Fluttering flag
### Ghost Racing
Car racing (sound). After passing the first lap (checkpoints are required), a rival "ghost" appears, which copies your previous path. You are competing with yourself. There are a total of 2 ghost opponents in the game (the second one should appear after the second lap). The game is unfinished - I couldn't calculate the correct transformation of the opponents' image into the camera and it is now only very approximate. It's more of a half-finished game for inspiration and to demonstrate 3D terrain projection (tile areas). Controls: I gear up, K gear down, J left, L right. 5 gears can be shifted. Originally, reverse was possible, but it was rather hindering.
### Gingerbread House
A fairy tale book about a gingerbread house. The program serves as a demonstration of working with images with RLE compression. Control: J previous page, L next page.
### Hello World
The simplest example of using the PicoVGA library.
### Hypno
A hypnotic rotating pattern. Example of matrix image transformation.
### Level Meter
Music spectrum indicator simulation (sound). The program uses a gradient graph level display mode. The input for the display is an array of values. There is no need to generate the indicator image programmatically and so a very fast response to change can be achieved. Random samples are used in the demo.
### Life
Cell life simulator (cellular automaton). Cells change at each step according to the number of neighboring cells: for 1 or less a cell dies on isolation, for 4 or more a cell dies on overpopulation, for 3 a new cell is created, for 2 there is no change. In the game, you can switch between 10 screens (slots) and transfer the image between them using the clipboard. In each slot there is a predefined definition of popular combinations. Controls: L right, I up, J left, K down, C copy to clipboard, V insert from clipboard, D clear area, space bar change cell, Enter start/stop generation, 0-9 select slot.
### Lines
Relaxation line pattern generator.
### Mandelbrot
Fractal pattern generator of Mandelbrot set. Integer mathematics is used to generate the pattern, which makes the redrawing fast. However, it must be taken into account that as the scale of the display increases, increasing accuracy in the number of digits is required. The used integer and float mathematics are sufficient up to a magnification scale of 10^5, double mathematics up to a scale of 10^10. When zooming in further, only colored lines are displayed instead of the pattern. Controls: E up, S left, D right, X down, Q scale up, A scale down, L low resolution selection 132x100, M medium resolution selection 264x200, H high resolution selection 528x400, I switch to integer math (fastest, range up to 10^-5), F switching to float math (slowest, range up to 10^-5), B switching to double math (slowest, range up to 10^-10), O decreasing the number of iteration steps, P increasing the number of iteration steps, U increasing the system clock, T decreasing the system clock, space redraw screen.
### Matrix Rain
"Matrix code rain" simulation. It uses text-based video mode.
### Maze
The goal is to find a way out of the maze. The mazes are generated randomly programmatically. Controls: J left, I up, L right, K down, H help (showing the door).
### Monoscope
Video modes test. The keys 0 to 9 and A to U can be used to switch the display resolution, from 256x192 to 1280x960, for both VGA monitor and PAL/NTSC TV.For the TV, interlaced video is used for higher resolutions (such as broadcast TV), and progressive mode is used for lower resolutions (such as the outputs from 8-bit computers). Can be used to test the display on different devices. The individual test patterns are stored in the program as prepared images with RLE compression. It would be possible to modify the program to use only 1 image, which would be recomputed as needed, but would have to be compressed into RAM with RLE compression when generated, as it would not fit in RAM at full size.
### Oscilloscope
Demonstration of oscilloscope signal display. The program uses graph and curve display mode. The signal waveform image does not need to be generated in software, only the array of values is passed to the display, and this allows a very fast response to changing values. In the demo the samples are generated programmatically. It also serves as a demonstration of stacking image segments in different modes. The basic oscilloscope image is an 8-bit bitmap (with dithering), consisting of 4 stripes. In place of the screen, 2 elements are used to display graphs. The screen is overlaid by a transparent overlay with a grid.
### Pac-Man
Popular action game (sound). The game attempts to emulate the original 1980's version of the game by Namco. The logic of ghost behavior, score and level counting is followed. I would like to point out that the sounds and appearance are taken from the original game, they are covered by Namco's copyright, and therefore the game serves only as an inspirational sample. Controls: J left, I up, L right, K down, A pause.
### Pi
Calculating the number Pi to 4833 digits. After the calculation, the result is checked against the expected sample.
### Pixels
Random generation of colored pixels.
### Raytracing
3D pattern generation by ray tracing method. Due to the limited color depth of PicoVGA, raster dithering ("graininess" of the image) is used in the display.
### Sokoban
Logic game (sound). The goal is to move the crates to the marked fields. The game contains 3000 levels from different authors, along with their solutions. Controls: L right, I up, J left, K down, H help (level solution), R restart level, Q previous level, W next level, P print info.
### Spheres
Random spheres generation.
### Spots
Random generation of spots.
### Tetris
Popular game, stacking blocks (sound). Control: L right, I turn, J left, K lay, A pause.
### Train
Logic game based on the principle of the Snake (sound). The goal is to collect all objects and pass through the gate. The game has 50 levels, along with their solutions. Controls.: L right, I up, J left, K down, H help (view solution of the level), Enter enter password, Esc back, BS delete character of password.
### Twister
Twisting of the textured block. It serves as an example of programmatic image deformation, using a hardware interpolator.
### Water Surface
Simulation of rippling water surface (sound).

View File

@@ -130,7 +130,7 @@ typedef unsigned char Bool;
* 14 and 16 line fonts in the library. Fonts are exported by the RaspPicoImg utility to *.cpp source text format,
* and are added to the program as a byte array.
*
* Example of font font_bold_8x8:
* Example of font FontBold8x8:
* ![](www/img/font1.jpg)
* @{
*/

112
vga_config.h Normal file
View File

@@ -0,0 +1,112 @@
// ****************************************************************************
//
// VGA configuration
//
// ****************************************************************************
// === Configuration
#define LAYERS 4 // total layers 1..4 (1 base layer + 3 overlapped layers)
#define SEGMAX 8 // max. number of video segment per video strip (size of 1 sSegm = 28 bytes)
#define STRIPMAX 8 // max. number of video strips (size of 1 sStrip = sSegm size*SEGMAX+4 = 228 bytes)
// size of sScreen = sStrip size*STRIPMAX+4 = 1828 bytes
#define MAXX 640 // max. resolution in X direction (must be power of 4)
#define MAXY 480 // max. resolution in Y direction
#define MAXLINE 700 // max. number of scanlines (including sync and dark lines)
// === Scanline render buffers (800 pixels: default size of buffers = 2*4*(800+8+800+24)+800 = 13856 bytes
// Requirements by format, base layer 0, 1 wrap X segment:
// GF_GRAPH8 ... control buffer 16 bytes
// GF_TILE8 ... control buffer "width"+8 bytes
// GF_TILE16 ... control buffer "width/2"+8 bytes
// GF_TILE32 ... control buffer "width/4"+8 bytes
// GF_TILE64 ... control buffer "width/8"+8 bytes
// GF_PROGRESS ... control buffer 24 bytes
// other formats: data buffer "width" bytes, control buffer 16 bytes
#define DBUF0_MAX (MAXX+8) // max. size of data buffer of layer 0
#define CBUF0_MAX ((MAXX+24)/4) // max. size of control buffer of layer 0
// Requirements by format, overlapped layer 1..3:
// LAYERMODE_SPRITE* ... data buffer "width"+4 bytes, control buffer 24 bytes
// LAYERMODE_FASTSPRITE* ... data buffer "width"+4 bytes, control buffer up to "width*2"+16 bytes
// other formats ... data buffer 4 bytes, control buffer 24 bytes
#define DBUF1_MAX (MAXX+8) // max. size of data buffer of layer 1
#define CBUF1_MAX ((MAXX+24)/4) // max. size of control buffer of layer 1
#define DBUF2_MAX (MAXX+8) // max. size of data buffer of layer 2
#define CBUF2_MAX ((MAXX+24)/4) // max. size of control buffer of layer 2
#define DBUF3_MAX (MAXX+8) // max. size of data buffer of layer 3
#define CBUF3_MAX ((MAXX+24)/4) // max. size of control buffer of layer 3
#if LAYERS==1
#define DBUF_MAX DBUF0_MAX // max. size of data buffer
#define CBUF_MAX CBUF0_MAX // max. size of control buffer
#elif LAYERS==2
#define DBUF_MAX (DBUF0_MAX+DBUF1_MAX) // max. size of data buffer
#define CBUF_MAX (CBUF0_MAX+CBUF1_MAX) // max. size of control buffer
#elif LAYERS==3
#define DBUF_MAX (DBUF0_MAX+DBUF1_MAX+DBUF2_MAX) // max. size of data buffer
#define CBUF_MAX (CBUF0_MAX+CBUF1_MAX+CBUF2_MAX) // max. size of control buffer
#elif LAYERS==4
#define DBUF_MAX (DBUF0_MAX+DBUF1_MAX+DBUF2_MAX+DBUF3_MAX) // max. size of data buffer
#define CBUF_MAX (CBUF0_MAX+CBUF1_MAX+CBUF2_MAX+CBUF3_MAX) // max. size of control buffer
#else
#error Unsupported number of layers!
#endif
// === VGA port pins
// GP0 ... VGA B0 blue
// GP1 ... VGA B1
// GP2 ... VGA G0 green
// GP3 ... VGA G1
// GP4 ... VGA G2
// GP5 ... VGA R0 red
// GP6 ... VGA R1
// GP7 ... VGA R2
// GP8 ... VGA SYNC synchronization (inverted: negative SYNC=LOW=0x80, BLACK=HIGH=0x00)
#define VGA_GPIO_FIRST 0 // first VGA GPIO
#define VGA_GPIO_NUM 9 // number of VGA GPIOs, including HSYNC and VSYNC
#define VGA_GPIO_OUTNUM 8 // number of VGA color GPIOs, without HSYNC and VSYNC
#define VGA_GPIO_LAST (VGA_GPIO_FIRST+VGA_GPIO_NUM-1) // last VGA GPIO
#define VGA_GPIO_SYNC 8 // VGA SYNC GPIO
// VGA PIO and state machines
#define VGA_PIO pio0 // VGA PIO
#define VGA_SM0 0 // VGA state machine of base layer 0
#define VGA_SM1 1 // VGA state machine of overlapped layer 1
#define VGA_SM2 2 // VGA state machine of overlapped layer 2
#define VGA_SM3 3 // VGA state machine of overlapped layer 3
#define VGA_SM(layer) (VGA_SM0+(layer)) // VGA state machine of the layer
#if LAYERS==1
#define VGA_SMALL B0 // mask of all state machines
#elif LAYERS==2
#define VGA_SMALL (B0+B1) // mask of all state machines
#elif LAYERS==3
#define VGA_SMALL (B0+B1+B2) // mask of all state machines
#elif LAYERS==4
#define VGA_SMALL (B0+B1+B2+B3) // mask of all state machines
#else
#error Unsupported number of layers!
#endif
// VGA DMA
#define VGA_DMA 0 // VGA DMA base channel
#define VGA_DMA_CB0 (VGA_DMA+0) // VGA DMA channel - control block of base layer
#define VGA_DMA_PIO0 (VGA_DMA+1) // VGA DMA channel - copy data of base layer to PIO (raises IRQ0 on quiet)
#define VGA_DMA_CB1 (VGA_DMA+2) // VGA DMA channel - control block of overlapped layer 1
#define VGA_DMA_PIO1 (VGA_DMA+3) // VGA DMA channel - copy data of overlapped layer 1 to PIO
#define VGA_DMA_CB2 (VGA_DMA+4) // VGA DMA channel - control block of overlapped layer 1
#define VGA_DMA_PIO2 (VGA_DMA+5) // VGA DMA channel - copy data of overlapped layer 2 to PIO
#define VGA_DMA_CB3 (VGA_DMA+6) // VGA DMA channel - control block of overlapped layer 1
#define VGA_DMA_PIO3 (VGA_DMA+7) // VGA DMA channel - copy data of overlapped layer 3 to PIO
#define VGA_DMA_CB(layer) (VGA_DMA_CB0+(layer)*2) // VGA DMA control channel of the layer
#define VGA_DMA_PIO(layer) (VGA_DMA_PIO0+(layer)*2) // VGA DMA data channel of the layer
#define VGA_DMA_NUM (LAYERS*2) // number of used DMA channels
#define VGA_DMA_FIRST VGA_DMA // first used DMA
#define VGA_DMA_LAST (VGA_DMA_FIRST+VGA_DMA_NUM-1) // last used DMA