1.1 --- a/examples/vga-cpu/vga.h Sat Nov 03 16:42:17 2018 +0100
1.2 +++ b/examples/vga-cpu/vga.h Sat Nov 03 21:47:40 2018 +0100
1.3 @@ -23,8 +23,8 @@
1.4 #include "vga_common.h"
1.5
1.6 #define LINE_LENGTH 160 /* pixels */
1.7 -#define LINE_COUNT 256 /* distinct display lines */
1.8 -#define LINE_MULTIPLIER (SCANLINES / LINE_COUNT)
1.9 +#define LINE_COUNT 256 /* display lines per frame */
1.10 +#define FRAME_COUNT 1 /* double-buffered display */
1.11
1.12 /* 24MHz cycle measurements. */
1.13
1.14 @@ -37,6 +37,12 @@
1.15
1.16 #define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT)
1.17
1.18 +/* A frame has an entire screen plus one line to allow horizontal scrolling,
1.19 + since a horizontal scroll offset causes the final transfer line to exceed the
1.20 + screen limit. */
1.21 +
1.22 +#define FRAME_SIZE (SCREEN_SIZE + LINE_COUNT)
1.23 +
1.24 /* Transfer and pixel allocation properties. */
1.25
1.26 #define TRANSFER_CELL_SIZE LINE_LENGTH
2.1 --- a/examples/vga-dual/vga.h Sat Nov 03 16:42:17 2018 +0100
2.2 +++ b/examples/vga-dual/vga.h Sat Nov 03 21:47:40 2018 +0100
2.3 @@ -23,8 +23,8 @@
2.4 #include "vga_common.h"
2.5
2.6 #define LINE_LENGTH 160 /* pixels */
2.7 -#define LINE_COUNT 256 /* distinct display lines */
2.8 -#define LINE_MULTIPLIER (SCANLINES / LINE_COUNT)
2.9 +#define LINE_COUNT 256 /* display lines per frame */
2.10 +#define FRAME_COUNT 1 /* double-buffered display */
2.11
2.12 /* 24MHz cycle measurements. */
2.13
2.14 @@ -37,6 +37,12 @@
2.15
2.16 #define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT)
2.17
2.18 +/* A frame has an entire screen plus one line to allow horizontal scrolling,
2.19 + since a horizontal scroll offset causes the final transfer line to exceed the
2.20 + screen limit. */
2.21 +
2.22 +#define FRAME_SIZE (SCREEN_SIZE + LINE_COUNT)
2.23 +
2.24 /* Transfer and pixel allocation properties. */
2.25
2.26 #define TRANSFER_CELL_SIZE (LINE_LENGTH / 2)
3.1 --- a/examples/vga-pmp/vga.h Sat Nov 03 16:42:17 2018 +0100
3.2 +++ b/examples/vga-pmp/vga.h Sat Nov 03 21:47:40 2018 +0100
3.3 @@ -23,8 +23,8 @@
3.4 #include "vga_common.h"
3.5
3.6 #define LINE_LENGTH 160 /* pixels */
3.7 -#define LINE_COUNT 256 /* distinct display lines */
3.8 -#define LINE_MULTIPLIER (SCANLINES / LINE_COUNT)
3.9 +#define LINE_COUNT 256 /* display lines per frame */
3.10 +#define FRAME_COUNT 1 /* double-buffered display */
3.11
3.12 /* 48MHz cycle measurements. */
3.13
3.14 @@ -37,6 +37,12 @@
3.15
3.16 #define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT)
3.17
3.18 +/* A frame has an entire screen plus one line to allow horizontal scrolling,
3.19 + since a horizontal scroll offset causes the final transfer line to exceed the
3.20 + screen limit. */
3.21 +
3.22 +#define FRAME_SIZE (SCREEN_SIZE + LINE_COUNT)
3.23 +
3.24 /* Transfer and pixel allocation properties. */
3.25
3.26 #define TRANSFER_CELL_SIZE LINE_LENGTH
4.1 --- a/examples/vga-timer/vga.h Sat Nov 03 16:42:17 2018 +0100
4.2 +++ b/examples/vga-timer/vga.h Sat Nov 03 21:47:40 2018 +0100
4.3 @@ -24,7 +24,7 @@
4.4
4.5 #define LINE_LENGTH 92 /* pixels */
4.6 #define LINE_COUNT 128 /* distinct display lines */
4.7 -#define LINE_MULTIPLIER (SCANLINES / LINE_COUNT)
4.8 +#define FRAME_COUNT 1 /* double-buffered display */
4.9
4.10 /* 24MHz cycle measurements. */
4.11
4.12 @@ -37,6 +37,12 @@
4.13
4.14 #define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT)
4.15
4.16 +/* A frame has an entire screen plus one line to allow horizontal scrolling,
4.17 + since a horizontal scroll offset causes the final transfer line to exceed the
4.18 + screen limit. */
4.19 +
4.20 +#define FRAME_SIZE (SCREEN_SIZE + LINE_COUNT)
4.21 +
4.22 /* Transfer and pixel allocation properties. */
4.23
4.24 #define TRANSFER_CELL_SIZE 1
5.1 --- a/examples/vga/main.c Sat Nov 03 16:42:17 2018 +0100
5.2 +++ b/examples/vga/main.c Sat Nov 03 21:47:40 2018 +0100
5.3 @@ -81,6 +81,12 @@
5.4
5.5
5.6
5.7 +/* Framebuffer memory. */
5.8 +
5.9 +static uint8_t framebuffer[FRAME_SIZE * FRAME_COUNT];
5.10 +
5.11 +
5.12 +
5.13 /* Bundled image and font data. */
5.14
5.15 extern uint8_t screendata[];
5.16 @@ -309,6 +315,13 @@
5.17 pm_on(0);
5.18 #endif
5.19
5.20 + uart_init(1, FPB, 115200);
5.21 + uart_on(1);
5.22 +
5.23 + /* Initialise memory for a double-buffered display. */
5.24 +
5.25 + init_display(&display_config, framebuffer, LINE_LENGTH, LINE_COUNT, FRAME_COUNT);
5.26 +
5.27 /* Initialise VGA output with one or two line channels, configuring a line
5.28 timer and any transfer timer, with an initiating channel being introduced
5.29 if a transfer timer is specified. */
5.30 @@ -321,16 +334,13 @@
5.31 vga_configure_transfer(VGA_OUTPUT);
5.32 vga_configure_sync(1, 2);
5.33
5.34 - uart_init(1, FPB, 115200);
5.35 - uart_on(1);
5.36 -
5.37 interrupts_on();
5.38
5.39 /* Plot the image centred on the screen. */
5.40
5.41 copy_display(&display_config, screendata, screendata_width, screendata_height,
5.42 - (LINE_LENGTH - screendata_width) / 2,
5.43 - (LINE_COUNT - screendata_height) / 2, -1, 1);
5.44 + (display_config.line_length - screendata_width) / 2,
5.45 + (display_config.line_count - screendata_height) / 2, -1, 1);
5.46
5.47 /* Write a sequence of characters. */
5.48
5.49 @@ -338,7 +348,7 @@
5.50
5.51 /* Move a sprite around on the screen with a delay between each movement. */
5.52
5.53 - animate(1 << 21);
5.54 + animate(1 << 18);
5.55 }
5.56
5.57
6.1 --- a/examples/vga/vga.h Sat Nov 03 16:42:17 2018 +0100
6.2 +++ b/examples/vga/vga.h Sat Nov 03 21:47:40 2018 +0100
6.3 @@ -23,8 +23,8 @@
6.4 #include "vga_common.h"
6.5
6.6 #define LINE_LENGTH 160 /* pixels */
6.7 -#define LINE_COUNT 256 /* distinct display lines */
6.8 -#define LINE_MULTIPLIER (SCANLINES / LINE_COUNT)
6.9 +#define LINE_COUNT 256 /* display lines per frame */
6.10 +#define FRAME_COUNT 1 /* double-buffered display */
6.11
6.12 /* 24MHz cycle measurements. */
6.13
6.14 @@ -37,6 +37,12 @@
6.15
6.16 #define SCREEN_SIZE (LINE_LENGTH * LINE_COUNT)
6.17
6.18 +/* A frame has an entire screen plus one line to allow horizontal scrolling,
6.19 + since a horizontal scroll offset causes the final transfer line to exceed the
6.20 + screen limit. */
6.21 +
6.22 +#define FRAME_SIZE (SCREEN_SIZE + LINE_COUNT)
6.23 +
6.24 /* Transfer and pixel allocation properties. */
6.25
6.26 #define TRANSFER_CELL_SIZE LINE_LENGTH
7.1 --- a/include/display.h Sat Nov 03 16:42:17 2018 +0100
7.2 +++ b/include/display.h Sat Nov 03 21:47:40 2018 +0100
7.3 @@ -28,19 +28,43 @@
7.4
7.5 typedef struct
7.6 {
7.7 - /* Framebuffer pointer and size. */
7.8 + /* Framebuffer address, potentially referencing many frames. */
7.9
7.10 uint8_t *framebuffer;
7.11 - uint32_t screen_size;
7.12 +
7.13 + /* The total number of lines in the framebuffer including spare lines to
7.14 + support horizontal scrolling. */
7.15 +
7.16 + uint32_t total_lines;
7.17 +
7.18 + /* The screen dimensions and size (derived from the dimensions). */
7.19 +
7.20 uint32_t line_length, line_count; /* width, height */
7.21 + uint32_t screen_size; /* = width * height */
7.22 +
7.23 + /* The current frame, number of frames, and the maximum number supported. */
7.24 +
7.25 + int frame, frames, max_frames;
7.26
7.27 - /* Screen start/top and limit pointers. */
7.28 + /* The fixed start address of the current frame. */
7.29 +
7.30 + uint8_t *frame_start; /* = framebuffer + (frame_size * frame) */
7.31 +
7.32 + /* The floating screen start/top pointer. */
7.33 +
7.34 + uint8_t *screen_start; /* >= frame_start; < screen_limit */
7.35
7.36 - uint8_t *screen_start, *screen_limit;
7.37 + /* The fixed end address of the current frame. */
7.38 +
7.39 + uint8_t *screen_limit; /* = frame_start + screen_size */
7.40 +
7.41 + /* Number of scanlines on the display. */
7.42 +
7.43 + uint32_t scanlines;
7.44
7.45 /* Number of scanlines per display line. */
7.46
7.47 - int line_multiplier;
7.48 + int line_multiplier; /* = scanlines / line_count */
7.49
7.50 /* Number of consecutive pixels provided by a framebuffer region. */
7.51
7.52 @@ -62,6 +86,19 @@
7.53
7.54
7.55
7.56 +/* Configuration functions. */
7.57 +
7.58 +void init_display(display_config_t *cfg, uint8_t *framebuffer,
7.59 + uint32_t line_length, uint32_t line_count, int frames);
7.60 +
7.61 +void init_display_properties(display_config_t *cfg, uint32_t offset);
7.62 +
7.63 +void select_frame(display_config_t *cfg, int frame, uint32_t offset);
7.64 +
7.65 +void set_frames(display_config_t *cfg, int frames);
7.66 +
7.67 +uint32_t get_start_offset(display_config_t *cfg);
7.68 +
7.69 /* Access functions. */
7.70
7.71 int get_position(display_config_t *cfg, int x);
8.1 --- a/include/display_config.h Sat Nov 03 16:42:17 2018 +0100
8.2 +++ b/include/display_config.h Sat Nov 03 21:47:40 2018 +0100
8.3 @@ -24,30 +24,13 @@
8.4 #include "display.h"
8.5 #include "vga.h"
8.6
8.7 -/* Reserve enough space for a screen, plus one line to allow horizontal
8.8 - scrolling, since a horizontal scroll offset causes the final transfer line to
8.9 - exceed the screen limit. */
8.10 -
8.11 -uint8_t framebuffer[SCREEN_SIZE + LINE_LENGTH];
8.12 -
8.13 -
8.14 -
8.15 /* Define a structure containing the display parameters. */
8.16
8.17 display_config_t display_config = {
8.18
8.19 - /* Set the reserved memory as the framebuffer. */
8.20 -
8.21 - .framebuffer = framebuffer,
8.22 - .screen_start = framebuffer,
8.23 - .screen_limit = framebuffer + SCREEN_SIZE,
8.24 + /* Define display properties. */
8.25
8.26 - /* Define screen dimensions and properties. */
8.27 -
8.28 - .screen_size = SCREEN_SIZE,
8.29 - .line_length = LINE_LENGTH,
8.30 - .line_count = LINE_COUNT,
8.31 - .line_multiplier = LINE_MULTIPLIER,
8.32 + .scanlines = SCANLINES,
8.33 .cell_size = CELL_SIZE,
8.34 .transfer_cell_size = TRANSFER_CELL_SIZE,
8.35
9.1 --- a/lib/display.c Sat Nov 03 16:42:17 2018 +0100
9.2 +++ b/lib/display.c Sat Nov 03 21:47:40 2018 +0100
9.3 @@ -21,6 +21,99 @@
9.4
9.5
9.6
9.7 +/* Initialise a display configuration. */
9.8 +
9.9 +void init_display(display_config_t *cfg, uint8_t *framebuffer,
9.10 + uint32_t line_length, uint32_t line_count, int frames)
9.11 +{
9.12 + /* Framebuffer address. */
9.13 +
9.14 + cfg->framebuffer = framebuffer;
9.15 +
9.16 + /* Frame allocation limits. */
9.17 +
9.18 + cfg->total_lines = (line_count + 1) * frames;
9.19 + cfg->max_frames = frames;
9.20 +
9.21 + /* Screen size and dimensions. */
9.22 +
9.23 + cfg->screen_size = line_length * line_count;
9.24 + cfg->line_length = line_length;
9.25 + cfg->line_count = line_count;
9.26 +
9.27 + /* Set the number of frames and the current frame. */
9.28 +
9.29 + cfg->frames = frames;
9.30 + cfg->frame = 0;
9.31 +
9.32 + init_display_properties(cfg, 0);
9.33 +}
9.34 +
9.35 +/* Initialise the display constraints. */
9.36 +
9.37 +void init_display_properties(display_config_t *cfg, uint32_t offset)
9.38 +{
9.39 + /* Fixed address of the frame. */
9.40 +
9.41 + cfg->frame_start = cfg->framebuffer +
9.42 + (cfg->screen_size + cfg->line_length) * cfg->frame;
9.43 +
9.44 + /* Floating address of the screen contents. */
9.45 +
9.46 + cfg->screen_start = cfg->frame_start + offset;
9.47 +
9.48 + /* Fixed limit of the frame. */
9.49 +
9.50 + cfg->screen_limit = cfg->frame_start + cfg->screen_size;
9.51 +
9.52 + /* Recalculate the line multiplier. */
9.53 +
9.54 + cfg->line_multiplier = cfg->scanlines / cfg->line_count;
9.55 +}
9.56 +
9.57 +/* Set the number of frames in the framebuffer memory. */
9.58 +
9.59 +void set_frames(display_config_t *cfg, int frames)
9.60 +{
9.61 + /* Recalculate the number of lines. */
9.62 +
9.63 + cfg->line_count = (cfg->total_lines - cfg->max_frames) / frames;
9.64 +
9.65 + /* Recalculate the screen size. */
9.66 +
9.67 + cfg->screen_size = cfg->line_count * cfg->line_length;
9.68 +
9.69 + /* Set the number of frames and the current frame. */
9.70 +
9.71 + cfg->frames = frames;
9.72 + cfg->frame = 0;
9.73 +
9.74 + init_display_properties(cfg, 0);
9.75 +}
9.76 +
9.77 +/* Select a frame in the framebuffer. */
9.78 +
9.79 +void select_frame(display_config_t *cfg, int frame, uint32_t offset)
9.80 +{
9.81 + if ((frame < 0) || (frame >= cfg->frames))
9.82 + return;
9.83 +
9.84 + /* Update the frame details. */
9.85 +
9.86 + cfg->frame = frame;
9.87 +
9.88 + /* Set the screen start offset when switching frames. */
9.89 +
9.90 + init_display_properties(cfg, offset);
9.91 +}
9.92 +
9.93 +/* Return the screen start offset. */
9.94 +
9.95 +uint32_t get_start_offset(display_config_t *cfg)
9.96 +{
9.97 + return cfg->screen_start - cfg->frame_start;
9.98 +}
9.99 +
9.100 /* Return the line data position for the given pixel. */
9.101
9.102 int get_position(display_config_t *cfg, int x)
9.103 @@ -125,13 +218,13 @@
9.104
9.105 /* Wrap around the start of the framebuffer to the end. */
9.106
9.107 - if (start < cfg->framebuffer)
9.108 - start = cfg->screen_limit - (cfg->screen_limit - start) % cfg->screen_size;
9.109 + if (start < cfg->frame_start)
9.110 + start = cfg->screen_limit - (cfg->frame_start - start) % cfg->screen_size;
9.111
9.112 /* Wrap around the end of the framebuffer to the start. */
9.113
9.114 else if (start >= cfg->screen_limit)
9.115 - start = cfg->framebuffer + (start - cfg->framebuffer) % cfg->screen_size;
9.116 + start = cfg->frame_start + (start - cfg->screen_limit) % cfg->screen_size;
9.117
9.118 cfg->screen_start = start;
9.119 }