picolcdgfx driver
Scott Meharg <[email protected]> Tue, 29 Jan 2013 18:59:21 -0600
| Newsgroups | gmane.comp.sysutils.lcdproc |
|---|---|
| Message-ID | <CAOgbcjQvV8HBY=kOKy71cfYO28ZH6NVWo4TyZBcWzh+zaY6B0w@mail.gmail.com> |
Attached is the patch and file for Mini-box.com's PicoLCDGraphics LCD. It uses glcd driver with connect type picolcdgfx. _______________________________________________ LCDproc mailing list [email protected] http://lists.omnipotent.net/mailman/listinfo/lcdproc
glcd-picolcdgfx.c
(text/x-csrc, 9.4 KB)
/** \file server/drivers/glcd-picolcdgfx.c * Driver for the picoLCD Graphics 256x64 from mini-box.com. Based on lcd4linux * driver by Nicu Pavel. */ /*- * Copyright (c) 2009 Nicu Pavel <[email protected]> * Copyright (c) 2012 Scott Meahrg <[email protected]> * * This file is released under the GNU General Public License. Refer to the * COPYING file distributed with this package. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <usb.h> #include "lcd.h" #include "report.h" #include "glcd-low.h" #define picoLCDGfx_VENDOR 0x04d8 #define picoLCDGfx_DEVICE 0xc002 /* picoLCD Graphics Commands */ /* These were taken from picolcd.h */ #define PICOLCDGFX_IN_KEY_STATE 0x11 #define PICOLCDGFX_OUT_GPO 0x81 #define PICOLCDGFX_OUT_BACKLIGHT 0x91 #define PICOLCDGFX_OUT_CONTRAST 0x92 #define PICOLCDGFX_OUT_INIT_DISPLAY 0x93 #define PICOLCDGFX_OUT_CMD 0x94 #define PICOLCDGFX_OUT_DATA 0x95 #define PICOLCDGFX_OUT_CMD_DATA 0x96 #define PICOLCDGFX_MAX_DATA_LEN 24 #define PICOLCDGFX_DEF_KEYTIMEOUT 125 #define PICOLCDGFX_DEF_INVERTED 0 /** Private data for the X11 connection type */ typedef struct glcd_picolcdgfx_data { usb_dev_handle *lcd; unsigned char inverted; int keytimeout; unsigned char *backingstore; } CT_picolcdgfx_data; /* Prototypes */ void glcd_picolcdgfx_blit(PrivateData *p); void glcd_picolcdgfx_close(PrivateData *p); unsigned char glcd_picolcdgfx_pollkeys(PrivateData *p); void glcd_picolcdgfx_set_backlight(PrivateData *p, int state); void glcd_picolcdgfx_set_contrast(PrivateData *p, int value); int picolcdgfx_read(usb_dev_handle *lcd, unsigned char *data, int size, int timeout) { return usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char *) data, size, timeout); } void picolcdgfx_write(usb_dev_handle *lcd, unsigned char *data, int size) { int __attribute__ ((unused)) ret; ret = usb_interrupt_write(lcd, USB_ENDPOINT_OUT + 1, (char *) data, size, 1000); } /** * API: Initialize the connection type driver. * \param drvthis Pointer to driver structure. * \retval 0 Success. * \retval <0 Error. */ int glcd_picolcdgfx_init(Driver *drvthis) { PrivateData *p = (PrivateData *)drvthis->private_data; CT_picolcdgfx_data *ct_data; struct usb_bus *busses, *bus; struct usb_device *dev; char driver[1024]; char product[1024]; char manufacturer[1024]; char serialnumber[1024]; int ret; report(RPT_INFO, "GLCD/picolcdgfx: intializing"); /* Set up connection type low-level functions */ p->glcd_functions->blit = glcd_picolcdgfx_blit; p->glcd_functions->close = glcd_picolcdgfx_close; p->glcd_functions->poll_keys = glcd_picolcdgfx_pollkeys; p->glcd_functions->set_backlight = glcd_picolcdgfx_set_backlight; p->glcd_functions->set_contrast = glcd_picolcdgfx_set_contrast; /* Allocate memory structures */ ct_data = (CT_picolcdgfx_data *) calloc(1, sizeof(CT_picolcdgfx_data)); if (ct_data == NULL) { report(RPT_ERR, "GLCD/picolcdgfx: error allocating connection data"); return -1; } p->ct_data = ct_data; /* Fix display size to 256x64 */ p->framebuf.px_width = 256; p->framebuf.px_height = 64; /* Since the display is fixed to 256x64 we have to recalculate. */ p->framebuf.bytesPerLine = (p->framebuf.px_width + 7) / 8; p->framebuf.size = p->framebuf.bytesPerLine * p->framebuf.px_height; ct_data->backingstore = malloc(p->framebuf.size); if (ct_data->backingstore == NULL) { report(RPT_ERR, "GLCD/picolcdgfx: unable to allocate backing store"); return -1; } memset(ct_data->backingstore, 0x00, p->framebuf.size); /* Get keytimeout */ ct_data->keytimeout = drvthis->config_get_int(drvthis->name, "picolcdgfx_KeyTimeout", 0, PICOLCDGFX_DEF_KEYTIMEOUT); /* Get inverted option */ ct_data->inverted = drvthis->config_get_bool(drvthis->name, "picolcdgfx_Inverted", 0, PICOLCDGFX_DEF_INVERTED); ct_data->lcd = NULL; report(RPT_DEBUG,"GLCD/picolcdgfx: scanning for picoLCD 256x64..."); 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 == picoLCDGfx_VENDOR) && (dev->descriptor.idProduct == picoLCDGfx_DEVICE)) { report(RPT_DEBUG,"GLCD/picolcdgfx: found picoLCDGraphics on bus %s device %s", bus->dirname, dev->filename); ct_data->lcd = usb_open(dev); ret = usb_get_driver_np(ct_data->lcd, 0, driver, sizeof(driver)); if (ret == 0) { report(RPT_DEBUG,"GLCD/picolcdgfx: interface 0 already claimed by '%s'", driver); report(RPT_DEBUG,"GLCD/picolcdgfx: attempting to detach driver..."); if (usb_detach_kernel_driver_np(ct_data->lcd, 0) < 0) { report(RPT_ERR,"GLCD/picolcdgfx: usb_detach_kernel_driver_np() failed!"); return -1; } } usb_set_configuration(ct_data->lcd, 1); usleep(100); if (usb_claim_interface(ct_data->lcd, 0) < 0) { report(RPT_ERR,"GLCD/picolcdgfx: usb_claim_interface() failed!"); return -1; } usb_set_altinterface(ct_data->lcd, 0); usb_get_string_simple(ct_data->lcd, dev->descriptor.iProduct, product, sizeof(product)); usb_get_string_simple(ct_data->lcd, dev->descriptor.iManufacturer, manufacturer, sizeof(manufacturer)); usb_get_string_simple(ct_data->lcd, dev->descriptor.iSerialNumber, serialnumber, sizeof(serialnumber)); report(RPT_INFO,"GLCD/picolcdgfx: Manufacturer='%s' Product='%s' SerialNumber='%s'", manufacturer, product, serialnumber); debug(RPT_DEBUG, "GLCD/picolcdgfx: init() done"); return 0; } } } report(RPT_ERR,"GLCD/picolcdgfx: could not find a picoLCDGraphics"); return -1; } /** * API: Write the framebuffer to the display * \param p Pointer to glcd driver's private date structure. */ void glcd_picolcdgfx_blit(PrivateData *p) { CT_picolcdgfx_data *ct_data = (CT_picolcdgfx_data *) p->ct_data; /* Check if framebufer has changed. If not there's nothing to do */ if (memcmp(p->framebuf.data, ct_data->backingstore, p->framebuf.size) == 0) return; unsigned char cmd3[64] = { PICOLCDGFX_OUT_CMD_DATA }; /* send command + data */ unsigned char cmd4[64] = { PICOLCDGFX_OUT_DATA }; /* send data only */ int index, bit, x, y; unsigned char cs, line; unsigned char pixel; for (cs = 0; cs < 4; cs++) { unsigned char chipsel = (cs << 2); //chipselect for (line = 0; line < 8; line++) { cmd3[0] = PICOLCDGFX_OUT_CMD_DATA; cmd3[1] = chipsel; cmd3[2] = 0x02; cmd3[3] = 0x00; cmd3[4] = 0x00; cmd3[5] = 0xb8 | line; cmd3[6] = 0x00; cmd3[7] = 0x00; cmd3[8] = 0x40; cmd3[9] = 0x00; cmd3[10] = 0x00; cmd3[11] = 32; cmd4[0] = PICOLCDGFX_OUT_DATA; cmd4[1] = chipsel | 0x01; cmd4[2] = 0x00; cmd4[3] = 0x00; cmd4[4] = 32; for (index = 0; index < 32; index++) { pixel = 0x00; for (bit = 0; bit < 8; bit++) { x = cs * 64 + index; y = (line * 8 + bit + 0) % p->framebuf.px_height; if ((fb_get_pixel(&p->framebuf, x, y) ^ ct_data->inverted) == FB_BLACK) pixel |= (1 << bit); } cmd3[12 + index] = pixel; } for (index = 32; index < 64; index++) { pixel = 0x00; for (bit = 0; bit < 8; bit++) { x = cs * 64 + index; y = (line * 8 + bit + 0) % p->framebuf.px_height; if ((fb_get_pixel(&p->framebuf, x, y) ^ ct_data->inverted) == FB_BLACK) pixel |= (1 << bit); } cmd4[5 + (index - 32)] = pixel; } picolcdgfx_write(ct_data->lcd,cmd3, 44); picolcdgfx_write(ct_data->lcd,cmd4, 38); } } memcpy(ct_data->backingstore, p->framebuf.data, p->framebuf.size); } /** * API: Release low-level resources. * \param p Pointer to glcd driver's private date structure. */ void glcd_picolcdgfx_close(PrivateData *p) { if (p->ct_data != NULL) { CT_picolcdgfx_data *ct_data = (CT_picolcdgfx_data *) p->ct_data; if (ct_data->lcd != NULL) { usb_release_interface(ct_data->lcd, 0); usb_close(ct_data->lcd); } if (ct_data->backingstore != NULL) free(ct_data->backingstore); free(p->ct_data); p->ct_data = NULL; } } unsigned char glcd_picolcdgfx_pollkeys(PrivateData *p) { CT_picolcdgfx_data *ct_data = (CT_picolcdgfx_data *) p->ct_data; unsigned char rv = 0; int ret; unsigned char rx_packet[PICOLCDGFX_MAX_DATA_LEN]; ret = picolcdgfx_read(ct_data->lcd, rx_packet, PICOLCDGFX_MAX_DATA_LEN, ct_data->keytimeout); if ((ret > 0) && (rx_packet[0] == PICOLCDGFX_IN_KEY_STATE)) { switch (rx_packet[1]) { case 0x01: rv = 6; //keystr = "Escape"; break; case 0x02: rv = 3; //keystr = "Left"; break; case 0x05: rv = 1; //keystr = "Up"; break; case 0x06: rv = 5; //keystr = "Enter"; break; case 0x07: rv = 2; //keystr = "Down"; break; } } return rv; } void glcd_picolcdgfx_set_backlight(PrivateData *p, int state) { CT_picolcdgfx_data *ct_data = (CT_picolcdgfx_data *)p->ct_data; unsigned char cmd[2] = { PICOLCDGFX_OUT_BACKLIGHT }; /* set backlight */ if (state < 0) cmd[1] = 0; if (state >= 1) cmd[1] = 200; picolcdgfx_write(ct_data->lcd, cmd, 2); } void glcd_picolcdgfx_set_contrast(PrivateData *p, int value) { CT_picolcdgfx_data *ct_data = (CT_picolcdgfx_data *)p->ct_data; unsigned char cmd[2] = { PICOLCDGFX_OUT_CONTRAST }; /* set contrast */ /* I believe contrast is 200 to 255 * with vlaue at 1000 I think 204 is the best. (S. Meharg) */ int val = (((1000 - value) / (float)1000) * 40) + 204; cmd[1] = val; picolcdgfx_write(ct_data->lcd, cmd, 2); }
glcd-picolcdgfx.patch
(application/octet-stream, 5.5 KB)
Index: lcdproc/LCDd.conf
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/LCDd.conf,v
retrieving revision 1.166
diff -u -r1.166 LCDd.conf
--- lcdproc/LCDd.conf 17 Jan 2013 22:15:45 -0000 1.166
+++ lcdproc/LCDd.conf 30 Jan 2013 00:44:58 -0000
@@ -357,6 +357,7 @@
# Width and height of the display in pixel. The supported sizes may depend on
# the ConnectionType. [default: 128x64; legal: 1x1 - 640x480]
+# NOTE: For connection type picolcdgfx the size is ignored and fixed at 256x64.
#Size=128x64
# Width and height of a character cell in pixels. This value is only used if
@@ -431,6 +432,14 @@
# Important: The value must be quoted as it contains equal signs!
#serdisp_options="INVERT=1"
+# picolcdgfx: Options
+# Time in ms for usb_read to wait on a key press. [default: 125; legal: >0]
+#picolcdgfx_KeyTimeout=125
+
+# Inverted: Inverts the pixels. [default: no; legal: yes or no]
+#picolcdgfx_Inverted=no
+
+# picolcdgfx: End of options
## glcdlib meta driver for graphical LCDs ##
Index: lcdproc/acinclude.m4
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/acinclude.m4,v
retrieving revision 1.128
diff -u -r1.128 acinclude.m4
--- lcdproc/acinclude.m4 27 Jan 2013 11:44:43 -0000 1.128
+++ lcdproc/acinclude.m4 30 Jan 2013 00:44:59 -0000
@@ -174,7 +174,7 @@
GLCD_DRIVERS="$GLCD_DRIVERS glcd-glcd-png.o"
fi
if test "$enable_libusb" = yes ; then
- GLCD_DRIVERS="$GLCD_DRIVERS glcd-glcd-glcd2usb.o"
+ GLCD_DRIVERS="$GLCD_DRIVERS glcd-glcd-glcd2usb.o glcd-glcd-picolcdgfx.o"
fi
AC_CHECK_HEADERS([serdisplib/serdisp.h],[
AC_CHECK_LIB(serdisp, serdisp_nextdisplaydescription,[
Index: lcdproc/docs/lcdproc-user/drivers/glcd.docbook
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/docs/lcdproc-user/drivers/glcd.docbook,v
retrieving revision 1.3
diff -u -r1.3 glcd.docbook
--- lcdproc/docs/lcdproc-user/drivers/glcd.docbook 4 Dec 2011 10:14:22 -0000 1.3
+++ lcdproc/docs/lcdproc-user/drivers/glcd.docbook 30 Jan 2013 00:44:59 -0000
@@ -80,6 +80,13 @@
</para>
</sect3>
+<sect3 id="glcd-ct-picolcdgfx">
+<title>Connection type picolcdgfx</title>
+<para>
+Support for the picoLCD Graphics 256x64 display from mini-box.com.
+</para>
+</sect3>
+
<!--
<sect3 id="glcd-ct-xyz">
<title>Connection type xyz</title>
@@ -107,6 +114,7 @@
<parameter><literal>glcd2usb</literal></parameter> |
<parameter><literal>png</literal></parameter> |
<parameter><literal>serdisplib</literal></parameter>
+ <parameter><literal>picolcdgfx</literal></parameter>
}
</term>
<listitem><para>
@@ -419,6 +427,27 @@
</varlistentry>
</variablelist>
+<variablelist>
+<title>Settings for the picolcdgfx connection type</title>
+<varlistentry>
+ <term>
+ <property>picolcdgfx_KeyTimeout</property>
+ </term>
+ <listitem><para>
+ The time in milliseconds to wait for a key press before assuming no key was
+ pressed. This settings is the usb_read timeout. Default 125.
+ </para></listitem>
+</varlistentry>
+<varlistentry>
+ <term>
+ <property>picolcdgfx_Inverted</property>
+ </term>
+ <listitem><para>
+ When set to yes, the pixel will be inverted. Default no.
+ </para></listitem>
+</varlistentry>
+</variablelist>
+
</sect3>
</sect2>
</sect1>
Index: lcdproc/server/drivers/Makefile.am
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/server/drivers/Makefile.am,v
retrieving revision 1.110
diff -u -r1.110 Makefile.am
--- lcdproc/server/drivers/Makefile.am 27 Jan 2013 11:44:43 -0000 1.110
+++ lcdproc/server/drivers/Makefile.am 30 Jan 2013 00:44:59 -0000
@@ -91,7 +91,7 @@
EyeboxOne_SOURCES = lcd.h lcd_lib.h EyeboxOne.c EyeboxOne.h report.h
g15_SOURCES = lcd.h lcd_lib.h g15.h g15-num.c g15.c report.h
glcd_SOURCES = lcd.h report.h glcd_drv.c glcd_drv.h glcd-low.h glcd-drivers.h glcd-render.c glcd-render.h
-EXTRA_glcd_SOURCES = glcd-t6963.c t6963_low.c t6963_low.h glcd-png.c glcd-serdisp.c glcd-glcd2usb.c glcd-glcd2usb.h
+EXTRA_glcd_SOURCES = glcd-t6963.c t6963_low.c t6963_low.h glcd-png.c glcd-serdisp.c glcd-glcd2usb.c glcd-glcd2usb.h glcd-picolcdgfx.c
glcdlib_SOURCES = lcd.h lcd_lib.h glcdlib.h glcdlib.c report.h
glk_SOURCES = lcd.h glk.c glk.h glkproto.c glkproto.h report.h
hd44780_SOURCES = lcd.h lcd_lib.h hd44780.h hd44780.c hd44780-drivers.h hd44780-low.h hd44780-charmap.h report.h adv_bignum.h
Index: lcdproc/server/drivers/glcd-drivers.h
===================================================================
RCS file: /cvsroot/lcdproc/lcdproc/server/drivers/glcd-drivers.h,v
retrieving revision 1.4
diff -u -r1.4 glcd-drivers.h
--- lcdproc/server/drivers/glcd-drivers.h 27 Nov 2011 10:36:51 -0000 1.4
+++ lcdproc/server/drivers/glcd-drivers.h 30 Jan 2013 00:44:59 -0000
@@ -24,6 +24,7 @@
#endif
#ifdef HAVE_LIBUSB
int glcd2usb_init(Driver *drvthis);
+int glcd_picolcdgfx_init(Driver *drvthis);
#endif
/* symbolic names for connection types */
@@ -32,6 +33,7 @@
#define GLCD_CT_PNG 2
#define GLCD_CT_SERDISP 3
#define GLCD_CT_GLCD2USB 4
+#define GLCD_CT_PICOLCDGFX 6
/** Structure linking symbolic names to initialization routines */
typedef struct ConnectionMapping {
@@ -58,6 +60,7 @@
#endif
#ifdef HAVE_LIBUSB
{"glcd2usb", GLCD_CT_GLCD2USB, glcd2usb_init},
+ {"picolcdgfx", GLCD_CT_PICOLCDGFX, glcd_picolcdgfx_init},
#endif
/* default, end of structure element (do not delete) */
{NULL, GLCD_CT_UNKNOWN, NULL}