mirror of
https://github.com/netfun2000/lcd4linux.git
synced 2026-02-27 09:44:34 +08:00
add shuttle VFD driver
git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1022 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
This commit is contained in:
@@ -99,6 +99,7 @@ drv_RouterBoard.c \
|
||||
drv_Sample.c \
|
||||
drv_st2205.c \
|
||||
drv_serdisplib.c \
|
||||
drv_ShuttleVFD.c \
|
||||
drv_SimpleLCD.c \
|
||||
drv_T6963.c \
|
||||
drv_Trefon.c \
|
||||
|
||||
+19
-4
@@ -36,9 +36,9 @@ AC_ARG_WITH(
|
||||
[ G15, GLCD2USB, HD44780, IRLCD, LCD2USB, LCDLinux, LCDTerm,]
|
||||
[ LPH7508, LUIse, M50530, MatrixOrbital, MilfordInstruments,]
|
||||
[ Noritake, NULL, PNG, PPM, Pertelian, PHAnderson, picoLCD,]
|
||||
[ picoLCDGraphic, RouterBoard, Sample, serdisplib, SimpleLCD,]
|
||||
[ st2205, T6963, Trefon, ULA200, USBLCD, USBHUB, VNC,]
|
||||
[ WincorNixdorf, X11],
|
||||
[ picoLCDGraphic, RouterBoard, Sample, serdisplib, ShuttleVFD,]
|
||||
[ SimpleLCD, st2205, T6963, Trefon, ULA200, USBLCD, USBHUB,]
|
||||
[ VNC, WincorNixdorf, X11],
|
||||
drivers=$withval,
|
||||
drivers=all
|
||||
)
|
||||
@@ -92,6 +92,7 @@ for driver in $drivers; do
|
||||
SAMPLE="yes"
|
||||
ST2205="yes"
|
||||
SERDISPLIB="yes"
|
||||
SHUTTLEVFD="yes"
|
||||
SIMPLELCD="yes"
|
||||
T6963="yes"
|
||||
Trefon="yes"
|
||||
@@ -186,7 +187,6 @@ for driver in $drivers; do
|
||||
picoLCDGraphic)
|
||||
PICOLCDGRAPHIC=$val
|
||||
;;
|
||||
|
||||
PNG)
|
||||
PNG=$val
|
||||
;;
|
||||
@@ -202,6 +202,9 @@ for driver in $drivers; do
|
||||
serdisplib)
|
||||
SERDISPLIB=$val;
|
||||
;;
|
||||
ShuttleVFD)
|
||||
SHUTTLEVFD=$val
|
||||
;;
|
||||
SimpleLCD)
|
||||
SIMPLELCD=$val
|
||||
;;
|
||||
@@ -576,6 +579,18 @@ if test "$SERDISPLIB" = "yes"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$SHUTTLEVFD" = "yes"; then
|
||||
if test "$has_usb" = "true"; then
|
||||
TEXT="yes"
|
||||
GPIO="yes"
|
||||
DRIVERS="$DRIVERS drv_ShuttleVFD.o"
|
||||
LIBUSB="yes"
|
||||
AC_DEFINE(WITH_SHUTTLEVFD,1,[ShuttleVFD driver])
|
||||
else
|
||||
AC_MSG_WARN(usb.h not found: ShuttleVFD driver disabled)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$SIMPLELCD" = "yes"; then
|
||||
TEXT="yes"
|
||||
SERIAL="yes"
|
||||
|
||||
@@ -78,6 +78,7 @@ extern DRIVER drv_RouterBoard;
|
||||
extern DRIVER drv_Sample;
|
||||
extern DRIVER drv_st2205;
|
||||
extern DRIVER drv_serdisplib;
|
||||
extern DRIVER drv_ShuttleVFD;
|
||||
extern DRIVER drv_SimpleLCD;
|
||||
extern DRIVER drv_T6963;
|
||||
extern DRIVER drv_Trefon;
|
||||
@@ -185,6 +186,9 @@ DRIVER *Driver[] = {
|
||||
#ifdef WITH_ST2205
|
||||
&drv_st2205,
|
||||
#endif
|
||||
#ifdef WITH_SHUTTLEVFD
|
||||
&drv_ShuttleVFD,
|
||||
#endif
|
||||
#ifdef WITH_SERDISPLIB
|
||||
&drv_serdisplib,
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
/* $Id: drv_Sample.c 975 2009-01-18 11:16:20Z michael $
|
||||
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_Sample.c $
|
||||
*
|
||||
* Shuttle SG33G5M VFD lcd4linux driver
|
||||
*
|
||||
* Copyright (C) 2009 Matthieu Crapet <mcrapet@gmail.com>
|
||||
* based on the USBLCD driver.
|
||||
*
|
||||
* Shuttle SG33G5M VFD (20x1 character display. Each character cell is 5x8 pixels)
|
||||
* - The display is driven by Princeton Technologies PT6314 VFD controller
|
||||
* - Cypress CY7C63723C (receives USB commands and talk to VFD controller)
|
||||
*
|
||||
* LCD "prococol" : each message has a length of 8 bytes
|
||||
* - 1 nibble: command (0x1, 0x3, 0x7, 0x9, 0xD)
|
||||
* - 0x1 : clear text and icons (len=1)
|
||||
* - 0x7 : icons (len=4)
|
||||
* - 0x9 : text (len=7)
|
||||
* - 0xD : set clock data (len=7)
|
||||
* - 0x3 : display clock (internal feature) (len=1)
|
||||
* - 1 nibble: message length (0-7)
|
||||
* - 7 bytes : message data
|
||||
*
|
||||
* 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_ShuttleVFD
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_USB_H
|
||||
#include <usb.h>
|
||||
#else
|
||||
#error "ShuttleVFD: libusb required"
|
||||
#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_bar.h" // for DIRECTION
|
||||
#include "drv.h"
|
||||
#include "drv_generic_text.h"
|
||||
#include "drv_generic_gpio.h"
|
||||
|
||||
|
||||
/*
|
||||
* Some hardware definitions
|
||||
*/
|
||||
// VFD USB properties
|
||||
#define SHUTTLE_VFD_VENDOR_ID 0x051C
|
||||
#define SHUTTLE_VFD_PRODUCT_ID1 0x0003
|
||||
#define SHUTTLE_VFD_PRODUCT_ID2 0x0005 // IR-receiver included
|
||||
#define SHUTTLE_VFD_INTERFACE_NUM 1
|
||||
|
||||
// VFD physical dimensions
|
||||
#define SHUTTLE_VFD_WIDTH 20
|
||||
#define SHUTTLE_VFD_HEIGHT 1
|
||||
|
||||
// VFD USB control message
|
||||
#define SHUTTLE_VFD_PACKET_SIZE 8
|
||||
#define SHUTTLE_VFD_DATA_SIZE (SHUTTLE_VFD_PACKET_SIZE-1)
|
||||
#define SHUTTLE_VFD_SUCCESS_SLEEP_USEC 25600
|
||||
|
||||
|
||||
/* Global static data */
|
||||
static char Name[] = "ShuttleVFD";
|
||||
static usb_dev_handle *lcd;
|
||||
static unsigned char buffer[SHUTTLE_VFD_PACKET_SIZE];
|
||||
|
||||
/* Issues with the display module:
|
||||
* - Can't set cursor position. Must save full buffer here.
|
||||
* - Can't get icons status (on or off). Must save status here.
|
||||
* - Clear command also clear text AND icons.
|
||||
*/
|
||||
static unsigned char fb[SHUTTLE_VFD_WIDTH * SHUTTLE_VFD_HEIGHT];
|
||||
static unsigned icons;
|
||||
|
||||
|
||||
/****************************************/
|
||||
/*** hardware dependant functions ***/
|
||||
/****************************************/
|
||||
|
||||
/* look for device on USB bus */
|
||||
static int drv_ShuttleVFD_open(void)
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
|
||||
int vendor_id = SHUTTLE_VFD_VENDOR_ID;
|
||||
int interface = SHUTTLE_VFD_INTERFACE_NUM;
|
||||
|
||||
lcd = NULL;
|
||||
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
|
||||
for (dev = bus->devices; dev != NULL; dev = dev->next) {
|
||||
if (dev->descriptor.idVendor == vendor_id && (
|
||||
(dev->descriptor.idProduct == SHUTTLE_VFD_PRODUCT_ID1) ||
|
||||
(dev->descriptor.idProduct == SHUTTLE_VFD_PRODUCT_ID2))) {
|
||||
|
||||
unsigned int v = dev->descriptor.bcdDevice;
|
||||
|
||||
info("%s: found ShuttleVFD V%1d%1d.%1d%1d on bus %s device %s", Name,
|
||||
(v & 0xF000) >> 12, (v & 0xF00) >> 8, (v & 0xF0) >> 4, (v & 0xF), bus->dirname, dev->filename);
|
||||
|
||||
lcd = usb_open(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lcd != NULL) {
|
||||
if (usb_claim_interface(lcd, interface) < 0) {
|
||||
usb_close(lcd);
|
||||
error("%s: usb_claim_interface() failed!", Name);
|
||||
error("%s: root permissions maybe required?", Name);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
error("%s: could not find ShuttleVFD", Name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int drv_ShuttleVFD_close(void)
|
||||
{
|
||||
int interface = SHUTTLE_VFD_INTERFACE_NUM;
|
||||
|
||||
usb_release_interface(lcd, interface);
|
||||
usb_close(lcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void drv_ShuttleVFD_send(unsigned char packet[SHUTTLE_VFD_PACKET_SIZE])
|
||||
{
|
||||
if (usb_control_msg(lcd, 0x21, // requesttype
|
||||
0x09, // request
|
||||
0x0200, // value
|
||||
0x0001, // index
|
||||
(char *) packet, SHUTTLE_VFD_PACKET_SIZE, 100) == SHUTTLE_VFD_PACKET_SIZE) {
|
||||
|
||||
udelay(SHUTTLE_VFD_SUCCESS_SLEEP_USEC);
|
||||
} else {
|
||||
debug("usb_control_msg failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Clear full display and icons. */
|
||||
static void drv_ShuttleVFD_clear(void)
|
||||
{
|
||||
// Update local framebuffer mirror
|
||||
memset(fb, ' ', SHUTTLE_VFD_HEIGHT * SHUTTLE_VFD_WIDTH);
|
||||
|
||||
buffer[0] = (1 << 4) + 1;
|
||||
buffer[1] = 0x1;
|
||||
drv_ShuttleVFD_send(buffer);
|
||||
}
|
||||
|
||||
|
||||
static void drv_ShuttleVFD_reset_cursor(void)
|
||||
{
|
||||
buffer[0] = (1 << 4) + 1;
|
||||
buffer[1] = 0x2;
|
||||
drv_ShuttleVFD_send(buffer);
|
||||
}
|
||||
|
||||
|
||||
/* text mode displays only */
|
||||
static void drv_ShuttleVFD_write(const int row, const int col, const char *data, int len)
|
||||
{
|
||||
unsigned char *p;
|
||||
int i;
|
||||
|
||||
// Update local framebuffer mirror
|
||||
memcpy(fb + (row * SHUTTLE_VFD_WIDTH) + col, data, len);
|
||||
|
||||
p = fb;
|
||||
len = SHUTTLE_VFD_WIDTH;
|
||||
|
||||
drv_ShuttleVFD_reset_cursor();
|
||||
|
||||
while (len > 0) {
|
||||
if (len > 7)
|
||||
buffer[0] = (9 << 4) + 7;
|
||||
else
|
||||
buffer[0] = (9 << 4) + len;
|
||||
|
||||
for (i = 0; i < 7 && len--; i++) {
|
||||
buffer[i + 1] = *p++;
|
||||
}
|
||||
|
||||
drv_ShuttleVFD_send(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drv_ShuttleVFD_defchar(const int ascii, const unsigned char *matrix)
|
||||
{
|
||||
(void)matrix;
|
||||
debug("%s: not available (ascii=%d)", Name, ascii);
|
||||
}
|
||||
|
||||
|
||||
static int drv_ShuttleVFD_start(const char *section)
|
||||
{
|
||||
char *port;
|
||||
|
||||
port = cfg_get(section, "Port", NULL);
|
||||
|
||||
if (port == NULL || *port == '\0') {
|
||||
error("%s: no '%s.Port' entry from %s", Name, section, cfg_source());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcasecmp(port, "libusb") != 0) {
|
||||
error("%s: libusb expected", Name);
|
||||
error("%s: compile lcd4linux with libusb support!", Name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DROWS = SHUTTLE_VFD_HEIGHT;
|
||||
DCOLS = SHUTTLE_VFD_WIDTH;
|
||||
|
||||
/* open communication with the display */
|
||||
if (drv_ShuttleVFD_open() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
drv_ShuttleVFD_clear(); /* clear display */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* VFD Icons. Add +1 in lcd4linux.conf (GPO1..GPIO27)
|
||||
* 0: television
|
||||
* 1: cd/dvd
|
||||
* 2: music
|
||||
* 3: radio
|
||||
* 4: clock
|
||||
* 5: pause
|
||||
* 6: play
|
||||
* 7: record
|
||||
* 8: rewind
|
||||
* 9: camera
|
||||
* 10: mute
|
||||
* 11: repeat
|
||||
* 12: reverse
|
||||
* 13: fastforward
|
||||
* 14: stop
|
||||
* 15: volume 1
|
||||
* 16: volume 2
|
||||
* ...
|
||||
* 25: volume 11
|
||||
* 26: volume 12
|
||||
*/
|
||||
static int drv_ShuttleVFD_icons_set(const int num, const int val)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
if (num < 0 || num >= 27) {
|
||||
info("%s: num %d out of range (1..27)", Name, num);
|
||||
return -1;
|
||||
}
|
||||
// Special case for volume (icon n°16)
|
||||
if (num >= 15)
|
||||
value = (num - 15 + 1) << 15;
|
||||
else
|
||||
value = 1 << num;
|
||||
|
||||
if (val > 0)
|
||||
icons |= value;
|
||||
else
|
||||
icons &= ~value;
|
||||
|
||||
buffer[0] = (7 << 4) + 4;
|
||||
buffer[1] = (value >> 15) & 0x1F;
|
||||
buffer[2] = (value >> 10) & 0x1F;
|
||||
buffer[3] = (value >> 5) & 0x1F;
|
||||
buffer[4] = value & 0x1F; // each data byte is stored on 5 bits
|
||||
drv_ShuttleVFD_send(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************/
|
||||
/*** plugins ***/
|
||||
/****************************************/
|
||||
|
||||
/* none yet ! */
|
||||
|
||||
|
||||
/****************************************/
|
||||
/*** widget callbacks ***/
|
||||
/****************************************/
|
||||
|
||||
/* using drv_generic_text_draw(W) */
|
||||
/* using drv_generic_gpio_draw(W) */
|
||||
|
||||
|
||||
/****************************************/
|
||||
/*** exported functions ***/
|
||||
/****************************************/
|
||||
|
||||
|
||||
/* supported Shuttle models */
|
||||
int drv_ShuttleVFD_list(void)
|
||||
{
|
||||
printf("Shuttle SG33G5M, Shuttle PF27 upgrade kit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* initialize driver & text display */
|
||||
int drv_ShuttleVFD_init(const char *section, const int quiet)
|
||||
{
|
||||
WIDGET_CLASS wc;
|
||||
int ret;
|
||||
|
||||
info("%s: %s", Name, "$Rev: 975 $");
|
||||
|
||||
/* display preferences */
|
||||
XRES = 5; /* pixel width of one char */
|
||||
YRES = 8; /* pixel height of one char */
|
||||
CHARS = 0; /* number of user-defineable characters */
|
||||
CHAR0 = 0; /* ASCII of first user-defineable char */
|
||||
GOTO_COST = 2; /* number of bytes a goto command requires */
|
||||
GPOS = 15 + 12; /* Fancy icons on top of display */
|
||||
|
||||
/* real worker functions */
|
||||
drv_generic_text_real_write = drv_ShuttleVFD_write;
|
||||
drv_generic_text_real_defchar = drv_ShuttleVFD_defchar;
|
||||
drv_generic_gpio_real_set = drv_ShuttleVFD_icons_set;
|
||||
|
||||
/* start display */
|
||||
if ((ret = drv_ShuttleVFD_start(section)) != 0)
|
||||
return ret;
|
||||
|
||||
if (!quiet) {
|
||||
char buffer[40];
|
||||
qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
|
||||
if (drv_generic_text_greet(buffer, "Shuttle")) {
|
||||
sleep(3);
|
||||
drv_ShuttleVFD_clear();
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize generic text driver */
|
||||
if ((ret = drv_generic_text_init(section, Name)) != 0)
|
||||
return ret;
|
||||
|
||||
/* initialize generic GPIO driver */
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* close driver & text display */
|
||||
int drv_ShuttleVFD_quit(const int quiet)
|
||||
{
|
||||
info("%s: shutting down.", Name);
|
||||
|
||||
/* clear display */
|
||||
drv_ShuttleVFD_clear();
|
||||
|
||||
/* say goodbye... */
|
||||
if (!quiet) {
|
||||
drv_generic_text_greet("goodbye!", NULL);
|
||||
}
|
||||
|
||||
drv_generic_text_quit();
|
||||
drv_generic_gpio_quit();
|
||||
|
||||
debug("closing connection");
|
||||
drv_ShuttleVFD_close();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
DRIVER drv_ShuttleVFD = {
|
||||
.name = Name,
|
||||
.list = drv_ShuttleVFD_list,
|
||||
.init = drv_ShuttleVFD_init,
|
||||
.quit = drv_ShuttleVFD_quit,
|
||||
};
|
||||
Reference in New Issue
Block a user