From 4219160d033cecc4d4b19077772295a49f653798 Mon Sep 17 00:00:00 2001 From: marschap Date: Tue, 29 Nov 2005 20:45:15 +0000 Subject: [PATCH] add driver for Tyan barebones --- LCDd.conf | 16 + acinclude.m4 | 8 +- server/drivers/Makefile.am | 3 +- server/drivers/tyan_lcdm.c | 855 +++++++++++++++++++++++++++++++++++++ server/drivers/tyan_lcdm.h | 49 +++ 5 files changed, 928 insertions(+), 3 deletions(-) create mode 100644 server/drivers/tyan_lcdm.c create mode 100644 server/drivers/tyan_lcdm.h diff --git a/LCDd.conf b/LCDd.conf index f25ee3b..4fef84f 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -585,6 +585,20 @@ Port=0x378 +## Tyan Barebones LCD driver (GS series; others too?) ## +[tyan] + +# Select the output device to use [default: /dev/lcd] +Device=/dev/lcd + +# Set the communication speed [default: 9600; legal: 4800, 9600] +Speed=19200 + +# set display size [default: 16x2] +Size=160x2 + + + ## Wirz SLI LCD driver ## [Wirz-sli] @@ -644,6 +658,7 @@ PixelShiftX=0 PixelshiftY=2 + ## Soundgraph/Ahanix/Silverstone/Uneed/Accent iMON driver ## [imon] @@ -651,6 +666,7 @@ Size=16x2 Device=/dev/lcd0 + ## OnScreen Display using libxosd ## [xosd] diff --git a/acinclude.m4 b/acinclude.m4 index cb16be4..d87e84b 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -9,14 +9,14 @@ AC_ARG_ENABLE(drivers, [ hd44780,joy,irman,lirc,bayrad,glk,mtc_s16209x] [ stv5730,sed1330,sed1520,svga,lcdm001,t6963] [ lcterm,icp_a106,ms6931,iowarrior,glcdlib,imon,xosd,] - [ noritakevfd] + [ noritakevfd,tyan] [ \"all\" compiles all drivers], drivers="$enableval", drivers=[lcdm001,mtxorb,cfontz,cfontz633,curses,cwlnx,text,lb216,bayrad,glk]) if test "$drivers" = "all"; then -drivers=[mtxorb,cfontz,cfontz633,curses,cwlnx,text,lb216,mtc_s16209x,hd44780,joy,irman,lirc,bayrad,glk,stv5730,sed1330,sed1520,svga,lcdm001,t6963,lcterm,icp_a106,ms6931,iowarrior,glcdlib,imon,xosd,noritakevfd] +drivers=[mtxorb,cfontz,cfontz633,curses,cwlnx,text,lb216,mtc_s16209x,hd44780,joy,irman,lirc,bayrad,glk,stv5730,sed1330,sed1520,svga,lcdm001,t6963,lcterm,icp_a106,ms6931,iowarrior,glcdlib,imon,xosd,noritakevfd,tyan] fi drivers=`echo $drivers | sed 's/,/ /g'` @@ -277,6 +277,10 @@ dnl else AC_MSG_WARN([The xosd driver needs xosd.h]) ]) ;; + tyan) + DRIVERS="$DRIVERS tyan${SO}" + actdrivers=["$actdrivers tyan"] + ;; *) AC_MSG_ERROR([Unknown driver $driver]) ;; diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am index e87681a..3302613 100644 --- a/server/drivers/Makefile.am +++ b/server/drivers/Makefile.am @@ -18,7 +18,7 @@ AM_LDFLAGS = @LDSHARED@ LIBS = pkglib_PROGRAMS = @DRIVERS@ -EXTRA_PROGRAMS = bayrad CFontz CFontz633 NoritakeVFD curses CwLnx glk hd44780 irman icp_a106 joy lb216 mtc_s16209x lcdm001 lcterm lirc MtxOrb sed1330 sed1520 stv5730 svga t6963 text wirz_sli ms6931 IOWarrior glcdlib imon xosd +EXTRA_PROGRAMS = bayrad CFontz CFontz633 NoritakeVFD curses CwLnx glk hd44780 irman icp_a106 joy lb216 mtc_s16209x lcdm001 lcterm lirc MtxOrb sed1330 sed1520 stv5730 svga t6963 text tyan wirz_sli ms6931 IOWarrior glcdlib imon xosd noinst_LIBRARIES = libLCD.a IOWarrior_CFLAGS = @libusb_cflags@ @@ -70,6 +70,7 @@ stv5730_SOURCES = lcd.h stv5730.c stv5730.h report.h svga_SOURCES = lcd.h svgalib_drv.c svgalib_drv.h report.h t6963_SOURCES = lcd.h t6963.c t6963.h t6963_font.h report.h text_SOURCES = lcd.h text.h text.c report.h +tyan_SOURCES = lcd.h tyan_lcdm.h tyan_lcdm.c report.h wirz_sli_SOURCES = lcd.h wirz-sli.h wirz-sli.c report.h ms6931_SOURCES = lcd.h ms6931.h ms6931.c report.h glcdlib_SOURCES = lcd.h glcdlib.h glcdlib.c report.h diff --git a/server/drivers/tyan_lcdm.c b/server/drivers/tyan_lcdm.c new file mode 100644 index 0000000..6d462ff --- /dev/null +++ b/server/drivers/tyan_lcdm.c @@ -0,0 +1,855 @@ +/* This is the LCDproc driver for tyan lcd module (tyan Barebone GS series) + + Author: yhlu@tyan.com + + Copyright (C) 2004 Tyan Corp + + 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 + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ + + +/* + * Driver status + * 02/04/2004: Working driver + * + * + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "lcd.h" +#include "tyan_lcdm.h" +#include "report.h" +#include "lcd_lib.h" + +#define TYAN_LCDM_KEY_ENTER 0xf2 +#define TYAN_LCDM_KEY_ESCAPE 0xf3 +#define TYAN_LCDM_KEY_RIGHT 0xf5 +#define TYAN_LCDM_KEY_LEFT 0xf6 +#define TYAN_LCDM_KEY_UP 0xf7 +#define TYAN_LCDM_KEY_DOWN 0xf8 + +#define TYAN_LCDM_CMD_BEGIN 0xf1 +#define TYAN_LCDM_CMD_END 0xf2 + + + +static int custom = 0; +typedef enum { + hbar = 1, + vbar = 2, + cust = 3, +} custom_type; + +static int fd; +static char *framebuf = NULL; +static char *old = NULL; +static int width = 0; +static int height = 0; +static int cellwidth = DEFAULT_CELL_WIDTH; +static int cellheight = DEFAULT_CELL_HEIGHT; + +/* 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 = "tyan_lcdm_"; + +/* Internal functions */ +static void tyan_lcdm_init_vbar (Driver * drvthis); +static void tyan_lcdm_init_hbar (Driver * drvthis); +static void tyan_lcdm_switch_mode (); +static void tyan_lcdm_hardware_clear (Driver * drvthis); + +static void tyan_lcdm_set_rampos(unsigned char pos); +static void tyan_lcdm_write_str(char *str,unsigned char start_addr, int length); +#if 0 +static void tyan_lcdm_set_cursor(unsigned char start_addr, int pos); +#endif +static unsigned char tyan_lcdm_read_key(); + +/* + * Opens com port and sets baud correctly... + */ +MODULE_EXPORT int +tyan_lcdm_init (Driver * drvthis, char *args) +{ + struct termios portset; + int tmp, w, h; + + char device[200] = DEFAULT_DEVICE; + int speed = DEFAULT_SPEED; + char size[200] = DEFAULT_SIZE; + + debug(RPT_INFO, "tyan_lcdm: init(%p,%s)", drvthis, args ); + + /* Read config file */ + /* Which serial device should be used */ + strncpy(device, drvthis->config_get_string ( drvthis->name , "Device" , 0 , DEFAULT_DEVICE),sizeof(device)); + device[sizeof(device)-1]=0; + debug (RPT_INFO,"tyan_lcdm: Using device: %s", device); + + /* Which size */ + strncpy(size, drvthis->config_get_string ( drvthis->name , "Size" , 0 , DEFAULT_SIZE),sizeof(size)); + size[sizeof(size)-1]=0; + if( sscanf(size , "%dx%d", &w, &h ) != 2 + || (w <= 0) || (w > LCD_MAX_WIDTH) + || (h <= 0) || (h > LCD_MAX_HEIGHT)) { + report (RPT_WARNING, "tyan_lcdm_init: Cannot read size: %s. Using default value.\n", size); + sscanf( DEFAULT_SIZE , "%dx%d", &w, &h ); + } else { + width = w; + height = h; + } + + /* Which speed */ + tmp = drvthis->config_get_int ( drvthis->name , "Speed" , 0 , DEFAULT_SPEED); + if (tmp == 4800) speed = B4800; + else if (tmp == 9600) speed = B9600; + else { report (RPT_WARNING, "tyan_lcdm_init: Speed must be 4800 or 9600. Using default value.\n", speed); + } + + /* Set up io port correctly, and open it... */ + debug( RPT_DEBUG, "tyan_lcdm: Opening serial device: %s", device); + + fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY); + + if (fd == -1) { + report (RPT_ERR, "tyan_lcdm_init: failed (%s)\n", strerror (errno)); + return -1; + } + + tcgetattr (fd, &portset); + + /* We use RAW mode */ +#ifdef HAVE_CFMAKERAW + /* The easy way */ + cfmakeraw( &portset ); +#else + /* The hard way */ + portset.c_cflag = CS8 | CREAD | CLOCAL; + portset.c_iflag = IXON | IXOFF | IGNBRK | IGNCR; + portset.c_oflag &= ~ONLCR; + portset.c_lflag = 0; + portset.c_cc[VMIN] = 1; + portset.c_cc[VTIME] = 0; + +#endif + + /* Set port speed */ + cfsetospeed (&portset, speed); + cfsetispeed (&portset, speed); + + /* Do it... */ + tcsetattr (fd, TCSANOW, &portset); + + /* Make sure the frame buffer is there... */ + framebuf = (unsigned char *) malloc (width * height); + memset (framebuf, ' ', width * height); + + /* Set display-specific stuff.. */ + tyan_lcdm_switch_mode (); + + report (RPT_DEBUG, "tyan_lcdm_init: done\n"); + + return 0; +} + +/* + * Clean-up + */ +MODULE_EXPORT void +tyan_lcdm_close (Driver * drvthis) +{ + close (fd); + + if(framebuf) free (framebuf); + framebuf = NULL; + + if(old) free (old); + old = NULL; +} + +/* + * Returns the display width + */ +MODULE_EXPORT int +tyan_lcdm_width (Driver *drvthis) +{ + return width; +} + +/* + * Returns the display height + */ +MODULE_EXPORT int +tyan_lcdm_height (Driver *drvthis) +{ + return height; +} + +/* + * Flushes all output to the lcd... + */ +MODULE_EXPORT void +tyan_lcdm_flush (Driver * drvthis) +{ + int i; + char *xp, *xq; +/* + * We don't use delta update yet. + * It is possible but not easy, we can only update a line, full or begining. + */ + if (old==NULL) { + old = (unsigned char *) malloc (width * height); + memset (old, ' ', width * height); + tyan_lcdm_hardware_clear (drvthis); + } + +xp = framebuf; +xq = old; + +for (i=0; i 0 mean "on" and values <= 0 are "off". + * + * The input is just an array of characters... + */ +MODULE_EXPORT void +tyan_lcdm_set_char (Driver * drvthis, int n, char *dat) +{ + char out[8]; + int row, col; + int letter; + + if (n < 0 || n > 7) + return; + if (!dat) + return; + + for (row = 0; row < cellheight; row++) { + letter = 0; + for (col = 0; col < cellwidth; col++) { + letter <<= 1; + letter |= (dat[(row * cellwidth) + col] > 0); + /* I should remove that debug code. */ + // if (dat[(row * cellheight) + col] == 0) printf("."); + // if (dat[(row * cellheight) + col] == 1) printf("+"); + // if (dat[(row * cellheight) + col] == 2) printf("x"); + // if (dat[(row * cellheight) + col] == 3) printf("*"); + // printf("'%1d'", dat[(row * cellwidth) + col]); + // printf("%3d ", letter); + } + out[row+1]=letter; + // printf(": %d\n", letter); + } + tyan_lcdm_write_str(out,(unsigned char)(0x40+n*8),8); +} + +/* + * Places an icon on screen + */ +MODULE_EXPORT int +tyan_lcdm_icon (Driver * drvthis, int x, int y, int icon) +{ + char icons[8][5 * 8] = { + /* Empty Heart */ + { + 1, 1, 1, 1, 1, + 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, + }, + /* Filled Heart */ + { + 1, 1, 1, 1, 1, + 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, + }, + /* arrow_up */ + { + 0, 0, 1, 0, 0, + 0, 1, 1, 1, 0, + 1, 0, 1, 0, 1, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + }, + /* arrow_down */ + { + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, + }, + /* checkbox_off */ + { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 1, 0, 0, 0, 1, + 1, 0, 0, 0, 1, + 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + }, + /* checkbox_on */ + { + 0, 0, 1, 0, 0, + 0, 0, 1, 0, 0, + 1, 1, 1, 0, 1, + 1, 0, 1, 1, 0, + 1, 0, 1, 0, 1, + 1, 0, 0, 0, 1, + 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, + }, + /* checkbox_gray */ + { + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, + 1, 0, 1, 0, 1, + 1, 1, 0, 1, 1, + 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, + 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, + }, + }; + + /* Yes we know, this is a VERY BAD implementation :-) */ + switch( icon ) { + case ICON_BLOCK_FILLED: + tyan_lcdm_chr( drvthis, x, y, 255 ); + break; + case ICON_HEART_FILLED: + custom = cust; + tyan_lcdm_set_char( drvthis, 0, icons[1] ); + tyan_lcdm_chr( drvthis, x, y, 0 ); + break; + case ICON_HEART_OPEN: + custom = cust; + tyan_lcdm_set_char( drvthis, 0, icons[0] ); + tyan_lcdm_chr( drvthis, x, y, 0 ); + break; + case ICON_ARROW_UP: + custom = cust; + tyan_lcdm_set_char( drvthis, 1, icons[2] ); + tyan_lcdm_chr( drvthis, x, y, 1 ); + break; + case ICON_ARROW_DOWN: + custom = cust; + tyan_lcdm_set_char( drvthis, 2, icons[3] ); + tyan_lcdm_chr( drvthis, x, y, 2 ); + break; + case ICON_ARROW_LEFT: + tyan_lcdm_chr( drvthis, x, y, 0x7F ); + break; + case ICON_ARROW_RIGHT: + tyan_lcdm_chr( drvthis, x, y, 0x7E ); + break; + case ICON_CHECKBOX_OFF: + custom = cust; + tyan_lcdm_set_char( drvthis, 3, icons[4] ); + tyan_lcdm_chr( drvthis, x, y, 3 ); + break; + case ICON_CHECKBOX_ON: + custom = cust; + tyan_lcdm_set_char( drvthis, 4, icons[5] ); + tyan_lcdm_chr( drvthis, x, y, 4 ); + break; + case ICON_CHECKBOX_GRAY: + custom = cust; + tyan_lcdm_set_char( drvthis, 5, icons[6] ); + tyan_lcdm_chr( drvthis, x, y, 5 ); + break; + default: + return -1; /* Let the core do other icons */ + } + return 0; + +} + +/* + * Clears the LCD screen + */ +MODULE_EXPORT void +tyan_lcdm_clear (Driver * drvthis) +{ + memset (framebuf, ' ', width * height); +} + +/* + * Hardware clears the LCD screen + */ +static void +tyan_lcdm_hardware_clear (Driver * drvthis) +{ + char lcdcmd[5]; + //set os selection + lcdcmd[0]=TYAN_LCDM_CMD_BEGIN; + lcdcmd[1]=0x70; + lcdcmd[2]=0x00; + lcdcmd[3]=0x01; + lcdcmd[4]=TYAN_LCDM_CMD_END; + write(fd,lcdcmd,5); + +} + +/* + * Prints a string on the lcd display, at position (x,y). The + * upper-left is (1,1), and the lower right should be (16,2). + */ +MODULE_EXPORT void +tyan_lcdm_string (Driver * drvthis, int x, int y, char string[]) +{ + int i; + + /* Convert 1-based coords to 0-based... */ + x -= 1; + y -= 1; + + for (i = 0; string[i]; i++) { + + /* Check for buffer overflows... */ + if ((y * width) + x + i > (width * height)) + break; + framebuf[(y * width) + x + i] = string[i]; + } +} + +static +void tyan_lcdm_set_rampos(unsigned char pos) +{ + char cmd_str[5]; + cmd_str[0]=TYAN_LCDM_CMD_BEGIN; + cmd_str[1]=0x70; + cmd_str[2]=0x00; + cmd_str[3]=pos; + cmd_str[4]=TYAN_LCDM_CMD_END; + write( fd,cmd_str,5); +} + +static +void tyan_lcdm_write_str(char *str,unsigned char start_addr, int length) +{ +//CGRAM 0x40, 0x48,.... +//if Line 1: start_addr = 0x80 +//if Line 2: start_addr = 0xc0 +// 1<= length <=16 + char cmd_str[20]; + tyan_lcdm_set_rampos(start_addr); + memset(cmd_str,' ', 20); + cmd_str[0] = TYAN_LCDM_CMD_BEGIN; + cmd_str[1] = 0x70; + cmd_str[2] = 0x02; + cmd_str[19] = TYAN_LCDM_CMD_END; + memcpy(cmd_str+3,str,length); + write(fd,cmd_str,20); +} +#if 0 +static +void tyan_lcdm_set_cursor(unsigned char start_addr, int pos){ + char cmd_str[5]; + tyan_lcdm_set_rampos(pos+start_addr); + cmd_str[0] = TYAN_LCDM_CMD_BEGIN; + cmd_str[1] = 0x70; + cmd_str[2] = 0x00; + cmd_str[3] = 0x0e; + cmd_str[4] = TYAN_LCDM_CMD_END; + write(fd,cmd_str,5); +} + +#endif + +static +unsigned char tyan_lcdm_read_key(){ + int count=0; + char key_str[4]; + memset(key_str,0,4); + count=read(fd,key_str,4); + if( key_str[0] == (char)TYAN_LCDM_CMD_BEGIN && key_str[1]==(char)0x72 && key_str[3]==(char)TYAN_LCDM_CMD_END){ + return key_str[2]; + } + return 0xf4; //error +} diff --git a/server/drivers/tyan_lcdm.h b/server/drivers/tyan_lcdm.h new file mode 100644 index 0000000..7945f9c --- /dev/null +++ b/server/drivers/tyan_lcdm.h @@ -0,0 +1,49 @@ +/* This is the LCDproc driver header for tyan lcd module (tyan Barebone GS series) + + Author: yhlu@tyan.com + + Copyright (C) 2004 Tyan Corp + + 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 + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */ +#ifndef TYAN_LCDM_H +#define TYAN_LCDM_H + +#include "lcd.h" + +#define DEFAULT_CELL_WIDTH 5 +#define DEFAULT_CELL_HEIGHT 8 +#define DEFAULT_DEVICE "/dev/lcd" +#define DEFAULT_SPEED B9600 +#define DEFAULT_SIZE "16x2" + +MODULE_EXPORT int tyan_lcdm_init (Driver * drvthis, char *device); +MODULE_EXPORT void tyan_lcdm_close (Driver * drvthis); +MODULE_EXPORT int tyan_lcdm_width (Driver * drvthis); +MODULE_EXPORT int tyan_lcdm_height (Driver * drvthis); +MODULE_EXPORT void tyan_lcdm_clear (Driver * drvthis); +MODULE_EXPORT void tyan_lcdm_flush (Driver * drvthis); +MODULE_EXPORT void tyan_lcdm_string (Driver * drvthis, int x, int y, char string[]); +MODULE_EXPORT void tyan_lcdm_chr (Driver * drvthis, int x, int y, char c); + +MODULE_EXPORT void tyan_lcdm_vbar (Driver * drvthis, int x, int y, int len, int promille, int options); +MODULE_EXPORT void tyan_lcdm_hbar (Driver * drvthis, int x, int y, int len, int promille, int options); +MODULE_EXPORT void tyan_lcdm_num (Driver * drvthis, int x, int num); +MODULE_EXPORT int tyan_lcdm_icon(Driver * drvthis, int x, int y, int icon); + +MODULE_EXPORT void tyan_lcdm_set_char (Driver * drvthis, int n, char *dat); + +MODULE_EXPORT void tyan_lcdm_backlight (Driver * drvthis, int on); + +#endif