root/trunk/drv_SimpleLCD.c

Revision 771, 9.0 kB (checked in by michael, 21 months ago)

lots of compiler warnings removed, C++-style comments removed, changed struc initialisation from 'field:value' to '.field=value'

  • Property svn:keywords set to Id URL Rev
Line 
1/* $Id$
2 * $URL$
3 *
4 * driver for a simple serial terminal.
5 *
6 * Copyright (C) 2005 Julien Aube <ob@obconseil.net>
7 * Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
8 *
9 * This file is part of LCD4Linux.
10 *
11 * LCD4Linux is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * LCD4Linux is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27/*
28 * This driver simply send out caracters on the serial port, without any
29 * formatting instructions for a particular LCD device.
30 * This is useful for custom boards of for very simple LCD.
31 *
32 * I use it for tests on a custom-made board based on a AVR microcontroler
33 * and also for driver a Point-of-Sale text-only display.
34 * I assume the following :
35 * - CR (0x0d) Return to the begining of the line without erasing,
36 * - LF (0x0a) Initiate a new line (but without sending the cursor to
37 * the begining of the line)
38 * - BS (0x08) Move the cursor to the previous caracter (but does no erase it).
39 * - It's not possible to return to the first line. Thus a back buffer is used
40 * in this driver.
41 *
42 * ******** UPDATE *********
43 * I have added a "VT-100 Compatible mode" that allows the driver to support
44 * control-sequence code. This greatly reduce flickering and eliminate the need
45 * for the back-buffer. But it is optional since all displays cannot support them.
46 * Here are the codes:
47 * Delete the display (but does not move the cursor) :
48 *    "ESC [ 2 J"     (0x1b 0x5b 0x32 0x4a)
49 * Position the cursor :
50 *    "ESC [ YY ; XX H" ( 0x1b 0x5b YY 0x3b XX 0x48 ) where YY is the ascii for the line
51 *    number, and XX is the ascii for the column number ( first line/column is '1', not zero)
52 * Delete to the end of line from current cursor position :
53 *    "ESC [ 0 K" ( 0x1b 0x5b 0x30 0x4b )
54 * Set Country Code :
55 *    "ESC R NN"  (0x1b 0x52 NN) where NN is the country code *in byte, NOT ascii*.
56 *    The default is 0 (USA), see below for specific countries.
57 *    the list of accessible characters page are available on this page :
58 *    http://www.wincor-nixdorf.com/internet/com/Services/Support/TechnicalSupport/POSSystems
59 *    /Manuals/BAxx/index.html
60 * Get the display identification : (Doesn't work reliably, timing issues here)
61 *    "ESC [ 0 c" ( 0x1b 0x5b 0x30 0x63). Return a string which look like this :
62 *  ESC [ ? M ; NN ; OO ; PP ; QQ c) where M is type of display (2 for VFD),
63 *  NN is the rom version, 00 is the current caracter set, PP is the number of lines and
64 *  QQ the number of colomns. 
65 *
66 *
67 * A "bar" capability is now provided if the config file has a "BarCharValue" parameter in it.
68 *
69 * The code come mostly taken from the LCDTerm driver in LCD4Linux, from
70 * Michaels Reinelt, many thanks to him.
71 *
72 * This driver is released under the GPL.
73 */
74
75/*
76 *
77 * exported fuctions:
78 *
79 * struct DRIVER drv_SimpleLCD
80 *
81 */
82
83#include "config.h"
84
85#include <stdlib.h>
86#include <unistd.h>
87#include <string.h>
88
89#include "debug.h"
90#include "cfg.h"
91#include "qprintf.h"
92#include "plugin.h"
93#include "widget.h"
94#include "widget_text.h"
95#include "widget_icon.h"
96#include "widget_bar.h"
97#include "drv.h"
98#include "drv_generic_text.h"
99#include "drv_generic_serial.h"
100
101
102static char Name[] = "SimpleLCD";
103static char *backbuffer = 0;
104static int backbuffer_size = 0;
105static int vt100_mode = 0;
106static unsigned char bar_char = 0;
107
108/****************************************/
109/***  hardware dependant functions    ***/
110/****************************************/
111
112/** No clear function on SimpleLCD : Just send CR-LF * number of lines **/
113static void drv_SL_simple_clear(void)
114{
115    char cmd[2];
116    int i;
117    cmd[0] = '\r';
118    cmd[1] = '\n';
119    for (i = 0; i < DROWS; ++i) {
120  drv_generic_serial_write(cmd, 2);
121    }
122    memset(backbuffer, ' ', backbuffer_size);
123}
124
125/** vt-100 mode : send the ESC-code **/
126static void drv_SL_vt100_clear(void)
127{
128    char cmd[4];
129    cmd[0] = 0x1b;
130    cmd[1] = '[';
131    cmd[2] = '2';
132    cmd[3] = 'J';
133    drv_generic_serial_write(cmd, 4);
134
135}
136
137static void drv_SL_clear(void)
138{
139    vt100_mode == 1 ? drv_SL_vt100_clear() : drv_SL_simple_clear();
140}
141
142
143/* If full_commit = true, then the whole buffer is to be sent to screen.
144   if full_commit = false, then only the last line is to be sent (faster on slow screens)
145*/
146
147static void drv_SL_commit(int full_commit)
148{
149    int row;
150    char cmd[2] = { '\r', '\n' };
151    if (full_commit) {
152  for (row = 0; row < DROWS; row++) {
153      drv_generic_serial_write(cmd, 2);
154      drv_generic_serial_write(backbuffer + (DCOLS * row), DCOLS);
155  }
156    } else {
157  drv_generic_serial_write(cmd, 1); /* Go to the beginning of the line only */
158  drv_generic_serial_write(backbuffer + (DCOLS * (DROWS - 1)), DCOLS);
159    }
160}
161
162static void drv_SL_simple_write(const int row, const int col, const char *data, int len)
163{
164    memcpy(backbuffer + (row * DCOLS) + col, data, len);
165    if (row == DROWS - 1)
166  drv_SL_commit(0);
167    else
168  drv_SL_commit(1);
169}
170
171static void drv_SL_vt100_write(const int row, const int col, const char *data, int len)
172{
173    char cmd[8];
174    cmd[0] = 0x1b;
175    cmd[1] = '[';
176    cmd[2] = row + '1';
177    cmd[3] = ';';
178    cmd[4] = (col / 10) + '0';
179    cmd[5] = (col % 10) + '1';
180    cmd[6] = 'H';
181    drv_generic_serial_write(cmd, 7);
182    drv_generic_serial_write(data, len);
183}
184
185
186static int drv_SL_start(const char *section, const int quiet)
187{
188    int rows = -1, cols = -1;
189    int value;
190    unsigned int flags = 0;
191    char *s;
192    char *model = 0;
193
194    vt100_mode = 0;
195    model = cfg_get(section, "Model", "generic");
196    if (model != NULL && *model != '\0') {
197  if (strcasecmp("vt100", model) == 0)
198      vt100_mode = 1;
199    }
200
201    cfg_number(section, "BarCharValue", 0, 0, 255, &value);
202    bar_char = value;
203    cfg_number(section, "Options", 0, 0, 0xffff, &value);
204    flags = value;
205    if (drv_generic_serial_open(section, Name, flags) < 0)
206  return -1;
207
208    s = cfg_get(section, "Size", NULL);
209    if (s == NULL || *s == '\0') {
210  error("%s: no '%s.Size' entry from %s", Name, section, cfg_source());
211  return -1;
212    }
213    if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) {
214  error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source());
215  free(s);
216  return -1;
217    }
218
219    DROWS = rows;
220    DCOLS = cols;
221
222    if (!vt100_mode) {
223  backbuffer_size = DROWS * DCOLS;
224  backbuffer = malloc(backbuffer_size);
225  if (!backbuffer) {
226      return -1;
227  }
228    }
229
230    /* real worker functions */
231    if (vt100_mode) {
232  drv_generic_text_real_write = drv_SL_vt100_write;
233    } else {
234  drv_generic_text_real_write = drv_SL_simple_write;
235    }
236
237    drv_SL_clear();   /* clear */
238
239
240    if (!quiet) {
241  char buffer[40];
242  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
243  if (drv_generic_text_greet(buffer, NULL)) {
244      sleep(3);
245      drv_SL_clear();
246  }
247    }
248
249    return 0;
250}
251
252
253/****************************************/
254/***            plugins               ***/
255/****************************************/
256
257/* none */
258
259
260/****************************************/
261/***        widget callbacks          ***/
262/****************************************/
263
264
265/* using drv_generic_text_draw(W) */
266
267
268/****************************************/
269/***        exported functions        ***/
270/****************************************/
271
272
273/* list models */
274int drv_SL_list(void)
275{
276    printf("generic vt100");
277    return 0;
278}
279
280
281/* initialize driver & display */
282int drv_SL_init(const char *section, const int quiet)
283{
284    WIDGET_CLASS wc;
285    int ret;
286
287    info("%s: %s", Name, "$Rev$");
288
289    /* display preferences */
290    XRES = 5;     /* pixel width of one char  */
291    YRES = 8;     /* pixel height of one char  */
292    CHARS = 0;      /* number of user-defineable characters */
293    CHAR0 = 0;      /* ASCII of first user-defineable char */
294
295    GOTO_COST = -1;   /* number of bytes a goto command requires */
296
297
298    /* start display */
299    if ((ret = drv_SL_start(section, quiet)) != 0)
300  return ret;
301
302    /* initialize generic text driver */
303    if ((ret = drv_generic_text_init(section, Name)) != 0)
304  return ret;
305
306    /* register text widget */
307    wc = Widget_Text;
308    wc.draw = drv_generic_text_draw;
309    widget_register(&wc);
310
311    /* register plugins */
312    /* none */
313
314    return 0;
315}
316
317
318/* close driver & display */
319int drv_SL_quit(const int quiet)
320{
321
322    info("%s: shutting down.", Name);
323
324    drv_generic_text_quit();
325
326    /* clear display */
327    drv_SL_clear();
328
329    /* say goodbye... */
330    if (!quiet) {
331  drv_generic_text_greet("goodbye!", NULL);
332    }
333
334    drv_generic_serial_close();
335
336    if (backbuffer) {
337  free(backbuffer);
338  backbuffer = 0;
339  backbuffer_size = 0;
340    }
341    return (0);
342}
343
344
345DRIVER drv_SimpleLCD = {
346    .name = Name,
347    .list = drv_SL_list,
348    .init = drv_SL_init,
349    .quit = drv_SL_quit,
350};
Note: See TracBrowser for help on using the browser.