Base: LCDproc 0.5.2
[lcdproc-de200c.git] / server / drivers / ea65.c
blobafea52a9752112dbadeff4983d41fd95acedbe08
1 /* This is the LCDproc driver for the vfd on the Aopen EA65, based on
2 the Crystal Fontz driver.
4 Copyright (C) 2004 ????
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 */
20 /*Initial modification of CFontz driver by Kent Williams (c) 2005*/
21 /*some additions and updates by Karsten Festag (c) 2007*/
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <termios.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <syslog.h>
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
36 #include "lcd.h"
37 #include "ea65.h"
38 #include "report.h"
39 #include "lcd_lib.h"
41 typedef struct driver_private_data {
42 int fd;
43 int brightness;
44 int offbrightness;
45 int width;
46 int height;
47 unsigned char *framebuf;
48 } PrivateData;
50 // Vars for the server core
51 MODULE_EXPORT char *api_version = API_VERSION;
52 MODULE_EXPORT int stay_in_foreground = 1;
53 MODULE_EXPORT int supports_multiple = 0;
54 MODULE_EXPORT int does_input = 0;
55 MODULE_EXPORT int does_output = 1;
56 MODULE_EXPORT char *symbol_prefix = "EA65_";
58 /////////////////////////////////////////////////////////////////
59 // Opens com port and sets baud correctly...
61 MODULE_EXPORT int
62 EA65_init (Driver *drvthis)
64 debug(RPT_INFO, "EA65: init(%p)", drvthis);
66 /* device is fixed */
67 char device[] = "/dev/ttyS1";
68 /*speed is fixed at 9600*/
69 int speed = B9600;
71 /* Allocate and store private data */
72 PrivateData *p;
73 p = (PrivateData *) malloc(sizeof(PrivateData));
74 if (p == NULL)
75 return -1;
76 if (drvthis->store_private_ptr(drvthis, p))
77 return -1;
79 //// initialize private data
80 // Width and Height are fixed
81 p->width = 9;
82 p->height = 1;
83 // Make sure the frame buffer is there...
84 p->framebuf = (unsigned char *) malloc (p->width * p->height);
85 memset (p->framebuf, ' ', p->width * p->height);
87 //// Read config file
88 // Which backlight brightness
89 p->brightness = drvthis->config_get_int ( drvthis->name , "Brightness" , 0 , DEFAULT_BRIGHTNESS);
90 if (0 <= p->brightness && p->brightness <= 1000) {
91 if (p->brightness < 300) {
92 p->brightness = 0x00; // command char that turns button LEDs off
93 } else if (p->brightness >= 700 ) {
94 p->brightness = 0x01; // command char that turns button LEDs on full
95 } else {
96 p->brightness = 0x02; // command char that turns button LEDs on half
98 } else {
99 report (RPT_WARNING, "EA65_init: Brightness must be between 0 and 1000. Using default value.\n");
100 p->brightness = DEFAULT_BRIGHTNESS;
103 // Which backlight-off "brightness"
104 p->offbrightness = drvthis->config_get_int ( drvthis->name , "OffBrightness" , 0 , DEFAULT_OFFBRIGHTNESS);
105 if (0 <= p->offbrightness && p->offbrightness <= 1000) {
106 if (p->offbrightness < 300) {
107 p->offbrightness = 0x00; // command char that turns button LEDs off
108 } else if (p->offbrightness >= 700) {
109 p->offbrightness = 0x01; // command char that turns button LEDs on full
110 } else {
111 p->offbrightness = 0x02; // command char that turns button LEDs on half
113 } else {
114 report (RPT_WARNING, "EA65_init: OffBrightness must be between 0 and 1000. Using default value.\n");
115 p->offbrightness = DEFAULT_OFFBRIGHTNESS;
118 // Set up io port correctly, and open it...
119 debug( RPT_DEBUG, "EA65: Opening serial device: %s", device);
120 struct termios portset;
121 p->fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY);
122 if (p->fd == -1) {
123 report (RPT_ERR, "EA65_init: failed (%s)\n", strerror (errno));
124 return -1;
126 tcgetattr (p->fd, &portset);
128 #ifdef HAVE_CFMAKERAW
129 // The easy way
130 cfmakeraw( &portset );
131 #else
132 // The hard way
133 portset.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP
134 | INLCR | IGNCR | ICRNL | IXON );
135 portset.c_oflag &= ~OPOST;
136 portset.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
137 portset.c_cflag &= ~( CSIZE | PARENB | CRTSCTS );
138 portset.c_cflag |= CS8 | CREAD | CLOCAL ;
139 #endif
141 // Set port speed
142 cfsetospeed (&portset, speed);
143 cfsetispeed (&portset, B0);
145 // Do it...
146 tcsetattr (p->fd, TCSANOW, &portset);
148 report (RPT_DEBUG, "EA65_init: done\n");
150 return 0;
153 /////////////////////////////////////////////////////////////////
154 // Clean-up
156 MODULE_EXPORT void
157 EA65_close (Driver *drvthis)
159 PrivateData *p = (PrivateData *) drvthis->private_data;
161 close (p->fd);
163 if(p->framebuf) free (p->framebuf);
164 p->framebuf = NULL;
167 /////////////////////////////////////////////////////////////////
168 // Returns the display width
170 MODULE_EXPORT int
171 EA65_width (Driver *drvthis)
173 PrivateData *p = (PrivateData *) drvthis->private_data;
175 return p->width;
178 /////////////////////////////////////////////////////////////////
179 // Returns the display height
181 MODULE_EXPORT int
182 EA65_height (Driver *drvthis)
184 PrivateData *p = (PrivateData *) drvthis->private_data;
186 return p->height;
189 //////////////////////////////////////////////////////////////////
190 // Flushes all output to the lcd...
192 MODULE_EXPORT void
193 EA65_flush (Driver *drvthis)
195 char out[6];
196 int i;
197 PrivateData *p = (PrivateData *) drvthis->private_data;
199 // Need to check for and deal with unsupported chars or the display gets a little upset
200 for (i=0; i < p->width * p->height; i++) {
201 if ( (p->framebuf[i] >= 224 && p->framebuf[i] <= 253) || // is a lowercase accented letter
202 (p->framebuf[i] >= 97 && p->framebuf[i] <= 122) ) { // is a lowercase letter
203 p->framebuf[i] -= 32; // -> convert to upper case
205 if (p->framebuf[i] >= 48 && p->framebuf[i] <= 57) { } // is a number -> do nothing
206 else if (p->framebuf[i] >= 65 && p->framebuf[i] <= 90) { } // is a uppercase letter -> do nothing
207 else if (p->framebuf[i] == 42 || p->framebuf[i] == 43 ||
208 p->framebuf[i] == 45 || p->framebuf[i] == 47 ) { } // is +,-,/,* -> do nothing
209 // Now lets replace some accented characters with remotely similar looking ones
210 else if (p->framebuf[i] == 223) p->framebuf[i] = 83; // use an "S" instead of "ß"
211 else if (p->framebuf[i] >= 192 && p->framebuf[i] <= 197) // use an "A"
212 p->framebuf[i] = 65;
213 else if (p->framebuf[i] >= 200 && p->framebuf[i] <= 203) // use an "E"
214 p->framebuf[i] = 69;
215 else if (p->framebuf[i] >= 204 && p->framebuf[i] <= 207) // use an "I"
216 p->framebuf[i] = 73;
217 else if (p->framebuf[i] >= 210 && p->framebuf[i] <= 214) // use an "O"
218 p->framebuf[i] = 79;
219 else if (p->framebuf[i] >= 217 && p->framebuf[i] <= 220) // use an "U"
220 p->framebuf[i] = 85;
221 else p->framebuf[i] = 32; // other characters replaced by a space
223 snprintf(out, sizeof(out), "%c%c%c%c%c", 0xa0, 0x00, 0x80, 0x8a, 0x8a);
224 write(p->fd, out, 5);
225 write(p->fd, p->framebuf, p->width * p->height);
228 /////////////////////////////////////////////////////////////////
229 // Prints a character on the lcd display, at position (x,y). The
230 // upper-left is (1,1), and the lower right should be (9,1).
232 MODULE_EXPORT void
233 EA65_chr (Driver *drvthis, int x, int y, char c)
235 PrivateData *p = (PrivateData *) drvthis->private_data;
237 y--;
238 x--;
240 //if (c < 32 && c >= 0)
241 // c += 128;
243 // For V2 of the firmware to get the block to display right
244 //if (newfirmware && c==-1) {
245 // c=214;
248 p->framebuf[(y * p->width) + x] = c;
251 /////////////////////////////////////////////////////////////////
252 // Sets the backlight on or off
254 MODULE_EXPORT void
255 EA65_backlight (Driver *drvthis, int on)
257 PrivateData *p = (PrivateData *) drvthis->private_data;
259 char out[6];
260 if (on) {
261 snprintf (out, sizeof(out), "%c%c%c%c%c", 0xa0, 0x00, 0x50, 0x81, p->brightness);
262 } else {
263 snprintf (out, sizeof(out), "%c%c%c%c%c", 0xa0, 0x00, 0x50, 0x81, p->offbrightness);
265 write (p->fd, out, 5);
268 /////////////////////////////////////////////////////////////////
269 // Clears the LCD screen
271 MODULE_EXPORT void
272 EA65_clear (Driver *drvthis)
274 PrivateData *p = (PrivateData *) drvthis->private_data;
276 memset (p->framebuf, ' ', p->width * p->height);
280 /////////////////////////////////////////////////////////////////
281 // Prints a string on the lcd display, at position (x,y). The
282 // upper-left is (1,1), and the lower right should be (9,1).
284 MODULE_EXPORT void
285 EA65_string (Driver *drvthis, int x, int y, const char string[])
287 PrivateData *p = (PrivateData *) drvthis->private_data;
289 int i;
291 x -= 1; // Convert 1-based coords to 0-based...
292 y -= 1;
294 for (i = 0; string[i]; i++) {
296 // Check for buffer overflows...
297 if ((y * p->width) + x + i > (p->width * p->height))
298 break;
299 p->framebuf[(y * p->width) + x + i] = string[i];
303 /////////////////////////////////////////////////////////////////
304 //// Turns the recording LED on or off as desired.
305 ////
306 MODULE_EXPORT void
307 EA65_output (Driver *drvthis, int on)
309 PrivateData *p = (PrivateData *) drvthis->private_data;
311 char out[6];
312 if (on) {
313 snprintf (out, sizeof(out), "%c%c%c%c%c", 0xa0,0x00,0x32,0x81,0x01);
314 } else {
315 snprintf (out, sizeof(out), "%c%c%c%c%c", 0xa0,0x00,0x32,0x81,0x00);
317 write (p->fd, out, 5);