Files
lcdproc/server/drivers/wirz-sli.c
T

542 lines
12 KiB
C
Raw Normal View History

1999-12-09 23:15:14 +00:00
/* wirz-sli.c -- Source file for LCDproc Wirz SLI driver
Copyright (C) 1999 Horizon Technologies-http://horizon.pair.com/
Written by Bryan Rittmeyer <bryanr@pair.com> - Released under GPL
2001-12-30 00:15:25 +00:00
LCD info: http://www.wirz.com/ */
1999-12-09 23:15:14 +00:00
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
1999-12-09 23:15:14 +00:00
#include "lcd.h"
#include "wirz-sli.h"
2001-12-30 00:15:25 +00:00
//#include "drv_base.h"
2005-01-29 18:49:29 +00:00
#include "report.h"
1999-12-09 23:15:14 +00:00
#include "shared/debug.h"
#include "shared/str.h"
1999-12-09 23:15:14 +00:00
2005-01-29 18:49:29 +00:00
#define SLI_DEFAULT_DEVICE "/dev/lcd"
static int custom = 0;
1999-12-09 23:15:14 +00:00
typedef enum {
2000-04-03 22:13:57 +00:00
hbar = 1,
vbar = 2,
bign = 4,
beat = 8
} custom_type;
1999-12-09 23:15:14 +00:00
static int fd;
2001-12-30 00:15:25 +00:00
static char *framebuf = NULL;
static int width = 0;
static int height = 0;
static int cellwidth = LCD_DEFAULT_CELLWIDTH;
static int cellheight = LCD_DEFAULT_CELLHEIGHT;
2001-12-30 00:15:25 +00:00
// Vars for the server core
MODULE_EXPORT char *api_version = API_VERSION;
MODULE_EXPORT int stay_in_foreground = 0;
MODULE_EXPORT int supports_multiple = 0;
MODULE_EXPORT char *symbol_prefix = "sli_";
1999-12-09 23:15:14 +00:00
/////////////////////////////////////////////////////////////////
// Opens com port and sets baud correctly...
//
2002-02-21 22:50:12 +00:00
MODULE_EXPORT int
sli_init (Driver *drvthis)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
struct termios portset;
char out[2];
1999-12-09 23:15:14 +00:00
2005-01-29 18:49:29 +00:00
char device[256] = WIRZ_DEFAULT_DEVICE;
2000-04-03 22:13:57 +00:00
int speed = B19200;
2005-01-29 18:49:29 +00:00
/* Read config file */
2005-01-29 18:49:29 +00:00
/* What device should be used */
strncpy(device, drvthis->config_get_string(drvthis->name, "Device", 0,
SLI_DEFAULT_DEVICE), sizeof(device));
device[sizeof(device)-1] = '\0';
2005-01-29 18:49:29 +00:00
/* What speed to use */
speed = drvthis->config_get_int(drvthis->name, "Speed", 0, 19200);
if (speed == 1200) speed = B1200;
else if (speed == 2400) speed = B2400;
else if (speed == 9600) speed = B9600;
else if (speed == 19200) speed = B19200;
else if (speed == 38400) speed = B38400;
else if (speed == 57600) speed = B57600;
else if (speed == 115200) speed = B115200;
else {
report(RPT_WARNING, "sli: Illegal speed: %d. Must be one of 1200, 2400, 9600, 19200, 38400, 57600, or 115200. Using default.\n", speed);
speed = B19200;
2000-04-03 22:13:57 +00:00
}
2005-01-29 18:49:29 +00:00
/* End of config file parsing */
2000-04-03 22:13:57 +00:00
// Set up io port correctly, and open it...
fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
2005-01-29 18:49:29 +00:00
report(RPT_ERR, "sli_init: open(%s) failed (%s)\n", device, strerror (errno));
2000-04-03 22:13:57 +00:00
return -1;
}
2005-01-29 18:49:29 +00:00
report(RPT_DEBUG, "sli_init: opened device %s\n", device);
2000-04-03 22:13:57 +00:00
tcgetattr (fd, &portset);
// We use RAW mode
#ifdef HAVE_CFMAKERAW
// The easy way
cfmakeraw( &portset );
#else
// The hard way
portset.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON );
portset.c_oflag &= ~OPOST;
portset.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
portset.c_cflag &= ~( CSIZE | PARENB | CRTSCTS );
portset.c_cflag |= CS8 | CREAD | CLOCAL ;
1999-12-09 23:15:14 +00:00
#endif
// Set port speed
2000-04-03 22:13:57 +00:00
cfsetospeed (&portset, speed);
cfsetispeed (&portset, B0);
// Do it...
2000-04-03 22:13:57 +00:00
tcsetattr (fd, TCSANOW, &portset);
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
/* Initialize SLI using autobaud detection, and then turn off cursor
2000-04-03 22:13:57 +00:00
and clear screen */
2005-01-29 18:49:29 +00:00
usleep (150000); /* 150ms delay to allow SLI to power on */
out[0] = 13; /* CR for SLI autobaud */
2000-04-03 22:13:57 +00:00
write (fd, out, 1);
2005-01-29 18:49:29 +00:00
usleep (3000); /* 3ms delay.. wait for it to autobaud */
2000-04-03 22:13:57 +00:00
out[0] = 0x0FE;
out[1] = 0x00C; /* No cursor */
write (fd, out, 2);
out[0] = 0x0FE;
out[1] = 0x001; /* Clear LCD, not sure if this belongs here */
write (fd, out, 2);
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
// Set LCD parameters (I use a 16x2 LCD) -- small but still useful
// Its also much cheaper than the higher quality Matrix Orbital modules
// Currently, $30 for interface kit and 16x2 non-backlit LCD...
2001-12-30 00:15:25 +00:00
width = 15;
height = 2;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
return fd;
1999-12-09 23:15:14 +00:00
}
2001-12-30 00:15:25 +00:00
/////////////////////////////////////////////////////////////////
// Clean up
//
MODULE_EXPORT void
sli_close (Driver *drvthis)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
close (fd);
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
if (framebuf)
free (framebuf);
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
framebuf = NULL;
1999-12-09 23:15:14 +00:00
}
2001-12-30 00:15:25 +00:00
/////////////////////////////////////////////////////////////////
// Returns the display width
//
MODULE_EXPORT int
sli_width (Driver *drvthis)
1999-12-09 23:15:14 +00:00
{
2001-12-30 00:15:25 +00:00
return width;
1999-12-09 23:15:14 +00:00
}
2001-12-30 00:15:25 +00:00
/////////////////////////////////////////////////////////////////
// Returns the display height
//
MODULE_EXPORT int
sli_height (Driver *drvthis)
1999-12-09 23:15:14 +00:00
{
2001-12-30 00:15:25 +00:00
return height;
}
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
/////////////////////////////////////////////////////////////////
// Flush framebuffer to LCD
//
MODULE_EXPORT void
sli_flush (Driver *drvthis)
{
char out[2]; /* Again, why does the Matrix driver allocate so much here? */
2001-12-30 00:15:25 +00:00
/*
out[0]=0x0FE;
out[1]=0x001;
write(fd, out, 2);
*/
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
/* Don't update if we have no new data
this keeps me from getting a migraine
(just like those copyleft penguin mints... mmmmmm) */
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
// if (!strncmp(dat,lastframe,32)) /* Nothing has changed */
// return;
2001-12-30 00:15:25 +00:00
/* Do the actual refresh */
out[0] = 0x0FE;
out[1] = 0x080;
write (fd, out, 2);
write (fd, &framebuf[0], 16);
usleep (10);
write (fd, &framebuf[16], 15);
// strncpy(lastframe,dat,32); // Update lastframe...
1999-12-09 23:15:14 +00:00
}
2001-09-25 17:26:25 +00:00
/////////////////////////////////////////////////////////////////
// Clears the LCD screen
//
2001-12-30 00:15:25 +00:00
MODULE_EXPORT void
sli_clear (Driver *drvthis)
2001-09-25 17:26:25 +00:00
{
2001-12-30 00:15:25 +00:00
memset (framebuf, ' ', width * height);
2001-09-25 17:26:25 +00:00
}
/////////////////////////////////////////////////////////////////
// Prints a string on the lcd display, at position (x,y). The
// upper-left is (1,1), and the lower right should be (20,4).
//
2001-12-30 00:15:25 +00:00
MODULE_EXPORT void
sli_string (Driver *drvthis, int x, int y, char string[])
2001-09-25 17:26:25 +00:00
{
int i;
x -= 1; // Convert 1-based coords to 0-based...
y -= 1;
for (i = 0; string[i]; i++) {
// Check for buffer overflows...
2001-12-30 00:15:25 +00:00
if ((y * width) + x + i > (width * height))
2001-09-25 17:26:25 +00:00
break;
2001-12-30 00:15:25 +00:00
framebuf[(y * width) + x + i] = string[i];
2001-09-25 17:26:25 +00:00
}
}
1999-12-09 23:15:14 +00:00
/////////////////////////////////////////////////////////////////
// Prints a character on the lcd display, at position (x,y). The
// upper-left is (1,1), and the lower right should be (20,4).
//
2001-12-30 00:15:25 +00:00
MODULE_EXPORT void
sli_chr (Driver *drvthis, int x, int y, char c)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
y--;
x--;
2001-12-30 00:15:25 +00:00
framebuf[(y * width) + x] = c;
2001-09-25 17:26:25 +00:00
}
/////////////////////////////////////////////////////////////////
// Sets up for vertical bars. Call before sli->vbar()
1999-12-09 23:15:14 +00:00
//
/* Because of the way we do this (custom characters in CGRAM)
we can't have both horizontal and vertical bars at once...
this also appears to be a limitation of the Matrix Orbital
2001-12-30 00:15:25 +00:00
modules so I will assume that all client coders know about it
1999-12-09 23:15:14 +00:00
I think it would be cool to use triangular stuff for the non-full
2001-12-30 00:15:25 +00:00
characters, so that you can do both bar types at once.. maybe I
1999-12-09 23:15:14 +00:00
will release a new version of the SLI driver that attempts this */
static void
2001-12-30 00:15:25 +00:00
sli_init_vbar (Driver *drvthis)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
char a[] = {
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, 1, 1, 1, 1,
};
char b[] = {
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, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
char c[] = {
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, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
char d[] = {
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
char e[] = {
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
char f[] = {
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
char g[] = {
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (custom != vbar) {
2001-12-30 00:15:25 +00:00
sli_set_char (drvthis, 1, a);
sli_set_char (drvthis, 2, b);
sli_set_char (drvthis, 3, c);
sli_set_char (drvthis, 4, d);
sli_set_char (drvthis, 5, e);
sli_set_char (drvthis, 6, f);
sli_set_char (drvthis, 7, g);
2000-04-03 22:13:57 +00:00
custom = vbar;
}
1999-12-09 23:15:14 +00:00
}
/////////////////////////////////////////////////////////////////
// Inits horizontal bars...
//
static void
2001-12-30 00:15:25 +00:00
sli_init_hbar (Driver *drvthis)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
char a[] = {
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
1, 0, 0, 0, 0,
};
char b[] = {
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
1, 1, 0, 0, 0,
};
char c[] = {
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
1, 1, 1, 0, 0,
};
char d[] = {
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
1, 1, 1, 1, 0,
};
char e[] = {
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
};
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
if (custom != hbar) {
2001-12-30 00:15:25 +00:00
sli_set_char (drvthis, 1, a);
sli_set_char (drvthis, 2, b);
sli_set_char (drvthis, 3, c);
sli_set_char (drvthis, 4, d);
sli_set_char (drvthis, 5, e);
2000-04-03 22:13:57 +00:00
custom = hbar;
}
1999-12-09 23:15:14 +00:00
}
/////////////////////////////////////////////////////////////////
// Draws a vertical bar...
//
/* It would be cool if you could start a vertical bar at any y
like the horizontal bar routine can start at any x... but
since we only have 2 lines anyway this is rather pointless
for me to add */
2001-12-30 00:15:25 +00:00
MODULE_EXPORT void
sli_vbar (Driver *drvthis, int x, int y, int len, int promille, int options)
1999-12-09 23:15:14 +00:00
{
sli_init_vbar(drvthis);
lib_vbar_static(drvthis, x, y, len, promille, options, cellheight, 0);
1999-12-09 23:15:14 +00:00
}
/////////////////////////////////////////////////////////////////
// Draws a horizontal bar to the right.
//
2001-12-30 00:15:25 +00:00
MODULE_EXPORT void
sli_hbar (Driver *drvthis, int x, int y, int len, int promille, int options)
1999-12-09 23:15:14 +00:00
{
sli_init_hbar(drvthis);
1999-12-09 23:15:14 +00:00
lib_hbar_static(drvthis, x, y, len, promille, options, cellwidth, 0);
1999-12-09 23:15:14 +00:00
}
/////////////////////////////////////////////////////////////////
// Sets a custom character from 0-7...
//
// For input, values > 0 mean "on" and values <= 0 are "off".
//
// The input is just an array of characters...
//
2001-12-30 00:15:25 +00:00
MODULE_EXPORT void
sli_set_char (Driver *drvthis, int n, char *dat)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
char out[2];
int row, col;
int letter;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
/* SLI also has 8 user definable characters */
if (n < 0 || n > 7)
return;
if (!dat)
return;
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
/* Move cursor to CGRAM */
out[0] = 0x0FE;
out[1] = 0x040 + 8 * n;
write (fd, out, 2);
1999-12-09 23:15:14 +00:00
2001-12-30 00:15:25 +00:00
for (row = 0; row < LCD_DEFAULT_CELLHEIGHT; row++) {
2000-04-03 22:13:57 +00:00
letter = 0;
2001-12-30 00:15:25 +00:00
for (col = 0; col < LCD_DEFAULT_CELLWIDTH; col++) {
2000-04-03 22:13:57 +00:00
letter <<= 1;
2001-12-30 00:15:25 +00:00
letter |= (dat[(row * LCD_DEFAULT_CELLWIDTH) + col] > 0);
2000-04-03 22:13:57 +00:00
}
letter |= 0x020; /* SLI can't accept CR, LF, etc in this character! */
write (fd, &letter, 1);
}
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
/* Move cursor back to DDRAM */
out[0] = 0x0FE;
out[1] = 0x080;
write (fd, out, 2);
1999-12-09 23:15:14 +00:00
}
MODULE_EXPORT int
sli_icon (Driver *drvthis, int x, int y, int icon)
1999-12-09 23:15:14 +00:00
{
2000-04-03 22:13:57 +00:00
char icons[3][5 * 8] = {
{
1, 1, 1, 1, 1, // Empty Heart
1, 0, 1, 0, 1,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 0, 0, 0, 1,
1, 1, 0, 1, 1,
1, 1, 1, 1, 1,
},
1999-12-09 23:15:14 +00:00
2000-04-03 22:13:57 +00:00
{
1, 1, 1, 1, 1, // Filled Heart
1, 0, 1, 0, 1,
0, 1, 0, 1, 0,
0, 1, 1, 1, 0,
0, 1, 1, 1, 0,
1, 0, 1, 0, 1,
1, 1, 0, 1, 1,
1, 1, 1, 1, 1,
},
2000-04-03 22:13:57 +00:00
{
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,
1, 0, 1, 0, 1,
},
2000-04-03 22:13:57 +00:00
};
2000-04-03 22:13:57 +00:00
if (custom == bign)
custom = beat;
2002-05-23 18:03:36 +00:00
switch( icon ) {
case ICON_BLOCK_FILLED:
CFontz_chr( drvthis, x, y, 255 );
break;
case ICON_HEART_FILLED:
CFontz_set_char( drvthis, 0, icons[1] );
CFontz_chr( drvthis, x, y, 0 );
break;
case ICON_HEART_OPEN:
CFontz_set_char( drvthis, 0, icons[0] );
CFontz_chr( drvthis, x, y, 0 );
break;
default:
return -1;
}
return 0;
1999-12-09 23:15:14 +00:00
}