diff options
author | mrwastl <mrwastl@users.sourceforge.net> | 2013-01-07 00:40:59 +0100 |
---|---|---|
committer | mrwastl <mrwastl@users.sourceforge.net> | 2013-01-07 00:40:59 +0100 |
commit | c37e9b482fd9c8a610ea232bb1c6d7b45e248e6c (patch) | |
tree | 40994b2dbac06cf06177bd1314bde76410f0ebaf /glcddrivers/picoLCD_256x64.c | |
parent | aa57a08ce857b7a932819cf9f40296f213a80539 (diff) | |
download | graphlcd-base-c37e9b482fd9c8a610ea232bb1c6d7b45e248e6c.tar.gz graphlcd-base-c37e9b482fd9c8a610ea232bb1c6d7b45e248e6c.tar.bz2 |
experimental support added for picoLCD 256x64 (contributed by Jochen Koch)
Diffstat (limited to 'glcddrivers/picoLCD_256x64.c')
-rw-r--r-- | glcddrivers/picoLCD_256x64.c | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/glcddrivers/picoLCD_256x64.c b/glcddrivers/picoLCD_256x64.c new file mode 100644 index 0000000..8cef04d --- /dev/null +++ b/glcddrivers/picoLCD_256x64.c @@ -0,0 +1,553 @@ +/* + * 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 +} + |