1
/* $Id: drv_SimpleLCD.c 771 2007-02-25 12:27:26Z michael $
2
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_SimpleLCD.c $
4
* driver for a simple serial terminal.
6
* Copyright (C) 2005 Julien Aube <ob@obconseil.net>
7
* Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
9
* This file is part of LCD4Linux.
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)
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.
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.
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.
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
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.
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 )
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.
67
* A "bar" capability is now provided if the config file has a "BarCharValue" parameter in it.
69
* The code come mostly taken from the LCDTerm driver in LCD4Linux, from
70
* Michaels Reinelt, many thanks to him.
72
* This driver is released under the GPL.
79
* struct DRIVER drv_SimpleLCD
94
#include "widget_text.h"
95
#include "widget_icon.h"
96
#include "widget_bar.h"
98
#include "drv_generic_text.h"
99
#include "drv_generic_serial.h"
102
static char Name[] = "SimpleLCD";
103
static char *backbuffer = 0;
104
static int backbuffer_size = 0;
105
static int vt100_mode = 0;
106
static unsigned char bar_char = 0;
108
/****************************************/
109
/*** hardware dependant functions ***/
110
/****************************************/
112
/** No clear function on SimpleLCD : Just send CR-LF * number of lines **/
113
static void drv_SL_simple_clear(void)
119
for (i = 0; i < DROWS; ++i) {
120
drv_generic_serial_write(cmd, 2);
122
memset(backbuffer, ' ', backbuffer_size);
125
/** vt-100 mode : send the ESC-code **/
126
static void drv_SL_vt100_clear(void)
133
drv_generic_serial_write(cmd, 4);
137
static void drv_SL_clear(void)
139
vt100_mode == 1 ? drv_SL_vt100_clear() : drv_SL_simple_clear();
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)
147
static void drv_SL_commit(int full_commit)
150
char cmd[2] = { '\r', '\n' };
152
for (row = 0; row < DROWS; row++) {
153
drv_generic_serial_write(cmd, 2);
154
drv_generic_serial_write(backbuffer + (DCOLS * row), DCOLS);
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);
162
static void drv_SL_simple_write(const int row, const int col, const char *data, int len)
164
memcpy(backbuffer + (row * DCOLS) + col, data, len);
165
if (row == DROWS - 1)
171
static void drv_SL_vt100_write(const int row, const int col, const char *data, int len)
178
cmd[4] = (col / 10) + '0';
179
cmd[5] = (col % 10) + '1';
181
drv_generic_serial_write(cmd, 7);
182
drv_generic_serial_write(data, len);
186
static int drv_SL_start(const char *section, const int quiet)
188
int rows = -1, cols = -1;
190
unsigned int flags = 0;
195
model = cfg_get(section, "Model", "generic");
196
if (model != NULL && *model != '\0') {
197
if (strcasecmp("vt100", model) == 0)
201
cfg_number(section, "BarCharValue", 0, 0, 255, &value);
203
cfg_number(section, "Options", 0, 0, 0xffff, &value);
205
if (drv_generic_serial_open(section, Name, flags) < 0)
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());
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());
223
backbuffer_size = DROWS * DCOLS;
224
backbuffer = malloc(backbuffer_size);
230
/* real worker functions */
232
drv_generic_text_real_write = drv_SL_vt100_write;
234
drv_generic_text_real_write = drv_SL_simple_write;
237
drv_SL_clear(); /* clear */
242
qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
243
if (drv_generic_text_greet(buffer, NULL)) {
253
/****************************************/
255
/****************************************/
260
/****************************************/
261
/*** widget callbacks ***/
262
/****************************************/
265
/* using drv_generic_text_draw(W) */
268
/****************************************/
269
/*** exported functions ***/
270
/****************************************/
274
int drv_SL_list(void)
276
printf("generic vt100");
281
/* initialize driver & display */
282
int drv_SL_init(const char *section, const int quiet)
287
info("%s: %s", Name, "$Rev: 771 $");
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 */
295
GOTO_COST = -1; /* number of bytes a goto command requires */
299
if ((ret = drv_SL_start(section, quiet)) != 0)
302
/* initialize generic text driver */
303
if ((ret = drv_generic_text_init(section, Name)) != 0)
306
/* register text widget */
308
wc.draw = drv_generic_text_draw;
309
widget_register(&wc);
311
/* register plugins */
318
/* close driver & display */
319
int drv_SL_quit(const int quiet)
322
info("%s: shutting down.", Name);
324
drv_generic_text_quit();
331
drv_generic_text_greet("goodbye!", NULL);
334
drv_generic_serial_close();
345
DRIVER drv_SimpleLCD = {