1.1 --- a/examples/vga/main.c Fri Nov 09 21:04:23 2018 +0100
1.2 +++ b/examples/vga/main.c Fri Nov 09 21:05:06 2018 +0100
1.3 @@ -89,6 +89,10 @@
1.4
1.5 static uint8_t framebuffer[FRAME_SIZE * FRAME_COUNT];
1.6
1.7 +/* Screen start values for each frame. */
1.8 +
1.9 +uint8_t *screen_starts[FRAME_COUNT];
1.10 +
1.11
1.12
1.13 /* Bundled image and font data. */
1.14 @@ -210,10 +214,6 @@
1.15 int background_x[FRAME_COUNT], background_y[FRAME_COUNT];
1.16 int background_stored[FRAME_COUNT];
1.17
1.18 - /* Screen start values for each frame. */
1.19 -
1.20 - uint32_t frame_offset[FRAME_COUNT];
1.21 -
1.22 /* Sprite position. */
1.23
1.24 int x, y;
1.25 @@ -242,7 +242,6 @@
1.26 for (frame = 0; frame < display_config.frames; frame++)
1.27 {
1.28 background_stored[frame] = 0;
1.29 - frame_offset[frame] = 0;
1.30 xorigins[frame] = xorigin;
1.31 yorigins[frame] = yorigin;
1.32 }
1.33 @@ -273,7 +272,7 @@
1.34 /* Select the next frame to plot to. */
1.35
1.36 frame = wrap_value(frame + 1, display_config.frames);
1.37 - display_select_frame(&display_config, frame, frame_offset[frame]);
1.38 + display_select_frame(&display_config, frame);
1.39
1.40 /* Prepare the frame for updates. */
1.41
1.42 @@ -312,10 +311,6 @@
1.43 display_scroll(&display_config, xstep / SCROLL_XSTEP,
1.44 ystep / SOURCE_YSTEP);
1.45
1.46 - /* Record the new screen start offset. */
1.47 -
1.48 - frame_offset[frame] = display_get_start_offset(&display_config);
1.49 -
1.50 /* For horizontal scrolling, plot the exposed column at the left
1.51 (if scrolling left) or at the right (if scrolling right). */
1.52
1.53 @@ -372,7 +367,7 @@
1.54 {
1.55 /* Obtain the frame. */
1.56
1.57 - display_select_frame(&display_config, frame, 0);
1.58 + display_select_frame(&display_config, frame);
1.59
1.60 /* Plot the image centred on the screen. */
1.61
1.62 @@ -388,7 +383,7 @@
1.63 write_chars();
1.64 }
1.65
1.66 - display_select_frame(&display_config, 0, 0);
1.67 + display_select_frame(&display_config, 0);
1.68 }
1.69
1.70
1.71 @@ -425,7 +420,8 @@
1.72
1.73 /* Initialise memory for a double-buffered display. */
1.74
1.75 - init_display(&display_config, framebuffer, LINE_LENGTH, LINE_COUNT, FRAME_COUNT);
1.76 + init_display(&display_config, framebuffer, LINE_LENGTH, LINE_COUNT,
1.77 + FRAME_COUNT, screen_starts);
1.78
1.79 /* Initialise VGA output with one or two line channels, configuring a line
1.80 timer and any transfer timer, with an initiating channel being introduced
2.1 --- a/include/display.h Fri Nov 09 21:04:23 2018 +0100
2.2 +++ b/include/display.h Fri Nov 09 21:05:06 2018 +0100
2.3 @@ -54,6 +54,10 @@
2.4
2.5 uint8_t *screen_start; /* >= frame_start; < screen_limit */
2.6
2.7 + /* A pointer to a collection of screen start pointers, one per frame. */
2.8 +
2.9 + uint8_t **screen_starts;
2.10 +
2.11 /* The fixed end address of the current frame. */
2.12
2.13 uint8_t *screen_limit; /* = frame_start + screen_size */
2.14 @@ -93,14 +97,19 @@
2.15 /* Configuration functions. */
2.16
2.17 void init_display(display_config_t *cfg, uint8_t *framebuffer,
2.18 - uint32_t line_length, uint32_t line_count, int frames);
2.19 + uint32_t line_length, uint32_t line_count,
2.20 + int frames, uint8_t **screen_starts);
2.21
2.22 -void init_display_properties(display_config_t *cfg, uint32_t offset);
2.23 +void init_display_properties(display_config_t *cfg);
2.24
2.25 -void display_select_frame(display_config_t *cfg, int frame, uint32_t offset);
2.26 +void init_frames(display_config_t *cfg);
2.27 +
2.28 +void display_select_frame(display_config_t *cfg, int frame);
2.29
2.30 void display_set_frames(display_config_t *cfg, int frames);
2.31
2.32 +uint8_t *display_get_frame_start(display_config_t *cfg, int frame);
2.33 +
2.34 uint32_t display_get_start_offset(display_config_t *cfg);
2.35
2.36 /* Access functions. */
3.1 --- a/lib/display.c Fri Nov 09 21:04:23 2018 +0100
3.2 +++ b/lib/display.c Fri Nov 09 21:05:06 2018 +0100
3.3 @@ -25,7 +25,8 @@
3.4 /* Initialise a display configuration. */
3.5
3.6 void init_display(display_config_t *cfg, uint8_t *framebuffer,
3.7 - uint32_t line_length, uint32_t line_count, int frames)
3.8 + uint32_t line_length, uint32_t line_count,
3.9 + int frames, uint8_t **screen_starts)
3.10 {
3.11 /* Framebuffer address. */
3.12
3.13 @@ -47,21 +48,32 @@
3.14 cfg->frames = frames;
3.15 cfg->frame = 0;
3.16
3.17 - init_display_properties(cfg, 0);
3.18 + /* Set the pointer to a collection of screen start pointers, one per
3.19 + frame. */
3.20 +
3.21 + cfg->screen_starts = screen_starts;
3.22 +
3.23 + init_frames(cfg);
3.24 + init_display_properties(cfg);
3.25 }
3.26
3.27 /* Initialise the display constraints. */
3.28
3.29 -void init_display_properties(display_config_t *cfg, uint32_t offset)
3.30 +void init_display_properties(display_config_t *cfg)
3.31 {
3.32 /* Fixed address of the frame. */
3.33
3.34 - cfg->frame_start = cfg->framebuffer +
3.35 - (cfg->screen_size + cfg->line_length) * cfg->frame;
3.36 + cfg->frame_start = display_get_frame_start(cfg, cfg->frame);
3.37
3.38 /* Floating address of the screen contents. */
3.39
3.40 - cfg->screen_start = cfg->frame_start + offset;
3.41 + if (cfg->screen_starts)
3.42 + cfg->screen_start = cfg->screen_starts[cfg->frame];
3.43 +
3.44 + /* Without any way of recording the address, just reset the start. */
3.45 +
3.46 + else
3.47 + cfg->screen_start = cfg->frame_start;
3.48
3.49 /* Fixed limit of the frame. */
3.50
3.51 @@ -72,22 +84,37 @@
3.52 cfg->line_multiplier = cfg->scanlines / cfg->line_count;
3.53 }
3.54
3.55 +/* Initialise the screen start addresses for all frames. */
3.56 +
3.57 +void init_frames(display_config_t *cfg)
3.58 +{
3.59 + int frame;
3.60 +
3.61 + for (frame = 0; frame < cfg->frames; frame++)
3.62 + cfg->screen_starts[frame] = display_get_frame_start(cfg, frame);
3.63 +}
3.64 +
3.65
3.66
3.67 /* Select a frame in the framebuffer. */
3.68
3.69 -void display_select_frame(display_config_t *cfg, int frame, uint32_t offset)
3.70 +void display_select_frame(display_config_t *cfg, int frame)
3.71 {
3.72 if ((frame < 0) || (frame >= cfg->frames))
3.73 return;
3.74
3.75 + /* Store the current frame's screen start, if possible. */
3.76 +
3.77 + if (cfg->screen_starts)
3.78 + cfg->screen_starts[cfg->frame] = cfg->screen_start;
3.79 +
3.80 /* Update the frame details. */
3.81
3.82 cfg->frame = frame;
3.83
3.84 /* Set the screen start offset when switching frames. */
3.85
3.86 - init_display_properties(cfg, offset);
3.87 + init_display_properties(cfg);
3.88 }
3.89
3.90 /* Set the number of frames in the framebuffer memory. */
3.91 @@ -110,11 +137,19 @@
3.92 cfg->frames = frames;
3.93 cfg->frame = 0;
3.94
3.95 - init_display_properties(cfg, 0);
3.96 + init_frames(cfg);
3.97 + init_display_properties(cfg);
3.98 }
3.99
3.100
3.101
3.102 +/* Return the start address of the given frame. */
3.103 +
3.104 +uint8_t *display_get_frame_start(display_config_t *cfg, int frame)
3.105 +{
3.106 + return cfg->framebuffer + (cfg->screen_size + cfg->line_length) * frame;
3.107 +}
3.108 +
3.109 /* Return the line data position for the given pixel. */
3.110
3.111 int display_get_position(display_config_t *cfg, int x)