Project

General

Profile

Feature #1210 » picoLCD256x64.diff

Anonymous, 01/05/2013 04:26 PM

View differences:

Make.config
# uncomment this variable if you want to enable the experimental AX 206 based digital photo frame driver
# Read DRIVER.ax206dpf before use!
#HAVE_AX206DPF_EXPERIMENTAL=1
HAVE_picoLCD_256x64_EXPERIMENTAL=1
glcddrivers/Makefile
LIBS += $(shell pkg-config --libs libusb)
DEFINES += -DHAVE_AX206DPF_EXPERIMENTAL
endif
endif
ifdef HAVE_picoLCD_256x64_EXPERIMENTAL
OBJS += picoLCD_256x64.o
INCLUDES += $(shell pkg-config --cflags libusb)
LIBS += $(shell pkg-config --libs libusb)
DEFINES += -DHAVE_picoLCD_256x64_EXPERIMENTAL
endif
endif
### Implicit rules:
glcddrivers/drivers.c
#ifdef HAVE_AX206DPF_EXPERIMENTAL
#include "ax206dpf.h"
#endif
#ifdef HAVE_picoLCD_256x64_EXPERIMENTAL
#include "picoLCD_256x64.h"
#endif
namespace GLCD
{
......
#ifdef HAVE_AX206DPF_EXPERIMENTAL
{"ax206dpf", kDriverAX206DPF},
#endif
#ifdef HAVE_picoLCD_256x64_EXPERIMENTAL
{"picolcd256x64", kDriverPicoLCD_256x64},
#endif
{"", kDriverUnknown}
};
......
case kDriverAX206DPF:
return new cDriverAX206DPF(config);
#endif
#ifdef HAVE_picoLCD_256x64_EXPERIMENTAL
case kDriverPicoLCD_256x64:
return new cDriverPicoLCD_256x64(config);
#endif
case kDriverUnknown:
default:
return NULL;
glcddrivers/drivers.h
#ifdef HAVE_AX206DPF_EXPERIMENTAL
kDriverAX206DPF = 17,
#endif
#ifdef HAVE_picoLCD_256x64_EXPERIMENTAL
kDriverPicoLCD_256x64 = 18,
#endif
kDriverSerDisp = 100,
kDriverG15daemon = 200
};
glcddrivers/picoLCD_256x64.c
/*
* GraphLCD driver library
*
* PicoLCD_256x64.c - picoLCD Graphic 256x64
* Output goes to a picoLCD Graphic 256x64 LCD
*
* Driver is based on lcd4linux driver by Nicu Pavel, Mini-Box.com <npavel@mini-box.com>
*
* This file is released under the GNU General Public License.
*
* See the files README and COPYING for details.
*
* 2012 by Jochen Koch <linuxfan1992 AT web de>
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <stdint.h>
#include <stdio.h>
#include <syslog.h>
#include <cstring>
#include "common.h"
#include "config.h"
#include "picoLCD_256x64.h"
namespace GLCD {
cDriverPicoLCD_256x64::cDriverPicoLCD_256x64(cDriverConfig * config)
: cDriver(config)
, pLG_framebuffer(0)
{
dirty = 1;
inverted = 0;
gpo = 0;
read_timeout = 0;
}
int cDriverPicoLCD_256x64::Init()
{
DEBUG("picoLCD Graphic initialization");
// default values
width = config->width;
if (width <= 0 || width > SCREEN_W)
width = SCREEN_W;
height = config->height;
if (height <= 0 || height > SCREEN_H)
height = SCREEN_H;
*oldConfig = *config;
if (drv_pLG_open() < 0) {
return -1;
}
/* Init framebuffer buffer */
pLG_framebuffer = (unsigned char *)malloc(SCREEN_W * SCREEN_H / 8 * sizeof(unsigned char));
if (!pLG_framebuffer)
{
INFO("picoLCD_256x64: frame buffer could not be allocated: malloc() failed");
return -1;
}
/* clear display */
Clear();
drv_pLG_clear();
DEBUG("zeroed");
// inverted display
inverted = (config->invert ? 0xff : 0);
// Set Display SetBrightness
SetBacklight(config->backlight);
// Set Display SetContrast
SetContrast(config->contrast);
return 0;
}
int cDriverPicoLCD_256x64::DeInit()
{
DEBUG("picoLCD_256x64: shutting down.");
/* clear display */
Clear();
drv_pLG_clear();
drv_pLG_close();
if (pLG_framebuffer) {
free(pLG_framebuffer);
pLG_framebuffer = NULL;
}
return 0;
}
int cDriverPicoLCD_256x64::CheckSetup()
{
if (config->width != oldConfig->width ||
config->height != oldConfig->height)
{
DeInit();
return Init();
}
if (config->backlight != oldConfig->backlight)
{
oldConfig->backlight = config->backlight;
SetBacklight(config->backlight);
}
if (config->contrast != oldConfig->contrast)
{
oldConfig->contrast = config->contrast;
SetContrast(config->contrast);
}
if (config->upsideDown != oldConfig->upsideDown ||
config->invert != oldConfig->invert)
{
oldConfig->upsideDown = config->upsideDown;
oldConfig->invert = config->invert;
inverted = (config->invert ? 0xff : 0);
return 1;
}
return 0;
}
void cDriverPicoLCD_256x64::Clear()
{
for (unsigned int n = 0; pLG_framebuffer && n < (SCREEN_W * SCREEN_H / 8); n++)
pLG_framebuffer[n] = 0x00;
}
void cDriverPicoLCD_256x64::SetPixel(int x, int y, uint32_t data)
{
unsigned char c;
int n;
if (!pLG_framebuffer)
return;
if (x >= width || x < 0)
return;
if (y >= height || y < 0)
return;
if (config->upsideDown)
{
x = width - 1 - x;
y = height - 1 - y;
}
n = x + ((y / 8) * SCREEN_W);
c = 0x01 << (y % 8);
if (data == GRAPHLCD_White)
pLG_framebuffer[n] |= c;
else
pLG_framebuffer[n] &= (0xFF ^ c);
/* display needs to be redrawn from frame buffer */
dirty = 1;
}
void cDriverPicoLCD_256x64::Refresh(bool refreshAll)
{
unsigned char cmd3[64] = { OUT_REPORT_CMD_DATA }; /* send command + data */
unsigned char cmd4[64] = { OUT_REPORT_DATA }; /* send data only */
int index, x, s;
unsigned char cs, line;
if (!pLG_framebuffer)
return;
s = CheckSetup();
if ((s > 0) || dirty)
refreshAll = true;
/* do not redraw display if frame buffer has not changed */
if (!refreshAll) {
DEBUG("Skipping");
return;
}
DEBUG("entered");
for (cs = 0; cs < 4; cs++)
{
unsigned char chipsel = (cs << 2); //chipselect
for (line = 0; line < 8; line++)
{
//ha64_1.setHIDPkt(OUT_REPORT_CMD_DATA, 8+3+32, 8, chipsel, 0x02, 0x00, 0x00, 0xb8|j, 0x00, 0x00, 0x40);
cmd3[0] = OUT_REPORT_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;
//ha64_2.setHIDPkt(OUT_REPORT_DATA, 4+32, 4, chipsel | 0x01, 0x00, 0x00, 32);
cmd4[0] = OUT_REPORT_DATA;
cmd4[1] = chipsel | 0x01;
cmd4[2] = 0x00;
cmd4[3] = 0x00;
cmd4[4] = 32;
for (index = 0; index < 32; index++)
{
x=64*cs+index;
cmd3[12 + index] = pLG_framebuffer[line * SCREEN_W + x] ^ inverted;
}
for (index = 32; index < 64; index++)
{
x=64*cs+index;
cmd4[5 + (index - 32)] = pLG_framebuffer[line * SCREEN_W + x] ^ inverted;
}
drv_pLG_send(cmd3, 44);
drv_pLG_send(cmd4, 38);
}
}
/* mark display as up-to-date */
dirty = 0;
}
/*
* Sets the backlight brightness of the display.
*
*/
void cDriverPicoLCD_256x64::SetBacklight(unsigned int onoff)
{
unsigned char cmd[2] = { 0x91 }; /* set backlight */
cmd[1] = (onoff>0 ? 0xff : 0);
drv_pLG_send(cmd, 2);
}
void cDriverPicoLCD_256x64::SetContrast(unsigned int val)
{
unsigned char cmd[2] = { 0x92 }; /* set contrast */
if (val > 10)
val = 10;
cmd[1] = 0x99+val*(0xff-0x99)/10;
drv_pLG_send(cmd, 2);
}
/****************************************/
/*** hardware dependant functions ***/
/****************************************/
int cDriverPicoLCD_256x64::drv_pLG_open(void)
{
struct usb_bus *busses, *bus;
struct usb_device *dev;
char driver[1024];
char product[1024];
char manufacturer[1024];
char serialnumber[1024];
int ret;
lcd = NULL;
INFO("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 == picoLCD_VENDOR) && (dev->descriptor.idProduct == picoLCD_DEVICE)) {
DEBUG1("found picoLCD on bus %s device %s", bus->dirname, dev->filename);
lcd = usb_open(dev);
ret = usb_get_driver_np(lcd, 0, driver, sizeof(driver));
if (ret == 0) {
DEBUG1("interface 0 already claimed by '%s'", driver);
DEBUG(" attempting to detach driver...");
if (usb_detach_kernel_driver_np(lcd, 0) < 0) {
DEBUG("usb_detach_kernel_driver_np() failed!");
return -1;
}
}
usb_set_configuration(lcd, 1);
usleep(100);
if (usb_claim_interface(lcd, 0) < 0) {
DEBUG("picoLCD_256x64: usb_claim_interface() failed!");
return -1;
}
usb_set_altinterface(lcd, 0);
usb_get_string_simple(lcd, dev->descriptor.iProduct, product, sizeof(product));
usb_get_string_simple(lcd, dev->descriptor.iManufacturer, manufacturer, sizeof(manufacturer));
usb_get_string_simple(lcd, dev->descriptor.iSerialNumber, serialnumber, sizeof(serialnumber));
INFO1("Manufacturer='%s' Product='%s' SerialNumber='%s\n'", manufacturer, product, serialnumber);
return 0;
}
}
}
INFO("could not find a picoLCD");
return -1;
}
int cDriverPicoLCD_256x64::drv_pLG_read(unsigned char *data, int size)
{
return usb_interrupt_read(lcd, USB_ENDPOINT_IN + 1, (char *) data, size, read_timeout);
}
void cDriverPicoLCD_256x64::drv_pLG_send(unsigned char *data, int size)
{
int __attribute__ ((unused)) ret;
ret = usb_interrupt_write(lcd, USB_ENDPOINT_OUT + 1, (char *) data, size, 1000);
}
int cDriverPicoLCD_256x64::drv_pLG_close(void)
{
usb_release_interface(lcd, 0);
usb_close(lcd);
return 0;
}
void cDriverPicoLCD_256x64::drv_pLG_clear(void)
{
unsigned char cmd[3] = { 0x93, 0x01, 0x00 }; /* init display */
unsigned char cmd2[9] = { OUT_REPORT_CMD }; /* init display */
unsigned char cmd3[64] = { OUT_REPORT_CMD_DATA }; /* clear screen */
unsigned char cmd4[64] = { OUT_REPORT_CMD_DATA }; /* clear screen */
int init, index;
unsigned char cs, line;
DEBUG("entering\n");
drv_pLG_send(cmd, 3);
for (init = 0; init < 4; init++) {
unsigned char cs = ((init << 2) & 0xFF);
cmd2[0] = OUT_REPORT_CMD;
cmd2[1] = cs;
cmd2[2] = 0x02;
cmd2[3] = 0x00;
cmd2[4] = 0x64;
cmd2[5] = 0x3F;
cmd2[6] = 0x00;
cmd2[7] = 0x64;
cmd2[8] = 0xC0;
drv_pLG_send(cmd2, 9);
}
for (cs = 0; cs < 4; cs++) {
unsigned char chipsel = (cs << 2); //chipselect
for (line = 0; line < 8; line++) {
//ha64_1.setHIDPkt(OUT_REPORT_CMD_DATA, 8+3+32, 8, cs, 0x02, 0x00, 0x00, 0xb8|j, 0x00, 0x00, 0x40);
cmd3[0] = OUT_REPORT_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;
unsigned char temp = 0;
for (index = 0; index < 32; index++) {
cmd3[12 + index] = temp;
}
drv_pLG_send(cmd3, 64);
//ha64_2.setHIDPkt(OUT_REPORT_DATA, 4+32, 4, cs | 0x01, 0x00, 0x00, 32);
cmd4[0] = OUT_REPORT_DATA;
cmd4[1] = chipsel | 0x01;
cmd4[2] = 0x00;
cmd4[3] = 0x00;
cmd4[4] = 32;
for (index = 32; index < 64; index++) {
temp = 0x00;
cmd4[5 + (index - 32)] = temp;
}
drv_pLG_send(cmd4, 64);
}
}
}
#ifdef ENABLE_GPIO_KEYPAD
/**************************************\
* *
* Routines for GPI, GPO & Keypad *
* *
\**************************************/
#define _USBLCD_MAX_DATA_LEN 24
#define IN_REPORT_KEY_STATE 0x11
typedef enum {
WIDGET_KEY_UP = 1,
WIDGET_KEY_DOWN = 2,
WIDGET_KEY_LEFT = 4,
WIDGET_KEY_RIGHT = 8,
WIDGET_KEY_CONFIRM = 16,
WIDGET_KEY_CANCEL = 32,
WIDGET_KEY_PRESSED = 64,
WIDGET_KEY_RELEASED = 128
} KEYPADKEY;
int cDriverPicoLCD_256x64::drv_pLG_gpi( __attribute__ ((unused))
int num)
{
int ret;
unsigned char read_packet[_USBLCD_MAX_DATA_LEN];
ret = drv_pLG_read(read_packet, _USBLCD_MAX_DATA_LEN);
if ((ret > 0) && (read_packet[0] == IN_REPORT_KEY_STATE)) {
// DEBUG("picoLCD: pressed key= 0x%02x\n", read_packet[1]);
return read_packet[1];
}
return 0;
}
int cDriverPicoLCD_256x64::drv_pLG_gpo(int num, int val)
{
unsigned char cmd[2] = { 0x81 }; /* set GPO */
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);
cmd[1] = gpo;
drv_pLG_send(cmd, 2);
return val;
}
void cDriverPicoLCD_256x64::drv_pLG_update_keypad(void)
{
static int pressed_key = 0;
int ret;
unsigned char read_packet[_USBLCD_MAX_DATA_LEN];
ret = drv_pLG_read(read_packet, _USBLCD_MAX_DATA_LEN);
if ((ret > 0) && (read_packet[0] == IN_REPORT_KEY_STATE)) {
// DEBUG("picoLCD: pressed key= 0x%02x\n", read_packet[1]);
int new_pressed_key = read_packet[1];
if (pressed_key != new_pressed_key) {
/* negative values mark a key release */
// drv_generic_keypad_press(-pressed_key);
// drv_generic_keypad_press(new_pressed_key);
pressed_key = new_pressed_key;
}
}
}
int cDriverPicoLCD_256x64::drv_pLG_keypad(const int num)
{
int val;
int new_num = num;
if (new_num == 0)
return 0;
else if (new_num > 0)
val = WIDGET_KEY_PRESSED;
else {
/* negative values mark a key release */
new_num = -num;
val = WIDGET_KEY_RELEASED;
}
switch (new_num) {
case 1:
val += WIDGET_KEY_CANCEL;
break;
case 2:
val += WIDGET_KEY_LEFT;
break;
case 3:
val += WIDGET_KEY_RIGHT;
break;
case 5:
val += WIDGET_KEY_UP;
break;
case 6:
val += WIDGET_KEY_CONFIRM;
break;
case 7:
val += WIDGET_KEY_DOWN;
break;
default:
fprintf(stderr,"picoLCD_256x64: unknown keypad value %d", num);
}
return val;
}
#endif
// /namespace
}
glcddrivers/picoLCD_256x64.h
/*
* GraphLCD driver library
*
* PicoLCD_256x64.h - picoLCD Graphic 256x64
* Output goes to a picoLCD Graphic 256x64 LCD
*
* Driver is based on lcd4linux driver by Nicu Pavel, Mini-Box.com <npavel@mini-box.com>
*
* This file is released under the GNU General Public License.
*
* See the files README and COPYING for details.
*
* 2012 by Jochen Koch <linuxfan1992 AT web de>
*/
#ifndef _GLCDDRIVERS_PicoLCD_256x64_H_
#define _GLCDDRIVERS_PicoLCD_256x64_H_
#include "driver.h"
#include "stdio.h"
#include <usb.h>
#include <syslog.h>
#define HAVE_STDBOOL_H
#define picoLCD_VENDOR 0x04d8
#define picoLCD_DEVICE 0xc002
#define OUT_REPORT_LED_STATE 0x81
#define OUT_REPORT_LCD_BACKLIGHT 0x91
#define OUT_REPORT_LCD_CONTRAST 0x92
#define OUT_REPORT_CMD 0x94
#define OUT_REPORT_DATA 0x95
#define OUT_REPORT_CMD_DATA 0x96
#define SCREEN_H 64
#define SCREEN_W 256
#if 0
#define DEBUG(x) fprintf(stderr,"picoLCD_256x64: %s(): " #x "\n", __FUNCTION__);
#define DEBUG1(x,...) fprintf(stderr,"picoLCD_256x64: %s(): " #x "\n", __FUNCTION__, __VA_ARGS__);
#else
#define DEBUG(x)
#define DEBUG1(x,...)
#endif
#define INFO(x) syslog(LOG_INFO, "picoLCD_256x64: %s\n", x);
#define INFO1(x,...) syslog(LOG_INFO, "picoLCD_256x64: " #x "\n", __VA_ARGS__);
namespace GLCD
{
class cDriverConfig;
class cDriverPicoLCD_256x64 : public cDriver
{
/* "dirty" marks the display to be redrawn from frame buffer */
int dirty;
/* USB read timeout in ms (the picoLCD 256x64 times out on every read
unless a key has been pressed!) */
int read_timeout;
unsigned char *pLG_framebuffer;
/* used to display white text on black background or inverse */
unsigned char inverted;
unsigned int gpo;
usb_dev_handle *lcd;
int CheckSetup();
protected:
int drv_pLG_open(void);
int drv_pLG_read(unsigned char *data, int size);
void drv_pLG_send(unsigned char *data, int size);
int drv_pLG_close(void);
void drv_pLG_clear(void);
#ifdef ENABLE_GPIO_KEYPAD
// GPI, GPO, Keypad
int drv_pLG_gpi(int num);
int drv_pLG_gpo(int num, int val);
void drv_pLG_update_keypad(void);
int drv_pLG_keypad(const int num);
#endif
public:
cDriverPicoLCD_256x64(cDriverConfig * config);
virtual int Init();
virtual int DeInit();
virtual void Clear();
virtual void SetPixel(int x, int y, uint32_t data);
//virtual void Set8Pixels(int x, int y, byte data);
virtual void Refresh(bool refreshAll = false);
virtual void SetBacklight(unsigned int percent);
virtual void SetContrast(unsigned int percent);
};
};
#endif
    (1-1/1)