]> git.webhop.me Git - lcd4linux.git/commitdiff
driver for picoLCD displays from mini-box.com by Nicu Pavel
authormichael <michael@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Fri, 19 Jan 2007 16:34:43 +0000 (16:34 +0000)
committermichael <michael@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Fri, 19 Jan 2007 16:34:43 +0000 (16:34 +0000)
git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@747 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

Makefile.am
drivers.m4
drv.c
drv_picoLCD.c [new file with mode: 0644]
lcd4linux.conf.sample

index e1d2c1dccc75a1e63cf7cb5f66a10d8afd954517..3d01351433a8828cf9bc686758d95b23292d2018 100644 (file)
@@ -83,6 +83,7 @@ drv_MatrixOrbital.c           \
 drv_MilfordInstruments.c      \
 drv_Noritake.c                \
 drv_NULL.c                    \
+drv_picoLCD.c                \
 drv_RouterBoard.c             \
 drv_Sample.c                  \
 drv_serdisplib.c              \
index 0976d5028d0ae7b89d7b0d93ee7397a830a12630..e0d0cbe9443caceea394ca0780737a1985a347c0 100644 (file)
@@ -35,7 +35,7 @@ AC_ARG_WITH(
   [                        BeckmannEgle, BWCT, CrystalFontz, Curses, Cwlinux,]
   [                        G15, HD44780, LCD2USB LCDLinux, LCDTerm, LPH7508,]
   [                        LUIse, M50530, MatrixOrbital, MilfordInstruments,]
-  [                        Noritake, NULL, PNG, PPM, RouterBoard, Sample,]
+  [                        Noritake, NULL, PNG, PPM, picoLCD, RouterBoard, Sample,]
   [                        serdisplib, SimpleLCD, T6963, Trefon, USBLCD,]
   [                        USBHUB, WincorNixdorf, X11],
   drivers=$withval, 
@@ -76,9 +76,10 @@ for driver in $drivers; do
          MILINST="yes"
          NORITAKE="yes" 
          NULL="yes" 
+         picoLCD="yes"
          PNG="yes"
          PPM="yes"
-        ROUTERBOARD="yes"
+         ROUTERBOARD="yes"
          SAMPLE="yes"
         SERDISPLIB="yes"
          SIMPLELCD="yes"
@@ -146,6 +147,9 @@ for driver in $drivers; do
       NULL)
          NULL=$val;
          ;;
+      picoLCD)
+         picoLCD=$val
+         ;;         
       PNG)
          PNG=$val
          ;;
@@ -375,6 +379,15 @@ if test "$NULL" = "yes"; then
    AC_DEFINE(WITH_NULL,1,[NULL driver])
 fi
 
+if test "$picoLCD" = "yes"; then
+   TEXT="yes"
+   GPIO="yes"
+   SERIAL="yes"
+   #I2C="yes"
+   DRIVERS="$DRIVERS drv_picoLCD.o"
+   AC_DEFINE(WITH_picoLCD,1,[picoLCD driver])
+fi
+
 if test "$PNG" = "yes"; then
    if test "$has_gd" = "true"; then
       IMAGE="yes"
diff --git a/drv.c b/drv.c
index 13bbc3b21ba66e164b836ffc745e9808e72b1a7a..da161a888aff9ca442fb0ccbc202ec5cbbeef3eb 100644 (file)
--- a/drv.c
+++ b/drv.c
@@ -66,6 +66,7 @@ extern DRIVER drv_MatrixOrbital;
 extern DRIVER drv_MilfordInstruments;
 extern DRIVER drv_Noritake;
 extern DRIVER drv_NULL;
+extern DRIVER drv_picoLCD;
 extern DRIVER drv_RouterBoard;
 extern DRIVER drv_Sample;
 extern DRIVER drv_serdisplib;
@@ -141,6 +142,10 @@ DRIVER *Driver[] = {
 #ifdef WITH_NULL
     &drv_NULL,
 #endif
+#ifdef WITH_picoLCD
+    &drv_picoLCD,
+#endif
+
 #ifdef WITH_ROUTERBOARD
     &drv_RouterBoard,
 #endif
diff --git a/drv_picoLCD.c b/drv_picoLCD.c
new file mode 100644 (file)
index 0000000..dafd496
--- /dev/null
@@ -0,0 +1,512 @@
+/* $Id$
+ * $URL$
+ *
+ * driver for picoLCD displays from mini-box.com
+ *
+ * Copyright (C) 2005 Michael Reinelt <reinelt@eunet.at>
+ * Copyright (C) 2005, 2006, 2007 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ *
+ * Copyright (C) 2007 Nicu Pavel, Mini-Box.com <npavel@mini-box.com>
+ *
+ * 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.
+ *
+ */
+
+/* 
+ *
+ * exported fuctions:
+ *
+ * struct DRIVER drv_picoLCD
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#ifdef HAVE_USB_H
+#include <usb.h>
+#endif
+
+#include "debug.h"
+#include "cfg.h"
+#include "qprintf.h"
+#include "udelay.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_gpio.h"
+#include "drv_generic_keypad.h"
+
+
+
+#define picoLCD_VENDOR  0x04d8
+#define picoLCD_DEVICE  0x0002
+
+static char Name[] = "picoLCD";
+
+static int use_libusb = 1;
+static unsigned int gpo = 0;
+
+static char *Buffer;
+static char *BufPtr;
+
+#ifdef HAVE_USB_H
+
+static usb_dev_handle *lcd;
+static int interface;
+
+extern int usb_debug;
+
+#endif
+
+
+
+/****************************************/
+/***  hardware dependant functions    ***/
+/****************************************/
+
+#ifdef HAVE_USB_H
+
+static int drv_pL_open(void)
+{
+    struct usb_bus *busses, *bus;
+    struct usb_device *dev;
+    char buf[1024];
+    int ret;
+
+    lcd = NULL;
+
+    info("%s: scanning for picoLCD...", Name);
+
+    usb_debug = 0;
+
+    usb_init();
+    usb_find_busses();
+    usb_find_devices();
+    busses = usb_get_busses();
+
+    for (bus = busses; bus; bus = bus->next) {
+       for (dev = bus->devices; dev; dev = dev->next) {
+           if ((dev->descriptor.idVendor == picoLCD_VENDOR) && (dev->descriptor.idProduct == picoLCD_DEVICE)) {
+
+               info("%s: found picoLCD on bus %s device %s", Name, bus->dirname, dev->filename);
+
+               interface = 0;
+               lcd = usb_open(dev);
+
+               ret = usb_get_driver_np(lcd, 0, buf, sizeof(buf));
+
+               if (ret == 0) {
+                   info("interface 0 already claimed attempting to detach it\n");
+                   ret = usb_detach_kernel_driver_np(lcd, 0);
+                   printf("usb_detach_kernel_driver_np returned %d\n", ret);
+               }
+
+               if (usb_claim_interface(lcd, interface) < 0) {
+                   error("%s: usb_claim_interface() failed!", Name);
+                   return -1;
+               }
+               return 0;
+           }
+       }
+    }
+    error("%s: could not find a picoLCD", Name);
+    return -1;
+}
+
+
+static int drv_pL_close(void)
+{
+    usb_release_interface(lcd, interface);
+    usb_close(lcd);
+
+    return 0;
+}
+
+#endif
+
+
+static void drv_pL_send(void)
+{
+
+#if 0
+    struct timeval now, end;
+    gettimeofday(&now, NULL);
+#endif
+
+    if (use_libusb) {
+#ifdef HAVE_USB_H
+       usb_bulk_write(lcd, USB_ENDPOINT_OUT + 1, Buffer, BufPtr - Buffer, 1000);
+#endif
+    }
+
+#if 0
+    gettimeofday(&end, NULL);
+    debug("send %d bytes in %d usec (%d usec/byte)", BufPtr - Buffer,
+         (1000000 * (end.tv_sec - now.tv_sec) + end.tv_usec - now.tv_usec),
+         (1000000 * (end.tv_sec - now.tv_sec) + end.tv_usec - now.tv_usec) / (BufPtr - Buffer));
+#endif
+
+    BufPtr = Buffer;
+}
+
+
+static void drv_pL_command(const unsigned char cmd)
+{
+    *BufPtr++ = cmd;
+}
+
+
+static void drv_pL_clear(void)
+{
+    drv_pL_command(0x94);      /* clear display */
+    drv_pL_send();             /* flush buffer */
+}
+
+static int drv_pL_contrast(int contrast)
+{
+
+    if (contrast < 0)
+       contrast = 0;
+    if (contrast > 255)
+       contrast = 255;
+
+    drv_pL_command(0x92);
+    drv_pL_command(contrast);
+
+    drv_pL_send();
+
+    return contrast;
+}
+
+
+static int drv_pL_backlight(int backlight)
+{
+    if (backlight < 0)
+       backlight = 0;
+    if (backlight > 1)
+       backlight = 1;
+
+    drv_pL_command(0x91);
+    drv_pL_command(backlight);
+
+    drv_pL_send();
+
+    return backlight;
+}
+
+static int drv_pL_gpo(int num, int val)
+{
+    if (num < 0)
+       num = 0;
+    if (num > 7)
+       num = 7;
+
+    if (val < 0)
+       val = 0;
+    if (val > 1)
+       val = 1;
+
+    /* set led bit to 1 or 0 */
+    if (val)
+       gpo |= 1 << num;
+    else
+       gpo &= ~(1 << num);
+
+    drv_pL_command(0x81);
+    drv_pL_command(gpo);
+
+    return val;
+}
+
+
+static void drv_pL_write(const int row, const int col, const char *data, int len)
+{
+
+    drv_pL_command(0x98);
+    drv_pL_command(row);
+    drv_pL_command(col);
+    drv_pL_command(len);
+
+    while (len--) {
+       if (*data == 0)
+           *BufPtr++ = 0;
+       *BufPtr++ = *data++;
+    }
+
+    drv_pL_send();
+}
+
+static void drv_pL_defchar(const int ascii, const unsigned char *matrix)
+{
+    int i;
+
+    drv_pL_command(0x9c);
+    drv_pL_command(ascii);
+
+    for (i = 0; i < 8; i++) {
+       if ((*matrix & 0x1f) == 0)
+           *BufPtr++ = 0;
+       *BufPtr++ = *matrix++ & 0x1f;
+    }
+
+    drv_pL_send();
+}
+
+
+static int drv_pL_start(const char *section, const int quiet)
+{
+    int rows = -1, cols = -1;
+    int value;
+    char *s;
+
+#ifdef HAVE_USB_H
+    use_libusb = 1;
+    debug("using libusb");
+#else
+    error("%s: lcd4linux was compiled without libusb support!", Name);
+    return -1;
+#endif
+
+    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;
+
+
+#ifdef HAVE_USB_H
+    if (drv_pL_open() < 0) {
+       return -1;
+    }
+#endif
+
+
+    /* Init the command buffer */
+    Buffer = (char *) malloc(1024);
+    if (Buffer == NULL) {
+       error("%s: coommand buffer could not be allocated: malloc() failed", Name);
+       return -1;
+    }
+    BufPtr = Buffer;
+
+    if (cfg_number(section, "Contrast", 0, 0, 255, &value) > 0) {
+       info("Setting contrast to %d\n", value);
+       drv_pL_contrast(value);
+    }
+
+    if (cfg_number(section, "Backlight", 0, 0, 1, &value) > 0) {
+       info("Setting backlight to %d\n", value);
+       drv_pL_backlight(value);
+    }
+
+    drv_pL_clear();            /* clear display */
+
+    if (!quiet) {
+       char buffer[40];
+       qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
+       if (drv_generic_text_greet(buffer, "http://www.picolcd.com")) {
+           sleep(3);
+           drv_pL_clear();
+       }
+    }
+
+    return 0;
+}
+
+
+/****************************************/
+/***            plugins               ***/
+/****************************************/
+
+static void plugin_contrast(RESULT * result, RESULT * arg1)
+{
+    double contrast;
+
+    contrast = drv_pL_contrast(R2N(arg1));
+    SetResult(&result, R_NUMBER, &contrast);
+}
+
+static void plugin_backlight(RESULT * result, RESULT * arg1)
+{
+    double backlight;
+
+    backlight = drv_pL_backlight(R2N(arg1));
+    SetResult(&result, R_NUMBER, &backlight);
+}
+
+static void plugin_gpo(RESULT * result, RESULT * argv[])
+{
+    double gpo;
+    gpo = drv_pL_gpo(R2N(argv[0]), R2N(argv[1]));
+    SetResult(&result, R_NUMBER, &gpo);
+}
+
+
+/****************************************/
+/***        widget callbacks          ***/
+/****************************************/
+
+
+/* using drv_generic_text_draw(W) */
+/* using drv_generic_text_icon_draw(W) */
+/* using drv_generic_text_bar_draw(W) */
+
+
+/****************************************/
+/***        exported functions        ***/
+/****************************************/
+
+
+/* list models */
+int drv_pL_list(void)
+{
+    printf("generic");
+    return 0;
+}
+
+
+/* initialize driver & display */
+int drv_pL_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 = 8;                 /* number of user-defineable characters */
+    CHAR0 = 0;                 /* ASCII of first user-defineable char */
+    GPOS = 8;
+    INVALIDATE = 1;
+    GOTO_COST = 2;             /* number of bytes a goto command requires */
+
+    /* real worker functions */
+    drv_generic_text_real_write = drv_pL_write;
+    drv_generic_text_real_defchar = drv_pL_defchar;
+    drv_generic_gpio_real_set = drv_pL_gpo;
+
+    /* start display */
+    if ((ret = drv_pL_start(section, quiet)) != 0)
+       return ret;
+
+    /* initialize generic text driver */
+    if ((ret = drv_generic_text_init(section, Name)) != 0)
+       return ret;
+
+    /* initialize generic icon driver */
+    if ((ret = drv_generic_text_icon_init()) != 0)
+       return ret;
+
+    /* initialize generic bar driver */
+    if ((ret = drv_generic_text_bar_init(0)) != 0)
+       return ret;
+
+    drv_generic_text_bar_add_segment(0, 0, 255, 32);
+
+    /* GPO's init */
+    if ((ret = drv_generic_gpio_init(section, Name)) != 0)
+       return ret;
+
+    /* register text widget */
+    wc = Widget_Text;
+    wc.draw = drv_generic_text_draw;
+    widget_register(&wc);
+
+    /* register icon widget */
+    wc = Widget_Icon;
+    wc.draw = drv_generic_text_icon_draw;
+    widget_register(&wc);
+
+    /* register bar widget */
+    wc = Widget_Bar;
+    wc.draw = drv_generic_text_bar_draw;
+    widget_register(&wc);
+
+    /* register plugins */
+    AddFunction("LCD::contrast", -1, plugin_contrast);
+    AddFunction("LCD::backlight", -1, plugin_backlight);
+    AddFunction("LCD::gpo", -1, plugin_gpo);
+
+    return 0;
+}
+
+
+/* close driver & display */
+int drv_pL_quit(const int quiet)
+{
+
+    info("%s: shutting down.", Name);
+
+    /* flush buffer */
+    drv_pL_send();
+
+    drv_generic_text_quit();
+
+    /* clear display */
+    drv_pL_clear();
+
+    /* say goodbye... */
+    if (!quiet) {
+       drv_generic_text_greet("goodbye!", NULL);
+    }
+
+    if (use_libusb) {
+#ifdef HAVE_USB_H
+       drv_pL_close();
+#endif
+    }
+
+    if (Buffer) {
+       free(Buffer);
+       Buffer = NULL;
+       BufPtr = Buffer;
+    }
+
+    return (0);
+}
+
+
+DRIVER drv_picoLCD = {
+  name:Name,
+  list:drv_pL_list,
+  init:drv_pL_init,
+  quit:drv_pL_quit,
+};
index 56eb740c31f54904f6926e08e9352ae4d6e78e24..e27981d5a03a48c3bddddb6f3b45803780d8b3db 100644 (file)
@@ -246,6 +246,14 @@ Display HD44780-kernelconcepts {
     }
 }
 
+Display picoLCD {
+    Driver 'picoLCD'
+    Size     '20x2'
+    Contrast  0
+    Backlight 1
+    Icons     4
+}
+
 Display SC1602D {
     Driver 'HD44780'
     Port '/dev/parports/0'