update serialVFD driver (Stefan Herdler)

This commit is contained in:
marschap
2006-05-20 14:38:18 +00:00
parent c6a1f841a7
commit 8ba4e54a3b
6 changed files with 511 additions and 665 deletions
+28 -14
View File
@@ -644,30 +644,44 @@ Port=0x378
## Serial VFD driver ## ## Serial VFD driver ##
## Drives various (see below) serial 5x7dot VFD's. ## ## Drives various (see below) serial 5x7dot VFD's. ##
[serialVFD] [serialVFD]
# device where the VFD is. Usual values are /dev/ttyS0 and /dev/ttyS1
# Specifies the displaytype.[default: 0]
# 0 NEC (FIPC8367 based) VFDs.
# 1 KD Rev 2.1.
# 2 Noritake VFDs (*).
# 3 Futaba VFDs
# (* most should work, not testet yet.)
Type=0
# "no" if display connected serial, "yes" if connected parallel. [default: no(=serial)]
use_parallel=no
# Number of Custom-Characters [default: displaytype dependent]
#Custom-Characters=0
# Portaddress where the LPT is. Used in parallelmode only. Usual values are 0x278, 0x378 and 0x3BC
Port=0x378
# Device to use in serial mode. Usual values are /dev/ttyS0 and /dev/ttyS1
Device=/dev/ttyS1 Device=/dev/ttyS1
# Specifies the size of the VFD. # Specifies the size of the VFD.
Size=20x2 Size=20x2
# Specifies the display type [default: 0] # Set the initial brightness [default: 1000; legal: 0 - 1000]
# 0 NEC (FIPC8367 based) VFDs. # (4 steps 0-250, 251-500, 501-750, 751-1000)
# 1 KD Rev 2.1. Brightness=1000
# 2 Noritake VFDs (*). # Set the initial off-brightness [default: 0; legal: 0 - 1000]
# 3 Futaba VFDs (*). # This value is used when the display is normally
# (* most should work, not tested yet.) # switched off in case LCDd is inactive
Type=1 # (4 steps 0-250, 251-500, 501-750, 751-1000)
OffBrightness=0
# Display brightness [default: 255].
# 0 min ... 255 max ... 1000 also max
# (4 steps 0-64, 65-128, 129-192, 193-1000)
Brightness=255
# set the serial port speed [default: 9600; legal: 1200, 2400, 9600, 19200, 115200] # set the serial port speed [default: 9600; legal: 1200, 2400, 9600, 19200, 115200]
Speed=9600 Speed=9600
# enable ISO 8859 1 compatibility [default: yes; legal: yes, no] # enable ISO 8859 1 compatibility [default: yes; legal: yes, no]
ISO_8859_1=yes #ISO_8859_1=yes
+1 -1
View File
@@ -169,7 +169,7 @@ SED1330/SED1335 (aka S1D13300/S1D13305) based graphical displays
122x32 pixel graphic displays based on SED1520 controllers 122x32 pixel graphic displays based on SED1520 controllers
.TP .TP
.B serialVFD .B serialVFD
NEC FIPC8367 based serial VFDs NEC (FIPC8367 based) and FUTABA VFDs
.TP .TP
.B sli .B sli
Wirz SLI driver (unknown) Wirz SLI driver (unknown)
+252 -76
View File
@@ -2,69 +2,116 @@
<title>The serialVFD Driver</title> <title>The serialVFD Driver</title>
<para> <para>
This section talks about using LCDproc with LCD displays that use the This section talks about using LCDproc with VFD character-displays build by NEC, FUTABA and NORITAKE.
serialVFD chipset.
</para> </para>
<sect2 id="serialVFD-connections">
<title>Connections</title> <para>
The serialVFD-driver is working with NEC FIPC8367 based VFDs
and the "KD Rev 2.1" (an ATMEL AT90S.... based FM20X2KB-AB replacement).
It is also known to work on FUTABA VFDs.</para>
<para>
The driver should operate most of NEC, Futaba and Noritake 7x5 dot VFDs with
serial(rs232) and/or parallel interface. See the following table for testing-status.
Feedback is welcome.
The serialVFD-driver should work with all NEC FIPC8367 based VFDs: <table><title>serialVFD: Display Status</title>
NEC FC20X2JA <tgroup cols="5">
NEC FM20X2KB-AB
NEC FC20X1SA-AB/AA
...
Tested only on: NEC FM20X2KB-AB
The driver also works (tested) on "KD Rev 2.1" (an ATMEL AT90S....
based FM20X2KB-AB replacement).
Note: Above char. 128 the FIPC-displays and KD's charactersets
are different.
The driver may work or will be easy to get working on the following
Displays / Controllers (not tested!).
<table>
<tgroup cols="2">
<thead> <thead>
<row> <row>
<entry>Display</entry> <entry>Display</entry>
<entry>Controller</entry> <entry>Controller</entry>
<entry>Serial</entry>
<entry>Parallel</entry>
<entry>Display tested</entry>
<entry>Remark</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry>FUTABA M204SD01AA</entry> <entry>NEC FM20X2KB-AB</entry>
<entry>FUTABA 5P00A016</entry> <entry>NEC FIPC8367</entry>
<entry>Ok</entry>
<entry>Ok</entry>
<entry>Yes</entry>
<entry> </entry>
</row> </row>
<row>
<entry>NEC FC20X2JA</entry>
<entry>NEC FIPC8367</entry>
<entry>(Ok)</entry>
<entry>(Ok)</entry>
<entry>No</entry>
<entry>Same Controller as on FM20X2KB-AB</entry>
</row>
<row>
<entry>NEC FC20X1SA-AB/AA</entry>
<entry>NEC FIPC8367</entry>
<entry>(Ok)</entry>
<entry>(Ok)</entry>
<entry>No</entry>
<entry>Same Controller as on FM20X2KB-AB</entry>
</row>
<row>
<entry>KD Rev 2.1</entry>
<entry>AT90S....
microcontroller</entry>
<entry>Ok</entry>
<entry>Ok</entry>
<entry>Yes</entry>
<entry> </entry>
</row>
<row>
<entry>FUTABA M402SD06GJ</entry>
<entry>?</entry>
<entry>(?)*</entry>
<entry>Ok</entry>
<entry>Yes</entry>
<entry>(* perhaps no compatible baudrate, not tested)
The display has no user-characters set <command>Custom-Characters=0</command>
in <filename>LCDd.conf.</filename></entry>
</row>
<row>
<entry>FUTABA M204SD01AA</entry>
<entry>FUTABA 5P00A016</entry>
<entry>(Ok)</entry>
<entry>(Ok)</entry>
<entry>No</entry>
<entry> </entry>
</row>
<row> <row>
<entry>Noritake CU20026SCPB-T</entry> <entry>Noritake CU20026SCPB-T</entry>
<entry>(microcontroller)</entry> <entry>microcontroller</entry>
<entry>(Ok)</entry>
<entry>(Ok)</entry>
<entry>No</entry>
<entry> </entry>
</row> </row>
<row> <row>
<entry>Noritake CU20045SCPB-T28A</entry> <entry>Noritake CU20045SCPB-T28A</entry>
<entry>?</entry> <entry>?</entry>
<entry>(Ok)</entry>
<entry>(Ok)</entry>
<entry>No</entry>
<entry> </entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
() feature not tested.
... or compatible.
(most Futaba/Noritake 7x5 dot VFDs with serial(rs232) interface
(including serial(rs232)/parallel types))
<para>
Maybe there are little changes in the commands to do to get all
functions to work correctly. But because of the similarity of the
protocols, it wont be much work.
</para> </para>
<para> <para>
If you want to add a new device to the driver add a new section If your display isn't working 100% satisfactorily you can add a new device with modified hardware
to the displaytype-switch-case in the init-function and fill it commands to the driver if you want. To do that you have to add a new section to the display-
with the correct commands for the display. <command>Type=</command>-switch-case in <filename>./server/drivers/serialVFD-displays.c</filename>
(Try which displaytype works best with your display, copy and modify and to write a new "load"function with the correct commands for the display.(Try which display-<command>Type=</command>
it's section that is the easiest way I guess.) works best with your display, copy, rename and modify this function that is the easiest way I guess.)
</para> </para>
<para> <para>
@@ -78,24 +125,25 @@ running. It may take a few minutes until the next full refresh makes
the display show everything correctly. the display show everything correctly.
</para> </para>
<para>
To enable the bignumbers on 2-line displays (only this driver supports
this yet) you have to edit <filename>clients/lcdproc/chrono.c</filename>
before compiling.
In function <function>big_clock_screen</function> you have to replace the
<literal>4</literal> by a <literal>2</literal> in this line:
<code>if (lcd_hgt &lt; 4)</code>
</para>
<sect2 id="serialVFD-connections">
<title>Connecting The Display</title>
<para>The Connections shown have been tested successfully.</para>
<warning><para>Always cross-check with your datasheet, before connecting your display!
Displays of same manufacturer may have different pin assignments!</para></warning>
<para>With this example connections it will be easy to connect displays with different connector
pin-layouts, the pins are commonly named equal in the datasheet.<para>
<sect3 id="serialVFD-serial-connections">
<title>Serial Connections</title>
<para> <para>
This driver uses the serial mode of the displays.
It is NOT possible to connect most of the displays directly to the It is NOT possible to connect most of the displays directly to the
serialport. The signal has to be inverted. I use the following serialport. The signal has to be inverted. I use the following
circuit to do that job. circuit to do that job.
</para> </para>
<figure> <figure>
<title>serialVFD: Connecting the display</title> <title>serialVFD: Serial Inverter</title>
<screen> <screen>
<![CDATA[ <![CDATA[
Computer Display Computer Display
@@ -121,9 +169,9 @@ pin(signal) |
| --->- A* | --->- A*
| E| | | E| |
| | | | | |
5(GND) --------o----------o----o----------------- GND 5(GND) --------o----------o----o--------------o-- GND
|*
Shield ------------------------------------------ Shield ---------------------------------------o
optional optional
*connect near display *connect near display
@@ -131,25 +179,27 @@ optional
</screen> </screen>
</figure> </figure>
The pins on the different displays vary. <para>The pins on the different displays vary.</para>
<para><title>NEC Displays (FM20X2KB-AB):</title></para>
FM20X2KB-AB: <para>CN1:</para>
<screen><![CDATA[
CN1:
Pin 33 &lt;--- RxD Pin 33 &lt;--- RxD
(Testmode: connect pins 25 and 26, then power up) (Testmode: connect pins 25 and 26, then power up)
]]></screen>
CN2: <para>CN2:</para>
<screen><![CDATA[
Pin 1 &lt;--- +5V Pin 1 &lt;--- +5V
Pin 2 &lt;--- GND Pin 2 &lt;--- GND
]]></screen>
<para><title>KD Rev 2.1:</title></para>
KD Rev 2.1: <para>
The blue connector (6pin in a row) (the important one!):
blue connector (6pin in a row) (the important one!): </para>
<screen> <screen>
<![CDATA[ <![CDATA[
-------------------------------- --------------------------------
@@ -165,31 +215,145 @@ blue connector (6pin in a row) (the important one!):
</para> </para>
</tip> </tip>
gray connector (10pin 2 rows): <para>The gray connector (10pin 2 rows):</para>
Do not use. (the ATMEL ISP connector I guess) <screen>
<![CDATA[Do not use. (the ATMEL ISP connector I guess)
The two jumpers next to the gray connector: ]]>
Normally not used. </screen>
<para>The two jumpers next to the gray connector:</para>
<screen>
<![CDATA[Normally not used.
You can activate two different testmodes with them. You can activate two different testmodes with them.
]]>
</screen>
</sect3>
<sect3 id="serialVFD-parallel-connections">
<title>Parallel Connections</title>
<para><title>NEC Displays (FM20X2KB-AB):</title></para>
<para>CN1:</para>
<screen><![CDATA[
parallel Port: Display (NEC):
Pin: Name: Name: Pin:
1 /STROBE -------------- /WR 1
2 D0 -------------- D0 15
3 D1 -------------- D1 13
4 D2 -------------- D2 11
5 D3 -------------- D3 9
6 D4 -------------- D4 7
7 D5 -------------- D5 5
8 D6 -------------- D6 3
9 D7 -------------- D7 1
10 /ACK --o
|
11 BUSY --o----------- BUSY 27
o-- /CS 23
|
18 - 25 GND ------------o-- GND 2,4,6,8,10,12,14,16,18,20,22,24,26,28,20,32,34
|*
Shield -------------------o
optional
*connect near display
]]></screen>
<para>CN2:</para>
<screen><![CDATA[
Pin 1 &lt;--- +5V
Pin 2 &lt;--- GND
]]></screen>
<para><title>FUTABA Displays (M402SD06GJ):</title></para>
<screen><![CDATA[
parallel Port: Display (FUTABA):
Pin: Name: Name: Pin:
1 /STROBE -------------- /WR 1
2 D0 -------------- D0 15
3 D1 -------------- D1 13
4 D2 -------------- D2 11
5 D3 -------------- D3 9
6 D4 -------------- D4 7
7 D5 -------------- D5 5
8 D6 -------------- D6 3
9 D7 -------------- D7 1
10 /ACK --o
|
11 BUSY --o----------- BUSY 20
o-- /SEL 23
|
18 - 25 GND ------------o-- GND 10,12,14
|*
Shield -------------------o
optional
0-- TEST 16
|
+5V -------o-- +5V 2,4,6
*connect near display
]]></screen>
</sect3>
</sect2> </sect2>
<!-- ## Serial VFD driver ## --> <!-- ## Serial VFD driver ## -->
<sect2 id="serialVFD-config"> <sect2 id="serialVFD-config">
<title>Configuration in LCDd.conf</title> <title>Configuration in LCDd.conf</title>
<sect3> <sect3>
<title>[serialVFD]</title> <title>[serialVFD]</title>
<variablelist> <variablelist>
<varlistentry>
<term>
<command>use_parallel=</command>
<arg choice="plain">
<group choice="req">
<arg choice="plain"><literal><emphasis>yes</emphasis></literal></arg>
<arg choice="plain"><literal>no</literal></arg>
</group>
</arg>
</term>
<listitem><para>
"<literal>no</literal>" if display connected serial, "<literal>yes</literal>" if connected parallel [default: <literal>no</literal>(serial)].
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>Port=</command>
<arg choice="plain"><replaceable>PORT</replaceable></arg>
</term>
<listitem><para>
Portaddress where the LPT is. Used in parallelmode only. Usual values are 0x278, 0x378 and 0x3BC [default: <literal>0x278</literal>].
</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<command>Device=</command> <command>Device=</command>
<arg choice="plain"><replaceable>DEVICE</replaceable></arg> <arg choice="plain"><replaceable>DEVICE</replaceable></arg>
</term> </term>
<listitem><para> <listitem><para>
Device where the VFD is. Usual values are <filename>/dev/ttyS0</filename> and <filename>/dev/ttyS1</filename> Device to use in serial mode. Usual values are <filename>/dev/ttyS0</filename> and <filename>/dev/ttyS1</filename>
Default: <filename>/dev/lcd</filename> [default: <filename>/dev/lcd</filename>].
</para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>Custom-Characters=</command>
<arg choice="plain"><replaceable>CUSTOM-CHARACTERS</replaceable></arg>
</term>
<listitem><para>
Number of Custom-Characters [default: Display-<command>Type</command> dependent].
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
@@ -204,7 +368,7 @@ You can activate two different testmodes with them.
</term> </term>
<listitem><para> <listitem><para>
Specifies the size of the VFD. Specifies the size of the VFD.
default: <literal>20x2</literal> [default: <literal>20x2</literal>]
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
@@ -247,7 +411,7 @@ You can activate two different testmodes with them.
</tgroup> </tgroup>
</informaltable> </informaltable>
<note><para> <note><para>
Options 3 and 4 should work, but have not been tested yet. Feedback is welcome. Noritake VFDs have not been tested yet. Feedback is welcome.
</para></note> </para></note>
</listitem> </listitem>
</varlistentry> </varlistentry>
@@ -258,9 +422,21 @@ You can activate two different testmodes with them.
<arg choice="plain"><replaceable>BRIGHTNESS</replaceable></arg> <arg choice="plain"><replaceable>BRIGHTNESS</replaceable></arg>
</term> </term>
<listitem><para> <listitem><para>
Display brightness [default: 255]. Set the initial brightness [default: 1000; legal: 0 - 1000]
0 min ... 255 max ... 1000 also max (4 steps 0-250, 251-500, 501-750, 751-1000)
(4 steps 0-64, 65-128, 129-192, 193-1000) </para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>OffBrightness=</command>
<arg choice="plain"><replaceable>OFFBRIGHTNESS</replaceable></arg>
</term>
<listitem><para>
Set the initial off-brightness [default: 0; legal: 0 - 1000].
This value is used when the display is normally
switched off in case LCDd is inactive.
(4 steps 0-250, 251-500, 501-750, 751-1000)
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
@@ -279,7 +455,7 @@ You can activate two different testmodes with them.
</term> </term>
<listitem><para> <listitem><para>
Set the the baud rate communication with the VFD. Set the the baud rate communication with the VFD.
If not given, it defaults to <literal>9600</literal>. If not given [default <literal>9600</literal>].
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
@@ -294,7 +470,7 @@ You can activate two different testmodes with them.
</arg> </arg>
</term> </term>
<listitem><para> <listitem><para>
Enable ISO-8859-1 compatibility. Ddefault is <literal>yes</literal>. Enable ISO-8859-1 compatibility [default is <literal>yes</literal>].
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
+1 -1
View File
@@ -80,7 +80,7 @@ NoritakeVFD_SOURCES = lcd.h lcd_lib.h NoritakeVFD.c NoritakeVFD.h report.h
pyramid_SOURCES = lcd.h pylcd.c pylcd.h pyramid_SOURCES = lcd.h pylcd.c pylcd.h
sed1330_SOURCES = lcd.h sed1330.h sed1330.c port.h lpt-port.h timing.h report.h sed1330_SOURCES = lcd.h sed1330.h sed1330.c port.h lpt-port.h timing.h report.h
sed1520_SOURCES = lcd.h sed1520.c sed1520.h sed1520fm.c sed1520fm.h port.h report.h sed1520_SOURCES = lcd.h sed1520.c sed1520.h sed1520fm.c sed1520fm.h port.h report.h
serialVFD_SOURCES = lcd.h lcd_lib.h serialVFD.c serialVFD.h report.h adv_bignum.h serialVFD_SOURCES = lcd.h lcd_lib.h serialVFD.c serialVFD.h report.h adv_bignum.h serialVFD_displays.c serialVFD_displays.h serialVFD_io.c serialVFD_io.h
stv5730_SOURCES = lcd.h stv5730.c stv5730.h report.h stv5730_SOURCES = lcd.h stv5730.c stv5730.h report.h
svga_SOURCES = lcd.h svgalib_drv.c svgalib_drv.h report.h svga_SOURCES = lcd.h svgalib_drv.c svgalib_drv.h report.h
t6963_SOURCES = lcd.h lcd_lib.h t6963.c t6963.h t6963_font.h report.h t6963_SOURCES = lcd.h lcd_lib.h t6963.c t6963.h t6963_font.h report.h
+187 -568
View File
@@ -6,7 +6,7 @@
driver. driver.
It may contain parts of other drivers of this package too. It may contain parts of other drivers of this package too.
2006-02-13 Version 0.2: everything should work (not all hardware tested!) 2006-05-16 Version 0.3: everything should work (not all hardware tested!)
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -24,120 +24,9 @@
The serialVFD-driver should work with all NEC FIPC8367 based VFDs: The driver should operate most of NEC, Futaba and Noritake 7x5 dot VFDs with
NEC FC20X2JA serial(rs232) and/or parallel interface. See /docs/lcdproc-user/serialvfd-howto.html
NEC FM20X2KB-AB for further information
NEC FC20X1SA-AB/AA
...
Tested only on: NEC FM20X2KB-AB
The driver also works (tested) on "KD Rev 2.1" (an ATMEL AT90S....
based FM20X2KB-AB replacement).
Note: Above char. 128 the FIPC-displays and KD's charactersets
are different.
The driver may work or will be easy to get working on the following
Displays / Controllers (not tested!).
Display: Controller:
FUTABA M204SD01AA FUTABA 5P00A016
Noritake CU20026SCPB-T (microcontroller)
Noritake CU20045SCPB-T28A ?
... or compatible.
(most Futaba/Noritake 7x5 dot VFDs with serial(rs232) interface
(including serial(rs232)/parallel types))
Maybe there are little changes in the commands to do to get all
functions to work correctly. But because of the similarity of the
protocols, it wont be much work.
If you want to add a new device to the driver add a new section
to the displaytype-switch-case in the init-function and fill it
with the corrrect commands for the display.
(Try wich displaytype works best with your display, copy and modify
it's section that is the easiest way I guess.)
On this page I found pictures and datasheets of the VFD's:
http://www.maltepoeggel.de/html/vfd/index.html
To enable the bignumbers on 2-line displays (only this driver supports
this yet) you have to edit "/clients/lcdproc/chrono.c" before compiling.
In function "big_clock_screen" you have to replace the "4" by a "2" in
this line: "if (lcd_hgt < 4)".
This driver uses the serial mode of the displays.
It is NOT possible to connect most of the displays directly to the
serialport. The signal has to be inverted. I use the following
circuit to do that job.
Computer Display
(signal)
HDD Powerconnector
color(Voltage)
red(+5V) --------------------------------o----- +5V
|
black(GND) --------------------o |
| R
| R 10k
Serial(SUB-D 9Pin female) V* R
pin(signal) |
|
3(TxD) --RRRR--o--o o-----------------o----- RxD
10k | | |
| | C|
| | ----- BC547c (or similar NPN)
R | B| / |
10k R o--|-| |
R | \ |
| --->- A*
| E| |
| | |
5(GND) --------o----------o----o----------------- GND
Shield ------------------------------------------
optional
*connect near display
The pins on the different displays vary.
FM20X2KB-AB:
CN1:
Pin 33 <--- RxD
(Testmode: connect pins 25 & 26 then power up)
CN2:
Pin 1 <--- +5V
Pin 2 ---- GND
KD Rev 2.1:
blue connector (6pin in a row) (the important one!):
--------------------------------
| +5V +5V RxD GND GND GND |
--------------------------------
NOTE: hold the display in that position where you can read
the "KD Rev 2.1" marking normally!
gray connector (10pin 2 rows):
Do not use. (the ATMEL ISP connector I guess)
The two jumpers next to the gray connector:
Normally not used.
You can activate two different testmodes with them.
List of driver entry point: List of driver entry point:
@@ -147,7 +36,7 @@ close Implemented.
width Implemented. width Implemented.
height Implemented. height Implemented.
clear Implemented by space filling no custom char info. clear Implemented by space filling no custom char info.
flush Calling draw_frame only. flush Implemented.
string Implemented. string Implemented.
chr Implemented. chr Implemented.
vbar Implemented. vbar Implemented.
@@ -164,7 +53,7 @@ get_contrast Not implemented, no software control.
set_contrast Not implemented, no software control. set_contrast Not implemented, no software control.
get_brightness Implemented. get_brightness Implemented.
set_brightness Implemented. set_brightness Implemented.
backlight Not implemented, no software control. backlight Implemented.
output Not implemented. output Not implemented.
get_key Not implemented, no keys. get_key Not implemented, no keys.
get_info Implemented. get_info Implemented.
@@ -185,6 +74,7 @@ get_info Implemented.
# include "config.h" # include "config.h"
#endif #endif
#include "lcd.h" #include "lcd.h"
#include "serialVFD.h" #include "serialVFD.h"
@@ -192,41 +82,16 @@ get_info Implemented.
#include "lcd_lib.h" #include "lcd_lib.h"
#include "adv_bignum.h" #include "adv_bignum.h"
#define DEFAULT_OFF_BRIGHTNESS 300
#define DEFAULT_ON_BRIGHTNESS 1000
#define pos1_cursor 4 //moves cursor to top left character. #define pos1_cursor 4 //moves cursor to top left character.
#define mv_cursor 5 //moves cursor to position specified by the next byte. #define mv_cursor 5 //moves cursor to position specified by the next byte.
#define reset 6 //reset #define reset 6 //reset
#define init_cmds 7 //commands needed to initialize the display. #define init_cmds 7 //commands needed to initialize the display.
#define set_user_char 8 //set user character. #define set_user_char 8 //set user character.
#define hor_tab 9 //moves cursor 1 chr right #define hor_tab 9 //moves cursor 1 chr right
#define LPTPORT 0x378
typedef struct driver_private_data {
char device[200];
int fd;
int speed;
/* dimensions */
int width, height;
int cellwidth, cellheight;
/* framebuffer and buffer for old LCD contents */
unsigned char *framebuf;
unsigned char *backingstore;
/* defineable characters */
int ccmode;
int brightness;
int customchars;
int ISO_8859_1;
unsigned int refresh_timer;
unsigned char charmap[128];
int display_type;
char custom_char[31][7]; // used for "KD Rev 2.1" only
char custom_char_changed[32]; // used only if need_refresh==1
int need_refresh; // 1 if displays need refresh after changing custonchars
char hw_cmd[10][4]; // hardwarespecific commands
int usr_chr_dot_assignment[57]; // how to setup usercharacters
unsigned int usr_chr_mapping[31];// where to place the usercharacters (0..30) in the asciicode
int hbar_cc_offset; // character offset of the bars
int vbar_cc_offset; // character offset of the bars
char info[255];
} PrivateData;
/* Vars for the server core */ /* Vars for the server core */
MODULE_EXPORT char *api_version = API_VERSION; MODULE_EXPORT char *api_version = API_VERSION;
@@ -237,8 +102,6 @@ MODULE_EXPORT char *symbol_prefix = "serialVFD_";
/* Internal functions */ /* Internal functions */
static void serialVFD_init_vbar (Driver *drvthis); static void serialVFD_init_vbar (Driver *drvthis);
static void serialVFD_init_hbar (Driver *drvthis); static void serialVFD_init_hbar (Driver *drvthis);
static void serialVFD_draw_frame (Driver *drvthis, unsigned char *dat);
static void serialVFD_put_brightness (Driver *drvthis);
static void serialVFD_put_char (Driver *drvthis, int n); static void serialVFD_put_char (Driver *drvthis, int n);
// Opens com port and sets baud correctly... // Opens com port and sets baud correctly...
@@ -246,8 +109,7 @@ static void serialVFD_put_char (Driver *drvthis, int n);
MODULE_EXPORT int MODULE_EXPORT int
serialVFD_init (Driver *drvthis) serialVFD_init (Driver *drvthis)
{ {
struct termios portset; int tmp, w, h;
int tmp, w, h, brightness;
char size[200] = DEFAULT_SIZE; char size[200] = DEFAULT_SIZE;
PrivateData *p; PrivateData *p;
@@ -265,22 +127,44 @@ serialVFD_init (Driver *drvthis)
p->ccmode = CCMODE_STANDARD; p->ccmode = CCMODE_STANDARD;
p->ISO_8859_1 = 1; p->ISO_8859_1 = 1;
p->refresh_timer = 0; p->refresh_timer = 0;
p->hw_brightness = 0;
debug(RPT_INFO, "%s(%p)", __FUNCTION__, drvthis ); debug(RPT_INFO, "%s(%p)", __FUNCTION__, drvthis );
/* Read config file */ /* Read config file */
p->use_parallel = drvthis->config_get_bool( drvthis->name, "use_parallel", 0, 0 );
if (p->use_parallel){
p->port = drvthis->config_get_int( drvthis->name, "port", 0, LPTPORT );
}
else {
/* Which device should be used */ /* Which device should be used */
strncpy(p->device, drvthis->config_get_string(drvthis->name, "Device", 0, DEFAULT_DEVICE), sizeof(p->device)); strncpy(p->device, drvthis->config_get_string (drvthis->name, "Device", 0, DEFAULT_DEVICE), sizeof(p->device));
p->device[sizeof(p->device)-1] = '\0'; p->device[sizeof(p->device)-1] = '\0';
report(RPT_INFO, "%s: using Device %s", drvthis->name, p->device); report(RPT_INFO, "%s: using Device %s", drvthis->name, p->device);
/* Which speed */
tmp = drvthis->config_get_int (drvthis->name, "Speed", 0, DEFAULT_SPEED);
if ((tmp != 1200) && (tmp != 2400) && (tmp != 9600) && (tmp != 19200) && (tmp != 115200)) {
report(RPT_WARNING, "%s: Speed must be 1200, 2400, 9600, 19200 or 115200. Using default %d.\n",
drvthis->name, DEFAULT_SPEED);
tmp = DEFAULT_SPEED;
}
if (tmp == 1200) p->speed = B1200;
else if (tmp == 2400) p->speed = B2400;
else if (tmp == 9600) p->speed = B9600;
else if (tmp == 19200) p->speed = B19200;
else if (tmp == 115200) p->speed = B115200;
}
// report(RPT_ERR, "%s: Port: %X\n", __FUNCTION__, p->port, strerror (errno));
/* Which size */ /* Which size */
strncpy(size, drvthis->config_get_string(drvthis->name, "Size", 0, DEFAULT_SIZE), sizeof(size)); strncpy(size, drvthis->config_get_string(drvthis->name, "Size", 0, DEFAULT_SIZE), sizeof(size));
size[sizeof(size)-1] = '\0'; size[sizeof(size)-1] = '\0';
if ((sscanf(size, "%dx%d", &w, &h) != 2) if ((sscanf(size, "%dx%d", &w, &h) != 2)
|| (w <= 0) || (w > LCD_MAX_WIDTH) || (w <= 0) || (w > LCD_MAX_WIDTH)
|| (h <= 0) || (h > LCD_MAX_HEIGHT)) { || (h <= 0) || (h > LCD_MAX_HEIGHT)) {
report(RPT_WARNING, "%s: cannot parse Size: %s; using default %s", report(RPT_WARNING, "%s: cannot parse size: %s; using default %s.",
drvthis->name, size, DEFAULT_SIZE); drvthis->name, size, DEFAULT_SIZE);
sscanf(DEFAULT_SIZE, "%dx%d", &w, &h); sscanf(DEFAULT_SIZE, "%dx%d", &w, &h);
} }
@@ -288,14 +172,24 @@ serialVFD_init (Driver *drvthis)
p->height = h; p->height = h;
/* Which backlight brightness */ /* Which backlight brightness */
tmp = drvthis->config_get_int(drvthis->name, "Brightness", 0, DEFAULT_BRIGHTNESS); tmp = drvthis->config_get_int(drvthis->name, "Brightness", 0, DEFAULT_ON_BRIGHTNESS);
debug(RPT_INFO, "%s: Brightness (in config) is '%d'", __FUNCTION__, tmp);
if ((tmp < 0) || (tmp > 1000)) { if ((tmp < 0) || (tmp > 1000)) {
report(RPT_WARNING, "%s: Brightness must be between 0 and 1000; using default %d", report(RPT_WARNING, "%s: Brightness must be between 0 and 1000; using default %d",
drvthis->name, DEFAULT_BRIGHTNESS); drvthis->name, DEFAULT_ON_BRIGHTNESS);
tmp = DEFAULT_BRIGHTNESS; tmp = DEFAULT_ON_BRIGHTNESS;
} }
brightness = tmp; p->on_brightness = tmp;
/* Which backlight-off "brightness" */
tmp = drvthis->config_get_int(drvthis->name, "OffBrightness", 0, DEFAULT_OFF_BRIGHTNESS);
debug(RPT_INFO, "%s: OffBrightness (in config) is '%d'", __FUNCTION__, tmp);
if ((tmp < 0) || (tmp > 1000)) {
report(RPT_WARNING, "%s: OffBrightness must be between 0 and 1000; using default %d",
drvthis->name, DEFAULT_OFF_BRIGHTNESS);
tmp = DEFAULT_OFF_BRIGHTNESS;
}
p->off_brightness = tmp;
/* ISO 8859 1 */ /* ISO 8859 1 */
p->ISO_8859_1 = drvthis->config_get_bool(drvthis->name, "ISO_8859_1", 0, 1); p->ISO_8859_1 = drvthis->config_get_bool(drvthis->name, "ISO_8859_1", 0, 1);
@@ -309,57 +203,29 @@ serialVFD_init (Driver *drvthis)
} }
p->display_type = tmp; p->display_type = tmp;
/* Number of custom characters */
/* Which speed */ tmp = drvthis->config_get_int (drvthis->name, "Custom-Characters", 0, -83);
tmp = drvthis->config_get_int(drvthis->name, "Speed", 0, DEFAULT_SPEED); if ((tmp < 0) || (tmp > 99)) {
if ((tmp != 1200) && (tmp != 2400) && (tmp != 9600) && (tmp != 19200) && (tmp != 115200)) { report(RPT_WARNING, "%s: The number of Custom-Characters must be between 0 and 99. Using default.",
report(RPT_WARNING, "%s: Speed must be 1200, 2400, 9600, 19200 or 115200; using default %d", drvthis->name, 0);
drvthis->name, DEFAULT_SPEED); tmp = -83;
tmp = DEFAULT_SPEED;
} }
if (tmp == 1200) p->speed = B1200; p->customchars = tmp;
else if (tmp == 2400) p->speed = B2400;
else if (tmp == 9600) p->speed = B9600;
else if (tmp == 19200) p->speed = B19200;
else if (tmp == 115200) p->speed = B115200;
// report (RPT_ERR, "%s: Port: %X\n", __FUNCTION__, p->port, strerror (errno));
/* Set up io port correctly, and open it...*/ // Do connection type specific io-port init
debug(RPT_DEBUG, "%s: Opening device: %s", __FUNCTION__, p->device); if (Port_Function[p->use_parallel].init_fkt (drvthis)==-1) {
p->fd = open(p->device, O_RDWR | O_NOCTTY | O_NDELAY); report(RPT_ERR, "%s: unable to initialize io-port.", drvthis->name);
if (p->fd == -1) {
report(RPT_ERR, "%s: open(%s) failed (%s)", drvthis->name, p->device, strerror(errno));
return -1; return -1;
} }
tcgetattr(p->fd, &portset); // setup frame buffer and backing store
// We use RAW mode
#ifdef HAVE_CFMAKERAW
// The easy way
cfmakeraw(&portset);
#else
// The hard way
portset.c_iflag &= ~( IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON );
portset.c_oflag &= ~OPOST;
portset.c_lflag &= ~( ECHO | ECHONL | ICANON | ISIG | IEXTEN );
portset.c_cflag &= ~( CSIZE | PARENB | CRTSCTS );
portset.c_cflag |= CS8 | CREAD | CLOCAL ;
#endif
// Set port speed
cfsetospeed(&portset, p->speed);
cfsetispeed (&portset, B0);
// Do it...
tcsetattr(p->fd, TCSANOW, &portset);
/* make sure the frame buffer is there... */ /* make sure the frame buffer is there... */
p->framebuf = (unsigned char *) malloc(p->width * p->height); p->framebuf = (unsigned char *) malloc(p->width * p->height);
if (p->framebuf == NULL) { if (p->framebuf == NULL) {
report(RPT_ERR, "%s: unable to create framebuffer", drvthis->name); report(RPT_ERR, "%s: unable to create framebuffer.", drvthis->name);
return -1; return -1;
} }
memset(p->framebuf, ' ', p->width * p->height); memset(p->framebuf, ' ', p->width * p->height);
@@ -367,318 +233,85 @@ serialVFD_init (Driver *drvthis)
/* make sure the framebuffer backing store is there... */ /* make sure the framebuffer backing store is there... */
p->backingstore = (unsigned char *) malloc(p->width * p->height); p->backingstore = (unsigned char *) malloc(p->width * p->height);
if (p->backingstore == NULL) { if (p->backingstore == NULL) {
report(RPT_ERR, "%s: unable to create framebuffer backing store", drvthis->name); report(RPT_ERR, "%s: unable to create framebuffer backing store.", drvthis->name);
return -1; return -1;
} }
memset(p->backingstore, ' ', p->width * p->height); memset(p->backingstore, ' ', p->width * p->height);
//setup displayspecific data //setup displayspecific data
switch (p->display_type) { serialVFD_load_display_data(drvthis);
//nec_fipc
case 0: //nec_fipc
p->need_refresh = 0; // 1 if displays need refresh after changing custonchars
p->customchars = 1; // number of customchaaracters the display provides
p->vbar_cc_offset = 5; // character offset of the bars
p->hbar_cc_offset = 12; // character offset of the bars
// hardwarespecific commands: // report (RPT_ERR, "%s: Port: %X\n", drvthis->name, p->port, strerror (errno));
// hw_cmd[Command][data] = {{commandlength , command 1},
// .....
// {commandlength , command N}}
const char hw_cmd_0[10][4]= {{1 ,0x04}, // dark
{1 ,0x03},
{1 ,0x02},
{1 ,0x01}, // bright
{1 ,0x0D}, // pos1
{1 ,0x1B}, // move cursor
{1 ,0x0C}, // reset
{2 ,0x14, 0x11}, // init
{1 ,0x1A}, // set user char
{1 ,0x09}}; // tab
for (tmp = 0; tmp < 10; tmp++)
for (w = 0; w < 4 ;w++)
p->hw_cmd[tmp][w] = hw_cmd_0[tmp][w];
// Translates ISO 8859-1 to display charset.
const unsigned char charmap_0[] = {
/* #128 = 0x80 */
128, 129, 130, 131, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 156, 157, 158, 159,
/* #160 = 0xA0 */
160, '!', 0xF7, 0xF8, '?', '?', 0x7C, 0xF9,
'"', '?', '?', '?', '?', '-', '?', '?',
0x8B, 0xF3, 0x89, 0x8A, 0x27, 0x98, '?', '.',
',', '?', '?', '?', '?', 0x8C, '?', 0xAA,
/* #192 = 0xC0 */
'A', 'A', 'A', 'A', 0xA2, 0xA8, 'A', 'C',
'E', 'E', 'E', 0xB6, 'I', 'I', 'I', 'I',
'D', 0xA9, 'O', 'O', 'O', 'O', 0xA3, 0x8D,
'0', 'U', 'U', 'U', 0xA4, 'Y', 'p', 0x91,
/* #224 = 0xE0 */
'a', 'a', 'a', 'a', 0xA5, 'a', 'a', 'c',
'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
'o', 'n', 'o', 'o', 'o', 'o', 0xA6, 0x8E,
'0', 'u', 'u', 'u', 0xA7, 'y', 'p', 'y'
};
for (tmp = 0; tmp < 128 ; tmp++)
p->charmap[tmp] = charmap_0[tmp];
//{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...}
const int usr_chr_dot_assignment_0[57]={ 7,
1, 2, 3, 4, 5, 0, 0, 0,
6, 7, 8, 9,10, 0, 0, 0,
11,12,13,14,15, 0, 0, 0,
16,17,18,19,20, 0, 0, 0,
21,22,23,24,25, 0, 0, 0,
26,27,28,29,30, 0, 0, 0,
31,32,33,34,35, 0, 0, 0 };
for (tmp = 0; tmp < 57 ;tmp++)
p->usr_chr_dot_assignment[tmp] = usr_chr_dot_assignment_0[tmp];
//Where to place the usercharacters (0..30) in the asciicode.
//Also used to map standardcharacters in the usercharacterspace(0..30)
//(useful for displays with less then 30 usercharacters and predefined bars)
const unsigned int usr_chr_mapping_0[31]=
{0xAF,0,0,0,0,0, 0x5F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0, 0x5F, 0xE1, 0xE3, 0xE4};
for (tmp = 0; tmp < 31; tmp++)
p->usr_chr_mapping[tmp] = usr_chr_mapping_0[tmp];
break;
//KD Rev2.1
case 1: //KD Rev2.1
p->need_refresh=1; // 1 if displays need refresh after changing custonchars
p->customchars=31; // number of customchaaracters the display provides
p->vbar_cc_offset=0; // character offset of the bars
p->hbar_cc_offset=0; // character offset of the bars
// hardwarespecific commands:
// hw_cmd[Command][data] = {{commandlength , command 1},
// .....
// {commandlength , command N}}
const char hw_cmd_1[10][4]= {{1 ,0x04}, // dark
{1 ,0x03},
{1 ,0x02},
{1 ,0x01}, // bright
{1 ,0x0D}, // pos1
{1 ,0x1B}, // move cursor
{1 ,0x0C}, // reset
{2 ,0x14, 0x11}, // init
{1 ,0x1A}, // set user char
{1 ,0x09}}; // tab
for (tmp = 0; tmp < 10; tmp++)
for (w = 0; w < 4; w++)
p->hw_cmd[tmp][w] = hw_cmd_1[tmp][w];
const unsigned char charmap_1[] = {
/* #128 = 0x80 */
128, 129, 130, 131, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 156, 157, 158, 159,
/* #160 = 0xA0 */
160, '!', 0xF7, 0xF8, '?', '?', 0x7C, 0xF9,
'"', '?', '?', '?', '?', '-', '?', '?',
0xA9, 0xBA, '?', '?', 0x27, '?', '?', '.',
',', '?', '?', '?', '?', '?', '?', '?',
/* #192 = 0xC0 */
0xB2, 'A', 'A', 'A', 0xA2, 0xA1, 'A', 'C',
'E', 'E', 0xA8, 0xB6, 0xAB, 0xAA, 0xAC, 0xA9,
'D', 0xAE, 0xB1, 0xB0, 0xBF, 'O', 0xA3, 'x',
0xAF, 0xB7, 0xB6, 0xB8, 0xA4, 'Y', 'p', 0x91,
/* #224 = 0xE0 */
0xD2, 0xC2, 0xC4, 'a', 0xA5, 0xC1, 0xC5, 0xC3,
0xC7, 0xC6, 0xC8, 0xD4, 0xCC, 0xCB, 0xCD, 0xCA,
'o', 0xCF, 0xD1, 0xD0, 0xCE, 'o', 0xA6, 0xBB,
0xD0, 0xD7, 0xD6, 0xD8, 0xA7, 'y', 'p', 'y'
};
for (tmp = 0; tmp < 128; tmp++)
p->charmap[tmp] = charmap_1[tmp];
//{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...}
const int usr_chr_dot_assignment_1[57]={ 7,
1, 2, 3, 4, 5, 0, 0, 0,
6, 7, 8, 9,10, 0, 0, 0,
11,12,13,14,15, 0, 0, 0,
16,17,18,19,20, 0, 0, 0,
21,22,23,24,25, 0, 0, 0,
26,27,28,29,30, 0, 0, 0,
31,32,33,34,35, 0, 0, 0};
for (tmp = 0; tmp < 57; tmp++)
p->usr_chr_dot_assignment[tmp] = usr_chr_dot_assignment_1[tmp];
//Where to place the usercharacters (0..30) in the asciicode.
//Also used to map standardcharacters in the usercharacterspace(0..30)
//(useful for displays with less then 30 usercharacters and predefined bars)
const unsigned int usr_chr_mapping_1[31]=
{0xAF};
for (tmp = 0; tmp < 31; tmp++)
p->usr_chr_mapping[tmp] = usr_chr_mapping_1[tmp];
break;
//Noritake
case 2: //Noritake
p->need_refresh=0; // 1 if displays need refresh after changing custonchars
p->customchars=16; // number of customchaaracters the display provides
p->vbar_cc_offset=0; // character offset of the bars
p->hbar_cc_offset=0; // character offset of the bars
// hardwarespecific commands:
// hw_cmd[Command][data] = {{commandlength , command 1},
// .....
// {commandlength , command N}}
const char hw_cmd_2[10][4]= {{1 ,0x1B, 0x4C, 0x00}, // dark
{1 ,0x1B, 0x4C, 0x50},
{2 ,0x1B, 0x4C, 0x90},
{1 ,0x1B, 0x4C, 0xFF}, // bright
{1 ,0x0C}, // pos1
{2 ,0x1B, 0x48}, // move cursor
{2 ,0x1B, 0x49}, // reset
{2 ,0x14, 0x11}, // init
{2 ,0x1B, 0x43}, // set user char
{1 ,0x09}}; // tab
for (tmp = 0; tmp < 10; tmp++)
for (w = 0; w < 4; w++)
p->hw_cmd[tmp][w] = hw_cmd_2[tmp][w];
// no charmap needed
for (tmp = 128; tmp <= 255; tmp++)
p->charmap[tmp]=tmp;
//{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...}
const int usr_chr_dot_assignment_2[57]={ 5,
1, 2, 3, 4, 5, 6, 7, 8,
9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,
33,34,35, 0, 0, 0, 0, 0};
for (tmp=0; tmp < 57; tmp++)
p->usr_chr_dot_assignment[tmp]=usr_chr_dot_assignment_2[tmp];
//Where to place the usercharacters (0..30) in the asciicode.
//Also used to map standardcharacters in the usercharacterspace(0..30)
//(useful for displays with less then 30 usercharacters and predefined bars)
const unsigned int usr_chr_mapping_2[31]=
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\
0x0F, 0x10, 0x13 , 0x14, 0x1C, 0x1D, 0x1E, 0x1F};
for (tmp=0;tmp < 31 ;tmp++)
p->usr_chr_mapping[tmp]=usr_chr_mapping_2[tmp];
break;
//Futaba
case 3: //Futaba
p->need_refresh=0; // 1 if displays need refresh after changing custonchars
p->customchars=3; // number of customchaaracters the display provides
p->vbar_cc_offset=0x30; // character offset of the bars
p->hbar_cc_offset=0x30; // character offset of the bars
// hardwarespecific commands:
// hw_cmd[Command][data] = {{commandlength , command 1},
// .....
// {commandlength , command N}}
const char hw_cmd_3[10][4]= {{1 ,0x04, 0x20}, // dark
{1 ,0x04, 0x40},
{2 ,0x04, 0x60},
{1 ,0x04, 0xFF}, // bright
{2 ,0x10, 0x00}, // pos1
{1 ,0x10,}, // move cursor
{1 ,0x1F}, // reset
{1 ,0x11}, // init
{1 ,0x03}, // set user char
{1 ,0x09}}; // tab
for (tmp=0;tmp < (10) ;tmp++)
for (w=0;w < (4) ;w++)
p->hw_cmd[tmp][w]=hw_cmd_3[tmp][w];
// Translates ISO 8859-1 to display charset.
const unsigned char charmap_3[] = {
/* #128 = 0x80 */
128, 129, 130, 131, 132, 133, 134, 135,
136, 137, 138, 139, 140, 141, 142, 143,
144, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 156, 157, 158, 159,
/* #160 = 0xA0 */
160, 0xAD, 0x9B, 0x9C, 0xC8, 0x9D, 0x7C, 0xC0,
'"', '?', 0xA6, 0xAE, 0xAA, '-', '?', '?',
0xEF, 0xCA, 0xC6, 0xC7, 0x27, 0xB8, '?', '.',
',', '?', 0xA7, 0xAF, 0xAC, 0xAB, '?', 0xA8,
/* #192 = 0xC0 */
0xD0, 'A', 0xD5, 'A', 0x8E, 0x8F, 0x92, 0x80,
0xD1, 0x90, 0xD6, 0xD3, 'I', 'I', 0xD7, 0xD4,
'D', 0xA5, 'O', 'O', 0xD8, 'O', 0x99, 'x',
'0', 0xD2, 'U', 0xD9, 0x9A, 'Y', 'p', 0xB1,
/* #224 = 0xE0 */
0x85, 0xA0, 0x83, 'a', 0x84, 0x86, 0x91, 0x87,
0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B,
'o', 0xA4, 0x95, 0xA9, 0x93, 'o', 0x94, '/',
'0', 0x97, 0xA3, 0x96, 0x81, 'y', 'p', 0x89
};
for (tmp = 0; tmp < 128; tmp++)
p->charmap[tmp] = charmap_3[tmp];
//{bytes to send, icon bit mapped to bit 0, icon bit mapped to bit 1, ...}
const int usr_chr_dot_assignment_3[57]={ 5,
8, 7, 6, 5, 4, 3, 2, 1,
16,15,14,13,12,11,10, 9,
24,23,22,21,20,19,18,17,
32,31,30,29,28,27,26,25,
0, 0, 0, 0, 0,35,34,33};
for (tmp=0;tmp < 57 ;tmp++)
p->usr_chr_dot_assignment[tmp]=usr_chr_dot_assignment_3[tmp];
//Where to place the usercharacters (0..30) in the asciicode.
//Also used to map standardcharacters in the usercharacterspace(0..30)
//(useful for displays with less then 30 usercharacters and predefined bars)
const unsigned int usr_chr_mapping_3[31]=
{0xCD, 0xCE, 0xCF};
for (tmp = 0; tmp < 31; tmp++)
p->usr_chr_mapping[tmp] = usr_chr_mapping_3[tmp];
break;
}
//initialise display
write(p->fd, &p->hw_cmd[reset][1],p->hw_cmd[reset][0]);
write(p->fd, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]);
serialVFD_set_brightness(drvthis, 1, brightness);
//initialise display
Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[reset][1],p->hw_cmd[reset][0]);
Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]);
serialVFD_backlight(drvthis, 1);
report(RPT_DEBUG, "%s: init() done", drvthis->name); report(RPT_DEBUG, "%s: init() done", drvthis->name);
return 0; return 0;
} }
/*
* Retrieves brightness (in promille)
*/
///////////////////////////////////////////////////////////////// MODULE_EXPORT int
// Changes screen brightness (0 min ... 255 max ... 1000 also max) serialVFD_get_brightness(Driver *drvthis, int state)
// {
MODULE_EXPORT void
serialVFD_set_brightness (Driver *drvthis, int state, int brightness)
{ // set p->brightness
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
if (brightness > 0) { return (state == BACKLIGHT_ON) ? p->on_brightness : p->off_brightness;
if (brightness > 255) }
brightness = 255;
if (p->brightness != brightness) {
p->brightness = brightness; /*
serialVFD_put_brightness(drvthis); * Sets on/off brightness (in promille)
} */
MODULE_EXPORT void
serialVFD_set_brightness(Driver *drvthis, int state, int promille)
{
PrivateData *p = drvthis->private_data;
/* Check it */
if (promille < 0 || promille > 1000)
return;
/* store the software value since there is not get */
if (state == BACKLIGHT_ON) {
p->on_brightness = promille;
}
else {
p->off_brightness = promille;
} }
} }
static void
serialVFD_put_brightness (Driver *drvthis)
{ // set hardware brightness
PrivateData *p = drvthis->private_data;
int realbrightness = (int) (p->brightness / 64);
//(4 steps 0-64, 65-128, 129-192, 193-1000) /*
write(p->fd, &p->hw_cmd[realbrightness][1],\ * Sets the backlight on or off.
p->hw_cmd[realbrightness][0]); * The hardware support any value between 0 and 100.
*/
MODULE_EXPORT void
serialVFD_backlight (Driver *drvthis, int on)
{
PrivateData *p = drvthis->private_data;
int hardware_value = (on == BACKLIGHT_ON)
? p->on_brightness
: p->off_brightness;
// map range [0, 1000] -> [0, 4] that the hardware understands
//(4 steps 0-250, 251-500, 501-750, 751-1000)
hardware_value /= 251;
if(hardware_value != p->hw_brightness){
p->hw_brightness=hardware_value;
Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[p->hw_brightness][1],\
p->hw_cmd[p->hw_brightness][0]);
}
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Draws a vertical bar... // Draws a vertical bar...
// //
@@ -719,7 +352,7 @@ serialVFD_set_char (Driver *drvthis, int n, unsigned char *dat)
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
unsigned int byte, bit; unsigned int byte, bit;
if ((n < 0) || (n > p->customchars-1)) if (n < 0 || n > p->customchars-1)
return; return;
if (!dat) if (!dat)
return; return;
@@ -740,11 +373,6 @@ serialVFD_set_char (Driver *drvthis, int n, unsigned char *dat)
p->custom_char[n][byte] = letter; p->custom_char[n][byte] = letter;
} }
if (p->display_type != 1) //not KD Rev 2.1
serialVFD_put_char(drvthis, n);
if (p->need_refresh == 1)
p->custom_char_changed[n] = 1;
} }
static void static void
@@ -752,10 +380,10 @@ serialVFD_put_char (Driver *drvthis, int n)
{ // put char in display { // put char in display
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
write(p->fd, &p->hw_cmd[set_user_char][1], Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[set_user_char][1],\
p->hw_cmd[set_user_char][0]);// substitute and select Character to overwrite p->hw_cmd[set_user_char][0]);// substitute and select Character to overwrite
write(p->fd, &p->usr_chr_mapping[n], 1); Port_Function[p->use_parallel].write_fkt (drvthis, (char*)&p->usr_chr_mapping[n], 1);
write(p->fd, &p->custom_char[n][0], p->usr_chr_dot_assignment[0]);// overwrite selected Character Port_Function[p->use_parallel].write_fkt (drvthis, &p->custom_char[n][0], p->usr_chr_dot_assignment[0]);// overwrite selected Character
} }
@@ -765,85 +393,95 @@ serialVFD_put_char (Driver *drvthis, int n)
// //
// Input is a character array, sized serialVFD->width*serialVFD->height // Input is a character array, sized serialVFD->width*serialVFD->height
// //
static void MODULE_EXPORT void
serialVFD_draw_frame (Driver *drvthis, unsigned char *dat) serialVFD_flush (Driver *drvthis)
{ {
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
int i, j, last_chr = -10; int i, j, last_chr = -10;
char custom_char_changed[32]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for (i = 0; i < p->customchars; i++) {
for (j = 0; j < p->usr_chr_dot_assignment[0]; j++) {
if (p->custom_char[i][j] != p->custom_char_store[i][j]) {
custom_char_changed[i]=1;
// report (RPT_ERR, "%s: Char: %X %i\n", __FUNCTION__, i, j, strerror (errno));
}
p->custom_char_store[i][j]=p->custom_char[i][j];
}
}
if (!dat)
return;
if (p->refresh_timer > 500) { // Do a full refresh every 500 refreshs. if (p->refresh_timer > 500) { // Do a full refresh every 500 refreshs.
// With this it is possible to switch display on and off while lcdproc is running // With this it is possible to switch display on and off while lcdproc is running
write(p->fd, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]); Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[init_cmds][1],p->hw_cmd[init_cmds][0]);
serialVFD_put_brightness(drvthis); // restore brightness
Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[p->hw_brightness][1],\
p->hw_cmd[p->hw_brightness][0]); // restore brightness
for (i = 0; i < (p->height * p->width); i++) for (i = 0; i < (p->height * p->width); i++)
p->backingstore[i] = '\0'; // clear Backing-store p->backingstore[i]=0; // clear Backing-store
if (p->display_type != 1) {//not KD Rev 2.1 for(i=0;i<p->customchars;i++) // refresh all customcharacters
for (i = 0; i < p->customchars; i++) // refresh all customcharacters custom_char_changed[i]=1;
serialVFD_put_char(drvthis, i);
/* {
write(p->fd, &p->hw_cmd[set_user_char][1],\
p->hw_cmd[set_user_char][0]);// substitute and select character to overwrite
write(p->fd, &p->usr_chr_mapping[i], 1);
write(p->fd, &p->custom_char[(int)dat[i]][0], p->usr_chr_dot_assignment[0]);// overwrite selected Character
}*/
}
p->refresh_timer = 0; p->refresh_timer = 0;
} }
p->refresh_timer++; p->refresh_timer++;
if (p->display_type != 1) { //not KD Rev 2.1
for(i=0;i<p->customchars;i++) // set customcharacters
if(custom_char_changed[i])
serialVFD_put_char (drvthis, i);
}
if(custom_char_changed[p->last_custom])
p->last_custom=-10;
for (i = 0; i < (p->height * p->width); i++) { for (i = 0; i < (p->height * p->width); i++) {
/* Backing-store implementation. If it's already /* Backing-store implementation. If it's already
* on the screen, don't put it there again * on the screen, don't put it there again
*/ */
if (dat[i] != p->backingstore[i] || (dat[i] <=30 && p->custom_char_changed[(int)dat[i]])) if(p->framebuf[i] != p->backingstore[i] || (p->framebuf[i] <=30 && custom_char_changed[(int)p->framebuf[i]])) {
{ if (last_chr < i-1){ // if not last char written cursor has to be moved.
if (last_chr < i-1) { // if not last char written cursor has to be moved. if(last_chr < i-2-p->hw_cmd[mv_cursor][0]) {
if (last_chr < i-2-p->hw_cmd[mv_cursor][0]) { Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[mv_cursor][1],\
write(p->fd, &p->hw_cmd[mv_cursor][1],
p->hw_cmd[mv_cursor][0]); p->hw_cmd[mv_cursor][0]);
write(p->fd, &i, 1); Port_Function[p->use_parallel].write_fkt (drvthis, (char*)&i, 1);
}
else {
for (j = last_chr; j < (i-1); j++) {
write(p->fd, &p->hw_cmd[hor_tab][1], p->hw_cmd[hor_tab][0]);
} }
else {
for (j = last_chr; j < (i-1); j++)
Port_Function[p->use_parallel].write_fkt (drvthis, &p->hw_cmd[hor_tab][1], p->hw_cmd[hor_tab][0]);
} }
} }
if (dat[i] <= 30) {// custom character if(p->framebuf[i] <= 30) { // custom character
if (p->display_type == 1) {// KD Rev 2.1 only if (p->display_type == 1) { // KD Rev 2.1 only
write(p->fd, "\x1A\xDB", 2); // substitute and select character to overwrite(237) if (p->last_custom != p->framebuf[i]){
write(p->fd, &p->custom_char[(int)dat[i]][0], 7);// overwrite selected character Port_Function[p->use_parallel].write_fkt (drvthis, "\x1A\xDB", 2); // substitute and select character to overwrite (237)
write(p->fd, "\xDB", 1); // write character Port_Function[p->use_parallel].write_fkt (drvthis, &p->custom_char[(int)p->framebuf[i]][0], 7);// overwrite selected character
}
Port_Function[p->use_parallel].write_fkt (drvthis, "\xDB", 1); // write character
p->last_custom = p->framebuf[i];
} }
else { // all other displays else { // all other displays
write(p->fd, &p->usr_chr_mapping[(int)dat[i]], 1); Port_Function[p->use_parallel].write_fkt (drvthis, (char*)&p->usr_chr_mapping[(int)p->framebuf[i]], 1);
} }
} }
else if (dat[i] > 127 && (p->ISO_8859_1 != 0)) { // ISO_8859_1 translation for 129 ... 255 else if(p->framebuf[i] > 127 && (p->ISO_8859_1 != 0)) { // ISO_8859_1 translation for 129 ... 255
write(p->fd, &p->charmap[dat[i] + 128], 1); Port_Function[p->use_parallel].write_fkt (drvthis, &p->charmap[p->framebuf[i] - 128], 1);
} }
else { else {
write(p->fd, &dat[i], 1); Port_Function[p->use_parallel].write_fkt (drvthis, &p->framebuf[i], 1);
} }
last_chr = i; last_chr = i;
} }
} }
if (last_chr != -10) { // update backingstore if something changed if (last_chr != -10) // update backingstore if something changed
int i; memcpy(p->backingstore, p->framebuf, p->height * p->width);
memcpy(p->backingstore, dat, p->height * p->width);
for (i = 0; i < p->customchars; i++)
p->custom_char_changed[i] = '\0';
}
} }
@@ -863,6 +501,7 @@ serialVFD_num( Driver * drvthis, int x, int num )
/* /*
* Places an icon on screen * Places an icon on screen
*/ */
@@ -969,6 +608,7 @@ MODULE_EXPORT void
serialVFD_clear (Driver *drvthis) serialVFD_clear (Driver *drvthis)
{ {
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
memset(p->framebuf, ' ', p->width * p->height); memset(p->framebuf, ' ', p->width * p->height);
} }
@@ -1001,17 +641,16 @@ MODULE_EXPORT void
serialVFD_close (Driver *drvthis) serialVFD_close (Driver *drvthis)
{ {
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
if (p != NULL) { if (p != NULL) {
close(p->fd); if (p->fd >= 0)
close(p->fd);
if (p->framebuf) if (p->framebuf)
free(p->framebuf); free(p->framebuf);
if (p->backingstore) if (p->backingstore)
free(p->backingstore); free(p->backingstore);
free(p); free(p);
} }
drvthis->store_private_ptr(drvthis, NULL); drvthis->store_private_ptr(drvthis, NULL);
} }
@@ -1073,16 +712,6 @@ serialVFD_cellheight (Driver *drvthis)
} }
MODULE_EXPORT void
serialVFD_flush (Driver *drvthis)
{
PrivateData *p = drvthis->private_data;
serialVFD_draw_frame(drvthis, p->framebuf);
}
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Prints a character on the lcd display, at position (x,y). The // Prints a character on the lcd display, at position (x,y). The
// upper-left is (1,1), and the lower right should be (20,4). // upper-left is (1,1), and the lower right should be (20,4).
@@ -1091,23 +720,14 @@ MODULE_EXPORT void
serialVFD_chr (Driver *drvthis, int x, int y, char c) serialVFD_chr (Driver *drvthis, int x, int y, char c)
{ {
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
if ((x > p->width) || (y > p->height))
return;
y--; y--;
x--; x--;
p->framebuf[(y * p->width) + x ] = c; p->framebuf[(y * p->width) + x ] = c;
} }
/////////////////////////////////////////////////////////////////
//
// Retrieves brightness
//
MODULE_EXPORT int
serialVFD_get_brightness(Driver *drvthis, int state)
{
PrivateData *p = drvthis->private_data;
return p->brightness;
}
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// provides some info about this driver // provides some info about this driver
@@ -1116,7 +736,6 @@ MODULE_EXPORT const char *
serialVFD_get_info (Driver *drvthis) serialVFD_get_info (Driver *drvthis)
{ {
PrivateData *p = drvthis->private_data; PrivateData *p = drvthis->private_data;
strcpy(p->info, "Driver for many serialVFDs from NEC(all FIPC based), Noritake, Futaba and the \"KD Rev2.1\"VFD."); strcpy(p->info, "Driver for many serialVFDs from NEC(all FIPC based), Noritake, Futaba and the \"KD Rev2.1\"VFD.");
return p->info; return p->info;
} }
+38 -1
View File
@@ -6,7 +6,7 @@
driver. driver.
It may contain parts of other drivers of this package too. It may contain parts of other drivers of this package too.
2006-02-13 Version 0.2: everything should work (not all hardware tested!) 2006-05-16 Version 0.3: everything should work (not all hardware tested!)
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -26,6 +26,8 @@
#define SERIALVFD_H #define SERIALVFD_H
#include "lcd.h" #include "lcd.h"
#include "adv_bignum.h" #include "adv_bignum.h"
#include "serialVFD_displays.h"
#include "serialVFD_io.h"
#define CCMODE_STANDARD 0 /* only char 0 is used for heartbeat */ #define CCMODE_STANDARD 0 /* only char 0 is used for heartbeat */
#define CCMODE_VBAR 1 #define CCMODE_VBAR 1
@@ -63,8 +65,43 @@ MODULE_EXPORT void serialVFD_set_char (Driver *drvthis, int n, unsigned char *da
MODULE_EXPORT int serialVFD_get_brightness (Driver *drvthis, int state); MODULE_EXPORT int serialVFD_get_brightness (Driver *drvthis, int state);
MODULE_EXPORT void serialVFD_set_brightness (Driver *drvthis, int state, int promille); MODULE_EXPORT void serialVFD_set_brightness (Driver *drvthis, int state, int promille);
MODULE_EXPORT void serialVFD_backlight (Driver *drvthis, int on);
MODULE_EXPORT void serialVFD_output (Driver *drvthis, int state); MODULE_EXPORT void serialVFD_output (Driver *drvthis, int state);
MODULE_EXPORT void serialVFD_num (Driver * drvthis, int x, int num); MODULE_EXPORT void serialVFD_num (Driver * drvthis, int x, int num);
MODULE_EXPORT int serialVFD_get_free_chars (Driver *drvthis); MODULE_EXPORT int serialVFD_get_free_chars (Driver *drvthis);
MODULE_EXPORT const char * serialVFD_get_info( Driver *drvthis ); MODULE_EXPORT const char * serialVFD_get_info( Driver *drvthis );
typedef struct driver_private_data {
int use_parallel; // use parallel?
unsigned int port; // Port in parallel mode
char device[200]; // Device in serial mode
int fd;
int speed; // Speed in serial mode
/* dimensions */
int width, height;
int cellwidth, cellheight;
/* framebuffer and buffer for old LCD contents */
unsigned char *framebuf;
unsigned char *backingstore;
/* defineable characters */
int ccmode;
int on_brightness;
int off_brightness;
int hw_brightness;
int customchars;
int ISO_8859_1;
unsigned int refresh_timer;
unsigned char charmap[128];
int display_type; // display type
int last_custom; // last custom character written
char custom_char[31][7]; // stored custom characters
char custom_char_store[31][7]; // custom characters backingstore
char hw_cmd[10][4]; // hardwarespecific commands
int usr_chr_dot_assignment[57]; // how to setup usercharacters
unsigned int usr_chr_mapping[31];// where to place the usercharacters (0..30) in the asciicode
int hbar_cc_offset; // character offset of the bars
int vbar_cc_offset; // character offset of the bars
char info[255];
} PrivateData;
#endif #endif