Add MDM166A driver for Futaba/Targa USB VFD (Christoph Rasim).
This commit is contained in:
@@ -270,6 +270,9 @@ Jonathan Kyler:
|
||||
Laurent Latil
|
||||
- SureElec driver for devices made by SURE Electronics
|
||||
|
||||
Christoph Rasim
|
||||
- MDM166A driver for Futaba/Targa USB VFD
|
||||
|
||||
|
||||
Further developers in the sourceforge lcdproc team:
|
||||
Mindaugas Idzelis aim4min
|
||||
|
||||
@@ -31,6 +31,7 @@ v.0.5dev (ongoing development)
|
||||
* picolcd: Use module output function to control key LEDs (Martin Jones)
|
||||
+ hd44780: Added 'usbtiny' connection type (Siarhei Herasimchuk)
|
||||
* SureElec: Fix stall on startup
|
||||
+ new driver: MDM166A for Futaba/Targa USB VFD (Christoph Rasim)
|
||||
|
||||
v0.5.3
|
||||
+ lcdexec: notification when called program finishes
|
||||
|
||||
@@ -45,11 +45,11 @@ DriverPath=server/drivers/
|
||||
#
|
||||
# The following drivers are supported:
|
||||
# bayrad, CFontz, CFontz633, CFontzPacket, curses, CwLnx, ea65,
|
||||
# EyeboxOne, g15, glcdlib, glk, hd44780, icp_a106, imon, imonlcd, IOWarrior,
|
||||
# irman, joy, lb216, lcdm001, lcterm, lirc, lis, MD8800, ms6931, mtc_s16209x,
|
||||
# MtxOrb, mx5000, NoritakeVFD, picolcd, pyramid, sed1330, sed1520, serialPOS,
|
||||
# serialVFD, shuttleVFD, sli, stv5730, svga, t6963, text, tyan, ula200,
|
||||
# xosd
|
||||
# EyeboxOne, g15, glcdlib, glk, hd44780, icp_a106, imon, imonlcd,
|
||||
# IOWarrior, irman, joy, lb216, lcdm001, lcterm, lirc, lis, MD8800,
|
||||
# mdm166a, ms6931, mtc_s16209x, MtxOrb, mx5000, NoritakeVFD, picolcd,
|
||||
# pyramid, sed1330, sed1520, serialPOS, serialVFD, shuttleVFD, sli,
|
||||
# stv5730, svga, t6963, text, tyan, ula200, xosd
|
||||
Driver=curses
|
||||
|
||||
# Tells the driver to bind to the given interface
|
||||
@@ -736,6 +736,18 @@ OffBrightness=50
|
||||
|
||||
|
||||
|
||||
## Futuba MDM166A Display
|
||||
[mdm166a]
|
||||
# Show self-running clock after LCDd shutdown
|
||||
# Possible values: [default: no; legal: no, small, big]
|
||||
Clock=big
|
||||
# Dimm display, no dimming gives full brightness [default: no, legal: yes, no]
|
||||
Dimming=no
|
||||
# Dimm display in case LCDd is inactive [default: no, legal: yes, no]
|
||||
OffDimming=yes
|
||||
|
||||
|
||||
|
||||
## MSI MS-6931 driver for displays in 1HU servers ##
|
||||
[ms6931]
|
||||
|
||||
|
||||
+14
-6
@@ -11,18 +11,18 @@ AC_ARG_ENABLE(drivers,
|
||||
[ bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,]
|
||||
[ ea65,EyeboxOne,g15,glcdlib,glk,hd44780,i2500vfd,]
|
||||
[ icp_a106,imon,imonlcd,IOWarrior,irman,irtrans,]
|
||||
[ joy,lb216,lcdm001,lcterm,lirc,lis,MD8800,ms6931,]
|
||||
[ mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,picolcd,]
|
||||
[ pyramid,sed1330,sed1520,serialPOS,serialVFD,]
|
||||
[ shuttleVFD,sli,stv5730,SureElec,svga,t6963,text,]
|
||||
[ tyan,ula200,xosd]
|
||||
[ joy,lb216,lcdm001,lcterm,lirc,lis,MD8800,mdm166a,]
|
||||
[ ms6931,mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,]
|
||||
[ picolcd,pyramid,sed1330,sed1520,serialPOS,]
|
||||
[ serialVFD,shuttleVFD,sli,stv5730,SureElec,svga,]
|
||||
[ t6963,text,tyan,ula200,xosd]
|
||||
[ ]
|
||||
[ 'all' compiles all drivers;]
|
||||
[ 'all,!xxx,!yyy' de-selects previously selected drivers],
|
||||
drivers="$enableval",
|
||||
drivers=[bayrad,CFontz,CFontz633,curses,CwLnx,glk,lb216,lcdm001,MtxOrb,pyramid,text])
|
||||
|
||||
allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,i2500vfd,icp_a106,imon,imonlcd,IOWarrior,irman,irtrans,joy,lb216,lcdm001,lcterm,lirc,lis,MD8800,ms6931,mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,shuttleVFD,sli,stv5730,SureElec,svga,t6963,text,tyan,ula200,xosd]
|
||||
allDrivers=[bayrad,CFontz,CFontz633,CFontzPacket,curses,CwLnx,ea65,EyeboxOne,g15,glcdlib,glk,hd44780,i2500vfd,icp_a106,imon,imonlcd,IOWarrior,irman,irtrans,joy,lb216,lcdm001,lcterm,lirc,lis,MD8800,mdm166a,ms6931,mtc_s16209x,MtxOrb,mx5000,NoritakeVFD,picolcd,pyramid,sed1330,sed1520,serialPOS,serialVFD,shuttleVFD,sli,stv5730,SureElec,svga,t6963,text,tyan,ula200,xosd]
|
||||
|
||||
drivers=`echo $drivers | sed -e 's/,/ /g'`
|
||||
|
||||
@@ -318,6 +318,14 @@ dnl else
|
||||
DRIVERS="$DRIVERS MD8800${SO}"
|
||||
actdrivers=["$actdrivers MD8800"]
|
||||
;;
|
||||
mdm166a)
|
||||
if test "$enable_libhid" = yes ; then
|
||||
DRIVERS="$DRIVERS mdm166a${SO}"
|
||||
actdrivers=["$actdrivers mdm166a"]
|
||||
else
|
||||
AC_MSG_WARN([The mdm166a driver needs the hid library])
|
||||
fi
|
||||
;;
|
||||
ms6931)
|
||||
DRIVERS="$DRIVERS ms6931${SO}"
|
||||
actdrivers=["$actdrivers ms6931"]
|
||||
|
||||
@@ -292,6 +292,29 @@ fi
|
||||
AC_SUBST(LIBFTDI_LIBS)
|
||||
AC_SUBST(LIBFTDI_CFLAGS)
|
||||
|
||||
dnl ######################################################################
|
||||
dnl libhid support
|
||||
dnl ######################################################################
|
||||
AC_MSG_CHECKING([if libhid support has been enabled]);
|
||||
AC_ARG_ENABLE(libhid,
|
||||
[AS_HELP_STRING([--disable-libhid],[disable HID support using libhid])],
|
||||
[ if test "$enableval" != "no"; then
|
||||
enable_libhid=yes
|
||||
fi ],
|
||||
[ enable_libhid=yes ]
|
||||
)
|
||||
AC_MSG_RESULT($enable_libhid)
|
||||
|
||||
if test "$enable_libhid" = "yes"; then
|
||||
ifdef([PKG_CHECK_MODULES],
|
||||
[PKG_CHECK_MODULES(LIBHID, libhid >= 0.2.16,
|
||||
[AC_DEFINE(HAVE_LIBHID, [1], [Define to 1 if you have libhid])],
|
||||
[ enable_libhid=no ])],
|
||||
[AC_MSG_WARN([pkg-config not (fully) installed; drivers requiring libhid may not be built])])
|
||||
fi
|
||||
AC_SUBST(LIBHID_LIBS)
|
||||
AC_SUBST(LIBHID_CFLAGS)
|
||||
|
||||
dnl ######################################################################
|
||||
dnl ethlcd support
|
||||
dnl ######################################################################
|
||||
|
||||
@@ -33,6 +33,7 @@ well as the configuration of LCDd.
|
||||
&lirc;
|
||||
&lis;
|
||||
&MD8800;
|
||||
&mdm166a;
|
||||
&ms6931;
|
||||
&mtc_s16209x;
|
||||
&MtxOrb;
|
||||
|
||||
@@ -25,6 +25,7 @@ EXTRA_DIST = bayrad.docbook \
|
||||
lircin.docbook \
|
||||
lis.docbook \
|
||||
MD8800.docbook \
|
||||
mdm166a.docbook \
|
||||
ms6931.docbook \
|
||||
mtc_s16209x.docbook \
|
||||
mtxorb.docbook \
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
<sect1 id="mdm166a-howto">
|
||||
<sect1info>
|
||||
<author>
|
||||
<firstname>Markus</firstname><surname>Dolze</surname>
|
||||
</author>
|
||||
</sect1info>
|
||||
<title>The mdm166a driver</title>
|
||||
|
||||
<para>This section talks about using <application>LCDproc</application> with
|
||||
the Futaba / Targa USB Graphic Vacuum Fluorescent Display (MDM166A; USB
|
||||
VID=0x19c2, PID=0x6a11).</para>
|
||||
|
||||
<para>The MDM166A is a graphical VFD with a 96x16 pixel dot matrix area which
|
||||
is used for 16x2 characters with a 6x8 pixel font. It features several icons,
|
||||
volume level and WLAN strength indicator which are all software controllable
|
||||
using the <function>output</function> function.</para>
|
||||
|
||||
<para>The mdm166a driver builts on top of <literal>libhid</literal> which in
|
||||
turn uses <literal>libusb</literal>.</para>
|
||||
|
||||
<para>The driver was developed by Christoph Rasim
|
||||
(<ulink url="http://www.rasim.net/" />) without any available documentation
|
||||
from the vendor, but with a good protocol description from Thomas Koos
|
||||
(<ulink url="http://www.muetze1.de" />) created by reverse engineering the
|
||||
protocol.</para>
|
||||
|
||||
|
||||
<sect2 id="mdm166a-config">
|
||||
<title>Configuration in LCDd.conf</title>
|
||||
|
||||
<sect3 id="mdm166a-config-section">
|
||||
<title>[mdm166a]</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
<property>Clock</property> =
|
||||
<parameter><replaceable>TYPE</replaceable></parameter>
|
||||
</term>
|
||||
<listitem><para>
|
||||
Show self-running clock after LCDd shutdown. Possible values for
|
||||
<replaceable>TYPE</replaceable> are <literal>no</literal>,
|
||||
<literal>small</literal> and <literal>big</literal>. If not given no clock
|
||||
is shown.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<property>Dimming</property> = ¶meters.yesnodef;
|
||||
</term>
|
||||
<listitem><para>
|
||||
Dimm display, no dimming gives full brightness.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<property>OffDimming</property> = ¶meters.yesnodef;
|
||||
</term>
|
||||
<listitem><para>
|
||||
Dimm display in case LCDd is inactive.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</sect3>
|
||||
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="mdm166a-icons">
|
||||
<title>Using the icons</title>
|
||||
|
||||
<para>The icons, the volume bar and the WLAN indicator supported by the VFD
|
||||
can be controlled by use of the <function>output</function> function.</para>
|
||||
|
||||
<para>The <parameter class="function">on</parameter> parameter is used as a
|
||||
bitmask to control which elements to display. Setting an icon bit to
|
||||
<literal>1</literal> enables the icon, setting the bit to <literal>0</literal>
|
||||
disables an icon. Volume and WLAN strength indicator accept an numeric value
|
||||
in the given bit mask.</para>
|
||||
|
||||
<table id="mdm166a-icons-bitmask">
|
||||
<title>mdm166a_output bitmask</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>bit(s)</entry>
|
||||
<entry>Icon</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>Play</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>Pause</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>Record</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>Message</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>4</entry>
|
||||
<entry>Mail (at-symbol)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>5</entry>
|
||||
<entry>Mute</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>6</entry>
|
||||
<entry>WLAN tower</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>7</entry>
|
||||
<entry>Volume (the word)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>8…12</entry>
|
||||
<entry>Volume (decimal 0…28)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>13…14</entry>
|
||||
<entry>WLAN strength (0…3)</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2 id="mdm166a-device-config">
|
||||
<title>Special device hints</title>
|
||||
|
||||
<para>This display may appear as a <acronym>HID</acronym> device in your
|
||||
system which may prevent <literal>libhid</literal> from being able to open
|
||||
the USB device. In this case you have to create some OS-specific
|
||||
configuration to prevent the <acronym>HID</acronym> driver to take control
|
||||
of this display.</para>
|
||||
|
||||
<sect3 id="mdm166a-device-config-freebsd">
|
||||
<title>Configuring FreeBSD 7.x to exclude this device from uhid</title>
|
||||
|
||||
<para>To make the uhid driver ignore this device you have to apply the
|
||||
following patch to your kernel source and recompile and install your kernel:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
--- sys/dev/usb/usbdevs.orig 2010-11-24 02:06:30.000000000 +0100
|
||||
+++ sys/dev/usb/usbdevs 2010-11-24 07:36:38.000000000 +0100
|
||||
@@ -623,6 +623,7 @@
|
||||
vendor AMIT 0x18c5 AMIT
|
||||
vendor QCOM 0x18e8 Qcom
|
||||
vendor LINKSYS3 0x1915 Linksys
|
||||
+vendor TARGA 0x19c2 Targa Corporation
|
||||
vendor QUALCOMMINC 0x19d2 Qualcomm, Incorporated
|
||||
vendor STELERA 0x1a8d Stelera Wireless
|
||||
vendor DRESDENELEKTRONIK 0x1cf1 dresden elektronik
|
||||
@@ -2343,6 +2344,9 @@
|
||||
/* System TALKS, Inc. */
|
||||
product SYSTEMTALKS SGCX2UL 0x1920 SGC-X2UL
|
||||
|
||||
+/* Targa Corporation */
|
||||
+product TARGA VFD 0x6a11 Targa USB Graphic VFD
|
||||
+
|
||||
/* Tapwave products */
|
||||
product TAPWAVE ZODIAC 0x0100 Zodiac
|
||||
|
||||
--- sys/dev/usb/usb_quirks.c.orig 2010-11-24 02:07:03.000000000 +0100
|
||||
+++ sys/dev/usb/usb_quirks.c 2010-11-24 02:16:30.000000000 +0100
|
||||
@@ -112,6 +112,8 @@
|
||||
ANY, { UQ_HID_IGNORE }},
|
||||
{ USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G,
|
||||
ANY, { UQ_HID_IGNORE }},
|
||||
+ { USB_VENDOR_TARGA, USB_PRODUCT_TARGA_VFD,
|
||||
+ ANY, { UQ_HID_IGNORE }},
|
||||
|
||||
/* Devices which should be ignored by both ukbd and uhid */
|
||||
{ USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A,
|
||||
]]>
|
||||
</programlisting>
|
||||
|
||||
</sect3>
|
||||
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
@@ -40,6 +40,7 @@
|
||||
<!ENTITY lirc SYSTEM "drivers/lircin.docbook">
|
||||
<!ENTITY lis SYSTEM "drivers/lis.docbook">
|
||||
<!ENTITY MD8800 SYSTEM "drivers/MD8800.docbook">
|
||||
<!ENTITY mdm166a SYSTEM "drivers/mdm166a.docbook">
|
||||
<!ENTITY ms6931 SYSTEM "drivers/ms6931.docbook">
|
||||
<!ENTITY mtc_s16209x SYSTEM "drivers/mtc_s16209x.docbook">
|
||||
<!ENTITY MtxOrb SYSTEM "drivers/mtxorb.docbook">
|
||||
|
||||
@@ -21,7 +21,7 @@ AM_LDFLAGS = @LDSHARED@
|
||||
## Keep the lists sorted!
|
||||
|
||||
pkglib_PROGRAMS = @DRIVERS@
|
||||
EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon imonlcd IOWarrior irman joy lb216 lcdm001 lcterm lirc lis MD8800 ms6931 mtc_s16209x MtxOrb mx5000 NoritakeVFD picolcd pyramid sed1330 sed1520 serialPOS serialVFD shuttleVFD stv5730 SureElec svga t6963 text tyan sli ula200 xosd i2500vfd irtrans
|
||||
EXTRA_PROGRAMS = bayrad CFontz CFontz633 CFontzPacket curses CwLnx ea65 EyeboxOne g15 glcdlib glk hd44780 icp_a106 imon imonlcd IOWarrior irman joy lb216 lcdm001 lcterm lirc lis MD8800 mdm166a ms6931 mtc_s16209x MtxOrb mx5000 NoritakeVFD picolcd pyramid sed1330 sed1520 serialPOS serialVFD shuttleVFD stv5730 SureElec svga t6963 text tyan sli ula200 xosd i2500vfd irtrans
|
||||
noinst_LIBRARIES = libLCD.a libbignum.a
|
||||
|
||||
g15_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
|
||||
@@ -29,6 +29,7 @@ hd44780_CFLAGS = @LIBUSB_CFLAGS@ @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
|
||||
i2500vfd_CFLAGS = @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
|
||||
IOWarrior_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
|
||||
lis_CFLAGS = @LIBUSB_CFLAGS@ @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
|
||||
mdm166a_CFLAGS = @LIBHID_CFLAGS@ $(AM_CFLAGS)
|
||||
picolcd_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
|
||||
shuttleVFD_CFLAGS = @LIBUSB_CFLAGS@ $(AM_CFLAGS)
|
||||
ula200_CFLAGS = @LIBFTDI_CFLAGS@ $(AM_CFLAGS)
|
||||
@@ -52,6 +53,7 @@ irman_LDADD = @LIBIRMAN@
|
||||
lcterm_LDADD = libLCD.a
|
||||
lirc_LDADD = @LIBLIRC_CLIENT@
|
||||
lis_LDADD = libLCD.a @LIBFTDI_LIBS@ @LIBUSB_LIBS@ @LIBPTHREAD_LIBS@ libbignum.a
|
||||
mdm166a_LDADD = @LIBHID_LIBS@ libLCD.a
|
||||
mtc_s16209x_LDADD = libLCD.a
|
||||
MtxOrb_LDADD = libLCD.a libbignum.a
|
||||
mx5000_LDADD = @LIBMX5000@
|
||||
@@ -99,6 +101,7 @@ lcterm_SOURCES = lcd.h lcd_lib.h lcterm.c lcterm.h report.h
|
||||
lirc_SOURCES = lcd.h lircin.c lircin.h report.h
|
||||
lis_SOURCES = lcd.h lcd_lib.h lis.h lis.c report.h
|
||||
MD8800_SOURCES = lcd.h lcd_lib.h MD8800.c MD8800.h report.h
|
||||
mdm166a_SOURCES = lcd.h mdm166a.c mdm166a.h i2500vfdfm.c i2500vfdfm.h report.h
|
||||
ms6931_SOURCES = lcd.h lcd_lib.h ms6931.h ms6931.c report.h
|
||||
mtc_s16209x_SOURCES = lcd.h lcd_lib.h mtc_s16209x.c mtc_s16209x.h report.h
|
||||
MtxOrb_SOURCES = lcd.h lcd_lib.h MtxOrb.c MtxOrb.h report.h adv_bignum.h
|
||||
|
||||
@@ -0,0 +1,738 @@
|
||||
/** \file server/drivers/mdm166a.c
|
||||
* LCDd \c mdm166a driver for Futuba MDM166A displays.
|
||||
*
|
||||
* The 96x16 pixel dot matrix area is used for 2x16 characters with a
|
||||
* 6x8 pixel font. The icons on the display are supported by using the
|
||||
* output-function.
|
||||
*
|
||||
* The display features a self-running clock mode, which can be
|
||||
* activated in the config file and will be shown on LCDproc shutdown.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* (C) 2010 Christoph Rasim (christoph@rasim.net)
|
||||
*
|
||||
* Code here is basend on i2500vfd.c:
|
||||
* (C) 2003,2007 Intra2net AG
|
||||
*
|
||||
* i2500vfdfm.c is used for the font, no need for another copy of it.
|
||||
* The HD44780 font in i2500vfdfm.c was taken from Michael Reinelt /
|
||||
* lcd4linux and is (C) 2000 by him.
|
||||
*
|
||||
* This driver is released under the GPL. See file COPYING in this
|
||||
* package for further details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <hid.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "mdm166a.h"
|
||||
#include "i2500vfdfm.h"
|
||||
#include "report.h"
|
||||
|
||||
/*
|
||||
* The display itself stores eight pixels in one byte We waste a little
|
||||
* memory as we store one pixel per byte as we want to keep the drawing code
|
||||
* simple. Take a look at mdm166a_flush for the conversion.
|
||||
*/
|
||||
|
||||
#define MDM166A_XSIZE 96
|
||||
#define MDM166A_YSIZE 16
|
||||
#define MDM166A_SCREENSIZE MDM166A_XSIZE*MDM166A_YSIZE
|
||||
#define MDM166A_PACKEDSIZE 96*2
|
||||
|
||||
#define WIDTH 16
|
||||
#define HEIGHT 2
|
||||
#define CELLWIDTH 6
|
||||
#define CELLHEIGHT 8
|
||||
|
||||
#define DEFAULT_CLOCK "no"
|
||||
|
||||
#define CMD_PREFIX 0x1b /**< Command prefix, indicates a command follows */
|
||||
#define CMD_SETCLOCK 0x00 /**< Send current time to display */
|
||||
#define CMD_SETSYMBOL 0x30 /**< Enable or disable a symbol */
|
||||
#define CMD_SETDIMM 0x40 /**< Set the dimming level of the display */
|
||||
#define CMD_RESET 0x50 /**< Reset all configuration data to default and clear */
|
||||
#define CMD_SETRAM 0x60 /**< Set the actual graphics RAM offset for next data write */
|
||||
#define CMD_SETPIXEL 0x70 /**< Write pixel data to RAM of the display */
|
||||
|
||||
|
||||
/** private data for the \c mdm166a driver */
|
||||
typedef struct mdm166a_private_data {
|
||||
HIDInterface *hid; /**< Pointer to HID interface */
|
||||
int showClock; /**< What clock to show on close */
|
||||
bool dimm; /**< Brightness level */
|
||||
bool offDimm; /**< Brightness level on close */
|
||||
unsigned char *framebuf; /**< Pointer to internal framebuffer */
|
||||
int changed; /**< Indicator for framebuffer changes */
|
||||
int last_output; /**< Icon states after last update */
|
||||
char info[255]; /**< Pointer to driver description */
|
||||
} PrivateData;
|
||||
|
||||
/* Vars for the server core */
|
||||
MODULE_EXPORT char *api_version = API_VERSION;
|
||||
MODULE_EXPORT int stay_in_foreground = 0;
|
||||
MODULE_EXPORT int supports_multiple = 0;
|
||||
MODULE_EXPORT char *symbol_prefix = "mdm166a_";
|
||||
|
||||
/**
|
||||
* Helper function for clock (conversion to BCD)
|
||||
* \param x int_value
|
||||
* \return BCD_value
|
||||
*/
|
||||
inline byte
|
||||
toBCD(int x)
|
||||
{
|
||||
return (byte) (((x) / 10 * 16) + ((x) % 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws char z from fontmap to the framebuffer at position
|
||||
* x,y. These are zero-based textmode positions.
|
||||
* The Fontmap is stored in rows while the framebuffer is stored
|
||||
* in columns, so we need a little conversion.
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param z Character that gets written.
|
||||
*/
|
||||
void
|
||||
drawchar2fb(Driver *drvthis, int x, int y, unsigned char z)
|
||||
{
|
||||
int font_x, font_y;
|
||||
PrivateData *p = drvthis->private_data;
|
||||
|
||||
if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT)
|
||||
return;
|
||||
|
||||
x++;
|
||||
|
||||
for (font_y = 0; font_y < 8; font_y++) {
|
||||
for (font_x = 5; font_x > -1; font_x--) {
|
||||
if ((i2500vfd_fontmap[z][font_y] & 1 << font_x) == 1 << font_x)
|
||||
p->framebuf[x * 6 - 1 - font_x + (y * 8 + font_y) * MDM166A_XSIZE] = 1;
|
||||
else
|
||||
p->framebuf[x * 6 - 1 - font_x + (y * 8 + font_y) * MDM166A_XSIZE] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
p->changed = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the driver.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \retval 0 Success.
|
||||
* \retval <0 Error.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
mdm166a_init(Driver *drvthis)
|
||||
{
|
||||
char clock[256] = DEFAULT_CLOCK;
|
||||
PrivateData *p;
|
||||
int const PATH_OUT[1] = {0xff7f0004};
|
||||
HIDInterfaceMatcher matcher = {0x19c2, 0x6a11, NULL, NULL, 0};
|
||||
hid_return ret;
|
||||
char Cmd[5];
|
||||
|
||||
/* Allocate and store private data */
|
||||
p = (PrivateData *) calloc(1, sizeof(PrivateData));
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
if (drvthis->store_private_ptr(drvthis, p))
|
||||
return -1;
|
||||
strcpy(p->info, "Targa USB Graphic Vacuum Fluorescent Display (mdm166a) driver v0.1 : 19c2:6a11");
|
||||
|
||||
/* Get clock setting from config */
|
||||
strncpy(clock, drvthis->config_get_string(drvthis->name, "Clock", 0, DEFAULT_CLOCK), sizeof(clock));
|
||||
clock[sizeof(clock) - 1] = '\0';
|
||||
p->showClock = 0;
|
||||
if (strcmp(clock, "small") == 0)
|
||||
p->showClock = 1;
|
||||
else if (strcmp(clock, "big") == 0)
|
||||
p->showClock = 2;
|
||||
|
||||
/* Get dimming setting from config */
|
||||
p->dimm = drvthis->config_get_bool(drvthis->name, "Dimming", 0, 0);
|
||||
p->offDimm = drvthis->config_get_bool(drvthis->name, "OffDimming", 0, 0);
|
||||
|
||||
/* Silence libhid and libusb */
|
||||
hid_set_debug(HID_DEBUG_NONE);
|
||||
hid_set_debug_stream(0);
|
||||
hid_set_usb_debug(0);
|
||||
|
||||
/*
|
||||
* We use one central error exit point utilizing forward goto below!
|
||||
*/
|
||||
|
||||
/* Init HID device */
|
||||
ret = hid_init();
|
||||
if (ret != HID_RET_SUCCESS) {
|
||||
report(RPT_ERR, "%s: hid_init failed: %s", drvthis->name, hid_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
|
||||
p->hid = hid_new_HIDInterface();
|
||||
if (p->hid == 0) {
|
||||
report(RPT_ERR, "%s: hid_new_HIDInterface() failed, out of memory?", drvthis->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = hid_force_open(p->hid, 0, &matcher, 3);
|
||||
if (ret != HID_RET_SUCCESS) {
|
||||
report(RPT_ERR, "%s: hid_force_open failed: %s", drvthis->name, hid_strerror(ret));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Allocate our framebuffer */
|
||||
p->framebuf = (unsigned char *)malloc(MDM166A_SCREENSIZE + MDM166A_PACKEDSIZE + 1);
|
||||
if (p->framebuf == NULL) {
|
||||
report(RPT_ERR, "%s: unable to allocate framebuffer", drvthis->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Reset and clear display */
|
||||
Cmd[0] = 0x02;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_RESET;
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 3);
|
||||
p->last_output = 0;
|
||||
|
||||
/* Set dimming */
|
||||
Cmd[0] = 0x03;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETDIMM;
|
||||
if (p->dimm)
|
||||
Cmd[3] = 1;
|
||||
else
|
||||
Cmd[3] = 2;
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 4);
|
||||
|
||||
/* Clear internal screen */
|
||||
mdm166a_clear(drvthis);
|
||||
|
||||
report(RPT_DEBUG, "%s: init() done", drvthis->name);
|
||||
return 0;
|
||||
|
||||
/* Central error exit point */
|
||||
error:
|
||||
mdm166a_close(drvthis);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the clock mode and close the driver (do necessary clean-up).
|
||||
* \param drvthis Pointer to driver structure.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_close(Driver *drvthis)
|
||||
{
|
||||
int const PATH_OUT[1] = {0xff7f0004};
|
||||
char Cmd[5];
|
||||
time_t tt; /* clock */
|
||||
struct tm l; /* time */
|
||||
|
||||
PrivateData *p = drvthis->private_data;
|
||||
|
||||
if (p != NULL) {
|
||||
if (p->hid != 0) {
|
||||
/*
|
||||
* XXX: I don't know if it is a good idea to talk to
|
||||
* the display here as this function will be called
|
||||
* on errors during init. p->hid may not be NULL even
|
||||
* if the device could not be open!
|
||||
*/
|
||||
|
||||
/* Set clock */
|
||||
if (p->showClock > 0) {
|
||||
tt = time(NULL);
|
||||
localtime_r(&tt, &l);
|
||||
/* Set time */
|
||||
Cmd[0] = 0x04;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETCLOCK;
|
||||
Cmd[3] = toBCD(l.tm_min);
|
||||
Cmd[4] = toBCD(l.tm_hour);
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 5);
|
||||
/* Show it */
|
||||
Cmd[0] = 0x03;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = p->showClock;
|
||||
Cmd[3] = 0x01; /* 24 hour mode */
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 4);
|
||||
}
|
||||
/* Set dimming */
|
||||
Cmd[0] = 0x03;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETDIMM;
|
||||
if (p->offDimm)
|
||||
Cmd[3] = 1;
|
||||
else
|
||||
Cmd[3] = 2;
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 4);
|
||||
|
||||
hid_close(p->hid);
|
||||
hid_delete_HIDInterface(&p->hid);
|
||||
p->hid = 0;
|
||||
}
|
||||
hid_cleanup();
|
||||
|
||||
if (p->framebuf)
|
||||
free(p->framebuf);
|
||||
|
||||
free(p);
|
||||
}
|
||||
drvthis->store_private_ptr(drvthis, NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the display width in characters.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return Number of characters the display is wide.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
mdm166a_width(Driver *drvthis)
|
||||
{
|
||||
return WIDTH;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the display height in characters.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return Number of characters the display is high.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
mdm166a_height(Driver *drvthis)
|
||||
{
|
||||
return HEIGHT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the width of a character in pixels.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return Number of pixel columns a character cell is wide.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
mdm166a_cellwidth(Driver *drvthis)
|
||||
{
|
||||
return CELLWIDTH;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the height of a character in pixels.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return Number of pixel lines a character cell is high.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
mdm166a_cellheight(Driver *drvthis)
|
||||
{
|
||||
return CELLHEIGHT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the screen.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_clear(Driver *drvthis)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
|
||||
memset(p->framebuf, 0, MDM166A_SCREENSIZE);
|
||||
p->changed = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Flush data on screen to the VFD.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_flush(Driver *drvthis)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int const PATH_OUT[1] = {0xff7f0004};
|
||||
char Cmd[64];
|
||||
int packed_begin = MDM166A_SCREENSIZE;
|
||||
int xpos = 0, ypos = 0, i, j;
|
||||
|
||||
if (!p->changed)
|
||||
return;
|
||||
|
||||
memset(p->framebuf + packed_begin, 0, MDM166A_PACKEDSIZE);
|
||||
|
||||
/* Convert framebuffer */
|
||||
for (xpos = 0; xpos < MDM166A_XSIZE; xpos++)
|
||||
for (ypos = 0; ypos < MDM166A_YSIZE; ypos++)
|
||||
if (p->framebuf[ypos * MDM166A_XSIZE + xpos])
|
||||
p->framebuf[packed_begin + 2 * xpos + (ypos / 8)] |= (1 << (7 - (ypos % 8)));
|
||||
|
||||
/* Write data to display */
|
||||
/* Set position (0,0) */
|
||||
Cmd[0] = 0x03;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETRAM;
|
||||
Cmd[3] = 0;
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 4);
|
||||
|
||||
/* Display accepts max. 64 bytes at a time -> Send 4 x 24 columns */
|
||||
Cmd[0] = 51;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETPIXEL;
|
||||
Cmd[3] = 48;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 24; j++) {
|
||||
Cmd[4 + 2 * j] = p->framebuf[packed_begin + i * 48 + 2 * j];
|
||||
Cmd[5 + 2 * j] = p->framebuf[packed_begin + i * 48 + 2 * j + 1];
|
||||
}
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 52);
|
||||
}
|
||||
|
||||
p->changed = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print a string on the screen at position (x,y).
|
||||
* The upper-left corner is (1,1), the lower-right corner is (p->width, p->height).
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param string String that gets written.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_string(Driver *drvthis, int x, int y, const char string[])
|
||||
{
|
||||
int i;
|
||||
x--; /* Convert 1-based coords to 0-based */
|
||||
y--;
|
||||
|
||||
for (i = 0; string[i]; i++)
|
||||
drawchar2fb(drvthis, x + i, y, string[i]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print a character on the screen at position (x,y).
|
||||
* The upper-left corner is (1,1), the lower-right corner is (p->width, p->height).
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param c Character that gets written.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_chr(Driver *drvthis, int x, int y, char c)
|
||||
{
|
||||
y--; /* Convert 1-based coords to 0-based */
|
||||
x--;
|
||||
drawchar2fb(drvthis, x, y, c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Define a custom character and write it to the VFD.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param n Custom character to define [0 - (p->customchars)].
|
||||
* \param dat Array of 7(=cellheight) bytes, each representing a pixel row
|
||||
* starting from the top to bottom. \n
|
||||
* The bits in each byte represent the pixels where the LSB
|
||||
* (least significant bit) is the rightmost pixel in each pixel row.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_set_char(Driver *drvthis, int n, char *dat)
|
||||
{
|
||||
int row, col;
|
||||
|
||||
if (n < 0 || n > 255)
|
||||
return;
|
||||
if (!dat)
|
||||
return;
|
||||
|
||||
for (row = 0; row < CELLHEIGHT; row++) {
|
||||
int i = 0;
|
||||
|
||||
for (col = 0; col < CELLWIDTH; col++)
|
||||
i = (i << 1) | (dat[(row * CELLWIDTH) + col] > 0);
|
||||
|
||||
i2500vfd_fontmap[n][row] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw a vertical bar bottom-up.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column) of the starting point.
|
||||
* \param y Vertical character position (row) of the starting point.
|
||||
* \param len Number of characters that the bar is high at 100%
|
||||
* \param promille Current height level of the bar in promille.
|
||||
* \param pattern Options (currently unused).
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_vbar(Driver *drvthis, int x, int y, int len, int promille, int pattern)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
unsigned int offset;
|
||||
int i, j, pixels;
|
||||
|
||||
debug(RPT_INFO, "%s: x=%i, y=%i, len=%i, promille=%i, options=%i",
|
||||
__FUNCTION__, x, y, len, promille, pattern);
|
||||
|
||||
x--;
|
||||
/* don't do y-- as we draw bottom up */
|
||||
|
||||
if (x < 0 || y < 1 || x >= WIDTH || y > HEIGHT || len > HEIGHT) {
|
||||
return;
|
||||
}
|
||||
|
||||
offset = x * CELLWIDTH + y * MDM166A_XSIZE * CELLHEIGHT;
|
||||
pixels = len * CELLHEIGHT * promille / 1000;
|
||||
|
||||
for (i = 0; i < pixels; i++) {
|
||||
for (j = 0; j < CELLWIDTH; j++) {
|
||||
p->framebuf[offset + j] = 1;
|
||||
}
|
||||
/* go to next y-line */
|
||||
offset -= MDM166A_XSIZE;
|
||||
}
|
||||
|
||||
p->changed = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw a horizontal bar to the right.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column) of the starting point.
|
||||
* \param y Vertical character position (row) of the starting point.
|
||||
* \param len Number of characters that the bar is long at 100%
|
||||
* \param promille Current length level of the bar in promille.
|
||||
* \param pattern Options (currently unused).
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_hbar(Driver *drvthis, int x, int y, int len, int promille, int pattern)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
unsigned int offset;
|
||||
int i, j, pixels;
|
||||
|
||||
debug(RPT_INFO, "%s: x=%i, y=%i, len=%i, promille=%i, options=%i",
|
||||
__FUNCTION__, x, y, len, promille, pattern);
|
||||
|
||||
x--;
|
||||
y--;
|
||||
|
||||
if (y < 0 || y >= HEIGHT || x < 0 || len < 0 || x + len > WIDTH) {
|
||||
return;
|
||||
}
|
||||
|
||||
offset = 2 + x * CELLWIDTH + y * MDM166A_XSIZE * CELLHEIGHT;
|
||||
|
||||
/* calculate length of bar */
|
||||
pixels = len * CELLWIDTH * promille / 1000;
|
||||
|
||||
for (i = 0; i < CELLHEIGHT - 1; i++) {
|
||||
for (j = 0; j < pixels; j++) {
|
||||
p->framebuf[offset + j] = 1;
|
||||
}
|
||||
/* go to next y-line */
|
||||
offset += MDM166A_XSIZE;
|
||||
}
|
||||
|
||||
p->changed = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Place an icon on the screen.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param x Horizontal character position (column).
|
||||
* \param y Vertical character position (row).
|
||||
* \param icon symbolic value representing the icon.
|
||||
* \retval 0 Icon has been successfully defined/written.
|
||||
* \retval <0 Server core shall define/write the icon.
|
||||
*/
|
||||
MODULE_EXPORT int
|
||||
mdm166a_icon(Driver *drvthis, int x, int y, int icon)
|
||||
{
|
||||
static char heart_open[] = {
|
||||
0, 1, 1, 1, 1, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 1,
|
||||
0, 1, 1, 1, 1, 1};
|
||||
|
||||
static char heart_filled[] = {
|
||||
0, 1, 1, 1, 1, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 0, 1, 0, 1, 0,
|
||||
0, 0, 1, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 0,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 1, 0, 1, 1,
|
||||
0, 1, 1, 1, 1, 1};
|
||||
|
||||
switch (icon) {
|
||||
case ICON_BLOCK_FILLED:
|
||||
mdm166a_chr(drvthis, x, y, 255);
|
||||
break;
|
||||
case ICON_HEART_FILLED:
|
||||
mdm166a_set_char(drvthis, 0, heart_filled);
|
||||
mdm166a_chr(drvthis, x, y, 0);
|
||||
break;
|
||||
case ICON_HEART_OPEN:
|
||||
mdm166a_set_char(drvthis, 0, heart_open);
|
||||
mdm166a_chr(drvthis, x, y, 0);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turn display backlight on or off.
|
||||
* This does not really toggle the backlight, but tries to handle it more
|
||||
* intelligently: It sets the brightness to the value defined for the related
|
||||
* backlight state.
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param on New backlight status.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_backlight(Driver *drvthis, int on)
|
||||
{
|
||||
int const PATH_OUT[1] = {0xff7f0004};
|
||||
char Cmd[5];
|
||||
PrivateData *p = drvthis->private_data;
|
||||
/* Set dimming */
|
||||
Cmd[0] = 0x03;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETDIMM;
|
||||
if ((p->dimm && (on == BACKLIGHT_ON)) || (p->offDimm && (on == BACKLIGHT_OFF)))
|
||||
Cmd[3] = 1;
|
||||
else
|
||||
Cmd[3] = 2;
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Controls the custom icons.
|
||||
*
|
||||
* The bits of the \c on value map to icons as this (a bit set '1' means the
|
||||
* icon is switched on, a bit set '0' means the icon is turned off):
|
||||
* \verbatim
|
||||
* Bit Funktion
|
||||
* 0 Play
|
||||
* 1 Pause
|
||||
* 2 Record
|
||||
* 3 Message
|
||||
* 4 @
|
||||
* 5 Mute
|
||||
* 6 WLAN tower
|
||||
* 7 Volume (the word)
|
||||
* 8..12 Volume level bar (decimal 0..28)
|
||||
* 13..14 WLAN strength (decimal 0..3)
|
||||
* \endverbatim
|
||||
*
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \param on Integer with bits representing LED states.
|
||||
*/
|
||||
MODULE_EXPORT void
|
||||
mdm166a_output(Driver *drvthis, int on)
|
||||
{
|
||||
char const Icon[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x0a};
|
||||
PrivateData *p = drvthis->private_data;
|
||||
int const PATH_OUT[1] = {0xff7f0004};
|
||||
char Cmd[64];
|
||||
int icons_changed = on ^ p->last_output;
|
||||
int i, volume, wlan;
|
||||
|
||||
/*
|
||||
* Icons, volume bar or WLAN indicator are only changed if different
|
||||
* from previous call.
|
||||
*/
|
||||
|
||||
/* Set Icons. */
|
||||
Cmd[0] = 0x04;
|
||||
Cmd[1] = CMD_PREFIX;
|
||||
Cmd[2] = CMD_SETSYMBOL;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (icons_changed & (1 << i)) {
|
||||
Cmd[3] = Icon[i];
|
||||
Cmd[4] = ((on & (1 << i)) < 1) ? 0 : 1;
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 5);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Volume (0..28). Note: Each bar element can individually be set to
|
||||
* one of three states: off, dimmed or fully on.
|
||||
*/
|
||||
volume = (on >> 8) & 0x1F;
|
||||
if (volume != ((p->last_output >> 8) & 0x1F)) {
|
||||
Cmd[0] = 56;
|
||||
for (i = 0; i < 14; i++) {
|
||||
Cmd[i * 4 + 1] = CMD_PREFIX;
|
||||
Cmd[i * 4 + 2] = CMD_SETSYMBOL;
|
||||
Cmd[i * 4 + 3] = 0x0B + i;
|
||||
if (i < (volume / 2))
|
||||
Cmd[i * 4 + 4] = 2;
|
||||
else if (i == (volume / 2))
|
||||
Cmd[i * 4 + 4] = volume % 2;
|
||||
else
|
||||
Cmd[i * 4 + 4] = 0;
|
||||
}
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 57);
|
||||
}
|
||||
|
||||
/* Wlan Strength (0..3) */
|
||||
wlan = (on >> 13) & 0x03;
|
||||
if (wlan != ((p->last_output >> 13) & 0x03)) {
|
||||
Cmd[0] = 12;
|
||||
for (i = 0; i < 3; i++) {
|
||||
Cmd[i * 4 + 1] = CMD_PREFIX;
|
||||
Cmd[i * 4 + 2] = CMD_SETSYMBOL;
|
||||
Cmd[i * 4 + 3] = 0x07 + i;
|
||||
Cmd[i * 4 + 4] = (i < wlan) ? 1 : 0;
|
||||
}
|
||||
hid_set_output_report(p->hid, PATH_OUT, sizeof(PATH_OUT), Cmd, 13);
|
||||
}
|
||||
|
||||
p->last_output = on;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provide general information about the LCD/VFD display/driver.
|
||||
* \param drvthis Pointer to driver structure.
|
||||
* \return Constant string with information.
|
||||
*/
|
||||
MODULE_EXPORT const char *
|
||||
mdm166a_get_info(Driver *drvthis)
|
||||
{
|
||||
PrivateData *p = drvthis->private_data;
|
||||
return p->info;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef MDM166A_H
|
||||
#define MDM166A_H
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
MODULE_EXPORT int mdm166a_init (Driver *drvthis);
|
||||
MODULE_EXPORT void mdm166a_close (Driver *drvthis);
|
||||
MODULE_EXPORT int mdm166a_width (Driver *drvthis);
|
||||
MODULE_EXPORT int mdm166a_height (Driver *drvthis);
|
||||
MODULE_EXPORT int mdm166a_cellwidth (Driver *drvthis);
|
||||
MODULE_EXPORT int mdm166a_cellheight (Driver *drvthis);
|
||||
MODULE_EXPORT void mdm166a_clear (Driver *drvthis);
|
||||
MODULE_EXPORT void mdm166a_flush (Driver *drvthis);
|
||||
MODULE_EXPORT void mdm166a_string (Driver *drvthis, int x, int y, const char string[]);
|
||||
MODULE_EXPORT void mdm166a_chr (Driver *drvthis, int x, int y, char c);
|
||||
|
||||
MODULE_EXPORT void mdm166a_vbar(Driver *drvthis, int x, int y, int len, int promille, int pattern);
|
||||
MODULE_EXPORT void mdm166a_hbar(Driver *drvthis, int x, int y, int len, int promille, int pattern);
|
||||
MODULE_EXPORT int mdm166a_icon (Driver *drvthis, int x, int y, int icon);
|
||||
|
||||
MODULE_EXPORT void mdm166a_set_char (Driver *drvthis, int n, char *dat);
|
||||
MODULE_EXPORT void mdm166a_backlight (Driver *drvthis, int on);
|
||||
MODULE_EXPORT const char * mdm166a_get_info (Driver *drvthis);
|
||||
MODULE_EXPORT void mdm166a_output (Driver *drvthis, int on);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user