From 71c9c7dd786aac13db8a390593317cd82b03a99b Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Thu, 28 Apr 2011 21:30:45 -0300 Subject: [PATCH] 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 --- ubb-vga/ubb-vga2.c | 83 ++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/ubb-vga/ubb-vga2.c b/ubb-vga/ubb-vga2.c index 08dd22a..6d72306 100644 --- a/ubb-vga/ubb-vga2.c +++ b/ubb-vga/ubb-vga2.c @@ -38,10 +38,6 @@ #include "ubb-vga.h" -#define XRES 640 -#define YRES 480 - - #define REG_BASE_PTR base static volatile void *base; @@ -190,13 +186,25 @@ static void until(uint16_t cycles) /* ----- Frame buffer output ----------------------------------------------- */ -static int line_words = XRES/8; -//static int line_cycles = US(36); /* nominally 31.77 us, but we're too slow */ -//static int line_cycles = US(32); /* nominally 31.77 us, but we're too slow */ -static int line_cycles = US(29.7); /* nominally 31.77 us, but we're too fast */ -/* - * Note: 29.6 is already too short. Tricky timing. - */ +static const struct mode { + const char *name; + int xres, yres; + int line_words; /* xres/8 */ + int clkdiv; /* pixel clock = 336 MHz/(clkdiv+1) */ + 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) { @@ -209,8 +217,7 @@ void setup(void) PDDATS = VSYNC | HSYNC; PDDATC = R | G | B | Y; -// *msccdr = 20; /* set the MSC clock to 336 MHz / 21 = 16 MHz */ - MSCCDR = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */ + MSCCDR = mode->clkdiv; /* set the MSC clock to 336 MHz / 12 = 28 MHz */ CLKGR &= ~(1 << 7); /* enable MSC clock */ MSC_CLKRT = 0; /* bus clock = MSC clock / 1 */ } @@ -236,6 +243,7 @@ static void line(const uint32_t *line) PDDATC = HSYNC; MSC_STRPCL = 2; /* start MMC clock output */ + MSC_RESTO = 0xffff; MSC_CMDAT = (1 << 10) | /* 4 bit bus */ @@ -245,7 +253,7 @@ static void line(const uint32_t *line) MSC_STRPCL = 4; /* START_OP */ - until(US(0.79+3.77-0.3)); + until(mode->hsync_end); /* * 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. */ -#if 0 /* quick load */ - MSC_TXFIFO = *p++; - MSC_TXFIFO = *p++; +#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++; #endif - while (p != line+line_words) { + while (p != line+mode->line_words) { uint8_t st; do { st = MSC_STAT; @@ -301,7 +312,7 @@ static void line(const uint32_t *line) } fail: - until(line_cycles); + until(mode->line_cycles); } @@ -312,7 +323,7 @@ static void hdelay(int cycles) PDDATC = HSYNC; until(US(3.77)); PDDATS = HSYNC; - until(line_cycles); + until(mode->line_cycles); } } @@ -338,9 +349,9 @@ static void frame(const uint32_t *f) PDDATC = HSYNC; until(US(3.77)); 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); /* 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) { - uint32_t f[YRES*(line_words+1)]; + uint32_t *f; int i; + f = malloc((mode->yres*mode->line_words)*4); + if (!f) { + perror("malloc"); + exit(1); + } memset(f, 0, sizeof(f)); ccube_init(); - gen(f, XRES, YRES); + gen(f, mode->xres, mode->yres); 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) { 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" " file PPM file\n\n" -" -t generate a test image\n" - , name); +" -m mode select the display mode, default \"%s\"\n" +" -t generate a test image\n" + , name, mode_db[0].name); exit(1); } @@ -387,8 +404,18 @@ int main(int argc, char *const *argv) int frames; int c; - while ((c = getopt(argc, argv, "t")) != EOF) + while ((c = getopt(argc, argv, "m:t")) != EOF) 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': gen = tstimg; break;