Date: | 2011-04-29 02:30:45 (12 years 10 months ago) |
---|---|
Author: | Werner Almesberger |
Commit: | 71c9c7dd786aac13db8a390593317cd82b03a99b |
Message: | 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 |
Files: |
ubb-vga/ubb-vga2.c (12 diffs) |
Change Details
ubb-vga/ubb-vga2.c | ||
---|---|---|
38 | 38 | #include "ubb-vga.h" |
39 | 39 | |
40 | 40 | |
41 | #define XRES 640 | |
42 | #define YRES 480 | |
43 | ||
44 | ||
45 | 41 | #define REG_BASE_PTR base |
46 | 42 | |
47 | 43 | static volatile void *base; |
... | ... | |
190 | 186 | /* ----- Frame buffer output ----------------------------------------------- */ |
191 | 187 | |
192 | 188 | |
193 | static int line_words = XRES/8; | |
194 | //static int line_cycles = US(36); /* nominally 31.77 us, but we're too slow */ | |
195 | //static int line_cycles = US(32); /* nominally 31.77 us, but we're too slow */ | |
196 | static int line_cycles = US(29.7); /* nominally 31.77 us, but we're too fast */ | |
197 | /* | |
198 | * Note: 29.6 is already too short. Tricky timing. | |
199 | */ | |
189 | static const struct mode { | |
190 | const char *name; | |
191 | int xres, yres; | |
192 | int line_words; /* xres/8 */ | |
193 | int clkdiv; /* pixel clock = 336 MHz/(clkdiv+1) */ | |
194 | int line_cycles; /* 31.77 us for official VGA */ | |
195 | int hsync_end; /* 0.79+3.77 us for official VGA */ | |
196 | } mode_db[] = { | |
197 | { "640x480", 640, 480, 640/8, 11, US(29.7), US(0.79+3.77-0.3) }, | |
198 | { "800x600", 800, 600, 800/8, 8, US(28.7), US(2.0+3.3+0.3) }, | |
199 | /* the next one may work after adjusting the timing in "frame" */ | |
200 | { "800x600", 800, 600, 800/8, 8, US(28.2), US(2.0+3.3+0.3-0.3) }, | |
201 | /* the 1024x768 below is not great but has good parameter tolerance */ | |
202 | { "1024x768", 1024, 768, 1024/8, 8, US(36.0), US(2.0+3.3) }, | |
203 | /* illustrate underruns */ | |
204 | { "1024x768ur", 1024, 768, 1024/8, 7, US(33.5), US(0.4+2.1+0.5) }, | |
205 | { NULL } | |
206 | }, *mode = mode_db; | |
207 | ||
200 | 208 | |
201 | 209 | void setup(void) |
202 | 210 | { |
... | ... | |
209 | 217 | PDDATS = VSYNC | HSYNC; |
210 | 218 | PDDATC = R | G | B | Y; |
211 | 219 | |
212 | // *msccdr = 20; /* set the MSC clock to 336 MHz / 21 = 16 MHz */ | |
213 | MSCCDR = 11; /* set the MSC clock to 336 MHz / 12 = 28 MHz */ | |
220 | MSCCDR = mode->clkdiv; /* set the MSC clock to 336 MHz / 12 = 28 MHz */ | |
214 | 221 | CLKGR &= ~(1 << 7); /* enable MSC clock */ |
215 | 222 | MSC_CLKRT = 0; /* bus clock = MSC clock / 1 */ |
216 | 223 | } |
... | ... | |
236 | 243 | |
237 | 244 | PDDATC = HSYNC; |
238 | 245 | MSC_STRPCL = 2; /* start MMC clock output */ |
246 | MSC_RESTO = 0xffff; | |
239 | 247 | |
240 | 248 | MSC_CMDAT = |
241 | 249 | (1 << 10) | /* 4 bit bus */ |
... | ... | |
245 | 253 | |
246 | 254 | MSC_STRPCL = 4; /* START_OP */ |
247 | 255 | |
248 | until(US(0.79+3.77-0.3)); | |
256 | until(mode->hsync_end); | |
249 | 257 | /* |
250 | 258 | * Adjustment value tests with the XEN-1510: |
251 | 259 | * |
... | ... | |
283 | 291 | * of the delay to shovel bits into the MSC's FIFO. |
284 | 292 | */ |
285 | 293 | |
286 | #if 0 /* quick load */ | |
287 | MSC_TXFIFO = *p++; | |
288 | MSC_TXFIFO = *p++; | |
294 | #if 1 /* quick load */ | |
295 | MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; | |
296 | MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; | |
297 | MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; | |
298 | MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; | |
299 | MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; MSC_TXFIFO = *p++; | |
289 | 300 | #endif |
290 | while (p != line+line_words) { | |
301 | while (p != line+mode->line_words) { | |
291 | 302 | uint8_t st; |
292 | 303 | do { |
293 | 304 | st = MSC_STAT; |
... | ... | |
301 | 312 | } |
302 | 313 | |
303 | 314 | fail: |
304 | until(line_cycles); | |
315 | until(mode->line_cycles); | |
305 | 316 | } |
306 | 317 | |
307 | 318 | |
... | ... | |
312 | 323 | PDDATC = HSYNC; |
313 | 324 | until(US(3.77)); |
314 | 325 | PDDATS = HSYNC; |
315 | until(line_cycles); | |
326 | until(mode->line_cycles); | |
316 | 327 | } |
317 | 328 | } |
318 | 329 | |
... | ... | |
338 | 349 | PDDATC = HSYNC; |
339 | 350 | until(US(3.77)); |
340 | 351 | PDDATS = HSYNC; |
341 | until(line_cycles-US(0.79)); | |
352 | until(mode->line_cycles-US(0.79)); | |
342 | 353 | |
343 | for (p = f; p != f+YRES*line_words; p += line_words) | |
354 | for (p = f; p != f+mode->yres*mode->line_words; p += mode->line_words) | |
344 | 355 | line(p); |
345 | 356 | |
346 | 357 | /* Back porch */ |
... | ... | |
353 | 364 | |
354 | 365 | static void session(void (*gen)(void *fb, int xres, int yres), int frames) |
355 | 366 | { |
356 | uint32_t f[YRES*(line_words+1)]; | |
367 | uint32_t *f; | |
357 | 368 | int i; |
358 | 369 | |
370 | f = malloc((mode->yres*mode->line_words)*4); | |
371 | if (!f) { | |
372 | perror("malloc"); | |
373 | exit(1); | |
374 | } | |
359 | 375 | memset(f, 0, sizeof(f)); |
360 | 376 | ccube_init(); |
361 | gen(f, XRES, YRES); | |
377 | gen(f, mode->xres, mode->yres); | |
362 | 378 | |
363 | 379 | disable_interrupts(); |
364 | 380 | |
... | ... | |
372 | 388 | static void usage(const char *name) |
373 | 389 | { |
374 | 390 | fprintf(stderr, |
375 | "usage: %s [-t] frames [file]\n\n" | |
391 | "usage: %s [-t] [-r resolution] frames [file]\n\n" | |
376 | 392 | " frames number of frames to display\n" |
377 | 393 | " file PPM file\n\n" |
378 | " -t generate a test image\n" | |
379 | , name); | |
394 | " -m mode select the display mode, default \"%s\"\n" | |
395 | " -t generate a test image\n" | |
396 | , name, mode_db[0].name); | |
380 | 397 | exit(1); |
381 | 398 | } |
382 | 399 | |
... | ... | |
387 | 404 | int frames; |
388 | 405 | int c; |
389 | 406 | |
390 | while ((c = getopt(argc, argv, "t")) != EOF) | |
407 | while ((c = getopt(argc, argv, "m:t")) != EOF) | |
391 | 408 | switch (c) { |
409 | case 'm': | |
410 | for (mode = mode_db; mode->name; mode++) | |
411 | if (!strcmp(mode->name, optarg)) | |
412 | break; | |
413 | if (!mode) { | |
414 | fprintf(stderr, "no resolution \"%s\"\n", | |
415 | optarg); | |
416 | exit(1); | |
417 | } | |
418 | break; | |
392 | 419 | case 't': |
393 | 420 | gen = tstimg; |
394 | 421 | break; |
Branches:
master