aboutsummaryrefslogtreecommitdiffstats
path: root/configure.in
blob: 5a853ba32f740416897688af5d77ee2f4ca8ee80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
dnl Process this file with autoconf to produce a configure script.
AC_INIT(lcd4linux.c)
AM_INIT_AUTOMAKE(lcd4linux, 0.98)

dnl Checks for programs.
AC_PROG_AWK
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S

dnl Checks for libraries.
AC_CHECK_LIB(m, log)

dnl Checks for X11
AC_PATH_XTRA
AM_CONDITIONAL(WITH_X, test x$no_x = x)

dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h sys/ioctl.h sys/time.h syslog.h unistd.h)
AC_CHECK_HEADERS(sys/io.h asm/io.h)

dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_PID_T
AC_HEADER_TIME

dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(gettimeofday socket strdup strerror strstr strtol uname)

AC_OUTPUT(Makefile)
href='#n228'>228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
/* $Id$
 * $URL$
 * 
 * driver for a simple serial terminal.
 * 
 * Copyright (C) 2005 Julien Aube <ob@obconseil.net>
 * Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 *
 * 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 <stdlib.h>
#include <unistd.h>
#include <string.h>

#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$");

    /* 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,
};