# HG changeset patch # User Paul Boddie # Date 1541793906 -3600 # Node ID bfe765ff97e0520cbffc0aab8b458ede9834cd02 # Parent 839de4f15476a3be250f12d9170d192c3b83e3d4 Introduced screen start address retention for each frame in the display library. diff -r 839de4f15476 -r bfe765ff97e0 examples/vga/main.c --- a/examples/vga/main.c Fri Nov 09 21:04:23 2018 +0100 +++ b/examples/vga/main.c Fri Nov 09 21:05:06 2018 +0100 @@ -89,6 +89,10 @@ static uint8_t framebuffer[FRAME_SIZE * FRAME_COUNT]; +/* Screen start values for each frame. */ + +uint8_t *screen_starts[FRAME_COUNT]; + /* Bundled image and font data. */ @@ -210,10 +214,6 @@ int background_x[FRAME_COUNT], background_y[FRAME_COUNT]; int background_stored[FRAME_COUNT]; - /* Screen start values for each frame. */ - - uint32_t frame_offset[FRAME_COUNT]; - /* Sprite position. */ int x, y; @@ -242,7 +242,6 @@ for (frame = 0; frame < display_config.frames; frame++) { background_stored[frame] = 0; - frame_offset[frame] = 0; xorigins[frame] = xorigin; yorigins[frame] = yorigin; } @@ -273,7 +272,7 @@ /* Select the next frame to plot to. */ frame = wrap_value(frame + 1, display_config.frames); - display_select_frame(&display_config, frame, frame_offset[frame]); + display_select_frame(&display_config, frame); /* Prepare the frame for updates. */ @@ -312,10 +311,6 @@ display_scroll(&display_config, xstep / SCROLL_XSTEP, ystep / SOURCE_YSTEP); - /* Record the new screen start offset. */ - - frame_offset[frame] = display_get_start_offset(&display_config); - /* For horizontal scrolling, plot the exposed column at the left (if scrolling left) or at the right (if scrolling right). */ @@ -372,7 +367,7 @@ { /* Obtain the frame. */ - display_select_frame(&display_config, frame, 0); + display_select_frame(&display_config, frame); /* Plot the image centred on the screen. */ @@ -388,7 +383,7 @@ write_chars(); } - display_select_frame(&display_config, 0, 0); + display_select_frame(&display_config, 0); } @@ -425,7 +420,8 @@ /* Initialise memory for a double-buffered display. */ - init_display(&display_config, framebuffer, LINE_LENGTH, LINE_COUNT, FRAME_COUNT); + init_display(&display_config, framebuffer, LINE_LENGTH, LINE_COUNT, + FRAME_COUNT, screen_starts); /* Initialise VGA output with one or two line channels, configuring a line timer and any transfer timer, with an initiating channel being introduced diff -r 839de4f15476 -r bfe765ff97e0 include/display.h --- a/include/display.h Fri Nov 09 21:04:23 2018 +0100 +++ b/include/display.h Fri Nov 09 21:05:06 2018 +0100 @@ -54,6 +54,10 @@ uint8_t *screen_start; /* >= frame_start; < screen_limit */ + /* A pointer to a collection of screen start pointers, one per frame. */ + + uint8_t **screen_starts; + /* The fixed end address of the current frame. */ uint8_t *screen_limit; /* = frame_start + screen_size */ @@ -93,14 +97,19 @@ /* Configuration functions. */ void init_display(display_config_t *cfg, uint8_t *framebuffer, - uint32_t line_length, uint32_t line_count, int frames); + uint32_t line_length, uint32_t line_count, + int frames, uint8_t **screen_starts); -void init_display_properties(display_config_t *cfg, uint32_t offset); +void init_display_properties(display_config_t *cfg); -void display_select_frame(display_config_t *cfg, int frame, uint32_t offset); +void init_frames(display_config_t *cfg); + +void display_select_frame(display_config_t *cfg, int frame); void display_set_frames(display_config_t *cfg, int frames); +uint8_t *display_get_frame_start(display_config_t *cfg, int frame); + uint32_t display_get_start_offset(display_config_t *cfg); /* Access functions. */ diff -r 839de4f15476 -r bfe765ff97e0 lib/display.c --- a/lib/display.c Fri Nov 09 21:04:23 2018 +0100 +++ b/lib/display.c Fri Nov 09 21:05:06 2018 +0100 @@ -25,7 +25,8 @@ /* Initialise a display configuration. */ void init_display(display_config_t *cfg, uint8_t *framebuffer, - uint32_t line_length, uint32_t line_count, int frames) + uint32_t line_length, uint32_t line_count, + int frames, uint8_t **screen_starts) { /* Framebuffer address. */ @@ -47,21 +48,32 @@ cfg->frames = frames; cfg->frame = 0; - init_display_properties(cfg, 0); + /* Set the pointer to a collection of screen start pointers, one per + frame. */ + + cfg->screen_starts = screen_starts; + + init_frames(cfg); + init_display_properties(cfg); } /* Initialise the display constraints. */ -void init_display_properties(display_config_t *cfg, uint32_t offset) +void init_display_properties(display_config_t *cfg) { /* Fixed address of the frame. */ - cfg->frame_start = cfg->framebuffer + - (cfg->screen_size + cfg->line_length) * cfg->frame; + cfg->frame_start = display_get_frame_start(cfg, cfg->frame); /* Floating address of the screen contents. */ - cfg->screen_start = cfg->frame_start + offset; + if (cfg->screen_starts) + cfg->screen_start = cfg->screen_starts[cfg->frame]; + + /* Without any way of recording the address, just reset the start. */ + + else + cfg->screen_start = cfg->frame_start; /* Fixed limit of the frame. */ @@ -72,22 +84,37 @@ cfg->line_multiplier = cfg->scanlines / cfg->line_count; } +/* Initialise the screen start addresses for all frames. */ + +void init_frames(display_config_t *cfg) +{ + int frame; + + for (frame = 0; frame < cfg->frames; frame++) + cfg->screen_starts[frame] = display_get_frame_start(cfg, frame); +} + /* Select a frame in the framebuffer. */ -void display_select_frame(display_config_t *cfg, int frame, uint32_t offset) +void display_select_frame(display_config_t *cfg, int frame) { if ((frame < 0) || (frame >= cfg->frames)) return; + /* Store the current frame's screen start, if possible. */ + + if (cfg->screen_starts) + cfg->screen_starts[cfg->frame] = cfg->screen_start; + /* Update the frame details. */ cfg->frame = frame; /* Set the screen start offset when switching frames. */ - init_display_properties(cfg, offset); + init_display_properties(cfg); } /* Set the number of frames in the framebuffer memory. */ @@ -110,11 +137,19 @@ cfg->frames = frames; cfg->frame = 0; - init_display_properties(cfg, 0); + init_frames(cfg); + init_display_properties(cfg); } +/* Return the start address of the given frame. */ + +uint8_t *display_get_frame_start(display_config_t *cfg, int frame) +{ + return cfg->framebuffer + (cfg->screen_size + cfg->line_length) * frame; +} + /* Return the line data position for the given pixel. */ int display_get_position(display_config_t *cfg, int x)