# HG changeset patch # User Paul Boddie # Date 1540335048 -7200 # Node ID ad11390f6d086953777a82a5b86b1971b208d3f6 # Parent 4a67e90a0e1a4dd583958d1432e72900782bf467 Extracted the display state machine, moving it into a separate library module. diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga-dual/main.c --- a/examples/vga-dual/main.c Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga-dual/main.c Wed Oct 24 00:50:48 2018 +0200 @@ -29,17 +29,9 @@ #include "vga.h" #include "display.h" #include "display_config.h" - +#include "vga_display.h" -/* Display state. */ - -static void (*state_handler)(void); -static uint32_t line; - -/* Pointers to pixel lines. */ - -static uint8_t *linedata; /* Pixel data. */ @@ -75,8 +67,9 @@ void main(void) { - line = 0; - state_handler = vbp_active; + init_vga(&display_config, start_visible, update_visible, stop_visible, + vsync_high, vsync_low); + test_linedata(&display_config); init_memory(); @@ -179,104 +172,59 @@ if (ifs) { - line += 1; - state_handler(); + vga_interrupt_handler(); CLR_REG(OCIFS, ifs); } } -/* Vertical back porch region. */ - -void vbp_active(void) -{ - if (line < VISIBLE_START) - return; - - /* Enter the visible region. */ +/* Enable the channels for the next line. */ - state_handler = visible_active; - - /* Set the line address. */ - - linedata = display_config.screen_start; - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length / 2); - dma_set_source(1, PHYSICAL((uint32_t) linedata + display_config.line_length / 2), +void start_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), display_config.line_length / 2); - - /* Enable the channels for the next line. */ - + dma_set_source(1, PHYSICAL((uint32_t) vga_display->linedata + + display_config.line_length / 2), + display_config.line_length / 2); dma_on(0); dma_on(1); } -/* Visible region. */ - -void visible_active(void) -{ - INV_REG(PORTA, 1 << 2); - - if (line < VFP_START) - { - /* Update the line address and handle wraparound. */ +/* Update the channels for the next line. */ - if (!(line % display_config.line_multiplier)) - { - linedata += display_config.line_length; - if (linedata >= display_config.screen_limit) - linedata -= display_config.screen_size; - } +void update_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), + display_config.line_length / 2); + dma_set_source(1, PHYSICAL((uint32_t) vga_display->linedata + + display_config.line_length / 2), + display_config.line_length / 2); +} - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length / 2); - dma_set_source(1, PHYSICAL((uint32_t) linedata + display_config.line_length / 2), - display_config.line_length / 2); - return; - } +/* Disable the channels for the next line. */ - /* End the visible region. */ - - state_handler = vfp_active; - - /* Disable the channels for the next line. */ - +void stop_visible(vga_display_t *vga_display) +{ dma_off(0); dma_off(1); } -/* Vertical front porch region. */ - -void vfp_active(void) -{ - if (line < VSYNC_START) - return; +/* Bring vsync low (single compare, output driven low) when the next line + starts. */ - /* Enter the vertical sync region. */ - - state_handler = vsync_active; - - /* Bring vsync low (single compare, output driven low) when the next line - starts. */ - +void vsync_low(void) +{ oc_init(2, 0b010, 2); oc_on(2); } -/* Vertical sync region. */ - -void vsync_active(void) -{ - if (line < VSYNC_END) - return; +/* Bring vsync high (single compare, output driven high) when the next line + starts. */ - /* Start again at the top of the display. */ - - line = 0; - state_handler = vbp_active; - - /* Bring vsync high (single compare, output driven high) when the next line - starts. */ - +void vsync_high(void) +{ oc_init(2, 0b001, 2); oc_on(2); } diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga-dual/main.h --- a/examples/vga-dual/main.h Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga-dual/main.h Wed Oct 24 00:50:48 2018 +0200 @@ -20,16 +20,22 @@ #ifndef __MAIN_H__ #define __MAIN_H__ +#include "vga_display.h" + /* Peripheral pin configuration. */ void config_oc(void); void config_uart(void); -/* Display state handlers. */ +/* Display operations. */ -void vbp_active(void); -void visible_active(void); -void vfp_active(void); -void vsync_active(void); +void start_visible(vga_display_t *vga_display); +void update_visible(vga_display_t *vga_display); +void stop_visible(vga_display_t *vga_display); + +/* Vertical sync operations. */ + +void vsync_high(void); +void vsync_low(void); #endif /* __MAIN_H__ */ diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga-pmp/main.c --- a/examples/vga-pmp/main.c Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga-pmp/main.c Wed Oct 24 00:50:48 2018 +0200 @@ -29,17 +29,9 @@ #include "vga.h" #include "display.h" #include "display_config.h" - +#include "vga_display.h" -/* Display state. */ - -static void (*state_handler)(void); -static uint32_t line; - -/* Pointers to pixel lines. */ - -static uint8_t *linedata; /* Pixel data. */ @@ -75,8 +67,9 @@ void main(void) { - line = 0; - state_handler = vbp_active; + init_vga(&display_config, start_visible, update_visible, stop_visible, + vsync_high, vsync_low); + test_linedata(&display_config); init_memory(); @@ -104,7 +97,8 @@ dma_init(0, 3); dma_set_auto_enable(0, 1); dma_set_interrupt(0, T2, 1); - dma_set_transfer(0, PHYSICAL((uint32_t) linedata), display_config.line_length, + dma_set_transfer(0, PHYSICAL((uint32_t) display_config.screen_start), + display_config.line_length, HW_PHYSICAL(PM_REG(0, PMxDIN)), 1, TRANSFER_CELL_SIZE); @@ -175,96 +169,51 @@ if (ifs) { - line += 1; - state_handler(); + vga_interrupt_handler(); CLR_REG(OCIFS, ifs); } } -/* Vertical back porch region. */ - -void vbp_active(void) -{ - if (line < VISIBLE_START) - return; - - /* Enter the visible region. */ +/* Enable the channel for the next line. */ - state_handler = visible_active; - - /* Set the line address. */ - - linedata = display_config.screen_start; - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length); - - /* Enable the channel for the next line. */ - +void start_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), + display_config.line_length); dma_on(0); } -/* Visible region. */ - -void visible_active(void) -{ - if (line < VFP_START) - { - /* Update the line address and handle wraparound. */ +/* Update the channel for the next line. */ - if (!(line % display_config.line_multiplier)) - { - linedata += display_config.line_length; - if (linedata >= display_config.screen_limit) - linedata -= display_config.screen_size; - } +void update_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), + display_config.line_length); +} - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length); - return; - } +/* Disable the channel for the next line. */ - /* End the visible region. */ - - state_handler = vfp_active; - - /* Disable the channel for the next line. */ - +void stop_visible(vga_display_t *vga_display) +{ dma_off(0); } -/* Vertical front porch region. */ - -void vfp_active(void) -{ - if (line < VSYNC_START) - return; +/* Bring vsync low (single compare, output driven low) when the next line + starts. */ - /* Enter the vertical sync region. */ - - state_handler = vsync_active; - - /* Bring vsync low (single compare, output driven low) when the next line - starts. */ - +void vsync_low(void) +{ oc_init(2, 0b010, 2); oc_on(2); } -/* Vertical sync region. */ - -void vsync_active(void) -{ - if (line < VSYNC_END) - return; +/* Bring vsync high (single compare, output driven high) when the next line + starts. */ - /* Start again at the top of the display. */ - - line = 0; - state_handler = vbp_active; - - /* Bring vsync high (single compare, output driven high) when the next line - starts. */ - +void vsync_high(void) +{ oc_init(2, 0b001, 2); oc_on(2); } diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga-pmp/main.h --- a/examples/vga-pmp/main.h Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga-pmp/main.h Wed Oct 24 00:50:48 2018 +0200 @@ -20,16 +20,22 @@ #ifndef __MAIN_H__ #define __MAIN_H__ +#include "vga_display.h" + /* Peripheral pin configuration. */ void config_oc(void); void config_uart(void); -/* Display state handlers. */ +/* Display operations. */ -void vbp_active(void); -void visible_active(void); -void vfp_active(void); -void vsync_active(void); +void start_visible(vga_display_t *vga_display); +void update_visible(vga_display_t *vga_display); +void stop_visible(vga_display_t *vga_display); + +/* Vertical sync operations. */ + +void vsync_high(void); +void vsync_low(void); #endif /* __MAIN_H__ */ diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga-timer/main.c --- a/examples/vga-timer/main.c Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga-timer/main.c Wed Oct 24 00:50:48 2018 +0200 @@ -29,17 +29,9 @@ #include "vga.h" #include "display.h" #include "display_config.h" - +#include "vga_display.h" -/* Display state. */ - -static void (*state_handler)(void); -static uint32_t line; - -/* Pointers to pixel lines. */ - -static uint8_t *linedata; /* Pixel data. */ @@ -75,8 +67,9 @@ void main(void) { - line = 0; - state_handler = vbp_active; + init_vga(&display_config, start_visible, update_visible, stop_visible, + vsync_high, vsync_low); + test_linedata(&display_config); init_memory(); @@ -206,102 +199,57 @@ if (ifs) { - line += 1; - state_handler(); + vga_interrupt_handler(); CLR_REG(OCIFS, ifs); } } -/* Vertical back porch region. */ - -void vbp_active(void) -{ - if (line < VISIBLE_START) - return; - - /* Enter the visible region. */ +/* Enable the channels for the next line. */ - state_handler = visible_active; - - /* Set the line address. */ - - linedata = display_config.screen_start; - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length / 2); - dma_set_source(2, PHYSICAL((uint32_t) linedata + display_config.line_length / 2), +void start_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), display_config.line_length / 2); - - /* Enable the channels for the next line. */ - + dma_set_source(2, PHYSICAL((uint32_t) vga_display->linedata + + display_config.line_length / 2), + display_config.line_length / 2); dma_on(1); } -/* Visible region. */ - -void visible_active(void) -{ - INV_REG(PORTA, 1 << 2); - - if (line < VFP_START) - { - /* Update the line address and handle wraparound. */ +/* Update the channels for the next line. */ - if (!(line % display_config.line_multiplier)) - { - linedata += display_config.line_length; - if (linedata >= display_config.screen_limit) - linedata -= display_config.screen_size; - } +void update_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), + display_config.line_length / 2); + dma_set_source(2, PHYSICAL((uint32_t) vga_display->linedata + + display_config.line_length / 2), + display_config.line_length / 2); +} - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length / 2); - dma_set_source(2, PHYSICAL((uint32_t) linedata + display_config.line_length / 2), - display_config.line_length / 2); - return; - } +/* Disable the channels for the next line. */ - /* End the visible region. */ - - state_handler = vfp_active; - - /* Disable the channels for the next line. */ - +void stop_visible(vga_display_t *vga_display) +{ dma_off(1); } -/* Vertical front porch region. */ - -void vfp_active(void) -{ - if (line < VSYNC_START) - return; +/* Bring vsync low (single compare, output driven low) when the next line + starts. */ - /* Enter the vertical sync region. */ - - state_handler = vsync_active; - - /* Bring vsync low (single compare, output driven low) when the next line - starts. */ - +void vsync_low(void) +{ oc_init(2, 0b010, 2); oc_on(2); } -/* Vertical sync region. */ - -void vsync_active(void) -{ - if (line < VSYNC_END) - return; +/* Bring vsync high (single compare, output driven high) when the next line + starts. */ - /* Start again at the top of the display. */ - - line = 0; - state_handler = vbp_active; - - /* Bring vsync high (single compare, output driven high) when the next line - starts. */ - +void vsync_high(void) +{ oc_init(2, 0b001, 2); oc_on(2); } diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga-timer/main.h --- a/examples/vga-timer/main.h Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga-timer/main.h Wed Oct 24 00:50:48 2018 +0200 @@ -20,16 +20,22 @@ #ifndef __MAIN_H__ #define __MAIN_H__ +#include "vga_display.h" + /* Peripheral pin configuration. */ void config_oc(void); void config_uart(void); -/* Display state handlers. */ +/* Display operations. */ -void vbp_active(void); -void visible_active(void); -void vfp_active(void); -void vsync_active(void); +void start_visible(vga_display_t *vga_display); +void update_visible(vga_display_t *vga_display); +void stop_visible(vga_display_t *vga_display); + +/* Vertical sync operations. */ + +void vsync_high(void); +void vsync_low(void); #endif /* __MAIN_H__ */ diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga/main.c --- a/examples/vga/main.c Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga/main.c Wed Oct 24 00:50:48 2018 +0200 @@ -29,17 +29,9 @@ #include "vga.h" #include "display.h" #include "display_config.h" - +#include "vga_display.h" -/* Display state. */ - -static void (*state_handler)(void); -static uint32_t line; - -/* Pointers to pixel lines. */ - -static uint8_t *linedata; /* Pixel data. */ @@ -75,8 +67,8 @@ void main(void) { - line = 0; - state_handler = vbp_active; + init_vga(&display_config, start_visible, update_visible, stop_visible, + vsync_high, vsync_low); test_linedata(&display_config); @@ -168,98 +160,51 @@ if (ifs) { - line += 1; - state_handler(); + vga_interrupt_handler(); CLR_REG(OCIFS, ifs); } } -/* Vertical back porch region. */ - -void vbp_active(void) -{ - if (line < VISIBLE_START) - return; - - /* Enter the visible region. */ +/* Enable the channel for the next line. */ - state_handler = visible_active; - - /* Set the line address. */ - - linedata = display_config.screen_start; - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length); - - /* Enable the channel for the next line. */ - +void start_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), + display_config.line_length); dma_on(0); } -/* Visible region. */ - -void visible_active(void) -{ - INV_REG(PORTA, 1 << 2); - - if (line < VFP_START) - { - /* Update the line address and handle wraparound. */ +/* Update the channel for the next line. */ - if (!(line % display_config.line_multiplier)) - { - linedata += display_config.line_length; - if (linedata >= display_config.screen_limit) - linedata -= display_config.screen_size; - } +void update_visible(vga_display_t *vga_display) +{ + dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata), + display_config.line_length); +} - dma_set_source(0, PHYSICAL((uint32_t) linedata), display_config.line_length); - return; - } +/* Disable the channel for the next line. */ - /* End the visible region. */ - - state_handler = vfp_active; - - /* Disable the channel for the next line. */ - +void stop_visible(vga_display_t *vga_display) +{ dma_off(0); } -/* Vertical front porch region. */ - -void vfp_active(void) -{ - if (line < VSYNC_START) - return; +/* Bring vsync low (single compare, output driven low) when the next line + starts. */ - /* Enter the vertical sync region. */ - - state_handler = vsync_active; - - /* Bring vsync low (single compare, output driven low) when the next line - starts. */ - +void vsync_low(void) +{ oc_init(2, 0b010, 2); oc_on(2); } -/* Vertical sync region. */ - -void vsync_active(void) -{ - if (line < VSYNC_END) - return; +/* Bring vsync high (single compare, output driven high) when the next line + starts. */ - /* Start again at the top of the display. */ - - line = 0; - state_handler = vbp_active; - - /* Bring vsync high (single compare, output driven high) when the next line - starts. */ - +void vsync_high(void) +{ oc_init(2, 0b001, 2); oc_on(2); } diff -r 4a67e90a0e1a -r ad11390f6d08 examples/vga/main.h --- a/examples/vga/main.h Tue Oct 23 23:25:47 2018 +0200 +++ b/examples/vga/main.h Wed Oct 24 00:50:48 2018 +0200 @@ -20,16 +20,22 @@ #ifndef __MAIN_H__ #define __MAIN_H__ +#include "vga_display.h" + /* Peripheral pin configuration. */ void config_oc(void); void config_uart(void); -/* Display state handlers. */ +/* Display operations. */ -void vbp_active(void); -void visible_active(void); -void vfp_active(void); -void vsync_active(void); +void start_visible(vga_display_t *vga_display); +void update_visible(vga_display_t *vga_display); +void stop_visible(vga_display_t *vga_display); + +/* Vertical sync operations. */ + +void vsync_high(void); +void vsync_low(void); #endif /* __MAIN_H__ */ diff -r 4a67e90a0e1a -r ad11390f6d08 include/display.h --- a/include/display.h Tue Oct 23 23:25:47 2018 +0200 +++ b/include/display.h Wed Oct 24 00:50:48 2018 +0200 @@ -46,6 +46,10 @@ int cell_size; + /* Display region scanline positions. */ + + uint32_t visible_start, vfp_start, vsync_start, vsync_end; + } display_config_t; diff -r 4a67e90a0e1a -r ad11390f6d08 include/display_config.h --- a/include/display_config.h Tue Oct 23 23:25:47 2018 +0200 +++ b/include/display_config.h Wed Oct 24 00:50:48 2018 +0200 @@ -1,5 +1,5 @@ /* - * VGA-specific display-related functions. + * Initialisation of application-specific display configuration. * * Copyright (C) 2018 Paul Boddie * @@ -17,22 +17,36 @@ * along with this program. If not, see . */ -#ifndef __DISPLAY_VGA_H__ -#define __DISPLAY_VGA_H__ +#ifndef __DISPLAY_CONFIG_H__ +#define __DISPLAY_CONFIG_H__ #include "display.h" uint8_t framebuffer[SCREEN_SIZE]; display_config_t display_config = { + + /* Set the reserved memory as the framebuffer. */ + .framebuffer = framebuffer, + .screen_start = framebuffer, + .screen_limit = framebuffer + SCREEN_SIZE, + + /* Define screen dimensions and properties. */ + .screen_size = SCREEN_SIZE, .line_length = LINE_LENGTH, .line_count = LINE_COUNT, .line_multiplier = LINE_MULTIPLIER, .cell_size = CELL_SIZE, - .screen_start = framebuffer, - .screen_limit = framebuffer + SCREEN_SIZE, + + /* Define display region properties. */ + + .visible_start = VISIBLE_START, + .vfp_start = VFP_START, + .vsync_start = VSYNC_START, + .vsync_end = VSYNC_END, + }; -#endif /* __DISPLAY_VGA_H__ */ +#endif /* __DISPLAY_CONFIG_H__ */ diff -r 4a67e90a0e1a -r ad11390f6d08 include/vga_display.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/vga_display.h Wed Oct 24 00:50:48 2018 +0200 @@ -0,0 +1,82 @@ +/* + * VGA display-related functions. + * + * Copyright (C) 2018 Paul Boddie + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __VGA_DISPLAY_H__ +#define __VGA_DISPLAY_H__ + +#include "display.h" + + + +/* Display configuration type. */ + +typedef struct +{ + /* Current display state handler. */ + + void (*state_handler)(); + + /* Display state handlers. */ + + void (*start_visible)(); + void (*update_visible)(); + void (*stop_visible)(); + + /* Vertical sync operations. */ + + void (*vsync_high)(); + void (*vsync_low)(); + + /* Current scanline. */ + + uint32_t line; + + /* Pointers to pixel lines. */ + + uint8_t *linedata; + + /* General display configuration. */ + + display_config_t *display_config; + +} vga_display_t; + + + +/* Initialisation. */ + +void init_vga(display_config_t *display_config, + void (*start_visible)(), + void (*update_visible)(), + void (*stop_visible)(), + void (*vsync_high)(), + void (*vsync_low)()); + +/* Interrupt handlers. */ + +void vga_interrupt_handler(void); + +/* Display state handlers. */ + +void vbp_active(void); +void visible_active(void); +void vfp_active(void); +void vsync_active(void); + +#endif /* __VGA_DISPLAY_H__ */ diff -r 4a67e90a0e1a -r ad11390f6d08 lib/vga_display.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/vga_display.c Wed Oct 24 00:50:48 2018 +0200 @@ -0,0 +1,150 @@ +/* + * Generate a VGA signal using a PIC32 microcontroller. + * + * Copyright (C) 2017, 2018 Paul Boddie + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "pic32_c.h" +#include "vga_display.h" + + + +/* Display state. */ + +vga_display_t vga_display; + + + +/* Initialise the state machine. */ + +void init_vga(display_config_t *display_config, + void (*start_visible)(), + void (*update_visible)(), + void (*stop_visible)(), + void (*vsync_high)(), + void (*vsync_low)()) +{ + /* Display parameters. */ + + vga_display.display_config = display_config; + + /* Display state handlers. */ + + vga_display.start_visible = start_visible; + vga_display.update_visible = update_visible; + vga_display.stop_visible = stop_visible; + + /* Vertical sync operations. */ + + vga_display.vsync_high = vsync_high; + vga_display.vsync_low = vsync_low; + + /* Initial state. */ + + vga_display.state_handler = vbp_active; + vga_display.line = 0; +} + + + +/* Interrupt handlers. */ + +void vga_interrupt_handler(void) +{ + vga_display.line += 1; + vga_display.state_handler(); +} + + + +/* Vertical back porch region. */ + +void vbp_active(void) +{ + if (vga_display.line < vga_display.display_config->visible_start) + return; + + /* Enter the visible region. */ + + vga_display.state_handler = visible_active; + + /* Set the line address. */ + + vga_display.linedata = vga_display.display_config->screen_start; + vga_display.start_visible(&vga_display); +} + +/* Visible region. */ + +void visible_active(void) +{ + if (vga_display.line < vga_display.display_config->vfp_start) + { + /* Update the line address and handle wraparound. */ + + if (!(vga_display.line % vga_display.display_config->line_multiplier)) + { + vga_display.linedata += vga_display.display_config->line_length; + + if (vga_display.linedata >= vga_display.display_config->screen_limit) + vga_display.linedata -= vga_display.display_config->screen_size; + } + + vga_display.update_visible(&vga_display); + return; + } + + /* End the visible region. */ + + vga_display.state_handler = vfp_active; + + /* Disable the channel for the next line. */ + + vga_display.stop_visible(&vga_display); +} + +/* Vertical front porch region. */ + +void vfp_active(void) +{ + if (vga_display.line < vga_display.display_config->vsync_start) + return; + + /* Enter the vertical sync region. */ + + vga_display.state_handler = vsync_active; + + /* Bring vsync low when the next line starts. */ + + vga_display.vsync_low(); +} + +/* Vertical sync region. */ + +void vsync_active(void) +{ + if (vga_display.line < vga_display.display_config->vsync_end) + return; + + /* Start again at the top of the display. */ + + vga_display.line = 0; + vga_display.state_handler = vbp_active; + + /* Bring vsync high when the next line starts. */ + + vga_display.vsync_high(); +} diff -r 4a67e90a0e1a -r ad11390f6d08 mk/common.mk --- a/mk/common.mk Tue Oct 23 23:25:47 2018 +0200 +++ b/mk/common.mk Wed Oct 24 00:50:48 2018 +0200 @@ -51,8 +51,8 @@ COMMON_SRC = $(LIBDIR)/init.c $(LIBDIR)/debug.c $(LIBDIR)/cpu.S COMMON_OBJ = $(LIBDIR)/init.o $(LIBDIR)/debug.o $(LIBDIR)/cpu.o -DISPLAY_SRC = $(LIBDIR)/display.c -DISPLAY_OBJ = $(LIBDIR)/display.o +DISPLAY_SRC = $(LIBDIR)/display.c $(LIBDIR)/vga_display.c +DISPLAY_OBJ = $(LIBDIR)/display.o $(LIBDIR)/vga_display.o # Common linker script.