Comments for documentation

This commit is contained in:
Wayne Venables
2023-03-02 22:44:24 -08:00
parent 6f734eebc2
commit 085f467ea4
13 changed files with 6569 additions and 284 deletions

View File

@@ -12,6 +12,9 @@
#ifndef _PICOVGA_H
#define _PICOVGA_H
//!@addtogroup VideoInit Video Initialization
//!@addtogroup VideoMode Video mode configuration
//!@addtogroup Screen Screen layout
typedef signed char s8;
typedef unsigned char u8;

View File

@@ -1058,9 +1058,7 @@ void VgaCore()
}
}
/**
* @brief Starts the VGA core on core1
*/
// Starts the VGA core on core1
void StartVgaCore()
{
// stop VGA core

View File

@@ -114,22 +114,59 @@ void ScanlineTypePrint(const u8* scan, int lines);
// - All layer modes must use same layer program (LAYERMODE_BASE = overlapped layers are OFF)
void VgaInit(const sVmode* vmode); //, u8 layer1mode=LAYERMODE_BASE, u8 layer2mode=LAYERMODE_BASE, u8 layer3mode=LAYERMODE_BASE);
// Start the VGA processing on core1
//!@addtogroup VideoInit Video Initialization
//!@brief Functions for initialzing the library
//!@{
/**
* @brief Start the VGA processing on core1
* @details The first function that should be called in the project. Starts the second processor core with the PicoVGA library.
*/
void StartVgaCore();
// request to initialize VGA videomode, NULL=only stop driver (wait to initialization completes)
/**
* @brief Request to initialize VGA videomode
* @details This function passes the library a pointer to the format descriptor generated by the VgaCfg function.
* This function does not actually initialize the video mode, it just passes the pointer to the library in the 2nd
* processor core and then waits for confirmation that the initialization is complete. If the video mode needs to
* be changed (this refers to changing the timing of the video signal and changing the type of overlay layers), it
* is necessary to first stop the video generation by calling the VgaInitReq function with the NULL parameter, and
* only then call the function with the new video mode setting.
* @param vmode Video format description generated by VgaCfg or NULL to stop driver.
*/
void VgaInitReq(const sVmode* vmode);
// execute core 1 remote function
//!@}
//!@addtogroup Core Second core
//!@brief Execute functions on the second core
//!@details If the 2nd core is not too busy generating the video, it can be passed a request to perform the function.
//! This does not affect the video generation, it may just happen that the requested function runs slowly when the
//! generator is heavily loaded. The function cannot use interrupts, cannot disable interrupts, and may be restricted
//! from using the hardware interpolator (video interrupt does not save its state).
//!@{
/**
* @brief Execute remote function on second core
* @param fnc Function to execute on the second core
*/
void Core1Exec(void (*fnc)());
// check if core 1 is busy (executing remote function)
/**
* @brief Check if core 1 is busy executing remote function
*/
Bool Core1Busy();
// wait if core 1 is busy (executing remote function)
/**
* @brief Wait for core 1 finish executing remote function
*/
void Core1Wait();
// wait for VSync scanline
//!@}
/**
* @brief Wait for VSync scanline
*/
void WaitVSync();
#endif // _VGA_H

View File

@@ -8,201 +8,368 @@
#ifndef _VGA_SCREEN_H
#define _VGA_SCREEN_H
// video segment (on change update SSEGM_* in define.h)
//!@addtogroup Screen Screen layout
//!@brief Defining the layout of the display
//!@details When displaying screen image, the default pointer is pScreen for the library. It points to the sScreen structure that
//!describes the contents of the display. The Raspberry Pico has a limited RAM size and cannot accommodate a high resolution image. Therefore, the image must be composed of smaller segments to minimize the memory-intensive parts.
//!@note The following descriptions of the image format only apply to the base image layer 0. It is the only one that can contain
//!segments in different formats. Overlay layers 1 through 3 are independent of the base layer format, sharing only the total
//!screen area with the base layer but using their own image format.
//!@{
//! Video segment (on change update SSEGM_* in define.h)
typedef struct {
u16 width; // SSEGM_WIDTH width of this video segment in pixels (must be multiple of 4, 0=inactive segment)
u16 wb; // SSEGM_WB pitch - number of bytes between lines
s16 offx; // SSEGM_OFFX display offset at X direction (must be multiple of 4)
s16 offy; // SSEGM_OFFY display offset at Y direction
u16 wrapx; // SSEGM_WRAPX wrap width in X direction (number of pixels, must be multiply of 4 and > 0)
// text modes: wrapx must be multiply of 8
u16 wrapy; // SSEGM_WRAPY wrap width in Y direction (number of lines, cannot be 0)
const void* data; // SSEGM_DATA pointer to video buffer with image data
u8 form; // SSEGM_FORM graphics format GF_*
bool dbly; // SSEGM_DBLY double Y (2 scanlines per 1 image line)
u16 par3; // SSEGM_PAR3 parameter 3
u32 par; // SSEGM_PAR parameter 1
u32 par2; // SSEGM_PAR2 parameter 2
u16 width; //!< SSEGM_WIDTH width of this video segment in pixels (must be multiple of 4, 0=inactive segment)
u16 wb; //!< SSEGM_WB pitch - number of bytes between lines
s16 offx; //!< SSEGM_OFFX display offset at X direction (must be multiple of 4)
s16 offy; //!< SSEGM_OFFY display offset at Y direction
u16 wrapx; //!< SSEGM_WRAPX wrap width in X direction (number of pixels, must be multiply of 4 and > 0)
//!< text modes: wrapx must be multiply of 8
u16 wrapy; //!< SSEGM_WRAPY wrap width in Y direction (number of lines, cannot be 0)
const void* data; //!< SSEGM_DATA pointer to video buffer with image data
u8 form; //!< SSEGM_FORM graphics format GF_*
bool dbly; //!< SSEGM_DBLY double Y (2 scanlines per 1 image line)
u16 par3; //!< SSEGM_PAR3 parameter 3
u32 par; //!< SSEGM_PAR parameter 1
u32 par2; //!< SSEGM_PAR2 parameter 2
} sSegm;
// video strip (on change update SSTRIP_* in define.h)
//! Video strip (on change update SSTRIP_* in define.h)
typedef struct {
u16 height; // SSTRIP_HEIGHT height of this strip in number of scanlines
u16 num; // SSTRIP_NUM number of video segments
sSegm seg[SEGMAX]; // SSTRIP_SEG list of video segments
u16 height; //!< SSTRIP_HEIGHT height of this strip in number of scanlines
u16 num; //!< SSTRIP_NUM number of video segments
sSegm seg[SEGMAX]; //!< SSTRIP_SEG list of video segments
} sStrip;
// video screen (on change update SSCREEN_* in define.h)
//! Video screen (on change update SSCREEN_* in define.h)
typedef struct {
u16 num; // SSCREEN_NUM number of video strips
u16 backup; // SSCREEN_BACKUP backup number of video strips during display OFF
sStrip strip[STRIPMAX]; // SSCREEN_STRIP list of video strips
u16 num; //!< SSCREEN_NUM number of video strips
u16 backup; //!< SSCREEN_BACKUP backup number of video strips during display OFF
sStrip strip[STRIPMAX]; //!< SSCREEN_STRIP list of video strips
} sScreen;
// current video screen
extern sScreen Screen; // default video screen
extern sScreen* pScreen; // pointer to current video screen
extern sScreen Screen; //!< Default video screen
extern sScreen* pScreen; //!< Pointer to current video screen
// clear screen (set 0 strips, does not modify sprites)
/**
* @brief Clear screen (set 0 strips, does not modify sprites)
* @details Resets the display handler structures, clearing the display. At a minimum, this function should be called
* before initializing the videmode. It initializes the display content descriptor structure pointed to by pScreen
* (usually the default structure Screen of the library) by setting the number of segments to 0. The screen will be black
* until we fill it with content descriptors
* @param s Pointer to screen to clear
*/
void ScreenClear(sScreen* s);
// add empty strip to the screen (returns pointer to the strip)
/**
* @brief Add empty strip to the screen
* @details This function adds a new horizontal bar of the specified number of video lines to the end of the screen definition.
* The maximum number of stripes is specified by the STRIPMAX constant (8 by default) in the vga_config.h file. Without added
* segments, the bar is empty (black).
* @param s The screen to add strip
* @param height The number of video lines in the strip
* @returns Pointer to the new strip
*/
sStrip* ScreenAddStrip(sScreen* s, int height);
// add empty segment to video strip (returns pointer to the segment and initialises is to defaults)
/**
* @brief Add empty segment to video strip; returns pointer to the segment and initialises it to defaults
* @details This function adds a new image segment of the specified width to the end of the strip. The segment will contain
* one image format. For the vast majority of formats, the width must be a multiple of 4 (a multiple of 4 pixels).
* @param strip The strip to add the segment to
* @param width The width of the segment in pixels (for many formats must be a multiple of 4)
* @returns Pointer to new segment initialized to defaults
*/
sSegm* ScreenAddSegm(sStrip* strip, int width);
// set video segment to simple color format GF_COLOR
// col1 = color pattern 4-pixels even line (use macro MULTICOL)
// col2 = color pattern 4-pixels odd line (use macro MULTICOL)
/**
* @brief Set video segment to simple color format GF_COLOR
* @param segm Segment to configure
* @param col1 Color pattern 4-pixels even line (use macro MULTICOL)
* @param col2 Color pattern 4-pixels odd line (use macro MULTICOL)
*/
void ScreenSegmColor(sSegm* segm, u32 col1, u32 col2);
// set video segment to gradient with 1 line
// data = pointer to data buffer with gradient
// wb = pitch - length of buffer
// To scroll gradient, set virtual dimension wrapx, then shift offx
/**
* @brief Set video segment to gradient with 1 line
* @details The segment will be filled with a color gradient (GF_GRAD1). The gradient is 1 line of 8-bit pixels.
* @note The gradient can be scrolled horizontally with the offx parameter.
* @param segm Segment to configure
* @param data Pointer to data buffer with gradient
* @param wb Length of buffer
*/
void ScreenSegmGrad1(sSegm* segm, const void* data, int wb);
// set video segment to gradient with 2 lines
// data = pointer to data buffer with gradient
// wb = pitch - lenght of buffer
// To scroll gradient, set virtual dimension wrapx, then shift offx
/**
* @brief Set video segment to gradient with 2 lines
* @details Gradient with 2 lines, even and odd (GF_GRAD2).
* @note To scroll gradient, set virtual dimension wrapx, then shift offx
* @param segm Segment to configure
* @param data Pointer to data buffer with gradient
* @param wb Length of buffer
*/
void ScreenSegmGrad2(sSegm* segm, const void* data, int wb);
// set video segment to native 8-bit graphics (R3G3B2)
// data = pointer to data buffer
// wb = pitch - number of bytes between lines
// To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
/**
* @brief Set video segment to native 8-bit graphics (R3G3B2)
* @details 8-bit graphics 256 colors (GF_GRAPH8). Each pixel is 1 byte. This mode is one of the fastest, the data is simply sent
* from the frame buffer to the PIO controller using a DMA transfer. However, it is also one of the most memory intensive.
* Really, the memory can hold a maximum image resolution of 512x400 pixels (EGA video mode).
* @note To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
* @param segm Segment to configure
* @param data Pointer to data buffer
* @param wb Line length in bytes
*/
void ScreenSegmGraph8(sSegm* segm, const void* data, int wb);
// generate 16-color palette translation table
// trans = pointer to destination palette translation table (u16 trans[256])
// pal = pointer to source palette of 16 colors (u8 pal[16])
/**
* @brief Generate 16-color palette translation table
* @details Generates a palette translation table for the @link ScreenSegmGraph4() function. The translation table is 256 entries of
* 16 bits, so it takes 512 bytes in memory. The table is used during display for internal purposes, must be aligned to 4 bytes,
* and must be available for the entire time the segment is displayed. The input to the function is the palette table, which is
* 16 color entries of 1 byte.
* @param trans Pointer to destination palette translation table (u16 trans[256])
* @param pal Pointer to source palette of 16 colors (u8 pal[16])
*/
void GenPal16Trans(u16* trans, const u8* pal);
// set video segment to 4-bit palette graphics
// data = pointer to data buffer
// trans = pointer to 16-color palette translation table (generated with GenPal16Trans function)
// wb = pitch - number of bytes between lines
// To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
/**
* @brief Set video segment to 4-bit palette graphics
* @details 4-bit palette graphics 16 colors (GF_GRAPH4). There are 2 pixels in 1 byte (the first pixel is in the higher 4 bits
* of the byte). The function requires a palette translation table.
* @note To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
* @param segm Segment to configure
* @param data Pointer to data buffer
* @param trans Pointer to 16-color palette translation table (generated with GenPal16Trans function)
* @param wb The line length in bytes
*/
void ScreenSegmGraph4(sSegm* segm, const void* data, const void* trans, int wb);
// generate palette 4 translation table for function ScreenSegmGraph2
// trans = pointer to destination palette translation table (u32 trans[256])
// pal = pointer to source palette of 4 colors (u8 pal[4])
/**
* @brief Generate palette 4 translation table for function
* @details Generate a palette translation table for the @link ScreenSegmGraph2() function. The translation table is 256 entries with
* a size of 32 bits, so it takes 1024 bytes in memory. The table is used during display for internal purposes, must be aligned
* to 4 bytes, and must be available for the entire time the segment is displayed. The input to the function is the palette table,
* which is 4 color entries of 1 byte.
* @param trans Pointer to destination palette translation table (u32 trans[256])
* @param pal Pointer to source palette of 4 colors (u8 pal[4])
*/
void GenPal4Trans(u32* trans, const u8* pal);
// set video segment to 2-bit palette graphics
// data = pointer to data buffer
// trans = pointer to 4-color palette translation table (generated with GenPal4Trans function)
// wb = pitch - number of bytes between lines
// To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
/**
* @brief Set video segment to 2-bit palette graphics
* @details
* @note To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
* @param segm Segment to configure
* @param data Pointer to data buffer
* @param trans Pointer to 4-color palette translation table (generated with GenPal4Trans function)
* @param wb The line length in bytes
*/
void ScreenSegmGraph2(sSegm* segm, const void* data, const void* trans, int wb);
// set video segment to 1-bit palette graphics
// data = pointer to data buffer
// bg = background color
// fg = foreground color
// wb = pitch - number of bytes between lines
// To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
/**
* @brief Set video segment to 1-bit palette graphics
* @details 1-bit mono graphics 2 colors (GF_GRAPH1). There are 8 pixels in 1 byte (first pixel in the highest bit). The function requires background color
* and foreground color.
* @note To scroll image, set virtual dimension wrapx and wrapy, then shift offx and offy.
* @param segm Segment to configure
* @param data Pointer to data buffer
* @param bg Background color
* @param fg Foreground color
* @param wb The line length in bytes
*/
void ScreenSegmGraph1(sSegm* segm, const void* data, u8 bg, u8 fg, int wb);
// set video segment to 8-pixel mono text
// data = pointer to text buffer
// font = pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
// fontheight = font height
// bg = background color
// fg = foreground color
// wb = pitch - number of bytes between text lines
/**
* @brief Set video segment to 8-pixel mono text
* @details Mono text (GF_MTEXT). For mono text, the foreground and background color is valid for the entire segment.
* In the display memory there are single characters, 1 byte is one character.
* @param segm Segment to configure
* @param data Pointer to text buffer
* @param font Pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
* @param fontheight Font height
* @param bg Background color
* @param fg Foregound color
* @param wb The line length in bytes
*/
void ScreenSegmMText(sSegm* segm, const void* data, const void* font, u16 fontheight, u8 bg, u8 fg, int wb);
// set video segment to 8-pixel attribute text
// data = pointer to text buffer (character + 2x4 bit attributes)
// font = pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
// fontheight = font height
// pal = pointer to palette of 16 colors
// wb = pitch - number of bytes between text lines
/**
* @brief Set video segment to 8-pixel attribute text
* @details Attribute text (GF_ATEXT). In attribute text, each character is a pair of bytes. The first byte is the ASCII
* value of the character, the second byte is the color attribute. The higher 4 bits of the attribute represent the background
* color, the lower 4 bits of the attribute represent the foreground color. The colors are translated from a palette table of
* 16 colors.
* @param segm Segment to configure
* @param data Pointer to text buffer (character + 2x4 bit attributes)
* @param font Pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
* @param fontheight Font height
* @param pal Pointer to palette of 16 colors
* @param wb The line length in bytes
*/
void ScreenSegmAText(sSegm* segm, const void* data, const void* font, u16 fontheight, const void* pal, int wb);
// set video segment to 8-pixel foreground color text
// data = pointer to text buffer (character + foreground color)
// font = pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
// fontheight = font height
// bg = background color
// wb = pitch - number of bytes between text lines
/**
* @brief Set video segment to 8-pixel foreground color text
* @details Text with foreground color (GF_FTEXT). In text with foreground, each character is represented by a pair of bytes.
* The first byte is ASCII value of the character, the second byte is foreground color. The background color is common, specified
* by the 'bg' parameter.
* @note Library's default fonts include an inverted lower half of the font in the upper half (bit 7 set) - this can provide a
* character with an optional background color.
* @param segm Segment to configure
* @param data Pointer to text buffer (character + foreground color)
* @param font Pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
* @param fontheight Font height
* @param bg Background color
* @param wb The line length in bytes
*/
void ScreenSegmFText(sSegm* segm, const void* data, const void* font, u16 fontheight, u8 bg, int wb);
// set video segment to 8-pixel color text
// data = pointer to text buffer (character + background color + foreground color)
// font = pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
// fontheight = font height
// wb = pitch - number of bytes between text lines
/**
* @brief Set video segment to 8-pixel color text
* @details Text with color (GF_CTEXT). For text with color, each character occupies 3 bytes. The first byte is the ASCII value
* of the character, the second byte is the background color, and the third byte is the foreground color.
* @param segm Segment to configure
* @param data Pointer to text buffer (character + background color + foreground color)
* @param font Pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
* @param fontheight Font height
* @param wb The line length in bytes
*/
void ScreenSegmCText(sSegm* segm, const void* data, const void* font, u16 fontheight, int wb);
// set video segment to 8-pixel gradient color text
// data = pointer to text buffer (character + foreground color)
// font = pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
// fontheight = font height
// bg = background color
// grad = pointer to array of gradient colors
// wb = pitch - number of bytes between text lines
/**
* @brief Set video segment to 8-pixel gradient color text
* @details Text with gradient (GF_GTEXT). In this mode, each character is represented by 1 byte in memory and the background
* color is specified by the 'bg' parameter, similar to the mono text. Instead of the foreground color, there is a parameter
* 'grad', which is a pointer to a color gradient of length equal to the graphic length of the line of text (e.g. for 40
* characters, the gradient is 320 bytes). The foreground color for each pixel of the character is taken from the gradient table.
* @param segm Segment to configure
* @param data Pointer to text buffer (character + foreground color)
* @param font Pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
* @param fontheight Font height
* @param bg Background color
* @param grad Pointer to array of gradient colors
* @param wb The line length in bytes
*/
void ScreenSegmGText(sSegm* segm, const void* data, const void* font, u8 fontheight, u8 bg, const void* grad, int wb);
// set video segment to 8-pixel double gradient color text
// data = pointer to text buffer (character + foreground color)
// font = pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
// fontheight = font height
// bg = background color
// grad = pointer to array of gradient colors
// wb = pitch - number of bytes between text lines
/**
* @brief Set video segment to 8-pixel double gradient color text
* @details Double gradient text (GF_DTEXT). The function is identical to the previous function, except that each character pixel
* is generated as 2 image pixels. Thus, the character has twice the width. It is the only text mode that allows displaying
* characters with double width. The color gradient works similarly here, but 1 byte of the gradient represents 1 pixel of the
* character (as in the previous function), not 1 pixel displayed. Thus a line of 40 characters again requires a gradient of
* 320 bytes.
* @param segm Segment to configure
* @param data Pointer to text buffer (character + foreground color)
* @param font Pointer to 1-bit font of 256 characters of width 8 (total width of image 2048 pixels)
* @param fontheight Font height
* @param bg Background color
* @param grad Pointer to array of gradient colors
* @param wb The line length in bytes
*/
void ScreenSegmDText(sSegm* segm, const void* data, const void* font, u8 fontheight, u8 bg, const void* grad, int wb);
// set video segment to tiles
// data = pointer to tile map buffer (with tile indices)
// tiles = pointer to 1 column of tiles, 1 pixel = 8 bits
// w = tile width (must be multiple of 4)
// h = tile height
// wb = pitch - number of bytes between tile map rows
/**
* @brief Set video segment to tiles
* @details Tiles in column (GF_TILE). Tiles are image segments of the specified size (tile width and height are 'w' and 'h').
* The tile patterns are arranged in a single image. In this case, into a column of width 1 tile. The 'tiles' parameter is a
* pointer to the image of the tile column. The 'data' parameter is a pointer to an array of bytes, where each byte represents
* number of displayed tile. Thus, there can be a maximum of 256 tiles. The 'wb' parameter refers to the length of the row of
* the index array (not the length of the tile image). The width of a tile must be a multiple of 4, at least 8. Tiles allow
* efficient display of image information by allowing the image to repeat. Thus, high image resolution can be achieved with
* low memory requirements.
* @param segm Segment to configure
* @param data Pointer to tile map buffer (with tile indices)
* @param tiles Pointer to 1 column of tiles, 1 pixel = 8 bits
* @param w tile width (must be multiple of 4)
* @param h tile height
* @param wb Number of bytes between tile map rows
*/
void ScreenSegmTile(sSegm* segm, const void* data, const void* tiles, int w, int h, int wb);
// set video segment to alternate tiles
// data = pointer to tile map buffer (with tile indices)
// tiles = pointer to 1 row of tiles, 1 pixel = 8 bits
// w = tile width (must be multiple of 4)
// h = tile height
// tilewb = tile width bytes (usually tile width * number of tiles)
// wb = pitch - number of bytes between tile map rows
/**
* @brief Set video segment to alternate tiles
* @details Tiles in a row (GF_TILE2). This function is an alternative to @link ScreenSegmTile(), except that the tile patterns
* are arranged in a single row in the image. This may be more convenient when creating a tile image, however, you must
* additionally specify the parameter 'tilewb' representing the line length of the tile image.
* Usually tilewb = number of tiles * tile width.
* @param segm Segment to configure
* @param data Pointer to tile map buffer (with tile indices)
* @param tiles Pointer to 1 row of tiles, 1 pixel = 8 bits
* @param w tile width (must be multiple of 4)
* @param h tile height
* @param tilewb Tile width bytes (usually tile width * number of tiles)
* @param wb Number of bytes between tile map rows
*/
void ScreenSegmTile2(sSegm* segm, const void* data, const void* tiles, int w, int h, int tilewb, int wb);
// set video segment to level graph GF_LEVEL
// data = pointer to buffer with line samples 0..255
// zero = Y zero level
// bg = background color
// fg = foreground color
/**
* @brief Set video segment to level graph GF_LEVEL
* @details Level display segment (GF_LEVEL). This segment is used to display graphs. The input is an array of 'data' bytes of
* length corresponding to the width of the array in pixels. The byte value represents the height of the graph at the given X
* coordinate. The display will show a foreground or background color depending on whether the displayed pixel lies above or
* below the value from the data array. The 'zero' parameter specifies the height of the reference zero. Zero does not imply
* negative numbers in the data, the numbers are still given as unsigned (with zero at the bottom). Starting from reference zero,
* the background and foreground colour is swapped. This results in the graph looking visually symmetrical around the reference
* zero. You can see the appearance of the segment in the Oscilloscope sample program (lower curve).
* @param segm Segment to configure
* @param data Pointer to buffer with line samples 0..255
* @param zero Y zero level
* @param bg Background color
* @param fg Foregound color
*/
void ScreenSegmLevel(sSegm* segm, const void* data, u8 zero, u8 bg, u8 fg);
// set video segment to leve gradient graph GF_LEVELGRAD
// data = pointer to buffer with values 0..255 of 4-pixels in rows
// sample1 = scanline sample < data
// sample2 = scanline sample >= data
/**
* @brief Set video segment to leve gradient graph GF_LEVELGRAD
* @details Level display segment with gradient (GF_LEVELGRAD). This segment is used to display graphs, similar to the previous
* function. It differs in that the color is given as a vertical gradient with a height corresponding to the height of the segment.
* If a pixel lies below the data value, the color from the first gradient is used. Otherwise, the second gradient is used.
* An example use case can be seen in the Level Meter sample program, to display the spectrum.
* @param segm Segment to configure
* @param data Pointer to buffer with values 0..255 of 4-pixels in rows
* @param sample1 Scanline sample < data
* @param sample2 Scanline sample >= data
*/
void ScreenSegmLevelGrad(sSegm* segm, const void* data, const void* sample1, const void* sample2);
// set video segment to oscilloscope 1-pixel graph GF_OSCIL
// data = pointer to buffer with line samples 0..255
// bg = background color
// fg = foreground color
// pixh = height of pixels - 1
/**
* @brief Set video segment to oscilloscope 1-pixel graph GF_OSCIL
* @details Oscilloscope waveform display segment (GF_OSCIL). The segment is similar in function to the level display segment.
* It differs in that the curve is displayed as a line of 'pixh' pixel thickness. This function is already more demanding and
* may not be able to service the full width of the image.
* @param segm Segment to configure
* @param data Pointer to buffer with line samples 0..255
* @param bg Background color
* @param fg Foregound color
* @param pixh Height of pixels - 1
*/
void ScreenSegmOscil(sSegm* segm, const void* data, u8 bg, u8 fg, int pixh);
// set video segment to oscilloscope line graph GF_OSCLINE
// data = pointer to buffer with line samples 0..255
// bg = background color
// fg = foreground color
/**
* @brief Set video segment to oscilloscope line graph GF_OSCLIN
* @details Oscilloscope continuous waveform segment (GF_OSCLINE). The curve is displayed as a continuous line with a thickness
* of 1 pixel. This mode is already very demanding to render and is therefore accelerated by halving the horizontal resolution
* (renders points 2 pixels wide).
* @param segm Segment to configure
* @param data Pointer to buffer with line samples 0..255
* @param bg Background color
* @param fg Foregound color
*/
void ScreenSegmOscLine(sSegm* segm, const void* data, u8 bg, u8 fg);
// generate palette 4-color translation table for function ScreenSegmPlane2
// trans = pointer to destination palette translation table (u32 trans[256])
// pal = pointer to source palette of 4 colors (u8 pal[4])
/**
* @brief Generate palette 4-color translation table for function @link ScreenSegmPlane2()
* @details Generate a palette translation table for the @link ScreenSegmPlane2() function. The translation table is 256 entries of
* 32 bits, so it takes 1024 bytes in memory. The table is used during display for internal purposes, must be aligned to 4 bytes,
* and must be available for the entire time the segment is displayed. The input to the function is the palette table, which is
* 4 color entries of 1 byte. Although there is no program in the PicoVGA library utilities that prepares an image in 2-plane
* mode, there is an internal function Plane2Conv that converts a 4-color image to 2-plane mode. Thus, the image is attached to
* the program as a 4-color image, and the conversion function is used to prepare a copy in RAM.
* @param trans Pointer to destination palette translation table (u32 trans[256])
* @param pal Pointer to source palette of 4 colors (u8 pal[4])
*/
void GenPal4Plane(u32* trans, const u8* pal);
// set video segment to 4-color on 2-planes graphics
@@ -304,4 +471,6 @@ void ScreenSegmTilePersp3(sSegm* segm, const u8* map, const u8* tiles, const int
void ScreenSegmTilePersp4(sSegm* segm, const u8* map, const u8* tiles, const int* mat,
u8 mapwbits, u8 maphbits, u8 tilebits, s8 horizon);
//!@}
#endif // _VGA_SCREEN_H

View File

@@ -8,230 +8,265 @@
#ifndef _VGA_VMODE_H
#define _VGA_VMODE_H
#define VIDEO_NAME_LEN 5 // length of video timing name
//!@addtogroup VideoMode Video mode configuration
//!@brief Structures and functions for video modes
//!@details The video mode can be initialized either simply by the Video function or in more detail by the other functions.
//!@{
// video timings
#define VIDEO_NAME_LEN 5 //!< length of video timing name
//! Video timings structure
typedef struct {
// horizontal
float htot; // total scanline in [us]
float hfront; // H front porch (after image, before HSYNC) in [us]
float hsync; // H sync pulse in [us]
float hback; // H back porch (after HSYNC, before image) in [us]
float hfull; // H full visible in [us] (corresponding to 'wfull' pixels)
float htot; //!< Horizontal total scanline in [us]
float hfront; //!< Horizontal front porch (after image, before HSYNC) in [us]
float hsync; //!< Horizontal sync pulse in [us]
float hback; //!< Horizontal back porch (after HSYNC, before image) in [us]
float hfull; //!< Horizontal full visible in [us] (corresponding to 'wfull' pixels)
// vertical
u16 vtot; // total scanlines (both subframes)
u16 vmax; // maximal height
u16 vtot; //!< Vertical total scanlines (both subframes)
u16 vmax; //!< Vertical maximal height
// subframe 1
u16 vsync1; // V sync (half-)pulses on subframe 1
u16 vpost1; // V sync post half-pulses on subframe 1
u16 vback1; // V back porch (after VSYNC, before image) on subframe 1
u16 vact1; // active visible scanlines, subframe 1
u16 vfront1; // V front porch (after image, before VSYNC) on subframe 1
u16 vpre1; // V sync pre half-pulses on subframe 1
u16 vsync1; //!< V sync (half-)pulses on subframe 1
u16 vpost1; //!< V sync post half-pulses on subframe 1
u16 vback1; //!< V back porch (after VSYNC, before image) on subframe 1
u16 vact1; //!< active visible scanlines, subframe 1
u16 vfront1; //!< V front porch (after image, before VSYNC) on subframe 1
u16 vpre1; //!< V sync pre half-pulses on subframe 1
// subframe 2 (ignored if not interlaced)
u16 vsync2; // V sync half-pulses on subframe 2
u16 vpost2; // V sync post half-pulses on subframe 2
u16 vback2; // V back porch (after VSYNC, before image) on subframe 2
u16 vact2; // active visible scanlines, subframe 2
u16 vfront2; // V front porch (after image, before VSYNC) on subframe 2
u16 vpre2; // V sync pre half-pulses on subframe 2
u16 vsync2; //!< V sync half-pulses on subframe 2
u16 vpost2; //!< V sync post half-pulses on subframe 2
u16 vback2; //!< V back porch (after VSYNC, before image) on subframe 2
u16 vact2; //!< active visible scanlines, subframe 2
u16 vfront2; //!< V front porch (after image, before VSYNC) on subframe 2
u16 vpre2; //!< V sync pre half-pulses on subframe 2
// name
const char* name; // video timing name (VIDEO_NAME_LEN characters + terminating 0)
const char* name; //!< video timing name (VIDEO_NAME_LEN characters + terminating 0)
// flags
bool inter; // interlaced (use subframes)
bool psync; // positive synchronization
bool odd; // first sub-frame is odd lines 1, 3, 5,... (PAL)
bool inter; //!< interlaced (use subframes)
bool psync; //!< positive synchronization
bool odd; //!< first sub-frame is odd lines 1, 3, 5,... (PAL)
} sVideo;
// === TV videomodes
// TV PAL interlaced 5:4 720x576 (4:3 768x576, 16:9 1024x576)
//! TV PAL interlaced 5:4 720x576 (4:3 768x576, 16:9 1024x576)
extern const sVideo VideoPAL;
// TV PAL progressive 5:4 360x288 (4:3 384x288, 16:9 512x288)
//! TV PAL progressive 5:4 360x288 (4:3 384x288, 16:9 512x288)
extern const sVideo VideoPALp;
// TV NTSC interlaced 4:3 640x480 (5:4 600x480, 16:9 848x480)
//! TV NTSC interlaced 4:3 640x480 (5:4 600x480, 16:9 848x480)
extern const sVideo VideoNTSC;
// TV NTSC progressive 4:3 320x240 (5:4 300x240, 16:9 424x240)
//! TV NTSC progressive 4:3 320x240 (5:4 300x240, 16:9 424x240)
extern const sVideo VideoNTSCp;
// === Monitor videomodes
// EGA 8:5 640x400 (5:4 500x400, 4:3 528x400, 16:9 704x400), vert. 70 Hz, hor. 31.4685 kHz, pixel clock 25.175 MHz
//! EGA 8:5 640x400 (5:4 500x400, 4:3 528x400, 16:9 704x400), vert. 70 Hz, hor. 31.4685 kHz, pixel clock 25.175 MHz
extern const sVideo VideoEGA;
// VGA 4:3 640x480 (16:9 848x480), vert. 60 Hz, hor. 31.4685 kHz, pixel clock 25.175 MHz
//! VGA 4:3 640x480 (16:9 848x480), vert. 60 Hz, hor. 31.4685 kHz, pixel clock 25.175 MHz
extern const sVideo VideoVGA;
// SVGA 4:3 800x600 (16:9 1064x600), vert. 60 Hz, hor. 37.897 kHz, pixel clock 40 MHz
//! SVGA 4:3 800x600 (16:9 1064x600), vert. 60 Hz, hor. 37.897 kHz, pixel clock 40 MHz
extern const sVideo VideoSVGA;
// XGA 4:3 1024x768 (16:9 1360x768), vert. 60 Hz, hor. 48.36310 kHz, pixel clock 65 MHz
//! XGA 4:3 1024x768 (16:9 1360x768), vert. 60 Hz, hor. 48.36310 kHz, pixel clock 65 MHz
extern const sVideo VideoXGA;
// VESA 4:3 1152x864, vert. 60 Hz, hor. 53.697 kHz, pixel clock 81.62 MHz
//! VESA 4:3 1152x864, vert. 60 Hz, hor. 53.697 kHz, pixel clock 81.62 MHz
extern const sVideo VideoVESA;
// HD 4:3 1280x960, vert. 53 Hz, hor. 51.858 kHz, pixel clock 102.1 MHz
//! HD 4:3 1280x960, vert. 53 Hz, hor. 51.858 kHz, pixel clock 102.1 MHz
extern const sVideo VideoHD;
// required configuration to initialize VGA output
//! Required configuration to initialize VGA output
typedef struct {
u16 width; // width in pixels
u16 height; // height in lines
u16 wfull; // width of full screen, corresponding to 'hfull' time (0=use 'width' parameter)
const sVideo* video; // used video timings
u32 freq; // required minimal system frequency in kHz (real frequency can be higher)
u32 fmax; // maximal system frequency in kHz (limit resolution if needed)
u8 mode[LAYERS_MAX]; // modes of overlapped layers 0..3 LAYERMODE_* (LAYERMODE_BASE = layer is off)
// - mode of layer 0 is ignored (always use LAYERMODE_BASE)
// - all overlapped layers must use same layer program
bool dbly; // double in Y direction
bool lockfreq; // lock required frequency, do not change it
u16 width; //!< Width in pixels
u16 height; //!< Height in lines
u16 wfull; //!< Width of full screen, corresponding to 'hfull' time (0=use 'width' parameter)
const sVideo* video; //!< Used video timings
u32 freq; //!< Required minimal system frequency in kHz (real frequency can be higher)
u32 fmax; //!< Maximal system frequency in kHz (limit resolution if needed)
u8 mode[LAYERS_MAX]; //!< Modes of overlapped layers 0..3 LAYERMODE_* (LAYERMODE_BASE = layer is off)
//!< - mode of layer 0 is ignored (always use LAYERMODE_BASE)
//!< - all overlapped layers must use same layer program
bool dbly; //!< double in Y direction
bool lockfreq; //!< Lock required frequency, do not change it
} sVgaCfg;
// videomode table - used to setup video driver
//! Videomode table - used to setup video driver
typedef struct {
// screen resolution
u16 width; // width in pixels
u16 height; // height in lines
u16 wfull; // width of full screen (corresponding to 'hfull' time)
u16 wmax; // maximal width (corresponding to 'hmax' time)
u16 width; //!< Screen width in pixels
u16 height; //!< Screen height in lines
u16 wfull; //!< Screen width of full screen (corresponding to 'hfull' time)
u16 wmax; //!< Screen maximal width (corresponding to 'hmax' time)
// setup PLL system clock
u32 freq; // system clock frequency in kHz
u32 vco; // VCO frequency in kHz
u16 fbdiv; // fbdiv PLL divider
u8 pd1; // postdiv1
u8 pd2; // postdiv2
u32 freq; //!< system clock frequency in kHz
u32 vco; //!< VCO frequency in kHz
u16 fbdiv; //!< fbdiv PLL divider
u8 pd1; //!< postdiv1
u8 pd2; //!< postdiv2
// setup PIO state machine
u16 div; // divide base state machine clock
u16 cpp; // state machine clocks per pixel
u8 prog; // layer program LAYERPROG_*
u8 mode[LAYERS_MAX]; // mode of layer 0..3 LAYERMODE_* (LAYERMODE_BASE = layer is off or base layer)
u16 div; //!< PIO divide base state machine clock
u16 cpp; //!< State machine clocks per pixel
u8 prog; //!< Layer program LAYERPROG_*
u8 mode[LAYERS_MAX]; //!< mode of layer 0..3 LAYERMODE_* (LAYERMODE_BASE = layer is off or base layer)
// horizontal timings
u16 htot; // total state machine clocks per line
u16 hfront; // H front porch in state machine clocks (min. 2)
u16 hsync; // H sync pulse in state machine clocks (min. 4)
u16 hback; // H back porch in state machine clocks (min. 13)
float hfreq; // horizontal frequency in [Hz]
u16 htot; //!< Total state machine clocks per line
u16 hfront; //!< H front porch in state machine clocks (min. 2)
u16 hsync; //!< H sync pulse in state machine clocks (min. 4)
u16 hback; //!< H back porch in state machine clocks (min. 13)
float hfreq; //!< Horizontal frequency in [Hz]
// vertical timings
u16 vtot; // total scanlines (both sub-frames)
u16 vmax; // maximal height
float vfreq; // vertical frequency in [Hz]
u16 vtot; //!< Total scanlines (both sub-frames)
u16 vmax; //!< Maximal height
float vfreq; //!< Vertical frequency in [Hz]
// subframe 1
u16 vsync1; // V sync (half-)pulses on subframe 1
u16 vpost1; // V sync post (half-)pulses on subframe 1
u16 vback1; // V back porch (after VSYNC, before image) on subframe 1
u16 vact1; // active visible scanlines, subframe 1
u16 vfront1; // V front porch (after image, before VSYNC) on subframe 1
u16 vpre1; // V sync pre (half-)pulses on subframe 1
u16 vfirst1; // first active scanline, subframe 1
u16 vsync1; //!< V sync (half-)pulses on subframe 1
u16 vpost1; //!< V sync post (half-)pulses on subframe 1
u16 vback1; //!< V back porch (after VSYNC, before image) on subframe 1
u16 vact1; //!< active visible scanlines, subframe 1
u16 vfront1; //!< V front porch (after image, before VSYNC) on subframe 1
u16 vpre1; //!< V sync pre (half-)pulses on subframe 1
u16 vfirst1; //!< first active scanline, subframe 1
// subframe 2 (ignored if not interlaced)
u16 vsync2; // V sync half-pulses on subframe 2
u16 vpost2; // V sync post half-pulses on subframe 2
u16 vback2; // V back porch (after VSYNC, before image) on subframe 2
u16 vact2; // active visible scanlines, subframe 2
u16 vfront2; // V front porch (after image, before VSYNC) on subframe 2
u16 vpre2; // V sync pre half-pulses on subframe 2
u16 vfirst2; // first active scanline, subframe 2
u16 vsync2; //!< V sync half-pulses on subframe 2
u16 vpost2; //!< V sync post half-pulses on subframe 2
u16 vback2; //!< V back porch (after VSYNC, before image) on subframe 2
u16 vact2; //!< active visible scanlines, subframe 2
u16 vfront2; //!< V front porch (after image, before VSYNC) on subframe 2
u16 vpre2; //!< V sync pre half-pulses on subframe 2
u16 vfirst2; //!< first active scanline, subframe 2
// name
const char* name; // video timing name (VIDEO_NAME_LEN characters + terminating 0)
const char* name; //!< Video timing name (VIDEO_NAME_LEN characters + terminating 0)
// flags
bool lockfreq; // lock current frequency, do not change it
bool dbly; // double scanlines
bool inter; // interlaced (use sub-frames)
bool psync; // positive synchronization
bool odd; // first sub-frame is odd lines 1, 3, 5,... (PAL)
bool lockfreq; //!< Lock current frequency, do not change it
bool dbly; //!< Double scanlines
bool inter; //!< Interlaced (use sub-frames)
bool psync; //!< Positive synchronization
bool odd; //!< First sub-frame is odd lines 1, 3, 5,... (PAL)
} sVmode;
// output device
//! Output device
enum {
DEV_PAL = 0, // PAL TV
DEV_NTSC, // NTSC TV
DEV_VGA, // VGA monitor
DEV_PAL = 0, //!< PAL TV
DEV_NTSC, //!< NTSC TV
DEV_VGA, //!< VGA monitor
DEV_MAX
};
// preset videomode resolution
//! Preset videomode resolution
enum {
RES_ZX = 0, // 256x192
RES_CGA, // 320x200
RES_QVGA, // 320x240
RES_EGA, // 512x400
RES_VGA, // 640x480
RES_SVGA, // 800x600 (not for TV device)
RES_XGA, // 1024x768 (not for TV device)
RES_HD, // 1280x960 (not for TV device)
RES_ZX = 0, //!< 256x192
RES_CGA, //!< 320x200
RES_QVGA, //!< 320x240
RES_EGA, //!< 512x400
RES_VGA, //!< 640x480
RES_SVGA, //!< 800x600 (not for TV device)
RES_XGA, //!< 1024x768 (not for TV device)
RES_HD, //!< 1280x960 (not for TV device)
RES_MAX
};
// graphics formats
//! Graphics formats
enum {
FORM_8BIT = 0, // 8-bit pixel graphics (up to EGA resolution)
FORM_4BIT, // 4-bit pixel graphics (up to SVGA graphics)
FORM_MONO, // 1-bit pixel graphics
FORM_TILE8, // 8x8 tiles
FORM_TILE12, // 12x12 tiles
FORM_TILE16, // 16x16 tiles
FORM_TILE24, // 24x24 tiles
FORM_TILE32, // 32x32 tiles
FORM_TILE48, // 48x48 tiles
FORM_TILE64, // 64x64 tiles
FORM_MTEXT8, // mono text with font 8x8
FORM_MTEXT16, // mono text with font 8x16
FORM_TEXT8, // attribute text with font 8x8
FORM_TEXT16, // attribute text with font 8x16
FORM_RLE, // images with RLE compression (on overlapped layer 1)
FORM_8BIT = 0, //!< 8-bit pixel graphics (up to EGA resolution)
FORM_4BIT, //!< 4-bit pixel graphics (up to SVGA graphics)
FORM_MONO, //!< 1-bit pixel graphics
FORM_TILE8, //!< 8x8 tiles
FORM_TILE12, //!< 12x12 tiles
FORM_TILE16, //!< 16x16 tiles
FORM_TILE24, //!< 24x24 tiles
FORM_TILE32, //!< 32x32 tiles
FORM_TILE48, //!< 48x48 tiles
FORM_TILE64, //!< 64x64 tiles
FORM_MTEXT8, //!< mono text with font 8x8
FORM_MTEXT16, //!< mono text with font 8x16
FORM_TEXT8, //!< attribute text with font 8x8
FORM_TEXT16, //!< attribute text with font 8x16
FORM_RLE, //!< images with RLE compression (on overlapped layer 1)
FORM_MAX
};
extern sVmode Vmode; // videomode setup
extern sVgaCfg Cfg; // required configuration
extern sCanvas Canvas; // canvas of draw box
extern sVmode Vmode; //!< Videomode setup
extern sVgaCfg Cfg; //!< Required configuration
extern sCanvas Canvas; //!< Canvas of draw box
// 16-color palette translation table
//! 16-color palette translation table
extern u16 Pal16Trans[256];
// initialize default VGA configuration
/**
* @brief Initialize configuration structure to VGA defaults
* @details The function presets the structure to the default parameters: 640x480 resolution, VGA display,
* processor frequency 120 to 270 MHz.
* @param cfg Configuration to modify
*/
void VgaCfgDef(sVgaCfg* cfg);
// debug print videomode setup
/**
* @brief Debug print videomode setup
* @param vmode Video mode table
*/
void VgaPrintCfg(const sVmode* vmode);
// calculate videomode setup
// cfg ... required configuration
// vmode ... destination videomode setup for driver
/**
* @brief Calculate the structure for setting up the video mode.
* @details The sVgaCfg structure contains the required properties of the video mode: the display resolution,
* the minimum processor frequency and the timing of the sVideo signal, possibly also the required overlay mode.
* You can first call the VgaCfgDef function, which presets the structure to the default parameters. The VgaCfg
* function prepares the sVmode descriptor structure, which is later passed to the init function.
* At this point no operations are taking place only the necessary settings are being calculated. After the calculation,
* some items of the sVmode structure can be adjusted. In the library there are global structures Cfg and Vmode that can
* be used for the function. The required screen resolution and signal timing are two independent properties.
* For timing, you are limited only by the number of video lines of the image, but otherwise you can set any screen resolution
* within them. For example, for PAL and NTSC video, you can set a VGA video resolution. To make the program versatile so that
* it can be run on both a VGA monitor and a TV, use a VGA resolution of 640x480 or 320x240 (or 512x400 and 256x192, due to RAM
* limitations). When changing the display, just select VGA/PAL or NTSC timing, the resolution does not change for the program.
* @param cfg Source configuration structure
* @param vmode Destination videomode setup for driver
*/
void VgaCfg(const sVgaCfg* cfg, sVmode* vmode);
// initialize videomode
// dev ... device DEV_*
// res ... resolution RES_*
// form ... format FORM_*
// buf ... pointer to frame buffer (must be aligned to 4-bites, use ALIGNED attribute)
// buf2 ...pointer to additional buffer:
// FORM_TILE*: pointer to column of tiles 32x32 in 8-bit graphics
// FORM_TEXT: pointer to font 8x16 or 8x8 (size 4 KB or 2 KB, ALIGNED attribute, should be in RAM)
// - copy font to 4KB or 2 KB RAM buffer with ALIGNED attribute
// - text uses color attributes PC_*
// FORM_RLE: pointer to image rows (ALIGNED attribute, should be in RAM)
/**
* @brief Simplified initialization of the video mode
* @details This function incorporates all the video initialization and configuration functions -- this one call initializes the
* video mode and starts the library.
* It supports only 1 display segment and has a limited repertoire of formats and resolutions, but may be sufficient in some cases.
* The function only needs to pass a pointer to the frame buffer, which is a u8 array of sufficient size for the image data.
* The function uses the library's default global structures (Cfg, Vmode, Canvas), otherwise the program can use the default global
* structures arbitrarily. When using the Video function, the initialization functions are not needed.
* @param dev Output device
* @param res Resolution
* @param form Graphics format
* @param buf Pointer to frame buffer (must be aligned to 4-bites, use ALIGNED attribute)
* @param buf2 Pointer to additional buffer:<br>
* <b>FORM_TILE*:</b> Pointer to column of tiles 32x32 in 8-bit graphics<br>
* <b>FORM_TEXT:</b> Pointer to font 8x16 or 8x8 (size 4 KB or 2 KB, ALIGNED attribute, should be in RAM) copy font to 4KB or 2 KB RAM buffer with ALIGNED attribute text uses color attributes PC_*<br>
* <b>FORM_RLE:</b> Pointer to image rows (ALIGNED attribute, should be in RAM)
*/
void Video(u8 dev, u8 res, u8 form, u8* buf, const void* buf2 = FontBoldB8x16);
//!@}
#endif // _VGA_VMODE_H