From 19f43a77c9742b18f2da9466db05f451fb565636 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Wed, 27 Apr 2011 23:31:39 -0300 Subject: [PATCH] ubb-vga2: added test image generator (option -t) - tstimg.c: test image generator - Makefile (OBJS): added tstimg.o - Makefile (LDFLAGS): tstimg.c needs libm - ubb-vga2.c (session, main): pass image generator as a function pointer - ubb-vga2.c (main): new option -t to select the test image generator --- ubb-vga/Makefile | 3 +- ubb-vga/tstimg.c | 335 +++++++++++++++++++++++++++++++++++++++++++++ ubb-vga/ubb-vga.h | 2 + ubb-vga/ubb-vga2.c | 13 +- 4 files changed, 347 insertions(+), 6 deletions(-) create mode 100644 ubb-vga/tstimg.c diff --git a/ubb-vga/Makefile b/ubb-vga/Makefile index 0f16e5a..fe32285 100644 --- a/ubb-vga/Makefile +++ b/ubb-vga/Makefile @@ -2,7 +2,8 @@ CC=mipsel-linux-gcc CFLAGS=-Wall -g -O9 -march=mips32 -OBJS=ubb-vga2.o grabfb.o +LDFLAGS=-lm +OBJS=ubb-vga2.o grabfb.o tstimg.o .PHONY: all asm sch clean spotless diff --git a/ubb-vga/tstimg.c b/ubb-vga/tstimg.c new file mode 100644 index 0000000..be0932b --- /dev/null +++ b/ubb-vga/tstimg.c @@ -0,0 +1,335 @@ +/* + * tstimg.c - Generate a test image + * + * Written 2011 by Werner Almesberger + * Copyright 2011 Werner Almesberger + * + * 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 2 of the License, or + * (at your option) any later version. + */ + +/* + * WARNING: this program does very nasty things to the Ben and it doesn't + * like company. In particular, it resents: + * + * - the MMC driver - disable it with + * echo jz4740-mmc.0 >/sys/bus/platform/drivers/jz4740-mmc/unbind + * - the AT86RF230/1 kernel driver - use a kernel that doesn't have it + * - anything that accesses the screen - kill GUI, X server, etc. + * - the screen blanker - either disable it or make sure the screen stays + * dark, e.g., with + * echo 1 >/sys/devices/platform/jz4740-fb/graphics/fb0/blank + * - probably a fair number of other daemons and things as well - best to + * kill them all. + */ + + +#include +#include +#include +#include + +#include "ubb-vga.h" + + +/* ----- Pixel operations -------------------------------------------------- */ + + +#define WHITE 0xf + + +static void pixel(void *f, int xres, int x, int y, uint8_t c) +{ + uint8_t *p; + + p = f+((y*xres+x) >> 1); + if (x & 1) + *p = (*p & 0xf0) | c; + else + *p = (*p & 0x0f) | (c << 4); +} + + +/* ----- Color bars -------------------------------------------------------- */ + + +#define CBAR_X0 0.1 +#define CBAR_X1 0.9 +#define CBAR_Y0 0.55 +#define CBAR_Y1 0.75 + + +static void color_bars(void *f, int xres, int yres, ...) +{ + int i, x, y; + uint8_t c; + + for (i = 0; i < xres*(CBAR_X1-CBAR_X0); i++) { + x = i+xres*CBAR_X0; + c = 1+15*i/(xres*(CBAR_X1-CBAR_X0)); + for (y = yres*CBAR_Y0; y < yres*CBAR_Y1; y++) + pixel(f, xres, x, y, c); + } +} + + +/* ----- Grid -------------------------------------------------------------- */ + + +#define GRID 50 + + +static void grill(void *f, int ares, int bres, int swap) +{ + int n, o; + int i, a, b; + + n = ares/GRID+1; + o = (ares % GRID)/2; + if (!(n & 1)) { + n--; + o += GRID/2; + } + for (i = 0; i != n; i++) { + a = o+i*GRID; + for (b = 0; b != bres; b++) + if (swap) + pixel(f, bres, b, a, WHITE); + else + pixel(f, ares, a, b, WHITE); + } + + if (o <= GRID/2) { + o += GRID/2; + n--; + } else { + o -= GRID/2; + n++; + } + for (i = 0; i != n; i++) { + a = o+i*GRID; + for (b = -GRID/4; b != GRID/4; b++) + if (swap) + pixel(f, bres, bres/2+b, a, WHITE); + else + pixel(f, ares, a, bres/2+b, WHITE); + } +} + + +static void grid(void *f, int xres, int yres) +{ + grill(f, xres, yres, 0); + grill(f, yres, xres, 1); +} + + +/* ----- Diagonal lines meeting at the sides ------------------------------- */ + + +static void sides(void *f, int xres, int yres) +{ + int i; + + for (i = 0; i != yres/2; i++) { + pixel(f, xres, i, yres/2-i, WHITE); + pixel(f, xres, i, yres/2+i, WHITE); + pixel(f, xres, xres-i-1, yres/2-i, WHITE); + pixel(f, xres, xres-i-1, yres/2+i, WHITE); + } + for (i = 0; i != xres/2; i++) { + pixel(f, xres, xres/2-i, i, WHITE); + pixel(f, xres, xres/2+i, i, WHITE); + pixel(f, xres, xres/2-i, yres-i-1, WHITE); + pixel(f, xres, xres/2+i, yres-i-1, WHITE); + } +} + + +/* ----- Text -------------------------------------------------------------- */ + + +static void dot(void *f, int xres, int x, int y, int color, int side) +{ + int xi, yi; + + for (xi = -side; xi != side+1; xi++) + for (yi = -side; yi != side+1; yi++) + pixel(f, xres, x+xi, y+yi, color); +} + + +static void line45(void *f, int xres, int x, int y, int dx, int dy, int n, + uint8_t color, int side) +{ + while (n--) { + dot(f, xres, x, y, color, side); + x += dx; + y += dy; + } + dot(f, xres, x, y, color, side); +} + + +static void arc(void *f, int xres, int x, int y, int n, int q, + uint8_t color, int side) +{ + int dx, dy; + + for (dx = 0; dx != n+1; dx++) { + dy = sqrt(n*n-dx*dx); + if (q & 1) + dot(f, xres, x+dx, y-dy, color, side); + if (q & 2) + dot(f, xres, x+dx, y+dy, color, side); + if (q & 4) + dot(f, xres, x-dx, y+dy, color, side); + if (q & 8) + dot(f, xres, x-dx, y-dy, color, side); + } +} + + +static void printc(void *f, int xres, int x, int y, char c, int n, + uint8_t color, int side) +{ + switch (c) { + case '0': + arc(f, xres, x+n, y+n, n, 9, color, side); + line45(f, xres, x, y+n, 0, 1, 2*n, color, side); + line45(f, xres, x+2*n, y+n, 0, 1, 2*n, color, side); + arc(f, xres, x+n, y+3*n, n, 6, color, side); + break; + case '1': + line45(f, xres, x+n, y, 0, 1, 4*n, color, side); + break; + case '2': + arc(f, xres, x+n, y+n, n, 9, color, side); + line45(f, xres, x+2*n, y+n, 0, 1, n, color, side); + line45(f, xres, x, y+4*n, 1, -1, 2*n, color, side); + line45(f, xres, x, y+4*n, 1, 0, 2*n, color, side); + break; + case '3': + arc(f, xres, x+n, y+n, n, 3, color, side); + arc(f, xres, x+n, y+3*n, n, 3, color, side); + line45(f, xres, x, y, 1, 0, n, color, side); + line45(f, xres, x, y+2*n, 1, 0, n, color, side); + line45(f, xres, x, y+4*n, 1, 0, n, color, side); + break; + case '4': + line45(f, xres, x, y, 0, 1, 2*n, color, side); + line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); + line45(f, xres, x+2*n, y, 0, 1, 4*n, color, side); + break; + case '5': + line45(f, xres, x, y, 1, 0, 2*n, color, side); + line45(f, xres, x, y, 0, 1, 2*n, color, side); + line45(f, xres, x, y+2*n, 1, 0, n, color, side); + arc(f, xres, x+n, y+3*n, n, 7, color, side); + break; + case '6': + arc(f, xres, x+n, y+n, n, 9, color, side); + line45(f, xres, x, y+n, 0, 1, 2*n, color, side); + arc(f, xres, x+n, y+3*n, n, 15, color, side); + break; + case '7': + line45(f, xres, x, y, 1, 0, 2*n, color, side); + line45(f, xres, x+2*n, y, 0, 1, 2*n, color, side); + line45(f, xres, x, y+4*n, 1, -1, 2*n, color, side); + break; + case '8': + arc(f, xres, x+n, y+n, n, 15, color, side); + arc(f, xres, x+n, y+3*n, n, 15, color, side); + break; + case '9': + arc(f, xres, x+n, y+n, n, 15, color, side); + line45(f, xres, x+2*n, y+n, 0, 1, 2*n, color, side); + arc(f, xres, x+n, y+3*n, n, 6, color, side); + break; + case 'x': + line45(f, xres, x, y+n, 1, 1, 2*n, color, side); + line45(f, xres, x, y+3*n, 1, -1, 2*n, color, side); + break; + case 'A': + line45(f, xres, x, y+n, 1, -1, n, color, side); + line45(f, xres, x, y+n, 0, 1, 3*n, color, side); + line45(f, xres, x+n, y, 1, 1, n, color, side); + line45(f, xres, x+2*n, y+n, 0, 1, 3*n, color, side); + line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); + break; + case 'B': + arc(f, xres, x+n, y+n, n, 3, color, side); + arc(f, xres, x+n, y+3*n, n, 3, color, side); + line45(f, xres, x, y, 1, 0, n, color, side); + line45(f, xres, x, y+2*n, 1, 0, n, color, side); + line45(f, xres, x, y+4*n, 1, 0, n, color, side); + line45(f, xres, x, y, 0, 1, 4*n, color, side); + break; + case 'G': + arc(f, xres, x+n, y+n, n, 9, color, side); + line45(f, xres, x, y+n, 0, 1, 2*n, color, side); + arc(f, xres, x+n, y+3*n, n, 6, color, side); + line45(f, xres, x+n, y+2*n, 1, 0, n, color, side); + line45(f, xres, x+2*n, y+2*n, 0, 1, n, color, side); + break; + case 'U': + line45(f, xres, x, y, 0, 1, 3*n, color, side); + line45(f, xres, x+2*n, y, 0, 1, 3*n, color, side); + arc(f, xres, x+n, y+3*n, n, 6, color, side); + break; + case 'V': + line45(f, xres, x, y, 0, 1, 3*n, color, side); + line45(f, xres, x+2*n, y, 0, 1, 3*n, color, side); + line45(f, xres, x+n, y+4*n, 1, -1, n, color, side); + line45(f, xres, x+n, y+4*n, -1, -1, n, color, side); + break; + case '-': + line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); + break; + case ' ': + break; + default: + arc(f, xres, x+n, y+n, n, 9, color, side); + line45(f, xres, x+n, y+2*n, 1, -1, n, color, side); + line45(f, xres, x+n, y+3*n, 0, 1, n, color, side); + break; + } +} + + +static void text(void *f, int xres, int x, int y, const char *s, int n, + uint8_t color, int side) +{ + while (*s) { + printc(f, xres, x, y, *s, n, color, side); + x += 3*n; + s++; + } +} + + + +static void ctext(void *f, int xres, int x, int y, const char *s, int n, + uint8_t color, int side) +{ + text(f, xres, x+n*(1-3*(int) strlen(s))/2, y-2*n, s, n, color, side); +} + + +/* ----- Generate the test image ------------------------------------------- */ + + +void tstimg(void *f, int xres, int yres) +{ + char buf[20]; + + memset(f, 0, xres*yres/2); + grid(f, xres, yres); + sides(f, xres, yres); + color_bars(f, xres, yres); + sprintf(buf, "UBB-VGA %dx%d", xres, yres); + ctext(f, xres, xres/2, yres/2-GRID*0.75, buf, 10, WHITE, 3); + ctext(f, xres, xres/2, yres*(CBAR_Y0+CBAR_Y1)/2, buf, 2, 0, 0); +} diff --git a/ubb-vga/ubb-vga.h b/ubb-vga/ubb-vga.h index 2f16d2d..f2d7568 100644 --- a/ubb-vga/ubb-vga.h +++ b/ubb-vga/ubb-vga.h @@ -30,4 +30,6 @@ extern uint8_t thres; void grabfb(void *f, int xres, int yres); +void tstimg(void *f, int xres, int yres); + #endif /* !UBB_VGA_H */ diff --git a/ubb-vga/ubb-vga2.c b/ubb-vga/ubb-vga2.c index 6b24653..1188f0f 100644 --- a/ubb-vga/ubb-vga2.c +++ b/ubb-vga/ubb-vga2.c @@ -390,14 +390,13 @@ static void frame(const uint32_t *f) /* ----- Command-line parsing and main loop -------------------------------- */ -static void session(int frames) +static void session(void (*gen)(void *fb, int xres, int yres), int frames) { uint32_t f[2*240*(line_words+1)]; int i; memset(f, 0, sizeof(f)); - grabfb(f, 640, 480); -// grid(f); + gen(f, 640, 480); disable_interrupts(); @@ -421,11 +420,15 @@ static void usage(const char *name) int main(int argc, char *const *argv) { + void (*gen)(void *fb, int xres, int yres) = grabfb; int frames; int c; - while ((c = getopt(argc, argv, "")) != EOF) + while ((c = getopt(argc, argv, "t")) != EOF) switch (c) { + case 't': + gen = tstimg; + break; default: usage(*argv); } @@ -442,7 +445,7 @@ int main(int argc, char *const *argv) } setup(); - session(frames); + session(gen, frames); cleanup(); if (bad)