Added driver for SED1520 graphic LCDs, STV5730 TV Output plus a small fix for render.c for bigger display sizes

This commit is contained in:
afrob
2001-09-22 11:45:12 +00:00
parent 968a733d88
commit 2e654fd333
10 changed files with 2470 additions and 2 deletions
+4
View File
@@ -45,6 +45,10 @@
#undef MTXORB_DRV
#undef SED1520_DRV
#undef STV5730_DRV
/* Define the package name */
#undef PACKAGE
+9 -1
View File
@@ -9,7 +9,7 @@ AC_ARG_ENABLE(drivers,
drivers=[mtxorb,cfontz,curses,text,lb216,bayrad,glk])
if test "$drivers" = "all"; then
drivers=[mtxorb,cfontz,curses,text,lb216,hd44780,joy,irman,lircin,bayrad,glk]
drivers=[mtxorb,cfontz,curses,text,lb216,hd44780,joy,irman,lircin,bayrad,glk,stv5730,sed1520]
AC_MSG_RESULT(all)
fi
@@ -73,6 +73,14 @@ fi
DRIVERS="$DRIVERS lircin.o"
AC_DEFINE(LIRCIN_DRV)
;;
sed1520)
DRIVERS="$DRIVERS sed1520.o"
AC_DEFINE(SED1520_DRV)
;;
stv5730)
DRIVERS="$DRIVERS stv5730.o"
AC_DEFINE(STV5730_DRV)
;;
*)
AC_MSG_ERROR([Unknown driver $driver])
;;
+2
View File
@@ -8,6 +8,8 @@ EXTRA_libLCDdrivers_a_SOURCES = MtxOrb.c MtxOrb.h text.c text.h \
hd44780-serialLpt.c hd44780-serialLpt.h \
hd44780-winamp.c hd44780-winamp.h \
hd44780-low.h hd44780-drivers.h \
sed1520.c sed1520.h sed1520fm.c \
stv5730.c stv5730.h \
port.h joy.c joy.h irmanin.c irmanin.h \
bayrad.h bayrad.c \
CFontz.c CFontz.h lircin.c lircin.h debug.h \
+14
View File
@@ -65,6 +65,14 @@
#include "bayrad.h"
#endif
#ifdef SED1520_DRV
#include "sed1520.h"
#endif
#ifdef STV5730_DRV
#include "stv5730.h"
#endif
#ifdef GLK_DRV
#include "glk.h"
#endif
@@ -122,6 +130,12 @@ lcd_physical_driver drivers[] = {
#endif
#ifdef GLK_DRV
{"glk", glk_init,},
#endif
#ifdef SED1520_DRV
{"sed1520", sed1520_init,},
#endif
#ifdef STV5730_DRV
{"stv5730", stv5730_init,},
#endif
{NULL, NULL,},
+559
View File
@@ -0,0 +1,559 @@
//////////////////////////////////////////////////////////////////////////
// This is a driver for 122x32 pixel graphic displays based on the //
// SED1520 Controller connected to the parallel port. Check //
// www.adams-online.de/lcd for where to buy //
// and how to build the hardware. This Controller has no built in //
// character generator. Therefore all fonts and pixels are generated //
// by this driver. //
// //
// This driver is based on drv_base.c and hd44780.c. //
// The HD44780 font in sed1520fm.c was shamelessly stolen from //
// Michael Reinelt / lcd4linux and is (C) 2000 by him. //
// The rest of fontmap.c and this driver is //
// //
// (C) 2001 Robin Adams ( robin@adams-online.de ) //
// //
// This driver is released under the GPL. See file COPYING in this //
// package for further details. //
//////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/errno.h>
#include <sched.h>
#include <time.h>
#include "port.h"
#include "sed1520fm.c"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef LPTPORT
#define LPTPORT 0x378
#endif
#define A0 0x08
#define CS2 0x04
#define CS1 0x02
#define WR 0x01
#define IODELAY 500
#include "shared/str.h"
#include "lcd.h"
#include "sed1520.h"
unsigned int sed1520_lptport = LPTPORT;
static void uPause (int delayCalls);
lcd_logical_driver *sed1520;
/////////////////////////////////////////////////////////////////
// writes command value to one or both sed1520 selected by chip
//
void
writecommand (int value, int chip)
{
port_out ( sed1520_lptport,value);
port_out ( sed1520_lptport + 2,WR + CS1 - (chip & CS1) + (chip & CS2));
port_out ( sed1520_lptport + 2,CS1 - (chip & CS1) + (chip & CS2));
uPause (IODELAY);
port_out ( sed1520_lptport + 2,WR + CS1 - (chip & CS1) + (chip & CS2));
uPause (IODELAY);
}
/////////////////////////////////////////////////////////////////
// writes data value to one or both sed 1520 selected by chip
//
void
writedata (int value, int chip)
{
port_out ( sed1520_lptport,value);
port_out ( sed1520_lptport + 2,A0 + WR + CS1 - (chip & CS1) + (chip & CS2));
port_out ( sed1520_lptport + 2,A0 + CS1 - (chip & CS1) + (chip & CS2));
uPause (IODELAY);
port_out ( sed1520_lptport + 2,A0 + WR + CS1 - (chip & CS1) + (chip & CS2));
uPause (IODELAY);
}
/////////////////////////////////////////////////////////////////
// selects a page (=row) on both sed1520s
//
void
selectpage (int page)
{
writecommand (0xB8 + (page & 3), CS1 + CS2);
}
/////////////////////////////////////////////////////////////////
// selects a column on the sed1520s specified by chip
//
void
selectcolumn (int column, int chip)
{
writecommand ((column & 0x7F), chip);
}
/////////////////////////////////////////////////////////////////
// draws char z from fontmap to the framebuffer at position
// x,y. These are zero-based textmode positions.
// The Fontmap is stored in rows while the framebuffer is stored
// in columns, so we need a little conversion.
//
void
drawchar2fb (int x, int y, unsigned char z)
{
int i, j, k;
if (x < 0 || x > 19 || y < 0 || y > 3)
return;
for (i = 6; i > 0; i--)
{
k = 0;
for (j = 0; j < 7; j++)
{
k = k +
(((fontmap[(int) z][j] * 2) & (1 << i)) / (1 << i)) *
(1 << j);
}
lcd.framebuf[(y * 122) + (x * 6) + (6 - i)] = k;
}
}
/////////////////////////////////////////////////////////////////
// This initialises the stuff. We support supplying port as
// a command line argument.
//
int
sed1520_init (struct lcd_logical_driver *driver, char *args)
{
char *argv[64], *str;
int argc, i;
sed1520 = driver;
if (args)
if ((str = (char *) malloc (strlen (args) + 1)))
strcpy (str, args);
else
{
fprintf (stderr, "Error mallocing\n");
return -1;
}
else
str = NULL;
argc = get_args (argv, args, 64);
for (i = 0; i < argc; i++)
{
if (0 == strcmp (argv[i], "-p")
|| 0 == strcmp (argv[i], "--port\0"))
{
if (i + 1 >= argc)
{
fprintf (stderr,
"sed1520_init: %s requires an argument\n",
argv[i]);
return -1;
}
else
{
int myport;
if (sscanf (argv[i + 1], "%i", &myport) != 1)
{
fprintf (stderr,
"sed1520_init: Couldn't read port address -"
" using default value 0x%x\n", sed1520_lptport);
return -1;
}
else
{
sed1520_lptport = myport;
++i;
}
}
}
else if (0 == strcmp (argv[i], "-h")
|| 0 == strcmp (argv[i], "--help"))
{
int i;
printf
("LCDproc sed1520 driver\n\t-p n\t--port n\tSelect the output device to use port n\n");
printf ("put the options in quotes like this: '-p 0x278'\n");
printf ("\t-h\t--help\t\tShow this help information\n");
return -1;
}
}
driver->wid = 20;
driver->hgt = 4;
{
struct sched_param param;
param.sched_priority = 1;
if ((sched_setscheduler (0, SCHED_RR, &param)) == -1)
{
fprintf (stderr, "sed1520_init: failed (%s)\n",
strerror (errno));
return -1;
}
}
// Initialize the Port and the sed1520s
if(port_access(sed1520_lptport)) return -1;
if(port_access(sed1520_lptport+2)) return -1;
port_out (sed1520_lptport,0);
port_out (sed1520_lptport +2,WR + CS2);
writecommand (0xE2, CS1 + CS2);
writecommand (0xAF, CS1 + CS2);
writecommand (0xC0, CS1 + CS2);
selectpage (3);
// The Framebuffer LCDproc allocates by default is too small,
// so we free() it and allocate one of adequate size.
if (!driver->framebuf)
free (driver->framebuf);
driver->framebuf = malloc (488);
if (!driver->framebuf)
{
sed1520_close ();
return -1;
}
// clear screen
memset (driver->framebuf, 0, 122 * 4);
driver->cellwid = 6;
driver->cellhgt = 8; // FIXME: lcd.cellwid always stays 5
// regardless what it is set to here. This is
// a bug but not inside this driver.
driver->clear = sed1520_clear;
driver->string = sed1520_string;
driver->chr = sed1520_chr;
driver->vbar = sed1520_vbar;
driver->hbar = sed1520_hbar;
driver->num = sed1520_num;
driver->init = sed1520_init;
driver->close = sed1520_close;
driver->flush = sed1520_flush;
driver->flush_box = sed1520_flush_box;
driver->set_char = sed1520_set_char;
driver->icon = sed1520_icon;
driver->draw_frame = sed1520_draw_frame;
// We dont't need init for vbar,hbar and friends.
driver->init_hbar = NULL;
driver->init_vbar = NULL;
driver->init_num = NULL;
// Neither contrast nor backlight are controllable.
driver->contrast = NULL;
driver->backlight = NULL;
// There are some unused input lines that may be used for input,
// but nothing is programmed so far.
driver->getkey = NULL;
return 200; // 200 is arbitrary. (must be 1 or more)
}
/////////////////////////////////////////////////////////////////
// Frees the frambuffer and exits the driver.
//
void
sed1520_close ()
{
if (lcd.framebuf != NULL)
free (lcd.framebuf);
lcd.framebuf = NULL;
}
/////////////////////////////////////////////////////////////////
// Clears the LCD screen
//
void
sed1520_clear ()
{
memset (lcd.framebuf, 0, 488);
}
/////////////////////////////////////////////////////////////////
//
// Flushes all output to the lcd...
//
void
sed1520_flush ()
{
lcd.draw_frame (lcd.framebuf);
}
/////////////////////////////////////////////////////////////////
// Prints a string on the lc display, at position (x,y). The
// upper-left is (1,1), and the lower right should be (20,4).
//
void
sed1520_string (int x, int y, char string[])
{
int i;
x--; // Convert 1-based coords to 0-based...
y--;
for (i = 0; string[i]; i++)
{
drawchar2fb (x + i, y, string[i]);
}
}
/////////////////////////////////////////////////////////////////
// Writes char c at position x,y into the framebuffer.
// x and y are 1-based textmode coordinates.
//
void
sed1520_chr (int x, int y, char c)
{
y--;
x--;
drawchar2fb (x, y, c);
}
/////////////////////////////////////////////////////////////////
// This function draws a number num into the last 3 rows of the
// framebuffer at 1-based position x. It should draw a 4-row font,
// but methinks this would look a little stretched. When
// num=10 a colon is drawn.
// FIXME: make big numbers use less memory
//
void
sed1520_num (int x, int num)
{
int z, c, i, s;
x--;
if (x < 0 || x > 19 || num < 0 || num > 10)
return;
if (num != 10 && (x < 0 || x > 17))
return;
if (num == 10 && (x < 0 || x > 19))
return;
if (num == 10)
{ // Doppelpunkt
for (z = 0; z < 3; z++)
{ // Zeilen a 8 Punkte
for (c = 0; c < 6; c++)
{ // 6 Spalten
s = 0;
for (i = 0; i < 8; i++)
{ // 8 bits aus zeilen
s >>= 1;
if (*(fontbigdp[(z * 8) + i] + c) == '.')
s += 128;
}
lcd.framebuf[(z * 122) + 122 + (x * 6) + c] = s;
}
}
}
else
{
for (z = 0; z < 3; z++)
{ // Zeilen a 8 Punkte
for (c = 0; c < 18; c++)
{ // 18 Spalten
s = 0;
for (i = 0; i < 8; i++)
{ // 8 bits aus zeilen
s >>= 1;
if (*(fontbignum[num][z * 8 + i] + c) == '.')
s += 128;
}
lcd.framebuf[(z * 122) + 122 + (x * 6) + c] = s;
}
}
}
}
/////////////////////////////////////////////////////////////////
// Changes the font of character n to a pattern given by *dat.
// HD44780 Controllers only posses 8 programmable chars. But
// we store the fontmap completely in RAM, so every character
// can be altered. !Important: Characters have to be redraw
// by drawchar2fb() to show their new shape. Because we use
// a non-standard 6x8 font a *dat not calculated from
// lcd.width and lcd.height will fail.
//
void
sed1520_set_char (int n, char *dat)
{
int row, col, i;
if (n < 0 || n > 255)
return;
if (!dat)
return;
for (row = 0; row < 8; row++)
{
i = 0;
for (col = 0; col < 6; col++)
{
i <<= 1;
i |= (dat[(row * 6) + col] > 0);
}
fontmap[n][row] = i;
}
}
/////////////////////////////////////////////////////////////////
// Draws a vertical from the bottom up to the last 3 rows of the
// framebuffer at 1-based position x. len is given in pixels.
//
void
sed1520_vbar (int x, int len)
{
int i, j, k;
x--;
for (j = 0; j < 3; j++)
{
i = 0;
k = 0;
for (i = 0; i < 8; i++)
{
if (len > i)
k += 1 << (7 - i);
}
lcd.framebuf[((3 - j) * 122) + (x * 6)] = 0;
lcd.framebuf[((3 - j) * 122) + (x * 6) + 1] = 0;
lcd.framebuf[((3 - j) * 122) + (x * 6) + 2] = k;
lcd.framebuf[((3 - j) * 122) + (x * 6) + 3] = k;
lcd.framebuf[((3 - j) * 122) + (x * 6) + 4] = k;
lcd.framebuf[((3 - j) * 122) + (x * 6) + 5] = 0;
len -= 8;
}
}
/////////////////////////////////////////////////////////////////
// Draws a horizontal bar from left to right at 1-based position
// x,y into the framebuffer. len is given in pixels.
//
void
sed1520_hbar (int x, int y, int len)
{
int i;
x--;
y--;
if (y < 0 || y > 3 || x < 0 || len < 0 || (x + (len / 6)) > 19)
return;
for (i = 0; i < len; i++)
lcd.framebuf[(y * 122) + (x * 6) + i] = 0x3C;
}
/////////////////////////////////////////////////////////////////
// Reprogrammes character dest to contain an icon given by
// which. Calls set_char() to do this.
//
void
sed1520_icon (int which, char dest)
{
char icons[3][6 * 8] = {
{
1, 1, 1, 1, 1, 1, // Empty Heart
1, 0, 1, 0, 1, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1,
1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1,}
,
{
1, 1, 1, 1, 1, 1, // Filled Heart
1, 0, 1, 0, 1, 1,
0, 1, 0, 1, 0, 1,
0, 1, 1, 1, 0, 1,
0, 1, 1, 1, 0, 1,
1, 0, 1, 0, 1, 1,
1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1,}
,
{
0, 0, 0, 0, 0, 0, // Ellipsis
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 1, 0, 1, 0,}
,
};
sed1520_set_char (dest, &icons[which][0]);
}
/////////////////////////////////////////////////////////////////
// Send a rectangular area from lft,top to rgt,bot to the display
// These coordinates are probably one-based, too. It's so fast to
// flush the whole display that it makes no sense to flush less then
// the whole display. Therefore this function redraws the whole
// display.
// FIXME: Check if this function is worth implementing.
//
void
sed1520_flush_box (int lft, int top, int rgt, int bot)
{
sed1520_flush ();
}
/////////////////////////////////////////////////////////////////
// Outputs the whole framebuffer *dat to the display. This Display
// contains 2 Controllers, each of them controlling one half of the
// screen.
//
void
sed1520_draw_frame (char *dat)
{
int i, j;
if (!dat)
return;
for (i = 0; i < 4; i++)
{
selectpage (i);
selectcolumn (0, CS2) ;
for (j = 0; j < 61; j++)
writedata (dat[j + (i * 122)], CS2);
selectcolumn (0, CS1) ;
for (j = 61; j < 122; j++)
writedata (dat[j + (i * 122)], CS1);
}
}
/////////////////////////////////////////////////////////////////
// This function delays a legth given by delayCalls
// x 10 Nanoseconds
//
void
uPause (int delayCalls)
{
struct timespec delay, remaining;
delay.tv_sec = 0;
delay.tv_nsec = delayCalls * 10;
while (nanosleep (&delay, &remaining) == -1)
{
delay.tv_sec = remaining.tv_sec;
delay.tv_nsec = remaining.tv_nsec;
}
}
+20
View File
@@ -0,0 +1,20 @@
#ifndef SED1520_H
#define SED1520_H
extern lcd_logical_driver *sed1520;
int sed1520_init (struct lcd_logical_driver *driver, char *args);
void sed1520_close ();
void sed1520_clear ();
void sed1520_flush ();
void sed1520_string (int x, int y, char string[]);
void sed1520_chr (int x, int y, char c);
void sed1520_vbar (int x, int len);
void sed1520_hbar (int x, int y, int len);
void sed1520_num (int x, int num);
void sed1520_set_char (int n, char *dat);
void sed1520_icon (int which, char dest);
void sed1520_flush_box (int lft, int top, int rgt, int bot);
void sed1520_draw_frame (char *dat);
#endif
File diff suppressed because it is too large Load Diff
+725
View File
@@ -0,0 +1,725 @@
//////////////////////////////////////////////////////////////////////////
// This is a driver for the STV5730A on-screen display chip in con- //
// junction with a parallel port interface. Check //
// www.adams-online.de/lcd/stv5730.html for where to buy //
// and how to build the hardware. //
// The STV3730 displays 11 rows with 28 characters. The characters are //
// fixed and can not be reprogrammed. Luckily the chraracter set con- //
// tains a heartbeat icon and some characters that can be used as //
// hbars / vbars. //
// //
// (C) 2001 Robin Adams ( robin@adams-online.de ) //
// //
// This driver is released under the GPL. See file COPYING in this //
// package for further details. //
//////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/errno.h>
#include <sys/io.h>
#include <sched.h>
#include <time.h>
#include "port.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "shared/str.h"
#include "lcd.h"
#include "stv5730.h"
#ifndef LPTPORT
#define LPTPORT 0x378
#endif
#define STV5730_TEST_O 0x01
#define STV5730_BAR 0x02
#define STV5730_CLK 0x04
#define STV5730_CSN 0x08
#define STV5730_DATA 0x10
#define STV5730_TEST_I 0x40
#define STV5730_MUTE 0x80
// If it doesn't work try increasing this value
#define IODELAY 400
// Change that to NTSC if you are from the US...
#define PAL
#define STV5730_HGT 11
#define STV5730_WID 28
#define STV5730_ATTRIB 0x800
#define STV5730_REG_ZOOM 0xCC
#define STV5730_REG_COLOR 0xCD
#define STV5730_REG_CONTROL 0xCE
#define STV5730_REG_POSITION 0xCF
#define STV5730_REG_MODE 0xD0
// Choose Colors: FLINE: First line text color, TEXT: Text color, CBACK: Character Background Color
// CBORD: Character Border Color, SBACK: Screen Background color
// 0:Black, 1: Blue, 2:Green, 3: Cyan, 4: Red, 5: Magenta, 6: Yellow, 7: White
#define STV5730_COL_FLINE 4
#define STV5730_COL_TEXT 1
#define STV5730_COL_CBACK 3
#define STV5730_COL_CBORD 0
#define STV5730_COL_SBACK 2
unsigned int stv5730_lptport = LPTPORT;
unsigned int stv5730_charattrib = STV5730_ATTRIB;
unsigned int stv5730_flags = 0;
// Translation map ascii->stv5730 charset
unsigned char stv5730_to_ascii[256] =
{ 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x27, 0x0B, 0x27, 0x28,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x26, 0x26,
0x62, 0x78, 0x61, 0x70,
0x6c, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, 0x1A,
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x0B,
0x0B, 0x0B, 0x0B, 0x72,
0x0B, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35, 0x36, 0x37, 0x38,
0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x6E,
0x6C, 0x71, 0x79, 0x7F,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x77
};
lcd_logical_driver *stv5730;
static void stv5730_upause (int delayCalls);
/////////////////////////////////////////////////////////////////
// This function returns true if a powered and working STV5730
// hardware is present at stv5730_lptport
int
stv5730_detect (void)
{
int i;
for (i = 0; i < 10; i++)
{
port_out (stv5730_lptport, STV5730_TEST_O);
stv5730_upause (IODELAY);
if ((port_in (stv5730_lptport + 1) & STV5730_TEST_I) == 0)
return -1;
port_out (stv5730_lptport, 0);
stv5730_upause (IODELAY);
if ((port_in (stv5730_lptport + 1) & STV5730_TEST_I) != 0)
return -1;
}
return 0;
}
/////////////////////////////////////////////////////////////////
// returns 0 if a valid video signal is connected to the video
// input
int
stv5730_is_mute (void)
{
stv5730_upause (IODELAY);
return ((port_in (stv5730_lptport + 1) & STV5730_MUTE) ? 0 : 1);
}
/////////////////////////////////////////////////////////////////
// stv5730_write16bit, stv5730_write8bit, stv5730_write0bit
// this family of functions write commands or data to the stv5730
// 8 bit writes repeat the high byte, 0 byte writes repeat the last
// written word
void
stv5730_write16bit (unsigned int value)
{
char i, databit;
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CLK + stv5730_flags);
for (i = 15; i >= 0; i--)
{
(value & (1 << i)) != 0 ? (databit = STV5730_DATA) : (databit = 0);
port_out (stv5730_lptport, databit + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, databit + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, databit + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
}
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + stv5730_flags);
stv5730_upause (IODELAY);
}
void
stv5730_write8bit (unsigned int value)
{
char i, databit;
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CLK + stv5730_flags);
for (i = 7; i >= 0; i--)
{
(value & (1 << i)) != 0 ? (databit = STV5730_DATA) : (databit = 0);
port_out (stv5730_lptport, databit + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, databit + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, databit + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
}
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + stv5730_flags);
}
void
stv5730_write0bit (void)
{
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + STV5730_CLK + stv5730_flags);
stv5730_upause (IODELAY);
port_out (stv5730_lptport, STV5730_CSN + stv5730_flags);
}
/////////////////////////////////////////////////////////////////
// sets the memory pointer inside the stv5730 to the position
// row, col.
void
stv5730_locate (int row, int col)
{
if (row < 0 || row >= STV5730_HGT || col < 0 || col >= STV5730_WID)
return;
stv5730_write16bit ((row << 8) + col);
}
/////////////////////////////////////////////////////////////////
// draws char z from fontmap to the framebuffer at position
// x,y. These are zero-based textmode positions.
// We need a conversion map to translate from ascii to the
// non-standard STV5730 charset.
//
void
stv5730_drawchar2fb (int x, int y, unsigned char z)
{
if (x < 0 || x >= STV5730_WID || y < 0 || y >= STV5730_HGT)
return;
lcd.framebuf[(y * STV5730_WID) + x] = stv5730_to_ascii[(unsigned int) z];
}
/////////////////////////////////////////////////////////////////
// This initialises the stuff. We support supplying port as
// a command line argument.
//
int
stv5730_init (struct lcd_logical_driver *driver, char *args)
{
char *argv[64], *str;
int argc, i;
stv5730 = driver;
if (args)
if ((str = (char *) malloc (strlen (args) + 1)))
strcpy (str, args);
else
{
fprintf (stderr, "Error mallocing\n");
return -1;
}
else
str = NULL;
argc = get_args (argv, args, 64);
for (i = 0; i < argc; i++)
{
if (0 == strcmp (argv[i], "-p")
|| 0 == strcmp (argv[i], "--port\0"))
{
if (i + 1 >= argc)
{
fprintf (stderr,
"stv5730_init: %s requires an argument\n",
argv[i]);
return -1;
}
else
{
int myport;
if (sscanf (argv[i + 1], "%i", &myport) != 1)
{
fprintf (stderr,
"stv5730_init: Couldn't read port address -"
" using default value 0x%x\n",
stv5730_lptport);
return -1;
}
else
{
stv5730_lptport = myport;
++i;
}
}
}
else if (0 == strcmp (argv[i], "-h")
|| 0 == strcmp (argv[i], "--help"))
{
int i;
printf
("LCDproc stv5730 driver\n\t-p n\t--port n\tSelect the output device to use port n\n");
printf ("put the options in quotes like this: '-p 0x278'\n");
printf ("\t-h\t--help\t\tShow this help information\n");
return -1;
}
}
driver->wid = STV5730_WID;
driver->hgt = STV5730_HGT;
{
struct sched_param param;
param.sched_priority = 1;
if ((sched_setscheduler (0, SCHED_RR, &param)) == -1)
{
fprintf (stderr, "stv5730_init: failed (%s)\n",
strerror (errno));
return -1;
}
}
// Initialize the Port and the stv5730
if (port_access (stv5730_lptport) || port_access (stv5730_lptport + 1))
{
printf
("Couldn't get IO-permission for 0x%X ! Are we running as root ?\n ",
stv5730_lptport); return -1;
};
if (stv5730_detect ())
{
printf ("No STV5730 hardware found at 0x%X !\n ", stv5730_lptport);
return -1;
};
port_out (stv5730_lptport, 0);
// Reset the STV5730
stv5730_write16bit (0x3000);
stv5730_write16bit (0x3000);
stv5730_write16bit (0x00db);
stv5730_write16bit (0x1000);
// Setup Mode + Control Register for video detection
stv5730_write16bit (STV5730_REG_MODE);
stv5730_write16bit (0x1576);
stv5730_write16bit (STV5730_REG_CONTROL);
stv5730_write16bit (0x1FF4);
printf ("Detecting Video Signal: ");
usleep (50000);
if (stv5730_is_mute ())
{
printf ("No Video Signal found, using full page mode.\n");
// Setup Mode + Control for full page mode
stv5730_charattrib = STV5730_ATTRIB;
stv5730_write16bit (STV5730_REG_MODE);
stv5730_write16bit (0x15A6);
stv5730_write16bit (STV5730_REG_CONTROL);
#ifdef PAL
stv5730_write16bit (0x1FD5);
#endif
#ifdef NTSC
stv5730_write16bit (0x1ED4);
#endif
}
else
{
printf ("Video Signal found, using mixed mode (B&W).\n");
// Setup Mode + Control for mixed mode, disable color
stv5730_charattrib = 0;
stv5730_write16bit (STV5730_REG_MODE);
stv5730_write16bit (0x1576);
stv5730_write16bit (STV5730_REG_CONTROL);
#ifdef PAL
stv5730_write16bit (0x1DD4);
#endif
#ifdef NTSC
stv5730_write16bit (0x1CF4);
#endif
}
// Position Register
stv5730_write16bit (STV5730_REG_POSITION);
stv5730_write16bit (0x1000 + 64 * 30 + 30);
// Color Register
stv5730_write16bit (STV5730_REG_COLOR);
stv5730_write16bit (0x1000 + (STV5730_COL_SBACK << 9) +
(STV5730_COL_CBORD << 6) + STV5730_COL_CBACK);
// Zoom Register: Zoom first line
stv5730_write16bit (STV5730_REG_ZOOM);
stv5730_write16bit (0x1000 + 4);
// Set the Row Attributes
for (i = 0; i <= 10; i++)
{
stv5730_write16bit (0x00C0 + i);
stv5730_write16bit (0x10C0);
}
// The Framebuffer LCDproc allocates by default is too small,
// so we free() it and allocate one of adequate size.
if (!driver->framebuf)
free (driver->framebuf);
driver->framebuf = malloc (STV5730_WID * STV5730_HGT);
if (!driver->framebuf)
{
stv5730_close ();
return -1;
}
// clear screen
memset (driver->framebuf, 0, STV5730_WID * STV5730_HGT);
driver->cellwid = 4;
driver->cellhgt = 6; // FIXME: lcd.cellwid always stays 5
// regardless what it is set to here. This is
// a bug but not inside this driver.
driver->clear = stv5730_clear;
driver->string = stv5730_string;
driver->chr = stv5730_chr;
driver->vbar = stv5730_vbar;
driver->hbar = stv5730_hbar;
driver->num = stv5730_num;
driver->init = stv5730_init;
driver->close = stv5730_close;
driver->flush = stv5730_flush;
driver->flush_box = stv5730_flush_box;
// We dont't have any programmable chars.
driver->set_char = NULL;
driver->icon = stv5730_icon;
driver->draw_frame = stv5730_draw_frame;
// We dont't need init for vbar,hbar and friends.
driver->init_hbar = NULL;
driver->init_vbar = NULL;
driver->init_num = NULL;
// Neither contrast nor backlight are controllable.
driver->contrast = NULL;
driver->backlight = NULL;
// There are some unused input lines that may be used for input,
// but nothing is programmed so far.
driver->getkey = NULL;
return 200; // 200 is arbitrary. (must be 1 or more)
}
/////////////////////////////////////////////////////////////////
// Frees the framebuffer and exits the driver.
//
void
stv5730_close ()
{
if (lcd.framebuf != NULL)
free (lcd.framebuf);
lcd.framebuf = NULL;
}
/////////////////////////////////////////////////////////////////
// Clears the screen
//
void
stv5730_clear ()
{
memset (lcd.framebuf, 0x0B, STV5730_WID * STV5730_HGT);
}
/////////////////////////////////////////////////////////////////
//
// Flushes all output to the lcd...
//
void
stv5730_flush ()
{
lcd.draw_frame (lcd.framebuf);
}
/////////////////////////////////////////////////////////////////
// Prints a string on the screen, at position (x,y). The
// upper-left is (1,1), and the lower right should be (28,11).
//
void
stv5730_string (int x, int y, char string[])
{
int i;
x--; // Convert 1-based coords to 0-based...
y--;
for (i = 0; string[i]; i++)
{
stv5730_drawchar2fb (x + i, y, string[i]);
}
}
/////////////////////////////////////////////////////////////////
// Writes char c at position x,y into the framebuffer.
// x and y are 1-based textmode coordinates.
//
void
stv5730_chr (int x, int y, char c)
{
y--;
x--;
stv5730_drawchar2fb (x, y, c);
}
/////////////////////////////////////////////////////////////////
// This function draws ugly big numbers. We could use the zoom
// feature of the stv5730 if we'd know when big numbers start
// and stop.
void
stv5730_num (int x, int num)
{
int i, j;
x--;
if (x < 0 || x > 19 || num < 0 || num > 10)
return;
if (num != 10 && (x < 0 || x > 17))
return;
if (num == 10 && (x < 0 || x > 19))
return;
for (j = 1; j < 10; j++)
{
if (num != 10)
{
for (i = 0; i < 3; i++)
stv5730_drawchar2fb (x + i, j, '0' + num);
}
else
{
stv5730_drawchar2fb (x, j, ':');
}
}
}
/////////////////////////////////////////////////////////////////
// Draws a vertical bar from the bottom up to the last 7 rows of the
// framebuffer at 1-based position x. len is given in pixels.
//
void
stv5730_vbar (int x, int len)
{
int i;
x--;
if (x < 0 || len < 0 || (len / 6) >= STV5730_WID)
return;
for (i = 0; i <= len; i += 6)
{
if (len >= (i + 6))
{
lcd.framebuf[((10 - (i / 6)) * STV5730_WID) + x] = 0x77;
}
else
{
lcd.framebuf[((10 - (i / 6)) * STV5730_WID) + x] =
0x72 + (len % 6);
}
}
}
/////////////////////////////////////////////////////////////////
// Draws a horizontal bar from left to right at 1-based position
// x,y into the framebuffer. len is given in pixels.
// It uses the STV5730 'channel-tuning' chars(0x64-0x68) to do
// this.
void
stv5730_hbar (int x, int y, int len)
{
int i;
x--;
y--;
if (y < 0 || y >= STV5730_HGT || x < 0 || len < 0
|| (x + (len / 5)) >= STV5730_WID)
return;
for (i = 0; i <= len; i += 5)
{
if (len >= (i + 4))
{
lcd.framebuf[(y * STV5730_WID) + x + (i / 5)] = 0x64;
}
else
{
lcd.framebuf[(y * STV5730_WID) + x + (i / 5)] =
0x65 + (len % 5);
}
}
}
/////////////////////////////////////////////////////////////////
// Reprogrammes character dest to contain an icon given by
// which.
// The STV5730 has no programmable chars. The charset is very
// limited, it doesn't even contain a '%' char. But wait...
// It contains a heartbeat char ! :-)
void
stv5730_icon (int which, char dest)
{
switch (which)
{
case 0: // 0:empty Heart
stv5730_to_ascii[(int) dest] = 0x71;
break;
case 1: // 1:Filled Heart
stv5730_to_ascii[(int) dest] = 0x0B;
break;
case 2: // 2:Ellipsis
stv5730_to_ascii[(int) dest] = 0x5F;
break;
default:
stv5730_to_ascii[(int) dest] = 0x0B;
break;
}
}
/////////////////////////////////////////////////////////////////
// Send a rectangular area from lft,top to rgt,bot to the display
// These coordinates are probably one-based, too. It's so fast to
// flush the whole display that it makes no sense to flush less then
// the whole display. Therefore this function redraws the whole
// display.
// FIXME: Check if this function is worth implementing.
//
void
stv5730_flush_box (int lft, int top, int rgt, int bot)
{
stv5730_flush ();
}
/////////////////////////////////////////////////////////////////
// Outputs the whole framebuffer *dat to the display.
// Attributes are set for every row only.
// The first line has special attributes.
void
stv5730_draw_frame (char *dat)
{
int i, j, atr;
if (!dat)
return;
stv5730_locate (0, 0);
for (i = 0; i < STV5730_HGT; i++)
{
if (i == 0)
atr = (STV5730_COL_FLINE << 8);
else
atr = (STV5730_COL_TEXT << 8);
stv5730_write16bit (0x1000 + atr + dat[i * STV5730_WID] +
stv5730_charattrib);
for (j = 1; j < STV5730_WID; j++)
{
if (dat[j + (i * STV5730_WID) - 1] !=
dat[j + (i * STV5730_WID)])
stv5730_write8bit (dat[j + (i * STV5730_WID)]);
else
stv5730_write0bit ();
};
}
}
/////////////////////////////////////////////////////////////////
// This function delays a legth given by delayCalls
// x 10 Nanoseconds
//
void
stv5730_upause (int delayCalls)
{
struct timespec delay, remaining;
delay.tv_sec = 0;
delay.tv_nsec = delayCalls * 10;
while (nanosleep (&delay, &remaining) == -1)
{
delay.tv_sec = remaining.tv_sec;
delay.tv_nsec = remaining.tv_nsec;
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef STV5730_H
#define STV5730_H
extern lcd_logical_driver *stv5730;
int stv5730_init (struct lcd_logical_driver *driver, char *args);
void stv5730_close ();
void stv5730_clear ();
void stv5730_flush ();
void stv5730_string (int x, int y, char string[]);
void stv5730_chr (int x, int y, char c);
void stv5730_vbar (int x, int len);
void stv5730_hbar (int x, int y, int len);
void stv5730_num (int x, int num);
void stv5730_icon (int which, char dest);
void stv5730_flush_box (int lft, int top, int rgt, int bot);
void stv5730_draw_frame (char *dat);
#endif
+1 -1
View File
@@ -111,7 +111,7 @@ draw_screen (screen * s, int timer)
lcd.output (output_state);
// Draw a frame...
draw_frame (s->widgets, 'v', 0, 0, lcd.wid, lcd.hgt, s->wid, s->hgt, s->duration / s->hgt, timer);
draw_frame (s->widgets, 'v', 0, 0, lcd.wid, lcd.hgt, s->wid, s->hgt, (((s->duration / s->hgt) < 1) ? 1 : (s->duration / s->hgt)), timer);
//debug("draw_screen done\n");