mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-19 10:42:28 +02:00
509 lines
14 KiB
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);
|
|
}
|