From 8ba4e54a3b6bba3e060452d7cdd028ec27cdccc3 Mon Sep 17 00:00:00 2001 From: marschap Date: Sat, 20 May 2006 14:38:18 +0000 Subject: [PATCH] update serialVFD driver (Stefan Herdler) --- LCDd.conf | 42 +- docs/LCDd.8 | 2 +- docs/lcdproc-user/drivers/serialVFD.docbook | 330 +++++++-- server/drivers/Makefile.am | 2 +- server/drivers/serialVFD.c | 761 +++++--------------- server/drivers/serialVFD.h | 39 +- 6 files changed, 511 insertions(+), 665 deletions(-) diff --git a/LCDd.conf b/LCDd.conf index 19dfdb1..94e369b 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -644,30 +644,44 @@ Port=0x378 ## Serial VFD driver ## ## Drives various (see below) serial 5x7dot VFD's. ## [serialVFD] -# device where the VFD is. Usual values are /dev/ttyS0 and /dev/ttyS1 + +# Specifies the displaytype.[default: 0] +# 0 NEC (FIPC8367 based) VFDs. +# 1 KD Rev 2.1. +# 2 Noritake VFDs (*). +# 3 Futaba VFDs +# (* most should work, not testet yet.) +Type=0 + +# "no" if display connected serial, "yes" if connected parallel. [default: no(=serial)] +use_parallel=no + +# Number of Custom-Characters [default: displaytype dependent] +#Custom-Characters=0 + +# Portaddress where the LPT is. Used in parallelmode only. Usual values are 0x278, 0x378 and 0x3BC +Port=0x378 + +# Device to use in serial mode. Usual values are /dev/ttyS0 and /dev/ttyS1 Device=/dev/ttyS1 # Specifies the size of the VFD. Size=20x2 -# Specifies the display type [default: 0] -# 0 NEC (FIPC8367 based) VFDs. -# 1 KD Rev 2.1. -# 2 Noritake VFDs (*). -# 3 Futaba VFDs (*). -# (* most should work, not tested yet.) -Type=1 - -# Display brightness [default: 255]. -# 0 min ... 255 max ... 1000 also max -# (4 steps 0-64, 65-128, 129-192, 193-1000) -Brightness=255 +# Set the initial brightness [default: 1000; legal: 0 - 1000] +# (4 steps 0-250, 251-500, 501-750, 751-1000) +Brightness=1000 +# Set the initial off-brightness [default: 0; legal: 0 - 1000] +# This value is used when the display is normally +# switched off in case LCDd is inactive +# (4 steps 0-250, 251-500, 501-750, 751-1000) +OffBrightness=0 # set the serial port speed [default: 9600; legal: 1200, 2400, 9600, 19200, 115200] Speed=9600 # enable ISO 8859 1 compatibility [default: yes; legal: yes, no] -ISO_8859_1=yes +#ISO_8859_1=yes diff --git a/docs/LCDd.8 b/docs/LCDd.8 index dc41baf..51143ac 100644 --- a/docs/LCDd.8 +++ b/docs/LCDd.8 @@ -169,7 +169,7 @@ SED1330/SED1335 (aka S1D13300/S1D13305) based graphical displays 122x32 pixel graphic displays based on SED1520 controllers .TP .B serialVFD -NEC FIPC8367 based serial VFDs +NEC (FIPC8367 based) and FUTABA VFDs .TP .B sli Wirz SLI driver (unknown) diff --git a/docs/lcdproc-user/drivers/serialVFD.docbook b/docs/lcdproc-user/drivers/serialVFD.docbook index dbe816c..3c9d082 100644 --- a/docs/lcdproc-user/drivers/serialVFD.docbook +++ b/docs/lcdproc-user/drivers/serialVFD.docbook @@ -2,69 +2,116 @@ The serialVFD Driver -This section talks about using LCDproc with LCD displays that use the -serialVFD chipset. +This section talks about using LCDproc with VFD character-displays build by NEC, FUTABA and NORITAKE. - -Connections + + +The serialVFD-driver is working with NEC FIPC8367 based VFDs +and the "KD Rev 2.1" (an ATMEL AT90S.... based FM20X2KB-AB replacement). + It is also known to work on FUTABA VFDs. + + +The driver should operate most of NEC, Futaba and Noritake 7x5 dot VFDs with + serial(rs232) and/or parallel interface. See the following table for testing-status. + Feedback is welcome. -The serialVFD-driver should work with all NEC FIPC8367 based VFDs: -NEC FC20X2JA -NEC FM20X2KB-AB -NEC FC20X1SA-AB/AA -... -Tested only on: NEC FM20X2KB-AB -The driver also works (tested) on "KD Rev 2.1" (an ATMEL AT90S.... -based FM20X2KB-AB replacement). -Note: Above char. 128 the FIPC-displays and KD's charactersets -are different. - -The driver may work or will be easy to get working on the following -Displays / Controllers (not tested!). - - - +
serialVFD: Display Status + Display Controller + Serial + Parallel + Display tested + Remark - FUTABA M204SD01AA - FUTABA 5P00A016 + NEC FM20X2KB-AB + NEC FIPC8367 + Ok + Ok + Yes + + + NEC FC20X2JA + NEC FIPC8367 + (Ok) + (Ok) + No + Same Controller as on FM20X2KB-AB + + + NEC FC20X1SA-AB/AA + NEC FIPC8367 + (Ok) + (Ok) + No + Same Controller as on FM20X2KB-AB + + + KD Rev 2.1 + AT90S.... + microcontroller + Ok + Ok + Yes + + + + + FUTABA M402SD06GJ + ? + (?)* + Ok + Yes + (* perhaps no compatible baudrate, not tested) + The display has no user-characters set Custom-Characters=0 + in LCDd.conf. + + + FUTABA M204SD01AA + FUTABA 5P00A016 + (Ok) + (Ok) + No + + + + Noritake CU20026SCPB-T - (microcontroller) + microcontroller + (Ok) + (Ok) + No + + Noritake CU20045SCPB-T28A ? + (Ok) + (Ok) + No +
- -... or compatible. -(most Futaba/Noritake 7x5 dot VFDs with serial(rs232) interface -(including serial(rs232)/parallel types)) - - -Maybe there are little changes in the commands to do to get all -functions to work correctly. But because of the similarity of the -protocols, it wont be much work. +() feature not tested. - -If you want to add a new device to the driver add a new section -to the displaytype-switch-case in the init-function and fill it -with the correct commands for the display. -(Try which displaytype works best with your display, copy and modify -it's section that is the easiest way I guess.) +If your display isn't working 100% satisfactorily you can add a new device with modified hardware +commands to the driver if you want. To do that you have to add a new section to the display- +Type=-switch-case in ./server/drivers/serialVFD-displays.c +and to write a new "load"function with the correct commands for the display.(Try which display-Type= +works best with your display, copy, rename and modify this function that is the easiest way I guess.) @@ -78,24 +125,25 @@ running. It may take a few minutes until the next full refresh makes the display show everything correctly. - -To enable the bignumbers on 2-line displays (only this driver supports -this yet) you have to edit clients/lcdproc/chrono.c -before compiling. -In function big_clock_screen you have to replace the -4 by a 2 in this line: -if (lcd_hgt < 4) - + +Connecting The Display +The Connections shown have been tested successfully. +Always cross-check with your datasheet, before connecting your display! + Displays of same manufacturer may have different pin assignments! +With this example connections it will be easy to connect displays with different connector + pin-layouts, the pins are commonly named equal in the datasheet. + + +Serial Connections -This driver uses the serial mode of the displays. It is NOT possible to connect most of the displays directly to the serialport. The signal has to be inverted. I use the following circuit to do that job.
-serialVFD: Connecting the display +serialVFD: Serial Inverter - A* | E| | | | | -5(GND) --------o----------o----o----------------- GND - -Shield ------------------------------------------ +5(GND) --------o----------o----o--------------o-- GND + |* +Shield ---------------------------------------o optional *connect near display @@ -131,25 +179,27 @@ optional
-The pins on the different displays vary. +The pins on the different displays vary. +NEC Displays (FM20X2KB-AB): -FM20X2KB-AB: - -CN1: +CN1: + -CN2: +CN2: + - -KD Rev 2.1: - -blue connector (6pin in a row) (the important one!): - +KD Rev 2.1: + +The blue connector (6pin in a row) (the important one!): + - + -gray connector (10pin 2 rows): -Do not use. (the ATMEL ISP connector I guess) - -The two jumpers next to the gray connector: -Normally not used. +The gray connector (10pin 2 rows): + + + +The two jumpers next to the gray connector: + + + +
+ + +Parallel Connections + + +NEC Displays (FM20X2KB-AB): + +CN1: + +CN2: + + +FUTABA Displays (M402SD06GJ): + + +
- Configuration in LCDd.conf + [serialVFD] + + + + use_parallel= + + + yes + no + + + + + "no" if display connected serial, "yes" if connected parallel [default: no(serial)]. + + + + + + Port= + PORT + + + Portaddress where the LPT is. Used in parallelmode only. Usual values are 0x278, 0x378 and 0x3BC [default: 0x278]. + + + Device= DEVICE - Device where the VFD is. Usual values are /dev/ttyS0 and /dev/ttyS1 - Default: /dev/lcd + Device to use in serial mode. Usual values are /dev/ttyS0 and /dev/ttyS1 + [default: /dev/lcd]. + + + + + + Custom-Characters= + CUSTOM-CHARACTERS + + +Number of Custom-Characters [default: Display-Type dependent]. @@ -204,7 +368,7 @@ You can activate two different testmodes with them. Specifies the size of the VFD. - default: 20x2 + [default: 20x2] @@ -247,7 +411,7 @@ You can activate two different testmodes with them. - Options 3 and 4 should work, but have not been tested yet. Feedback is welcome. + Noritake VFDs have not been tested yet. Feedback is welcome. @@ -258,9 +422,21 @@ You can activate two different testmodes with them. BRIGHTNESS - Display brightness [default: 255]. - 0 min ... 255 max ... 1000 also max - (4 steps 0-64, 65-128, 129-192, 193-1000) +Set the initial brightness [default: 1000; legal: 0 - 1000] + (4 steps 0-250, 251-500, 501-750, 751-1000) + + + + + + OffBrightness= + OFFBRIGHTNESS + + +Set the initial off-brightness [default: 0; legal: 0 - 1000]. + This value is used when the display is normally + switched off in case LCDd is inactive. + (4 steps 0-250, 251-500, 501-750, 751-1000) @@ -279,7 +455,7 @@ You can activate two different testmodes with them. Set the the baud rate communication with the VFD. - If not given, it defaults to 9600. + If not given [default 9600]. @@ -294,7 +470,7 @@ You can activate two different testmodes with them. - Enable ISO-8859-1 compatibility. Ddefault is yes. + Enable ISO-8859-1 compatibility [default is yes]. diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am index c4c64e7..db476e2 100644 --- a/server/drivers/Makefile.am +++ b/server/drivers/Makefile.am @@ -80,7 +80,7 @@ NoritakeVFD_SOURCES = lcd.h lcd_lib.h NoritakeVFD.c NoritakeVFD.h report.h pyramid_SOURCES = lcd.h pylcd.c pylcd.h sed1330_SOURCES = lcd.h sed1330.h sed1330.c port.h lpt-port.h timing.h report.h sed1520_SOURCES = lcd.h sed1520.c sed1520.h sed1520fm.c sed1520fm.h port.h report.h -serialVFD_SOURCES = lcd.h lcd_lib.h serialVFD.c serialVFD.h report.h adv_bignum.h +serialVFD_SOURCES = lcd.h lcd_lib.h serialVFD.c serialVFD.h report.h adv_bignum.h serialVFD_displays.c serialVFD_displays.h serialVFD_io.c serialVFD_io.h 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 lcd_lib.h t6963.c t6963.h t6963_font.h report.h diff --git a/server/drivers/serialVFD.c b/server/drivers/serialVFD.c index 855b685..1fe50e8 100644 --- a/server/drivers/serialVFD.c +++ b/server/drivers/serialVFD.c @@ -6,7 +6,7 @@ driver. It may contain parts of other drivers of this package too. - 2006-02-13 Version 0.2: everything should work (not all hardware tested!) + 2006-05-16 Version 0.3: everything should work (not all hardware tested!) 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 @@ -24,120 +24,9 @@ - The serialVFD-driver should work with all NEC FIPC8367 based VFDs: - NEC FC20X2JA - NEC FM20X2KB-AB - NEC FC20X1SA-AB/AA - ... - Tested only on: NEC FM20X2KB-AB - The driver also works (tested) on "KD Rev 2.1" (an ATMEL AT90S.... - based FM20X2KB-AB replacement). - Note: Above char. 128 the FIPC-displays and KD's charactersets - are different. - - The driver may work or will be easy to get working on the following - Displays / Controllers (not tested!). - Display: Controller: - FUTABA M204SD01AA FUTABA 5P00A016 - Noritake CU20026SCPB-T (microcontroller) - Noritake CU20045SCPB-T28A ? - ... or compatible. - (most Futaba/Noritake 7x5 dot VFDs with serial(rs232) interface - (including serial(rs232)/parallel types)) - Maybe there are little changes in the commands to do to get all - functions to work correctly. But because of the similarity of the - protocols, it wont be much work. - - If you want to add a new device to the driver add a new section - to the displaytype-switch-case in the init-function and fill it - with the corrrect commands for the display. - (Try wich displaytype works best with your display, copy and modify - it's section that is the easiest way I guess.) - - - On this page I found pictures and datasheets of the VFD's: - http://www.maltepoeggel.de/html/vfd/index.html - - - - - To enable the bignumbers on 2-line displays (only this driver supports - this yet) you have to edit "/clients/lcdproc/chrono.c" before compiling. - In function "big_clock_screen" you have to replace the "4" by a "2" in - this line: "if (lcd_hgt < 4)". - - - - This driver uses the serial mode of the displays. - It is NOT possible to connect most of the displays directly to the - serialport. The signal has to be inverted. I use the following - circuit to do that job. - - Computer Display - (signal) - HDD Powerconnector - color(Voltage) - - red(+5V) --------------------------------o----- +5V - | - black(GND) --------------------o | - | R - | R 10k - Serial(SUB-D 9Pin female) V* R - pin(signal) | - | - 3(TxD) --RRRR--o--o o-----------------o----- RxD - 10k | | | - | | C| - | | ----- BC547c (or similar NPN) - R | B| / | - 10k R o--|-| | - R | \ | - | --->- A* - | E| | - | | | - 5(GND) --------o----------o----o----------------- GND - - Shield ------------------------------------------ - optional - - *connect near display - - - The pins on the different displays vary. - - - - FM20X2KB-AB: - - CN1: - Pin 33 <--- RxD - (Testmode: connect pins 25 & 26 then power up) - - CN2: - Pin 1 <--- +5V - Pin 2 ---- GND - - - - KD Rev 2.1: - - blue connector (6pin in a row) (the important one!): - -------------------------------- - | +5V +5V RxD GND GND GND | - -------------------------------- - NOTE: hold the display in that position where you can read - the "KD Rev 2.1" marking normally! - - gray connector (10pin 2 rows): - Do not use. (the ATMEL ISP connector I guess) - - The two jumpers next to the gray connector: - Normally not used. - You can activate two different testmodes with them. - - - + The driver should operate most of NEC, Futaba and Noritake 7x5 dot VFDs with + serial(rs232) and/or parallel interface. See /docs/lcdproc-user/serialvfd-howto.html + for further information List of driver entry point: @@ -147,7 +36,7 @@ close Implemented. width Implemented. height Implemented. clear Implemented by space filling no custom char info. -flush Calling draw_frame only. +flush Implemented. string Implemented. chr Implemented. vbar Implemented. @@ -164,7 +53,7 @@ get_contrast Not implemented, no software control. set_contrast Not implemented, no software control. get_brightness Implemented. set_brightness Implemented. -backlight Not implemented, no software control. +backlight Implemented. output Not implemented. get_key Not implemented, no keys. get_info Implemented. @@ -185,6 +74,7 @@ get_info Implemented. # include "config.h" #endif + #include "lcd.h" #include "serialVFD.h" @@ -192,41 +82,16 @@ get_info Implemented. #include "lcd_lib.h" #include "adv_bignum.h" +#define DEFAULT_OFF_BRIGHTNESS 300 +#define DEFAULT_ON_BRIGHTNESS 1000 + #define pos1_cursor 4 //moves cursor to top left character. #define mv_cursor 5 //moves cursor to position specified by the next byte. #define reset 6 //reset #define init_cmds 7 //commands needed to initialize the display. #define set_user_char 8 //set user character. #define hor_tab 9 //moves cursor 1 chr right - -typedef struct driver_private_data { - char device[200]; - int fd; - int speed; - /* dimensions */ - int width, height; - int cellwidth, cellheight; - /* framebuffer and buffer for old LCD contents */ - unsigned char *framebuf; - unsigned char *backingstore; - /* defineable characters */ - int ccmode; - int brightness; - int customchars; - int ISO_8859_1; - unsigned int refresh_timer; - unsigned char charmap[128]; - int display_type; - char custom_char[31][7]; // used for "KD Rev 2.1" only - char custom_char_changed[32]; // used only if need_refresh==1 - int need_refresh; // 1 if displays need refresh after changing custonchars - char hw_cmd[10][4]; // hardwarespecific commands - int usr_chr_dot_assignment[57]; // how to setup usercharacters - unsigned int usr_chr_mapping[31];// where to place the usercharacters (0..30) in the asciicode - int hbar_cc_offset; // character offset of the bars - int vbar_cc_offset; // character offset of the bars - char info[255]; -} PrivateData; +#define LPTPORT 0x378 /* Vars for the server core */ MODULE_EXPORT char *api_version = API_VERSION; @@ -237,8 +102,6 @@ MODULE_EXPORT char *symbol_prefix = "serialVFD_"; /* Internal functions */ static void serialVFD_init_vbar (Driver *drvthis); static void serialVFD_init_hbar (Driver *drvthis); -static void serialVFD_draw_frame (Driver *drvthis, unsigned char *dat); -static void serialVFD_put_brightness (Driver *drvthis); static void serialVFD_put_char (Driver *drvthis, int n); // Opens com port and sets baud correctly... @@ -246,8 +109,7 @@ static void serialVFD_put_char (Driver *drvthis, int n); MODULE_EXPORT int serialVFD_init (Driver *drvthis) { - struct termios portset; - int tmp, w, h, brightness; + int tmp, w, h; char size[200] = DEFAULT_SIZE; PrivateData *p; @@ -265,22 +127,44 @@ serialVFD_init (Driver *drvthis) p->ccmode = CCMODE_STANDARD; p->ISO_8859_1 = 1; p->refresh_timer = 0; + p->hw_brightness = 0; debug(RPT_INFO, "%s(%p)", __FUNCTION__, drvthis ); + +/* Read config file */ - /* Read config file */ + p->use_parallel = drvthis->config_get_bool( drvthis->name, "use_parallel", 0, 0 ); + if (p->use_parallel){ + p->port = drvthis->config_get_int( drvthis->name, "port", 0, LPTPORT ); + } + else { /* Which device should be used */ - strncpy(p->device, drvthis->config_get_string(drvthis->name, "Device", 0, DEFAULT_DEVICE), sizeof(p->device)); + strncpy(p->device, drvthis->config_get_string (drvthis->name, "Device", 0, DEFAULT_DEVICE), sizeof(p->device)); p->device[sizeof(p->device)-1] = '\0'; report(RPT_INFO, "%s: using Device %s", drvthis->name, p->device); + /* Which speed */ + tmp = drvthis->config_get_int (drvthis->name, "Speed", 0, DEFAULT_SPEED); + if ((tmp != 1200) && (tmp != 2400) && (tmp != 9600) && (tmp != 19200) && (tmp != 115200)) { + report(RPT_WARNING, "%s: Speed must be 1200, 2400, 9600, 19200 or 115200. Using default %d.\n", + drvthis->name, DEFAULT_SPEED); + tmp = DEFAULT_SPEED; + } + if (tmp == 1200) p->speed = B1200; + else if (tmp == 2400) p->speed = B2400; + else if (tmp == 9600) p->speed = B9600; + else if (tmp == 19200) p->speed = B19200; + else if (tmp == 115200) p->speed = B115200; + } +// report(RPT_ERR, "%s: Port: %X\n", __FUNCTION__, p->port, strerror (errno)); + /* 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, "%s: cannot parse Size: %s; using default %s", + report(RPT_WARNING, "%s: cannot parse size: %s; using default %s.", drvthis->name, size, DEFAULT_SIZE); sscanf(DEFAULT_SIZE, "%dx%d", &w, &h); } @@ -288,14 +172,24 @@ serialVFD_init (Driver *drvthis) p->height = h; /* Which backlight brightness */ - tmp = drvthis->config_get_int(drvthis->name, "Brightness", 0, DEFAULT_BRIGHTNESS); + tmp = drvthis->config_get_int(drvthis->name, "Brightness", 0, DEFAULT_ON_BRIGHTNESS); + debug(RPT_INFO, "%s: Brightness (in config) is '%d'", __FUNCTION__, tmp); if ((tmp < 0) || (tmp > 1000)) { report(RPT_WARNING, "%s: Brightness must be between 0 and 1000; using default %d", - drvthis->name, DEFAULT_BRIGHTNESS); - tmp = DEFAULT_BRIGHTNESS; + drvthis->name, DEFAULT_ON_BRIGHTNESS); + tmp = DEFAULT_ON_BRIGHTNESS; } - brightness = tmp; + p->on_brightness = tmp; + /* Which backlight-off "brightness" */ + tmp = drvthis->config_get_int(drvthis->name, "OffBrightness", 0, DEFAULT_OFF_BRIGHTNESS); + debug(RPT_INFO, "%s: OffBrightness (in config) is '%d'", __FUNCTION__, tmp); + if ((tmp < 0) || (tmp > 1000)) { + report(RPT_WARNING, "%s: OffBrightness must be between 0 and 1000; using default %d", + drvthis->name, DEFAULT_OFF_BRIGHTNESS); + tmp = DEFAULT_OFF_BRIGHTNESS; + } + p->off_brightness = tmp; /* ISO 8859 1 */ p->ISO_8859_1 = drvthis->config_get_bool(drvthis->name, "ISO_8859_1", 0, 1); @@ -309,57 +203,29 @@ serialVFD_init (Driver *drvthis) } p->display_type = tmp; - - /* Which speed */ - tmp = drvthis->config_get_int(drvthis->name, "Speed", 0, DEFAULT_SPEED); - if ((tmp != 1200) && (tmp != 2400) && (tmp != 9600) && (tmp != 19200) && (tmp != 115200)) { - report(RPT_WARNING, "%s: Speed must be 1200, 2400, 9600, 19200 or 115200; using default %d", - drvthis->name, DEFAULT_SPEED); - tmp = DEFAULT_SPEED; + /* Number of custom characters */ + tmp = drvthis->config_get_int (drvthis->name, "Custom-Characters", 0, -83); + if ((tmp < 0) || (tmp > 99)) { + report(RPT_WARNING, "%s: The number of Custom-Characters must be between 0 and 99. Using default.", + drvthis->name, 0); + tmp = -83; } - if (tmp == 1200) p->speed = B1200; - else if (tmp == 2400) p->speed = B2400; - else if (tmp == 9600) p->speed = B9600; - else if (tmp == 19200) p->speed = B19200; - else if (tmp == 115200) p->speed = B115200; + p->customchars = tmp; +// report (RPT_ERR, "%s: Port: %X\n", __FUNCTION__, p->port, strerror (errno)); - /* Set up io port correctly, and open it...*/ - debug(RPT_DEBUG, "%s: Opening device: %s", __FUNCTION__, p->device); - p->fd = open(p->device, O_RDWR | O_NOCTTY | O_NDELAY); - if (p->fd == -1) { - report(RPT_ERR, "%s: open(%s) failed (%s)", drvthis->name, p->device, strerror(errno)); +// Do connection type specific io-port init + if (Port_Function[p->use_parallel].init_fkt (drvthis)==-1) { + report(RPT_ERR, "%s: unable to initialize io-port.", drvthis->name); return -1; } - tcgetattr(p->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 ; -#endif - - // Set port speed - cfsetospeed(&portset, p->speed); - cfsetispeed (&portset, B0); - - // Do it... - tcsetattr(p->fd, TCSANOW, &portset); - +// setup frame buffer and backing store /* make sure the frame buffer is there... */ p->framebuf = (unsigned char *) malloc(p->width * p->height); if (p->framebuf == NULL) { - report(RPT_ERR, "%s: unable to create framebuffer", drvthis->name); + report(RPT_ERR, "%s: unable to create framebuffer.", drvthis->name); return -1; } memset(p->framebuf, ' ', p->width * p->height); @@ -367,318 +233,85 @@ serialVFD_init (Driver *drvthis) /* make sure the framebuffer backing store is there... */ p->backingstore = (unsigned char *) malloc(p->width * p->height); if (p->backingstore == NULL) { - report(RPT_ERR, "%s: unable to create framebuffer backing store", drvthis->name); + report(RPT_ERR, "%s: unable to create framebuffer backing store.", drvthis->name); return -1; } memset(p->backingstore, ' ', p->width * p->height); //setup displayspecific data - switch (p->display_type) { -//nec_fipc - case 0: //nec_fipc - p->need_refresh = 0; // 1 if displays need refresh after changing custonchars - p->customchars = 1; // number of customchaaracters the display provides - p->vbar_cc_offset = 5; // character offset of the bars - p->hbar_cc_offset = 12; // character offset of the bars + serialVFD_load_display_data(drvthis); - // hardwarespecific commands: - // hw_cmd[Command][data] = {{commandlength , command 1}, - // ..... - // {commandlength , command N}} - const char hw_cmd_0[10][4]= {{1 ,0x04}, // dark - {1 ,0x03}, - {1 ,0x02}, - {1 ,0x01}, // bright - {1 ,0x0D}, // pos1 - {1 ,0x1B}, // move cursor - {1 ,0x0C}, // reset - {2 ,0x14, 0x11}, // init - {1 ,0x1A}, // set user char - {1 ,0x09}}; // tab - for (tmp = 0; tmp < 10; tmp++) - for (w = 0; w < 4 ;w++) - p->hw_cmd[tmp][w] = hw_cmd_0[tmp][w]; - - // Translates ISO 8859-1 to display charset. - const unsigned char charmap_0[] = { - /* #128 = 0x80 */ - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - /* #160 = 0xA0 */ - 160, '!', 0xF7, 0xF8, '?', '?', 0x7C, 0xF9, - '"', '?', '?', '?', '?', '-', '?', '?', - 0x8B, 0xF3, 0x89, 0x8A, 0x27, 0x98, '?', '.', - ',', '?', '?', '?', '?', 0x8C, '?', 0xAA, - /* #192 = 0xC0 */ - 'A', 'A', 'A', 'A', 0xA2, 0xA8, 'A', 'C', - 'E', 'E', 'E', 0xB6, 'I', 'I', 'I', 'I', - 'D', 0xA9, 'O', 'O', 'O', 'O', 0xA3, 0x8D, - '0', 'U', 'U', 'U', 0xA4, 'Y', 'p', 0x91, - /* #224 = 0xE0 */ - 'a', 'a', 'a', 'a', 0xA5, 'a', 'a', 'c', - 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', - 'o', 'n', 'o', 'o', 'o', 'o', 0xA6, 0x8E, - '0', 'u', 'u', 'u', 0xA7, 'y', 'p', 'y' - }; - for (tmp = 0; tmp < 128 ; tmp++) - p->charmap[tmp] = charmap_0[tmp]; - - //{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...} - const int usr_chr_dot_assignment_0[57]={ 7, - 1, 2, 3, 4, 5, 0, 0, 0, - 6, 7, 8, 9,10, 0, 0, 0, - 11,12,13,14,15, 0, 0, 0, - 16,17,18,19,20, 0, 0, 0, - 21,22,23,24,25, 0, 0, 0, - 26,27,28,29,30, 0, 0, 0, - 31,32,33,34,35, 0, 0, 0 }; - for (tmp = 0; tmp < 57 ;tmp++) - p->usr_chr_dot_assignment[tmp] = usr_chr_dot_assignment_0[tmp]; - - //Where to place the usercharacters (0..30) in the asciicode. - //Also used to map standardcharacters in the usercharacterspace(0..30) - //(useful for displays with less then 30 usercharacters and predefined bars) - const unsigned int usr_chr_mapping_0[31]= - {0xAF,0,0,0,0,0, 0x5F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0, 0x5F, 0xE1, 0xE3, 0xE4}; - for (tmp = 0; tmp < 31; tmp++) - p->usr_chr_mapping[tmp] = usr_chr_mapping_0[tmp]; - break; - -//KD Rev2.1 - case 1: //KD Rev2.1 - p->need_refresh=1; // 1 if displays need refresh after changing custonchars - p->customchars=31; // number of customchaaracters the display provides - p->vbar_cc_offset=0; // character offset of the bars - p->hbar_cc_offset=0; // character offset of the bars - - // hardwarespecific commands: - // hw_cmd[Command][data] = {{commandlength , command 1}, - // ..... - // {commandlength , command N}} - const char hw_cmd_1[10][4]= {{1 ,0x04}, // dark - {1 ,0x03}, - {1 ,0x02}, - {1 ,0x01}, // bright - {1 ,0x0D}, // pos1 - {1 ,0x1B}, // move cursor - {1 ,0x0C}, // reset - {2 ,0x14, 0x11}, // init - {1 ,0x1A}, // set user char - {1 ,0x09}}; // tab - for (tmp = 0; tmp < 10; tmp++) - for (w = 0; w < 4; w++) - p->hw_cmd[tmp][w] = hw_cmd_1[tmp][w]; - - const unsigned char charmap_1[] = { - /* #128 = 0x80 */ - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - /* #160 = 0xA0 */ - 160, '!', 0xF7, 0xF8, '?', '?', 0x7C, 0xF9, - '"', '?', '?', '?', '?', '-', '?', '?', - 0xA9, 0xBA, '?', '?', 0x27, '?', '?', '.', - ',', '?', '?', '?', '?', '?', '?', '?', - /* #192 = 0xC0 */ - 0xB2, 'A', 'A', 'A', 0xA2, 0xA1, 'A', 'C', - 'E', 'E', 0xA8, 0xB6, 0xAB, 0xAA, 0xAC, 0xA9, - 'D', 0xAE, 0xB1, 0xB0, 0xBF, 'O', 0xA3, 'x', - 0xAF, 0xB7, 0xB6, 0xB8, 0xA4, 'Y', 'p', 0x91, - /* #224 = 0xE0 */ - 0xD2, 0xC2, 0xC4, 'a', 0xA5, 0xC1, 0xC5, 0xC3, - 0xC7, 0xC6, 0xC8, 0xD4, 0xCC, 0xCB, 0xCD, 0xCA, - 'o', 0xCF, 0xD1, 0xD0, 0xCE, 'o', 0xA6, 0xBB, - 0xD0, 0xD7, 0xD6, 0xD8, 0xA7, 'y', 'p', 'y' - }; - for (tmp = 0; tmp < 128; tmp++) - p->charmap[tmp] = charmap_1[tmp]; - - - //{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...} - const int usr_chr_dot_assignment_1[57]={ 7, - 1, 2, 3, 4, 5, 0, 0, 0, - 6, 7, 8, 9,10, 0, 0, 0, - 11,12,13,14,15, 0, 0, 0, - 16,17,18,19,20, 0, 0, 0, - 21,22,23,24,25, 0, 0, 0, - 26,27,28,29,30, 0, 0, 0, - 31,32,33,34,35, 0, 0, 0}; - for (tmp = 0; tmp < 57; tmp++) - p->usr_chr_dot_assignment[tmp] = usr_chr_dot_assignment_1[tmp]; - - //Where to place the usercharacters (0..30) in the asciicode. - //Also used to map standardcharacters in the usercharacterspace(0..30) - //(useful for displays with less then 30 usercharacters and predefined bars) - const unsigned int usr_chr_mapping_1[31]= - {0xAF}; - for (tmp = 0; tmp < 31; tmp++) - p->usr_chr_mapping[tmp] = usr_chr_mapping_1[tmp]; - break; - -//Noritake - case 2: //Noritake - p->need_refresh=0; // 1 if displays need refresh after changing custonchars - p->customchars=16; // number of customchaaracters the display provides - p->vbar_cc_offset=0; // character offset of the bars - p->hbar_cc_offset=0; // character offset of the bars - - // hardwarespecific commands: - // hw_cmd[Command][data] = {{commandlength , command 1}, - // ..... - // {commandlength , command N}} - const char hw_cmd_2[10][4]= {{1 ,0x1B, 0x4C, 0x00}, // dark - {1 ,0x1B, 0x4C, 0x50}, - {2 ,0x1B, 0x4C, 0x90}, - {1 ,0x1B, 0x4C, 0xFF}, // bright - {1 ,0x0C}, // pos1 - {2 ,0x1B, 0x48}, // move cursor - {2 ,0x1B, 0x49}, // reset - {2 ,0x14, 0x11}, // init - {2 ,0x1B, 0x43}, // set user char - {1 ,0x09}}; // tab - for (tmp = 0; tmp < 10; tmp++) - for (w = 0; w < 4; w++) - p->hw_cmd[tmp][w] = hw_cmd_2[tmp][w]; - - // no charmap needed - for (tmp = 128; tmp <= 255; tmp++) - p->charmap[tmp]=tmp; - - //{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...} - const int usr_chr_dot_assignment_2[57]={ 5, - 1, 2, 3, 4, 5, 6, 7, 8, - 9,10,11,12,13,14,15,16, - 17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31,32, - 33,34,35, 0, 0, 0, 0, 0}; - for (tmp=0; tmp < 57; tmp++) - p->usr_chr_dot_assignment[tmp]=usr_chr_dot_assignment_2[tmp]; - - //Where to place the usercharacters (0..30) in the asciicode. - //Also used to map standardcharacters in the usercharacterspace(0..30) - //(useful for displays with less then 30 usercharacters and predefined bars) - const unsigned int usr_chr_mapping_2[31]= - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\ - 0x0F, 0x10, 0x13 , 0x14, 0x1C, 0x1D, 0x1E, 0x1F}; - for (tmp=0;tmp < 31 ;tmp++) - p->usr_chr_mapping[tmp]=usr_chr_mapping_2[tmp]; - break; -//Futaba - case 3: //Futaba - p->need_refresh=0; // 1 if displays need refresh after changing custonchars - p->customchars=3; // number of customchaaracters the display provides - p->vbar_cc_offset=0x30; // character offset of the bars - p->hbar_cc_offset=0x30; // character offset of the bars - - // hardwarespecific commands: - // hw_cmd[Command][data] = {{commandlength , command 1}, - // ..... - // {commandlength , command N}} - const char hw_cmd_3[10][4]= {{1 ,0x04, 0x20}, // dark - {1 ,0x04, 0x40}, - {2 ,0x04, 0x60}, - {1 ,0x04, 0xFF}, // bright - {2 ,0x10, 0x00}, // pos1 - {1 ,0x10,}, // move cursor - {1 ,0x1F}, // reset - {1 ,0x11}, // init - {1 ,0x03}, // set user char - {1 ,0x09}}; // tab - for (tmp=0;tmp < (10) ;tmp++) - for (w=0;w < (4) ;w++) - p->hw_cmd[tmp][w]=hw_cmd_3[tmp][w]; - - // Translates ISO 8859-1 to display charset. - const unsigned char charmap_3[] = { - /* #128 = 0x80 */ - 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, - /* #160 = 0xA0 */ - 160, 0xAD, 0x9B, 0x9C, 0xC8, 0x9D, 0x7C, 0xC0, - '"', '?', 0xA6, 0xAE, 0xAA, '-', '?', '?', - 0xEF, 0xCA, 0xC6, 0xC7, 0x27, 0xB8, '?', '.', - ',', '?', 0xA7, 0xAF, 0xAC, 0xAB, '?', 0xA8, - /* #192 = 0xC0 */ - 0xD0, 'A', 0xD5, 'A', 0x8E, 0x8F, 0x92, 0x80, - 0xD1, 0x90, 0xD6, 0xD3, 'I', 'I', 0xD7, 0xD4, - 'D', 0xA5, 'O', 'O', 0xD8, 'O', 0x99, 'x', - '0', 0xD2, 'U', 0xD9, 0x9A, 'Y', 'p', 0xB1, - /* #224 = 0xE0 */ - 0x85, 0xA0, 0x83, 'a', 0x84, 0x86, 0x91, 0x87, - 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B, - 'o', 0xA4, 0x95, 0xA9, 0x93, 'o', 0x94, '/', - '0', 0x97, 0xA3, 0x96, 0x81, 'y', 'p', 0x89 - }; - for (tmp = 0; tmp < 128; tmp++) - p->charmap[tmp] = charmap_3[tmp]; - - //{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...} - const int usr_chr_dot_assignment_3[57]={ 5, - 8, 7, 6, 5, 4, 3, 2, 1, - 16,15,14,13,12,11,10, 9, - 24,23,22,21,20,19,18,17, - 32,31,30,29,28,27,26,25, - 0, 0, 0, 0, 0,35,34,33}; - for (tmp=0;tmp < 57 ;tmp++) - p->usr_chr_dot_assignment[tmp]=usr_chr_dot_assignment_3[tmp]; - - //Where to place the usercharacters (0..30) in the asciicode. - //Also used to map standardcharacters in the usercharacterspace(0..30) - //(useful for displays with less then 30 usercharacters and predefined bars) - const unsigned int usr_chr_mapping_3[31]= - {0xCD, 0xCE, 0xCF}; - for (tmp = 0; tmp < 31; tmp++) - p->usr_chr_mapping[tmp] = usr_chr_mapping_3[tmp]; - break; - } - - //initialise display - write(p->fd, &p->hw_cmd[reset][1],p->hw_cmd[reset][0]); - write(p->fd, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]); - serialVFD_set_brightness(drvthis, 1, brightness); +// report (RPT_ERR, "%s: Port: %X\n", drvthis->name, p->port, strerror (errno)); +//initialise display + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[reset][1],p->hw_cmd[reset][0]); + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]); + serialVFD_backlight(drvthis, 1); report(RPT_DEBUG, "%s: init() done", drvthis->name); - return 0; } +/* + * Retrieves brightness (in promille) + */ -///////////////////////////////////////////////////////////////// -// Changes screen brightness (0 min ... 255 max ... 1000 also max) -// -MODULE_EXPORT void -serialVFD_set_brightness (Driver *drvthis, int state, int brightness) -{ // set p->brightness +MODULE_EXPORT int +serialVFD_get_brightness(Driver *drvthis, int state) +{ PrivateData *p = drvthis->private_data; - if (brightness > 0) { - if (brightness > 255) - brightness = 255; - if (p->brightness != brightness) { - p->brightness = brightness; - serialVFD_put_brightness(drvthis); - } + return (state == BACKLIGHT_ON) ? p->on_brightness : p->off_brightness; +} + + +/* + * Sets on/off brightness (in promille) + */ +MODULE_EXPORT void +serialVFD_set_brightness(Driver *drvthis, int state, int promille) +{ + PrivateData *p = drvthis->private_data; + + /* Check it */ + if (promille < 0 || promille > 1000) + return; + + /* store the software value since there is not get */ + if (state == BACKLIGHT_ON) { + p->on_brightness = promille; + } + else { + p->off_brightness = promille; } } -static void -serialVFD_put_brightness (Driver *drvthis) -{ // set hardware brightness - PrivateData *p = drvthis->private_data; - int realbrightness = (int) (p->brightness / 64); - //(4 steps 0-64, 65-128, 129-192, 193-1000) - write(p->fd, &p->hw_cmd[realbrightness][1],\ - p->hw_cmd[realbrightness][0]); +/* + * Sets the backlight on or off. + * The hardware support any value between 0 and 100. + */ +MODULE_EXPORT void +serialVFD_backlight (Driver *drvthis, int on) +{ + PrivateData *p = drvthis->private_data; + int hardware_value = (on == BACKLIGHT_ON) + ? p->on_brightness + : p->off_brightness; + + // map range [0, 1000] -> [0, 4] that the hardware understands + //(4 steps 0-250, 251-500, 501-750, 751-1000) + hardware_value /= 251; + if(hardware_value != p->hw_brightness){ + p->hw_brightness=hardware_value; + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[p->hw_brightness][1],\ + p->hw_cmd[p->hw_brightness][0]); + } + } + ///////////////////////////////////////////////////////////////// // Draws a vertical bar... // @@ -719,7 +352,7 @@ serialVFD_set_char (Driver *drvthis, int n, unsigned char *dat) PrivateData *p = drvthis->private_data; unsigned int byte, bit; - if ((n < 0) || (n > p->customchars-1)) + if (n < 0 || n > p->customchars-1) return; if (!dat) return; @@ -735,16 +368,11 @@ serialVFD_set_char (Driver *drvthis, int n, unsigned char *dat) int posbit = 4 - ((pos-1) % 5); letter |= ((dat[posbyte] >> posbit) & 1) << bit;; - } + } } p->custom_char[n][byte] = letter; } - if (p->display_type != 1) //not KD Rev 2.1 - serialVFD_put_char(drvthis, n); - - if (p->need_refresh == 1) - p->custom_char_changed[n] = 1; } static void @@ -752,10 +380,10 @@ serialVFD_put_char (Driver *drvthis, int n) { // put char in display PrivateData *p = drvthis->private_data; - write(p->fd, &p->hw_cmd[set_user_char][1], + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[set_user_char][1],\ p->hw_cmd[set_user_char][0]);// substitute and select Character to overwrite - write(p->fd, &p->usr_chr_mapping[n], 1); - write(p->fd, &p->custom_char[n][0], p->usr_chr_dot_assignment[0]);// overwrite selected Character + Port_Function[p->use_parallel].write_fkt (drvthis, (char*)&p->usr_chr_mapping[n], 1); + Port_Function[p->use_parallel].write_fkt (drvthis, &p->custom_char[n][0], p->usr_chr_dot_assignment[0]);// overwrite selected Character } @@ -765,85 +393,95 @@ serialVFD_put_char (Driver *drvthis, int n) // // Input is a character array, sized serialVFD->width*serialVFD->height // -static void -serialVFD_draw_frame (Driver *drvthis, unsigned char *dat) +MODULE_EXPORT void +serialVFD_flush (Driver *drvthis) { PrivateData *p = drvthis->private_data; int i, j, last_chr = -10; + char custom_char_changed[32]={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}; + + + for (i = 0; i < p->customchars; i++) { + for (j = 0; j < p->usr_chr_dot_assignment[0]; j++) { + if (p->custom_char[i][j] != p->custom_char_store[i][j]) { + custom_char_changed[i]=1; +// report (RPT_ERR, "%s: Char: %X %i\n", __FUNCTION__, i, j, strerror (errno)); + } + p->custom_char_store[i][j]=p->custom_char[i][j]; + } + } - if (!dat) - return; if (p->refresh_timer > 500) { // Do a full refresh every 500 refreshs. // With this it is possible to switch display on and off while lcdproc is running - write(p->fd, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]); - serialVFD_put_brightness(drvthis); // restore brightness + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]); + + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[p->hw_brightness][1],\ + p->hw_cmd[p->hw_brightness][0]); // restore brightness for (i = 0; i < (p->height * p->width); i++) - p->backingstore[i] = '\0'; // clear Backing-store + p->backingstore[i]=0; // clear Backing-store - if (p->display_type != 1) {//not KD Rev 2.1 - for (i = 0; i < p->customchars; i++) // refresh all customcharacters - serialVFD_put_char(drvthis, i); -/* { - write(p->fd, &p->hw_cmd[set_user_char][1],\ - p->hw_cmd[set_user_char][0]);// substitute and select character to overwrite - write(p->fd, &p->usr_chr_mapping[i], 1); - write(p->fd, &p->custom_char[(int)dat[i]][0], p->usr_chr_dot_assignment[0]);// overwrite selected Character - }*/ - } + for(i=0;icustomchars;i++) // refresh all customcharacters + custom_char_changed[i]=1; p->refresh_timer = 0; } + p->refresh_timer++; + if (p->display_type != 1) { //not KD Rev 2.1 + for(i=0;icustomchars;i++) // set customcharacters + if(custom_char_changed[i]) + serialVFD_put_char (drvthis, i); + } + + if(custom_char_changed[p->last_custom]) + p->last_custom=-10; + for (i = 0; i < (p->height * p->width); i++) { + /* Backing-store implementation. If it's already * on the screen, don't put it there again */ - if (dat[i] != p->backingstore[i] || (dat[i] <=30 && p->custom_char_changed[(int)dat[i]])) - { - if (last_chr < i-1) { // if not last char written cursor has to be moved. - if (last_chr < i-2-p->hw_cmd[mv_cursor][0]) { - write(p->fd, &p->hw_cmd[mv_cursor][1], + if(p->framebuf[i] != p->backingstore[i] || (p->framebuf[i] <=30 && custom_char_changed[(int)p->framebuf[i]])) { + if (last_chr < i-1){ // if not last char written cursor has to be moved. + if(last_chr < i-2-p->hw_cmd[mv_cursor][0]) { + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[mv_cursor][1],\ p->hw_cmd[mv_cursor][0]); - write(p->fd, &i, 1); - } - else { - for (j = last_chr; j < (i-1); j++) { - write(p->fd, &p->hw_cmd[hor_tab][1], p->hw_cmd[hor_tab][0]); + Port_Function[p->use_parallel].write_fkt (drvthis, (char*)&i, 1); } + else { + for (j = last_chr; j < (i-1); j++) + Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[hor_tab][1], p->hw_cmd[hor_tab][0]); } } - if (dat[i] <= 30) {// custom character - if (p->display_type == 1) {// KD Rev 2.1 only - write(p->fd, "\x1A\xDB", 2); // substitute and select character to overwrite(237) - write(p->fd, &p->custom_char[(int)dat[i]][0], 7);// overwrite selected character - write(p->fd, "\xDB", 1); // write character + if(p->framebuf[i] <= 30) { // custom character + if (p->display_type == 1) { // KD Rev 2.1 only + if (p->last_custom != p->framebuf[i]){ + Port_Function[p->use_parallel].write_fkt (drvthis, "\x1A\xDB", 2); // substitute and select character to overwrite (237) + Port_Function[p->use_parallel].write_fkt (drvthis, &p->custom_char[(int)p->framebuf[i]][0], 7);// overwrite selected character + } + Port_Function[p->use_parallel].write_fkt (drvthis, "\xDB", 1); // write character + p->last_custom = p->framebuf[i]; } else { // all other displays - write(p->fd, &p->usr_chr_mapping[(int)dat[i]], 1); + Port_Function[p->use_parallel].write_fkt (drvthis, (char*)&p->usr_chr_mapping[(int)p->framebuf[i]], 1); } } - else if (dat[i] > 127 && (p->ISO_8859_1 != 0)) { // ISO_8859_1 translation for 129 ... 255 - write(p->fd, &p->charmap[dat[i] + 128], 1); + else if(p->framebuf[i] > 127 && (p->ISO_8859_1 != 0)) { // ISO_8859_1 translation for 129 ... 255 + Port_Function[p->use_parallel].write_fkt (drvthis, &p->charmap[p->framebuf[i] - 128], 1); } else { - write(p->fd, &dat[i], 1); + Port_Function[p->use_parallel].write_fkt (drvthis, &p->framebuf[i], 1); } last_chr = i; } } - if (last_chr != -10) { // update backingstore if something changed - int i; - - memcpy(p->backingstore, dat, p->height * p->width); - - for (i = 0; i < p->customchars; i++) - p->custom_char_changed[i] = '\0'; - } + if (last_chr != -10) // update backingstore if something changed + memcpy(p->backingstore, p->framebuf, p->height * p->width); } @@ -863,6 +501,7 @@ serialVFD_num( Driver * drvthis, int x, int num ) + /* * Places an icon on screen */ @@ -870,7 +509,7 @@ MODULE_EXPORT int serialVFD_icon (Driver *drvthis, int x, int y, int icon) { PrivateData *p = drvthis->private_data; - static unsigned char heart_open[] = + static unsigned char heart_open[] = { b__XXXXX, b__X_X_X, b_______, @@ -879,7 +518,7 @@ serialVFD_icon (Driver *drvthis, int x, int y, int icon) b__X___X, b__XX_XX, b__XXXXX }; - static unsigned char heart_filled[] = + static unsigned char heart_filled[] = { b__XXXXX, b__X_X_X, b___X_X_, @@ -969,6 +608,7 @@ MODULE_EXPORT void serialVFD_clear (Driver *drvthis) { PrivateData *p = drvthis->private_data; + memset(p->framebuf, ' ', p->width * p->height); } @@ -1001,17 +641,16 @@ MODULE_EXPORT void serialVFD_close (Driver *drvthis) { PrivateData *p = drvthis->private_data; - if (p != NULL) { - close(p->fd); - + if (p->fd >= 0) + close(p->fd); if (p->framebuf) free(p->framebuf); - if (p->backingstore) free(p->backingstore); free(p); } + drvthis->store_private_ptr(drvthis, NULL); } @@ -1073,16 +712,6 @@ serialVFD_cellheight (Driver *drvthis) } -MODULE_EXPORT void -serialVFD_flush (Driver *drvthis) -{ - PrivateData *p = drvthis->private_data; - - serialVFD_draw_frame(drvthis, p->framebuf); -} - - - ///////////////////////////////////////////////////////////////// // 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). @@ -1091,23 +720,14 @@ MODULE_EXPORT void serialVFD_chr (Driver *drvthis, int x, int y, char c) { PrivateData *p = drvthis->private_data; - + if ((x > p->width) || (y > p->height)) + return; y--; x--; + p->framebuf[(y * p->width) + x ] = c; } -///////////////////////////////////////////////////////////////// -// -// Retrieves brightness -// -MODULE_EXPORT int -serialVFD_get_brightness(Driver *drvthis, int state) -{ - PrivateData *p = drvthis->private_data; - - return p->brightness; -} ///////////////////////////////////////////////////////////////// // provides some info about this driver @@ -1116,7 +736,6 @@ MODULE_EXPORT const char * serialVFD_get_info (Driver *drvthis) { PrivateData *p = drvthis->private_data; - strcpy(p->info, "Driver for many serialVFDs from NEC(all FIPC based), Noritake, Futaba and the \"KD Rev2.1\"VFD."); return p->info; } diff --git a/server/drivers/serialVFD.h b/server/drivers/serialVFD.h index 3eef2e6..f4a09da 100644 --- a/server/drivers/serialVFD.h +++ b/server/drivers/serialVFD.h @@ -6,7 +6,7 @@ driver. It may contain parts of other drivers of this package too. - 2006-02-13 Version 0.2: everything should work (not all hardware tested!) + 2006-05-16 Version 0.3: everything should work (not all hardware tested!) 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 @@ -26,6 +26,8 @@ #define SERIALVFD_H #include "lcd.h" #include "adv_bignum.h" +#include "serialVFD_displays.h" +#include "serialVFD_io.h" #define CCMODE_STANDARD 0 /* only char 0 is used for heartbeat */ #define CCMODE_VBAR 1 @@ -63,8 +65,43 @@ MODULE_EXPORT void serialVFD_set_char (Driver *drvthis, int n, unsigned char *da MODULE_EXPORT int serialVFD_get_brightness (Driver *drvthis, int state); MODULE_EXPORT void serialVFD_set_brightness (Driver *drvthis, int state, int promille); +MODULE_EXPORT void serialVFD_backlight (Driver *drvthis, int on); MODULE_EXPORT void serialVFD_output (Driver *drvthis, int state); MODULE_EXPORT void serialVFD_num (Driver * drvthis, int x, int num); MODULE_EXPORT int serialVFD_get_free_chars (Driver *drvthis); MODULE_EXPORT const char * serialVFD_get_info( Driver *drvthis ); + +typedef struct driver_private_data { + int use_parallel; // use parallel? + unsigned int port; // Port in parallel mode + char device[200]; // Device in serial mode + int fd; + int speed; // Speed in serial mode + /* dimensions */ + int width, height; + int cellwidth, cellheight; + /* framebuffer and buffer for old LCD contents */ + unsigned char *framebuf; + unsigned char *backingstore; + /* defineable characters */ + int ccmode; + int on_brightness; + int off_brightness; + int hw_brightness; + int customchars; + int ISO_8859_1; + unsigned int refresh_timer; + unsigned char charmap[128]; + int display_type; // display type + int last_custom; // last custom character written + char custom_char[31][7]; // stored custom characters + char custom_char_store[31][7]; // custom characters backingstore + char hw_cmd[10][4]; // hardwarespecific commands + int usr_chr_dot_assignment[57]; // how to setup usercharacters + unsigned int usr_chr_mapping[31];// where to place the usercharacters (0..30) in the asciicode + int hbar_cc_offset; // character offset of the bars + int vbar_cc_offset; // character offset of the bars + char info[255]; +} PrivateData; + #endif