New connection type 'picolcdgfx' that supports picoLCD 256x64 Sideshow
graphical displays from Mini-Box.com (by S. Meharg).
This commit is contained in:
@@ -16,6 +16,7 @@ v0.5dev (ongoing development)
|
||||
+ hd44780: New connection type 'piplate' (J. Brogdon)
|
||||
* lcdproc client: Add option to turn off title on OldTime screen
|
||||
+ glcd driver: Connection type 'x11' that draws to a X window (S. Meharg)
|
||||
+ glcd driver: 'picolcdgfx' for picoLCD 256x64 from Mini-Box.com (S. Meharg)
|
||||
|
||||
v0.5.6
|
||||
- Remove deprecated CFontz633 driver. Use CFontzPacket with Model=633 instead!
|
||||
|
||||
@@ -456,6 +456,14 @@ serdisp_device=/dev/ppi0
|
||||
# Inverted: inverts the pixels [default: no; legal: yes, no]
|
||||
#x11_Inverted=no
|
||||
|
||||
# --- 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
|
||||
|
||||
|
||||
|
||||
## glcdlib meta driver for graphical LCDs ##
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@ dnl else
|
||||
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,[
|
||||
|
||||
@@ -89,6 +89,13 @@ contrast and brightness. PC keyboard is used to simulate buttons.
|
||||
</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>
|
||||
@@ -115,7 +122,8 @@ contrast and brightness. PC keyboard is used to simulate buttons.
|
||||
<emphasis><parameter><literal>t6963</literal></parameter></emphasis> |
|
||||
<parameter><literal>glcd2usb</literal></parameter> |
|
||||
<parameter><literal>png</literal></parameter> |
|
||||
<parameter><literal>serdisplib</literal></parameter>
|
||||
<parameter><literal>picolcdgfx</literal></parameter> |
|
||||
<parameter><literal>serdisplib</literal></parameter> |
|
||||
<parameter><literal>x11</literal></parameter>
|
||||
}
|
||||
</term>
|
||||
@@ -488,6 +496,28 @@ contrast and brightness. PC keyboard is used to simulate buttons.
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<variablelist>
|
||||
<title>Settings for the picolcdgfx connection type</title>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<property>picolcdgfx_KeyTimeout</property> =
|
||||
<parameter><replaceable>TIMEOUT</replaceable></parameter>
|
||||
</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> = ¶meters.yesnodef;
|
||||
</term>
|
||||
<listitem><para>
|
||||
When set to yes, the pixel will be inverted. Default no.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</sect3>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
@@ -91,7 +91,7 @@ ea65_SOURCES = lcd.h ea65.h ea65.c report.h
|
||||
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 glcd-x11.c
|
||||
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-x11.c 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
|
||||
|
||||
@@ -24,6 +24,7 @@ int glcd_serdisp_init(Driver *drvthis);
|
||||
#endif
|
||||
#ifdef HAVE_LIBUSB
|
||||
int glcd2usb_init(Driver *drvthis);
|
||||
int glcd_picolcdgfx_init(Driver *drvthis);
|
||||
#endif
|
||||
#ifdef HAVE_LIBX11
|
||||
int glcd_x11_init(Driver *drvthis);
|
||||
@@ -36,6 +37,7 @@ int glcd_x11_init(Driver *drvthis);
|
||||
#define GLCD_CT_SERDISP 3
|
||||
#define GLCD_CT_GLCD2USB 4
|
||||
#define GLCD_CT_X11 5
|
||||
#define GLCD_CT_PICOLCDGFX 6
|
||||
|
||||
/** Structure linking symbolic names to initialization routines */
|
||||
typedef struct ConnectionMapping {
|
||||
@@ -62,6 +64,7 @@ static const ConnectionMapping connectionMapping[] = {
|
||||
#endif
|
||||
#ifdef HAVE_LIBUSB
|
||||
{"glcd2usb", GLCD_CT_GLCD2USB, glcd2usb_init},
|
||||
{"picolcdgfx", GLCD_CT_PICOLCDGFX, glcd_picolcdgfx_init},
|
||||
#endif
|
||||
#ifdef HAVE_LIBX11
|
||||
{"x11", GLCD_CT_X11, glcd_x11_init},
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
/** \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 <napvel@mini-box.com>
|
||||
* Copyright (c) 2012 Scott Meahrg <ssmeharg@gmail.com>
|
||||
*
|
||||
* 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 */
|
||||
#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
|
||||
|
||||
/* Display properties */
|
||||
#define PICOLCDGFX_WIDTH 256
|
||||
#define PICOLCDGFX_HEIGHT 64
|
||||
|
||||
/** Private data for the picolcdgfx 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);
|
||||
|
||||
/* Local functions */
|
||||
static 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);
|
||||
}
|
||||
|
||||
static void
|
||||
picolcdgfx_write(usb_dev_handle * lcd, unsigned char *data, int size)
|
||||
{
|
||||
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.layout = FB_TYPE_VPAGED;
|
||||
p->framebuf.px_width = PICOLCDGFX_WIDTH;
|
||||
p->framebuf.px_height = PICOLCDGFX_HEIGHT;
|
||||
|
||||
/* Since the display is fixed to 256x64 we have to recalculate. */
|
||||
p->framebuf.size = (PICOLCDGFX_HEIGHT / 8) * PICOLCDGFX_WIDTH;
|
||||
|
||||
ct_data->backingstore = malloc(p->framebuf.size);
|
||||
if (ct_data->backingstore == NULL) {
|
||||
report(RPT_ERR, "GLCD/picolcdgfx: unable to allocate backing store");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* framebuf is initialized with 0x00 so initialize the backingstore with
|
||||
* 0xFF so the first call to _blit will draw the entire screen.
|
||||
* */
|
||||
memset(ct_data->backingstore, 0xFF, p->framebuf.size);
|
||||
|
||||
/* Get key timeout */
|
||||
ct_data->keytimeout = drvthis->config_get_int(drvthis->name,
|
||||
"picolcdgfx_KeyTimeout", 0,
|
||||
PICOLCDGFX_DEF_KEYTIMEOUT);
|
||||
|
||||
/* Get inverted option */
|
||||
if (drvthis->config_get_bool(drvthis->name, "picolcdgfx_Inverted", 0, PICOLCDGFX_DEF_INVERTED))
|
||||
ct_data->inverted = 0xFF;
|
||||
else
|
||||
ct_data->inverted = 0;
|
||||
|
||||
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;
|
||||
|
||||
/* send command + data */
|
||||
unsigned char cmd3[64] = {PICOLCDGFX_OUT_CMD_DATA};
|
||||
/* send data only */
|
||||
unsigned char cmd4[64] = {PICOLCDGFX_OUT_DATA};
|
||||
|
||||
int offset;
|
||||
int index;
|
||||
unsigned char cs, line; /* controller and page */
|
||||
|
||||
for (cs = 0; cs < 4; cs++) {
|
||||
unsigned char chipsel = (cs << 2);
|
||||
for (line = 0; line < 8; line++) {
|
||||
offset = line * PICOLCDGFX_WIDTH + cs * 64;
|
||||
if (memcmp((p->framebuf.data) + offset, (ct_data->backingstore) + offset, 64) == 0)
|
||||
continue;
|
||||
|
||||
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++) {
|
||||
cmd3[12 + index] = *((p->framebuf.data) + offset + index) ^ ct_data->inverted;
|
||||
}
|
||||
|
||||
for (index = 32; index < 64; index++) {
|
||||
cmd4[5 + (index - 32)] = *((p->framebuf.data) + offset + index) ^ ct_data->inverted;
|
||||
}
|
||||
|
||||
picolcdgfx_write(ct_data->lcd, cmd3, 44);
|
||||
picolcdgfx_write(ct_data->lcd, cmd4, 37);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(ct_data->backingstore, p->framebuf.data, p->framebuf.size);
|
||||
}
|
||||
|
||||
/**
|
||||
* API: Release low-level resources.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* API: Poll for any pressed keys. Converts the bitmap of keys pressed into a
|
||||
* scancode (1-6) for each pressed key.
|
||||
*/
|
||||
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; /* Escape */
|
||||
break;
|
||||
case 0x02:
|
||||
rv = 3; /* Left */
|
||||
break;
|
||||
case 0x05:
|
||||
rv = 1; /* Up */
|
||||
break;
|
||||
case 0x06:
|
||||
rv = 5; /* Enter */
|
||||
break;
|
||||
case 0x07:
|
||||
rv = 2; /* Down */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* API: Set the backlight brightness.
|
||||
*/
|
||||
void
|
||||
glcd_picolcdgfx_set_backlight(PrivateData *p, int state)
|
||||
{
|
||||
CT_picolcdgfx_data *ct_data = (CT_picolcdgfx_data *) p->ct_data;
|
||||
int promille = (state == BACKLIGHT_ON) ? p->brightness : p->offbrightness;
|
||||
unsigned char cmd[2];
|
||||
|
||||
cmd[0] = PICOLCDGFX_OUT_BACKLIGHT;
|
||||
cmd[1] = (promille * 255 / 1000);
|
||||
|
||||
picolcdgfx_write(ct_data->lcd, cmd, 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* API: Change LCD contrast.
|
||||
*/
|
||||
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};
|
||||
|
||||
/* I believe hardware contrast values are 200 to 255. Where a higher
|
||||
* contrast setting sends a lower value to the deivce. (S. Meharg) */
|
||||
unsigned char val = ((1000 - value) * (255 - 200)) / 1000 + 200;
|
||||
|
||||
cmd[1] = val;
|
||||
picolcdgfx_write(ct_data->lcd, cmd, 2);
|
||||
}
|
||||
Reference in New Issue
Block a user