root/tags/0.10.0/drv_Cwlinux.c

Revision 547, 11.8 kB (checked in by reinelt, 4 years ago)

[lcd4linux @ 2005-05-08 04:32:43 by reinelt]
CodingStyle? added and applied

Line 
1/* $Id: drv_Cwlinux.c,v 1.22 2005/05/08 04:32:44 reinelt Exp $
2 *
3 * new style driver for Cwlinux display modules
4 *
5 * Copyright (C) 1999, 2000 Michael Reinelt <reinelt@eunet.at>
6 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
7 *
8 * This file is part of LCD4Linux.
9 *
10 * LCD4Linux is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * LCD4Linux is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *
25 * $Log: drv_Cwlinux.c,v $
26 * Revision 1.22  2005/05/08 04:32:44  reinelt
27 * CodingStyle added and applied
28 *
29 * Revision 1.21  2005/01/18 06:30:22  reinelt
30 * added (C) to all copyright statements
31 *
32 * Revision 1.20  2004/11/28 15:50:24  reinelt
33 * Cwlinux fixes (invalidation of user-defined chars)
34 *
35 * Revision 1.19  2004/06/26 12:04:59  reinelt
36 *
37 * uh-oh... the last CVS log message messed up things a lot...
38 *
39 * Revision 1.18  2004/06/26 09:27:20  reinelt
40 *
41 * added '-W' to CFLAGS
42 * changed all C++ comments to C ones
43 * cleaned up a lot of signed/unsigned mistakes
44 *
45 * Revision 1.17  2004/06/20 10:09:54  reinelt
46 *
47 * 'const'ified the whole source
48 *
49 * Revision 1.16  2004/06/06 06:51:59  reinelt
50 *
51 * do not display end splash screen if quiet=1
52 *
53 * Revision 1.15  2004/06/05 14:56:48  reinelt
54 *
55 * Cwlinux splash screen fixed
56 * USBLCD splash screen fixed
57 * plugin_i2c qprintf("%f") replaced with snprintf()
58 *
59 * Revision 1.14  2004/06/05 06:41:39  reinelt
60 *
61 * chancged splash screen again
62 *
63 * Revision 1.13  2004/06/05 06:13:11  reinelt
64 *
65 * splash screen for all text-based display drivers
66 *
67 * Revision 1.12  2004/06/02 09:41:19  reinelt
68 *
69 * prepared support for startup splash screen
70 *
71 * Revision 1.11  2004/06/01 06:45:29  reinelt
72 *
73 * some Fixme's processed
74 * documented some code
75 *
76 * Revision 1.10  2004/05/31 21:05:13  reinelt
77 *
78 * fixed lots of bugs in the Cwlinux driver
79 * do not emit EAGAIN error on the first retry
80 * made plugin_i2c_sensors a bit less 'chatty'
81 * moved init and exit functions to the bottom of plugin_pop3
82 *
83 * Revision 1.9  2004/05/31 16:39:06  reinelt
84 *
85 * added NULL display driver (for debugging/profiling purposes)
86 * added backlight/contrast initialisation for matrixOrbital
87 * added Backlight initialisation for Cwlinux
88 *
89 * Revision 1.8  2004/05/31 05:38:02  reinelt
90 *
91 * fixed possible bugs with user-defined chars (clear high bits)
92 * thanks to Andy Baxter for debugging the MilfordInstruments driver!
93 *
94 * Revision 1.7  2004/05/28 13:51:42  reinelt
95 *
96 * ported driver for Beckmann+Egle Mini-Terminals
97 * added 'flags' parameter to serial_init()
98 *
99 * Revision 1.6  2004/05/27 03:39:47  reinelt
100 *
101 * changed function naming scheme to plugin::function
102 *
103 * Revision 1.5  2004/05/26 11:37:36  reinelt
104 *
105 * Curses driver ported.
106 *
107 * Revision 1.4  2004/03/19 09:17:46  reinelt
108 *
109 * removed the extra 'goto' function, row and col are additional parameters
110 * of the write() function now.
111 *
112 * Revision 1.3  2004/02/14 11:56:17  reinelt
113 * M50530 driver ported
114 * changed lots of 'char' to 'unsigned char'
115 *
116 * Revision 1.2  2004/01/29 04:40:02  reinelt
117 * every .c file includes "config.h" now
118 *
119 * Revision 1.1  2004/01/27 06:34:14  reinelt
120 * Cwlinux driver portet to NextGeneration (compiles, but not tested!)
121 *
122 */
123
124/*
125 *
126 * exported fuctions:
127 *
128 * struct DRIVER drv_Cwlinux
129 *
130 */
131
132#include "config.h"
133
134#include <stdlib.h>
135#include <stdio.h>
136#include <string.h>
137#include <unistd.h>
138
139#include "debug.h"
140#include "cfg.h"
141#include "qprintf.h"
142#include "plugin.h"
143#include "widget.h"
144#include "widget_text.h"
145#include "widget_icon.h"
146#include "widget_bar.h"
147#include "drv.h"
148#include "drv_generic_text.h"
149#include "drv_generic_serial.h"
150
151
152static char Name[] = "Cwlinux";
153
154static int Model;
155static int Protocol;
156
157/* Fixme: GPO's not yet implemented */
158/* static int GPO[8]; */
159static int GPOS;
160
161
162typedef struct {
163    int type;
164    char *name;
165    int rows;
166    int cols;
167    int xres;
168    int gpos;
169    int protocol;
170} MODEL;
171
172
173/* Fixme: number of gpo's should be verified */
174
175static MODEL Models[] = {
176    {0x01, "CW1602", 2, 16, 5, 0, 1},
177    {0x02, "CW12232", 4, 20, 6, 0, 2},
178    {0xff, "Unknown", -1, -1, -1, -1, -1}
179};
180
181
182/****************************************/
183/***  hardware dependant functions    ***/
184/****************************************/
185
186static void drv_CW_send(const char *string, const int len)
187{
188    drv_generic_serial_write(string, len);
189    usleep(20);
190}
191
192
193static void drv_CW_write(const int row, const int col, const char *data, const int len)
194{
195    char cmd[6] = "\376Gxy\375";
196
197    cmd[2] = (char) col;
198    cmd[3] = (char) row;
199    drv_CW_send(cmd, 5);
200    drv_CW_send(data, len);
201}
202
203
204static void drv_CW1602_defchar(const int ascii, const unsigned char *buffer)
205{
206    int i;
207    char cmd[12] = "\376Nn12345678\375";
208
209    cmd[2] = (char) ascii;
210
211    for (i = 0; i < 8; i++) {
212  cmd[3 + i] = buffer[i] & 0x1f;
213    }
214    drv_CW_send(cmd, 12);
215}
216
217
218static void drv_CW12232_defchar(const int ascii, const unsigned char *buffer)
219{
220    int i, j;
221    char cmd[10] = "\376Nn123456\375";
222
223    cmd[2] = (char) ascii;
224
225    /* The CW12232 uses a vertical bitmap layout, */
226    /* so we have to 'rotate' the bitmap. */
227
228    for (i = 0; i < 6; i++) {
229  cmd[3 + i] = 0;
230  for (j = 0; j < 8; j++) {
231      if (buffer[j] & (1 << (5 - i))) {
232    cmd[3 + i] |= (1 << j);
233      }
234  }
235    }
236    drv_CW_send(cmd, 10);
237}
238
239
240static void drv_CW_clear(void)
241{
242#if 1
243    drv_CW_send("\376X\375", 3);  /* Clear Display */
244    usleep(500000);
245#else
246    /* for some mysterious reason, we have to sleep after  */
247    /* the command _and_ after the CMD_END... */
248    drv_CW_send("\376X", 2);  /* Clear Display */
249    drv_CW_send("\375", 1); /* Command End */
250#endif
251}
252
253
254static int drv_CW_brightness(int brightness)
255{
256    static unsigned char Brightness = 0;
257    char cmd[5] = "\376A_\375";
258
259    /* -1 is used to query the current brightness */
260    if (brightness == -1)
261  return Brightness;
262
263    if (brightness < 0)
264  brightness = 0;
265    if (brightness > 255)
266  brightness = 255;
267    Brightness = brightness;
268
269    switch (Brightness) {
270    case 0:
271  /* backlight off */
272  drv_CW_send("\376F\375", 3);
273  break;
274    case 8:
275  /* backlight on */
276  drv_CW_send("\376B\375", 3);
277  break;
278    default:
279  /* backlight level */
280  cmd[2] = (char) Brightness;
281  drv_CW_send(cmd, 4);
282  break;
283    }
284
285    return Brightness;
286}
287
288
289static int drv_CW_start(const char *section)
290{
291    int i;
292    char *model;
293
294    model = cfg_get(section, "Model", NULL);
295    if (model != NULL && *model != '\0') {
296  for (i = 0; Models[i].type != 0xff; i++) {
297      if (strcasecmp(Models[i].name, model) == 0)
298    break;
299  }
300  if (Models[i].type == 0xff) {
301      error("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source());
302      return -1;
303  }
304  Model = i;
305  info("%s: using model '%s'", Name, Models[Model].name);
306    } else {
307  error("%s: no '%s.Model' entry from %s", Name, section, cfg_source());
308  return -1;
309    }
310
311    /* open serial port */
312    if (drv_generic_serial_open(section, Name, 0) < 0)
313  return -1;
314
315    /* this does not work as I'd expect it... */
316#if 0
317    /* read firmware version */
318    generic_serial_read(buffer, sizeof(buffer));
319    usleep(100000);
320    generic_serial_write("\3761", 2);
321    usleep(100000);
322    generic_serial_write("\375", 1);
323    usleep(100000);
324    if (generic_serial_read(buffer, 2) != 2) {
325  info("unable to read firmware version!");
326    }
327    info("Cwlinux Firmware %d.%d", (int) buffer[0], (int) buffer[1]);
328#endif
329
330    /* initialize global variables */
331    DROWS = Models[Model].rows;
332    DCOLS = Models[Model].cols;
333    XRES = Models[Model].xres;
334    GPOS = Models[Model].gpos;
335    Protocol = Models[Model].protocol;
336
337    drv_CW_clear();
338
339    drv_CW_send("\376D\375", 3);  /* auto line wrap off */
340    drv_CW_send("\376R\375", 3);  /* auto scroll off */
341    drv_CW_send("\376K\375", 3);  /* underline cursor off */
342    drv_CW_send("\376B\375", 3);  /* backlight on */
343
344    /* set brightness */
345    if (cfg_number(section, "Brightness", 0, 0, 8, &i) > 0) {
346  drv_CW_brightness(i);
347    }
348
349    return 0;
350}
351
352
353/****************************************/
354/***            plugins               ***/
355/****************************************/
356
357
358static void plugin_brightness(RESULT * result, const int argc, RESULT * argv[])
359{
360    double brightness;
361
362    switch (argc) {
363    case 0:
364  brightness = drv_CW_brightness(-1);
365  SetResult(&result, R_NUMBER, &brightness);
366  break;
367    case 1:
368  brightness = drv_CW_brightness(R2N(argv[0]));
369  SetResult(&result, R_NUMBER, &brightness);
370  break;
371    default:
372  error("%s.brightness(): wrong number of parameters", Name);
373  SetResult(&result, R_STRING, "");
374    }
375}
376
377
378/****************************************/
379/***        widget callbacks          ***/
380/****************************************/
381
382/* using drv_generic_text_draw(W) */
383/* using drv_generic_text_icon_draw(W) */
384/* using drv_generic_text_bar_draw(W) */
385
386
387/****************************************/
388/***        exported functions        ***/
389/****************************************/
390
391
392/* list models */
393int drv_CW_list(void)
394{
395    int i;
396
397    for (i = 0; Models[i].type != 0xff; i++) {
398  printf("%s ", Models[i].name);
399    }
400    return 0;
401}
402
403
404/* initialize driver & display */
405int drv_CW_init(const char *section, const int quiet)
406{
407    WIDGET_CLASS wc;
408    int ret;
409
410    /* display preferences */
411    XRES = 6;     /* pixel width of one char  */
412    YRES = 8;     /* pixel height of one char  */
413    CHARS = 16;     /* number of user-defineable characters */
414    CHAR0 = 1;      /* ASCII of first user-defineable char */
415    GOTO_COST = 3;    /* number of bytes a goto command requires */
416    INVALIDATE = 1;   /* re-defined chars must be re-sent to the display */
417
418    /* start display */
419    if ((ret = drv_CW_start(section)) != 0)
420  return ret;
421
422    /* real worker functions */
423    drv_generic_text_real_write = drv_CW_write;
424
425    switch (Protocol) {
426    case 1:
427  drv_generic_text_real_defchar = drv_CW1602_defchar;
428  break;
429    case 2:
430  drv_generic_text_real_defchar = drv_CW12232_defchar;
431  break;
432    }
433
434    if (!quiet) {
435  char buffer[40];
436  qprintf(buffer, sizeof(buffer), "%s %s", Name, Models[Model].name);
437  if (drv_generic_text_greet(buffer, "www.cwlinux.com")) {
438      sleep(3);
439      drv_CW_clear();
440  }
441    }
442
443    /* initialize generic text driver */
444    if ((ret = drv_generic_text_init(section, Name)) != 0)
445  return ret;
446
447    /* initialize generic icon driver */
448    if ((ret = drv_generic_text_icon_init()) != 0)
449  return ret;
450
451    /* initialize generic bar driver */
452    if ((ret = drv_generic_text_bar_init(0)) != 0)
453  return ret;
454
455    /* add fixed chars to the bar driver */
456    drv_generic_text_bar_add_segment(0, 0, 255, 32);  /* ASCII 32 = blank */
457
458    /* register text widget */
459    wc = Widget_Text;
460    wc.draw = drv_generic_text_draw;
461    widget_register(&wc);
462
463    /* register icon widget */
464    wc = Widget_Icon;
465    wc.draw = drv_generic_text_icon_draw;
466    widget_register(&wc);
467
468    /* register bar widget */
469    wc = Widget_Bar;
470    wc.draw = drv_generic_text_bar_draw;
471    widget_register(&wc);
472
473    /* register plugins */
474    AddFunction("LCD::brightness", -1, plugin_brightness);
475
476    return 0;
477}
478
479
480/* close driver & display */
481int drv_CW_quit(const int quiet)
482{
483
484    info("%s: shutting down.", Name);
485    drv_generic_text_quit();
486
487    /* clear display */
488    drv_CW_clear();
489
490    /* say goodbye... */
491    if (!quiet) {
492  drv_generic_text_greet("goodbye!", NULL);
493    }
494
495    drv_generic_serial_close();
496
497    return (0);
498}
499
500
501DRIVER drv_Cwlinux = {
502  name:Name,
503  list:drv_CW_list,
504  init:drv_CW_init,
505  quit:drv_CW_quit,
506};
Note: See TracBrowser for help on using the browser.