~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_SimpleLCD.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 750.
  • Revision ID: siretart@tauware.de-20110427172415-6n4aptmvmz0eztvm
Tags: upstream-0.11.0~svn1143
ImportĀ upstreamĀ versionĀ 0.11.0~svn1143

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 $
 
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
 
 
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;
 
107
 
 
108
/****************************************/
 
109
/***  hardware dependant functions    ***/
 
110
/****************************************/
 
111
 
 
112
/** No clear function on SimpleLCD : Just send CR-LF * number of lines **/
 
113
static 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 **/
 
126
static 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
 
 
137
static 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
 
 
147
static 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
 
 
162
static 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
 
 
171
static 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
 
 
186
static 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 */
 
274
int drv_SL_list(void)
 
275
{
 
276
    printf("generic vt100");
 
277
    return 0;
 
278
}
 
279
 
 
280
 
 
281
/* initialize driver & display */
 
282
int drv_SL_init(const char *section, const int quiet)
 
283
{
 
284
    WIDGET_CLASS wc;
 
285
    int ret;
 
286
 
 
287
    info("%s: %s", Name, "$Rev: 771 $");
 
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 */
 
319
int 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
 
 
345
DRIVER drv_SimpleLCD = {
 
346
    .name = Name,
 
347
    .list = drv_SL_list,
 
348
    .init = drv_SL_init,
 
349
    .quit = drv_SL_quit,
 
350
};