1
0
mirror of git://projects.qi-hardware.com/ben-blinkenlights.git synced 2025-04-21 12:27:27 +03:00

renamed "video" to ubb-vga

This commit is contained in:
Werner Almesberger
2011-04-24 02:56:56 -03:00
parent b11dc612e2
commit 3b7a7caec1
5 changed files with 4 additions and 4 deletions

19
ubb-vga/Makefile Normal file
View File

@@ -0,0 +1,19 @@
#CC=mipsel-openwrt-linux-uclibc-gcc
CC=mipsel-linux-gcc
CFLAGS=-Wall -g -O9 -march=mips32
.PHONY: all asm sch clean spotless
all: ubb-vga
asm: ubb-vga.c
$(CC) $(CFLAGS) -S $<
sch:
eeschema `pwd`/ubb-vga.sch
clean:
rm -f ubb-vga
spotless: clean

37
ubb-vga/README Normal file
View File

@@ -0,0 +1,37 @@
Sources
-------
Timing and the idea for the voltage divider is from:
http://faculty.lasierra.edu/~ehwang/public/mypublications/VGA Monitor Controller.pdf
More timing parameters:
http://tinyvga.com/vga-timing/640x480@60Hz
Signal 8:10 VGA
------- ------- ---
R DAT2 1
VSYNC DAT3 14
HSYNC CMD 13
G DAT0 2
B DAT1 3
GND GND 5
http://en.wikipedia.org/wiki/VGA_connector
Timing
------
Since the Ingenic CPUs take about 8.5 PCLK cycles for a GPIO set or clear,
and we can only set or clear a set of signals in GPIO operation, but not
set some and clear others, we cannot have a real 320 horizontal pixels.
Instead, set and clear operations alternate. This means that the best-case
resolution is equivalent to 320 pixels (if the original pixel boundaries
coincide with the set/clear phases), but it can be as low as 160 pixels if
the boundaries don't match.
Furthermore, timing is still a bit too tight. We therefore use a pixel
clock that's about 10% slower than the original. Luckily, most monitors
don't mind.

416
ubb-vga/ubb-vga.c Normal file
View File

@@ -0,0 +1,416 @@
/*
* ubb-vga.c - Output video on UBB with more or less VGA timing
*
* 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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#define DAT0 (1 << 10)
#define DAT1 (1 << 11)
#define DAT2 (1 << 12)
#define DAT3 (1 << 13)
#define CMD (1 << 8)
#define CLK (1 << 9)
#define R DAT2
#define G DAT0
#define B DAT1
#define HSYNC CMD
#define VSYNC DAT3
#define TIMER 7
#define PAGE_SIZE 4096
#define SOC_BASE 0x10000000
#define DEFAULT_COUNT (1000*1000)
static uint8_t thres = 63;
/* ----- Ben hardware ------------------------------------------------------ */
static volatile uint32_t *icmr, *icmsr, *icmcr;
static uint32_t old_icmr;
static volatile uint32_t *clkgr;
static uint32_t old_clkgr;
static volatile uint32_t *pdpin, *pddats, *pddatc;
static volatile uint32_t *pddirs, *pddirc;
static volatile uint32_t *tssr, *tscr;
static volatile uint32_t *tesr, *tecr;
static volatile uint32_t *tcsr, *tdfr, *tcnt;
static void disable_interrupts(void)
{
/*
* @@@ Race condition alert ! If we get interrupted/preempted between
* reading ICMR and masking all interrupts, and the code that runs
* between these two operations changes ICMR, then we may set an
* incorrect mask when restoring interrupts, which may hang the system.
*/
old_icmr = *icmr;
*icmsr = 0xffffffff;
}
static void enable_interrupts(void)
{
*icmcr = ~old_icmr;
}
/*
* @@@ Disabling the LCD clock will halng operations that depend on the LCD
* subsystem to advance. This includes the screen saver.
*/
static void disable_lcd(void)
{
old_clkgr = *clkgr;
*clkgr = old_clkgr | 1 << 10;
}
static void enable_lcd(void)
{
*clkgr = old_clkgr;
}
static void get_timer(void)
{
*tscr = 1 << TIMER; /* enable clock */
*tcsr = 1; /* count at PCLK/1 */
*tdfr = 0xffff; /* count to 0xffff */
*tesr = 1 << TIMER;
}
static void release_timer(void)
{
*tecr = 1 << TIMER;
*tssr = 1 << TIMER;
}
static void *map(off_t addr, size_t size)
{
int fd;
void *mem;
fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
perror("/dev/mem");
exit(1);
}
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr);
if (mem == MAP_FAILED) {
perror("mmap");
exit(1);
}
return mem;
}
static void ben_setup(void)
{
volatile void *base;
base = map(SOC_BASE, PAGE_SIZE*3*16);
icmr = base+0x1004;
icmsr = base+0x1008;
icmcr = base+0x100c;
clkgr = base+0x20;
pdpin = base+0x10300;
pddats = base+0x10314;
pddatc = base+0x10318;
pddirs = base+0x10364;
pddirc = base+0x10368;
tssr = base+0x202c;
tscr = base+0x203c;
tesr = base+0x2014;
tecr = base+0x2018;
tcsr = base+0x204c+0x10*TIMER;
tdfr = base+0x2040+0x10*TIMER;
tcnt = base+0x2048+0x10*TIMER;
/*
* Ironically, switching the LCD clock on and off many times only
* increases the risk of a hang. Therefore, we leave stop it during
* all the measurements and only enable it again at the end.
*/
disable_lcd();
get_timer();
}
static void cleanup(void)
{
release_timer();
enable_lcd();
}
/* ----- Interface --------------------------------------------------------- */
void setup(void)
{
mlockall(MCL_CURRENT | MCL_FUTURE);
ben_setup();
*pddirs = R | G | B | HSYNC | VSYNC;
}
static uint32_t pick(int set, int bit, uint32_t val)
{
return set == bit ? val >> 8 : 0;
}
static uint32_t pattern(int set, int r, int g, int b)
{
return pick(set, r, R) | pick(set, g, G) | pick(set, b, B);
}
#define BURST 32
#define PREFETCH_HSYNC 160
#define PREFETCH_HFRONT (160-PREFETCH_HSYNC)
#define DELAY_HFRONT 30
#define DELAY_HBACK 40
//#define DELAY_VSYNC 3500
//#define DELAY_VFRONT 56000
//#define DELAY_VBACK 28000
#define DELAY_VFRONT 1500
#define DELAY_LINE 1800
#define DELAY_HSYNC 210
static inline void prefetch(const uint8_t *prefetch, int words)
{
volatile const uint8_t *p = prefetch;
while (p != prefetch+words) {
(void) *p;
p += BURST;
}
}
static void until(uint16_t cycles)
{
while ((*tcnt & 0xffff) < cycles);
}
#define US(us) ((uint16_t) ((us)*112))
static void line(const uint8_t *line, const uint8_t *fetch)
{
const uint8_t *p = line;
//volatile uint8_t pat = R | B | G;
/* HSYNC */
*tcnt = 0;
*pddatc = HSYNC;
// prefetch(fetch, PREFETCH_HSYNC);
prefetch(fetch, 160);
until(US(3.77));
// *tcnt = 0;
*pddats = HSYNC;
/* Front porch */
// prefetch(fetch+PREFETCH_HSYNC, PREFETCH_HFRONT);
// until(US(3.77+1.79-3.77));
until(US(3.77+1.79));
while (p != line+320) {
*pddats = *p++ << 8;//pat; //R | G | B; //*p++;
*pddatc = *p++ << 8;//pat;//R | G | B; // *p++;
}
/* Back porch */
// until(US(31.77-3.77));
until(US(31.77));
until(US(36));
}
static void hdelay(int cycles)
{
while (cycles--) {
*tcnt = 0;
*pddatc = HSYNC;
until(US(3.77));
*pddats = HSYNC;
until(US(31.77));
until(US(36));
}
}
static void frame(const uint8_t *f)
{
const uint8_t *p;
/* VSYNC */
*pddatc = VSYNC;
hdelay(2);
*pddats = VSYNC;
/* Front porch */
*tcnt = 0;
*pddatc = HSYNC;
// prefetch(f, PREFETCH_HSYNC);
until(US(3.77));
// *tcnt = 0;
*pddats = HSYNC;
// prefetch(f+PREFETCH_HSYNC, PREFETCH_HFRONT);
prefetch(f, 160);
// until(US(31.77-3.77));
until(US(31.77));
until(US(36));
hdelay(31);
for (p = f; p != f+240*320; p += 320) {
line(p, p+160);
line(p, p+320);
}
/* Back porch */
hdelay(14);
}
static void tricolor(uint32_t *f)
{
int i;
for (i = 0; i != 320*240/3; i++) {
f[i & ~1] = R;
f[i | 1] = G | B;
}
for (; i != 320*240*2/3; i++) {
f[i & ~1] = G;
f[i | 1] = R | B;
}
for (; i != 320*240; i++) {
f[i & ~1] = B;
f[i | 1] = R | G;
}
}
static void grid(uint8_t *f)
{
static uint32_t col[8] = {
R | G | B,
R,
R | G,
G,
G | B,
B,
R | B,
R | G | B,
};
int i, x, y;
for (i = 0; i != 8; i++) {
x = i*40+20;
for (y = 0; y != 240; y++) {
f[y*320+x] = f[y*320+x+1] = col[i] >> 8;
}
}
}
static void grab(uint8_t *f)
{
uint32_t *fb = map(0x01d00000, 4*320*240);
int x, y;
uint32_t pix;
for (y = 0; y != 240; y++)
for (x = 0; x != 320; x++) {
pix = *fb++;
*f++ = pattern(!(x & 1),
((pix >> 16) & 255) >= thres,
((pix >> 8) & 255) >= thres,
(pix & 255) >= thres);
}
}
static void session(int n)
{
uint8_t f[320*(240+1)];
int i;
memset(f, 0, sizeof(f));
grab(f);
// grid(f);
disable_interrupts();
for (i = 0; i != n; i++)
frame(f);
enable_interrupts();
}
int main(int argc, char **argv)
{
thres = atoi(argv[2]);
setup();
session(atoi(argv[1]));
cleanup();
return 0;
}

40
ubb-vga/ubb-vga.pro Normal file
View File

@@ -0,0 +1,40 @@
update=Sun Apr 24 01:38:18 2011
last_client=eeschema
[eeschema]
version=1
LibDir=
NetFmt=1
HPGLSpd=20
HPGLDm=15
HPGLNum=1
offX_A4=0
offY_A4=0
offX_A3=0
offY_A3=0
offX_A2=0
offY_A2=0
offX_A1=0
offY_A1=0
offX_A0=0
offY_A0=0
offX_A=0
offY_A=0
offX_B=0
offY_B=0
offX_C=0
offY_C=0
offX_D=0
offY_D=0
offX_E=0
offY_E=0
RptD_X=0
RptD_Y=100
RptLab=1
LabSize=60
PrintMonochrome=1
ShowSheetReferenceAndTitleBlock=1
[eeschema/libraries]
LibName1=power
LibName2=device
LibName3=../../kicad-libs/components/8_10-card
LibName4=../../kicad-libs/components/vga

245
ubb-vga/ubb-vga.sch Normal file
View File

@@ -0,0 +1,245 @@
EESchema Schematic File Version 2 date Sun Apr 24 02:16:48 2011
LIBS:power
LIBS:device
LIBS:8_10-card
LIBS:vga
LIBS:ubb-vga-cache
EELAYER 24 0
EELAYER END
$Descr A4 11700 8267
Sheet 1 1
Title "UBB VGA Adapter"
Date "24 apr 2011"
Rev "20110424"
Comp "Werner Almesberger"
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
Text Label 8200 3300 0 60 ~ 0
VSYNC
Text Label 8200 3400 0 60 ~ 0
HSYNC
Text Label 2100 3800 0 60 ~ 0
VSYNC
Text Label 2100 3600 0 60 ~ 0
HSYNC
Text Label 8200 3900 0 60 ~ 0
B
Text Label 8200 3800 0 60 ~ 0
G
Text Label 8200 3200 0 60 ~ 0
R
Wire Wire Line
2550 3800 1800 3800
Wire Wire Line
1800 3800 1800 2550
Wire Wire Line
1800 2550 5150 2550
Wire Wire Line
5150 3300 5150 2550
Wire Wire Line
8850 3300 5150 3300
Wire Wire Line
3750 3600 4750 3600
Wire Wire Line
4750 3600 4750 4000
Wire Wire Line
4750 4000 7000 4000
Wire Wire Line
7000 4000 7200 4000
Wire Wire Line
7200 3800 6650 3800
Wire Wire Line
6650 3800 4850 3800
Connection ~ 3950 4000
Wire Wire Line
3750 4000 3950 4000
Connection ~ 7000 4000
Connection ~ 6300 3200
Wire Wire Line
6650 3800 6650 4200
Wire Wire Line
7000 4600 7000 4800
Wire Wire Line
6300 4800 6300 4600
Wire Wire Line
8850 3800 7700 3800
Wire Wire Line
8850 3700 8650 3700
Wire Wire Line
8650 3700 8650 4300
Wire Wire Line
7700 4000 7900 4000
Wire Wire Line
7900 4000 7900 3900
Wire Wire Line
7900 3900 8850 3900
Wire Wire Line
8850 3200 7700 3200
Wire Wire Line
6650 4600 6650 4800
Wire Wire Line
7000 4000 7000 4200
Wire Wire Line
6300 3200 6300 4200
Connection ~ 6650 3800
Wire Wire Line
3750 3900 3950 3900
Wire Wire Line
3950 3900 3950 4000
Wire Wire Line
3950 4000 3950 4200
Wire Wire Line
3750 3200 6300 3200
Wire Wire Line
6300 3200 7200 3200
Wire Wire Line
3750 3400 4850 3400
Wire Wire Line
4850 3400 4850 3800
Wire Wire Line
8850 3400 5050 3400
Wire Wire Line
5050 3400 5050 2650
Wire Wire Line
5050 2650 1900 2650
Wire Wire Line
1900 2650 1900 3600
Wire Wire Line
1900 3600 2550 3600
NoConn ~ 2550 3200
NoConn ~ 2550 3400
NoConn ~ 2550 4000
Text Label 3950 3600 0 60 ~ 0
BLUE
Text Label 3950 3400 0 60 ~ 0
GREEN
Text Label 3950 3200 0 60 ~ 0
RED
NoConn ~ 3750 3800
NoConn ~ 3750 3700
NoConn ~ 3750 3500
NoConn ~ 3750 3300
NoConn ~ 3750 3100
$Comp
L GND #PWR1
U 1 1 4DB3B0C4
P 3950 4200
F 0 "#PWR1" H 3950 4200 30 0001 C CNN
F 1 "GND" H 3950 4130 30 0001 C CNN
1 3950 4200
1 0 0 -1
$EndComp
$Comp
L GND #PWR4
U 1 1 4DB3B04B
P 7000 4800
F 0 "#PWR4" H 7000 4800 30 0001 C CNN
F 1 "GND" H 7000 4730 30 0001 C CNN
1 7000 4800
1 0 0 -1
$EndComp
$Comp
L GND #PWR3
U 1 1 4DB3B04A
P 6650 4800
F 0 "#PWR3" H 6650 4800 30 0001 C CNN
F 1 "GND" H 6650 4730 30 0001 C CNN
1 6650 4800
1 0 0 -1
$EndComp
$Comp
L GND #PWR2
U 1 1 4DB3B048
P 6300 4800
F 0 "#PWR2" H 6300 4800 30 0001 C CNN
F 1 "GND" H 6300 4730 30 0001 C CNN
1 6300 4800
1 0 0 -1
$EndComp
$Comp
L GND #PWR5
U 1 1 4DB3AFED
P 8650 4300
F 0 "#PWR5" H 8650 4300 30 0001 C CNN
F 1 "GND" H 8650 4230 30 0001 C CNN
1 8650 4300
1 0 0 -1
$EndComp
NoConn ~ 8850 3600
NoConn ~ 8850 3500
$Comp
L DIODE D1
U 1 1 4DB3AF61
P 6300 4400
F 0 "D1" H 6300 4500 40 0000 C CNN
F 1 "1N4148" H 6300 4300 40 0000 C CNN
1 6300 4400
0 -1 1 0
$EndComp
$Comp
L DIODE D2
U 1 1 4DB3AF5F
P 6650 4400
F 0 "D2" H 6650 4500 40 0000 C CNN
F 1 "1N4148" H 6650 4300 40 0000 C CNN
1 6650 4400
0 -1 1 0
$EndComp
$Comp
L DIODE D3
U 1 1 4DB3AF5B
P 7000 4400
F 0 "D3" H 7000 4500 40 0000 C CNN
F 1 "1N4148" H 7000 4300 40 0000 C CNN
1 7000 4400
0 -1 1 0
$EndComp
$Comp
L R R3
U 1 1 4DB3AF4D
P 7450 4000
F 0 "R3" V 7530 4000 50 0000 C CNN
F 1 "1k" V 7450 4000 50 0000 C CNN
1 7450 4000
0 -1 -1 0
$EndComp
$Comp
L R R2
U 1 1 4DB3AF4B
P 7450 3800
F 0 "R2" V 7530 3800 50 0000 C CNN
F 1 "1k" V 7450 3800 50 0000 C CNN
1 7450 3800
0 -1 -1 0
$EndComp
$Comp
L R R1
U 1 1 4DB3AF49
P 7450 3200
F 0 "R1" V 7530 3200 50 0000 C CNN
F 1 "1k" V 7450 3200 50 0000 C CNN
1 7450 3200
0 -1 -1 0
$EndComp
$Comp
L 8:10-CARD P1
U 1 1 4DB3AF38
P 9150 3500
F 0 "P1" H 8950 4050 60 0000 C CNN
F 1 "UBB" H 9200 2900 60 0000 C CNN
1 9150 3500
1 0 0 -1
$EndComp
$Comp
L VGA J1
U 1 1 4DB3AF2A
P 3150 3550
F 0 "J1" H 3350 2850 60 0000 C CNN
F 1 "VGA" H 3150 4300 60 0000 C CNN
1 3150 3550
-1 0 0 1
$EndComp
$EndSCHEMATC