# HG changeset patch # User Paul Boddie # Date 1540495141 -7200 # Node ID 45a99a68c2ed4abc30a2fffbb6f6b7b58a43968b # Parent ddc36d3c6fbb52bde2ad21f3d40e9a2d54f3608b Made VGA initialisation more convenient, permitting the indication of timers to be used and simplifying the DMA-related configuration operations. Eliminated duplicate files, directing Makefiles to the vga example's resources where possible. The vga, vga-dual and vga-timer examples employ the same main file as a result. diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-dual/Makefile --- a/examples/vga-dual/Makefile Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga-dual/Makefile Thu Oct 25 21:19:01 2018 +0200 @@ -30,4 +30,9 @@ SRC = $(START_SRC) main.c $(COMMON_SRC) $(DISPLAY_SRC) OBJ = $(START_OBJ) main.o $(COMMON_OBJ) $(DISPLAY_OBJ) +# Application-specific adjustments. +# See: examples/vga/Makefile + +CFLAGS += -DLINE_CHANNELS=2 -I../vga + include ../../mk/rules.mk diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-dual/devconfig.h --- a/examples/vga-dual/devconfig.h Thu Oct 25 21:11:22 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Device configuration. - * - * 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 __CONFIG_H__ -#define __CONFIG_H__ - -#include "pic32.h" - -/* -Set the oscillator to be the FRC oscillator with PLL, with peripheral clock -divided by 2 (FPBDIV), and FRCDIV+PLL selected (FNOSC). - -The watchdog timer (FWDTEN) is also disabled. - -The secondary oscillator pin (FSOSCEN) is disabled to avoid pin conflicts with -RPB4. -*/ - -#define DEVCFG1_CONFIG (DEVCFG1_FWDTEN_OFF | DEVCFG1_FPBDIV_2 | \ - DEVCFG1_OSCIOFNC_OFF | DEVCFG1_FSOSCEN_OFF | \ - DEVCFG1_FNOSC_FRCDIV_PLL) - -/* -Set the FRC oscillator PLL function with an input division of 2, an output -division of 2, a multiplication of 24, yielding a multiplication of 6. - -The FRC is apparently at 8MHz but enforces input division of 2 to produce a -frequency in the acceptable range from 4MHz to 5MHz for the PLL: - -8MHz / 2 = 4MHz - -Multiplication and output division should produce a system clock of 48MHz: - -4MHz * 24 / 2 = 48MHz -*/ - -#define DEVCFG2_CONFIG (DEVCFG2_FPLLODIV_2 | DEVCFG2_FPLLMUL_24 | \ - DEVCFG2_FPLLIDIV_2) - -/* -The peripheral clock frequency (FPB) will be 24MHz given the above DEVCFG1 and -DEVCFG2 settings. -*/ - -#define FPB 24000000 - -#endif /* __CONFIG_H__ */ diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-dual/main.c --- a/examples/vga-dual/main.c Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga-dual/main.c Thu Oct 25 21:19:01 2018 +0200 @@ -1,148 +1,1 @@ -/* - * 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 "init.h" -#include "debug.h" - -/* Specific functionality. */ - -#include "main.h" -#include "devconfig.h" -#include "vga.h" -#include "display.h" -#include "display_config.h" -#include "vga_display.h" - - - -/* Blink an attached LED with delays implemented using a loop. */ - -static void blink(uint32_t delay, uint32_t port, uint32_t pins) -{ - uint32_t counter; - - /* Clear outputs (LED). */ - - CLR_REG(port, pins); - - while (1) - { - counter = delay; - - while (counter--) __asm__(""); /* retain loop */ - - /* Invert outputs (LED). */ - - INV_REG(port, pins); - } -} - - - -/* Main program. */ - -void main(void) -{ - init_memory(); - init_pins(); - init_outputs(); - - unlock_config(); - config_oc(); - config_uart(); - lock_config(); - - init_dma(); - - /* Initialise VGA output structures with two line channels and no initiating - channel. */ - - init_vga(&display_config, 2, -1); - - /* Configure VGA output transfer details along with a timer and output - compare units for horizontal and vertical sync. */ - - vga_configure_transfer(T2, PORTB); - vga_configure_sync(1, 2, 2); - - uart_init(1, FPB, 115200); - uart_on(1); - - test_linedata(&display_config); - - interrupts_on(); - - blink(3 << 24, PORTA, 1 << 3); -} - - - -/* Exception and interrupt handlers. */ - -void exception_handler(void) -{ - blink(3 << 12, PORTA, 1 << 3); -} - -void interrupt_handler(void) -{ - uint32_t ifs; - - /* Check for a OC1 interrupt condition. */ - - ifs = REG(OCIFS) & OC_INT_FLAGS(1, OCxIF); - - if (ifs) - { - vga_interrupt_handler(); - CLR_REG(OCIFS, ifs); - } -} - - - -/* Peripheral pin configuration. */ - -void config_oc(void) -{ - /* Map OC1 to RPA0. */ - - REG(RPA0R) = 0b0101; /* RPA0R<3:0> = 0101 (OC1) */ - - /* Map OC2 to RPA1. */ - - REG(RPA1R) = 0b0101; /* RPA1R<3:0> = 0101 (OC2) */ -} - -void config_uart(void) -{ - /* Map U1RX to RPB13. */ - - REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */ - - /* Map U1TX to RPB15. */ - - REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */ - - /* Set RPB13 to input. */ - - SET_REG(TRISB, 1 << 13); -} +../vga/main.c \ No newline at end of file diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-dual/main.h --- a/examples/vga-dual/main.h Thu Oct 25 21:11:22 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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 . - */ - -#ifndef __MAIN_H__ -#define __MAIN_H__ - -#include "vga_display.h" - -/* Peripheral pin configuration. */ - -void config_oc(void); -void config_uart(void); - -#endif /* __MAIN_H__ */ diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-pmp/Makefile --- a/examples/vga-pmp/Makefile Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga-pmp/Makefile Thu Oct 25 21:19:01 2018 +0200 @@ -30,4 +30,8 @@ SRC = $(START_SRC) main.c $(COMMON_SRC) $(DISPLAY_SRC) OBJ = $(START_OBJ) main.o $(COMMON_OBJ) $(DISPLAY_OBJ) +# Application-specific adjustments. + +CFLAGS += -I../vga + include ../../mk/rules.mk diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-pmp/main.c --- a/examples/vga-pmp/main.c Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga-pmp/main.c Thu Oct 25 21:19:01 2018 +0200 @@ -79,16 +79,16 @@ pm_set_output(0, 1, 0); pm_on(0); - /* Initialise VGA output structures with a single line channel and no - initiating channel. */ + /* Initialise VGA output with a single line channel, configuring Timer2, + with no transfer timer and thus no initiating channel. */ - init_vga(&display_config, 1, -1); + init_vga_with_timers(&display_config, 1, 2, 0); - /* Configure VGA output transfer details along with a timer and output - compare units for horizontal and vertical sync. */ + /* Configure VGA output transfer to the parallel mode output register, also + configuring output compare units for horizontal and vertical sync. */ - vga_configure_transfer(T2, PM_REG(0, PMxDIN)); - vga_configure_sync(1, 2, 2); + vga_configure_transfer(PM_REG(0, PMxDIN)); + vga_configure_sync(1, 2); uart_init(1, FPB, 115200); uart_on(1); diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-pmp/main.h --- a/examples/vga-pmp/main.h Thu Oct 25 21:11:22 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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 . - */ - -#ifndef __MAIN_H__ -#define __MAIN_H__ - -#include "vga_display.h" - -/* Peripheral pin configuration. */ - -void config_oc(void); -void config_uart(void); - -#endif /* __MAIN_H__ */ diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-timer/Makefile --- a/examples/vga-timer/Makefile Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga-timer/Makefile Thu Oct 25 21:19:01 2018 +0200 @@ -30,4 +30,9 @@ SRC = $(START_SRC) main.c $(COMMON_SRC) $(DISPLAY_SRC) OBJ = $(START_OBJ) main.o $(COMMON_OBJ) $(DISPLAY_OBJ) +# Application-specific adjustments. +# See: examples/vga/Makefile + +CFLAGS += -DLINE_CHANNELS=2 -DTRANSFER_TIMER=3 -I../vga + include ../../mk/rules.mk diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-timer/devconfig.h --- a/examples/vga-timer/devconfig.h Thu Oct 25 21:11:22 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Device configuration. - * - * 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 __CONFIG_H__ -#define __CONFIG_H__ - -#include "pic32.h" - -/* -Set the oscillator to be the FRC oscillator with PLL, with peripheral clock -divided by 2 (FPBDIV), and FRCDIV+PLL selected (FNOSC). - -The watchdog timer (FWDTEN) is also disabled. - -The secondary oscillator pin (FSOSCEN) is disabled to avoid pin conflicts with -RPB4. -*/ - -#define DEVCFG1_CONFIG (DEVCFG1_FWDTEN_OFF | DEVCFG1_FPBDIV_2 | \ - DEVCFG1_OSCIOFNC_OFF | DEVCFG1_FSOSCEN_OFF | \ - DEVCFG1_FNOSC_FRCDIV_PLL) - -/* -Set the FRC oscillator PLL function with an input division of 2, an output -division of 2, a multiplication of 24, yielding a multiplication of 6. - -The FRC is apparently at 8MHz but enforces input division of 2 to produce a -frequency in the acceptable range from 4MHz to 5MHz for the PLL: - -8MHz / 2 = 4MHz - -Multiplication and output division should produce a system clock of 48MHz: - -4MHz * 24 / 2 = 48MHz -*/ - -#define DEVCFG2_CONFIG (DEVCFG2_FPLLODIV_2 | DEVCFG2_FPLLMUL_24 | \ - DEVCFG2_FPLLIDIV_2) - -/* -The peripheral clock frequency (FPB) will be 24MHz given the above DEVCFG1 and -DEVCFG2 settings. -*/ - -#define FPB 24000000 - -#endif /* __CONFIG_H__ */ diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-timer/main.c --- a/examples/vga-timer/main.c Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga-timer/main.c Thu Oct 25 21:19:01 2018 +0200 @@ -1,165 +1,1 @@ -/* - * 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 "init.h" -#include "debug.h" - -/* Specific functionality. */ - -#include "main.h" -#include "devconfig.h" -#include "vga.h" -#include "display.h" -#include "display_config.h" -#include "vga_display.h" - - - -/* Blink an attached LED with delays implemented using a loop. */ - -static void blink(uint32_t delay, uint32_t port, uint32_t pins) -{ - uint32_t counter; - - /* Clear outputs (LED). */ - - CLR_REG(port, pins); - - while (1) - { - counter = delay; - - while (counter--) __asm__(""); /* retain loop */ - - /* Invert outputs (LED). */ - - INV_REG(port, pins); - } -} - - - -/* Main program. */ - -void main(void) -{ - init_memory(); - init_pins(); - init_outputs(); - - unlock_config(); - config_oc(); - config_uart(); - lock_config(); - - init_dma(); - - /* Initialise VGA output structures with two line channels and an initiating - channel. */ - - init_vga(&display_config, 2, T2); - - /* Peripheral relationships: - - Timer2 -> OC1 - -> OC2 (vertical sync region) - -> DMA1: zerodata -> PORTB (visible region) - | - Timer3 -> DMA0: linedata -> PORTB - Timer3 -> DMA2: linedata -> PORTB - | - Timer3 -> DMA3: zerodata -> PORTB - */ - - /* Configure VGA output transfer details along with a timer and output - compare units for horizontal and vertical sync. */ - - vga_configure_transfer(T3, PORTB); - vga_configure_sync(1, 2, 2); - - /* Configure a timer for line data transfers. */ - - timer_init(3, 0, 1); - timer_on(3); - - uart_init(1, FPB, 115200); - uart_on(1); - - test_linedata(&display_config); - - interrupts_on(); - - blink(3 << 24, PORTA, 1 << 3); -} - - - -/* Exception and interrupt handlers. */ - -void exception_handler(void) -{ - blink(3 << 12, PORTA, 1 << 3); -} - -void interrupt_handler(void) -{ - uint32_t ifs; - - /* Check for a OC1 interrupt condition. */ - - ifs = REG(OCIFS) & OC_INT_FLAGS(1, OCxIF); - - if (ifs) - { - vga_interrupt_handler(); - CLR_REG(OCIFS, ifs); - } -} - - - -/* Peripheral pin configuration. */ - -void config_oc(void) -{ - /* Map OC1 to RPA0. */ - - REG(RPA0R) = 0b0101; /* RPA0R<3:0> = 0101 (OC1) */ - - /* Map OC2 to RPA1. */ - - REG(RPA1R) = 0b0101; /* RPA1R<3:0> = 0101 (OC2) */ -} - -void config_uart(void) -{ - /* Map U1RX to RPB13. */ - - REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */ - - /* Map U1TX to RPB15. */ - - REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */ - - /* Set RPB13 to input. */ - - SET_REG(TRISB, 1 << 13); -} +../vga/main.c \ No newline at end of file diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga-timer/main.h --- a/examples/vga-timer/main.h Thu Oct 25 21:11:22 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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 . - */ - -#ifndef __MAIN_H__ -#define __MAIN_H__ - -#include "vga_display.h" - -/* Peripheral pin configuration. */ - -void config_oc(void); -void config_uart(void); - -#endif /* __MAIN_H__ */ diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga/Makefile --- a/examples/vga/Makefile Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga/Makefile Thu Oct 25 21:19:01 2018 +0200 @@ -30,4 +30,13 @@ SRC = $(START_SRC) main.c $(COMMON_SRC) $(DISPLAY_SRC) OBJ = $(START_OBJ) main.o $(COMMON_OBJ) $(DISPLAY_OBJ) +# Application-specific adjustments. + +# Setting: Default: Alternatives: +# LINE_CHANNELS 1 2 +# LINE_TIMER 2 3, 4, 5 +# TRANSFER_TIMER 0 2, 3, 4, 5 + +CFLAGS += -DLINE_CHANNELS=1 + include ../../mk/rules.mk diff -r ddc36d3c6fbb -r 45a99a68c2ed examples/vga/main.c --- a/examples/vga/main.c Thu Oct 25 21:11:22 2018 +0200 +++ b/examples/vga/main.c Thu Oct 25 21:19:01 2018 +0200 @@ -33,6 +33,22 @@ +/* Define timers if not indicated in the build configuration. */ + +#ifndef LINE_CHANNELS +#define LINE_CHANNELS 1 +#endif + +#ifndef LINE_TIMER +#define LINE_TIMER 2 +#endif + +#ifndef TRANSFER_TIMER +#define TRANSFER_TIMER 0 +#endif + + + /* Blink an attached LED with delays implemented using a loop. */ static void blink(uint32_t delay, uint32_t port, uint32_t pins) @@ -72,16 +88,17 @@ init_dma(); - /* Initialise VGA output structures with a single line channel and no - initiating channel. */ + /* Initialise VGA output with one or two line channels, configuring a line + timer and any transfer timer, with an initiating channel being introduced + if a transfer timer is specified. */ - init_vga(&display_config, 1, -1); + init_vga_with_timers(&display_config, LINE_CHANNELS, LINE_TIMER, TRANSFER_TIMER); - /* Configure VGA output transfer details along with a timer and output - compare units for horizontal and vertical sync. */ + /* Configure VGA output transfer to the output register, also configuring + output compare units for horizontal and vertical sync. */ - vga_configure_transfer(T2, PORTB); - vga_configure_sync(1, 2, 2); + vga_configure_transfer(PORTB); + vga_configure_sync(1, 2); uart_init(1, FPB, 115200); uart_on(1); diff -r ddc36d3c6fbb -r 45a99a68c2ed include/vga_display.h --- a/include/vga_display.h Thu Oct 25 21:11:22 2018 +0200 +++ b/include/vga_display.h Thu Oct 25 21:19:01 2018 +0200 @@ -35,11 +35,11 @@ /* DMA transfer properties. */ - int line_channels, initiating_int_num; + int line_timer, line_channels, transfer_int_num; /* Horizontal and vertical sync peripherals. */ - int timer, hsync_unit, vsync_unit; + int hsync_unit, vsync_unit; /* Current scanline. */ @@ -60,11 +60,16 @@ /* Initialisation. */ void init_vga(display_config_t *display_config, int line_channels, - int initiating_int_num); + int line_timer, int initiating_int_num); + +void init_vga_with_timers(display_config_t *display_config, int line_channels, + int line_timer, int transfer_timer); -void vga_configure_sync(int hsync_unit, int vsync_unit, int timer); +void vga_configure_sync(int hsync_unit, int vsync_unit); -void vga_configure_transfer(int transfer_int_num, uint32_t output); +void vga_configure_transfer(uint32_t output); + +/* Initialisation helpers. */ void vga_configure_line_channel(int channel, int int_num, enum dma_chain chain, uint32_t output); diff -r ddc36d3c6fbb -r 45a99a68c2ed lib/vga_display.c --- a/lib/vga_display.c Thu Oct 25 21:11:22 2018 +0200 +++ b/lib/vga_display.c Thu Oct 25 21:19:01 2018 +0200 @@ -37,30 +37,78 @@ /* Initialise the state machine. */ void init_vga(display_config_t *display_config, int line_channels, - int initiating_int_num) + int line_timer, int transfer_int_num) { /* Display parameters. */ vga_display.display_config = display_config; vga_display.line_channels = line_channels; - vga_display.initiating_int_num = initiating_int_num; /* Initial state. */ vga_display.state_handler = vbp_active; vga_display.line = 0; + + /* Configure a general display timer to start line data transfer and for the + horizontal sync. */ + + vga_display.line_timer = line_timer; + + /* Configure a separate transfer interrupt condition, if indicated. + Otherwise, transfers are initiated by the line timer. */ + + vga_display.transfer_int_num = transfer_int_num; +} + +/* Initialise a separate transfer timer if different from the general display + timer. */ + +void init_vga_with_timers(display_config_t *display_config, int line_channels, + int line_timer, int transfer_timer) +{ + /* Initialise the basic properties of the display. */ + + init_vga(display_config, line_channels, line_timer, + transfer_timer ? timer_interrupt_number(transfer_timer) : -1); + + /* Configure a line timer for horizontal sync and line data transfers. */ + + /* The timers have no prescaling (0). */ + + timer_init(line_timer, 0, display_config->hfreq_limit); + timer_on(line_timer); + + /* Configure a separate transfer timer, if indicated. */ + + if (!transfer_timer || (transfer_timer == line_timer)) + return; + + /* The timer wraps around immediately. */ + + timer_init(transfer_timer, 0, 1); + timer_on(transfer_timer); } /* Configure DMA channels for the transfer of pixel data. */ -void vga_configure_transfer(int transfer_int_num, uint32_t output) +void vga_configure_transfer(uint32_t output) { - int initiating_channel = vga_display.initiating_int_num >= 0; int dual_channel = vga_display.line_channels == 2; int channel = 0; + /* Determine whether an initiating channel is used. */ + + int initiating_channel = vga_display.transfer_int_num >= 0; + + /* Determine the different interrupt conditions, with pixel data employing + any specified transfer condition or the line condition otherwise. */ + + int line_int_num = timer_interrupt_number(vga_display.line_timer); + int transfer_int_num = initiating_channel ? + vga_display.transfer_int_num : line_int_num; + /* Where dual line channels are involved, put the first before any initiating channel, chaining it to such a channel. */ @@ -71,13 +119,12 @@ output); } - /* Introduce a special initiating channel if an interrupt has been - indicated. */ + /* Introduce a special initiating channel if a separate transfer interrupt + has been indicated. */ if (initiating_channel) { - vga_configure_zero_channel(channel++, vga_display.initiating_int_num, 1, - output); + vga_configure_zero_channel(channel++, line_int_num, 1, output); } /* A line channel is always configured, chaining it to any initiating @@ -146,30 +193,22 @@ ZERO_LENGTH); } -/* Configure a timer and output compare units for horizontal and vertical - sync. */ +/* Configure output compare units for horizontal and vertical sync. */ -void vga_configure_sync(int hsync_unit, int vsync_unit, int timer) +void vga_configure_sync(int hsync_unit, int vsync_unit) { /* Record the peripherals in use. */ vga_display.hsync_unit = hsync_unit; vga_display.vsync_unit = vsync_unit; - vga_display.timer = timer; - /* Configure a timer for the horizontal sync. The timer has no prescaling - (0). */ - - timer_init(timer, 0, vga_display.display_config->hfreq_limit); - timer_on(timer); - /* Horizontal sync. */ /* Configure output compare in dual compare (continuous output) mode using the timer as time base. The interrupt condition drives the first DMA channel and is handled to drive the display state machine. */ - oc_init(hsync_unit, 0b101, timer); + oc_init(hsync_unit, 0b101, vga_display.line_timer); oc_set_pulse(hsync_unit, vga_display.display_config->hsync_end); oc_set_pulse_end(hsync_unit, vga_display.display_config->hsync_start); oc_init_interrupt(hsync_unit, 7, 3); @@ -181,7 +220,7 @@ the timer as time base. The unit is enabled later. It is only really used to achieve precisely-timed level transitions in hardware. */ - oc_init(vsync_unit, 0b010, timer); + oc_init(vsync_unit, 0b010, vga_display.line_timer); oc_set_pulse(vsync_unit, 0); } @@ -296,7 +335,7 @@ /* Determine whether an initiating channel is used. */ - int initiating_channel = vga_display.initiating_int_num >= 0; + int initiating_channel = vga_display.transfer_int_num >= 0; int channel = 0; /* Update the source of a secondary line channel. */ @@ -330,9 +369,12 @@ void update_transfers(int enable) { - int initiating_channel = vga_display.initiating_int_num >= 0; + void (*fn)() = enable ? dma_on : dma_off; + + /* Determine whether an initiating channel is used. */ + + int initiating_channel = vga_display.transfer_int_num >= 0; int channel = 0; - void (*fn)() = enable ? dma_on : dma_off; /* Update line channels if no initiating channel is used. */ @@ -364,7 +406,7 @@ void vsync_low(void) { - oc_init(vga_display.vsync_unit, 0b010, vga_display.timer); + oc_init(vga_display.vsync_unit, 0b010, vga_display.line_timer); oc_on(vga_display.vsync_unit); } @@ -373,6 +415,6 @@ void vsync_high(void) { - oc_init(vga_display.vsync_unit, 0b001, vga_display.timer); + oc_init(vga_display.vsync_unit, 0b001, vga_display.line_timer); oc_on(vga_display.vsync_unit); }