mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 18:06:16 +02:00
ubb-vga2: new option -m to select the display mode (resolution, timing)
- ubb-vga2.c (XREs, YRES, res, res_db, setup, line, hdelay, frame, session): replaced hard-coded display characteristics with a mode database - ubb-vga2.c (usage, main): new option -m to select the display mode - ubb-vga2.c (session): allocate frame buffer dynamically - ubb-vga2.c (session): since we no longer prefetch, we don't need to allocate space beyond the end of the frame buffer - ubb-vga2.c (line): resurrected "quick load" and extended it to fill the FIFO completely
This commit is contained in:
parent
957491d209
commit
71c9c7dd78
@ -38,10 +38,6 @@
|
|||||||
#include "ubb-vga.h"
|
#include "ubb-vga.h"
|
||||||
|
|
||||||
|
|
||||||
#define XRES 640
|
|
||||||
#define YRES 480
|
|
||||||
|
|
||||||
|
|
||||||
#define REG_BASE_PTR base
|
#define REG_BASE_PTR base
|
||||||
|
|
||||||
static volatile void *base;
|
static volatile void *base;
|
||||||
@ -190,13 +186,25 @@ static void until(uint16_t cycles)
|
|||||||
/* ----- Frame buffer output ----------------------------------------------- */
|
/* ----- Frame buffer output ----------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
static int line_words = XRES/8;
|
static const struct mode {
|
||||||
//static int line_cycles = US(36); /* nominally 31.77 us, but we're too slow */
|
const char *name;
|
||||||
//static int line_cycles = US(32); /* nominally 31.77 us, but we're too slow */
|
int xres, yres;
|
||||||
static int line_cycles = US(29.7); /* nominally 31.77 us, but we're too fast */
|
int line_words; /* xres/8 */
|
||||||
/*
|
int clkdiv; /* pixel clock = 336 MHz/(clkdiv+1) */
|
||||||
* Note: 29.6 is already too short. Tricky timing.
|
int line_cycles; /* 31.77 us for official VGA */
|
||||||
*/
|
int hsync_end; /* 0.79+3.77 us for official VGA */
|
||||||
|
} mode_db[] = {
|
||||||
|
{ "640x480", 640, 480, 640/8, 11, US(29.7), US(0.79+3.77-0.3) },
|
||||||
|
{ "800x600", 800, 600, 800/8, 8, US(28.7), US(2.0+3.3+0.3) },
|
||||||
|
/* the next one may work after adjusting the timing in "frame" */
|
||||||
|
{ "800x600", 800, 600, 800/8, 8, US(28.2), US(2.0+3.3+0.3-0.3) },
|
||||||
|
/* the 1024x768 below is not great but has good parameter tolerance */
|
||||||
|
{ "1024x768", 1024, 768, 1024/8, 8, US(36.0), US(2.0+3.3) },
|
||||||
|
/* illustrate underruns */
|
||||||
|
{ "1024x768ur", 1024, 768, 1024/8, 7, US(33.5), US(0.4+2.1+0.5) },
|
||||||
|
{ NULL }
|
||||||
|
}, *mode = mode_db;
|
||||||
|
|
||||||
|
|
||||||
void setup(void)
|
void setup(void)
|
||||||
{
|
{
|
||||||
@ -209,8 +217,7 @@ void setup(void)
|
|||||||
PDDATS = VSYNC | HSYNC;
|
PDDATS = VSYNC | HSYNC;
|
||||||
PDDATC = R | G | B | Y;
|
PDDATC = R | G | B | Y;
|
||||||
|
|
||||||
// *msccdr = 20; /* set the MSC clock to 336 MHz / 21 = 16 MHz */
|
MSCCDR = mode->clkdiv; /* set the MSC clock to 336 MHz / 12 = 28 MHz */
|
||||||
MSCCDR = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */
|
|
||||||
CLKGR &= ~(1 << 7); /* enable MSC clock */
|
CLKGR &= ~(1 << 7); /* enable MSC clock */
|
||||||
MSC_CLKRT = 0; /* bus clock = MSC clock / 1 */
|
MSC_CLKRT = 0; /* bus clock = MSC clock / 1 */
|
||||||
}
|
}
|
||||||
@ -236,6 +243,7 @@ static void line(const uint32_t *line)
|
|||||||
|
|
||||||
PDDATC = HSYNC;
|
PDDATC = HSYNC;
|
||||||
MSC_STRPCL = 2; /* start MMC clock output */
|
MSC_STRPCL = 2; /* start MMC clock output */
|
||||||
|
MSC_RESTO = 0xffff;
|
||||||
|
|
||||||
MSC_CMDAT =
|
MSC_CMDAT =
|
||||||
(1 << 10) | /* 4 bit bus */
|
(1 << 10) | /* 4 bit bus */
|
||||||
@ -245,7 +253,7 @@ static void line(const uint32_t *line)
|
|||||||
|
|
||||||
MSC_STRPCL = 4; /* START_OP */
|
MSC_STRPCL = 4; /* START_OP */
|
||||||
|
|
||||||
until(US(0.79+3.77-0.3));
|
until(mode->hsync_end);
|
||||||
/*
|
/*
|
||||||
* Adjustment value tests with the XEN-1510:
|
* Adjustment value tests with the XEN-1510:
|
||||||
*
|
*
|
||||||
@ -283,11 +291,14 @@ static void line(const uint32_t *line)
|
|||||||
* of the delay to shovel bits into the MSC's FIFO.
|
* of the delay to shovel bits into the MSC's FIFO.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0 /* quick load */
|
#if 1 /* quick load */
|
||||||
MSC_TXFIFO = *p++;
|
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
||||||
MSC_TXFIFO = *p++;
|
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
||||||
|
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
||||||
|
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
||||||
|
MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++;
|
||||||
#endif
|
#endif
|
||||||
while (p != line+line_words) {
|
while (p != line+mode->line_words) {
|
||||||
uint8_t st;
|
uint8_t st;
|
||||||
do {
|
do {
|
||||||
st = MSC_STAT;
|
st = MSC_STAT;
|
||||||
@ -301,7 +312,7 @@ static void line(const uint32_t *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
until(line_cycles);
|
until(mode->line_cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -312,7 +323,7 @@ static void hdelay(int cycles)
|
|||||||
PDDATC = HSYNC;
|
PDDATC = HSYNC;
|
||||||
until(US(3.77));
|
until(US(3.77));
|
||||||
PDDATS = HSYNC;
|
PDDATS = HSYNC;
|
||||||
until(line_cycles);
|
until(mode->line_cycles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,9 +349,9 @@ static void frame(const uint32_t *f)
|
|||||||
PDDATC = HSYNC;
|
PDDATC = HSYNC;
|
||||||
until(US(3.77));
|
until(US(3.77));
|
||||||
PDDATS = HSYNC;
|
PDDATS = HSYNC;
|
||||||
until(line_cycles-US(0.79));
|
until(mode->line_cycles-US(0.79));
|
||||||
|
|
||||||
for (p = f; p != f+YRES*line_words; p += line_words)
|
for (p = f; p != f+mode->yres*mode->line_words; p += mode->line_words)
|
||||||
line(p);
|
line(p);
|
||||||
|
|
||||||
/* Back porch */
|
/* Back porch */
|
||||||
@ -353,12 +364,17 @@ static void frame(const uint32_t *f)
|
|||||||
|
|
||||||
static void session(void (*gen)(void *fb, int xres, int yres), int frames)
|
static void session(void (*gen)(void *fb, int xres, int yres), int frames)
|
||||||
{
|
{
|
||||||
uint32_t f[YRES*(line_words+1)];
|
uint32_t *f;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
f = malloc((mode->yres*mode->line_words)*4);
|
||||||
|
if (!f) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
memset(f, 0, sizeof(f));
|
memset(f, 0, sizeof(f));
|
||||||
ccube_init();
|
ccube_init();
|
||||||
gen(f, XRES, YRES);
|
gen(f, mode->xres, mode->yres);
|
||||||
|
|
||||||
disable_interrupts();
|
disable_interrupts();
|
||||||
|
|
||||||
@ -372,11 +388,12 @@ static void session(void (*gen)(void *fb, int xres, int yres), int frames)
|
|||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"usage: %s [-t] frames [file]\n\n"
|
"usage: %s [-t] [-r resolution] frames [file]\n\n"
|
||||||
" frames number of frames to display\n"
|
" frames number of frames to display\n"
|
||||||
" file PPM file\n\n"
|
" file PPM file\n\n"
|
||||||
|
" -m mode select the display mode, default \"%s\"\n"
|
||||||
" -t generate a test image\n"
|
" -t generate a test image\n"
|
||||||
, name);
|
, name, mode_db[0].name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,8 +404,18 @@ int main(int argc, char *const *argv)
|
|||||||
int frames;
|
int frames;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "t")) != EOF)
|
while ((c = getopt(argc, argv, "m:t")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'm':
|
||||||
|
for (mode = mode_db; mode->name; mode++)
|
||||||
|
if (!strcmp(mode->name, optarg))
|
||||||
|
break;
|
||||||
|
if (!mode) {
|
||||||
|
fprintf(stderr, "no resolution \"%s\"\n",
|
||||||
|
optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
gen = tstimg;
|
gen = tstimg;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user