From 181cec4348da40331b3e8ab365732c025ec149b2 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Wed, 27 Apr 2011 19:24:15 +0200 Subject: Import upstream version 0.11.0~svn1143 --- drv_SimpleLCD.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 drv_SimpleLCD.c (limited to 'drv_SimpleLCD.c') diff --git a/drv_SimpleLCD.c b/drv_SimpleLCD.c new file mode 100644 index 0000000..f308d87 --- /dev/null +++ b/drv_SimpleLCD.c @@ -0,0 +1,350 @@ +/* $Id: drv_SimpleLCD.c 771 2007-02-25 12:27:26Z michael $ + * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_SimpleLCD.c $ + * + * driver for a simple serial terminal. + * + * Copyright (C) 2005 Julien Aube + * Copyright (C) 2005 The LCD4Linux Team + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * This driver simply send out caracters on the serial port, without any + * formatting instructions for a particular LCD device. + * This is useful for custom boards of for very simple LCD. + * + * I use it for tests on a custom-made board based on a AVR microcontroler + * and also for driver a Point-of-Sale text-only display. + * I assume the following : + * - CR (0x0d) Return to the begining of the line without erasing, + * - LF (0x0a) Initiate a new line (but without sending the cursor to + * the begining of the line) + * - BS (0x08) Move the cursor to the previous caracter (but does no erase it). + * - It's not possible to return to the first line. Thus a back buffer is used + * in this driver. + * + * ******** UPDATE ********* + * I have added a "VT-100 Compatible mode" that allows the driver to support + * control-sequence code. This greatly reduce flickering and eliminate the need + * for the back-buffer. But it is optional since all displays cannot support them. + * Here are the codes: + * Delete the display (but does not move the cursor) : + * "ESC [ 2 J" (0x1b 0x5b 0x32 0x4a) + * Position the cursor : + * "ESC [ YY ; XX H" ( 0x1b 0x5b YY 0x3b XX 0x48 ) where YY is the ascii for the line + * number, and XX is the ascii for the column number ( first line/column is '1', not zero) + * Delete to the end of line from current cursor position : + * "ESC [ 0 K" ( 0x1b 0x5b 0x30 0x4b ) + * Set Country Code : + * "ESC R NN" (0x1b 0x52 NN) where NN is the country code *in byte, NOT ascii*. + * The default is 0 (USA), see below for specific countries. + * the list of accessible characters page are available on this page : + * http://www.wincor-nixdorf.com/internet/com/Services/Support/TechnicalSupport/POSSystems + * /Manuals/BAxx/index.html + * Get the display identification : (Doesn't work reliably, timing issues here) + * "ESC [ 0 c" ( 0x1b 0x5b 0x30 0x63). Return a string which look like this : + * ESC [ ? M ; NN ; OO ; PP ; QQ c) where M is type of display (2 for VFD), + * NN is the rom version, 00 is the current caracter set, PP is the number of lines and + * QQ the number of colomns. + * + * + * A "bar" capability is now provided if the config file has a "BarCharValue" parameter in it. + * + * The code come mostly taken from the LCDTerm driver in LCD4Linux, from + * Michaels Reinelt, many thanks to him. + * + * This driver is released under the GPL. + */ + +/* + * + * exported fuctions: + * + * struct DRIVER drv_SimpleLCD + * + */ + +#include "config.h" + +#include +#include +#include + +#include "debug.h" +#include "cfg.h" +#include "qprintf.h" +#include "plugin.h" +#include "widget.h" +#include "widget_text.h" +#include "widget_icon.h" +#include "widget_bar.h" +#include "drv.h" +#include "drv_generic_text.h" +#include "drv_generic_serial.h" + + +static char Name[] = "SimpleLCD"; +static char *backbuffer = 0; +static int backbuffer_size = 0; +static int vt100_mode = 0; +static unsigned char bar_char = 0; + +/****************************************/ +/*** hardware dependant functions ***/ +/****************************************/ + +/** No clear function on SimpleLCD : Just send CR-LF * number of lines **/ +static void drv_SL_simple_clear(void) +{ + char cmd[2]; + int i; + cmd[0] = '\r'; + cmd[1] = '\n'; + for (i = 0; i < DROWS; ++i) { + drv_generic_serial_write(cmd, 2); + } + memset(backbuffer, ' ', backbuffer_size); +} + +/** vt-100 mode : send the ESC-code **/ +static void drv_SL_vt100_clear(void) +{ + char cmd[4]; + cmd[0] = 0x1b; + cmd[1] = '['; + cmd[2] = '2'; + cmd[3] = 'J'; + drv_generic_serial_write(cmd, 4); + +} + +static void drv_SL_clear(void) +{ + vt100_mode == 1 ? drv_SL_vt100_clear() : drv_SL_simple_clear(); +} + + +/* If full_commit = true, then the whole buffer is to be sent to screen. + if full_commit = false, then only the last line is to be sent (faster on slow screens) +*/ + +static void drv_SL_commit(int full_commit) +{ + int row; + char cmd[2] = { '\r', '\n' }; + if (full_commit) { + for (row = 0; row < DROWS; row++) { + drv_generic_serial_write(cmd, 2); + drv_generic_serial_write(backbuffer + (DCOLS * row), DCOLS); + } + } else { + drv_generic_serial_write(cmd, 1); /* Go to the beginning of the line only */ + drv_generic_serial_write(backbuffer + (DCOLS * (DROWS - 1)), DCOLS); + } +} + +static void drv_SL_simple_write(const int row, const int col, const char *data, int len) +{ + memcpy(backbuffer + (row * DCOLS) + col, data, len); + if (row == DROWS - 1) + drv_SL_commit(0); + else + drv_SL_commit(1); +} + +static void drv_SL_vt100_write(const int row, const int col, const char *data, int len) +{ + char cmd[8]; + cmd[0] = 0x1b; + cmd[1] = '['; + cmd[2] = row + '1'; + cmd[3] = ';'; + cmd[4] = (col / 10) + '0'; + cmd[5] = (col % 10) + '1'; + cmd[6] = 'H'; + drv_generic_serial_write(cmd, 7); + drv_generic_serial_write(data, len); +} + + +static int drv_SL_start(const char *section, const int quiet) +{ + int rows = -1, cols = -1; + int value; + unsigned int flags = 0; + char *s; + char *model = 0; + + vt100_mode = 0; + model = cfg_get(section, "Model", "generic"); + if (model != NULL && *model != '\0') { + if (strcasecmp("vt100", model) == 0) + vt100_mode = 1; + } + + cfg_number(section, "BarCharValue", 0, 0, 255, &value); + bar_char = value; + cfg_number(section, "Options", 0, 0, 0xffff, &value); + flags = value; + if (drv_generic_serial_open(section, Name, flags) < 0) + return -1; + + s = cfg_get(section, "Size", NULL); + if (s == NULL || *s == '\0') { + error("%s: no '%s.Size' entry from %s", Name, section, cfg_source()); + return -1; + } + if (sscanf(s, "%dx%d", &cols, &rows) != 2 || rows < 1 || cols < 1) { + error("%s: bad %s.Size '%s' from %s", Name, section, s, cfg_source()); + free(s); + return -1; + } + + DROWS = rows; + DCOLS = cols; + + if (!vt100_mode) { + backbuffer_size = DROWS * DCOLS; + backbuffer = malloc(backbuffer_size); + if (!backbuffer) { + return -1; + } + } + + /* real worker functions */ + if (vt100_mode) { + drv_generic_text_real_write = drv_SL_vt100_write; + } else { + drv_generic_text_real_write = drv_SL_simple_write; + } + + drv_SL_clear(); /* clear */ + + + if (!quiet) { + char buffer[40]; + qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS); + if (drv_generic_text_greet(buffer, NULL)) { + sleep(3); + drv_SL_clear(); + } + } + + return 0; +} + + +/****************************************/ +/*** plugins ***/ +/****************************************/ + +/* none */ + + +/****************************************/ +/*** widget callbacks ***/ +/****************************************/ + + +/* using drv_generic_text_draw(W) */ + + +/****************************************/ +/*** exported functions ***/ +/****************************************/ + + +/* list models */ +int drv_SL_list(void) +{ + printf("generic vt100"); + return 0; +} + + +/* initialize driver & display */ +int drv_SL_init(const char *section, const int quiet) +{ + WIDGET_CLASS wc; + int ret; + + info("%s: %s", Name, "$Rev: 771 $"); + + /* display preferences */ + XRES = 5; /* pixel width of one char */ + YRES = 8; /* pixel height of one char */ + CHARS = 0; /* number of user-defineable characters */ + CHAR0 = 0; /* ASCII of first user-defineable char */ + + GOTO_COST = -1; /* number of bytes a goto command requires */ + + + /* start display */ + if ((ret = drv_SL_start(section, quiet)) != 0) + return ret; + + /* initialize generic text driver */ + if ((ret = drv_generic_text_init(section, Name)) != 0) + return ret; + + /* register text widget */ + wc = Widget_Text; + wc.draw = drv_generic_text_draw; + widget_register(&wc); + + /* register plugins */ + /* none */ + + return 0; +} + + +/* close driver & display */ +int drv_SL_quit(const int quiet) +{ + + info("%s: shutting down.", Name); + + drv_generic_text_quit(); + + /* clear display */ + drv_SL_clear(); + + /* say goodbye... */ + if (!quiet) { + drv_generic_text_greet("goodbye!", NULL); + } + + drv_generic_serial_close(); + + if (backbuffer) { + free(backbuffer); + backbuffer = 0; + backbuffer_size = 0; + } + return (0); +} + + +DRIVER drv_SimpleLCD = { + .name = Name, + .list = drv_SL_list, + .init = drv_SL_init, + .quit = drv_SL_quit, +}; -- cgit v1.2.3