1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/examples/vga-timer/Makefile Mon Oct 22 19:12:33 2018 +0200
1.3 @@ -0,0 +1,33 @@
1.4 +# Makefile - Build the PIC32 deployment payload
1.5 +#
1.6 +# Copyright (C) 2015, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
1.7 +# Copyright (C) Xiangfu Liu <xiangfu@sharism.cc>
1.8 +#
1.9 +# This program is free software: you can redistribute it and/or modify
1.10 +# it under the terms of the GNU General Public License as published by
1.11 +# the Free Software Foundation, either version 3 of the License, or
1.12 +# (at your option) any later version.
1.13 +#
1.14 +# This program is distributed in the hope that it will be useful,
1.15 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 +# GNU General Public License for more details.
1.18 +#
1.19 +# You should have received a copy of the GNU General Public License
1.20 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
1.21 +
1.22 +include ../../mk/common.mk
1.23 +
1.24 +TARGET = vga.elf
1.25 +DUMP = $(TARGET:.elf=.dump)
1.26 +MAP = $(TARGET:.elf=.map)
1.27 +
1.28 +HEX = $(TARGET:.elf=.hex)
1.29 +SREC = $(TARGET:.elf=.srec)
1.30 +
1.31 +# Ordering of objects is important and cannot be left to replacement rules.
1.32 +
1.33 +SRC = $(START_SRC) main.c $(COMMON_SRC)
1.34 +OBJ = $(START_OBJ) main.o $(COMMON_OBJ)
1.35 +
1.36 +include ../../mk/rules.mk
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/examples/vga-timer/README.txt Mon Oct 22 19:12:33 2018 +0200
2.3 @@ -0,0 +1,135 @@
2.4 +Introduction
2.5 +------------
2.6 +
2.7 +This example demonstrates the generation of an analogue VGA signal from a
2.8 +PIC32 microcontroller using general output pins. Unlike the vga and vga-pmp
2.9 +examples, it employs a regular interrupt condition to schedule single-byte
2.10 +(single-pixel) DMA transfers instead of a single whole-line transfer.
2.11 +
2.12 +The principal advantage of this method over the whole-line transfer method is
2.13 +its production of pixels with consistent widths. The principal disadvantage is
2.14 +the significant loss of horizontal resolution due to the latencies involved in
2.15 +propagating interrupt conditions to the DMA controller and thereby initiating
2.16 +each transfer.
2.17 +
2.18 +Employing a peripheral clock that has half the frequency of the system clock
2.19 +should ensure the stability of the picture, since the lower frequency may make
2.20 +transfers easier to schedule. The peripheral clock should provide a more
2.21 +forgiving deadline for each transfer, permitting late transfers to complete on
2.22 +time.
2.23 +
2.24 +Meanwhile, matching the system and peripheral clock frequencies appears to
2.25 +leave the scheduling of transfers open to uncertainty, with transfers being
2.26 +more readily delayed by other activity in the system, and with instability of
2.27 +the picture being the result.
2.28 +
2.29 +In contrast to the vga and vga-pmp examples, a special DMA channel is employed
2.30 +to initiate the pixel transfer process without actually transferring any pixel
2.31 +data itself. The channel arrangement is as follows:
2.32 +
2.33 + Transfer Initiator DMA Channel Transfer Activity
2.34 + ------------------ ----------- -----------------
2.35 + Timer2 DMA0 zerodata -> PORTB
2.36 + Timer3 DMA1 linedata -> PORTB
2.37 + DMA1 (completion) DMA2 zerodata -> PORTB
2.38 +
2.39 +The real purpose of this channel (DMA0) is to capture the Timer2 interrupt
2.40 +condition and to enable the following channel (DMA1) through channel chaining.
2.41 +Having been enabled, DMA1 is then able to conduct transfers at a tempo
2.42 +dictated by Timer3. Finally, DMA2 acts as the "reset" or "zero" channel to
2.43 +ensure that the pixel level is set to black at the end of each display line.
2.44 +
2.45 +In principle, other initiating conditions can be used instead of Timer3, which
2.46 +is configured to produce such conditions as frequently as possible:
2.47 +
2.48 + * A persistent interrupt condition can be employed instead. For example,
2.49 + configuring UART2 and setting the UART2 transfer interrupt, employing this
2.50 + interrupt condition for DMA1, produces the same effect.
2.51 +
2.52 + * An external interrupt such as INT2 can be configured, and the peripheral
2.53 + clock can be routed through the CLKO pin and back into the microcontroller
2.54 + via an appropriate pin. With INT2 being employed as the interrupt
2.55 + condition for DMA1, the same effect is produced.
2.56 +
2.57 +Hardware Details
2.58 +================
2.59 +
2.60 +The pin usage of this solution is documented below.
2.61 +
2.62 +PIC32MX270F256B-50I/SP Pin Assignments
2.63 +--------------------------------------
2.64 +
2.65 +MCLR# 1 \/ 28
2.66 +HSYNC/OC1/RA0 2 27
2.67 +VSYNC/OC2/RA1 3 26 RB15/U1TX
2.68 + D0/RB0 4 25 RB14
2.69 + D1/RB1 5 24 RB13/U1RX
2.70 + D2/RB2 6 23
2.71 + D3/RB3 7 22 RB11/PGEC2
2.72 + 8 21 RB10/PGEC3
2.73 + RA2 9 20
2.74 + RA3 10 19
2.75 + D4/RB4 11 18 RB9
2.76 + 12 17 RB8
2.77 + 13 16 RB7/D7
2.78 + D5/RB5 14 15
2.79 +
2.80 +Note that RB6 is not available on pin 15 on this device (it is needed for VBUS
2.81 +unlike the MX170 variant).
2.82 +
2.83 +UART Connections
2.84 +----------------
2.85 +
2.86 +UART1 is exposed by the RB13 and RB15 pins.
2.87 +
2.88 +Data Signal Routing
2.89 +-------------------
2.90 +
2.91 +For one bit of intensity, two bits per colour channel:
2.92 +
2.93 +D7 -> 2200R -> I
2.94 +
2.95 +I -> diode -> R
2.96 +I -> diode -> G
2.97 +I -> diode -> B
2.98 +
2.99 +D6 (not connected)
2.100 +
2.101 +D5 -> 470R -> R
2.102 +D4 -> 1000R -> R
2.103 +D3 -> 470R -> G
2.104 +D2 -> 1000R -> G
2.105 +D1 -> 470R -> B
2.106 +D0 -> 1000R -> B
2.107 +
2.108 +HSYNC -> HS
2.109 +VSYNC -> VS
2.110 +
2.111 +Output Socket Pinout
2.112 +--------------------
2.113 +
2.114 + 5 (GND) 4 (NC) 3 (B) 2 (G) 1 (R)
2.115 +
2.116 + 10 (GND) 9 (NC) 8 (GND) 7 (GND) 6 (GND)
2.117 +
2.118 + 15 (NC) 14 (VS) 13 (HS) 12 (NC) 11 (NC)
2.119 +
2.120 +Output Cable Pinout
2.121 +-------------------
2.122 +
2.123 + 1 (R) 2 (G) 3 (B) 4 (NC) 5 (GND)
2.124 +
2.125 + 6 (GND) 7 (GND) 8 (GND) 9 (NC) 10 (GND)
2.126 +
2.127 + 11 (NC) 12 (NC) 13 (HS) 14 (VS) 15 (NC)
2.128 +
2.129 +References
2.130 +----------
2.131 +
2.132 +https://en.wikipedia.org/wiki/VGA_connector
2.133 +
2.134 +http://papilio.cc/index.php?n=Papilio.VGAWing
2.135 +
2.136 +http://lucidscience.com/pro-vga%20video%20generator-2.aspx
2.137 +
2.138 +https://sites.google.com/site/h2obsession/CBM/C128/rgbi-to-vga
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/examples/vga-timer/devconfig.h Mon Oct 22 19:12:33 2018 +0200
3.3 @@ -0,0 +1,63 @@
3.4 +/*
3.5 + * Device configuration.
3.6 + *
3.7 + * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
3.8 + *
3.9 + * This program is free software: you can redistribute it and/or modify
3.10 + * it under the terms of the GNU General Public License as published by
3.11 + * the Free Software Foundation, either version 3 of the License, or
3.12 + * (at your option) any later version.
3.13 + *
3.14 + * This program is distributed in the hope that it will be useful,
3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 + * GNU General Public License for more details.
3.18 + *
3.19 + * You should have received a copy of the GNU General Public License
3.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
3.21 + */
3.22 +
3.23 +#ifndef __CONFIG_H__
3.24 +#define __CONFIG_H__
3.25 +
3.26 +#include "pic32.h"
3.27 +
3.28 +/*
3.29 +Set the oscillator to be the FRC oscillator with PLL, with peripheral clock
3.30 +divided by 2 (FPBDIV), and FRCDIV+PLL selected (FNOSC).
3.31 +
3.32 +The watchdog timer (FWDTEN) is also disabled.
3.33 +
3.34 +The secondary oscillator pin (FSOSCEN) is disabled to avoid pin conflicts with
3.35 +RPB4.
3.36 +*/
3.37 +
3.38 +#define DEVCFG1_CONFIG (DEVCFG1_FWDTEN_OFF | DEVCFG1_FPBDIV_2 | \
3.39 + DEVCFG1_OSCIOFNC_OFF | DEVCFG1_FSOSCEN_OFF | \
3.40 + DEVCFG1_FNOSC_FRCDIV_PLL)
3.41 +
3.42 +/*
3.43 +Set the FRC oscillator PLL function with an input division of 2, an output
3.44 +division of 2, a multiplication of 24, yielding a multiplication of 6.
3.45 +
3.46 +The FRC is apparently at 8MHz but enforces input division of 2 to produce a
3.47 +frequency in the acceptable range from 4MHz to 5MHz for the PLL:
3.48 +
3.49 +8MHz / 2 = 4MHz
3.50 +
3.51 +Multiplication and output division should produce a system clock of 48MHz:
3.52 +
3.53 +4MHz * 24 / 2 = 48MHz
3.54 +*/
3.55 +
3.56 +#define DEVCFG2_CONFIG (DEVCFG2_FPLLODIV_2 | DEVCFG2_FPLLMUL_24 | \
3.57 + DEVCFG2_FPLLIDIV_2)
3.58 +
3.59 +/*
3.60 +The peripheral clock frequency (FPB) will be 24MHz given the above DEVCFG1 and
3.61 +DEVCFG2 settings.
3.62 +*/
3.63 +
3.64 +#define FPB 24000000
3.65 +
3.66 +#endif /* __CONFIG_H__ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/examples/vga-timer/main.c Mon Oct 22 19:12:33 2018 +0200
4.3 @@ -0,0 +1,319 @@
4.4 +/*
4.5 + * Generate a VGA signal using a PIC32 microcontroller.
4.6 + *
4.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software: you can redistribute it and/or modify
4.10 + * it under the terms of the GNU General Public License as published by
4.11 + * the Free Software Foundation, either version 3 of the License, or
4.12 + * (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
4.21 + */
4.22 +
4.23 +
4.24 +#include "pic32_c.h"
4.25 +#include "init.h"
4.26 +#include "debug.h"
4.27 +#include "main.h"
4.28 +#include "vga.h"
4.29 +
4.30 +
4.31 +
4.32 +/* Display state. */
4.33 +
4.34 +static void (*state_handler)(void);
4.35 +static uint32_t line;
4.36 +
4.37 +/* Pixel data. */
4.38 +
4.39 +static uint8_t linedata[LINE_LENGTH];
4.40 +static const uint8_t zerodata[ZERO_LENGTH] = {0};
4.41 +
4.42 +
4.43 +
4.44 +static void test_linedata(void)
4.45 +{
4.46 + int i;
4.47 +
4.48 + for (i = 0; i < LINE_LENGTH; i++)
4.49 + linedata[i] = (i % 2) ? 0xff : 0x00;
4.50 +}
4.51 +
4.52 +/* Blink an attached LED with delays implemented using a loop. */
4.53 +
4.54 +static void blink(uint32_t delay, uint32_t port, uint32_t pins)
4.55 +{
4.56 + uint32_t counter;
4.57 +
4.58 + /* Clear outputs (LED). */
4.59 +
4.60 + CLR_REG(port, pins);
4.61 +
4.62 + while (1)
4.63 + {
4.64 + counter = delay;
4.65 +
4.66 + while (counter--) __asm__(""); /* retain loop */
4.67 +
4.68 + /* Invert outputs (LED). */
4.69 +
4.70 + INV_REG(port, pins);
4.71 + }
4.72 +}
4.73 +
4.74 +
4.75 +
4.76 +/* Main program. */
4.77 +
4.78 +void main(void)
4.79 +{
4.80 + line = 0;
4.81 + state_handler = vbp_active;
4.82 + test_linedata();
4.83 +
4.84 + init_memory();
4.85 + init_pins();
4.86 + init_outputs();
4.87 +
4.88 + unlock_config();
4.89 + config_oc();
4.90 + config_uart();
4.91 + lock_config();
4.92 +
4.93 + init_dma();
4.94 +
4.95 + /* Peripheral relationships:
4.96 +
4.97 + Timer2 -> OC1
4.98 + -> OC2 (vertical sync region)
4.99 + -> DMA0: zerodata -> PORTB (visible region)
4.100 + |
4.101 + Timer3 -> DMA1: linedata -> PORTB
4.102 + |
4.103 + DMA1 -> DMA2: zerodata -> PORTB
4.104 + */
4.105 +
4.106 + /* Initiate DMA on the Timer2 interrupt condition, transferring line data to
4.107 + the first byte of PORTB. Do not enable the channel for initiation until
4.108 + the visible region is about to start. */
4.109 +
4.110 + dma_init(0, 3);
4.111 + dma_set_auto_enable(0, 1);
4.112 + dma_set_interrupt(0, T2, 1);
4.113 + dma_set_transfer(0, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
4.114 + HW_PHYSICAL(PORTB), 1,
4.115 + ZERO_LENGTH);
4.116 +
4.117 + /* Enable DMA on the preceding channel's completion, with the Timer3
4.118 + interrupt condition initiating transfers. */
4.119 +
4.120 + dma_init(1, 3);
4.121 + dma_set_chaining(1, dma_chain_previous);
4.122 + dma_set_interrupt(1, T3, 1);
4.123 + dma_set_transfer(1, PHYSICAL((uint32_t) linedata), LINE_LENGTH,
4.124 + HW_PHYSICAL(PORTB), 1,
4.125 + 1);
4.126 + dma_init_interrupt(1, 0b00001000, 1, 3);
4.127 +
4.128 + /* Enable DMA on the preceding channel's completion, with this also
4.129 + initiating transfers. */
4.130 +
4.131 + dma_init(2, 3);
4.132 + dma_set_chaining(2, dma_chain_previous);
4.133 + dma_set_interrupt(2, DMA1, 1);
4.134 + dma_set_transfer(2, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
4.135 + HW_PHYSICAL(PORTB), 1,
4.136 + ZERO_LENGTH);
4.137 + dma_set_receive_events(2, 1);
4.138 +
4.139 + /* Configure a timer for the horizontal sync. The timer has no prescaling
4.140 + (0). */
4.141 +
4.142 + timer_init(2, 0, HFREQ_LIMIT);
4.143 + timer_on(2);
4.144 +
4.145 + /* Configure a timer for line data transfers. */
4.146 +
4.147 + timer_init(3, 0, 1);
4.148 + timer_on(3);
4.149 +
4.150 + /* Horizontal sync. */
4.151 +
4.152 + /* Configure output compare in dual compare (continuous output) mode using
4.153 + Timer2 as time base. The interrupt condition drives the first DMA channel
4.154 + and is handled to drive the display state machine. */
4.155 +
4.156 + oc_init(1, 0b101, 2);
4.157 + oc_set_pulse(1, HSYNC_END);
4.158 + oc_set_pulse_end(1, HSYNC_START);
4.159 + oc_init_interrupt(1, 7, 3);
4.160 + oc_on(1);
4.161 +
4.162 + /* Vertical sync. */
4.163 +
4.164 + /* Configure output compare in single compare (output driven low) mode using
4.165 + Timer2 as time base. The unit is enabled later. It is only really used to
4.166 + achieve precisely-timed level transitions in hardware. */
4.167 +
4.168 + oc_init(2, 0b010, 2);
4.169 + oc_set_pulse(2, 0);
4.170 +
4.171 + uart_init(1, 115200);
4.172 + uart_on(1);
4.173 +
4.174 + interrupts_on();
4.175 +
4.176 + blink(3 << 24, PORTA, 1 << 3);
4.177 +}
4.178 +
4.179 +
4.180 +
4.181 +/* Exception and interrupt handlers. */
4.182 +
4.183 +void exception_handler(void)
4.184 +{
4.185 + blink(3 << 12, PORTA, 1 << 3);
4.186 +}
4.187 +
4.188 +void interrupt_handler(void)
4.189 +{
4.190 + uint32_t ifs;
4.191 +
4.192 + /* Check for a OC1 interrupt condition. */
4.193 +
4.194 + ifs = REG(OCIFS) & OC_INT_FLAGS(1, OCxIF);
4.195 +
4.196 + if (ifs)
4.197 + {
4.198 + line += 1;
4.199 + state_handler();
4.200 + CLR_REG(OCIFS, ifs);
4.201 + }
4.202 +}
4.203 +
4.204 +
4.205 +
4.206 +/* Vertical back porch region. */
4.207 +
4.208 +void vbp_active(void)
4.209 +{
4.210 + if (line < VISIBLE_START)
4.211 + return;
4.212 +
4.213 + /* Enter the visible region. */
4.214 +
4.215 + state_handler = visible_active;
4.216 +
4.217 + /* NOTE: Set the line address. */
4.218 +
4.219 + /* Enable the channel for the next line. */
4.220 +
4.221 + dma_on(0);
4.222 +}
4.223 +
4.224 +/* Visible region. */
4.225 +
4.226 +void visible_active(void)
4.227 +{
4.228 + uint32_t ifs;
4.229 +
4.230 + /* Remove any DMA interrupt condition (CHBCIF). */
4.231 +
4.232 + ifs = REG(DMAIFS) & DMA_INT_FLAGS(1, DCHxIF);
4.233 +
4.234 + if (ifs)
4.235 + {
4.236 + CLR_REG(DMA_REG(1, DCHxINT), 0b11111111);
4.237 + CLR_REG(DMAIFS, ifs);
4.238 + INV_REG(PORTA, 1 << 2);
4.239 + }
4.240 +
4.241 + if (line < VFP_START)
4.242 + {
4.243 + /* NOTE: Update the line address and handle wraparound. */
4.244 +
4.245 + return;
4.246 + }
4.247 +
4.248 + /* End the visible region. */
4.249 +
4.250 + state_handler = vfp_active;
4.251 +
4.252 + /* Disable the channel for the next line. */
4.253 +
4.254 + dma_off(0);
4.255 +}
4.256 +
4.257 +/* Vertical front porch region. */
4.258 +
4.259 +void vfp_active(void)
4.260 +{
4.261 + if (line < VSYNC_START)
4.262 + return;
4.263 +
4.264 + /* Enter the vertical sync region. */
4.265 +
4.266 + state_handler = vsync_active;
4.267 +
4.268 + /* Bring vsync low (single compare, output driven low) when the next line
4.269 + starts. */
4.270 +
4.271 + oc_init(2, 0b010, 2);
4.272 + oc_on(2);
4.273 +}
4.274 +
4.275 +/* Vertical sync region. */
4.276 +
4.277 +void vsync_active(void)
4.278 +{
4.279 + if (line < VSYNC_END)
4.280 + return;
4.281 +
4.282 + /* Start again at the top of the display. */
4.283 +
4.284 + line = 0;
4.285 + state_handler = vbp_active;
4.286 +
4.287 + /* Bring vsync high (single compare, output driven high) when the next line
4.288 + starts. */
4.289 +
4.290 + oc_init(2, 0b001, 2);
4.291 + oc_on(2);
4.292 +}
4.293 +
4.294 +
4.295 +
4.296 +/* Peripheral pin configuration. */
4.297 +
4.298 +void config_oc(void)
4.299 +{
4.300 + /* Map OC1 to RPA0. */
4.301 +
4.302 + REG(RPA0R) = 0b0101; /* RPA0R<3:0> = 0101 (OC1) */
4.303 +
4.304 + /* Map OC2 to RPA1. */
4.305 +
4.306 + REG(RPA1R) = 0b0101; /* RPA1R<3:0> = 0101 (OC2) */
4.307 +}
4.308 +
4.309 +void config_uart(void)
4.310 +{
4.311 + /* Map U1RX to RPB13. */
4.312 +
4.313 + REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */
4.314 +
4.315 + /* Map U1TX to RPB15. */
4.316 +
4.317 + REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */
4.318 +
4.319 + /* Set RPB13 to input. */
4.320 +
4.321 + SET_REG(TRISB, 1 << 13);
4.322 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/examples/vga-timer/main.h Mon Oct 22 19:12:33 2018 +0200
5.3 @@ -0,0 +1,35 @@
5.4 +/*
5.5 + * Generate a VGA signal using a PIC32 microcontroller.
5.6 + *
5.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software: you can redistribute it and/or modify
5.10 + * it under the terms of the GNU General Public License as published by
5.11 + * the Free Software Foundation, either version 3 of the License, or
5.12 + * (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
5.21 + */
5.22 +
5.23 +#ifndef __MAIN_H__
5.24 +#define __MAIN_H__
5.25 +
5.26 +/* Peripheral pin configuration. */
5.27 +
5.28 +void config_oc(void);
5.29 +void config_uart(void);
5.30 +
5.31 +/* Display state handlers. */
5.32 +
5.33 +void vbp_active(void);
5.34 +void visible_active(void);
5.35 +void vfp_active(void);
5.36 +void vsync_active(void);
5.37 +
5.38 +#endif /* __MAIN_H__ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/examples/vga-timer/vga.h Mon Oct 22 19:12:33 2018 +0200
6.3 @@ -0,0 +1,55 @@
6.4 +/*
6.5 + * Generate a VGA signal using a PIC32 microcontroller.
6.6 + *
6.7 + * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk>
6.8 + *
6.9 + * This program is free software: you can redistribute it and/or modify
6.10 + * it under the terms of the GNU General Public License as published by
6.11 + * the Free Software Foundation, either version 3 of the License, or
6.12 + * (at your option) any later version.
6.13 + *
6.14 + * This program is distributed in the hope that it will be useful,
6.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.17 + * GNU General Public License for more details.
6.18 + *
6.19 + * You should have received a copy of the GNU General Public License
6.20 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
6.21 + */
6.22 +
6.23 +#ifndef __VGA_H__
6.24 +#define __VGA_H__
6.25 +
6.26 +#define LINE_LENGTH 80 /* pixels */
6.27 +#define LINE_COUNT 256 /* distinct display lines */
6.28 +
6.29 +#define ZERO_LENGTH 1 /* pixels */
6.30 +
6.31 +/* 24MHz cycle measurements. */
6.32 +
6.33 +#define HFREQ_LIMIT 643
6.34 +#define HSYNC_START 523
6.35 +#define HSYNC_LIMIT 40
6.36 +#define HSYNC_END (HSYNC_START + HSYNC_LIMIT)
6.37 +
6.38 +/* Horizontal lines, back porch end. */
6.39 +
6.40 +#define VISIBLE_START 70
6.41 +#define VFP_START (VISIBLE_START + 2 * LINE_COUNT)
6.42 +
6.43 +/* Horizontal lines, front porch end. */
6.44 +
6.45 +#define VSYNC_START 620
6.46 +
6.47 +/* Horizontal lines, back porch start. */
6.48 +
6.49 +#define VSYNC_END 622
6.50 +
6.51 +#define SCREEN_BASE 256
6.52 +#define SCREEN_SIZE (40 * 1024)
6.53 +#define SCREEN_LIMIT (SCREEN_BASE + SCREEN_SIZE)
6.54 +
6.55 +#define SCREEN_BASE_KSEG0 (KSEG0_BASE + SCREEN_BASE)
6.56 +#define SCREEN_LIMIT_KSEG0 (KSEG0_BASE + SCREEN_LIMIT)
6.57 +
6.58 +#endif /* __VGA_H__ */