1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2024-11-16 21:01:54 +02:00
ben-blinkenlights/ubb-vga/tstimg.c

509 lines
14 KiB
C

/*
* 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 <stdint.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#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;
int y, n;
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);
y = yres/8;
n = 5;
if (yres < 768)
y = yres/16;
if (yres < 600)
n = 4;
sprintf(buf, "PIXEL %5.2f MHZ", 336.0/(mode->clkdiv+1));
text(f, xres, xres/8, y, buf, n, WHITE, 1);
y += 6*n;
line_freq_hz = 112000000.0/(mode->line_cycles);
sprintf(buf, "LINE %5.2f KHZ", line_freq_hz/1000);
text(f, xres, xres/8, y, buf, n, WHITE, 1);
y += 6*n;
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, y, buf, n, WHITE, 1);
y += 6*n;
sprintf(buf, "VERT %d+%d+%d+%d LINES",
mode->vsync_lines, mode->vfront_lines, mode->yres,
mode->vback_lines);
text(f, xres, xres/8, y, buf, n, WHITE, 1);
y += 6*n;
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, y, buf, n, WHITE, 1);
}