/* * 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]+(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-1)/GRID+1; o = ((ares-1) % GRID)/2; if (!(n & 1)) { n--; o += GRID/2; } for (i = 0; i != n; i++) { a = o+i*GRID; for (b = 0; b != bres-1; 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); line45(f, xres, x, y+3*n, 1, -1, 2*n, color, side); break; case '1': line45(f, xres, x, y+n, 1, -1, n, color, side); 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 'C': 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); break; case 'D': arc(f, xres, x+n, y+n, n, 1, color, side); line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x+2*n, y+n, 0, 1, 3*n, color, side); line45(f, xres, x, y, 1, 0, n, color, side); line45(f, xres, x, y+4*n, 1, 0, n, color, side); arc(f, xres, x+n, y+3*n, n, 2, color, side); break; case 'E': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 0, 2*n, color, side); line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); line45(f, xres, x, y+4*n, 1, 0, 2*n, color, side); break; case 'F': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 0, 2*n, color, side); line45(f, xres, x, y+2*n, 1, 0, 2*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 'H': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x+2*n, y, 0, 1, 4*n, color, side); line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); break; case 'I': line45(f, xres, x+n, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 0, 2*n, color, side); line45(f, xres, x, y+4*n, 1, 0, 2*n, color, side); break; case 'J': 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 'K': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x, y+2*n, 1, -1, 2*n, color, side); line45(f, xres, x, y+2*n, 1, 1, 2*n, color, side); break; case 'L': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x, y+4*n, 1, 0, 2*n, color, side); break; case 'M': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x+2*n, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 1, n, color, side); line45(f, xres, x+n, y+n, 1, -1, n, color, side); line45(f, xres, x+n, y+1*n, 0, 1, n, color, side); break; case 'N': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x+2*n, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 1, n, color, side); line45(f, xres, x+n, y+n, 0, 1, 2*n, color, side); line45(f, xres, x+n, y+3*n, 1, 1, n, color, side); break; case 'O': 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 'P': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 0, n, color, side); line45(f, xres, x, y+2*n, 1, 0, n, color, side); arc(f, xres, x+n, y+n, n, 3, color, side); break; case 'Q': 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); line45(f, xres, x+n, y+3*n, 1, 1, n, color, side); break; case 'R': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 0, n, color, side); line45(f, xres, x, y+2*n, 1, 0, n, color, side); arc(f, xres, x+n, y+n, n, 3, color, side); line45(f, xres, x, y+2*n, 1, 1, 2*n, color, side); break; case 'S': arc(f, xres, x+n, y+n, n, 9, color, side); line45(f, xres, x, y+n, 1, 1, 2*n, color, side); arc(f, xres, x+n, y+3*n, n, 6, color, side); break; case 'T': line45(f, xres, x+n, y, 0, 1, 4*n, color, side); line45(f, xres, x, y, 1, 0, 2*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 'W': line45(f, xres, x, y, 0, 1, 4*n, color, side); line45(f, xres, x+2*n, y, 0, 1, 4*n, color, side); line45(f, xres, x, y+4*n, 1, -1, n, color, side); line45(f, xres, x+n, y+3*n, 1, 1, n, color, side); line45(f, xres, x+n, y+2*n, 0, 1, n, 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); line45(f, xres, x, y, 0, 1, n, color, side); line45(f, xres, x+2*n, y, 0, 1, n, color, side); line45(f, xres, x, y+3*n, 0, 1, n, color, side); line45(f, xres, x+2*n, y+3*n, 0, 1, n, color, side); break; case 'Y': line45(f, xres, x, y, 0, 1, n, color, side); line45(f, xres, x+2*n, y, 0, 1, n, color, side); line45(f, xres, x, y+n, 1, 1, n, color, side); line45(f, xres, x+2*n, y+n, -1, 1, n, color, side); line45(f, xres, x+n, y+2*n, 0, 1, 2*n, color, side); break; case 'Z': line45(f, xres, x, y, 1, 0, 2*n, color, side); line45(f, xres, x, y+4*n, 1, 0, 2*n, color, side); line45(f, xres, x+2*n, y, 0, 1, n, color, side); line45(f, xres, x, y+3*n, 0, 1, n, color, side); line45(f, xres, x, y+3*n, 1, -1, 2*n, color, side); break; case '-': line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); break; case '=': line45(f, xres, x, y+1*n, 1, 0, 2*n, color, side); line45(f, xres, x, y+3*n, 1, 0, 2*n, color, side); break; case '+': line45(f, xres, x, y+2*n, 1, 0, 2*n, color, side); line45(f, xres, x+n, y+n, 0, 1, 2*n, color, side); break; case ' ': break; case '.': line45(f, xres, x+n, y+3*n, 0, 1, n, color, side); 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[40]; double line_freq_hz; 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); sprintf(buf, "PIXEL %5.2f MHZ", 336.0/(mode->clkdiv+1)); text(f, xres, xres/8, yres/8, buf, 5, WHITE, 1); line_freq_hz = 112000000.0/(mode->line_cycles); sprintf(buf, "LINE %5.2f KHZ", line_freq_hz/1000); text(f, xres, xres/8, yres/8+5*6, buf, 5, WHITE, 1); sprintf(buf, "FRAME %5.2f HZ", line_freq_hz/(mode->vsync_lines+ mode->vfront_lines+mode->yres+ mode->vback_lines)); text(f, xres, xres/8, yres/8+5*12, buf, 5, WHITE, 1); sprintf(buf, "VERT %d+%d+%d+%d LINES", mode->vsync_lines, mode->vfront_lines, mode->yres, mode->vback_lines); text(f, xres, xres/8, yres/8+5*18, buf, 5, WHITE, 1); sprintf(buf, "HOR %4.2f+...+%4.2f = %5.2f US", CYCLES(mode->hsync_cycles), CYCLES(mode->hback_cycles), CYCLES(mode->line_cycles)); text(f, xres, xres/8, yres/8+5*24, buf, 5, WHITE, 1); }