summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING340
-rw-r--r--HISTORY151
-rw-r--r--Make.config36
-rw-r--r--Makefile41
-rw-r--r--README97
-rw-r--r--docs/DRIVER.framebuffer44
-rw-r--r--docs/DRIVER.gu126x64D-K610A4111
-rw-r--r--docs/DRIVER.gu140x32f126
-rw-r--r--docs/DRIVER.gu256x64-37296
-rw-r--r--docs/DRIVER.gu256x64-3900176
-rw-r--r--docs/DRIVER.hd6183096
-rw-r--r--docs/DRIVER.image36
-rw-r--r--docs/DRIVER.ks0108124
-rw-r--r--docs/DRIVER.noritake800115
-rw-r--r--docs/DRIVER.sed1330223
-rw-r--r--docs/DRIVER.sed152098
-rw-r--r--docs/DRIVER.serdisp61
-rw-r--r--docs/DRIVER.simlcd36
-rw-r--r--docs/DRIVER.t6963c159
-rw-r--r--docs/README.convpic42
-rw-r--r--docs/README.crtfont61
-rw-r--r--docs/README.showpic38
-rw-r--r--docs/README.showtext35
-rw-r--r--glcddrivers/Makefile60
-rw-r--r--glcddrivers/avrctl.c355
-rw-r--r--glcddrivers/avrctl.h58
-rw-r--r--glcddrivers/common.c231
-rw-r--r--glcddrivers/common.h42
-rw-r--r--glcddrivers/config.c286
-rw-r--r--glcddrivers/config.h85
-rw-r--r--glcddrivers/driver.c54
-rw-r--r--glcddrivers/driver.h48
-rw-r--r--glcddrivers/drivers.c117
-rw-r--r--glcddrivers/drivers.h58
-rw-r--r--glcddrivers/framebuffer.c249
-rw-r--r--glcddrivers/framebuffer.h56
-rw-r--r--glcddrivers/g15daemon.c219
-rw-r--r--glcddrivers/g15daemon.h49
-rw-r--r--glcddrivers/gu126x64D-K610A4.c967
-rw-r--r--glcddrivers/gu126x64D-K610A4.h130
-rw-r--r--glcddrivers/gu140x32f.c443
-rw-r--r--glcddrivers/gu140x32f.h73
-rw-r--r--glcddrivers/gu256x64-372.c408
-rw-r--r--glcddrivers/gu256x64-372.h73
-rw-r--r--glcddrivers/gu256x64-3900.c651
-rw-r--r--glcddrivers/gu256x64-3900.h87
-rw-r--r--glcddrivers/hd61830.c391
-rw-r--r--glcddrivers/hd61830.h54
-rw-r--r--glcddrivers/image.c167
-rw-r--r--glcddrivers/image.h50
-rw-r--r--glcddrivers/ks0108.c593
-rw-r--r--glcddrivers/ks0108.h78
-rw-r--r--glcddrivers/network.c267
-rw-r--r--glcddrivers/network.h56
-rw-r--r--glcddrivers/noritake800.c537
-rw-r--r--glcddrivers/noritake800.h92
-rw-r--r--glcddrivers/port.c350
-rw-r--r--glcddrivers/port.h78
-rw-r--r--glcddrivers/sed1330.c630
-rw-r--r--glcddrivers/sed1330.h78
-rw-r--r--glcddrivers/sed1520.c402
-rw-r--r--glcddrivers/sed1520.h72
-rw-r--r--glcddrivers/serdisp.c467
-rw-r--r--glcddrivers/serdisp.h78
-rw-r--r--glcddrivers/simlcd.c183
-rw-r--r--glcddrivers/simlcd.h48
-rw-r--r--glcddrivers/t6963c.c678
-rw-r--r--glcddrivers/t6963c.h76
-rw-r--r--glcdgraphics/Makefile68
-rw-r--r--glcdgraphics/bitmap.c807
-rw-r--r--glcdgraphics/bitmap.h75
-rw-r--r--glcdgraphics/common.c60
-rw-r--r--glcdgraphics/common.h26
-rw-r--r--glcdgraphics/font.c581
-rw-r--r--glcdgraphics/font.h75
-rw-r--r--glcdgraphics/glcd.c277
-rw-r--r--glcdgraphics/glcd.h36
-rw-r--r--glcdgraphics/image.c67
-rw-r--r--glcdgraphics/image.h58
-rw-r--r--glcdgraphics/imagefile.c35
-rw-r--r--glcdgraphics/imagefile.h33
-rw-r--r--glcdgraphics/pbm.c187
-rw-r--r--glcdgraphics/pbm.h34
-rw-r--r--graphlcd.conf528
-rw-r--r--tools/Makefile47
-rw-r--r--tools/convpic/Makefile46
-rw-r--r--tools/convpic/bmp.c375
-rw-r--r--tools/convpic/bmp.h45
-rwxr-xr-xtools/convpic/c_bmp2glcd10
-rwxr-xr-xtools/convpic/c_tif2glcd10
-rwxr-xr-xtools/convpic/convall10
-rw-r--r--tools/convpic/convpic.c279
-rw-r--r--tools/convpic/formats.txt32
-rw-r--r--tools/convpic/tiff.c201
-rw-r--r--tools/convpic/tiff.h42
-rw-r--r--tools/convpic/tuxbox.c280
-rw-r--r--tools/convpic/tuxbox.h44
-rw-r--r--tools/crtfont/Makefile45
-rw-r--r--tools/crtfont/crtfont.c305
-rw-r--r--tools/genfont/Makefile48
-rw-r--r--tools/genfont/genfont.c167
-rw-r--r--tools/lcdtestpattern/Makefile46
-rw-r--r--tools/lcdtestpattern/lcdtestpattern.c260
-rw-r--r--tools/showpic/Makefile46
-rw-r--r--tools/showpic/showpic.c256
-rw-r--r--tools/showtext/Makefile46
-rw-r--r--tools/showtext/showtext.c279
107 files changed, 18432 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..f2aa7a5
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,151 @@
+GraphLCD base package Revision History
+--------------------------------------
+
+2007-02-25: Version 0.1.5
+- added missing include path definition (thanks to Wolfgang Astleitner)
+- replaced unsigned long long with uint64_t
+- added missing includes
+- increased VER_MAJOR for glcdgraphics library as interface changed in an incompatible way (thanks to Tobias Grimm)
+- changed type of fbp (framebuffer pointer) to void*. Compare fbp against MAP_FAILED to test for success of mmap. This should fix a x86_64 compile error.
+- ks0108: clear data lines after display refresh to fix problems with display contrast that occur under some conditions.
+
+
+2007-02-04: Version 0.1.4
+- added missing include of stdint.h in several files
+- added -fPIC compiler option to library Makefiles
+- graphlcd.conf: added missing "Driver=serdisp" in serdisp section (thanks to Jörn Hermann)
+- graphlcd.conf: changed default value for sleep method to gettimeofday
+- glcdgraphics library changes:
+ - Added cBitmap::DrawSlope function that draws a slope of the given type
+ - added class for loading and saving PBM (portable bitmap) files
+ - made loading of GLCD files platform independent (hopefully)
+ - added copy constructor to cBitmap class
+ - removed the friend class stuff from cImage, instead added some functions to set members
+ - new class cImageFile that acts as a base class for image format load/save classes like cGLCDFile or cPBMFile
+ - removed const qualifier from cImage::GetBitmap
+ - added added Invert method to cBitmap
+ - added methods to set font parameter (height, ascent, ...) to cFont class
+ - made loading of FNT files platform independent (hopefully)
+ - return false in cGLCDFile::Open and ::Save when opening of file failed
+ - added trim function to cut leading and trailing spaces from strings
+ - added WrapText method to cFont class
+ - fixed missing last line in cFont::WrapText
+ - fixed WrapText when Height is zero
+ - fixed font loading bug for graphlcd's FNT format
+ - fixed missing addition of spaceBetween in cFont::WrapText that caused too long lines with some fonts
+ - fixed loading of GLCD animations (thanks to Malte Schröder)
+- glcddrivers library changes:
+ - only config.h, driver.h and drivers.h are needed for applications
+ - added driver for g15daemon (thanks to Mike)
+ - added driver for noritake gu126x64D-K610A4 display (thanks to Alexander Rieger)
+ - gu140x32: fix seqfault if fonts.conf missed (thanks to Andreas Brachold)
+ - t6963c: added support for Serial wiring using an industry version with a serial to parallel converter (thanks to Torsten Lang)
+ - avrctl: adapted to changed commands PC -> AVR
+ - avrctl: implemented SetBrightness method
+ - avrctl: changed type of some parameters to SetColData to uint16_t
+ - avrctl: allow sizes below 256x128. Buffer sent to controller is still 256x128.
+ - framebuffer: fixed compiler error on 64bit systems (thanks to Malte Schröder)
+ - serdisp: updated serdisplib driver (thanks to Wolfgang Astleitner)
+ - added simple network driver (not complete) that sends the current display content as and hey string to connected clients
+ - link against libpthread
+ - fixed some default values to be consistent with comments in graphlcd.conf
+- tools changes:
+ - convpic: adapted to changes related to new base class cImageFile
+ - convpic: use classes from glcdgraphics lib for glcd file conversion
+ - convpic: added pbm support
+ - crtfont: use cFont class methods to save in FNT format
+ - genfont: use cFont class methods to load freetype2 supported fonts
+ - genfont: use cFont class methods to save in FNT format
+ - showpic: call SetBrightness method
+ - showpic: changed setting of brightness to use value from config structure
+ - new tool lcdtestpattern to display a test pattern on a LCD (thanks to Alexander Rieger)
+
+
+2006-01-15: Version 0.1.3
+- Added a major.minor.micro version to the libraries starting with 1.0.0
+- Moved usage of DESTDIR from serveral Makefiles to Make.config (thanks to
+ Lucian Muresan).
+- Moved Freetype2 dependency from Make.config to Makefile of libglcdgraphics
+ (thanks to Tobias Grimm).
+- Creating an additional symlink for the library files to be found during
+ making the tools that need them (thanks to Tobias Grimm).
+- Updated serdisplib driver (thanks to Wolfgang Astleitner).
+- KS0108 driver: Added an alternative way of setting the display control lines
+ (same as in old versions). It is selectable through graphlcd configfile
+ parameter "Control".
+- Using default values for width and height in case they are zero, too
+ (thanks to Tobias Grimm).
+- Added cSerialPort class.
+- Added driver for my AVR controlled display.
+
+
+2005-09-17: Version 0.1.2
+- split off drivers from graphlcd plugin to GraphLCD driver library
+ (libglcddrivers)
+- split off graphics and font handling from graphlcd plugin to GraphLCD
+ graphics library (libglcdgraphics)
+- split off tools from graphlcd plugin to GraphLCD base package
+- almost completely rewritten graphics and font handling
+- added configuration file to hold the driver-specific options
+- changed driver interface
+- adopted the tools' code to use the new driver and graphics API
+- glcddrivers: new driver noritake800 for Noritake 800(A) series
+ displays (thanks to Lucian Muresan)
+- glcdgraphics: fixed a NULL-pointer exception in cBitmap::DrawCharacter
+ when skipPixels is equal to width of the character and SubBitmap
+ returns NULL, which was not tested for (thanks to Malte Schröder for
+ reporting this one)
+- glcdgraphics: fixed a wrong return value in cBitmap::DrawCharacter in
+ case skipPixels > 0 which prevented scrolling from working right.
+- now compiles with gcc 2.95 and gcc 3.x
+- added missing #includes
+- new tool showtext: allows showing a text on the LCD, see
+ README.showtext for details.
+- glcddrivers: fixed a too early port release in sed1330 driver (thanks
+ to Matthias Huber)
+- glcddrivers: sed1330: added missing horizontal scrolling
+ initialization. Now, there should be no displaced display any longer.
+ (thanks to Wolfgang Astleitner)
+- glcddrivers: Now serdisplib is loaded dynamically using libdl. So, no
+ INCLUDE_SERDISPLIB define is needed any longer (thanks to Wolfgang
+ Astleitner)
+- glcddrivers: fixed gu256x64-3900 driver: Now sizes other than 256x64
+ should work. (thanks to Detlef Ruge and Ralf Müller)
+- glcdgraphics: fixed a bug in cBitmap::DrawText that prevented scrolling
+ from working.
+- glcdgraphics: fixed a bug in cBitmap::SubBitmap.
+- glcdgraphics: changed the interface of DrawText and DrawCharacter of
+ cBitmap class.
+- glcdgraphics: extended font attributes to better support converted true
+ type fonts. Also changed font file format to support this attributes.
+- glcdgraphics: the lastChange attribute of cImage now is 64 bits wide.
+- crtfont: extended it to support the new font attributes
+- crtfont: changed file format of description files. Now the font
+ attributes are given by its names, p. e. lineheight:20. Look in
+ README.crtfont for details.
+- new tool genfont: allows converting of true type fonts to GraphLCD
+ fonts using freetype2 library. You have to uncomment HAVE_FREETYPE2 in
+ Make.config to use it.
+- added new fonts verdana and verdana bold in sizes 9 to 29 converted by
+ genfont.
+- glcdgraphics: Added additional type casts to std::min calls to make it
+ compile on x86-64 (thanks to Stefan Bergler).
+- glcddrivers: fixed a bug in serdisp.c. When using direct IO the port
+ string was truncated (thanks to Stefan Bergler).
+- glcddrivers: Added method cConfig::GetConfigIndex for getting a
+ configuration by its name (thanks to Lucian Muresan).
+- Added some $(DESTDIR) all over the Makefiles (thanks to Lucian Muresan).
+- glcddrivers: sed1330: Added setting of CS line in 6800 mode (thanks to
+ Wolfgang Astleitner).
+- glcdgraphics: Added FreeType2 support based on patch by Lucian Muresan.
+ - You have to set HAVE_FREETYPE2 in Make.config to enable this
+ - Added some helper functions to GLCD::cFont class
+- glcddrivers: ks0108: Improved timings: Made setting of display control
+ lines like defined in the controller's data sheet. This fixes problems
+ with some display types. Thanks to Matthias Breitbach for providing a
+ LCD of that type.
+- glcddrivers: gu256x64-3900:
+ - Corrected calculation of m_nTimingAdjustCmd.
+ - Added a test for RefreshDisplay config value to prevent a floating
+ point exception to occur when it is set to zero.
+
diff --git a/Make.config b/Make.config
new file mode 100644
index 0000000..cdafd16
--- /dev/null
+++ b/Make.config
@@ -0,0 +1,36 @@
+#
+# User defined Makefile options for graphlcd daemon and tools
+
+### The C compiler and options:
+
+CC = gcc
+CFLAGS = -O2
+
+CXX = g++
+CXXFLAGS = -g -O2 -Wall -Woverloaded-virtual
+#CXXFLAGS = -g -ggdb -O0 -Wall -Woverloaded-virtual
+
+#LDFLAGS = -g -ggdb -O0
+
+LDCONFIG = ldconfig
+
+### The directory environment:
+
+ifndef $(DESTDIR)
+DESTDIR = /usr/local
+endif
+
+BINDIR = $(DESTDIR)/bin
+LIBDIR = $(DESTDIR)/lib
+INCDIR = $(DESTDIR)/include
+MANDIR = $(DESTDIR)/man
+
+### Includes and defines
+
+#INCLUDES += -I
+
+DEFINES += -D_GNU_SOURCE
+
+# comment this variable out if you don't want to use FreeType2 font rendering
+HAVE_FREETYPE2=1
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..cd3f45d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for the GraphLCD driver library, graphics library and tools
+#
+
+PROJECT = graphlcd-base
+VERSION = 0.1.5
+ARCHIVE = $(PROJECT)-$(VERSION)
+PACKAGE = $(ARCHIVE)
+TMPDIR = /tmp
+
+### Targets:
+
+all:
+ @$(MAKE) -C glcdgraphics all
+ @$(MAKE) -C glcddrivers all
+ @$(MAKE) -C tools all
+
+install:
+ @$(MAKE) -C glcdgraphics install
+ @$(MAKE) -C glcddrivers install
+ @$(MAKE) -C tools install
+
+uninstall:
+ @$(MAKE) -C glcdgraphics uninstall
+ @$(MAKE) -C glcddrivers uninstall
+ @$(MAKE) -C tools uninstall
+
+clean:
+ @-rm -f *.tgz
+ @$(MAKE) -C glcdgraphics clean
+ @$(MAKE) -C glcddrivers clean
+ @$(MAKE) -C tools clean
+
+dist: clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tgz --exclude .svn --exclude *.cbp --exclude *.layout -C $(TMPDIR) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tgz
+
diff --git a/README b/README
new file mode 100644
index 0000000..6d85ff1
--- /dev/null
+++ b/README
@@ -0,0 +1,97 @@
+This is the base package of the GraphLCD project. It contains
+ - GraphLCD driver library - libglcddrivers
+ - GraphLCD graphics library - libglcdgraphics
+ - GraphLCD tools (crtfont, convpic, showpic, showtext)
+ - GraphLCD media files (pictures and splash screens in GLCD format, fonts)
+
+written by Andreas Regel (andreas.regel AT powarman.de)
+
+based on the graphlcd plugin for the Video Disc Recorder
+ written by Carsten Siebholz (c.siebholz AT t-online.de)
+ from 0.0.8 on maintained by Andreas Regel (andreas.regel AT powarman.de)
+ gu140x32f driver by Andreas Brachold (vdr04 AT deltab.de)
+ gu256x64-372 driver by Andreas Weinberger (vdr AT smue.org)
+ gu256x64-3xx0 driver by Ralf Mueller (ralf AT bj-ig.de)
+ gu126x64D-K610A4 driver by Alexander Rieger (Alexander.Rieger AT inka.de)
+ image driver by Andreas Regel (andreas.regel AT powarman.de)
+ ks0108 driver by Andreas Weinberger (vdr AT smue.org)
+ sed1330 driver by Roland Praml (praml.roland AT t-online.de)
+ Heinz Gressenberger (heinz.gressenberger AT stmk.gv.at)
+ sed1520 driver by Andreas Weinberger (vdr AT smue.org)
+ framebuffer driver by Stephan Skrodzki (skrodzki AT stevekist.de)
+ serdisplib driver by Wolfgang Astleitner (mrwastl AT users.sourceforge.net)
+ t6963c driver by Andreas Regel (andreas.regel AT powarman.de)
+ noritake800 drider by Lucian Muresan (lucianm AT users.sourceforge.net)
+
+
+Project's homepage: http://graphlcd.berlios.de/
+
+
+See the file COPYING for license information.
+
+
+Description
+-----------
+The GraphLCD base is a project to support graphical LC displays. It is
+mainly used by the graphlcd plugin for the Video Disc Recorder to
+display its information.
+
+The GraphLCD driver library supports the following LCD
+controllers/modules:
+ - Hitachi HD61830
+ - Toshiba T6963
+ - Samsung KS0108
+ - Epson SED1520 (only tested with DIP122 lcd module)
+ - Epson SED1330
+ - Noritake GU140X32F-7806
+ - Noritake GU256X64-372
+ - Noritake GU256X64-3XX0 (serial or parallel)
+ - Noritake GU126x64D-K610A4 displays (parallel)
+ - Noritake 800 series displays
+ - all controllers supported by serdisplib (http://serdisplib.sourceforge.net)
+
+Other controllers might be supported in the future.
+
+Additionally the GraphLCD driver library includes some special drivers:
+ - framebuffer, for devices that are connected to the VGA connector
+ - image, for writing image sequences in PBM (Portable Bit Map) format that
+ show the plugin's output.
+
+
+Installation and Configuration:
+-------------------------------
+1. Unpack the tarball to an arbitrary directory.
+
+ tar xzf graphlcd-base-0.1.2.tgz
+
+2. Configure if you want FreeType2 support by commenting/uncommenting
+ HAVE_FREETYPE2 in Make.config.
+
+3. Compile the libraries and tools.
+
+ make all (from the package's directory)
+
+4. Install the libraries and tools.
+
+ make install (from the package's directory)
+
+5. Edit the configuration file graphlcd.conf to fit your needs.
+
+6. Copy it to the GraphLCD's default configuration search path (/etc).
+
+ cp graphlcd.conf /etc
+
+
+Notes about FreeType2:
+----------------------
+If the HAVE_FREETYPE2 variable is defined, then the new method
+cFont::LoadFT2(..) from the graphics library will load a FreeType2-supported
+font (only TTFs tested so far) and render it into the raster font structure
+that cFont uses normally. The method is also defined if no FT2 support is
+compiled in, only then it will return false afer logging an error message in
+the system log, telling that graphlcd-base has been compiled without FT2
+support. This way, applications using this library (vdrplugin-graphlcd, or the
+wrapper LCDproc "meta-driver" glcdprocdriver for example, can treat this case
+and have a fallback to the glcdraphics-native raster font if FT2 is not
+supported, or the TTF font could not be loaded for some reason.
+
diff --git a/docs/DRIVER.framebuffer b/docs/DRIVER.framebuffer
new file mode 100644
index 0000000..ec1c65e
--- /dev/null
+++ b/docs/DRIVER.framebuffer
@@ -0,0 +1,44 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The Framebuffer driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The Framebuffer driver writes the output to the framebuffer device at
+/dev/fb0.
+
+The driver is optimized for a 640x480x16 framebuffer. To use it, have
+a kernel with a framebuffer device (e.g. vesa fb) and add e.g.
+vga=0311 to the kernel init parameters (e.g. in lilo.conf).
+
+
+Configuration Parameters
+------------------------
+The Framebuffer driver supports the following parameters in config
+file:
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 320 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 240 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Zoom
+ Determines if pixels should be drawn double sized.
+ Possible values: 0, 1
+
diff --git a/docs/DRIVER.gu126x64D-K610A4 b/docs/DRIVER.gu126x64D-K610A4
new file mode 100644
index 0000000..903e21d
--- /dev/null
+++ b/docs/DRIVER.gu126x64D-K610A4
@@ -0,0 +1,111 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The GU126X64-K610A4 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The GU126X64-K610A4 driver supports Noritake GU126X64D-K610A4 VFD
+display.
+
+The VFD is connected to a single PC parallel port.
+
+Wirings
+-------
+The GU126X64-K610A4 driver supports the following connections on a
+parallel port:
+
+
+ printerport LCD other
+ ----------- ---------------- -------
+ 5V (Con1.1) VCC (Power supply 5V)
+ ACK (10) MB (Con1.9) (Module Busy)
+ 0V (Con1.5) GND (Ground)
+
+ GND (18) 0V (Con2.1) (Ground)
+ INIT (16) ENABLE (Con2.2) (ENABLE)
+ D0 (02) PA0 (Con2.3) (DataBit 0)
+ D1 (03) PA1 (Con2.4) (DataBit 1)
+ D2 (04) PA2 (Con2.5) (DataBit 2)
+ D3 (05) PA3 (Con2.6) (DataBit 3)
+ D4 (06) PA4 (Con2.7) (DataBit 4)
+ D5 (07) PA5 (Con2.8) (DataBit 5)
+ D6 (08) PA6 (Con2.9) (DataBit 6)
+ D7 (09) PA7 (Con2.10) (DataBit 7)
+
+The Display is configured to parallel port mode with "Clock Input"
+to "Falling Edge".
+
+================================================================
+
+Configuration Parameters
+------------------------
+The GU126X64-K610A4 driver supports the following parameters in
+config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 256 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 64 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Brightness
+ Sets the brightness of your display's backlight.
+ Possible values: 0 <= x <= 100)
+ Default value: 100
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 0
+
+Debug
+ Prints debugging information of some methods of the driver.
+ (add the values of interest)
+
+ 1: show a log at the start of a refresh
+ 2: show a log at the end of a refresh with timing information
+ 4: show the rows (8 pixel) refreshed
+ 8: show every commands/bytes sent to the display
+ 16: log every unsuccessful waiting for display acknowledge
diff --git a/docs/DRIVER.gu140x32f b/docs/DRIVER.gu140x32f
new file mode 100644
index 0000000..60748cf
--- /dev/null
+++ b/docs/DRIVER.gu140x32f
@@ -0,0 +1,126 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The GU140X32F driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The GU140X32F driver supports Noritake GU140x32-F7806 VFD displays.
+The VFD is operating in its 8 bit-mode connected to a PC's parallel
+port.
+
+
+Wirings
+-------
+The GU140x32F driver supports the following connections on a parallel
+port:
+ - Standard
+ - Windows
+
+Standard wiring:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (01) GND (Ground)
+ VCC (02) VCC (+5VDC 500mA)
+ NC (03)
+ nSTRB (01) RS (04) (Register Select)
+ nAUTO (14) RW (05) (Read/Write)
+ INIT (16) EN (06) (Chip Enable)
+ D0 (02) D0 (07) (Data Bit 0)
+ D1 (03) D1 (08) (Data Bit 1)
+ D2 (04) D2 (09) (Data Bit 2)
+ D3 (05) D3 (10) (Data Bit 3)
+ D4 (06) D4 (11) (Data Bit 4)
+ D5 (07) D5 (12) (Data Bit 5)
+ D6 (08) D6 (13) (Data Bit 6)
+ D7 (09) D7 (14) (Data Bit 7)
+
+Windows wiring:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (01) GND (Ground)
+ VCC (02) VCC (+5VDC 500mA)
+ NC (03)
+ INIT (16) RS (04) (Register Select)
+ nAUTO (14) RW (05) (Read/Write)
+ nSTRB (01) EN (06) (Chip Enable)
+ D0 (02) D0 (07) (Data Bit 0)
+ D1 (03) D1 (08) (Data Bit 1)
+ D2 (04) D2 (09) (Data Bit 2)
+ D3 (05) D3 (10) (Data Bit 3)
+ D4 (06) D4 (11) (Data Bit 4)
+ D5 (07) D5 (12) (Data Bit 5)
+ D6 (08) D6 (13) (Data Bit 6)
+ D7 (09) D7 (14) (Data Bit 7)
+
+Note: The pin numbering may vary with other displays.
+
+
+Configuration Parameters
+------------------------
+The GU140x32F driver supports the following parameters in config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 140 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 32 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Brightness
+ Sets the brightness of your display's backlight.
+ Possible values: 0 <= x <= 100)
+ Default value: 100
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
+Wiring
+ Select the type of wiring your display is connected with.
+ Possible values: 'Standard', 'Windows'
+ Default value: 'Standard'
+
diff --git a/docs/DRIVER.gu256x64-372 b/docs/DRIVER.gu256x64-372
new file mode 100644
index 0000000..b840137
--- /dev/null
+++ b/docs/DRIVER.gu256x64-372
@@ -0,0 +1,96 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The GU256X64-372 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The GU256X64-372 driver supports Noritake GU256x64-372 VFD displays.
+The VFD is operating in its 8 bit-mode connected to a PC's parallel
+port.
+
+
+Wiring
+------
+The GU256x64-372 driver supports the following connection on a parallel
+port:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ D0 (02) D0 (15) (Data Bit 0)
+ D1 (03) D1 (13) (Data Bit 1)
+ D2 (04) D2 (11) (Data Bit 2)
+ D3 (05) D3 (09) (Data Bit 3)
+ D4 (06) D4 (07) (Data Bit 4)
+ D5 (07) D5 (05) (Data Bit 5)
+ D6 (08) D6 (03) (Data Bit 6)
+ D7 (09) D7 (01) (Data Bit 7)
+ INIT (16) nWR (17) (Write)
+ nSEL (17) R/S (19) (Register Select, C/D)
+ GND (18) nRD (21) (Read)
+ GND (18) CSS (23) (Chip Select)
+ GND (18) GND (02) (Ground)
+
+
+Configuration Parameters
+------------------------
+The GU256x64-372 driver supports the following parameters in config
+file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 256 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 64 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Brightness
+ Sets the brightness of your display's backlight.
+ Possible values: 0 <= x <= 100)
+ Default value: 100
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
diff --git a/docs/DRIVER.gu256x64-3900 b/docs/DRIVER.gu256x64-3900
new file mode 100644
index 0000000..44bf4d1
--- /dev/null
+++ b/docs/DRIVER.gu256x64-3900
@@ -0,0 +1,176 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The GU256X64-3900 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The GU256X64-3900 driver supports Noritake GU256X64-3900 VFD displays.
+The VFD is either operating in 8 bit-mode connected to a single PC
+parallel port or in serial mode connected to a single PC serial port.
+
+
+Wirings
+-------
+The GU256X64-3900 driver supports the following connections on a
+parallel port:
+ - Standard
+ - Satyr
+
+Standard wiring:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ D0 (02) DB0 (08) (DataBit 0)
+ D1 (03) DB1 (07) (DataBit 1)
+ D2 (04) DB2 (06) (DataBit 2)
+ D3 (05) DB3 (05) (DataBit 3)
+ D4 (06) DB4 (04) (DataBit 4)
+ D5 (07) DB5 (03) (DataBit 5)
+ D6 (08) DB6 (02) (DataBit 6)
+ D7 (09) DB7 (01) (DataBit 7)
+ ACK (10) RDY (12) (Display Ready)
+ INIT (16) nWR (10) (Write)
+ GND (18) GND (09) GND (Ground)
+ GND (19) GND (11) GND (Ground)
+ GND (20) GND (13) GND (Ground)
+ GND (21) GND (14) GND (Ground)
+ VCC (15) VCC (Power supply 5V)
+ VCC (16) VCC (Power supply 5V)
+
+Satyr Wiring:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ nSTRB (01) nWR (10) (Write)
+ D0 (02) DB0 (08) (DataBit 0)
+ D1 (03) DB1 (07) (DataBit 1)
+ D2 (04) DB2 (06) (DataBit 2)
+ D3 (05) DB3 (05) (DataBit 3)
+ D4 (06) DB4 (04) (DataBit 4)
+ D5 (07) DB5 (03) (DataBit 5)
+ D6 (08) DB6 (02) (DataBit 6)
+ D7 (09) DB7 (01) (DataBit 7)
+ BUSY (11) RDY (12) (Display Ready)
+ GND (18) GND (09) GND (Ground)
+ GND (19) GND (11) GND (Ground)
+ GND (20) GND (13) GND (Ground)
+ GND (21) GND (14) GND (Ground)
+ VCC (15) VCC (Power supply 5V)
+ VCC (16) VCC (Power supply 5V)
+
+Note: The pin numbering may vary with other displays.
+
+
+The GU256X64-3900 driver supports the following connection on a
+serial port:
+
+ serialport LCD other
+ ---------- ---------- ----------
+ DCD (01) DTR (02)
+ RxD (02) TxD (04)
+ TxD (03) RxD (01)
+ DTR (04) DSR (03)
+ GND (05) GND (07) GND (Ground)
+ DSR (06) DTR (02)
+ VCC (06) VCC (Power supply 5V)
+
+Note: The pin numbering may vary with other displays.
+
+On display switches:
+ SW No. Function Default
+ ------ -------- -------
+ 1 Display address select Off
+ 2 Display address select Off
+ 3 Display address select Off
+ 4 Display address select Off
+ 5 Baud rate select Off
+ 6 Command mode select Off switch DMA On/Off
+ 7 Operating mode select Off
+ 8 Protocol Select Off
+
+Serial access to GU256X64C-3xx0 is nearly as fast as normal parallel
+access but doesn't create the high system load of the parallel
+approach. So for me serial access is preferred over normal parallel
+mode. Even better is the DMA parallel mode. For DMA mode you have to
+switch SW6 on the display to ON.
+
+
+Configuration Parameters
+------------------------
+The GU256X64-3900 driver supports the following parameters in config
+file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 256 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 64 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Brightness
+ Sets the brightness of your display's backlight.
+ Possible values: 0 <= x <= 100)
+ Default value: 100
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
+Wiring
+ Select the type of wiring your display is connected with.
+ Possible values: 'Standard', 'Satyr'
+ Default value: 'Standard'
+
+Interface
+ Select the interface your display is connnected to.
+ Possible values: 'Parallel', 'Serial'
+ Default value: 'Parallel'
+
+DMA
+ Enables/disables the usage of the controller's DMA mode which
+ increases writing speed. This only works in parallel interface mode.
+ Possible values: 'yes', 'no'
+ Default value: 'yes'
+
diff --git a/docs/DRIVER.hd61830 b/docs/DRIVER.hd61830
new file mode 100644
index 0000000..8e23420
--- /dev/null
+++ b/docs/DRIVER.hd61830
@@ -0,0 +1,96 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The HD61830 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The HD61830 driver supports LC displays that use the Hitachi HD61830
+controller, connected to the parallel port of your PC.
+
+
+Wirings
+-------
+The HD61830 driver supports the following connection on a parallel
+port:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (18) GND (01) GND (Ground)
+ VDD (02) +5V (V Controller)
+ V0 (03) +5V..-15V (Contrast)
+ INIT (16) RS (04) (Register Select)
+ nAUTO (14) R/W (05) (Read 1/Write 0)
+ nSTRB (01) EN (06) (Enable)
+ D0 (02) D0 (07) (DataBit0)
+ D1 (03) D1 (08) (DataBit1)
+ D2 (04) D2 (09) (DataBit2)
+ D3 (05) D3 (10) (DataBit3)
+ D4 (06) D4 (11) (DataBit4)
+ D5 (07) D5 (12) (DataBit5)
+ D6 (08) D6 (13) (DataBit6)
+ D7 (09) D7 (14) (DataBit7)
+ nCS (15) GND (Chip Select)
+ nRES (16) +5V (Reset)
+ VEE (17) -12V (V LCD)
+ nDO (18) (not connected)
+
+Note: The pin numbering may vary with other displays.
+
+
+Configuration Parameters
+------------------------
+The HD61830 driver supports the following parameters in config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 240 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 128 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
diff --git a/docs/DRIVER.image b/docs/DRIVER.image
new file mode 100644
index 0000000..8da1ffd
--- /dev/null
+++ b/docs/DRIVER.image
@@ -0,0 +1,36 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The Image driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The Image driver writes image sequences in PBM (Portable Bit Map)
+format showing the output that you would normally see on a LCD e.g.
+from the graphlcd plugin.
+
+
+Configuration Parameters
+------------------------
+The Image driver supports the following parameters in config file:
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 240 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 128 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
diff --git a/docs/DRIVER.ks0108 b/docs/DRIVER.ks0108
new file mode 100644
index 0000000..24d5a17
--- /dev/null
+++ b/docs/DRIVER.ks0108
@@ -0,0 +1,124 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The KS0108 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The KS0108 driver supports LC displays that use the Samsung KS0108
+controller, connected to the parallel port of your PC.
+
+
+Wirings
+-------
+The KS0108 driver supports the following connection on a parallel
+port:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (18) GND (01) GND (Ground)
+ Vdd (02) +5V
+ Vo (03) (LCD Contrast In)
+ nSEL (17) R/S (04) (Register Select)
+ R/W (05) GND (Read/Write)
+ nSTRB (01) EN (06) (Enable)
+ D0 (02) D0 (07) (DataBit0)
+ D1 (03) D1 (08) (DataBit1)
+ D2 (04) D2 (09) (DataBit2)
+ D3 (05) D3 (10) (DataBit3)
+ D4 (06) D4 (11) (DataBit4)
+ D5 (07) D5 (12) (DataBit5)
+ D6 (08) D6 (13) (DataBit6)
+ D7 (09) D7 (14) (DataBit7)
+ nAUTO (14) CS1 (15) (ChipSelect Controller 1)
+ INIT (16) CS2 (16) (ChipSelect Controller 2)
+ RESET (17) +5V (Controller Reset)
+ Vout (18) (Contrast Out)
+ LED+ (19) +4V (Backlight)
+ LED- (20) GND (Backlight GND)
+
+Note: The pin numbering may vary with other displays.
+
+If you want to connect a 192x64 or 256x64 display (with 3 or 4
+ChipSelects) or two 128x64 displays, you must add a binary decoder for
+the ChipSelect lines. The mode ist auto-selected based on the width and
+height parameters.
+
+ nAUTO (14)
+ | INIT (16)
+ Vdd | | GND GND
+ | | | | |
+ 16 15 14 13 12 11 10 09
+ --------------------------------
+ | |
+ > |
+ | |
+ --------------------------------
+ 01 02 03 04 05 06 07 08
+ | | | | |
+ CS1 | | | GND
+ CS2 | CS4 (CS2 second LCD)
+ CS3 (CS1 second LCD)
+
+
+Configuration Parameters
+------------------------
+The KS0108 driver supports the following parameters in config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 128 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 64 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
+Control
+ Sets the variant of setting the display control lines.
+ Possible values: 0, 1
+ Default value: 1
+
diff --git a/docs/DRIVER.noritake800 b/docs/DRIVER.noritake800
new file mode 100644
index 0000000..1962900
--- /dev/null
+++ b/docs/DRIVER.noritake800
@@ -0,0 +1,115 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The Noritake 800(A) series driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The Noritake 800(A) series driver supports following VFD displays manufactured
+by Noritake (see http://www.noritake-itron.com on the link "Medium 0.6 dot"):
+ - GU128X64-800A;
+ - GU256X32-800A;
+ - GU128X32-800A;
+ - GU160X16-800A;
+ - GU160X32-800A;
+ - GU192X16-800A.
+
+Wirings
+-------
+The VFD should be connected to a parallel port of the PC
+
+printer port LIQUIDMP3 MZ other?
+---------------------------------------------
+
+Data lines D0...D7 connected straight in all wirings
+
+Strobe (1) CSS (23) WR (17)
+Linefeed (14) RD (21) RD (21)
+Init (16) WR (17) CSS (23)
+Select (17) C/D (19) C/D (19)
+
+Printer port pins 18 .... 25 connected to GND;
+VFD *ONLY EVEN* pins 2 .... 24 connected to GND
+Everything else is *NOT CONNECTED*
+
+Further wirings might work and then for sure very easyly added to the code.
+Just extend N800LptWiringMask(..) accordingly. This method is called in a
+loop over all 16 (4 wires for now) possibilities in the constructor, so the
+results are cached for the actual writes to the LPT control port, very
+similar to ReverseBits(..) for data.
+
+The driver should also work for "WIRING_MZ", just report if there are
+problems.
+Feel free to add support for "Parallel #2 Interface" or "Serial interface".
+
+Tested only on my own GU128x64-800(A) so far, just with the default 8-bit
+mode parallel wiring (referred as WIRING_LIQUIDMP3 or "0" in this code, or
+"Parallel #1 Interface"in the data sheet). I can't actually test the other
+wiring (as the display is already mounted in my HTPC, and the cable soldered),
+or even the other modes from the datasheet ("Parallel #2 Interface", or
+"Serial interface"), for those, my display lacks the necessary jumpers on
+it's PCB)
+
+
+Configuration Parameters
+------------------------
+The Noritake 800(A) series driver supports the following parameters in config
+file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 256 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 64 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Brightness
+ Sets the brightness of your display's backlight.
+ Possible values: 0 <= x <= 100)
+ Default value: 100
+
+AdjustTiming ---> not used in this driver (if there are problems, please report)
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay ---> not used in this driver (if there are problems, please report)
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
diff --git a/docs/DRIVER.sed1330 b/docs/DRIVER.sed1330
new file mode 100644
index 0000000..2346cc5
--- /dev/null
+++ b/docs/DRIVER.sed1330
@@ -0,0 +1,223 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The SED1330 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The SED1330 driver supports LC displays that use the Epson
+SED1330/1335 controller, connected to the parallel port of your PC.
+
+
+Wirings
+-------
+The SED1330 driver supports the following connections on a parallel
+port:
+ - Original
+ - PowerLCD
+ - LCDProc
+ - Tweakers
+ - YASEDW
+
+Original wiring:
+
+ printerport LCD other function in 6800 mode 8080 mode
+ ----------- ---------- ---------- --------------------- -----------
+ /RES (01) +5V /RES (Reset)
+ nSTRB (01) /RD (02) E (Enable) /RD (Read)
+ nAUTO (14) /WR (03) R/W (Read/Write) /WR (Write)
+ SEL2 (04) GND Interface select 2
+ SEL1 (05) +5V Interface select 1
+ nSEL (17) /CS (06) GND /CS (Chip select)
+ INIT (16) A0 (07) A0 (Access type)
+ D0 (02) DB0 (08) D0 (Data bus 0)
+ D1 (03) DB1 (09) D1 (Data bus 1)
+ D2 (04) DB2 (10) D2 (Data bus 2)
+ D3 (05) DB3 (11) D3 (Data bus 3)
+ D4 (06) DB4 (12) D4 (Data bus 4)
+ D5 (07) DB5 (13) D5 (Data bus 5)
+ D6 (08) DB6 (14) D6 (Data bus 6)
+ D7 (09) DB7 (15) D7 (Data bus 7)
+ VDD (16) +5V VDD (Logic power supply)
+ GND (18) VSS (17) GND GND (Ground)
+ V0 (18) +5V..-22V V0 (LCD contrast)
+ VLC (19) -22V VEE (LCD drive voltage)
+ FGND (20) GND Frame ground
+
+PowerLCD wiring:
+
+ printerport LCD other function in 6800 mode 8080 mode
+ ----------- ---------- ---------- --------------------- -----------
+ /RES (01) +5V /RES (Reset)
+ nSEL (17) /RD (02) E (Enable) /RD (Read)
+ nSTRB (01) /WR (03) R/W (Read/Write) /WR (Write)
+ SEL2 (04) GND Interface select 2
+ SEL1 (05) +5V Interface select 1
+ nAUTO (14) /CS (06) GND /CS (Chip select)
+ INIT (16) A0 (07) A0 (Access type)
+ D0 (02) DB0 (08) D0 (Data bus 0)
+ D1 (03) DB1 (09) D1 (Data bus 1)
+ D2 (04) DB2 (10) D2 (Data bus 2)
+ D3 (05) DB3 (11) D3 (Data bus 3)
+ D4 (06) DB4 (12) D4 (Data bus 4)
+ D5 (07) DB5 (13) D5 (Data bus 5)
+ D6 (08) DB6 (14) D6 (Data bus 6)
+ D7 (09) DB7 (15) D7 (Data bus 7)
+ VDD (16) +5V VDD (Logic power supply)
+ GND (18) VSS (17) GND GND (Ground)
+ V0 (18) +5V..-22V V0 (LCD contrast)
+ VLC (19) -22V VEE (LCD drive voltage)
+ FGND (20) GND Frame ground
+
+LCDProc wiring:
+
+ printerport LCD other function in 6800 mode 8080 mode
+ ----------- ---------- ---------- --------------------- -----------
+ /RES (01) +5V /RES (Reset)
+ INIT (16) /RD (02) E (Enable) /RD (Read)
+ nAUTO (14) /WR (03) R/W (Read/Write) /WR (Write)
+ SEL2 (04) GND Interface select 2
+ SEL1 (05) +5V Interface select 1
+ nSTRB (01) /CS (06) GND /CS (Chip select)
+ nSEL (17) A0 (07) A0 (Access type)
+ D0 (02) DB0 (08) D0 (Data bus 0)
+ D1 (03) DB1 (09) D1 (Data bus 1)
+ D2 (04) DB2 (10) D2 (Data bus 2)
+ D3 (05) DB3 (11) D3 (Data bus 3)
+ D4 (06) DB4 (12) D4 (Data bus 4)
+ D5 (07) DB5 (13) D5 (Data bus 5)
+ D6 (08) DB6 (14) D6 (Data bus 6)
+ D7 (09) DB7 (15) D7 (Data bus 7)
+ VDD (16) +5V VDD (Logic power supply)
+ GND (18) VSS (17) GND GND (Ground)
+ V0 (18) +5V..-22V V0 (LCD contrast)
+ VLC (19) -22V VEE (LCD drive voltage)
+ FGND (20) GND Frame ground
+
+Tweakers wiring:
+
+ printerport LCD other function in 6800 mode 8080 mode
+ ----------- ---------- ---------- --------------------- -----------
+ /RES (01) +5V /RES (Reset)
+ nAUTO (14) /RD (02) E (Enable) /RD (Read)
+ INIT (16) /WR (03) R/W (Read/Write) /WR (Write)
+ SEL2 (04) GND Interface select 2
+ SEL1 (05) +5V Interface select 1
+ nSTRB (01) /CS (06) GND /CS (Chip select)
+ nSEL (17) A0 (07) A0 (Access type)
+ D0 (02) DB0 (08) D0 (Data bus 0)
+ D1 (03) DB1 (09) D1 (Data bus 1)
+ D2 (04) DB2 (10) D2 (Data bus 2)
+ D3 (05) DB3 (11) D3 (Data bus 3)
+ D4 (06) DB4 (12) D4 (Data bus 4)
+ D5 (07) DB5 (13) D5 (Data bus 5)
+ D6 (08) DB6 (14) D6 (Data bus 6)
+ D7 (09) DB7 (15) D7 (Data bus 7)
+ VDD (16) +5V VDD (Logic power supply)
+ GND (18) VSS (17) GND GND (Ground)
+ V0 (18) +5V..-22V V0 (LCD contrast)
+ VLC (19) -22V VEE (LCD drive voltage)
+ FGND (20) GND Frame ground
+
+YASEDW wiring:
+
+ printerport LCD other function in 6800 mode 8080 mode
+ ----------- ---------- ---------- --------------------- -----------
+ /RES (01) +5V /RES (Reset)
+ INIT (16) /RD (02) E (Enable) /RD (Read)
+ nSTRB (01) /WR (03) R/W (Read/Write) /WR (Write)
+ SEL2 (04) GND Interface select 2
+ SEL1 (05) +5V Interface select 1
+ nSEL (17) /CS (06) GND /CS (Chip select)
+ nAUTO (14) A0 (07) A0 (Access type)
+ D0 (02) DB0 (08) D0 (Data bus 0)
+ D1 (03) DB1 (09) D1 (Data bus 1)
+ D2 (04) DB2 (10) D2 (Data bus 2)
+ D3 (05) DB3 (11) D3 (Data bus 3)
+ D4 (06) DB4 (12) D4 (Data bus 4)
+ D5 (07) DB5 (13) D5 (Data bus 5)
+ D6 (08) DB6 (14) D6 (Data bus 6)
+ D7 (09) DB7 (15) D7 (Data bus 7)
+ VDD (16) +5V VDD (Logic power supply)
+ GND (18) VSS (17) GND GND (Ground)
+ V0 (18) +5V..-22V V0 (LCD contrast)
+ VLC (19) -22V VEE (LCD drive voltage)
+ FGND (20) GND Frame ground
+
+Note: The pin numbering may vary with other displays.
+
+SEL1 on GND selects 8080 mode, SEL1 on VDD selects 6800 mode.
+
+
+Configuration Parameters
+------------------------
+The SED1330 driver supports the following parameters in config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 320 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 240 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
+Wiring
+ Select the type of wiring your display is connected with.
+ Possible values: 'Original', 'PowerLCD', 'LCDProc', 'Tweakers',
+ 'YASEDW'
+ Default value: 'Original'
+
+OscillatorFrequency
+ Select the frequency the oscillator on your LCD board uses in kHz.
+ Possible values: 1000 <= x <= 15000)
+ Default value: 9600
+
+Interface
+ Select the interface mode your display is connected with.
+ Possible values: '6800', '8080'
+ Default value: '6800'
+
diff --git a/docs/DRIVER.sed1520 b/docs/DRIVER.sed1520
new file mode 100644
index 0000000..c4084fc
--- /dev/null
+++ b/docs/DRIVER.sed1520
@@ -0,0 +1,98 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The SED1520 driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The SED1520 driver supports LC displays that use the Epson SED1520
+controller, connected to the parallel port of your PC.
+
+
+Wirings
+-------
+The SED1520 driver supports the following connection on a parallel
+port:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (18) GND (01) GND (Ground)
+ Vdd (02) +5V
+ Vo (03) (LCD Contrast In -4V)
+ nSEL (17) R/S (04) (Register Select)
+ R/W (05) GND (Read/Write)
+ nSTRB (01) EN1 (06) (Enable Left)
+ D0 (02) D0 (07) (DataBit0)
+ D1 (03) D1 (08) (DataBit1)
+ D2 (04) D2 (09) (DataBit2)
+ D3 (05) D3 (10) (DataBit3)
+ D4 (06) D4 (11) (DataBit4)
+ D5 (07) D5 (12) (DataBit5)
+ D6 (08) D6 (13) (DataBit6)
+ D7 (09) D7 (14) (DataBit7)
+ INIT (16) EN2 (15) (Enable Right)
+ RESET (16) +5V (Controller Reset)
+ LED+ (17) +4V/150mA (Backlight with 6,4Ohm Resistor to +5V)
+ nAUTO (14) LED- (18) GND (Backlight GND [via BS170])
+
+ See also http://www.usblcd.de/lcdproc/sed1520-dip.php4 ...
+
+Note: The pin numbering may vary with other displays.
+
+
+Configuration Parameters
+------------------------
+The SED1520 driver supports the following parameters in config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 120 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 32 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+AdjustTiming
+ To get a timing that is as accurate as possible, the drivers measure
+ the time for port commands (see: benchmark in syslog). You might
+ decrease or increase the time to wait after port commands with this
+ parameter. Normally, there is no need to change this parameter.
+ Possible values: -50 <= x <= 50
+ Default value: 0
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
diff --git a/docs/DRIVER.serdisp b/docs/DRIVER.serdisp
new file mode 100644
index 0000000..c3113d9
--- /dev/null
+++ b/docs/DRIVER.serdisp
@@ -0,0 +1,61 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The serdisp driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The serdisp driver supports LC displays that are supported by
+serdisplib (http://serdisplib.sourceforge.net).
+
+
+Configuration Parameters
+------------------------
+The serdisp driver supports the following parameters in config file:
+
+Controller
+ Select the controller your LCD uses named like in serdisplib.
+ Possible values: See README in serdisplib package
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value according to the selected controller is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value according to the selected controller is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Contrast
+ Sets the contrast of your display.
+ Possible values: 0 <= x <= 10
+ Default value: 5
+
+Backlight
+ Switches the backlight of your display on and off.
+ Possible values: 'yes', 'no'
+ Default value: 'yes'
+
diff --git a/docs/DRIVER.simlcd b/docs/DRIVER.simlcd
new file mode 100644
index 0000000..90bc3cb
--- /dev/null
+++ b/docs/DRIVER.simlcd
@@ -0,0 +1,36 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The SimLCD driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The Image driver writes a file including the output that you would
+normally see on a LCD e.g. from the graphlcd plugin. You can use the
+SimLCD tool to view this file.
+
+
+Configuration Parameters
+------------------------
+The SimLCD driver supports the following parameters in config file:
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 240 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 128 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
diff --git a/docs/DRIVER.t6963c b/docs/DRIVER.t6963c
new file mode 100644
index 0000000..33c61e6
--- /dev/null
+++ b/docs/DRIVER.t6963c
@@ -0,0 +1,159 @@
+---------------------------------------------------------------------
+GraphLCD driver library
+
+The T6963C driver
+---------------------------------------------------------------------
+
+Description
+-----------
+The T6963C driver supports LC displays that use the Toshiba T6963C
+controller, connected to the parallel port of your PC.
+
+
+Wirings
+-------
+The T6963C driver supports the following connections on a parallel
+port:
+ - Standard (used by LCDproc)
+ - Windows (used by many windows programs)
+
+Standard wiring:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (18) GND (01) GND (Ground)
+ nSTRB (01) WR (06) (Write)
+ nAUTO (14) CE (15) (Chip Enable)
+ INIT (16) C/D (04) (Command/Data)
+ nSEL (17) RD (05) (Read)
+ D0 (02) D0 (07) (Data Bit 0)
+ D1 (03) D1 (08) (Data Bit 1)
+ D2 (04) D2 (09) (Data Bit 2)
+ D3 (05) D3 (10) (Data Bit 3)
+ D4 (06) D4 (11) (Data Bit 4)
+ D5 (07) D5 (12) (Data Bit 5)
+ D6 (08) D6 (13) (Data Bit 6)
+ D7 (09) D7 (14) (Data Bit 7)
+
+Windows wiring:
+
+ printerport LCD other
+ ----------- ---------- ----------
+ GND (18) GND (01) GND (Ground)
+ nSTRB (01) CE (15) (Chip Enable)
+ nAUTO (14) RD (05) (Read)
+ INIT (16) WR (06) (Write)
+ nSEL (17) C/D (04) (Command/Data)
+ D0 (02) D0 (07) (Data Bit 0)
+ D1 (03) D1 (08) (Data Bit 1)
+ D2 (04) D2 (09) (Data Bit 2)
+ D3 (05) D3 (10) (Data Bit 3)
+ D4 (06) D4 (11) (Data Bit 4)
+ D5 (07) D5 (12) (Data Bit 5)
+ D6 (08) D6 (13) (Data Bit 6)
+ D7 (09) D7 (14) (Data Bit 7)
+
+Serial wiring using a industry version with a serial to parallel
+converter:
+
+ printerport LCD
+ ----------- ----------
+ nAuto (14) nCE (03)
+ nSTRB (01) nSCK (07)
+ INIT (16) nC/D (08)
+ INIT (16) nSDAT (08)
+ GND (25) GND (01)
+
+
+Note: The pin numbering may vary with other displays.
+
+The LCD must operate in the 6x8 or 8x8 font mode. Usually, there is a
+pin to choose 6x8 or 8x8 font mode.
+
+There are Displays that have a pin to select the number of characters
+per line. In that case, you have to select (width (in pixels) / 6) or
+(width (in pixels) / 8) characters per line.
+
+Attention: You have to tie these pins to +5V or GND. Don't leave them
+open circuit or you will get unpredictable results.
+
+Because the T6963 driver reads the status of the display, it might be
+neccessary to enable the bidirectional mode in the BIOS and to enable
+bidirectional mode in the Linux kernel:
+ <*> Parallel port support
+ <*> PC-style hardware
+ [*] IEEE 1284 transfer modes
+
+
+Configuration Parameters
+------------------------
+The T6963C driver supports the following parameters in config file:
+
+Device
+ Instead of using the direct output via port address (see Port), you
+ can use the parport device (/dev/parportX). The advantage over the
+ direct output via port address is that this works for non-root users
+ also. But it's a little bit slower. The modules ppdev.o, parport.o
+ and parport_pc.o must be loaded or compiled into the kernel.
+
+Port
+ Sets the port address of the parallel port. If this parameter is not
+ given, 0x378 is used. To use this direct output, the program that
+ uses the driver library has to be started with user 'root'.
+
+Width
+ Sets the horizontal size of the display. If this parameter is not
+ given, a default value of 240 pixels is used.
+
+Height
+ Sets the vertical size of the display. If this parameter is not
+ given, a default value of 128 pixels is used.
+
+UpsideDown
+ Rotates the display output by 180 degrees. This might be useful, if
+ the LCD is mounted upside-down.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+Invert
+ Inverts the display.
+ Possible values: 'yes', 'no'
+ Default value: 'no'
+
+RefreshDisplay
+ Normally, most of the drivers do not update the whole display, but
+ only the areas that have changed since last update. So it might be,
+ that some faulty pixels would stay a longer time. To avoid this, the
+ plugin makes a complete refresh from time to time. This parameter
+ defines how often a complete refresh will be done.
+ e.g.: A value of 5 means, that the plugin will make a complete
+ refresh on every 5th update.
+ A value of 0 completely disables complete refreshs.
+ Possible values: 0 <= x <= 50
+ Default value: 5
+
+Wiring
+ Select the type of wiring your display is connected with.
+ Possible values: 'Standard', 'Windows'
+ Default value: 'Standard'
+
+FontSelect
+ Select the font width your display uses for text mode. In most cases
+ this is selectable through one of the pins of your LCD board
+ Possible values: '6', '8'
+ Default value: '6'
+
+AutoMode
+ Enables or disables the usage of T6963C's auto mode which doubles
+ writing speed when enabled.
+ Possible values: 'yes', 'no'
+ Default value: 'yes'
+
+StatusCheck
+ Enables or disables the usage of T6963C's status check. When using a
+ shielded cable for connecting your display, the disabling may be
+ possible. This results in doubling the speed of writing data to the
+ LCD.
+ Possible values: 'yes', 'no'
+ Default value: 'yes'
+
diff --git a/docs/README.convpic b/docs/README.convpic
new file mode 100644
index 0000000..5ab1d45
--- /dev/null
+++ b/docs/README.convpic
@@ -0,0 +1,42 @@
+This is the README of the crtfont tool, which is part of the GraphLCD
+base package.
+
+written by Carsten Siebholz <c.siebholz AT t-online.de>
+ Andreas Brachold <vdr04 AT deltab de>
+
+See the file COPYING for license information.
+
+
+Description:
+------------
+convpic is a program to convert images to an own simple format (*.glcd)
+that is used by the GraphLCD graphics library.
+
+
+Installation and Configuration:
+-------------------------------
+see the file README in the base package's root directory.
+
+
+Using convpic:
+--------------
+Usage: convpic [-n] [-d x] -i infile [more files] -o outfile
+
+ -n --invert inverts the output (default: no)
+ -i --infile specifies the name of the input file
+ -o --outfile specifies the name of the output file
+ -d --delay specifies the delay delay between multiple images
+
+supported formats:
+ TIFF: file is an uncompressed RGB-encoded 2-color TIFF
+ BMP : file is an uncompressed RGB-encoded 2-color Windows BMP
+ ANI : file is an uncompressed multi-frame from tuxbox-aniplay
+ GLCD: file is the own format used by the GraphLCD graphics library
+
+example: convpic -i vdr-logo.bmp -o vdr-logo.glcd
+
+
+Known Problems:
+---------------
+ Export of TIFF isn't supported.
+
diff --git a/docs/README.crtfont b/docs/README.crtfont
new file mode 100644
index 0000000..03bf485
--- /dev/null
+++ b/docs/README.crtfont
@@ -0,0 +1,61 @@
+This is the README of the crtfont tool, which is part of the GraphLCD
+base package.
+
+written by Andreas Regel (andreas.regel AT powarman.de)
+
+based on crtfont from the graphlcd plugin for the Video Disc Recorder
+written by Carsten Siebholz (c.siebholz AT t-online.de)
+
+See the file COPYING for license information.
+
+
+Description:
+------------
+crtfont is a program to create fonts for the GraphLCD graphics library.
+
+
+Installation and Configuration:
+-------------------------------
+see the file README in the base package's root directory.
+
+
+Using crtfont:
+--------------
+To create a font, 2 source files are required:
+- an image, that contains the characters as a bitmap. This image might
+ be in:
+ - Portable Bit Map (PBM) format.
+- a description file (*.desc), that contains informations about the
+ positions of each character in the image.
+ The format of the description file:
+ - The first line contains the version of the description file format:
+ version:1
+ - The next lines contain the font attributes in the format
+ <attribute>:<value>, one attribute per line. Possible attributes
+ are:
+ fontheight: the total height of the font
+ fontascent: the vertical distance from the horizontal baseline to
+ the highest character coordinate.
+ lineheight: the baseline-to-baseline distance
+ spacebetween: additional space between characters in a text
+ spacewidth: the width of the space character. If this value is
+ greater than zero, all characters will be compressed
+ horizontally to their active pixels.
+ - All other lines define the characters and their positions in the
+ image. The syntax is like:
+ PosX_1 Char_1 PosX_2 Char_2 PosX_3 ... PosX_n Char_n EndX
+ where PosX_x specifies the horizontal position of the leftmost
+ pixel of the character. Char_x might be the character itself
+ (A, B, ...) or it's decimal ASCII value (65, 66, ...)
+
+Usage: crtfont -f <format> -b <bmpfile> -d <descfile> -o <outfile>
+
+ -f --format specifies the format of the bitmap. Possible values
+ are:
+ PBM: file is an Portable Bit Map
+ -b --bmpfile specifies the name of the bitmap file (*.pbm)
+ -d --descfile specifies the name of the description file (*.desc)
+ -o --outfile specifies the name of the output file (*.fnt)
+
+ example: crtfont -f PBM -b f12.pbm -d f12.desc -o f12.fnt
+
diff --git a/docs/README.showpic b/docs/README.showpic
new file mode 100644
index 0000000..5ea6184
--- /dev/null
+++ b/docs/README.showpic
@@ -0,0 +1,38 @@
+This is the README of the showpic tool, which is part of the GraphLCD
+base package.
+
+written by Andreas Regel (andreas.regel AT powarman.de)
+
+based on showpic from the graphlcd plugin for the Video Disc Recorder
+written by Carsten Siebholz (c.siebholz AT t-online.de)
+
+See the file COPYING for license information.
+
+
+Description:
+------------
+showpic is a program to show an image on a graphical LC Display. It
+support all controller the GraphLCD driver library supports.
+
+The images must be in an own format (*.glcd), which can be created with
+the convpic tool.
+
+
+Using showpic:
+--------------
+ showpic [-c CONFIGFILE] [-d DISPLAY] [-s SLEEP] [-uie] file [more files]
+
+ -c --config specifies the location of the config file
+ (default: /etc/graphlcd.conf)
+ -d --display specifies the output display
+ (default: the first one in config file)
+ -u --upsidedown rotates the output by 180 degrees (default: no)
+ -i --invert inverts the output (default: no)
+ -e --endless show all images in endless loop (default: no)
+ -s --sleep set sleeptime between two images [ms]
+ -b --brightness set brightness for display if driver support it
+ (default: config file value)
+
+examples: showpic -c /etc/graphlcd.conf vdr-logo.glcd
+ showpic -c /etc/graphlcd.conf -d LCD_T6963 -u -i vdr-logo.glcd
+
diff --git a/docs/README.showtext b/docs/README.showtext
new file mode 100644
index 0000000..2136322
--- /dev/null
+++ b/docs/README.showtext
@@ -0,0 +1,35 @@
+This is the README of the showtext tool, which is part of the GraphLCD
+base package.
+
+written by Andreas Regel (andreas.regel AT powarman.de)
+
+See the file COPYING for license information.
+
+
+Description:
+------------
+showtext is a program to show a user defined text with a user defined
+font on a graphical LC Display. It supports all controllers the GraphLCD
+driver library supports.
+
+The font must be in a special format (*.fnt), which can be created with
+the crtfont tool.
+
+
+Using showtext:
+--------------
+ showtext [-c CONFIGFILE] [-d DISPLAY] [-f FONT] [-x XPOS] [-y YPOS] [-uib] text [more text]
+
+ -c --config specifies the location of the config file
+ (default: /etc/graphlcd.conf)
+ -d --display specifies the output display
+ (default: the first one in config file)
+ -f --font specifies the font that is used for the text output
+ -x --xpos specifies the x-position where the text starts
+ -y --ypos specifies the y-position where the text starts
+ -u --upsidedown rotates the output by 180 degrees (default: no)
+ -i --invert inverts the output (default: no)
+ -b --brightness set brightness for display if driver support it [%]
+ (default: config file value)
+
+ example: showtext -c /etc/graphlcd.conf -f f17.fnt "Line1" "Line2"
diff --git a/glcddrivers/Makefile b/glcddrivers/Makefile
new file mode 100644
index 0000000..bd4f375
--- /dev/null
+++ b/glcddrivers/Makefile
@@ -0,0 +1,60 @@
+#
+# Makefile for the GraphLCD driver library
+#
+
+-include ../Make.config
+
+CXXFLAGS += -fPIC
+
+VERMAJOR = 1
+VERMINOR = 0
+VERMICRO = 0
+
+BASENAME = libglcddrivers.so
+
+LIBNAME = $(BASENAME).$(VERMAJOR).$(VERMINOR).$(VERMICRO)
+
+OBJS = common.o config.o driver.o drivers.o port.o simlcd.o framebuffer.o gu140x32f.o gu256x64-372.o gu256x64-3900.o hd61830.o ks0108.o image.o sed1330.o sed1520.o t6963c.o noritake800.o serdisp.o avrctl.o g15daemon.o network.o gu126x64D-K610A4.o
+
+HEADERS = config.h driver.h drivers.h
+
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = g++ -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+all: $(LIBNAME)
+
+$(LIBNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -ldl -lpthread -Wl,-soname="$(BASENAME).$(VERMAJOR)" -o $@
+ ln -sf $(LIBNAME) $(BASENAME)
+
+install: all
+ install -d $(LIBDIR)
+ install -m 755 $(LIBNAME) $(LIBDIR)/
+ install -d $(INCDIR)/glcddrivers
+ install -m 644 $(HEADERS) $(INCDIR)/glcddrivers/
+ ( cd $(LIBDIR); ln -sf $(LIBNAME) $(BASENAME).$(VERMAJOR); ln -sf $(LIBNAME) $(BASENAME) )
+
+uninstall:
+ rm -f $(LIBDIR)/$(BASENAME)
+ rm -f $(LIBDIR)/$(BASENAME).$(VERMAJOR)
+ rm -f $(LIBDIR)/$(LIBNAME)
+ (for i in $(HEADERS); do rm -f $(INCDIR)/glcddrivers/$$i; done)
+ rmdir $(INCDIR)/glcddrivers
+
+clean:
+ rm -f $(OBJS) $(DEPFILE) $(LIBNAME) $(BASENAME) *~
+
diff --git a/glcddrivers/avrctl.c b/glcddrivers/avrctl.c
new file mode 100644
index 0000000..4e1e4ea
--- /dev/null
+++ b/glcddrivers/avrctl.c
@@ -0,0 +1,355 @@
+/*
+ * GraphLCD driver library
+ *
+ * avrctl.c - AVR controlled LCD driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2005 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdint.h>
+#include <syslog.h>
+
+#include "common.h"
+#include "config.h"
+#include "port.h"
+#include "avrctl.h"
+
+
+namespace GLCD
+{
+
+/* command header:
+** 8 bits sync byte (0xAA for sent commands, 0x55 for received commands)
+** 8 bits command id
+** 16 bits command length (excluding header)
+*/
+const unsigned char CMD_HDR_SYNC = 0;
+const unsigned char CMD_HDR_COMMAND = 1;
+const unsigned char CMD_HDR_LENGTH = 2;
+const unsigned char CMD_DATA_START = 4;
+
+const unsigned char CMD_SYNC_SEND = 0xAA;
+const unsigned char CMD_SYNC_RECV = 0x55;
+
+const unsigned char CMD_SYS_SYNC = 0x00;
+const unsigned char CMD_SYS_ACK = 0x01;
+
+const unsigned char CMD_DISP_CLEAR_SCREEN = 0x10;
+const unsigned char CMD_DISP_SWITCH_SCREEN = 0x11;
+const unsigned char CMD_DISP_SET_BRIGHTNESS = 0x12;
+const unsigned char CMD_DISP_SET_COL_DATA = 0x13;
+const unsigned char CMD_DISP_SET_ROW_DATA = 0x14;
+const unsigned char CMD_DISP_UPDATE = 0x15;
+
+const int kBufferWidth = 256;
+const int kBufferHeight = 128;
+
+
+cDriverAvrCtl::cDriverAvrCtl(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cSerialPort();
+
+ //width = config->width;
+ //height = config->height;
+ refreshCounter = 0;
+}
+
+cDriverAvrCtl::~cDriverAvrCtl()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverAvrCtl::Init()
+{
+ int x;
+
+ width = config->width;
+ if (width <= 0)
+ width = 256;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup lcd array (wanted state)
+ newLCD = new unsigned char*[kBufferWidth];
+ if (newLCD)
+ {
+ for (x = 0; x < kBufferWidth; x++)
+ {
+ newLCD[x] = new unsigned char[(kBufferHeight + 7) / 8];
+ memset(newLCD[x], 0, (kBufferHeight + 7) / 8);
+ }
+ }
+ // setup lcd array (current state)
+ oldLCD = new unsigned char*[kBufferWidth];
+ if (oldLCD)
+ {
+ for (x = 0; x < kBufferWidth; x++)
+ {
+ oldLCD[x] = new unsigned char[(kBufferHeight + 7) / 8];
+ memset(oldLCD[x], 0, (kBufferHeight + 7) / 8);
+ }
+ }
+
+ if (config->device == "")
+ {
+ return -1;
+ }
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: AvrCtl initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverAvrCtl::DeInit()
+{
+ int x;
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ for (x = 0; x < kBufferWidth; x++)
+ {
+ delete[] newLCD[x];
+ }
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ for (x = 0; x < kBufferWidth; x++)
+ {
+ delete[] oldLCD[x];
+ }
+ delete[] oldLCD;
+ }
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverAvrCtl::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverAvrCtl::Clear()
+{
+ for (int x = 0; x < kBufferWidth; x++)
+ memset(newLCD[x], 0, (kBufferHeight + 7) / 8);
+}
+
+void cDriverAvrCtl::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ int offset = 7 - (y % 8);
+ for (int i = 0; i < 8; i++)
+ {
+ newLCD[x + i][y / 8] |= ((data >> (7 - i)) << offset) & (1 << offset);
+ }
+ }
+ else
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ int offset = 7 - (y % 8);
+ for (int i = 0; i < 8; i++)
+ {
+ newLCD[x - i][y / 8] |= ((data >> (7 - i)) << offset) & (1 << offset);
+ }
+ }
+}
+
+void cDriverAvrCtl::Refresh(bool refreshAll)
+{
+ int x;
+ int y;
+ int i;
+ int num = kBufferWidth / 2;
+ unsigned char data[16*num];
+
+ if (CheckSetup() == 1)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ refreshAll = true;
+ if (refreshAll)
+ {
+ for (x = 0; x < kBufferWidth; x += num)
+ {
+ for (i = 0; i < num; i++)
+ {
+ for (y = 0; y < (kBufferHeight + 7) / 8; y++)
+ {
+ data[i * ((kBufferHeight + 7) / 8) + y] = (newLCD[x + i][y]) ^ (config->invert ? 0xff : 0x00);
+ }
+ memcpy(oldLCD[x + i], newLCD[x + i], (kBufferHeight + 7) / 8);
+ }
+ CmdDispSetColData(x, 0, 16 * num, data);
+ }
+ CmdDispUpdate();
+ CmdDispSwitchScreen();
+ // and reset RefreshCounter
+ refreshCounter = 0;
+ }
+ else
+ {
+ // draw only the changed bytes
+ }
+}
+
+void cDriverAvrCtl::SetBrightness(unsigned int percent)
+{
+ CmdDispSetBrightness(percent);
+}
+
+int cDriverAvrCtl::WaitForAck(void)
+{
+ uint8_t cmd[4];
+ int len;
+ int timeout = 10000;
+
+ len = 0;
+ while (len < 4 && timeout > 0)
+ {
+ len += port->ReadData(&cmd[len]);
+ timeout--;
+ }
+ if (timeout == 0)
+ return 0;
+ return 1;
+}
+
+void cDriverAvrCtl::CmdSysSync(void)
+{
+ uint8_t cmd[4];
+
+ cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
+ cmd[CMD_HDR_COMMAND] = CMD_SYS_SYNC;
+ cmd[CMD_HDR_LENGTH] = 0;
+ cmd[CMD_HDR_LENGTH+1] = 0;
+
+ port->WriteData(cmd, 4);
+ WaitForAck();
+}
+
+void cDriverAvrCtl::CmdDispClearScreen(void)
+{
+ uint8_t cmd[4];
+
+ cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
+ cmd[CMD_HDR_COMMAND] = CMD_DISP_CLEAR_SCREEN;
+ cmd[CMD_HDR_LENGTH] = 0;
+ cmd[CMD_HDR_LENGTH+1] = 0;
+
+ port->WriteData(cmd, 4);
+ WaitForAck();
+}
+
+void cDriverAvrCtl::CmdDispSwitchScreen(void)
+{
+ uint8_t cmd[4];
+
+ cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
+ cmd[CMD_HDR_COMMAND] = CMD_DISP_SWITCH_SCREEN;
+ cmd[CMD_HDR_LENGTH] = 0;
+ cmd[CMD_HDR_LENGTH+1] = 0;
+
+ port->WriteData(cmd, 4);
+ WaitForAck();
+}
+
+void cDriverAvrCtl::CmdDispSetBrightness(uint8_t percent)
+{
+ uint8_t cmd[5];
+
+ cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
+ cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_BRIGHTNESS;
+ cmd[CMD_HDR_LENGTH] = 0;
+ cmd[CMD_HDR_LENGTH+1] = 1;
+ cmd[CMD_DATA_START] = percent;
+
+ port->WriteData(cmd, 5);
+ WaitForAck();
+}
+
+void cDriverAvrCtl::CmdDispSetColData(uint16_t column, uint16_t offset, uint16_t length, uint8_t * data)
+{
+ uint8_t cmd[2560];
+
+ cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
+ cmd[CMD_HDR_COMMAND] = CMD_DISP_SET_COL_DATA;
+ cmd[CMD_HDR_LENGTH] = (length + 6) >> 8;
+ cmd[CMD_HDR_LENGTH+1] = (length + 6);
+ cmd[CMD_DATA_START] = column >> 8;
+ cmd[CMD_DATA_START+1] = column;
+ cmd[CMD_DATA_START+2] = offset >> 8;
+ cmd[CMD_DATA_START+3] = offset;
+ cmd[CMD_DATA_START+4] = length >> 8;
+ cmd[CMD_DATA_START+5] = length;
+ memcpy(&cmd[CMD_DATA_START+6], data, length);
+
+ port->WriteData(cmd, length+10);
+ WaitForAck();
+}
+
+void cDriverAvrCtl::CmdDispUpdate(void)
+{
+ uint8_t cmd[4];
+
+ cmd[CMD_HDR_SYNC] = CMD_SYNC_SEND;
+ cmd[CMD_HDR_COMMAND] = CMD_DISP_UPDATE;
+ cmd[CMD_HDR_LENGTH] = 0;
+ cmd[CMD_HDR_LENGTH+1] = 0;
+
+ port->WriteData(cmd, 4);
+ WaitForAck();
+}
+
+}
diff --git a/glcddrivers/avrctl.h b/glcddrivers/avrctl.h
new file mode 100644
index 0000000..557b7d2
--- /dev/null
+++ b/glcddrivers/avrctl.h
@@ -0,0 +1,58 @@
+/*
+ * GraphLCD driver library
+ *
+ * avrctl.h - AVR controlled LCD driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2005 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_AVRCTL_H_
+#define _GLCDDRIVERS_AVRCTL_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cSerialPort;
+
+class cDriverAvrCtl : public cDriver
+{
+private:
+ cSerialPort * port;
+ unsigned char ** newLCD; // wanted state
+ unsigned char ** oldLCD; // current state
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ int refreshCounter;
+
+ int WaitForAck(void);
+ void CmdSysSync(void);
+ void CmdDispClearScreen(void);
+ void CmdDispSwitchScreen(void);
+ void CmdDispSetBrightness(unsigned char percent);
+ void CmdDispSetColData(uint16_t column, uint16_t offset, uint16_t length, uint8_t * data);
+ void CmdDispUpdate(void);
+
+ int CheckSetup();
+
+public:
+ cDriverAvrCtl(cDriverConfig * config);
+ virtual ~cDriverAvrCtl();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/common.c b/glcddrivers/common.c
new file mode 100644
index 0000000..0d0fad9
--- /dev/null
+++ b/glcddrivers/common.c
@@ -0,0 +1,231 @@
+/*
+ * GraphLCD driver library
+ *
+ * common.c - various functions
+ *
+ * parts were taken from graphlcd plugin for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <ctype.h>
+#include <sched.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "common.h"
+#include "config.h"
+
+
+namespace GLCD
+{
+
+static const int BitReverseTable[256] =
+{
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+int nSleepInit()
+{
+ int ret = 0;
+
+ if (Config.waitPriority != 0)
+ {
+ ret = setpriority(PRIO_PROCESS, 0, Config.waitPriority);
+ }
+
+ if (!ret)
+ {
+ switch (Config.waitMethod)
+ {
+ case kWaitUsleep: // usleep
+ break;
+ case kWaitNanosleep: // nanosleep
+ break;
+ case kWaitNanosleepRR: // nanosleep (sched_rr)
+ // set sched algorithm
+ struct sched_param param;
+
+ param.sched_priority=1;
+ ret = sched_setscheduler(0, SCHED_RR, &param);
+ break;
+ case kWaitGettimeofday: // gettimeofday
+ break;
+ }
+ }
+ return ret;
+}
+
+int nSleepDeInit()
+{
+ int ret = 0;
+
+ if (Config.waitPriority != 0)
+ {
+ ret = setpriority(PRIO_PROCESS, 0, 0);
+ }
+
+ if (!ret)
+ {
+ switch (Config.waitMethod)
+ {
+ case kWaitUsleep: // usleep
+ break;
+ case kWaitNanosleep: // nanosleep
+ break;
+ case kWaitNanosleepRR: // nanosleep (sched_rr)
+ // set sched algorithm
+ struct sched_param param;
+
+ param.sched_priority=0;
+ ret = sched_setscheduler(0, SCHED_OTHER, &param);
+ break;
+ case kWaitGettimeofday: // gettimeofday
+ break;
+ }
+ }
+ return ret;
+}
+
+void nSleep(long ns)
+{
+ switch (Config.waitMethod)
+ {
+ case kWaitUsleep: // usleep
+ if (ns > 0)
+ {
+ usleep(std::max(1L, ns/1000));
+ }
+ break;
+ case kWaitNanosleep: // nanosleep
+ case kWaitNanosleepRR: // nanosleep(sched_rr)
+ struct timespec delay, remaining;
+ if (ns > 0)
+ {
+ delay.tv_sec = ns/1000000000;
+ delay.tv_nsec = ns%1000000000;
+ while (nanosleep(&delay, &remaining) == -1)
+ {
+ delay.tv_sec = remaining.tv_sec;
+ delay.tv_nsec = remaining.tv_nsec;
+ }
+ }
+ break;
+ case kWaitGettimeofday: //getTimeofday for Kernel 2.6
+ long us;
+ struct timeval tv1, tv2;
+ suseconds_t us2;
+ if (ns > 0)
+ {
+ us = ns / 1000;
+ if (us == 0)
+ us = 1;
+ gettimeofday(&tv1, 0);
+ do
+ {
+ gettimeofday(&tv2, 0);
+ us2 = tv2.tv_usec + ((tv2.tv_sec - tv1.tv_sec) * 1000000);
+ } while (us2 - tv1.tv_usec < us);
+ }
+ }
+}
+
+void uSleep(long us)
+{
+ if (Config.waitMethod == kWaitUsleep)
+ {
+ // usleep
+ if (us > 0)
+ usleep(std::max(1L, us));
+ }
+ else
+ {
+ nSleep(us * 1000);
+ }
+}
+
+
+
+unsigned char ReverseBits(unsigned char value)
+{
+ return BitReverseTable[value];
+}
+
+void clip(int & value, int min, int max)
+{
+ if (value < min)
+ value = min;
+ if (value > max)
+ value = max;
+}
+
+void sort(int & value1, int & value2)
+{
+ if (value2 < value1)
+ {
+ int tmp;
+ tmp = value2;
+ value2 = value1;
+ value1 = tmp;
+ }
+}
+
+std::string trim(const std::string & s)
+{
+ std::string::size_type start, end;
+
+ start = 0;
+ while (start < s.length())
+ {
+ if (!isspace(s[start]))
+ break;
+ start++;
+ }
+ end = s.length() - 1;
+ while (end >= 0)
+ {
+ if (!isspace(s[end]))
+ break;
+ end--;
+ }
+ return s.substr(start, end - start + 1);
+}
+
+} // end of namespace
diff --git a/glcddrivers/common.h b/glcddrivers/common.h
new file mode 100644
index 0000000..d1ddcda
--- /dev/null
+++ b/glcddrivers/common.h
@@ -0,0 +1,42 @@
+/*
+ * GraphLCD driver library
+ *
+ * common.c - various functions
+ *
+ * parts were taken from graphlcd plugin for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_COMMON_H_
+#define _GLCDDRIVERS_COMMON_H_
+
+#include <string>
+
+namespace GLCD
+{
+
+const unsigned char bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+const unsigned char bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
+const unsigned char bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+
+// functions to enable/disable very short sleeps.
+// Therefore, the priority will be changed. => use with care !
+int nSleepInit(void);
+int nSleepDeInit(void);
+
+void nSleep(long ns);
+void uSleep(long us);
+
+unsigned char ReverseBits(unsigned char value);
+void clip(int & value, int min, int max);
+void sort(int & value1, int & value2);
+std::string trim(const std::string & s);
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/config.c b/glcddrivers/config.c
new file mode 100644
index 0000000..fec3372
--- /dev/null
+++ b/glcddrivers/config.c
@@ -0,0 +1,286 @@
+/*
+ * GraphLCD driver library
+ *
+ * config.c - config file classes
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <syslog.h>
+#include <fstream>
+
+#include "common.h"
+#include "config.h"
+#include "drivers.h"
+
+
+namespace GLCD
+{
+
+cDriverConfig::cDriverConfig()
+: name(""),
+ driver(""),
+ id(kDriverUnknown),
+ device(""),
+ port(0),
+ width(0),
+ height(0),
+ upsideDown(false),
+ invert(false),
+ brightness(100),
+ contrast(5),
+ backlight(true),
+ adjustTiming(0),
+ refreshDisplay(5)
+{
+}
+
+cDriverConfig::cDriverConfig(const cDriverConfig & rhs)
+{
+ name = rhs.name;
+ driver = rhs.driver;
+ id = rhs.id;
+ device = rhs.device;
+ port = rhs.port;
+ width = rhs.width;
+ height = rhs.height;
+ upsideDown = rhs.upsideDown;
+ invert = rhs.invert;
+ brightness = rhs.brightness;
+ contrast = rhs.contrast;
+ backlight = rhs.backlight;
+ adjustTiming = rhs.adjustTiming;
+ refreshDisplay = rhs.refreshDisplay;
+ for (unsigned int i = 0; i < rhs.options.size(); i++)
+ options.push_back(rhs.options[i]);
+}
+
+cDriverConfig::~cDriverConfig()
+{
+}
+
+cDriverConfig & cDriverConfig::operator=(const cDriverConfig & rhs)
+{
+ if (this == &rhs)
+ return *this;
+
+ name = rhs.name;
+ driver = rhs.driver;
+ id = rhs.id;
+ device = rhs.device;
+ port = rhs.port;
+ width = rhs.width;
+ height = rhs.height;
+ upsideDown = rhs.upsideDown;
+ invert = rhs.invert;
+ brightness = rhs.brightness;
+ contrast = rhs.contrast;
+ backlight = rhs.backlight;
+ adjustTiming = rhs.adjustTiming;
+ refreshDisplay = rhs.refreshDisplay;
+ options.clear();
+ for (unsigned int i = 0; i < rhs.options.size(); i++)
+ options.push_back(rhs.options[i]);
+
+ return *this;
+}
+
+bool cDriverConfig::Parse(const std::string & line)
+{
+ std::string::size_type pos;
+ tOption option;
+
+ pos = line.find("=");
+ if (pos == std::string::npos)
+ return false;
+ option.name = trim(line.substr(0, pos));
+ option.value = trim(line.substr(pos + 1));
+ //printf("D %s = %s\n", option.name.c_str(), option.value.c_str());
+
+ if (option.name == "Driver")
+ {
+ int driverCount;
+ tDriver * drivers = GetAvailableDrivers(driverCount);
+ for (int i = 0; i < driverCount; i++)
+ {
+ if (option.value == drivers[i].name)
+ {
+ driver = drivers[i].name;
+ id = drivers[i].id;
+ break;
+ }
+ }
+ }
+ else if (option.name == "Device")
+ {
+ device = option.value;
+ }
+ else if (option.name == "Port")
+ {
+ port = GetInt(option.value);
+ }
+ else if (option.name == "Width")
+ {
+ width = GetInt(option.value);
+ }
+ else if (option.name == "Height")
+ {
+ height = GetInt(option.value);
+ }
+ else if (option.name == "UpsideDown")
+ {
+ upsideDown = GetBool(option.value);
+ }
+ else if (option.name == "Invert")
+ {
+ invert = GetBool(option.value);
+ }
+ else if (option.name == "Brightness")
+ {
+ brightness = GetInt(option.value);
+ }
+ else if (option.name == "Contrast")
+ {
+ contrast = GetInt(option.value);
+ }
+ else if (option.name == "Backlight")
+ {
+ backlight = GetBool(option.value);
+ }
+ else if (option.name == "AdjustTiming")
+ {
+ adjustTiming = GetInt(option.value);
+ }
+ else if (option.name == "RefreshDisplay")
+ {
+ refreshDisplay = GetInt(option.value);
+ }
+ else
+ {
+ options.push_back(option);
+ }
+ return true;
+}
+
+int cDriverConfig::GetInt(const std::string & value)
+{
+ return strtol(value.c_str(), NULL, 0);
+}
+
+bool cDriverConfig::GetBool(const std::string & value)
+{
+ return value == "yes";
+}
+
+
+cConfig::cConfig()
+: waitMethod(kWaitGettimeofday),
+ waitPriority(0)
+{
+}
+
+cConfig::~cConfig()
+{
+}
+
+bool cConfig::Load(const std::string & filename)
+{
+ std::fstream file;
+ char readLine[1000];
+ std::string line;
+ bool inSections = false;
+ int section = 0;
+
+#if (__GNUC__ < 3)
+ file.open(filename.c_str(), std::ios::in);
+#else
+ file.open(filename.c_str(), std::ios_base::in);
+#endif
+ if (!file.is_open())
+ return false;
+
+ while (!file.eof())
+ {
+ file.getline(readLine, 1000);
+ line = trim(readLine);
+ if (line.length() == 0)
+ continue;
+ if (line[0] == '#')
+ continue;
+ if (line[0] == '[' && line[line.length() - 1] == ']')
+ {
+ if (!inSections)
+ inSections = true;
+ else
+ section++;
+ driverConfigs.resize(section + 1);
+ driverConfigs[section].name = line.substr(1, line.length() - 2);
+ continue;
+ }
+ if (!inSections)
+ {
+ Parse(line);
+ }
+ else
+ {
+ driverConfigs[section].Parse(line);
+ }
+ }
+
+ file.close();
+ return true;
+}
+
+bool cConfig::Parse(const std::string & line)
+{
+ std::string::size_type pos;
+ tOption option;
+
+ pos = line.find("=");
+ if (pos == std::string::npos)
+ return false;
+ option.name = trim(line.substr(0, pos));
+ option.value = trim(line.substr(pos + 1));
+ //printf("%s = %s\n", option.name.c_str(), option.value.c_str());
+
+ if (option.name == "WaitMethod")
+ {
+ waitMethod = GetInt(option.value);
+ }
+ else if (option.name == "WaitPriority")
+ {
+ waitPriority = GetInt(option.value);
+ }
+ else
+ {
+ syslog(LOG_ERR, "Config error: unknown option %s given!\n", option.value.c_str());
+ return false;
+ }
+ return true;
+}
+
+int cConfig::GetInt(const std::string & value)
+{
+ return strtol(value.c_str(), NULL, 0);
+}
+
+bool cConfig::GetBool(const std::string & value)
+{
+ return value == "yes";
+}
+
+int cConfig::GetConfigIndex(const std::string & name)
+{
+ for (int i = 0; i < (int)driverConfigs.size(); i++)
+ if (driverConfigs[i].name == name)
+ return i;
+ syslog(LOG_ERR, "Config error: configuration %s not found!\n", name.c_str());
+ return -1;
+}
+
+cConfig Config;
+
+} // end of namespace
diff --git a/glcddrivers/config.h b/glcddrivers/config.h
new file mode 100644
index 0000000..8caa77e
--- /dev/null
+++ b/glcddrivers/config.h
@@ -0,0 +1,85 @@
+/*
+ * GraphLCD driver library
+ *
+ * config.h - config file classes
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_CONFIG_H_
+#define _GLCDDRIVERS_CONFIG_H_
+
+#include <string>
+#include <vector>
+
+
+namespace GLCD
+{
+
+const int kWaitUsleep = 0;
+const int kWaitNanosleep = 1;
+const int kWaitNanosleepRR = 2;
+const int kWaitGettimeofday = 3;
+
+
+struct tOption
+{
+ std::string name;
+ std::string value;
+};
+
+class cDriverConfig
+{
+public:
+ std::string name;
+ std::string driver;
+ int id;
+ std::string device;
+ int port;
+ int width;
+ int height;
+ bool upsideDown;
+ bool invert;
+ int brightness;
+ int contrast;
+ bool backlight;
+ int adjustTiming;
+ int refreshDisplay;
+ std::vector <tOption> options;
+
+public:
+ cDriverConfig();
+ cDriverConfig(const cDriverConfig & rhs);
+ ~cDriverConfig();
+ cDriverConfig & operator=(const cDriverConfig & rhs);
+ bool Parse(const std::string & line);
+ int GetInt(const std::string & value);
+ bool GetBool(const std::string & value);
+};
+
+class cConfig
+{
+public:
+ int waitMethod;
+ int waitPriority;
+ std::vector <cDriverConfig> driverConfigs;
+
+public:
+ cConfig();
+ ~cConfig();
+ bool Load(const std::string & filename);
+ bool Save(const std::string & filename);
+ bool Parse(const std::string & line);
+ int GetInt(const std::string & value);
+ bool GetBool(const std::string & value);
+ int GetConfigIndex(const std::string & name);
+};
+
+extern cConfig Config;
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/driver.c b/glcddrivers/driver.c
new file mode 100644
index 0000000..b1b6286
--- /dev/null
+++ b/glcddrivers/driver.c
@@ -0,0 +1,54 @@
+/*
+ * GraphLCD driver library
+ *
+ * driver.c - driver base class
+ *
+ * parts were taken from graphlcd plugin for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include "common.h"
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+cDriver::cDriver()
+: width(0),
+ height(0)
+{
+}
+
+void cDriver::SetScreen(const unsigned char * data, int wid, int hgt, int lineSize)
+{
+ int x, y;
+
+ if (wid > width)
+ wid = width;
+ if (hgt > height)
+ hgt = height;
+
+ Clear();
+ if (data)
+ {
+ for (y = 0; y < hgt; y++)
+ {
+ for (x = 0; x < (wid / 8); x++)
+ {
+ Set8Pixels(x * 8, y, data[y * lineSize + x]);
+ }
+ if (width % 8)
+ {
+ Set8Pixels((wid / 8) * 8, y, data[y * lineSize + wid / 8] & bitmaskl[wid % 8 - 1]);
+ }
+ }
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/driver.h b/glcddrivers/driver.h
new file mode 100644
index 0000000..1d82eaa
--- /dev/null
+++ b/glcddrivers/driver.h
@@ -0,0 +1,48 @@
+/*
+ * GraphLCD driver library
+ *
+ * driver.h - driver base class
+ *
+ * parts were taken from graphlcd plugin for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_DRIVER_H_
+#define _GLCDDRIVERS_DRIVER_H_
+
+#include <stdint.h>
+
+namespace GLCD
+{
+
+class cDriver
+{
+protected:
+ int width;
+ int height;
+public:
+ cDriver();
+ virtual ~cDriver() {}
+
+ int Width() const { return width; }
+ int Height() const { return height; }
+
+ virtual int Init() { return 0; }
+ virtual int DeInit() { return 0; }
+
+ virtual void Clear() {}
+ virtual void Set8Pixels(int x, int y, unsigned char data) {}
+ virtual void SetScreen(const unsigned char * data, int width, int height, int lineSize);
+ virtual void Refresh(bool refreshAll = false) {}
+
+ virtual void SetBrightness(unsigned int percent) {}
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/drivers.c b/glcddrivers/drivers.c
new file mode 100644
index 0000000..ff1e439
--- /dev/null
+++ b/glcddrivers/drivers.c
@@ -0,0 +1,117 @@
+/*
+ * GraphLCD driver library
+ *
+ * drivers.c - global driver constants and functions
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <string.h>
+
+#include "drivers.h"
+#include "simlcd.h"
+#include "gu140x32f.h"
+#include "gu256x64-372.h"
+#include "gu256x64-3900.h"
+#include "hd61830.h"
+#include "ks0108.h"
+#include "sed1330.h"
+#include "sed1520.h"
+#include "t6963c.h"
+#include "framebuffer.h"
+#include "image.h"
+#include "noritake800.h"
+#include "avrctl.h"
+#include "network.h"
+#include "gu126x64D-K610A4.h"
+#include "serdisp.h"
+#include "g15daemon.h"
+
+namespace GLCD
+{
+
+tDriver drivers[] =
+{
+ {"simlcd", kDriverSimLCD},
+ {"gu140x32f", kDriverGU140X32F},
+ {"gu256x64-372", kDriverGU256X64_372},
+ {"gu256x64-3900", kDriverGU256X64_3900},
+ {"hd61830", kDriverHD61830},
+ {"ks0108", kDriverKS0108},
+ {"sed1330", kDriverSED1330},
+ {"sed1520", kDriverSED1520},
+ {"t6963c", kDriverT6963C},
+ {"framebuffer", kDriverFramebuffer},
+ {"image", kDriverImage},
+ {"noritake800", kDriverNoritake800},
+ {"avrctl", kDriverAvrCtl},
+ {"network", kDriverNetwork},
+ {"gu126x64D-K610A4", kDriverGU126X64D_K610A4},
+ {"serdisp", kDriverSerDisp},
+ {"g15daemon", kDriverG15daemon},
+ {"", kDriverUnknown}
+};
+
+tDriver * GetAvailableDrivers(int & count)
+{
+ for (count = 0; drivers[count].name.length() > 0; count++)
+ ;
+ return drivers;
+}
+
+int GetDriverID(const std::string & driver)
+{
+ for (int i = 0; drivers[i].name.length() > 0; i++)
+ if (drivers[i].name == driver)
+ return drivers[i].id;
+ return kDriverUnknown;
+}
+
+cDriver * CreateDriver(int driverID, cDriverConfig * config)
+{
+ switch (driverID)
+ {
+ case kDriverSimLCD:
+ return new cDriverSimLCD(config);
+ case kDriverGU140X32F:
+ return new cDriverGU140X32F(config);
+ case kDriverGU256X64_372:
+ return new cDriverGU256X64_372(config);
+ case kDriverGU256X64_3900:
+ return new cDriverGU256X64_3900(config);
+ case kDriverHD61830:
+ return new cDriverHD61830(config);
+ case kDriverKS0108:
+ return new cDriverKS0108(config);
+ case kDriverSED1330:
+ return new cDriverSED1330(config);
+ case kDriverSED1520:
+ return new cDriverSED1520(config);
+ case kDriverT6963C:
+ return new cDriverT6963C(config);
+ case kDriverFramebuffer:
+ return new cDriverFramebuffer(config);
+ case kDriverImage:
+ return new cDriverImage(config);
+ case kDriverNoritake800:
+ return new cDriverNoritake800(config);
+ case kDriverAvrCtl:
+ return new cDriverAvrCtl(config);
+ case kDriverNetwork:
+ return new cDriverNetwork(config);
+ case kDriverGU126X64D_K610A4:
+ return new cDriverGU126X64D_K610A4(config);
+ case kDriverSerDisp:
+ return new cDriverSerDisp(config);
+ case kDriverG15daemon:
+ return new cDriverG15daemon(config);
+ case kDriverUnknown:
+ default:
+ return NULL;
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/drivers.h b/glcddrivers/drivers.h
new file mode 100644
index 0000000..f51ea1d
--- /dev/null
+++ b/glcddrivers/drivers.h
@@ -0,0 +1,58 @@
+/*
+ * GraphLCD driver library
+ *
+ * drivers.h - global driver constants and functions
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_DRIVERS_H_
+#define _GLCDDRIVERS_DRIVERS_H_
+
+#include <string>
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cDriver;
+
+enum eDriver
+{
+ kDriverUnknown = 0,
+ kDriverSimLCD = 1,
+ kDriverGU140X32F = 2,
+ kDriverGU256X64_372 = 3,
+ kDriverGU256X64_3900 = 4,
+ kDriverHD61830 = 5,
+ kDriverKS0108 = 6,
+ kDriverSED1330 = 7,
+ kDriverSED1520 = 8,
+ kDriverT6963C = 9,
+ kDriverFramebuffer = 10,
+ kDriverImage = 11,
+ kDriverNoritake800 = 12,
+ kDriverAvrCtl = 13,
+ kDriverNetwork = 14,
+ kDriverGU126X64D_K610A4 = 15,
+ kDriverSerDisp = 100,
+ kDriverG15daemon = 200
+};
+
+struct tDriver
+{
+ std::string name;
+ eDriver id;
+};
+
+tDriver * GetAvailableDrivers(int & count);
+int GetDriverID(const std::string & driver);
+cDriver * CreateDriver(int driverID, cDriverConfig * config);
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/framebuffer.c b/glcddrivers/framebuffer.c
new file mode 100644
index 0000000..f9666fa
--- /dev/null
+++ b/glcddrivers/framebuffer.c
@@ -0,0 +1,249 @@
+/*
+ * GraphLCD driver library
+ *
+ * framebuffer.h - framebuffer device
+ * Output goes to a framebuffer device
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Stephan Skrodzki
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#include "common.h"
+#include "config.h"
+#include "framebuffer.h"
+
+
+namespace GLCD
+{
+
+cDriverFramebuffer::cDriverFramebuffer(cDriverConfig * config)
+: config(config),
+ offbuff(0),
+ fbfd(-1)
+{
+ oldConfig = new cDriverConfig(*config);
+}
+
+cDriverFramebuffer::~cDriverFramebuffer()
+{
+ delete oldConfig;
+}
+
+int cDriverFramebuffer::Init()
+{
+ // default values
+ width = config->width;
+ if (width <= 0)
+ width = 320;
+ height = config->height;
+ if (height <= 0)
+ height = 240;
+ zoom = 1;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Zoom")
+ {
+ int z = atoi(config->options[i].value.c_str());
+ if (z == 0 || z == 1)
+ zoom = z;
+ else
+ syslog(LOG_ERR, "%s error: zoom %d not supported, using default (%d)!\n",
+ config->name.c_str(), z, zoom);
+ }
+ }
+
+ // Open the file for reading and writing
+ fbfd = open("/dev/fb0", O_RDWR);
+ if (1 == fbfd)
+ {
+ syslog(LOG_ERR, "%s: cannot open framebuffer device.\n", config->name.c_str());
+ return -1;
+ }
+ syslog(LOG_INFO, "%s: The framebuffer device was opened successfully.\n", config->name.c_str());
+
+ // Get fixed screen information
+ if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
+ {
+ syslog(LOG_ERR, "%s: Error reading fixed information.\n", config->name.c_str());
+ return -1;
+ }
+
+ // Get variable screen information
+ if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
+ {
+ syslog(LOG_ERR, "%s: Error reading variable information.\n", config->name.c_str());
+ return -1;
+ }
+
+ // Figure out the size of the screen in bytes
+ screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
+
+ syslog(LOG_INFO, "%s: V01: xres: %d, yres %d, vyres: %d, bpp: %d, linelenght: %d\n", config->name.c_str(),vinfo.xres,vinfo.yres,vinfo.yres_virtual,vinfo.bits_per_pixel,finfo.line_length);
+
+ // reserve another memory to draw into
+ offbuff = new char[screensize];
+ if (!offbuff)
+ {
+ syslog(LOG_ERR, "%s: failed to alloc memory for framebuffer device.\n", config->name.c_str());
+ return -1;
+ }
+
+ // Map the device to memory
+ fbp = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
+ if (fbp == MAP_FAILED)
+ {
+ syslog(LOG_ERR, "%s: failed to map framebuffer device to memory.\n", config->name.c_str());
+ return -1;
+ }
+ syslog(LOG_INFO, "%s: The framebuffer device was mapped to memory successfully.\n", config->name.c_str());
+
+ *oldConfig = *config;
+
+ // clear display
+ Refresh(true);
+
+ syslog(LOG_INFO, "%s: Framebuffer initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverFramebuffer::DeInit()
+{
+ if (offbuff)
+ delete[] offbuff;
+ munmap(fbp, screensize);
+ if (-1 != fbfd)
+ close(fbfd);
+ return 0;
+}
+
+int cDriverFramebuffer::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverFramebuffer::SetPixel(int x, int y)
+{
+ int location;
+ int outcol;
+
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ // Figure out where in memory to put the pixel
+ location = (x*(1+zoom)+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
+ (y*(1+zoom)+vinfo.yoffset) * finfo.line_length;
+
+ if (vinfo.bits_per_pixel <= 8)
+ {
+ outcol = 15;
+ }
+ else
+ {
+ outcol = 255;
+ }
+
+ if (vinfo.bits_per_pixel <= 8)
+ {
+ *(offbuff + location) = outcol;
+ if (zoom == 1)
+ {
+ *(offbuff + location + 1) = outcol;
+ *(offbuff + location + finfo.line_length) = outcol;
+ *(offbuff + location + finfo.line_length + 1) = outcol;
+ }
+ }
+ else if (vinfo.bits_per_pixel <= 16)
+ {
+ *(offbuff + location) = outcol;
+ *(offbuff + location + 1) = outcol;
+ if (zoom == 1)
+ {
+ *(offbuff + location + 2) = outcol;
+ *(offbuff + location + 3) = outcol;
+ *(offbuff + location + finfo.line_length) = outcol;
+ *(offbuff + location + finfo.line_length + 1) = outcol;
+ *(offbuff + location + finfo.line_length + 2) = outcol;
+ *(offbuff + location + finfo.line_length + 3) = outcol;
+ }
+ }
+ else
+ {
+ *(offbuff + location) = outcol;
+ *(offbuff + location + 1) = outcol;
+ *(offbuff + location + 2) = outcol;
+ *(offbuff + location + 3) = 0; /* should be transparency */
+ if (zoom == 1)
+ {
+ *(offbuff + location + 4) = outcol;
+ *(offbuff + location + 5) = outcol;
+ *(offbuff + location + 6) = outcol;
+ *(offbuff + location + 7) = 0;
+ *(offbuff + location + finfo.line_length) = outcol;
+ *(offbuff + location + finfo.line_length + 1) = outcol;
+ *(offbuff + location + finfo.line_length + 2) = outcol;
+ *(offbuff + location + finfo.line_length + 3) = 0;
+ *(offbuff + location + finfo.line_length + 4) = outcol;
+ *(offbuff + location + finfo.line_length + 5) = outcol;
+ *(offbuff + location + finfo.line_length + 6) = outcol;
+ *(offbuff + location + finfo.line_length + 7) = 0;
+ }
+ }
+}
+
+void cDriverFramebuffer::Clear()
+{
+ memset(offbuff, 0, screensize);
+}
+
+void cDriverFramebuffer::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverFramebuffer::Refresh(bool refreshAll)
+{
+ memcpy(fbp, offbuff, screensize);
+}
+
+} // end of namespace
diff --git a/glcddrivers/framebuffer.h b/glcddrivers/framebuffer.h
new file mode 100644
index 0000000..79d1d77
--- /dev/null
+++ b/glcddrivers/framebuffer.h
@@ -0,0 +1,56 @@
+/*
+ * GraphLCD driver library
+ *
+ * framebuffer.h - framebuffer device
+ * Output goes to a framebuffer device
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Stephan Skrodzki
+ */
+
+#ifndef _GLCDDRIVERS_FRAMEBUFFER_H_
+#define _GLCDDRIVERS_FRAMEBUFFER_H_
+
+#include "driver.h"
+#include <linux/fb.h>
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverFramebuffer : public cDriver
+{
+private:
+ unsigned char ** LCD;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ char *offbuff;
+ int fbfd;
+ struct fb_var_screeninfo vinfo;
+ struct fb_fix_screeninfo finfo;
+ long int screensize;
+ void *fbp;
+ int zoom;
+
+ int CheckSetup();
+ void SetPixel(int x, int y);
+
+public:
+ cDriverFramebuffer(cDriverConfig * config);
+ virtual ~cDriverFramebuffer();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/g15daemon.c b/glcddrivers/g15daemon.c
new file mode 100644
index 0000000..f041b29
--- /dev/null
+++ b/glcddrivers/g15daemon.c
@@ -0,0 +1,219 @@
+/*
+* GraphLCD driver library
+*
+* g15daemon.c - pseudo device for the g15daemon meta driver
+* Output goes to the g15daemon which then displays it
+*
+* This file is released under the GNU General Public License. Refer
+* to the COPYING file distributed with this package.
+*
+*/
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <poll.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#include "common.h"
+#include "config.h"
+
+#include "g15daemon.h"
+
+#define G15SERVER_PORT 15550
+#define G15SERVER_ADDR "127.0.0.1"
+
+#define G15_WIDTH 160
+#define G15_HEIGHT 43
+
+
+static int g15_send(int sock, char *buf, int len)
+{
+ int total = 0;
+ int retval = 0;
+ int bytesleft = len;
+
+ while (total < len) {
+ retval = send(sock, buf+total, bytesleft, 0);
+ if (retval == -1) {
+ break;
+ }
+ bytesleft -= retval;
+ total += retval;
+ }
+ return retval==-1?-1:0;
+}
+
+static int g15_recv(int sock, char *buf, int len)
+{
+ int total = 0;
+ int retval = 0;
+ int bytesleft = len;
+
+ while (total < len) {
+ retval = recv(sock, buf+total, bytesleft, 0);
+ if (retval < 1) {
+ break;
+ }
+ total += retval;
+ bytesleft -= retval;
+ }
+ return total;
+}
+
+static int open_g15_daemon()
+{
+ int g15screen_fd;
+ struct sockaddr_in serv_addr;
+
+ char buffer[256];
+
+ g15screen_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (g15screen_fd < 0)
+ return -1;
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ inet_aton (G15SERVER_ADDR, &serv_addr.sin_addr);
+ serv_addr.sin_port = htons(G15SERVER_PORT);
+
+ if (connect(g15screen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
+ return -1;
+
+ memset(buffer,0,256);
+ if (g15_recv(g15screen_fd, buffer, 16)<0)
+ return -1;
+
+ /* here we check that we're really talking to the g15daemon */
+ if (strcmp(buffer,"G15 daemon HELLO") != 0)
+ return -1;
+
+ /* we want to use a pixelbuffer */
+ g15_send(g15screen_fd,"GBUF",4);
+
+ return g15screen_fd;
+}
+
+
+namespace GLCD
+{
+
+cDriverG15daemon::cDriverG15daemon(cDriverConfig * config)
+: config(config),
+ offbuff(0),
+ sockfd(-1)
+{
+ oldConfig = new cDriverConfig(*config);
+}
+
+cDriverG15daemon::~cDriverG15daemon()
+{
+ delete oldConfig;
+}
+
+int cDriverG15daemon::Init()
+{
+ // default values
+ width = config->width;
+ if (width !=G15_WIDTH)
+ width = G15_WIDTH;
+ height = config->height;
+ if (height !=G15_HEIGHT)
+ height = G15_HEIGHT;
+
+ for (unsigned int i = 0; i < config->options.size(); i++) {
+ if (config->options[i].name == "") {
+ }
+ }
+
+ screensize = 6880;
+
+ if ((sockfd = open_g15_daemon())<0)
+ return -1;
+ // reserve memory to draw into
+ offbuff = new char[6880];
+
+ *oldConfig = *config;
+
+ // clear display
+ Refresh(true);
+
+ syslog(LOG_INFO, "%s: g15daemon initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverG15daemon::DeInit()
+{
+ if (offbuff);
+ delete[] offbuff;
+ if (-1 != sockfd)
+ close(sockfd);
+
+ return 0;
+}
+
+int cDriverG15daemon::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverG15daemon::SetPixel(int x, int y)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ offbuff[x + (width * y)] = 1;
+}
+
+void cDriverG15daemon::Clear()
+{
+ memset(offbuff, 0, screensize);
+}
+
+void cDriverG15daemon::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverG15daemon::Refresh(bool refreshAll)
+{
+ g15_send(sockfd, offbuff, screensize);
+}
+
+} // end of namespace
diff --git a/glcddrivers/g15daemon.h b/glcddrivers/g15daemon.h
new file mode 100644
index 0000000..c91ef17
--- /dev/null
+++ b/glcddrivers/g15daemon.h
@@ -0,0 +1,49 @@
+/*
+ * GraphLCD driver library
+ *
+ * g15daemon.h - pseudo device for the g15daemon
+ * Output goes to the g15daemon which then displays it
+ *
+ */
+
+#ifndef _GLCDDRIVERS_G15DAEMON_H_
+#define _GLCDDRIVERS_G15DAEMON_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverG15daemon : public cDriver
+{
+private:
+ unsigned char ** LCD;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ char *offbuff;
+ int sockfd;
+ long int screensize;
+ char *fbp;
+ int zoom;
+
+ int CheckSetup();
+ void SetPixel(int x, int y);
+
+public:
+ cDriverG15daemon(cDriverConfig * config);
+ virtual ~cDriverG15daemon();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/gu126x64D-K610A4.c b/glcddrivers/gu126x64D-K610A4.c
new file mode 100644
index 0000000..e927f49
--- /dev/null
+++ b/glcddrivers/gu126x64D-K610A4.c
@@ -0,0 +1,967 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu126x64D-K610A4.c - 8-bit driver module for Noritake GU126x64D-K610A4 VFD
+ * displays. The VFD is operating in its 8 bit-mode
+ * connected to a single PC parallel port.
+ *
+ * based on:
+ * gu256x64-372 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ * gu256x64-3900 driver module for graphlcd
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * gu140x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * ks0108 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ */
+
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "gu126x64D-K610A4.h"
+#include "port.h"
+
+namespace GLCD
+{
+//----- commands to the display -----------------------------------------------
+static const unsigned char CMD_RUN_MACRO_01 = 0x01; // run macro 1
+static const unsigned char CMD_RUN_MACRO_02 = 0x02; // run macro 2
+static const unsigned char CMD_RUN_MACRO_03 = 0x03; // run macro 3
+static const unsigned char CMD_RUN_MACRO_04 = 0x04; // run macro 4
+static const unsigned char CMD_RUN_MACRO_05 = 0x05; // run macro 5
+static const unsigned char CMD_RUN_MACRO_06 = 0x06; // run macro 6
+static const unsigned char CMD_RUN_MACRO_07 = 0x07; // run macro 7
+
+static const unsigned char CMD_CURSOR_POS = 0x10; // Set cursor position
+static const unsigned char CMD_BOX_SET = 0x11; // Set area
+static const unsigned char CMD_BOX_CLEAR = 0x12; // Clear area
+static const unsigned char CMD_BOX_INVERT = 0x13; // Invert area
+static const unsigned char CMD_RECT_SET = 0x14; // Set outline
+static const unsigned char CMD_RECT_CLEAR = 0x15; // Clear outline
+
+static const unsigned char CMD_PIXEL_SET = 0x16; // Set pixel at current pos
+static const unsigned char CMD_PIXEL_CLEAR = 0x17; // Clear pixel at current pos
+
+static const unsigned char CMD_GRAPHIC_WRITE = 0x18; // Write graphics data (args: len, data)
+static const unsigned char CMD_RESET = 0x19; // Reset display
+static const unsigned char CMD_WRITE_MODE = 0x1A; // Write mode
+static const unsigned char CMD_INTRO = 0x1B; // Intro for other commands (see CMA_*)
+static const unsigned char CMD_FONT_PROP_SML = 0x1C; // Select font: proportional mini
+static const unsigned char CMD_FONT_FIX_MED = 0x1D; // Select font: fixed spaced 5x7
+static const unsigned char CMD_FONT_FIX_BIG = 0x1E; // Select font: fixed spaced 10x14
+
+static const unsigned char CMA_MACROS_ERASE = 0x4D; // Erase Macros (usage: CMD_INTRO + this)
+static const unsigned char CMA_EPROM_LOCK = 0x4C; // Lock EEPROM (usage: CMD_INTRO + this)
+static const unsigned char CMA_EPROM_UNLOCK = 0x55; // Unlock EEPROM (usage: CMD_INTRO + this)
+
+static const unsigned char CMA_POWER_OFF = 0x46; // Power off (usage: CMD_INTRO + this)
+static const unsigned char CMA_POWER_ON = 0x50; // Power on (usage: CMD_INTRO + this)
+
+//----- signal lines ----------------------------------------------------------
+static const unsigned char OUT_EN_HI = kAutoLow ;
+static const unsigned char OUT_EN_LO = kAutoHigh;
+static const unsigned char OUT_EN_MASK = OUT_EN_HI;
+
+static const unsigned char IN_MB_HI = 0x40;
+static const unsigned char IN_MB_LO = 0x00;
+static const unsigned char IN_MB_MASK = IN_MB_HI;
+
+//----- log flags -------------------------------------------------------------
+static const unsigned int LL_REFRESH_START = 0x0001; // 1
+static const unsigned int LL_REFRESH_END = 0x0002; // 2
+static const unsigned int LL_REFRESH_MED = 0x0004; // 4
+static const unsigned int LL_VFD_CMD = 0x0008; // 8
+static const unsigned int LL_MAX_WAIT = 0x0010; // 16
+
+//----- mixed consts ----------------------------------------------------------
+static const long ADJUST_FACTOR = 100; // used to adjust timing
+
+//-----------------------------------------------------------------------------
+cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4(cDriverConfig * config)
+ : port (0)
+ , config (config)
+ , oldConfig (0)
+ , myNumRows (0)
+ , myDrawMem (0)
+ , myVFDMem (0)
+ , myUseSleepInit (false)
+ , myPortDelayNS (0)
+ , myDelay125NS (0)
+ , myRefreshCounter (0)
+ , myClaimCounter (0)
+ , myDataPendingCounter(0)
+ , myLogFlags (0)
+{
+ oldConfig = new cDriverConfig(*config);
+} // cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4()
+
+//-----------------------------------------------------------------------------
+cDriverGU126X64D_K610A4::~cDriverGU126X64D_K610A4()
+{
+ delete oldConfig;
+} // cDriverGU126X64D_K610A4::cDriverGU126X64D_K610A4()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::Init()
+{
+ width = config->width;
+ if (width <= 0 || width > 256) // don't allow unreasonable big sizes from config
+ {
+ width = 126;
+ } // if
+
+ height = config->height;
+ if (height <= 0 || height > 256) // don't allow unreasonable big sizes from config
+ {
+ height = 64;
+ } // if
+
+ //----- parse config -----
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Debug")
+ {
+ myLogFlags = atoi(config->options[i].value.c_str());
+ } // if
+ } // for
+
+ myNumRows = ((height + 7) / 8);
+ port = new cParallelPort();
+
+ // setup drawing memory
+ myDrawMem = new unsigned char *[width];
+ for (int x = 0; x < width; x++)
+ {
+ myDrawMem[x] = new unsigned char[myNumRows];
+ memset(myDrawMem[x], 0, myNumRows);
+ } // for
+
+ // setup vfd memory
+ myVFDMem = new unsigned char *[width];
+ for (int x = 0; x < width; x++)
+ {
+ myVFDMem[x] = new unsigned char[myNumRows];
+ memset(myVFDMem[x], 0, myNumRows);
+ } // for
+
+ if (initParallelPort() < 0)
+ {
+ return -1;
+ } // if
+
+ initDisplay();
+
+ *oldConfig = *config;
+
+ // Set Display SetBrightness
+ SetBrightness(config->brightness);
+
+ // clear display
+ Clear();
+ clearVFDMem();
+
+ syslog( LOG_INFO, "%s: initialized (width: %d height: %d)"
+ , config->name.c_str(), width, height
+ );
+
+ return 0;
+} // cDriverGU126X64D_K610A4::Init()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::DeInit()
+{
+ if (myVFDMem)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ delete[] myVFDMem[x];
+ } // for
+ delete[] myVFDMem;
+ myVFDMem = 0;
+ } // if
+
+ if (myDrawMem)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ delete[] myDrawMem[x];
+ } // for
+ delete[] myDrawMem;
+ myDrawMem = 0;
+ } // if
+
+ if (port)
+ {
+ // claim port to avoid msg when closing the port
+ port->Claim();
+ if (port->Close() != 0)
+ {
+ return -1;
+ } // if
+ delete port;
+ port = 0;
+ } // if
+
+ return 0;
+} // cDriverGU126X64D_K610A4::DeInit()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::checkSetup()
+{
+ if ( config->device != oldConfig->device
+ || config->port != oldConfig->port
+ || config->width != oldConfig->width
+ || config->height != oldConfig->height
+ )
+ {
+ DeInit();
+ Init();
+ return 0;
+ } // if
+
+ if (config->brightness != oldConfig->brightness)
+ {
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
+ } // if
+
+ if ( config->upsideDown != oldConfig->upsideDown
+ || config->invert != oldConfig->invert
+ )
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+
+ return 1;
+ } // if
+
+ return 0;
+} // cDriverGU126X64D_K610A4::checkSetup()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::initParallelPort()
+{
+ struct timeval tv1, tv2;
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!", config->name.c_str());
+ return -1;
+ } // if
+ syslog(LOG_INFO, "%s: using direct IO!", config->name.c_str());
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!", config->name.c_str());
+ return -1;
+ } // if
+ syslog(LOG_INFO, "%s: using ppdev!", config->name.c_str());
+ } // if
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)", config->name.c_str(), strerror(errno));
+ myUseSleepInit = false;
+ }
+ else
+ {
+ myUseSleepInit = true;
+ } // if
+
+ //----- measure the time to write to the port -----
+ syslog(LOG_DEBUG, "%s: benchmark started.", config->name.c_str());
+ gettimeofday(&tv1, 0);
+
+ const int aBenchCount = 1000; // don't change this!
+ for (int x = 0; x < aBenchCount; x++)
+ {
+ port->WriteData(x % 0x100);
+ } // for
+
+ gettimeofday(&tv2, 0);
+
+ // release the port, which was implicitely claimed by open
+ port->Release();
+
+ if (myUseSleepInit) nSleepDeInit();
+
+ myPortDelayNS = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+
+ myDelay125NS = std::max(125 + (ADJUST_FACTOR * config->adjustTiming) - myPortDelayNS, 0L);
+
+ syslog( LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns, delay: %ldns"
+ , config->name.c_str(), myPortDelayNS, myDelay125NS
+ );
+
+ return 0;
+} // cDriverGU126X64D_K610A4::initParallelPort()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::initDisplay()
+{
+ claimPort();
+ cmdReset();
+ releasePort();
+} // cDriverGU126X64D_K610A4::initDisplay()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::clearVFDMem()
+{
+ for (int x = 0; x < width; x++)
+ {
+ memset(myVFDMem[x], 0, myNumRows);
+ } // for
+} // cDriverGU126X64D_K610A4::clearVFDMem()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::Clear()
+{
+ for (int x = 0; x < width; x++)
+ {
+ memset(myDrawMem[x], 0, myNumRows);
+ } // for
+} // cDriverGU126X64D_K610A4::Clear()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::SetBrightness(unsigned int percent)
+{
+ claimPort();
+ cmdSetBrightness(percent);
+ releasePort();
+} // cDriverGU126X64D_K610A4::SetBrightness()
+
+//-----------------------------------------------------------------------------
+bool cDriverGU126X64D_K610A4::waitForStatus(unsigned char theMask, unsigned char theValue, int theMaxWait)
+{
+ theValue = theValue & theMask;
+
+ int status = port->ReadStatus();
+
+ if ((status & theMask) != theValue)
+ {
+ // wait some time for MB go HI/LO but not forever
+ int i = 0;
+ for(i = 0; ((status & theMask) != theValue) && i < theMaxWait; i++)
+ {
+ status = port->ReadStatus();
+ } // for
+
+ if (isLogEnabled(LL_MAX_WAIT) && i >= theMaxWait)
+ {
+ syslog( LOG_INFO, "%s: slept for %5d times while waiting for MB = %d"
+ , config->name.c_str(), i, ((theMask & theValue) == 0 ? 0 : 1)
+ );
+ } //
+ } // if
+
+ return ((status & theMask) == theValue);
+} // cDriverGU126X64D_K610A4::waitForStatus()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::writeParallel(unsigned char data)
+{
+ if (myUseSleepInit) nSleepInit();
+
+ waitForStatus(IN_MB_MASK, IN_MB_LO, 500); // wait for MB == LO
+
+ port->WriteData(data); // write data
+ nSleep(myDelay125NS); // - sleep
+
+ port->WriteControl(OUT_EN_LO & OUT_EN_MASK); // set ENABLE to LO
+ nSleep(myDelay125NS); // - sleep
+
+ port->WriteControl(OUT_EN_HI & OUT_EN_MASK); // set ENABLE to HI
+
+ waitForStatus(IN_MB_MASK, IN_MB_HI, 50); // wait for MB == HI
+
+// the other drivers don't do this neither
+// if (myUseSleepInit) nSleepDeInit();
+} // cDriverGU126X64D_K610A4::writeParallel()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::write(unsigned char data)
+{
+ int b = 0;
+
+ writeParallel(data);
+ ++b;
+
+ // if data == 0x60 -> send 0x60 twice
+ // (0x60 switches to hex-mode)
+ if (data == 0x60)
+ {
+ writeParallel(data);
+ ++b;
+ } // if
+
+ return b;
+} // cDriverGU126X64D_K610A4::write()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::setPixel(int x, int y)
+{
+ if (!myDrawMem ) return;
+ if (x >= width || x < 0) return;
+ if (y >= height || y < 0) return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ } // if
+
+ unsigned char c = 0x80 >> (y % 8);
+
+ myDrawMem[x][y/8] = myDrawMem[x][y/8] | c;
+} // cDriverGU126X64D_K610A4::setPixel()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::Set8Pixels(int x, int y, unsigned char data)
+{
+ // x - pos isn't maybe align to 8
+ x &= 0xFFF8;
+
+ for (int n = 0; n < 8; ++n)
+ {
+ if ((data & (0x80 >> n)) != 0) // if bit is set
+ {
+ setPixel(x + n, y);
+ } // if
+ } // for
+} // cDriverGU126X64D_K610A4::Set8Pixels()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::Refresh(bool refreshAll)
+{
+ // no mem present -> return
+ if (!myVFDMem || !myDrawMem)
+ {
+ return;
+ } // if
+
+ // create log
+ if (isLogEnabled(LL_REFRESH_START))
+ {
+ syslog( LOG_INFO, "%s: > Refresh() all = %d RefreshDisplay = %d RefreshCtr = %d Delay = %ld"
+ , config->name.c_str()
+ , refreshAll
+ , config->refreshDisplay
+ , myRefreshCounter
+ , myDelay125NS
+ );
+ } // if
+
+ // setup changed -> refresh all
+ if (checkSetup() > 0)
+ {
+ syslog(LOG_DEBUG, "%s: Refresh() checkSetup() returned != 0 -> refreshAll = true", config->name.c_str());
+ refreshAll = true;
+ } // if
+
+ // refresh-counter exceeded -> refresh all
+ if (!refreshAll && config->refreshDisplay != 0)
+ {
+ myRefreshCounter = (myRefreshCounter + 1) % config->refreshDisplay;
+ refreshAll = myRefreshCounter == 0;
+
+ if (refreshAll && isLogEnabled(LL_REFRESH_START))
+ {
+ syslog(LOG_DEBUG, "%s: Refresh() refresh-count reached -> refreshAll = true", config->name.c_str());
+ } // if
+ } // if
+
+ if (isLogEnabled(LL_REFRESH_START))
+ {
+ syslog( LOG_INFO, "%s: Refresh() all = %d RefreshDisplay = %d RefreshCtr = %d Delay = %ld"
+ , config->name.c_str()
+ , refreshAll
+ , config->refreshDisplay
+ , myRefreshCounter
+ , myDelay125NS
+ );
+ } // if
+
+ // time for logs
+ struct timeval tv1, tv2;
+ gettimeofday(&tv1, 0);
+
+ claimPort();
+
+ int chunk = 128; // displays with more than 128 pixels width are written in chunks
+ // note: this driver isn't really prepared to handle displays
+ // with other dimensions than 126x64
+ int xb = 0;
+ int yb = 0;
+ long bc = 0;
+
+ for (yb = 0; yb < myNumRows; ++yb)
+ {
+ int minX = width;
+ int maxX = 0;
+
+ //----- if !refreshAll -> check modified bytes
+ if (!refreshAll)
+ {
+ for (xb = 0; xb < width; ++xb)
+ {
+ if (myVFDMem[xb][yb] != myDrawMem[xb][yb])
+ {
+ minX = std::min(minX, xb);
+ maxX = std::max(maxX, xb);
+ } // if
+ } // for
+ }
+ else
+ {
+ minX = 0;
+ maxX = width - 1;
+ } // if
+
+ // create log
+ if (isLogEnabled(LL_REFRESH_MED))
+ {
+ if (minX <= maxX)
+ {
+ syslog( LOG_INFO, "%s: Row[%d] %3d - %3d : %3d"
+ , config->name.c_str(), yb
+ , minX, maxX
+ , maxX - minX + 1
+ );
+ }
+ else
+ {
+ syslog( LOG_INFO, "%s: Row[%d] --- - --- : ---"
+ , config->name.c_str(), yb
+ );
+ } // if
+ } // if
+
+ // perform refresh
+ if (minX <= maxX)
+ {
+ bc += cmdSetCursorPos(minX, yb * 8);
+
+ for (xb = minX; xb <= maxX; ++xb)
+ {
+ if ((xb - minX) % chunk == 0)
+ {
+ bc += cmdGraphicWrite(std::min((maxX - xb + 1), chunk));
+ } // if
+
+ bc += cmdGraphicData(myDrawMem[xb][yb]);
+ myVFDMem[xb][yb] = myDrawMem[xb][yb];
+ } // for
+ } // if
+ } // for
+
+ releasePort();
+
+ // create log
+ if (isLogEnabled(LL_REFRESH_END))
+ {
+ gettimeofday(&tv2, 0);
+
+ long duration_ms = ((tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec))
+ / 1000 /* us -> ms */
+ ;
+
+ syslog( LOG_INFO, "%s: < Refresh() all = %d took %3ld ms %5ld bytes = %5ld bytes/sec = %5ld ns/byte"
+ , config->name.c_str()
+ , refreshAll
+ , duration_ms
+ , bc
+ , duration_ms == 0 ? -1 : bc * 1000 / duration_ms
+ , bc == 0 ? -1 : duration_ms * 1000000 / bc
+ );
+ } // if
+} // cDriverGU126X64D_K610A4::Refresh()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdReset()
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: CMD_RESET : 0x%02X ", int(CMD_RESET));
+ } // if
+
+ b += write(CMD_RESET);
+
+ unsigned char aMode = 1 << 7 // data orientation : 0: horizontal, 1: vertical , default: 0
+ | 0 << 6 // cursor movement : 0: horizontal, 1: vertical , default: 0
+ | 0 << 5 // cursor direction : 0: forwards , 1: backwards, default: 0
+ | 0 << 4 // underscore cursor: 0: off , 1: on , default: 0
+ | 0 << 3 // underscore cursor: 0: static , 1: flash , default: 0
+ | 0 << 2 // not in documentation
+ | 0 << 0 // pen type: 0: overwrite, 1: AND, 2: OR, 3: XOR , default: 0
+ ;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 2B: CMD_WRITE_MODE : 0x%02X 0x%02X", int(CMD_RESET), int(aMode));
+ } // if
+
+ b += write(CMD_WRITE_MODE);
+ b += write(aMode);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdReset()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdPower(bool fOn)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_POWER : 0x%02X 0x%02X"
+ , int(CMD_INTRO), int(fOn ? CMA_POWER_ON : CMA_POWER_OFF)
+ );
+ } // if
+
+ b += write(CMD_INTRO);
+ b += write(fOn ? CMA_POWER_ON : CMA_POWER_OFF);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdPower()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdLock(bool fLock)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_LOCK : 0x%02X 0x%02X"
+ , int(CMD_INTRO), int(fLock ? CMA_EPROM_LOCK : CMA_EPROM_UNLOCK)
+ );
+ } // if
+
+ b += write(CMD_INTRO);
+ b += write(fLock ? CMA_EPROM_LOCK : CMA_EPROM_UNLOCK);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdPower()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetCursorPos(unsigned char x, unsigned char y)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 3B: CMD_CURSOR_POS : 0x%02X 0x%02X 0x%02X (x = %3d, y = %3d)"
+ , int(CMD_CURSOR_POS), int(x), int(y), int(x), int(y)
+ );
+ } // if
+
+ b += write(CMD_CURSOR_POS); // cmd
+ b += write(x ); // xpos
+ b += write(y ); // ypos
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetCursorPos();
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdGraphicWrite(unsigned char count)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_GRAPHIC_WRITE: 0x%02X 0x%02X (%d bytes)"
+ , int(CMD_GRAPHIC_WRITE), int(count), int(count)
+ );
+ } // if
+
+ b += write(CMD_GRAPHIC_WRITE); // cmd
+ b += write(count ); // len
+
+ myDataPendingCounter = count;
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdGraphicWrite()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdGraphicData(unsigned char data)
+{
+ int b = 0;
+
+ myDataPendingCounter--;
+ if (myDataPendingCounter < 0)
+ {
+ syslog( LOG_WARNING, "%s error: more graphic data written than announced -> ignored"
+ , config->name.c_str()
+ );
+ }
+ else
+ {
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 1B: CMD_GRAPHIC_DATA : 0x%02X (expecting another %d bytes)"
+ , int(data), myDataPendingCounter
+ );
+ } // if
+
+ b += write(data ^ (config->invert ? 0xFF : 0x00));
+ } // if
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdGraphicData()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetBrightness(unsigned int percent)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ unsigned char bright = 0;
+ if (percent >= 85) bright = 0xFF;
+ else if (percent >= 71) bright = 0xFE;
+ else if (percent >= 57) bright = 0xFD;
+ else if (percent >= 43) bright = 0xFC;
+ else if (percent >= 29) bright = 0xFB;
+ else if (percent >= 15) bright = 0xFA;
+ else if (percent >= 1) bright = 0xF9;
+ else bright = 0xF8;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 2B: CMD_INTRO : 0x%02X 0x%02X = set brightness"
+ , int(CMD_INTRO), int(bright)
+ );
+ } // if
+
+ b += write(CMD_INTRO);
+ b += write(bright);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetBrightness()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetFont(FontType theFont)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ unsigned char aCmd = 0;
+ switch (theFont)
+ {
+ case FONT_PROP_SML: aCmd = CMD_FONT_PROP_SML; break;
+ case FONT_FIX_BIG : aCmd = CMD_FONT_FIX_BIG ; break;
+ case FONT_FIX_MED :
+ default : aCmd = CMD_FONT_FIX_MED ; break;
+ } // switch
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: CMD_SET_FONT : 0x%02X", int(aCmd));
+ } // if
+
+ b += write(aCmd);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetFont()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdWriteText(const char *theText)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "-%2dB: WRITE_TEXT : '%s'", strlen(theText), theText);
+ } // if
+
+ for (const char *p = theText; *p != '\0'; ++p)
+ {
+ b += write(*p);
+ } // for
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdWriteText()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdDrawRect(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2)
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 5B: CMD_SET_OUTLINE : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X (x1 = %3d, y1 = %3d, x2 = %3d, y2 = %3d)"
+ , int(CMD_CURSOR_POS)
+ , int(x1), int(y1), int(x2), int(y2)
+ , int(x1), int(y1), int(x2), int(y2)
+ );
+ } // if
+
+ b += write(CMD_RECT_SET );
+ b += write(x1 );
+ b += write(y1 );
+ b += write(x2 );
+ b += write(y2 );
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdDrawRect()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetMacro(unsigned char theMacroNum, unsigned char theCountBytes)
+{
+ if (theMacroNum > 7)
+ {
+ return 0;
+ } // if
+
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog( LOG_INFO, "- 3B: CMD_INTRO : 0x%02X 0x%02X 0x%02X (define macro %d with length %d)"
+ , int(CMD_INTRO)
+ , int(theMacroNum), int(theCountBytes)
+ , int(theMacroNum), int(theCountBytes)
+ );
+ } // if
+
+ b += write(CMD_INTRO );
+ b += write(theMacroNum );
+ b += write(theCountBytes );
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetMacro()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdSetPixel(bool fSet)
+{
+ int b = 0;
+
+ if (fSet)
+ {
+ ensureNotInGraphics();
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: SET_PIXEL : 0x%02X", 0x16);
+ } // if
+
+ b += write(CMD_PIXEL_SET);
+ }
+ else
+ {
+ b = cmdClrPixel();
+ } // if
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdSetPixel()
+
+//-----------------------------------------------------------------------------
+int cDriverGU126X64D_K610A4::cmdClrPixel()
+{
+ ensureNotInGraphics();
+ int b = 0;
+
+ if (isLogEnabled(LL_VFD_CMD))
+ {
+ syslog(LOG_INFO, "- 1B: CLR_PIXEL : 0x%02X", 0x17);
+ } // if
+
+ b += write(CMD_PIXEL_CLEAR);
+
+ return b;
+} // cDriverGU126X64D_K610A4::cmdClrPixel()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::ensureNotInGraphics()
+{
+ if (myClaimCounter <= 0)
+ {
+ syslog(LOG_ERR, "%s: ERROR: port not claimed (%d)", config->name.c_str(), myClaimCounter);
+ } // if
+
+ if (myDataPendingCounter > 0)
+ {
+ syslog( LOG_WARNING, "%s error: expected another %d bytes graphic data, filling with 0x00"
+ , config->name.c_str(), myDataPendingCounter
+ );
+ } // if
+ while (myDataPendingCounter > 0)
+ {
+ cmdGraphicData(0);
+ } // while
+} // cDriverGU126X64D_K610A4::ensureNotInGraphics()
+
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::claimPort()
+{
+ if (myClaimCounter == 0)
+ {
+ port->Claim();
+ } // if
+
+ myClaimCounter++;
+
+ if (myClaimCounter > 1)
+ {
+ syslog( LOG_WARNING, "%s: port claimed more than once (%d)"
+ , config->name.c_str(), myClaimCounter
+ );
+ } // if
+
+} // cDriverGU126X64D_K610A4::claimPort()
+
+//-----------------------------------------------------------------------------
+void cDriverGU126X64D_K610A4::releasePort()
+{
+ if (myClaimCounter == 1)
+ {
+ port->Release();
+ } // if
+
+ myClaimCounter--;
+
+ if (myClaimCounter < 0)
+ {
+ syslog( LOG_WARNING, "%s: port released more often than claimed"
+ , config->name.c_str()
+ );
+ myClaimCounter = 0;
+ } // if
+
+} // cDriverGU126X64D_K610A4::releasePort()
+
+//-----------------------------------------------------------------------------
+bool cDriverGU126X64D_K610A4::isLogEnabled(int theLevel) const
+{
+ return (theLevel & myLogFlags) != 0;
+} // cDriverGU126X64D_K610A4::isLogEnabled()
+
+//-----------------------------------------------------------------------------
+} // end of namespace
+
diff --git a/glcddrivers/gu126x64D-K610A4.h b/glcddrivers/gu126x64D-K610A4.h
new file mode 100644
index 0000000..3d6c29c
--- /dev/null
+++ b/glcddrivers/gu126x64D-K610A4.h
@@ -0,0 +1,130 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu126x64D-K610A4.h - 8-bit driver module for Noritake GU126x64D-K610A4 VFD
+ * displays. The VFD is operating in its 8 bit-mode
+ * connected to a single PC parallel port.
+ *
+ * based on:
+ * gu256x64-372 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ * gu256x64-3900 driver module for graphlcd
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ * gu140x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * ks0108 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ */
+
+#ifndef _GLCDDRIVERS_GU126X64D_K610A4_H_
+#define _GLCDDRIVERS_GU126X64D_K610A4_H_
+
+#include "driver.h"
+
+//===============================================================================
+// namespace GLCD
+//===============================================================================
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+//===============================================================================
+// class cDriverGU126X64D_K610A4
+//===============================================================================
+class cDriverGU126X64D_K610A4 : public cDriver
+{
+public:
+ //---------------------------------------------------------------------------
+ // constructor/destructor
+ //---------------------------------------------------------------------------
+ cDriverGU126X64D_K610A4(cDriverConfig * config);
+ virtual ~cDriverGU126X64D_K610A4();
+
+ //---------------------------------------------------------------------------
+ // from cDriver
+ //---------------------------------------------------------------------------
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+ virtual void SetBrightness(unsigned int percent);
+
+ //---------------------------------------------------------------------------
+ // display-specific enums/methods/etc.
+ //---------------------------------------------------------------------------
+ enum FontType
+ {
+ FONT_PROP_SML
+ , FONT_FIX_MED
+ , FONT_FIX_BIG
+ };
+
+ void setPixel (int x, int y);
+
+ int cmdReset ();
+ int cmdPower (bool fOn);
+ int cmdLock (bool fLock);
+ int cmdSetCursorPos (unsigned char x, unsigned char y);
+ int cmdGraphicWrite (unsigned char count);
+ int cmdGraphicData (unsigned char data);
+ int cmdSetBrightness(unsigned int percent);
+ int cmdSetFont (FontType);
+ int cmdWriteText (const char *theText);
+ int cmdDrawRect (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2);
+ int cmdSetMacro (unsigned char theMacroNum, unsigned char theCountBytes);
+ int cmdSetPixel (bool fSet = true);
+ int cmdClrPixel ();
+
+ void claimPort();
+ void releasePort();
+
+private:
+ //---------------------------------------------------------------------------
+ // helper methods
+ //---------------------------------------------------------------------------
+ void clearVFDMem();
+ int checkSetup();
+ int initParallelPort();
+ void initDisplay();
+
+ bool waitForStatus(unsigned char theMask, unsigned char theValue, int theMaxWait);
+ void writeParallel(unsigned char data);
+ int write(unsigned char data);
+
+ void ensureNotInGraphics();
+ bool isLogEnabled(int theLevel) const;
+
+ //---------------------------------------------------------------------------
+ // attributes
+ //---------------------------------------------------------------------------
+ cParallelPort *port;
+
+ cDriverConfig *config;
+ cDriverConfig *oldConfig;
+
+ int myNumRows;
+ unsigned char **myDrawMem;
+ unsigned char **myVFDMem;
+
+ bool myUseSleepInit;
+ long myPortDelayNS;
+ long myDelay125NS;
+ int myRefreshCounter;
+ int myClaimCounter;
+ int myDataPendingCounter;
+ unsigned int myLogFlags;
+
+}; // class cDriverGU126X64D_K610A4
+
+} // namespace GLCD
+
+#endif
diff --git a/glcddrivers/gu140x32f.c b/glcddrivers/gu140x32f.c
new file mode 100644
index 0000000..212b381
--- /dev/null
+++ b/glcddrivers/gu140x32f.c
@@ -0,0 +1,443 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu140x32f.c - 8-bit driver module for Noritake GU140x32-F7806 VFD
+ * displays. The VFD is operating in its 8 bit-mode
+ * connected to a single PC parallel port.
+ *
+ * based on:
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT Comports com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ */
+
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "gu140x32f.h"
+#include "port.h"
+
+
+namespace GLCD
+{
+
+// Defines for hd44780 Displays
+#define RS_DAT 0x00
+#define RS_CMD 0x01
+
+#define CLEAR 0x01
+
+#define HOMECURSOR 0x02
+
+#define ENTRYMODE 0x04
+#define E_MOVERIGHT 0x02
+#define E_MOVELEFT 0x00
+#define EDGESCROLL 0x01
+#define NOSCROLL 0x00
+
+#define ONOFFCTRL 0x08
+#define DISPON 0x04
+#define DISPOFF 0x00
+#define CURSORON 0x02
+#define CURSOROFF 0x00
+#define CURSORBLINK 0x01
+#define CURSORNOBLINK 0x00
+
+#define CURSORSHIFT 0x10
+#define SCROLLDISP 0x08
+#define MOVECURSOR 0x00
+#define MOVERIGHT 0x04
+#define MOVELEFT 0x00
+
+#define FUNCSET 0x20
+#define IF_8BIT 0x10
+#define IF_4BIT 0x00
+
+// Control output lines
+// Write to baseaddress+2
+#define nSTRB 0x01 // pin 1; negative logic
+#define nLF 0x02 // pin 14
+#define nINIT 0x04 // pin 16; the only positive logic output line
+#define nSEL 0x08 // pin 17
+#define ENIRQ 0x10 // Enable IRQ via ACK line (don't enable this withouT
+ // setting up interrupt stuff too)
+#define ENBI 0x20 // Enable bi-directional port (is nice to play with!
+ // I first didn't know a SPP could do this)
+
+#define OUTMASK 0x0B // SEL, LF and STRB are hardware inverted
+ // Use this mask only for the control output lines
+ // XOR with this mask ( ^ OUTMASK )
+
+static const std::string kWiringStandard = "Standard";
+static const std::string kWiringWindows = "Windows";
+
+// standard wiring
+// #define RS nSTRB
+// #define RW nLF
+// #define EN1 nINIT
+// #define BL nSEL
+
+// windows wiring
+// #define RS nINIT
+// #define RW nLF
+// #define EN1 nSTRB
+// #define BL nSEL
+
+
+cDriverGU140X32F::cDriverGU140X32F(cDriverConfig * config)
+: config(config),
+ m_pDrawMem(0),
+ m_pVFDMem(0)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ m_nRefreshCounter = 0;
+}
+
+cDriverGU140X32F::~cDriverGU140X32F()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverGU140X32F::Init()
+{
+ int x;
+ struct timeval tv1, tv2;
+
+ // default values
+ width = config->width;
+ if (width <= 0)
+ width = 140;
+ height = config->height;
+ if (height <= 0)
+ height = 32;
+ m_iSizeYb = ((height + 7) / 8); // 4
+ m_WiringRS = nSTRB;
+ m_WiringEN1 = nINIT;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Wiring")
+ {
+ if (config->options[i].value == kWiringStandard)
+ {
+ m_WiringRS = nSTRB;
+ m_WiringEN1 = nINIT;
+ }
+ else if (config->options[i].value == kWiringWindows)
+ {
+ m_WiringRS = nINIT;
+ m_WiringEN1 = nSTRB;
+ }
+ else
+ syslog(LOG_ERR, "%s error: wiring %s not supported, using default (Standard)!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
+ }
+
+ // setup the memory array for the drawing array gu140x32f
+ m_pDrawMem = new unsigned char[width * m_iSizeYb];
+ Clear();
+
+ // setup the memory array for the display array gu140x32f
+ m_pVFDMem = new unsigned char[width * m_iSizeYb];
+ ClearVFDMem();
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)\n", config->name.c_str(), strerror(errno));
+ m_bSleepIsInit = false;
+ }
+ else
+ {
+ m_bSleepIsInit = true;
+ }
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (x = 0; x < 10000; x++)
+ {
+ port->WriteData(x % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ nSleepDeInit();
+ m_nTimingAdjustCmd = ((tv2.tv_sec - tv1.tv_sec) * 10000 + (tv2.tv_usec - tv1.tv_usec)) / 1000;
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", config->name.c_str(), m_nTimingAdjustCmd);
+
+
+ // setup the lcd in 8 bit mode
+ Write(RS_CMD, FUNCSET | IF_8BIT, 4100);
+ Write(RS_CMD, FUNCSET | IF_8BIT, 100);
+ Write(RS_CMD, FUNCSET | IF_8BIT, 40);
+
+ Write(RS_CMD, ONOFFCTRL | DISPON | CURSOROFF | CURSORNOBLINK, 40);
+ Write(RS_CMD, CLEAR, 1600);
+ Write(RS_CMD, HOMECURSOR, 1600);
+
+ port->Release();
+
+ *oldConfig = *config;
+
+ // Set Display SetBrightness
+ SetBrightness(config->brightness);
+ // clear display
+ ClearVFDMem();
+ Clear();
+
+ syslog(LOG_INFO, "%s: gu140x32f initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverGU140X32F::DeInit()
+{
+ if (m_pVFDMem)
+ delete[] m_pVFDMem;
+ if (m_pDrawMem)
+ delete[] m_pDrawMem;
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverGU140X32F::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->brightness != oldConfig->brightness)
+ {
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverGU140X32F::ClearVFDMem()
+{
+ for (int n = 0; m_pVFDMem && n < (width * m_iSizeYb); n++)
+ m_pVFDMem[n] = 0x00;
+}
+
+void cDriverGU140X32F::Clear()
+{
+ for (int n = 0; m_pDrawMem && n < (width * m_iSizeYb); n++)
+ m_pDrawMem[n] = 0x00;
+}
+
+void cDriverGU140X32F::SetBrightness(unsigned int percent)
+{
+ port->Claim();
+
+ unsigned char level;
+ if (percent > 100)
+ percent = 100;
+ level = percent / 25;
+ if (level < 1)
+ level = 1;
+ level = (4 - level) & 0x03;
+ // Set Brightness
+ // 00 - 100%
+ // 01 - 75%
+ // 02 - 50%
+ // 03 - 25%
+ Write(RS_CMD, FUNCSET | IF_8BIT, 40);
+ Write(RS_DAT, level, 40);
+
+ port->Release();
+}
+
+void cDriverGU140X32F::Write(unsigned char nFlags, unsigned char bData, unsigned int nMicroSecBusyTime)
+{
+ if (m_bSleepIsInit)
+ nSleepInit();
+
+ unsigned char enableLines = 0, portControl;
+
+ // Only one controller is supported
+ enableLines = m_WiringEN1;
+
+ if (nFlags == RS_CMD)
+ portControl = 0;
+ else // if (nFlags == RS_DAT)
+ portControl = m_WiringRS;
+
+ // portControl |= m_WiringBL;
+
+ port->WriteControl(portControl ^ OUTMASK); //Reset controlbits
+ port->WriteData(bData); //Set data
+ port->WriteControl((enableLines | portControl) ^ OUTMASK); //Set controlbits
+
+ // How long hold the data active
+ if (m_bSleepIsInit && (25 + (100 * config->adjustTiming) - m_nTimingAdjustCmd > 0))
+ {
+ // Wait 50ns
+ nSleep(std::max(25L, 50 + (100 * config->adjustTiming) - m_nTimingAdjustCmd));
+ }
+
+ port->WriteControl(portControl ^ OUTMASK); //Reset controlbits
+
+ nSleep((nMicroSecBusyTime * 1000) + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+
+ if (m_bSleepIsInit)
+ nSleepDeInit();
+}
+
+void cDriverGU140X32F::SetPixel(int x, int y)
+{
+ unsigned char c;
+ int n;
+
+ if (!m_pDrawMem)
+ return;
+
+ if (x >= width || x < 0)
+ return;
+ if (y >= height || y < 0)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ n = x + ((y / 8) * width);
+ c = 0x80 >> (y % 8);
+
+ m_pDrawMem[n] |= c;
+}
+
+void cDriverGU140X32F::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+
+ // x - pos is'nt mayby align to 8
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverGU140X32F::Refresh(bool refreshAll)
+{
+ int n, x, yb;
+
+ if (!m_pVFDMem || !m_pDrawMem)
+ return;
+
+ bool doRefresh = false;
+ int minX = width;
+ int maxX = 0;
+ int minYb = m_iSizeYb;
+ int maxYb = 0;
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ for (yb = 0; yb < m_iSizeYb; ++yb)
+ for (x = 0; x < width; ++x)
+ {
+ n = x + (yb * width);
+ if (m_pVFDMem[n] != m_pDrawMem[n])
+ {
+ m_pVFDMem[n] = m_pDrawMem[n];
+ minX = std::min(minX, x);
+ maxX = std::max(maxX, x);
+ minYb = std::min(minYb, yb);
+ maxYb = std::max(maxYb, yb + 1);
+ doRefresh = true;
+ }
+ }
+
+ m_nRefreshCounter = (m_nRefreshCounter + 1) % config->refreshDisplay;
+
+ if (!refreshAll && !m_nRefreshCounter)
+ refreshAll = true;
+
+ if (refreshAll || doRefresh)
+ {
+ if (refreshAll)
+ {
+ minX = 0;
+ maxX = width;
+ minYb = 0;
+ maxYb = m_iSizeYb;
+ // and reset RefreshCounter
+ m_nRefreshCounter = 0;
+ }
+
+ minX = std::max(minX, 0);
+ maxX = std::min(maxX, width - 1);
+ minYb = std::max(minYb, 0);
+ maxYb = std::min(maxYb, m_iSizeYb);
+
+ port->Claim();
+ // send lcd data to display, controller
+ Write(RS_CMD, 0xF1, 40);
+ Write(RS_DAT, minX, 40);
+ Write(RS_DAT, (minYb * 8) & 0xFFF8, 40);
+ Write(RS_DAT, maxX, 40);
+ Write(RS_DAT, (maxYb * 8), 40);
+
+ Write(RS_DAT, 'v', 500);
+
+ for (yb = minYb; yb <= maxYb; ++yb)
+ for (x = minX; x <= maxX; ++x)
+ {
+ n = x + (yb * width);
+
+ if (n >= (width * m_iSizeYb))
+ break;
+ Write(RS_DAT, (m_pVFDMem[n]) ^ (config->invert ? 0xff : 0x00), 40);
+ }
+ port->Release();
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/gu140x32f.h b/glcddrivers/gu140x32f.h
new file mode 100644
index 0000000..c0b87f2
--- /dev/null
+++ b/glcddrivers/gu140x32f.h
@@ -0,0 +1,73 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu140x32f.h - 8-bit driver module for Noritake GU140x32-F7806 VFD
+ * displays. The VFD is operating in its 8 bit-mode
+ * connected to a single PC parallel port.
+ *
+ * based on:
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT Comports com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ */
+
+#ifndef _GLCDDRIVERS_GU140X32F_H_
+#define _GLCDDRIVERS_GU140X32F_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+
+class cDriverGU140X32F : public cDriver
+{
+ unsigned char m_WiringRS;
+ unsigned char m_WiringEN1;
+
+ cParallelPort * port;
+
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ int m_iSizeYb;
+ int m_nRefreshCounter;
+ unsigned char *m_pDrawMem; // the draw "memory"
+ unsigned char *m_pVFDMem; // the double buffed display "memory"
+ long m_nTimingAdjustCmd;
+ bool m_bSleepIsInit;
+
+ int CheckSetup();
+
+protected:
+ void ClearVFDMem();
+ void SetPixel(int x, int y);
+ void Write(unsigned char nFlags, unsigned char bData, unsigned int nMicroSecBusyTime);
+
+public:
+ cDriverGU140X32F(cDriverConfig * config);
+ virtual ~cDriverGU140X32F();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/gu256x64-372.c b/glcddrivers/gu256x64-372.c
new file mode 100644
index 0000000..6eb2a4c
--- /dev/null
+++ b/glcddrivers/gu256x64-372.c
@@ -0,0 +1,408 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu256x64-372.c - 8-bit driver module for Noritake GU256x64-372
+ * VFD displays. The VFD is operating in its 8-bit
+ * mode connected to a single PC parallel port.
+ *
+ * based on:
+ * gu256x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT comports.com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ */
+
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "gu256x64-372.h"
+#include "port.h"
+
+
+namespace GLCD
+{
+
+#define SCREENSOFF 0x00 // both screens are off
+#define SCREEN1ON 0x01 // only screen #1 is on (graphic screen)
+#define SCREEN2ON 0x02 // only screen #2 is on (graphic/character screen)
+#define SCREENSON 0x03 // both screens are on
+
+#define CURS_AUTOINC 0x04 // cursor increments automatically
+#define CURS_HOLD 0x05 // cursor holds
+
+#define SCREEN2CHAR 0x06 // screen #2 sets to "character" display
+#define SCREEN2GRAPH 0x07 // screen #2 sets to "graphic" display
+
+#define DATA_WRITE 0x08 // data write mode
+#define DATA_READ 0x09 // data read mode
+
+#define DISP_LOSTA1 0x0A // lower addr. of display start of screen #1
+#define DISP_HISTA1 0x0B // upper addr. of display start of screen #1
+#define DISP_LOSTA2 0x0C // lower addr. of display start of screen #2
+#define DISP_HISTA2 0x0D // upper addr. of display start of screen #2
+#define CURS_LOADDR 0x0E // lower addr. of cursor of screen #1 & #2
+#define CURS_HIADDR 0x0F // upper addr. of cursor start of screen #1 & #2
+
+#define DISP_OR 0x10 // or display of screen #1 & #2
+#define DISP_EXOR 0x11 // ex-or display of screen #1 & #2
+#define DISP_AND 0x12 // and display of screen #1 & #2
+
+#define BRIGHT_1 0x18 // luminance level 1 100.0%
+#define BRIGHT_2 0x19 // luminance level 2 87.5%
+#define BRIGHT_3 0x1A // luminance level 3 75.0%
+#define BRIGHT_4 0x1B // luminance level 4 62.5%
+
+#define WRHI 0x04 // INIT
+#define WRLO 0x00
+#define CDHI 0x00 // nSEL
+#define CDLO 0x08
+
+
+cDriverGU256X64_372::cDriverGU256X64_372(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ m_nRefreshCounter = 0;
+}
+
+cDriverGU256X64_372::~cDriverGU256X64_372()
+{
+ delete oldConfig;
+ delete port;
+}
+
+int cDriverGU256X64_372::Init()
+{
+ int x;
+ struct timeval tv1, tv2;
+
+ width = config->width;
+ if (width <= 0)
+ width = 256;
+ height = config->height;
+ if (height <= 0)
+ height = 64;
+ m_iSizeYb = (height + 7) / 8;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup linear lcd array
+ m_pDrawMem = new unsigned char *[width];
+ if (m_pDrawMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ m_pDrawMem[x] = new unsigned char[m_iSizeYb];
+ memset(m_pDrawMem[x], 0, m_iSizeYb);
+ }
+ }
+ Clear();
+
+ // setup the lcd array for the "vertical" mem
+ m_pVFDMem = new unsigned char *[width];
+ if (m_pVFDMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ m_pVFDMem[x] = new unsigned char[m_iSizeYb];
+ memset(m_pVFDMem[x], 0, m_iSizeYb);
+ }
+ }
+ ClearVFDMem();
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)\n", config->name.c_str(), strerror(errno));
+ m_bSleepIsInit = false;
+ }
+ else
+ {
+ m_bSleepIsInit = true;
+ }
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (x = 0; x < 10000; x++)
+ {
+ port->WriteData(x % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ nSleepDeInit();
+ m_nTimingAdjustCmd = ((tv2.tv_sec - tv1.tv_sec) * 10000 + (tv2.tv_usec - tv1.tv_usec)) / 1000;
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", config->name.c_str(), m_nTimingAdjustCmd);
+
+ GU256X64Cmd(SCREEN1ON);
+ GU256X64Cmd(CURS_AUTOINC);
+ GU256X64Cmd(SCREEN2CHAR);
+
+ GU256X64Cmd(DISP_LOSTA1); GU256X64Data(0x00);
+ GU256X64Cmd(DISP_HISTA1); GU256X64Data(0x00);
+ GU256X64Cmd(DISP_LOSTA2); GU256X64Data(0x00);
+ GU256X64Cmd(DISP_HISTA2); GU256X64Data(0x10);
+ GU256X64Cmd(CURS_LOADDR); GU256X64Data(0x00);
+ GU256X64Cmd(CURS_HIADDR); GU256X64Data(0x00);
+
+ GU256X64Cmd(DISP_OR);
+
+ port->Release();
+
+ *oldConfig = *config;
+
+ // Set Display SetBrightness
+ SetBrightness(config->brightness);
+ // clear display
+ Clear();
+ ClearVFDMem();
+
+ syslog(LOG_INFO, "%s: gu256x64-372 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverGU256X64_372::DeInit()
+{
+ int x;
+
+ if (m_pVFDMem)
+ for (x = 0; x < width; x++)
+ {
+ delete[] m_pVFDMem[x];
+ }
+ delete[] m_pVFDMem;
+
+ if (m_pDrawMem)
+ for (x = 0; x < width; x++)
+ {
+ delete[] m_pDrawMem[x];
+ }
+ delete[] m_pDrawMem;
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverGU256X64_372::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->brightness != oldConfig->brightness)
+ {
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
+ }
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverGU256X64_372::ClearVFDMem()
+{
+ for (int x = 0; x < width; x++)
+ memset(m_pVFDMem[x], 0, m_iSizeYb);
+}
+
+void cDriverGU256X64_372::Clear()
+{
+ for (int x = 0; x < width; x++)
+ memset(m_pDrawMem[x], 0, m_iSizeYb);
+}
+
+void cDriverGU256X64_372::SetBrightness(unsigned int percent)
+{
+ port->Claim();
+
+ if (percent > 88) {
+ GU256X64Cmd(BRIGHT_1);
+ } else if (percent > 75) {
+ GU256X64Cmd(BRIGHT_2);
+ } else if (percent > 66) {
+ GU256X64Cmd(BRIGHT_3);
+ } else if (percent > 0 ) {
+ GU256X64Cmd(BRIGHT_4);
+ } else {
+ GU256X64Cmd(SCREENSOFF);
+ }
+ port->Release();
+}
+
+void cDriverGU256X64_372::GU256X64Cmd(unsigned char data)
+{
+ if (m_bSleepIsInit)
+ nSleepInit();
+
+ port->WriteControl(CDHI | WRHI);
+ port->WriteData(data);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+ port->WriteControl(CDHI | WRLO);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+ port->WriteControl(CDHI | WRHI);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+}
+
+void cDriverGU256X64_372::GU256X64Data(unsigned char data)
+{
+ if (m_bSleepIsInit)
+ nSleepInit();
+
+ port->WriteControl(CDLO | WRHI);
+ port->WriteData(data);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+ port->WriteControl(CDLO | WRLO);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+ port->WriteControl(CDLO | WRHI);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+}
+
+void cDriverGU256X64_372::SetPixel(int x, int y)
+{
+ unsigned char c;
+
+ if (!m_pDrawMem)
+ return;
+
+ if (x >= width || x < 0)
+ return;
+ if (y >= height || y < 0)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ c = 0x80 >> (y % 8);
+
+ m_pDrawMem[x][y/8] = m_pDrawMem[x][y/8] | c;
+}
+
+void cDriverGU256X64_372::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+
+ // x - pos is'nt mayby align to 8
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverGU256X64_372::Refresh(bool refreshAll)
+{
+ int xb, yb;
+
+ if (!m_pVFDMem || !m_pDrawMem)
+ return;
+
+ bool doRefresh = false;
+ int minX = width;
+ int maxX = 0;
+ int minYb = m_iSizeYb;
+ int maxYb = 0;
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ for (xb = 0; xb < width; ++xb)
+ {
+ for (yb = 0; yb < m_iSizeYb; ++yb)
+ {
+ if (m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb])
+ {
+ m_pVFDMem[xb][yb] = m_pDrawMem[xb][yb];
+ minX = std::min(minX, xb);
+ maxX = std::max(maxX, xb);
+ minYb = std::min(minYb, yb);
+ maxYb = std::max(maxYb, yb + 1);
+ doRefresh = true;
+ }
+ }
+ }
+
+ m_nRefreshCounter = (m_nRefreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !m_nRefreshCounter)
+ refreshAll = true;
+
+ if (refreshAll || doRefresh)
+ {
+ if (refreshAll) {
+ minX = 0;
+ maxX = width;
+ minYb = 0;
+ maxYb = m_iSizeYb;
+ // and reset RefreshCounter
+ m_nRefreshCounter = 0;
+ }
+
+ minX = std::max(minX, 0);
+ maxX = std::min(maxX, width - 1);
+ minYb = std::max(minYb, 0);
+ maxYb = std::min(maxYb, m_iSizeYb);
+
+ port->Claim();
+
+ GU256X64Cmd(CURS_LOADDR); GU256X64Data(0x00);
+ GU256X64Cmd(CURS_HIADDR); GU256X64Data(0x00);
+ GU256X64Cmd(DATA_WRITE);
+
+ for (xb = 0; xb < width; xb++)
+ {
+ for (yb = 0; yb < m_iSizeYb; yb++)
+ {
+ GU256X64Data((m_pVFDMem[xb][yb]) ^ (config->invert ? 0xff : 0x00));
+ }
+ }
+ port->Release();
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/gu256x64-372.h b/glcddrivers/gu256x64-372.h
new file mode 100644
index 0000000..f685f7d
--- /dev/null
+++ b/glcddrivers/gu256x64-372.h
@@ -0,0 +1,73 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu256x64-372.h - 8-bit driver module for Noritake GU256x64-372
+ * VFD displays. The VFD is operating in its 8-bit
+ * mode connected to a single PC parallel port.
+ *
+ * based on:
+ * gu256x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT comports.com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas 'randy' Weinberger (randy AT smue.org)
+ */
+
+#ifndef _GLCDDRIVERS_GU256X64_372_H_
+#define _GLCDDRIVERS_GU256X64_372_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverGU256X64_372 : public cDriver
+{
+ cParallelPort * port;
+
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ int m_iSizeYb;
+ int m_nRefreshCounter;
+
+ unsigned char ** m_pDrawMem; // the draw "memory"
+ unsigned char ** m_pVFDMem; // the double buffed display "memory"
+
+ long m_nTimingAdjustCmd;
+ bool m_bSleepIsInit;
+
+ int CheckSetup();
+
+protected:
+ void ClearVFDMem();
+ void SetPixel(int x, int y);
+ void GU256X64Cmd(unsigned char data);
+ void GU256X64Data(unsigned char data);
+
+public:
+ cDriverGU256X64_372(cDriverConfig * config);
+ virtual ~cDriverGU256X64_372();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/gu256x64-3900.c b/glcddrivers/gu256x64-3900.c
new file mode 100644
index 0000000..8b4560b
--- /dev/null
+++ b/glcddrivers/gu256x64-3900.c
@@ -0,0 +1,651 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu256x64-3900.c - 8-bit driver module for Noritake GU256X64x-3900
+ * VFD displays. The VFD is either operating in
+ * 8-bit mode connected to a single PC parallel
+ * port or in serial mode connected to a single PC
+ * serial port.
+ *
+ * based on:
+ * gu256x64-372 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger <randy AT smue.org>
+ * gu256x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT comports.com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "gu256x64-3900.h"
+#include "port.h"
+
+
+namespace GLCD
+{
+
+static const unsigned char dSETSTART0 = 0x02; // Set display start address (CMD prefix)
+static const unsigned char dSETSTART1 = 0x44; // Set display start address (CMD)
+static const unsigned char dSETSTART2 = 0x00; // Set display start address
+static const unsigned char dSETSTART3 = 0x53; // Set display start address
+
+static const unsigned char nINITDISPLAY0 = 0x1b; // Initialize display (CMD prefix)
+static const unsigned char nINITDISPLAY1 = 0x40; // Initialize display (CMD)
+
+static const unsigned char nPOWER0 = 0x1f; // Power on/off
+static const unsigned char nPOWER1 = 0x28; // Power on/off
+static const unsigned char nPOWER2 = 0x61; // Power on/off
+static const unsigned char nPOWER3 = 0x40; // Power on/off
+
+static const unsigned char nSETBRIGHT0 = 0x1f; // Set brightness (CMD prefix)
+static const unsigned char nSETBRIGHT1 = 0x58; // Set brightness (CMD)
+
+static const unsigned char dSETBRIGHT0 = 0x02; // Set brightness (CMD prefix)
+static const unsigned char dSETBRIGHT1 = 0x44; // Set brightness (CMD)
+static const unsigned char dSETBRIGHT2 = 0x00; // Set brightness
+static const unsigned char dSETBRIGHT3 = 0x58; // Set brightness
+
+static const unsigned char BRIGHT_000 = 0x10; // Brightness 0%
+static const unsigned char BRIGHT_012 = 0x11; // Brightness 12.5%
+static const unsigned char BRIGHT_025 = 0x12; // Brightness 25%
+static const unsigned char BRIGHT_037 = 0x13; // Brightness 37.5%
+static const unsigned char BRIGHT_050 = 0x14; // Brightness 50%
+static const unsigned char BRIGHT_062 = 0x15; // Brightness 62.5%
+static const unsigned char BRIGHT_075 = 0x16; // Brightness 75%
+static const unsigned char BRIGHT_087 = 0x17; // Brightness 87.5%
+static const unsigned char BRIGHT_100 = 0x18; // Brightness 100%
+
+static const unsigned char nSETCURSOR0 = 0x1f; // Set cursor (CMD prefix)
+static const unsigned char nSETCURSOR1 = 0x24; // Set cursor (CMD)
+
+static const unsigned char nDISPLAYCURSOR0 = 0x1f; // display cursor
+static const unsigned char nDISPLAYCURSOR1 = 0x43; // display cursor
+
+static const unsigned char nBLITIMAGE0 = 0x1f; // Display image
+static const unsigned char nBLITIMAGE1 = 0x28; // Display image
+static const unsigned char nBLITIMAGE2 = 0x66; // Display image
+static const unsigned char nBLITIMAGE3 = 0x11; // Display image
+
+static const unsigned char dBLITIMAGE0 = 0x02; // Image write
+static const unsigned char dBLITIMAGE1 = 0x44; // Image write
+static const unsigned char dBLITIMAGE2 = 0x00; // Image write
+static const unsigned char dBLITIMAGE3 = 0x46; // Image write
+
+
+static const unsigned char WRHI = 0x0f; // any control pin to high
+static const unsigned char WRLO = 0x00;
+static const unsigned char RDYHI = 0x40; // RDY
+static const unsigned char RDYHIALT = 0x80; // RDY satyr wiring
+static const unsigned char RDYLO = 0x00;
+
+static const std::string kWiringStandard = "Standard";
+static const std::string kWiringSatyr = "Satyr";
+
+static const int kInterfaceParallel = 0; // parallel mode
+static const int kInterfaceSerial = 1; // serial mode
+
+
+cDriverGU256X64_3900::cDriverGU256X64_3900(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ portFd = -1;
+ m_nRefreshCounter = 0;
+}
+
+cDriverGU256X64_3900::~cDriverGU256X64_3900()
+{
+ delete oldConfig;
+}
+
+int cDriverGU256X64_3900::Init()
+{
+ int x;
+
+ width = config->width;
+ if (width <= 0)
+ width = 256;
+ height = config->height;
+ if (height <= 0)
+ height = 64;
+ m_iSizeYb = ((height + 7) / 8);
+
+ // default values
+ readyMask = RDYHI;
+ readyHi = RDYHI;
+ interface = kInterfaceParallel;
+ useDMA = true;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Wiring")
+ {
+ if (config->options[i].value == kWiringStandard)
+ {
+ readyMask = RDYHI;
+ readyHi = RDYHI;
+ }
+ else if (config->options[i].value == kWiringSatyr)
+ {
+ readyMask = RDYHIALT;
+ readyHi = RDYLO;
+ }
+ else
+ syslog(LOG_ERR, "%s error: wiring %s not supported, using default (Standard)!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
+ if (config->options[i].name == "Interface")
+ {
+ if (config->options[i].value == "Parallel")
+ interface = kInterfaceParallel;
+ else if (config->options[i].value == "Serial")
+ interface = kInterfaceSerial;
+ else
+ syslog(LOG_ERR, "%s error: interface %s not supported, using default (Parallel)!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
+ else if (config->options[i].name == "DMA")
+ {
+ if (config->options[i].value == "yes")
+ useDMA = true;
+ else if (config->options[i].value == "no")
+ useDMA = false;
+ else
+ syslog(LOG_ERR, "%s error: unknown DMA setting %s, using default (%s)!\n",
+ config->name.c_str(), config->options[i].value.c_str(), useDMA ? "yes" : "no");
+ }
+ }
+
+ if (interface == kInterfaceParallel)
+ port = new cParallelPort();
+ else
+ port = NULL;
+
+ // setup linear lcd array
+ m_pDrawMem = new unsigned char *[width];
+ if (m_pDrawMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ m_pDrawMem[x] = new unsigned char[m_iSizeYb];
+ memset(m_pDrawMem[x], 0, m_iSizeYb);
+ }
+ }
+ Clear();
+
+ // setup the lcd array for the "vertical" mem
+ m_pVFDMem = new unsigned char *[width];
+ if (m_pVFDMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ m_pVFDMem[x] = new unsigned char[m_iSizeYb];
+ memset(m_pVFDMem[x], 0, m_iSizeYb);
+ }
+ }
+ ClearVFDMem();
+
+ if (interface == kInterfaceSerial)
+ {
+ if (InitSerialPort() < 0)
+ return -1;
+ }
+ else
+ {
+ if (InitParallelPort() < 0)
+ return -1;
+ }
+
+ if (useDMA)
+ InitDMADisplay();
+ else
+ InitNormalDisplay();
+
+ if (interface == kInterfaceParallel)
+ {
+ // claim is in InitParallelPort
+ port->Release();
+ }
+
+ *oldConfig = *config;
+
+ // Set Display SetBrightness
+ SetBrightness(config->brightness);
+ // clear display
+ Clear();
+ ClearVFDMem();
+
+ syslog(LOG_INFO, "%s: gu256x64-3900 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverGU256X64_3900::DeInit()
+{
+ int x;
+
+ if (m_pVFDMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ delete[] m_pVFDMem[x];
+ }
+ delete[] m_pVFDMem;
+ }
+ if (m_pDrawMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ delete[] m_pDrawMem[x];
+ }
+ delete[] m_pDrawMem;
+ }
+
+ if (interface == kInterfaceSerial)
+ {
+ if (portFd >= 0)
+ {
+ close(portFd);
+ portFd =- 1;
+ }
+ }
+ if (port)
+ {
+ if (port->Close() != 0)
+ {
+ return -1;
+ }
+ delete port;
+ port = NULL;
+ }
+ return 0;
+}
+
+int cDriverGU256X64_3900::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->brightness != oldConfig->brightness)
+ {
+ oldConfig->brightness = config->brightness;
+ SetBrightness(config->brightness);
+ }
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+int cDriverGU256X64_3900::InitSerialPort()
+{
+ if (config->device == "")
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!\n", config->name.c_str());
+ return -1;
+ }
+
+ portFd = open(config->device.c_str(), O_RDWR | O_NOCTTY);
+ if (portFd >= 0)
+ {
+ struct termios options;
+ tcgetattr(portFd, &options);
+ cfsetispeed(&options, B38400);
+ cfsetospeed(&options, B38400);
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ options.c_cflag |= CS8;
+ tcsetattr(portFd, TCSANOW, &options);
+ }
+ else
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!\n", config->name.c_str());
+ return -1;
+ }
+ return 0;
+}
+
+int cDriverGU256X64_3900::InitParallelPort()
+{
+ struct timeval tv1, tv2;
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!\n", config->name.c_str());
+ return -1;
+ }
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ {
+ syslog(LOG_ERR, "%s: unable to initialize gu256x64-3900!\n", config->name.c_str());
+ return -1;
+ }
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)\n", config->name.c_str(), strerror(errno));
+ m_bSleepIsInit = false;
+ }
+ else
+ {
+ m_bSleepIsInit = true;
+ }
+
+ port->Claim();
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (int x = 0; x < 1000; x++)
+ {
+ port->WriteData(x % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ nSleepDeInit();
+ m_nTimingAdjustCmd = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+ syslog(LOG_INFO, "%s: benchmark stopped. Time for Port Command: %ldns\n", config->name.c_str(), m_nTimingAdjustCmd);
+
+ return 0;
+}
+
+void cDriverGU256X64_3900::InitNormalDisplay()
+{
+ Write(nPOWER0);
+ Write(nPOWER1);
+ Write(nPOWER2);
+ Write(nPOWER3);
+ Write(1); // power on
+
+ Write(nINITDISPLAY0);
+ Write(nINITDISPLAY1);
+
+ Write(nDISPLAYCURSOR0);
+ Write(nDISPLAYCURSOR1);
+ Write(0); // off
+
+ Write(nSETCURSOR0);
+ Write(nSETCURSOR1);
+ Write(0); // low byte x
+ Write(0); // high byte x
+ Write(0); // low byte y
+ Write(0); // high byte y
+}
+
+void cDriverGU256X64_3900::InitDMADisplay()
+{
+ Write(dSETSTART0);
+ Write(dSETSTART1);
+ Write(dSETSTART2);
+ Write(dSETSTART3);
+ Write(0);
+ Write(0);
+}
+
+void cDriverGU256X64_3900::ClearVFDMem()
+{
+ for (int x = 0; x < width; x++)
+ memset(m_pVFDMem[x], 0, m_iSizeYb);
+}
+
+void cDriverGU256X64_3900::Clear()
+{
+ for (int x = 0; x < width; x++)
+ memset(m_pDrawMem[x], 0, m_iSizeYb);
+}
+
+void cDriverGU256X64_3900::SetBrightness(unsigned int percent)
+{
+ if (interface == kInterfaceParallel)
+ port->Claim();
+
+ if (interface == kInterfaceParallel && useDMA)
+ {
+ Write(dSETBRIGHT0);
+ Write(dSETBRIGHT1);
+ Write(dSETBRIGHT2);
+ Write(dSETBRIGHT3);
+ }
+ else
+ {
+ Write(nSETBRIGHT0);
+ Write(nSETBRIGHT1);
+ }
+ if (percent > 87) {
+ Write(BRIGHT_100);
+ } else if (percent > 75) {
+ Write(BRIGHT_087);
+ } else if (percent > 62) {
+ Write(BRIGHT_075);
+ } else if (percent > 50) {
+ Write(BRIGHT_062);
+ } else if (percent > 37) {
+ Write(BRIGHT_050);
+ } else if (percent > 25) {
+ Write(BRIGHT_037);
+ } else if (percent > 12) {
+ Write(BRIGHT_025);
+ } else if (percent > 1) {
+ Write(BRIGHT_012);
+ } else {
+ Write(BRIGHT_000);
+ }
+ if (interface == kInterfaceParallel)
+ port->Release();
+}
+
+void cDriverGU256X64_3900::WriteParallel(unsigned char data)
+{
+ if (m_bSleepIsInit)
+ nSleepInit();
+ if ((port->ReadStatus() & readyMask) != readyHi)
+ {
+ int i = 0;
+ int status = port->ReadStatus();
+ for (; ((status&readyMask) != readyHi) && i < 1000; i++)
+ {
+ // wait until display ack's write but not forever
+ status=port->ReadStatus();
+ }
+ }
+
+ port->WriteControl(WRLO);
+ port->WriteData(data);
+ nSleep(100 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+ port->WriteControl(WRHI);
+ nSleep(500 + (100 * config->adjustTiming) - m_nTimingAdjustCmd);
+}
+
+void cDriverGU256X64_3900::WriteSerial(unsigned char data)
+{
+ write(portFd, &data, 1);
+}
+
+void cDriverGU256X64_3900::Write(unsigned char data)
+{
+ if (interface == kInterfaceSerial)
+ WriteSerial(data);
+ else
+ WriteParallel(data);
+}
+
+void cDriverGU256X64_3900::SetPixel(int x, int y)
+{
+ unsigned char c;
+
+ if (!m_pDrawMem)
+ return;
+
+ if (x >= width || x < 0)
+ return;
+ if (y >= height || y < 0)
+ return;
+
+ if (config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ c = 0x80 >> (y % 8);
+
+ m_pDrawMem[x][y/8] = m_pDrawMem[x][y/8] | c;
+}
+
+void cDriverGU256X64_3900::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+
+ // x - pos is'nt maybe align to 8
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverGU256X64_3900::Refresh(bool refreshAll)
+{
+ int xb, yb;
+
+ if (!m_pVFDMem || !m_pDrawMem)
+ return;
+
+ bool doRefresh = false;
+ int minX = width;
+ int maxX = 0;
+ int minYb = m_iSizeYb;
+ int maxYb = 0;
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ for (xb = 0; xb < width; ++xb)
+ {
+ for (yb = 0; yb < m_iSizeYb; ++yb)
+ {
+ if (m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb])
+ {
+ m_pVFDMem[xb][yb] = m_pDrawMem[xb][yb];
+ minX = std::min(minX, xb);
+ maxX = std::max(maxX, xb);
+ minYb = std::min(minYb, yb);
+ maxYb = std::max(maxYb, yb + 1);
+ doRefresh = true;
+ }
+ }
+ }
+
+ if (config->refreshDisplay > 0)
+ {
+ m_nRefreshCounter = (m_nRefreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !m_nRefreshCounter)
+ refreshAll = true;
+ }
+
+ if (refreshAll || doRefresh)
+ {
+ if (refreshAll)
+ {
+ minX = 0;
+ maxX = width;
+ minYb = 0;
+ maxYb = m_iSizeYb;
+ // and reset RefreshCounter
+ m_nRefreshCounter = 0;
+ }
+
+ minX = std::max(minX, 0);
+ maxX = std::min(maxX, width - 1);
+ minYb = std::max(minYb, 0);
+ maxYb = std::min(maxYb, m_iSizeYb);
+
+ if (interface == kInterfaceParallel)
+ port->Claim();
+
+ if (interface == kInterfaceParallel && useDMA)
+ {
+ Write(dBLITIMAGE0);
+ Write(dBLITIMAGE1);
+ Write(dBLITIMAGE2);
+ Write(dBLITIMAGE3);
+ Write(0); // low byte address
+ Write(0); // high byte address
+ Write((m_iSizeYb*width)&0xff); // low byte size
+ Write((m_iSizeYb*width)>>8); // high byte size
+ }
+ else
+ {
+ Write(nSETCURSOR0);
+ Write(nSETCURSOR1);
+ Write(0); // low byte x
+ Write(0); // high byte x
+ Write(0); // low byte y
+ Write(0); // high byte y
+
+ Write(nBLITIMAGE0);
+ Write(nBLITIMAGE1);
+ Write(nBLITIMAGE2);
+ Write(nBLITIMAGE3);
+ Write(width&0xff); // low byte width
+ Write(width>>8); // high byte width
+ Write(m_iSizeYb); // low byte height
+ Write(0); // high byte height
+ Write(1); // end header
+ }
+
+ for (xb = 0; xb < width; xb++)
+ {
+ for (yb = 0; yb < m_iSizeYb; yb++)
+ {
+ Write((m_pVFDMem[xb][yb]) ^ (config->invert ? 0xff : 0x00));
+ }
+ // parallel port writing is busy waiting - with realtime priority you
+ // can lock the system - so don't be so greedy ;)
+ if ((xb % 32) == 31)
+ {
+ uSleep(1000);
+ }
+ }
+
+ if (interface == kInterfaceParallel)
+ port->Release();
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/gu256x64-3900.h b/glcddrivers/gu256x64-3900.h
new file mode 100644
index 0000000..2201417
--- /dev/null
+++ b/glcddrivers/gu256x64-3900.h
@@ -0,0 +1,87 @@
+/*
+ * GraphLCD driver library
+ *
+ * gu256x64-3900.h - 8-bit driver module for Noritake GU256X64x-3900
+ * VFD displays. The VFD is either operating in
+ * 8-bit mode connected to a single PC parallel
+ * port or in serial mode connected to a single PC
+ * serial port.
+ *
+ * based on:
+ * gu256x64-372 driver module for graphlcd
+ * (c) 2004 Andreas 'randy' Weinberger <randy AT smue.org>
+ * gu140x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab.de>
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT comports.com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Ralf Mueller (ralf AT bj-ig.de)
+ */
+
+#ifndef _GLCDDRIVERS_GU256X64_3900_H_
+#define _GLCDDRIVERS_GU256X64_3900_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverGU256X64_3900 : public cDriver
+{
+ cParallelPort * port;
+ int portFd;
+
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ int m_iSizeYb;
+ int m_nRefreshCounter;
+ int interface;
+ bool useDMA;
+ unsigned char readyMask;
+ unsigned char readyHi;
+
+ unsigned char ** m_pDrawMem; // the draw "memory"
+ unsigned char ** m_pVFDMem; // the double buffed display "memory"
+
+ long m_nTimingAdjustCmd;
+ bool m_bSleepIsInit;
+
+ int CheckSetup();
+
+protected:
+ void ClearVFDMem();
+ void SetPixel(int x, int y);
+ int InitSerialPort();
+ int InitParallelPort();
+ void InitNormalDisplay();
+ void InitDMADisplay();
+
+ void WriteSerial(unsigned char data);
+ void WriteParallel(unsigned char data);
+ void Write(unsigned char data);
+public:
+ cDriverGU256X64_3900(cDriverConfig * config);
+ virtual ~cDriverGU256X64_3900();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/hd61830.c b/glcddrivers/hd61830.c
new file mode 100644
index 0000000..6bc225d
--- /dev/null
+++ b/glcddrivers/hd61830.c
@@ -0,0 +1,391 @@
+/*
+ * GraphLCD driver library
+ *
+ * hd61830.c - HD61830 driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ */
+
+#include <syslog.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "hd61830.h"
+#include "port.h"
+
+
+namespace GLCD
+{
+
+// commands
+#define MCNT 0x00
+#define CPIT 0x01
+#define NOCH 0x02
+#define NOTD 0x03
+#define CPOS 0x04
+
+#define DSAL 0x08
+#define DSAH 0x09
+#define CACL 0x0A
+#define CACH 0x0B
+
+#define WDDI 0x0C
+#define RDDI 0x0D
+
+#define CBIT 0x0E
+#define SBIT 0x0F
+
+// control bits for DirectIO
+#define EN 0x01
+#define ENHI 0x00
+#define ENLO 0x01
+
+#define RW 0x02
+#define RWHI 0x00
+#define RWLO 0x02
+
+#define RS 0x04
+#define RSHI 0x04
+#define RSLO 0x00
+
+
+cDriverHD61830::cDriverHD61830(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ useSleepInit = false;
+
+ refreshCounter = 0;
+ timeForPortCmdInNs = 0;
+}
+
+cDriverHD61830::~cDriverHD61830()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverHD61830::Init()
+{
+ int i;
+ int x;
+ struct timeval tv1, tv2;
+
+ width = config->width;
+ if (width <= 0)
+ width = 240;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup lcd array (wanted state)
+ newLCD = new unsigned char *[(width + 7) / 8];
+ if (newLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ newLCD[x] = new unsigned char[height];
+ memset(newLCD[x], 0, height);
+ }
+ }
+ // setup lcd array (current state)
+ oldLCD = new unsigned char*[(width + 7) / 8];
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ oldLCD[x] = new unsigned char[height];
+ memset(oldLCD[x], 0, height);
+ }
+ }
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_DEBUG, "%s: INFO: cannot change wait parameters (cDriver::Init)\n", config->name.c_str());
+ useSleepInit = false;
+ }
+ else
+ {
+ useSleepInit = true;
+ }
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (i = 0; i < 1000; i++)
+ {
+ port->WriteData(1 % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ if (useSleepInit)
+ nSleepDeInit();
+ timeForPortCmdInNs = (tv2.tv_sec-tv1.tv_sec) * 1000000 + (tv2.tv_usec-tv1.tv_usec);
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", config->name.c_str(), timeForPortCmdInNs);
+
+ // initialize graphic mode
+ InitGraphic();
+
+ port->Release();
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: HD61830 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverHD61830::DeInit()
+{
+ int x;
+
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] newLCD[x];
+ }
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] oldLCD[x];
+ }
+ delete[] oldLCD;
+ }
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverHD61830::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+int cDriverHD61830::InitGraphic()
+{
+ Write(MCNT, 0x32); // set Mode Control Register
+ // DISP ON, MASTER ON, BLINK OFF, CURSOR OFF, GRAPHIC-Mode, int.Clock
+ Write(CPIT, 0x07); // set Character Pitch Register
+ // 8 pixels per byte
+ Write(NOCH, std::max(1, (width + 7) / 8 - 1)); // set Number-Of-Characters Register
+ // (width - 1) / 8 bytes per line horizontally
+ Write(NOTD, std::max(1, height - 1)); // set Number-Of-Time-Divisions Register
+ // height - 1
+ Write(CPOS, 0x00); // set Cursor Position Register
+ // optional, because we havn't enabled a cursor
+ Write(DSAL, 0x00); // set Display Start Address Register (Low Order Byte)
+ Write(DSAH, 0x00); // set Display Start Address Register (High Order Byte)
+ Write(CACL, 0x00); // set Cursor Address Counter Register (Low Order Byte)
+ Write(CACH, 0x00); // set Cursor Address Counter Register (High Order Byte)
+
+ return 0;
+}
+
+void cDriverHD61830::Write(unsigned char cmd, unsigned char data)
+{
+ if (useSleepInit)
+ nSleepInit();
+
+ // set RS high (instruction), RW low (write) and E low
+ port->WriteControl(RSHI | RWLO | ENLO);
+ nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+
+ // Output the actual command
+ port->WriteData(cmd);
+
+ // set E high
+ port->WriteControl(RSHI | RWLO | ENHI);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+
+ // set E low
+ port->WriteControl(RSHI | RWLO | ENLO);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+
+
+ // set RS low (data), RW low (write) and E low
+ port->WriteControl(RSLO | RWLO | ENLO);
+ nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+
+ // Output the actual data
+ port->WriteData(data);
+
+ // set E high
+ port->WriteControl(RSLO | RWLO | ENHI);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+
+ // set E low
+ port->WriteControl(RSLO | RWLO | ENLO);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+
+ switch (cmd)
+ {
+ case MCNT:
+ case CPIT:
+ case NOCH:
+ case NOTD:
+ case CPOS:
+ case DSAL:
+ case DSAH:
+ case CACL:
+ case CACH:
+ nSleep(4000 - std::max(450l, timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case WDDI:
+ case RDDI:
+ nSleep(6000 - std::max(450l, timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case CBIT:
+ case SBIT:
+ nSleep(36000 - std::max(450l, timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ }
+ if (useSleepInit)
+ nSleepDeInit();
+}
+
+void cDriverHD61830::Clear()
+{
+ for (int x = 0; x < (width + 7) / 8; x++)
+ memset(newLCD[x], 0, height);
+}
+
+void cDriverHD61830::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ newLCD[x / 8][y] = newLCD[x / 8][y] | ReverseBits(data);
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ newLCD[x / 8][y] = newLCD[x / 8][y] | data;
+ }
+}
+
+void cDriverHD61830::Refresh(bool refreshAll)
+{
+ int x;
+ int y;
+ int pos = 0;
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ port->Claim();
+
+ if (refreshAll)
+ {
+ // draw all
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ // (re-setting the cursor position
+ // might be removed, when the graphic glitches are solved)
+ Write(CACL, (pos % 0x100));
+ Write(CACH, (pos / 0x100));
+ Write(WDDI, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
+ oldLCD[x][y] = newLCD[x][y];
+ pos++;
+ }
+ }
+ // and reset RefreshCounter
+ refreshCounter = 0;
+ }
+ else
+ {
+ // draw only the changed bytes
+
+ bool cs = false;
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ if (newLCD[x][y] != oldLCD[x][y])
+ {
+ if (!cs)
+ {
+ Write(CACL, (pos % 0x100));
+ Write(CACH, (pos / 0x100));
+ cs = true;
+ }
+ Write(WDDI, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
+ oldLCD[x][y] = newLCD[x][y];
+ }
+ else
+ {
+ cs = false;
+ }
+ pos++;
+ }
+ }
+ }
+ port->Release();
+}
+
+} // end of namespace
diff --git a/glcddrivers/hd61830.h b/glcddrivers/hd61830.h
new file mode 100644
index 0000000..50f3b26
--- /dev/null
+++ b/glcddrivers/hd61830.h
@@ -0,0 +1,54 @@
+/*
+ * GraphLCD driver library
+ *
+ * hd61830.h - HD61830 driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ */
+
+#ifndef _GLCDDRIVERS_HD61830_H_
+#define _GLCDDRIVERS_HD61830_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverHD61830 : public cDriver
+{
+private:
+ cParallelPort * port;
+
+ unsigned char ** newLCD; // wanted state
+ unsigned char ** oldLCD; // current state
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ int refreshCounter;
+ long timeForPortCmdInNs;
+ bool useSleepInit;
+
+ int CheckSetup();
+ int InitGraphic();
+ void Write(unsigned char cmd, unsigned char data);
+
+public:
+ cDriverHD61830(cDriverConfig * config);
+ virtual ~cDriverHD61830();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/image.c b/glcddrivers/image.c
new file mode 100644
index 0000000..4d11cbd
--- /dev/null
+++ b/glcddrivers/image.c
@@ -0,0 +1,167 @@
+/*
+ * GraphLCD driver library
+ *
+ * image.c - Image output device
+ * Output goes to a image file instead of LCD.
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+
+#include "common.h"
+#include "config.h"
+#include "image.h"
+
+
+namespace GLCD
+{
+
+cDriverImage::cDriverImage(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+}
+
+cDriverImage::~cDriverImage()
+{
+ delete oldConfig;
+}
+
+int cDriverImage::Init()
+{
+ width = config->width;
+ if (width <= 0)
+ width = 240;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+ lineSize = (width + 7) / 8;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ newLCD = new unsigned char[lineSize * height];
+ if (newLCD)
+ memset(newLCD, 0, lineSize * height);
+ oldLCD = new unsigned char[lineSize * height];
+ if (oldLCD)
+ memset(oldLCD, 0, lineSize * height);
+
+ counter = 0;
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: image driver initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverImage::DeInit()
+{
+ if (newLCD)
+ delete[] newLCD;
+ if (oldLCD)
+ delete[] oldLCD;
+ return 0;
+}
+
+int cDriverImage::CheckSetup()
+{
+ if (config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverImage::Clear()
+{
+ memset(newLCD, 0, lineSize * height);
+}
+
+void cDriverImage::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ newLCD[lineSize * y + x / 8] |= data;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ newLCD[lineSize * y + x / 8] |= ReverseBits(data);
+ }
+}
+
+void cDriverImage::Refresh(bool refreshAll)
+{
+ int i;
+ bool refresh;
+ char fileName[256];
+ char str[32];
+ FILE * fp;
+ unsigned char c;
+
+ refresh = false;
+ if (CheckSetup() > 0)
+ refresh = true;
+
+ for (i = 0; i < lineSize * height; i++)
+ {
+ if (newLCD[i] != oldLCD[i])
+ {
+ refresh = true;
+ break;
+ }
+ }
+
+ if (refresh)
+ {
+ sprintf(fileName, "%s/%s%05d.%s", "/tmp", "lcd", counter, "pbm");
+ fp = fopen(fileName, "wb");
+ if (fp)
+ {
+ sprintf(str, "P4\n%d %d\n", width, height);
+ fwrite(str, strlen(str), 1, fp);
+ for (i = 0; i < lineSize * height; i++)
+ {
+ c = newLCD[i] ^ (config->invert ? 0xff : 0x00);
+ fwrite(&c, 1, 1, fp);
+ oldLCD[i] = newLCD[i];
+ }
+ fclose(fp);
+ }
+ counter++;
+ if (counter > 99999)
+ counter = 0;
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/image.h b/glcddrivers/image.h
new file mode 100644
index 0000000..3e39e3f
--- /dev/null
+++ b/glcddrivers/image.h
@@ -0,0 +1,50 @@
+/*
+ * GraphLCD driver library
+ *
+ * image.h - Image output device
+ * Output goes to a image file instead of LCD.
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_IMAGE_H_
+#define _GLCDDRIVERS_IMAGE_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverImage : public cDriver
+{
+private:
+ unsigned char * newLCD;
+ unsigned char * oldLCD;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ int lineSize;
+ int counter;
+
+ int CheckSetup();
+
+public:
+ cDriverImage(cDriverConfig * config);
+ virtual ~cDriverImage();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/ks0108.c b/glcddrivers/ks0108.c
new file mode 100644
index 0000000..0c607bb
--- /dev/null
+++ b/glcddrivers/ks0108.c
@@ -0,0 +1,593 @@
+/*
+ * GraphLCD driver library
+ *
+ * ks0108.c - KS0108 driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ */
+
+#include <syslog.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "ks0108.h"
+#include "port.h"
+
+
+namespace GLCD
+{
+
+// commands
+const unsigned char kSEAD = 0x40; // Set (X) Address
+const unsigned char kSEPA = 0xb8; // Set (Y) Page
+const unsigned char kSEDS = 0xc0; // Set Display Start Line
+const unsigned char kDIOF = 0x3e; // Display off
+const unsigned char kDION = 0x3f; // Display on
+
+const unsigned char kCEHI = 0x01; // Chip Enable on
+const unsigned char kCELO = 0x00;
+const unsigned char kCDHI = 0x08; // Command/Data Register Select
+const unsigned char kCDLO = 0x00;
+
+const unsigned char kCS1HI = 0x02; // ChipSelect 1
+const unsigned char kCS1LO = 0x00;
+const unsigned char kCS2HI = 0x00; // ChipSelect 2
+const unsigned char kCS2LO = 0x04;
+
+
+cDriverKS0108::cDriverKS0108(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ refreshCounter = 0;
+ timeForLCDInNs = 50;
+ control = 1;
+}
+
+cDriverKS0108::~cDriverKS0108()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverKS0108::Init()
+{
+ int x;
+ int i;
+ struct timeval tv1, tv2;
+
+ if (config->width <= 128) {
+ width = 128;
+ } else if (config->width > 192) {
+ width = 256;
+ } else if (config->width > 128) {
+ width = 192;
+ }
+
+ if (config->height <= 64) {
+ height = 64;
+ } else if (config->height > 64) {
+ height = 128;
+ width = 128; // force 2* 128x64 display
+ }
+
+ if (width == 128 && height == 64) {
+ CS1 = kCS2HI | kCS1LO;
+ CS2 = kCS2LO | kCS1HI;
+ CS3 = -1; // invalid
+ CS4 = -1;
+ } else { // multiplexed via 74LS42
+ CS1 = kCS2HI | kCS1HI;
+ CS2 = kCS2HI | kCS1LO;
+ CS3 = kCS2LO | kCS1HI;
+ CS4 = kCS2LO | kCS1LO;
+ }
+
+ SEAD = kSEAD;
+ SEPA = kSEPA;
+ SEDS = kSEDS;
+ DIOF = kDIOF;
+ DION = kDION;
+
+ CEHI = kCEHI;
+ CELO = kCELO;
+ CDHI = kCDHI;
+ CDLO = kCDLO;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Control")
+ {
+ if (config->options[i].value == "0")
+ control = 0;
+ else if (config->options[i].value == "1")
+ control = 1;
+ else
+ syslog(LOG_ERR, "%s error: unknown control setting %s, using default (%d)!\n",
+ config->name.c_str(), config->options[i].value.c_str(), control);
+ }
+ }
+
+ // setup linear lcd array
+ LCD = new unsigned char *[(width + 7) / 8];
+ if (LCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ LCD[x] = new unsigned char[height];
+ memset(LCD[x], 0, height);
+ }
+ }
+ // setup the lcd array for the paged ks0108
+ LCD_page = new unsigned char *[width];
+ if (LCD_page)
+ {
+ for (x = 0; x < width; x++)
+ {
+ LCD_page[x] = new unsigned char[(height + 7) / 8];
+ memset(LCD_page[x], 0, (height + 7) / 8);
+ }
+ }
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_DEBUG, "%s: INFO: cannot change wait parameters (cDriver::Init)\n", config->name.c_str());
+ useSleepInit = false;
+ }
+ else
+ {
+ useSleepInit = true;
+ }
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (i = 0; i < 1000; i++)
+ {
+ port->WriteData(i % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ if (useSleepInit)
+ nSleepDeInit();
+ timeForPortCmdInNs = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Command: %ldns\n", config->name.c_str(), timeForPortCmdInNs);
+
+ // initialize graphic mode
+ InitGraphic();
+
+ port->Release();
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: KS0108 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverKS0108::DeInit()
+{
+ int x;
+
+ // free linear lcd array
+ if (LCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] LCD[x];
+ }
+ delete[] LCD;
+ }
+ // free paged lcd array
+ if (LCD_page)
+ {
+ for (x = 0; x < width; x++)
+ {
+ delete[] LCD_page[x];
+ }
+ delete[] LCD_page;
+ }
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverKS0108::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+int cDriverKS0108::InitGraphic()
+{
+ // init controllers
+ if (CS1 > -1) {
+ KS0108Cmd(SEDS, 1);
+ KS0108Cmd(SEPA, 1);
+ KS0108Cmd(SEAD, 1);
+ KS0108Cmd(DION, 1);
+ }
+ if (CS2 > -1) {
+ KS0108Cmd(SEDS, 2);
+ KS0108Cmd(SEPA, 2);
+ KS0108Cmd(SEAD, 2);
+ KS0108Cmd(DION, 2);
+ }
+ if (CS3 > -1) {
+ KS0108Cmd(SEDS, 3);
+ KS0108Cmd(SEPA, 3);
+ KS0108Cmd(SEAD, 3);
+ KS0108Cmd(DION, 3);
+ }
+ if (CS4 > -1) {
+ KS0108Cmd(SEDS, 4);
+ KS0108Cmd(SEPA, 4);
+ KS0108Cmd(SEAD, 4);
+ KS0108Cmd(DION, 4);
+ }
+ return 0;
+}
+
+void cDriverKS0108::KS0108Cmd(unsigned char data, int cs)
+{
+ if (useSleepInit)
+ nSleepInit();
+ switch (cs) {
+ case 1:
+ if (control == 1)
+ port->WriteControl(CDHI | CS1 | CELO);
+ else
+ port->WriteControl(CDHI | CS1 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDHI | CS1 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDHI | CS1 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case 2:
+ if (control == 1)
+ port->WriteControl(CDHI | CS2 | CELO);
+ else
+ port->WriteControl(CDHI | CS2 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDHI | CS2 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDHI | CS2 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case 3:
+ if (control == 1)
+ port->WriteControl(CDHI | CS3 | CELO);
+ else
+ port->WriteControl(CDHI | CS3 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDHI | CS3 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDHI | CS3 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case 4:
+ if (control == 1)
+ port->WriteControl(CDHI | CS4 | CELO);
+ else
+ port->WriteControl(CDHI | CS4 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDHI | CS4 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDHI | CS4 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ }
+ if (useSleepInit)
+ nSleepDeInit();
+}
+
+void cDriverKS0108::KS0108Data(unsigned char data, int cs)
+{
+ if (useSleepInit)
+ nSleepInit();
+ switch (cs) {
+ case 1:
+ if (control == 1)
+ port->WriteControl(CDLO | CS1 | CELO);
+ else
+ port->WriteControl(CDLO | CS1 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDLO | CS1 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDLO | CS1 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case 2:
+ if (control == 1)
+ port->WriteControl(CDLO | CS2 | CELO);
+ else
+ port->WriteControl(CDLO | CS2 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDLO | CS2 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDLO | CS2 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case 3:
+ if (control == 1)
+ port->WriteControl(CDLO | CS3 | CELO);
+ else
+ port->WriteControl(CDLO | CS3 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDLO | CS3 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDLO | CS3 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ case 4:
+ if (control == 1)
+ port->WriteControl(CDLO | CS4 | CELO);
+ else
+ port->WriteControl(CDLO | CS4 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ if (control == 1)
+ {
+ port->WriteControl(CDLO | CS4 | CEHI);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ }
+ port->WriteControl(CDLO | CS4 | CELO);
+ nSleep((timeForLCDInNs + timeForPortCmdInNs) + 100 * config->adjustTiming);
+ break;
+ }
+ if (useSleepInit)
+ nSleepDeInit();
+}
+
+void cDriverKS0108::Clear()
+{
+ for (int x = 0; x < (width + 7) / 8; x++)
+ memset(LCD[x], 0, height);
+}
+
+void cDriverKS0108::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ LCD[x / 8][y] = LCD[x / 8][y] | data;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ LCD[x / 8][y] = LCD[x / 8][y] | ReverseBits(data);
+ }
+}
+
+void cDriverKS0108::Refresh(bool refreshAll)
+{
+ int x,y;
+ int xx,yy;
+ unsigned char dByte, oneBlock[8];
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll=true;
+ }
+
+ refreshAll = true; // differential update is not yet supported
+
+ if (refreshAll)
+ {
+ // draw all
+
+ // convert the linear lcd array to the paged array for the display
+ for (y = 0; y < (height + 7) / 8; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ for (yy = 0; yy < 8; yy++)
+ {
+ oneBlock[yy] = LCD[x][yy + (y * 8)] ^ (config->invert ? 0xff : 0x00);
+ }
+ for (xx = 0; xx < 8; xx++)
+ {
+ dByte = 0;
+ for (yy = 0; yy < 8; yy++)
+ {
+ if (oneBlock[yy] & bitmask[xx])
+ {
+ dByte += (1 << yy);
+ }
+ }
+ LCD_page[x * 8 + xx][y] = dByte;
+ }
+ }
+ }
+
+ port->Claim();
+
+ if (width == 128 && height == 64) {
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 1);
+ KS0108Cmd(SEAD, 1);
+
+ for (x = 0; x < 64; x++) {
+ KS0108Data(LCD_page[x][y], 1);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 2);
+ KS0108Cmd(SEAD, 2);
+
+ for (x = 64; x < 128; x++) {
+ KS0108Data(LCD_page[x][y], 2);
+ }
+ }
+ }
+
+ if (width > 128 && height == 64) {
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 1);
+ KS0108Cmd(SEAD, 1);
+
+ for (x = 0; x < 64; x++) {
+ KS0108Data(LCD_page[x][y], 1);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 2);
+ KS0108Cmd(SEAD, 2);
+ for (x = 64; x < 128; x++) {
+ KS0108Data(LCD_page[x][y], 2);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 3);
+ KS0108Cmd(SEAD, 3);
+
+ for (x = 128; x < 192; x++) {
+ KS0108Data(LCD_page[x][y], 3);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ if (width > 192) {
+ KS0108Cmd(SEPA + y, 4);
+ KS0108Cmd(SEAD, 4);
+ for (x = 192; x < 256; x++) {
+ KS0108Data(LCD_page[x][y], 4);
+ }
+ }
+ }
+ }
+
+ if (width == 128 && height == 128) {
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 1);
+ KS0108Cmd(SEAD, 1);
+
+ for (x = 0; x < 64; x++) {
+ KS0108Data(LCD_page[x][y], 1);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 2);
+ KS0108Cmd(SEAD, 2);
+
+ for (x = 64; x < 128; x++) {
+ KS0108Data(LCD_page[x][y], 2);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 3);
+ KS0108Cmd(SEAD, 3);
+
+ for (x = 0; x < 64; x++) {
+ KS0108Data(LCD_page[x][y+8], 3);
+ }
+ }
+
+ for (y = 0; y < 64/8; y++) {
+ KS0108Cmd(SEPA + y, 4);
+ KS0108Cmd(SEAD, 4);
+
+ for (x = 64; x < 128; x++) {
+ KS0108Data(LCD_page[x][y+8], 4);
+ }
+ }
+ }
+ port->WriteData(0);
+ port->Release();
+ }
+ else
+ {
+ // draw only the changed bytes
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/ks0108.h b/glcddrivers/ks0108.h
new file mode 100644
index 0000000..66ac425
--- /dev/null
+++ b/glcddrivers/ks0108.h
@@ -0,0 +1,78 @@
+/*
+ * GraphLCD driver library
+ *
+ * ks0108.h - KS0108 driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ */
+
+#ifndef _GLCDDRIVERS_KS0108_H_
+#define _GLCDDRIVERS_KS0108_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverKS0108 : public cDriver
+{
+private:
+ cParallelPort * port;
+ unsigned char ** LCD; // linear lcd display "memory"
+ unsigned char ** LCD_page; // paged lcd display "memory"
+ int refreshCounter;
+ long timeForPortCmdInNs;
+ long timeForLCDInNs;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ bool useSleepInit;
+
+ int CheckSetup();
+ int InitGraphic();
+ void KS0108Cmd(unsigned char data, int cs);
+ void KS0108Data(unsigned char data, int cs);
+
+ int SEAD;
+ int SEPA;
+ int SEDS;
+ int DIOF;
+ int DION;
+
+ int CEHI;
+ int CELO;
+ int CDHI;
+ int CDLO;
+ int CS1HI;
+ int CS1LO;
+ int CS2HI;
+ int CS2LO;
+
+ int CS1;
+ int CS2;
+ int CS3;
+ int CS4;
+
+ unsigned char control;
+
+public:
+ cDriverKS0108(cDriverConfig * config);
+ virtual ~cDriverKS0108();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/network.c b/glcddrivers/network.c
new file mode 100644
index 0000000..9820f3b
--- /dev/null
+++ b/glcddrivers/network.c
@@ -0,0 +1,267 @@
+/*
+ * GraphLCD driver library
+ *
+ * network.c - Network output device
+ * Output goes to a network client.
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include "common.h"
+#include "config.h"
+#include "network.h"
+
+
+namespace GLCD
+{
+
+cDriverNetwork::cDriverNetwork(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+ childTid = 0;
+ running = false;
+ clientConnected = false;
+}
+
+cDriverNetwork::~cDriverNetwork()
+{
+ delete oldConfig;
+}
+
+int cDriverNetwork::Init()
+{
+ width = config->width;
+ if (width <= 0)
+ width = 240;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+ lineSize = (width + 7) / 8;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ newLCD = new unsigned char[lineSize * height];
+ if (newLCD)
+ memset(newLCD, 0, lineSize * height);
+ oldLCD = new unsigned char[lineSize * height];
+ if (oldLCD)
+ memset(oldLCD, 0, lineSize * height);
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ running = true;
+ if (pthread_create(&childTid, NULL, (void *(*) (void *)) &ServerThread, (void *)this) != 0)
+ {
+ syslog(LOG_ERR, "%s: error creating server thread.\n", config->name.c_str());
+ running = false;
+ return 1;
+ }
+ syslog(LOG_INFO, "%s: network driver initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverNetwork::DeInit()
+{
+ // stop server thread
+ running = false;
+ usleep(3000000); // wait 3 seconds
+ pthread_cancel(childTid);
+ childTid = 0;
+
+ if (newLCD)
+ delete[] newLCD;
+ if (oldLCD)
+ delete[] oldLCD;
+ return 0;
+}
+
+int cDriverNetwork::CheckSetup()
+{
+ if (config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverNetwork::Clear()
+{
+ memset(newLCD, 0, lineSize * height);
+}
+
+void cDriverNetwork::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ newLCD[lineSize * y + x / 8] |= data;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ newLCD[lineSize * y + x / 8] |= ReverseBits(data);
+ }
+}
+
+void cDriverNetwork::Refresh(bool refreshAll)
+{
+ int i;
+ bool refresh;
+
+ refresh = false;
+ if (CheckSetup() > 0)
+ refresh = true;
+
+ for (i = 0; i < lineSize * height; i++)
+ {
+ if (newLCD[i] != oldLCD[i])
+ {
+ refresh = true;
+ break;
+ }
+ }
+
+ if (refresh && clientConnected)
+ {
+ char msg[1024];
+ int x;
+ int y;
+ int sent;
+
+ sprintf(msg, "update begin %d %d\r\n", width, height);
+ sent = send(clientSocket, msg, strlen(msg), 0);
+ if (sent == -1)
+ {
+ syslog(LOG_ERR, "%s: error sending message: %s.\n", config->name.c_str(), strerror(errno));
+ clientConnected = false;
+ return;
+ }
+ for (y = 0; y < height; y++)
+ {
+ sprintf(msg, "update line %d ", y);
+ for (x = 0; x < lineSize; x++)
+ {
+ char tmp[3];
+ sprintf(tmp, "%02X", newLCD[y * lineSize + x]);
+ strcat(msg, tmp);
+ oldLCD[i] = newLCD[i];
+ }
+ strcat(msg, "\r\n");
+ sent = send(clientSocket, msg, strlen(msg), 0);
+ if (sent == -1)
+ {
+ syslog(LOG_ERR, "%s: error sending message: %s.\n", config->name.c_str(), strerror(errno));
+ clientConnected = false;
+ return;
+ }
+ }
+ sprintf(msg, "update end\r\n");
+ sent = send(clientSocket, msg, strlen(msg), 0);
+ if (sent == -1)
+ {
+ syslog(LOG_ERR, "%s: error sending message: %s.\n", config->name.c_str(), strerror(errno));
+ clientConnected = false;
+ return;
+ }
+ }
+}
+
+void * cDriverNetwork::ServerThread(cDriverNetwork * Driver)
+{
+ int serverSocket;
+ struct sockaddr_in address;
+ socklen_t addrlen;
+ int clientSocket;
+ fd_set set;
+ fd_set setsave;
+ struct timeval timeout;
+
+ serverSocket = socket(AF_INET, SOCK_STREAM, 0);
+ if (serverSocket == -1)
+ {
+ syslog(LOG_ERR, "%s: error creating server socket.\n", Driver->config->name.c_str());
+ return NULL;
+ }
+
+ int y = 1;
+ setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
+
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+ address.sin_port = htons(2003);
+ if (bind(serverSocket, (struct sockaddr *) &address, sizeof(address)) != 0)
+ {
+ syslog(LOG_ERR, "%s: error port %d is already used.\n", Driver->config->name.c_str(), 2003);
+ return NULL;
+ }
+
+ listen(serverSocket, 1);
+ addrlen = sizeof(struct sockaddr_in);
+
+ FD_ZERO(&set);
+ FD_SET(serverSocket, &set);
+ setsave = set;
+
+ while (Driver->running)
+ {
+ set = setsave;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ if (select(FD_SETSIZE, &set, NULL, NULL, &timeout) < 0)
+ {
+ syslog(LOG_ERR, "%s: error during select.\n", Driver->config->name.c_str());
+ break;
+ }
+
+ if (FD_ISSET(serverSocket, &set))
+ {
+ clientSocket = accept(serverSocket, (struct sockaddr *) &address, &addrlen);
+ if (clientSocket > 0)
+ {
+ Driver->clientSocket = clientSocket;
+ Driver->clientConnected = true;
+ }
+ }
+ }
+ close(serverSocket);
+ return NULL;
+}
+
+} // end of namespace
diff --git a/glcddrivers/network.h b/glcddrivers/network.h
new file mode 100644
index 0000000..4664f4c
--- /dev/null
+++ b/glcddrivers/network.h
@@ -0,0 +1,56 @@
+/*
+ * GraphLCD driver library
+ *
+ * network.h - Network output device
+ * Output goes to a network client.
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_NETWORK_H_
+#define _GLCDDRIVERS_NETWORK_H_
+
+#include <pthread.h>
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverNetwork : public cDriver
+{
+private:
+ unsigned char * newLCD;
+ unsigned char * oldLCD;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ int lineSize;
+ bool running;
+ pthread_t childTid;
+ int clientSocket;
+ bool clientConnected;
+
+ int CheckSetup();
+ static void * ServerThread(cDriverNetwork * Driver);
+
+public:
+ cDriverNetwork(cDriverConfig * config);
+ virtual ~cDriverNetwork();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/noritake800.c b/glcddrivers/noritake800.c
new file mode 100644
index 0000000..fe7bc72
--- /dev/null
+++ b/glcddrivers/noritake800.c
@@ -0,0 +1,537 @@
+/*
+ * GraphLCD driver library
+ *
+ * noritake800.c - Noritake 800(A) series VFD graphlcd driver,
+ * different "Medium 0.6 dot" sizes should work,
+ * see http://www.noritake-itron.com:
+ * - GU128X64-800A,
+ * - GU256X32-800A,
+ * - GU128X32-800A,
+ * - GU160X16-800A,
+ * - GU160X32-800A,
+ * - GU192X16-800A.
+ *
+ * based on:
+ * ideas and HW-command related stuff from the open source project
+ * "lcdplugin for Winamp":
+ * (c) 1999 - 2003 Markus Zehnder <lcdplugin AT markuszehnder.ch>
+ * GU256x64-372 driver module for graphlcd
+ * (c) 20040410 Andreas 'Randy' Weinberger <randy AT smue.org>
+ * gu140x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab de>
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT Comports.com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Lucian Muresan <lucianm AT users.sourceforge.net>
+ */
+
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "noritake800.h"
+#include "port.h"
+
+namespace GLCD
+{
+
+/* LPT Control Port lines */
+#define LPT_CTL_HI_DIR 0x20
+#define LPT_CTL_HI_IRQEN 0x10
+#define LPT_CTL_LO_STROBE 0x01
+#define LPT_CTL_LO_LFEED 0x02
+#define LPT_CTL_LO_INIT 0x04
+#define LPT_CTL_LO_SELECT 0x08
+
+/* Noritake 800(A) VFD control signals bit masks*/
+#define VFDSGN_CD 0x01
+#define VFDSGN_WR 0x02
+#define VFDSGN_RD 0x04
+#define VFDSGN_CSS 0x08
+
+//wirings
+#define WIRING_LIQUIDMP3 0
+static const std::string kWiringLiquidmp3 = "LiquidMp3";
+#define WIRING_MZ 1
+static const std::string kWiringMZ = "MZ";
+// ... other wirings may follow
+
+/* Command set for this display */
+#define ANDCNTL 0x03
+#define ORCNTL 0x01
+#define XORCNTL 0x02
+#define Init800A 0x5F /* initialization code sequence 5f */
+#define Init800B 0x62
+#define Init800C 0x00+n
+#define Init800D 0xFF
+#define CLEARSCREENS 0x5e /* clear all screens (layers) */
+#define LAYER0ON 0x24 /* screen0 both on */
+#define LAYER1ON 0x28 /* screen1 both on */
+#define LAYERSON 0x2c /* both screens both on */
+#define LAYERSOFF 0x20 /* screens both off */
+#define ORON 0x40 /* OR screens */
+#define ANDON 0x48 /* AND screens */
+#define XORON 0x44 /* XOR screens */
+#define SETX 0x64 /* set X position */
+#define SETY 0x60 /* set Y position */
+#define HSHIFT 0x70 /* set horizontal shift */
+#define VSHIFT 0xB0
+#define AUTOINCOFF 0x80 /* address auto increment off */
+#define SETPOSITION 0xff
+
+
+cDriverNoritake800::cDriverNoritake800(cDriverConfig * config)
+{
+ int x = 0;
+ m_bGraphScreen0_On = true;
+ m_bGraphScreen1_On = false;
+ // default initilaization for the wiring
+ m_nWiring = WIRING_LIQUIDMP3;
+
+ m_Config = config;
+ m_oldConfig = new cDriverConfig(* config);
+
+ m_pport = new cParallelPort();
+
+ m_nTimingAdjustCmd = 0;
+ m_nRefreshCounter = 0;
+
+ width = m_Config->width; // 128
+ if (width <= 0)
+ width = 128;
+ height = m_Config->height; // 64
+ if (height <= 0)
+ height = 64;
+ m_iSizeYb = (height + 7)/8; // 8
+
+ //
+ // initialize wiring
+ //
+ for (unsigned int i = 0; i < m_Config->options.size(); i++)
+ {
+ if (m_Config->options[i].name == "Wiring")
+ {
+ if (m_Config->options[i].value == kWiringLiquidmp3)
+ {
+ m_nWiring = WIRING_LIQUIDMP3;
+ }
+ else if (m_Config->options[i].value == kWiringMZ)
+ {
+ m_nWiring = WIRING_MZ;
+ }
+ else
+ syslog(LOG_ERR, "%s error: wiring %s not supported, using default wiring(%s)!\n",
+ config->name.c_str(), config->options[i].value.c_str(), kWiringLiquidmp3.c_str());
+ }
+ }
+ // fill the wiring mask cache for all the 16 possibilities
+ m_pWiringMaskCache = new unsigned char[16];
+ for (unsigned int i = 0; i < 16; i++)
+ {
+ m_pWiringMaskCache[i] = N800LptWiringMask(i);
+ }
+
+ // setup linear lcd array
+ m_pDrawMem = new unsigned char*[width];
+ if (m_pDrawMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ m_pDrawMem[x] = new unsigned char[m_iSizeYb];
+ memset(m_pDrawMem[x], 0, m_iSizeYb);
+ }
+ }
+ Clear();
+
+ // setup the lcd array for the "vertikal" mem
+ m_pVFDMem = new unsigned char*[width];
+ if (m_pVFDMem)
+ {
+ for (x = 0; x < width; x++)
+ {
+ m_pVFDMem[x] = new unsigned char[m_iSizeYb];
+ memset(m_pVFDMem[x], 0, m_iSizeYb);
+ }
+ }
+ ClearVFDMem();
+}
+
+cDriverNoritake800::~cDriverNoritake800()
+{
+ int x;
+
+ if (m_pVFDMem)
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] m_pVFDMem[x];
+ }
+ delete[] m_pVFDMem;
+ if (m_pDrawMem)
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] m_pDrawMem[x];
+ }
+ delete[] m_pDrawMem;
+ delete[] m_pWiringMaskCache;
+ delete m_oldConfig;
+ delete m_pport;
+}
+
+void cDriverNoritake800::Clear()
+{
+ for (int x = 0; x < width; x++)
+ {
+ memset(m_pDrawMem[x], 0, m_iSizeYb);
+ }
+}
+
+void cDriverNoritake800::ClearVFDMem()
+{
+ for (int x = 0; x < width; x++)
+ {
+ memset(m_pVFDMem[x], 0, m_iSizeYb);
+ }
+}
+
+int cDriverNoritake800::DeInit()
+{
+ if (m_pport->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverNoritake800::CheckSetup()
+{
+ if (m_Config->device != m_oldConfig->device ||
+ m_Config->port != m_oldConfig->port ||
+ m_Config->width != m_oldConfig->width ||
+ m_Config->height != m_oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (m_Config->brightness != m_oldConfig->brightness)
+ {
+ m_oldConfig->brightness = m_Config->brightness;
+ SetBrightness(m_Config->brightness);
+ }
+
+ if (m_Config->upsideDown != m_oldConfig->upsideDown ||
+ m_Config->invert != m_oldConfig->invert)
+ {
+ m_oldConfig->upsideDown = m_Config->upsideDown;
+ m_oldConfig->invert = m_Config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+int cDriverNoritake800::Init()
+{
+ int x;
+ struct timeval tv1, tv2;
+
+ if (m_Config->device == "")
+ {
+ // use DirectIO
+ if (m_pport->Open(m_Config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (m_pport->Open(m_Config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_ERR, "%s: INFO: cannot change wait parameters Err: %s (cDriver::Init)\n", m_Config->name.c_str(), strerror(errno));
+ m_bSleepIsInit = false;
+ }
+ else
+ {
+ m_bSleepIsInit = true;
+ }
+
+ // benchmark port access
+ m_pport->Claim();
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", m_Config->name.c_str());
+ gettimeofday(&tv1, 0);
+ int nBenchFactor = 100000;
+ for (x = 0; x < nBenchFactor; x++)
+ {
+ m_pport->WriteData(x % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ nSleepDeInit();
+ //m_nTimingAdjustCmd = ((tv2.tv_sec - tv1.tv_sec) * 10000 + (tv2.tv_usec - tv1.tv_usec)) / 1000;
+ m_nTimingAdjustCmd = long(double((tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec)) / double(nBenchFactor));
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Port Command: %ldns\n", m_Config->name.c_str(), m_nTimingAdjustCmd);
+ m_pport->Release();
+
+
+ // initialize display
+ N800Cmd(Init800A);
+
+ int n;
+ for (n=0; n < 15; n++)
+ {
+ N800Cmd(0x62);
+ nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ N800Cmd(n);
+ nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ N800Data(0xff);
+ nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ }
+ nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+
+
+ N800Cmd(LAYERSOFF | LAYER0ON); // layer 0 of the graphic RAM on
+ N800Cmd(ORON); // OR the layers
+ N800Cmd(HSHIFT); // set horizontal shift
+ N800Cmd(0x00); // no shift
+ N800Cmd(VSHIFT); // Vertical shift =0
+ N800Cmd(AUTOINCOFF); // auto increment off
+ N800Cmd(SETX); // set x coord
+ N800Cmd(0x40); // to 0
+ N800Cmd(SETY); // set y coord
+ N800Cmd(0); // to 0
+
+ m_pport->Release();
+
+ *m_oldConfig = *m_Config;
+
+ // Set Display SetBrightness
+ SetBrightness(m_Config->brightness);
+ // clear display
+ ClearVFDMem();
+ Refresh(true);
+
+ syslog(LOG_INFO, "%s: initialization done.\n", m_Config->name.c_str());
+ return 0;
+}
+
+void cDriverNoritake800::Refresh(bool refreshAll)
+{
+ //
+ // for VFD displays, we can safely ignore refreshAll, as they are "sticky"
+ //
+ int xb, yb;
+
+ if (CheckSetup() > 0)
+ refreshAll = true; // we don't use it
+
+ if (!m_pVFDMem || !m_pDrawMem)
+ return;
+
+// // just refresh if the time needed between refreshes is up
+// m_nRefreshCounter = (m_nRefreshCounter + 1) % m_Config->refreshDisplay;
+// if(!m_nRefreshCounter)
+// {
+ m_pport->Claim();
+ for (xb = 0; xb < width; ++xb)
+ {
+ for (yb = 0; yb < m_iSizeYb; ++yb)
+ {
+ if (m_pVFDMem[xb][yb] != m_pDrawMem[xb][yb])
+ {
+ m_pVFDMem[xb][yb] = m_pDrawMem[xb][yb];
+ // reset RefreshCounter
+ m_nRefreshCounter = 0;
+ // actually write to display
+ N800WriteByte(
+ (m_pVFDMem[xb][yb]) ^ ((m_Config->invert != 0) ? 0xff : 0x00),
+ xb,
+ yb,
+ 0);
+ }
+ }
+ }
+ m_pport->Release();
+// }
+}
+
+void cDriverNoritake800::N800Cmd(unsigned char data)
+{
+ if (m_bSleepIsInit)
+ nSleepInit();
+
+ // set direction to "port_output" & C/D to C
+ m_pport->WriteControl(m_pWiringMaskCache[0x00]);
+ // write to data port
+ m_pport->WriteData(data);
+ //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ // set /WR on the control port
+ m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_WR]);
+ //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ // reset /WR on the control port
+ m_pport->WriteControl(m_pWiringMaskCache[0x00]);
+ //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ // set direction to "port_input"
+ m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]);
+}
+
+void cDriverNoritake800::N800Data(unsigned char data)
+{
+ if (m_bSleepIsInit)
+ nSleepInit();
+
+ // set direction to "port_output" & C/D to C
+ m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]);
+ // write to data port
+ m_pport->WriteData(data);
+ //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ // set /WR on the control port
+ m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD | VFDSGN_WR]);
+ //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ // reset /WR on the control port
+ m_pport->WriteControl(m_pWiringMaskCache[VFDSGN_CD]);
+ //nSleep(100 + (100 * m_Config->adjustTiming) - m_nTimingAdjustCmd);
+ // set direction to "port_input"
+ m_pport->WriteControl(LPT_CTL_HI_DIR | m_pWiringMaskCache[0x00]);
+}
+
+void cDriverNoritake800::SetPixel(int x, int y)
+{
+ unsigned char c;
+
+ if (!m_pDrawMem)
+ return;
+
+ if (x >= width || x < 0)
+ return;
+ if (y >= height || y < 0)
+ return;
+
+ if (m_Config->upsideDown)
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ }
+
+ c = 0x80 >> (y % 8);
+
+ m_pDrawMem[x][y/8] |= c;
+}
+
+void cDriverNoritake800::Set8Pixels(int x, int y, unsigned char data)
+{
+ int n;
+
+ // x - pos is'nt mayby align to 8
+ x &= 0xFFF8;
+
+ for (n = 0; n < 8; ++n)
+ {
+ if (data & (0x80 >> n)) // if bit is set
+ SetPixel(x + n, y);
+ }
+}
+
+void cDriverNoritake800::SetBrightness(unsigned int percent)
+{
+ // display can do 16 brightness levels,
+ // 0 = light
+ // 15 = dark
+
+ // convert from "light percentage" into darkness values from 0 to 15
+ if (percent > 100)
+ {
+ percent = 100;
+ }
+ unsigned int darkness = 16 - (unsigned int)((double)percent * 16.0 / 100.0);
+
+ m_pport->Claim();
+ N800Cmd(0x40 + (darkness & 0xf));
+ m_pport->Release();
+}
+
+unsigned char cDriverNoritake800::N800LptWiringMask(unsigned char ctrl_bits)
+{
+ unsigned char newstatus = 0x0;
+
+ if (m_nWiring == WIRING_LIQUIDMP3)
+ {
+ if (ctrl_bits & VFDSGN_CSS)
+ newstatus |= LPT_CTL_LO_STROBE;
+ else
+ newstatus &= ~LPT_CTL_LO_STROBE;
+
+ if (ctrl_bits & VFDSGN_RD)
+ newstatus |= LPT_CTL_LO_LFEED;
+ else
+ newstatus &= ~LPT_CTL_LO_LFEED;
+
+ if (ctrl_bits & VFDSGN_WR)
+ newstatus |= LPT_CTL_LO_INIT;
+ else
+ newstatus &= ~LPT_CTL_LO_INIT;
+
+ if (ctrl_bits & VFDSGN_CD)
+ newstatus |= LPT_CTL_LO_SELECT;
+ else
+ newstatus &= ~LPT_CTL_LO_SELECT;
+
+ // control commands are XOR-ed with 0x5
+ // to account for active lows and highs
+ newstatus ^= 0x5;
+ }
+ else if (m_nWiring == WIRING_MZ)
+ {
+ if (ctrl_bits & VFDSGN_CSS)
+ newstatus |= LPT_CTL_LO_INIT;
+ else
+ newstatus &= ~LPT_CTL_LO_INIT;
+
+ if (ctrl_bits & VFDSGN_RD)
+ newstatus |= LPT_CTL_LO_LFEED;
+ else
+ newstatus &= ~LPT_CTL_LO_LFEED;
+
+ if (ctrl_bits & VFDSGN_WR)
+ newstatus |= LPT_CTL_LO_STROBE;
+ else
+ newstatus &= ~LPT_CTL_LO_STROBE;
+
+ if (ctrl_bits & VFDSGN_CD)
+ newstatus |= LPT_CTL_LO_SELECT;
+ else
+ newstatus &= ~LPT_CTL_LO_SELECT;
+ }
+ return newstatus;
+}
+
+void cDriverNoritake800::N800WriteByte(unsigned char data, int nCol, int nRow, int layer)
+{
+ /* set cursor to desired address */
+ N800Cmd(SETX); /* set upper cursor address */
+ N800Cmd(nCol);
+
+ if (layer==0)
+ {
+ N800Cmd(SETY); /* set lower cursor address */
+ N800Cmd(nRow); /*layer0 */
+ }
+ else if (layer==1)
+ {
+ N800Cmd(SETY); /* set lower cursor address */
+ N800Cmd(nRow+8); /* layer 1 */
+ }
+
+ N800Data(ReverseBits(data));
+}
+
+} // end of namespace
+
diff --git a/glcddrivers/noritake800.h b/glcddrivers/noritake800.h
new file mode 100644
index 0000000..cb2dfb0
--- /dev/null
+++ b/glcddrivers/noritake800.h
@@ -0,0 +1,92 @@
+/*
+ * GraphLCD driver library
+ *
+ * noritake800.h - Noritake 800(A) series VFD graphlcd driver,
+ * different "Medium 0.6 dot" sizes should work,
+ * see http://www.noritake-itron.com:
+ * - GU128X64-800A,
+ * - GU256X32-800A,
+ * - GU128X32-800A,
+ * - GU160X16-800A,
+ * - GU160X32-800A,
+ * - GU192X16-800A.
+ *
+ * based on:
+ * ideas and HW-command related stuff from the open source project
+ * "lcdplugin for Winamp":
+ * (c) 1999 - 2003 Markus Zehnder <lcdplugin AT markuszehnder.ch>
+ * GU256x64-372 driver module for graphlcd
+ * (c) 20040410 Andreas 'Randy' Weinberger <randy AT smue.org>
+ * gu140x32f driver module for graphlcd
+ * (c) 2003 Andreas Brachold <vdr04 AT deltab de>
+ * HD61830 device
+ * (c) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ * lcdproc 0.4 driver hd44780-ext8bit
+ * (c) 1999, 1995 Benjamin Tse <blt AT Comports.com>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Lucian Muresan <lucianm AT users.sourceforge.net>
+ */
+
+#ifndef _GLCDDRIVERS_NORITAKE800_H_
+#define _GLCDDRIVERS_NORITAKE800_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverNoritake800 : public cDriver
+{
+ cParallelPort * m_pport;
+
+ cDriverConfig * m_Config;
+ cDriverConfig * m_oldConfig;
+
+ int m_iSizeYb;
+ int m_nRefreshCounter;
+ int m_nWiring;
+
+ unsigned char ** m_pDrawMem; /* the draw "memory" */
+ unsigned char ** m_pVFDMem; /* the double buffed display "memory" */
+
+ long m_nTimingAdjustCmd;
+ bool m_bSleepIsInit;
+
+ // internal graphics layers
+ bool m_bGraphScreen0_On;
+ bool m_bGraphScreen1_On;
+
+ unsigned char * m_pWiringMaskCache;
+
+protected:
+ void ClearVFDMem();
+ void N800Cmd(unsigned char data);
+ void N800Data(unsigned char data);
+ int CheckSetup();
+ unsigned char N800LptWiringMask(unsigned char ctrl_bits);
+ void N800WriteByte(unsigned char data, int nCol, int nRow, int layer);
+
+public:
+ cDriverNoritake800(cDriverConfig * config);
+ virtual ~cDriverNoritake800();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void SetPixel(int x, int y);
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+
+ virtual void SetBrightness(unsigned int percent);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/port.c b/glcddrivers/port.c
new file mode 100644
index 0000000..d6e8e34
--- /dev/null
+++ b/glcddrivers/port.c
@@ -0,0 +1,350 @@
+/*
+ * GraphLCD driver library
+ *
+ * port.c - parallel port class with low level routines
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/io.h>
+#include <sys/ioctl.h>
+#include <linux/ppdev.h>
+#include <linux/parport.h>
+
+
+
+#include "port.h"
+
+namespace GLCD
+{
+
+static inline int port_in(int port)
+{
+ unsigned char value;
+ __asm__ volatile ("inb %1,%0"
+ : "=a" (value)
+ : "d" ((unsigned short) port));
+ return value;
+}
+
+static inline void port_out(unsigned short int port, unsigned char val)
+{
+ __asm__ volatile ("outb %0,%1\n"
+ :
+ : "a" (val), "d" (port));
+}
+
+cParallelPort::cParallelPort()
+: fd(-1),
+ port(0),
+ usePPDev(false)
+{
+}
+
+cParallelPort::~cParallelPort()
+{
+}
+
+int cParallelPort::Open(int portIO)
+{
+ usePPDev = false;
+ port = portIO;
+
+ if (port < 0x400)
+ {
+ if (ioperm(port, 3, 255) == -1)
+ {
+ syslog(LOG_ERR, "glcd drivers: ERROR ioperm(0x%X) failed! Err:%s (cParallelPort::Open)\n",
+ port, strerror(errno));
+ return -1;
+ }
+ }
+ else
+ {
+ if (iopl(3) == -1)
+ {
+ syslog(LOG_ERR, "glcd drivers: ERROR iopl failed! Err:%s (cParallelPort::Init)\n",
+ strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int cParallelPort::Open(const char * device)
+{
+ usePPDev = true;
+
+ fd = open(device, O_RDWR);
+ if (fd == -1)
+ {
+ syslog(LOG_ERR, "glcd drivers: ERROR cannot open %s. Err:%s (cParallelPort::Init)\n",
+ device, strerror(errno));
+ return -1;
+ }
+
+ if (ioctl(fd, PPCLAIM, NULL) == -1)
+ {
+ syslog(LOG_ERR, "glcd drivers: ERROR cannot claim %s. Err:%s (cParallelPort::Init)\n",
+ device, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ int mode = PARPORT_MODE_PCSPP;
+ if (ioctl(fd, PPSETMODE, &mode) == -1)
+ {
+ syslog(LOG_ERR, "glcd drivers: ERROR cannot setmode %s. Err:%s (cParallelPort::Init)\n",
+ device, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+int cParallelPort::Close()
+{
+ if (usePPDev)
+ {
+ if (fd != -1)
+ {
+ ioctl(fd, PPRELEASE);
+ close(fd);
+ fd = -1;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ if (port < 0x400)
+ {
+ if (ioperm(port, 3, 0) == -1)
+ {
+ return -1;
+ }
+ }
+ else
+ {
+ if (iopl(0) == -1)
+ {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+void cParallelPort::Claim()
+{
+ if (usePPDev)
+ ioctl(fd, PPCLAIM);
+}
+
+void cParallelPort::Release()
+{
+ if (usePPDev)
+ ioctl(fd, PPRELEASE);
+}
+
+void cParallelPort::SetDirection(int direction)
+{
+ if (usePPDev)
+ {
+ if (ioctl(fd, PPDATADIR, &direction) == -1)
+ {
+ perror("ioctl(PPDATADIR)");
+ //exit(1);
+ }
+ }
+ else
+ {
+ if (direction == kForward)
+ port_out(port + 2, port_in(port + 2) & 0xdf);
+ else
+ port_out(port + 2, port_in(port + 2) | 0x20);
+ }
+}
+
+unsigned char cParallelPort::ReadControl()
+{
+ unsigned char value;
+
+ if (usePPDev)
+ {
+ if (ioctl(fd, PPRCONTROL, &value) == -1)
+ {
+ perror("ioctl(PPRCONTROL)");
+ //exit(1);
+ }
+ }
+ else
+ {
+ value = port_in(port + 2);
+ }
+
+ return value;
+}
+
+void cParallelPort::WriteControl(unsigned char value)
+{
+ if (usePPDev)
+ {
+ if (ioctl(fd, PPWCONTROL, &value) == -1)
+ {
+ perror("ioctl(PPWCONTROL)");
+ //exit(1);
+ }
+ }
+ else
+ {
+ port_out(port + 2, value);
+ }
+}
+
+unsigned char cParallelPort::ReadStatus()
+{
+ unsigned char value;
+
+ if (usePPDev)
+ {
+ if (ioctl(fd, PPRSTATUS, &value) == -1)
+ {
+ perror("ioctl(PPRSTATUS)");
+ //exit(1);
+ }
+ }
+ else
+ {
+ value = port_in(port + 1);
+ }
+
+ return value;
+}
+
+unsigned char cParallelPort::ReadData()
+{
+ unsigned char data;
+
+ if (usePPDev)
+ {
+ if (ioctl(fd, PPRDATA, &data) == -1)
+ {
+ perror("ioctl(PPRDATA)");
+ //exit(1);
+ }
+ }
+ else
+ {
+ data = port_in(port);
+ }
+
+ return data;
+}
+
+void cParallelPort::WriteData(unsigned char data)
+{
+ if (usePPDev)
+ {
+ if (ioctl(fd, PPWDATA, &data) == -1)
+ {
+ perror("ioctl(PPWDATA)");
+ //exit(1);
+ }
+ }
+ else
+ {
+ port_out(port, data);
+ }
+}
+
+
+
+cSerialPort::cSerialPort()
+: fd(-1)
+{
+}
+
+cSerialPort::~cSerialPort()
+{
+}
+
+int cSerialPort::Open(const char * device)
+{
+ struct termios options;
+
+ fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
+ if (fd == -1)
+ {
+ printf("error opening port\n");
+ return -1;
+ }
+ //fcntl(fd, F_SETFL, FNDELAY);
+ fcntl(fd, F_SETFL, 0);
+
+ tcgetattr(fd, &options);
+
+ cfsetispeed(&options, B921600);
+ cfsetospeed(&options, B921600);
+
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag |= CS8;
+
+ options.c_cflag &= ~CRTSCTS;
+
+ options.c_cflag |= (CLOCAL | CREAD);
+
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+
+ options.c_iflag &= ~(IXON | IXOFF | IXANY);
+
+ options.c_oflag &= ~OPOST;
+
+ tcsetattr(fd, TCSANOW, &options);
+
+ return 0;
+}
+
+int cSerialPort::Close()
+{
+ if (fd == -1)
+ return -1;
+ close(fd);
+ return 0;
+}
+
+int cSerialPort::ReadData(unsigned char * data)
+{
+ if (fd == -1)
+ return 0;
+ return read(fd, data, 1);
+}
+
+void cSerialPort::WriteData(unsigned char data)
+{
+ WriteData(&data, 1);
+}
+
+void cSerialPort::WriteData(unsigned char * data, unsigned short length)
+{
+ if (fd == -1)
+ return;
+ write(fd, data, length);
+}
+
+} // end of namespace
diff --git a/glcddrivers/port.h b/glcddrivers/port.h
new file mode 100644
index 0000000..2920461
--- /dev/null
+++ b/glcddrivers/port.h
@@ -0,0 +1,78 @@
+/*
+ * GraphLCD driver library
+ *
+ * port.h - parallel port class with low level routines
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_PORT_H_
+#define _GLCDDRIVERS_PORT_H_
+
+namespace GLCD
+{
+
+const int kForward = 0;
+const int kReverse = 1;
+
+const unsigned char kStrobeHigh = 0x00; // Pin 1
+const unsigned char kStrobeLow = 0x01;
+const unsigned char kAutoHigh = 0x00; // Pin 14
+const unsigned char kAutoLow = 0x02;
+const unsigned char kInitHigh = 0x04; // Pin 16
+const unsigned char kInitLow = 0x00;
+const unsigned char kSelectHigh = 0x00; // Pin 17
+const unsigned char kSelectLow = 0x08;
+
+class cParallelPort
+{
+private:
+ int fd;
+ int port;
+ bool usePPDev;
+
+public:
+ cParallelPort();
+ ~cParallelPort();
+
+ int Open(int port);
+ int Open(const char * device);
+ int Close();
+
+ bool IsDirectIO() const { return (!usePPDev); }
+ int GetPortHandle() const { return ((usePPDev) ? fd : port); }
+
+ void Claim();
+ void Release();
+
+ void SetDirection(int direction);
+ unsigned char ReadControl();
+ void WriteControl(unsigned char values);
+ unsigned char ReadStatus();
+ unsigned char ReadData();
+ void WriteData(unsigned char data);
+};
+
+class cSerialPort
+{
+private:
+ int fd;
+
+public:
+ cSerialPort();
+ ~cSerialPort();
+
+ int Open(const char * device);
+ int Close();
+
+ int ReadData(unsigned char * data);
+ void WriteData(unsigned char data);
+ void WriteData(unsigned char * data, unsigned short length);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/sed1330.c b/glcddrivers/sed1330.c
new file mode 100644
index 0000000..34b1c74
--- /dev/null
+++ b/glcddrivers/sed1330.c
@@ -0,0 +1,630 @@
+/*
+ * GraphLCD driver library
+ *
+ * sed1330.c - SED1330 driver class
+ *
+ * based on: hd61830.c
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * changes for Seiko-Epson displays: Mar 2004
+ * (c) 2004 Heinz Gressenberger <heinz.gressenberger AT stmk.gv.at>
+ *
+ * init sequence taken from Thomas Baumann's LCD-Test program
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Roland Praml <praml.roland AT t-online.de>
+ */
+
+#include <syslog.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "port.h"
+#include "sed1330.h"
+
+
+namespace GLCD
+{
+
+// SED1330 Commands
+
+// Command Codes, Bytes for Param
+
+#define C_SYSTEMSET 0x40
+#define C_SLEEPIN 0x53
+#define C_DISPON 0x59
+#define C_DISPOFF 0x58
+#define C_SCROLL 0x44
+#define C_CSRFORM 0x5D
+#define C_CGRAMADR 0x5C
+#define C_CSRDIR_R 0x4C
+#define C_CSRDIR_L 0x4D
+#define C_CSRDIR_U 0x4E
+#define C_CSRDIR_D 0x4F
+#define C_HDOTSCR 0x5A
+#define C_OVLAY 0x5B
+#define C_CSRW 0x46
+#define C_CSRR 0x47
+#define C_MWRITE 0x42
+#define C_MREAD 0x43
+
+#define M0 0
+// 0-internal CG ROM, 1-external CG-ROM/RAM
+
+#define M1 0
+// 0 - 32 char CG-RAM, 1 - 64 char
+
+#define M2 0
+// 0 - 8x8, 1 - 8x16 matrix in CG-RAM/ROM
+
+#define FX 8
+// character-with
+#define FY 8
+// character-height
+#define BPC 1
+// byte per character, 1 - FX<=8, 2 - FX=9..16
+
+#define SAD1 0x0000
+// startadress first screen
+
+
+const int kInterface6800 = 0;
+const int kInterface8080 = 1;
+
+const std::string kWiringOriginal = "Original";
+const std::string kWiringPowerLCD = "PowerLCD";
+const std::string kWiringLCDProc = "LCDProc";
+const std::string kWiringTweakers = "Tweakers";
+const std::string kWiringYASEDW = "YASEDW";
+
+const unsigned char kOriginalA0HI = kInitHigh;
+const unsigned char kOriginalA0LO = kInitLow;
+const unsigned char kOriginalRDHI = kStrobeHigh;
+const unsigned char kOriginalRDLO = kStrobeLow;
+const unsigned char kOriginalWRHI = kAutoHigh;
+const unsigned char kOriginalWRLO = kAutoLow;
+const unsigned char kOriginalCSHI = kSelectHigh;
+const unsigned char kOriginalCSLO = kSelectLow;
+
+const unsigned char kPowerLCDA0HI = kInitHigh;
+const unsigned char kPowerLCDA0LO = kInitLow;
+const unsigned char kPowerLCDRDHI = kSelectHigh;
+const unsigned char kPowerLCDRDLO = kSelectLow;
+const unsigned char kPowerLCDWRHI = kStrobeHigh;
+const unsigned char kPowerLCDWRLO = kStrobeLow;
+const unsigned char kPowerLCDCSHI = kAutoHigh;
+const unsigned char kPowerLCDCSLO = kAutoLow;
+
+const unsigned char kLCDProcA0HI = kSelectHigh;
+const unsigned char kLCDProcA0LO = kSelectLow;
+const unsigned char kLCDProcRDHI = kInitHigh;
+const unsigned char kLCDProcRDLO = kInitLow;
+const unsigned char kLCDProcWRHI = kAutoHigh;
+const unsigned char kLCDProcWRLO = kAutoLow;
+const unsigned char kLCDProcCSHI = kStrobeHigh;
+const unsigned char kLCDProcCSLO = kStrobeLow;
+
+const unsigned char kTweakersA0HI = kSelectHigh;
+const unsigned char kTweakersA0LO = kSelectLow;
+const unsigned char kTweakersRDHI = kAutoHigh;
+const unsigned char kTweakersRDLO = kAutoLow;
+const unsigned char kTweakersWRHI = kInitHigh;
+const unsigned char kTweakersWRLO = kInitLow;
+const unsigned char kTweakersCSHI = kStrobeHigh;
+const unsigned char kTweakersCSLO = kStrobeLow;
+
+const unsigned char kYASEDWA0HI = kAutoHigh;
+const unsigned char kYASEDWA0LO = kAutoLow;
+const unsigned char kYASEDWRDHI = kInitHigh;
+const unsigned char kYASEDWRDLO = kInitLow;
+const unsigned char kYASEDWWRHI = kStrobeHigh;
+const unsigned char kYASEDWWRLO = kStrobeLow;
+const unsigned char kYASEDWCSHI = kSelectHigh;
+const unsigned char kYASEDWCSLO = kSelectLow;
+
+
+cDriverSED1330::cDriverSED1330(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ refreshCounter = 0;
+}
+
+cDriverSED1330::~cDriverSED1330()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverSED1330::Init()
+{
+ int x;
+ struct timeval tv1, tv2;
+
+ width = config->width;
+ if (width <= 0)
+ width = 320;
+ height = config->height;
+ if (height <= 0)
+ height = 240;
+
+ // default values
+ oscillatorFrequency = 9600;
+ interface = kInterface6800;
+ A0HI = kOriginalA0HI;
+ A0LO = kOriginalA0LO;
+ RDHI = kOriginalRDHI;
+ RDLO = kOriginalRDLO;
+ WRHI = kOriginalWRHI;
+ WRLO = kOriginalWRLO;
+ CSHI = kOriginalCSHI;
+ CSLO = kOriginalCSLO;
+ ENHI = RDHI;
+ ENLO = RDLO;
+ RWHI = WRHI;
+ RWLO = WRLO;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Wiring")
+ {
+ if (config->options[i].value == kWiringOriginal)
+ {
+ A0HI = kOriginalA0HI;
+ A0LO = kOriginalA0LO;
+ RDHI = kOriginalRDHI;
+ RDLO = kOriginalRDLO;
+ WRHI = kOriginalWRHI;
+ WRLO = kOriginalWRLO;
+ CSHI = kOriginalCSHI;
+ CSLO = kOriginalCSLO;
+ }
+ else if (config->options[i].value == kWiringPowerLCD)
+ {
+ A0HI = kPowerLCDA0HI;
+ A0LO = kPowerLCDA0LO;
+ RDHI = kPowerLCDRDHI;
+ RDLO = kPowerLCDRDLO;
+ WRHI = kPowerLCDWRHI;
+ WRLO = kPowerLCDWRLO;
+ CSHI = kPowerLCDCSHI;
+ CSLO = kPowerLCDCSLO;
+ }
+ else if (config->options[i].value == kWiringLCDProc)
+ {
+ A0HI = kLCDProcA0HI;
+ A0LO = kLCDProcA0LO;
+ RDHI = kLCDProcRDHI;
+ RDLO = kLCDProcRDLO;
+ WRHI = kLCDProcWRHI;
+ WRLO = kLCDProcWRLO;
+ CSHI = kLCDProcCSHI;
+ CSLO = kLCDProcCSLO;
+ }
+ else if (config->options[i].value == kWiringTweakers)
+ {
+ A0HI = kTweakersA0HI;
+ A0LO = kTweakersA0LO;
+ RDHI = kTweakersRDHI;
+ RDLO = kTweakersRDLO;
+ WRHI = kTweakersWRHI;
+ WRLO = kTweakersWRLO;
+ CSHI = kTweakersCSHI;
+ CSLO = kTweakersCSLO;
+ }
+ else if (config->options[i].value == kWiringYASEDW)
+ {
+ A0HI = kYASEDWA0HI;
+ A0LO = kYASEDWA0LO;
+ RDHI = kYASEDWRDHI;
+ RDLO = kYASEDWRDLO;
+ WRHI = kYASEDWWRHI;
+ WRLO = kYASEDWWRLO;
+ CSHI = kYASEDWCSHI;
+ CSLO = kYASEDWCSLO;
+ }
+ else
+ {
+ syslog(LOG_ERR, "%s error: wiring %s not supported, using default (Original)!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
+ ENHI = RDHI;
+ ENLO = RDLO;
+ RWHI = WRHI;
+ RWLO = WRLO;
+ }
+ else if (config->options[i].name == "OscillatorFrequency")
+ {
+ int freq = atoi(config->options[i].value.c_str());
+ if (freq > 1000 && freq < 15000)
+ oscillatorFrequency = freq;
+ else
+ syslog(LOG_ERR, "%s error: oscillator frequency %d out of range, using default (%d)!\n",
+ config->name.c_str(), freq, oscillatorFrequency);
+ }
+ if (config->options[i].name == "Interface")
+ {
+ if (config->options[i].value == "6800")
+ interface = kInterface6800;
+ else if (config->options[i].value == "8080")
+ interface = kInterface8080;
+ else
+ syslog(LOG_ERR, "%s error: interface %s not supported, using default (6800)!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
+ }
+
+ // setup lcd array (wanted state)
+ newLCD = new unsigned char *[(width + 7) / 8];
+ if (newLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ newLCD[x] = new unsigned char[height];
+ memset(newLCD[x], 0, height);
+ }
+ }
+ // setup lcd array (current state)
+ oldLCD = new unsigned char *[(width + 7) / 8];
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ oldLCD[x] = new unsigned char[height];
+ memset(oldLCD[x], 0, height);
+ }
+ }
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_DEBUG, "%s: INFO: cannot change wait parameters (cDriver::Init)\n", config->name.c_str());
+ useSleepInit = false;
+ }
+ else
+ {
+ useSleepInit = true;
+ }
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (x = 0; x < 1000; x++)
+ {
+ port->WriteData(x % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ if (useSleepInit)
+ nSleepDeInit();
+ timeForPortCmdInNs = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Command: %ldns\n", config->name.c_str(), timeForPortCmdInNs);
+
+ // initialize graphic mode
+ InitGraphic();
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+ // The SED1330 can have up to 64k memory. If there is less memory
+ // it will be overwritten twice or more times.
+ WriteCmd(C_MWRITE);
+ for (x = 0; x < 65536; x++)
+ WriteData(0x00);
+
+ WriteCmd(C_CSRW);
+ WriteData(0x00); // initializing cursor adress, low byte
+ WriteData(0x00); // high byte
+
+ port->Release();
+
+ syslog(LOG_INFO, "%s: SED1330 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverSED1330::DeInit()
+{
+ int x;
+
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] newLCD[x];
+ }
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] oldLCD[x];
+ }
+ delete[] oldLCD;
+ }
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverSED1330::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+int cDriverSED1330::InitGraphic()
+{
+ // initialize setup with two graphic screens
+ // most parts taken from Thomas Baumann's LCD-Test program
+ int cr;
+ int memGraph;
+ int sad1l, sad1h, sad2l, sad2h;
+
+ cr = (width / FX - 1) * BPC;
+ memGraph = ((cr + 1) * height); // required memory for a graphic layer
+ sad1l = SAD1 & 0xFF;
+ sad1h = SAD1 >> 8 & 0xFF;
+ sad2l = ((SAD1 + memGraph) & 0xFF);
+ sad2h = ((SAD1 + memGraph) >> 8 & 0xFF);
+
+ WriteCmd(C_SYSTEMSET);
+ WriteData(0x30 + M0 + (M1 << 1) + (M2 << 2));
+ WriteData(0x80 + (FX - 1));
+ WriteData(0x00 + (FY - 1));
+ WriteData(cr); // C/R .. display adresses per line
+ WriteData((oscillatorFrequency * 1000 / (70 * height) - 1) / 9); // TC/R .. , fFR=70Hz
+ WriteData(height - 1); // L/F .. display lines per screen
+ WriteData(cr + 1); // adresses per virtual display line, low byte
+ WriteData(0x00); // adresses per virtual display line, high byte
+ // currently we don't use virtual screens greater then the display,
+ // therefore the high byte should always be zero
+
+ WriteCmd(C_SCROLL);
+ WriteData(sad1l); // low-byte startadress first layer
+ WriteData(sad1h); // high-byte startadress first layer
+ WriteData(height); // lines per screen
+ WriteData(sad2l); // low-byte startadress second layer
+ WriteData(sad2h); // high-byte startadress second layer
+ WriteData(height); // lines per screen
+ WriteData(0x00); // low-byte startadress third layer, not used
+ WriteData(0x00); // high-byte startadress third layer, not used
+ WriteData(0x00); // low-byte startadress fourth layer, not used
+ WriteData(0x00); // high-byte startadress fourth layer, not used
+
+ WriteCmd(C_CSRFORM);
+ WriteData(0x00); // cursor with: 1 pixel
+ WriteData(0x86); // cursor height: 7 lines, block mode
+
+ WriteCmd(C_CSRDIR_R); // automatic cursor increment to the right
+
+ WriteCmd(C_OVLAY);
+ WriteData(0x0C); // two layer composition with Priority-OR
+
+ WriteCmd(C_HDOTSCR);
+ WriteData(0x00);
+
+ WriteCmd(C_DISPON); // display ON with
+ WriteData(0x04); // cursor OFF and first layer ON without flashing
+
+ WriteCmd(C_CSRW);
+ WriteData(0x00); // initializing cursor adress, low byte
+ WriteData(0x00); // high byte
+
+ return 0;
+}
+
+void cDriverSED1330::WriteCmd(unsigned char cmd)
+{
+ //if (useSleepInit)
+ // nSleepInit();
+
+ if (interface == kInterface6800)
+ {
+ // set A0 high (instruction), RW low (write) and E low
+ port->WriteControl(A0HI | CSLO | RWLO | ENLO);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // Output the actual command
+ port->WriteData(cmd);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set E high
+ port->WriteControl(A0HI | CSLO | RWLO | ENHI);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set E low
+ port->WriteControl(A0HI | CSLO | RWLO | ENLO);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ }
+ else
+ {
+ // set A0 high (instruction), CS low, RD and WR high
+ port->WriteControl(A0HI | CSLO | RDHI | WRHI);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // Output the actual command
+ port->WriteData(cmd);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set WR low
+ port->WriteControl(A0HI | CSLO | RDHI | WRLO);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set WR high
+ port->WriteControl(A0HI | CSLO | RDHI | WRHI);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ }
+
+ //if (useSleepInit)
+ // nSleepDeInit();
+}
+
+void cDriverSED1330::WriteData(unsigned char data)
+{
+ //if (useSleepInit)
+ // nSleepInit();
+
+ if (interface == kInterface6800)
+ {
+ // set A0 low (data), RW low (write) and E low
+ port->WriteControl(A0LO | CSLO | RWLO | ENLO);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // Output the actual data
+ port->WriteData(data);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set E high
+ port->WriteControl(A0LO | CSLO | RWLO | ENHI);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set E low
+ port->WriteControl(A0LO | CSLO | RWLO | ENLO);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ }
+ else
+ {
+ // set A0 low (data), CS low, RD and WR high
+ port->WriteControl(A0LO | CSLO | RDHI | WRHI);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // Output the actual data
+ port->WriteData(data);
+ //nSleep(140 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set WR low
+ port->WriteControl(A0LO | CSLO | RDHI | WRLO);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ // set WR high
+ port->WriteControl(A0LO | CSLO | RDHI | WRHI);
+ //nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ }
+
+ //if (useSleepInit)
+ // nSleepDeInit();
+}
+
+void cDriverSED1330::Clear()
+{
+ for (int x = 0; x < (width + 7) / 8; x++)
+ memset(newLCD[x], 0, height);
+}
+
+void cDriverSED1330::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ newLCD[x / 8][y] = newLCD[x / 8][y] | data;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ newLCD[x / 8][y] = newLCD[x / 8][y] | ReverseBits(data);
+ }
+}
+
+void cDriverSED1330::Refresh(bool refreshAll)
+{
+ int x;
+ int y;
+ int pos = SAD1;
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ port->Claim();
+
+ if (refreshAll)
+ {
+ // draw all
+ // set cursor to startadress
+ WriteCmd(C_CSRW);
+ WriteData(pos & 0xFF);
+ WriteData(pos >> 8);
+
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ WriteCmd(C_MWRITE); // cursor increments automatically
+ WriteData(newLCD[x][y] ^ (config->invert ? 0xff : 0x00));
+ oldLCD[x][y] = newLCD[x][y];
+ pos++;
+ }
+ }
+ // and reset RefreshCounter
+ refreshCounter = 0;
+ }
+ else
+ {
+ // draw only the changed bytes
+ bool cs = false;
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ if (newLCD[x][y] != oldLCD[x][y])
+ {
+ if (!cs)
+ {
+ WriteCmd(C_CSRW);
+ WriteData(pos & 0xFF);
+ WriteData(pos >> 8);
+ WriteCmd(C_MWRITE);
+ cs = true;
+ }
+ WriteData(newLCD[x][y] ^ (config->invert ? 0xff : 0x00));
+ oldLCD[x][y] = newLCD[x][y];
+ }
+ else
+ {
+ cs = false;
+ }
+ pos++;
+ }
+ }
+ }
+ port->Release();
+}
+
+} // end of namespace
diff --git a/glcddrivers/sed1330.h b/glcddrivers/sed1330.h
new file mode 100644
index 0000000..354b853
--- /dev/null
+++ b/glcddrivers/sed1330.h
@@ -0,0 +1,78 @@
+/*
+ * GraphLCD driver library
+ *
+ * sed1330.h - SED1330 driver class
+ *
+ * based on: hd61830.c
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * changes for Seiko-Epson displays: Mar 2004
+ * (c) 2004 Heinz Gressenberger <heinz.gressenberger AT stmk.gv.at>
+ *
+ * init sequence taken from Thomas Baumann's LCD-Test program
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Roland Praml <praml.roland AT t-online.de>
+ */
+
+#ifndef _GLCDDRIVERS_SED1330_H_
+#define _GLCDDRIVERS_SED1330_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverSED1330 : public cDriver
+{
+private:
+ cParallelPort * port;
+ unsigned char ** newLCD; // wanted state
+ unsigned char ** oldLCD; // current state
+ int refreshCounter;
+ long timeForPortCmdInNs;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ bool useSleepInit;
+
+ int oscillatorFrequency;
+ int interface;
+ unsigned char A0HI;
+ unsigned char A0LO;
+ unsigned char RDHI;
+ unsigned char RDLO;
+ unsigned char ENHI;
+ unsigned char ENLO;
+ unsigned char WRHI;
+ unsigned char WRLO;
+ unsigned char RWHI;
+ unsigned char RWLO;
+ unsigned char CSHI;
+ unsigned char CSLO;
+
+ int CheckSetup();
+ int InitGraphic();
+ void WriteCmd(unsigned char cmd);
+ void WriteData(unsigned char data);
+
+public:
+ cDriverSED1330(cDriverConfig * config);
+ virtual ~cDriverSED1330();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/sed1520.c b/glcddrivers/sed1520.c
new file mode 100644
index 0000000..67da56d
--- /dev/null
+++ b/glcddrivers/sed1520.c
@@ -0,0 +1,402 @@
+/*
+ * GraphLCD driver library
+ *
+ * sed1520.c - SED1520 driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ */
+
+#include <syslog.h>
+#include <sys/time.h>
+
+#include "common.h"
+#include "config.h"
+#include "port.h"
+#include "sed1520.h"
+
+
+namespace GLCD
+{
+
+// commands
+const unsigned char kSEAD = 0x00; // Set (X) Column Address
+const unsigned char kSEPA = 0xb8; // Set (Y) Page Address
+const unsigned char kSEDS = 0xc0; // Set Display Start Line
+const unsigned char kDION = 0xaf; // Display on
+const unsigned char kDIOF = 0xae; // Display off
+
+// control bits for DirectIO
+#define CE1 0x01
+#define CE1HI 0x01 // Chip Enable 1 on
+#define CE1LO 0x00 // Chip Enable 1 off
+
+const unsigned char kCS1HI = 0x00; // Chip Select 1
+const unsigned char kCS1LO = 0x01;
+const unsigned char kCS2HI = 0x04; // Chip Select 2
+const unsigned char kCS2LO = 0x00;
+const unsigned char kCDHI = 0x08; // Command/Data Register Select
+const unsigned char kCDLO = 0x00;
+const unsigned char kLEDHI = 0x02; // LED Backlight (not supported currently)
+const unsigned char kLEDLO = 0x00;
+
+
+cDriverSED1520::cDriverSED1520(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ refreshCounter = 0;
+}
+
+cDriverSED1520::~cDriverSED1520()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverSED1520::Init()
+{
+ int x;
+ int i;
+ struct timeval tv1, tv2;
+
+ if (!(config->width % 8) == 0) {
+ width = config->width + (8 - (config->width % 8));
+ } else {
+ width = config->width;
+ }
+
+ if (!(config->height % 8) == 0) {
+ height = config->height + (8 - (config->height % 8));
+ } else {
+ height = config->height;
+ }
+
+ if (width <= 0)
+ width = 120;
+ if (height <= 0)
+ height = 32;
+
+ SEAD = kSEAD;
+ SEPA = kSEPA;
+ SEDS = kSEDS;
+ DION = kDION;
+ DIOF = kDIOF;
+ LED = kLEDHI;
+ CDHI = kCDHI;
+ CDLO = kCDLO;
+ CS1HI = kCS1HI;
+ CS1LO = kCS1LO;
+ CS2HI = kCS2HI;
+ CS2LO = kCS2LO;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup linear lcd array
+ LCD = new unsigned char *[(width + 7) / 8];
+ if (LCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ LCD[x] = new unsigned char[height];
+ memset(LCD[x], 0, height);
+ }
+ }
+ // setup the lcd array for the paged sed1520
+ LCD_page = new unsigned char *[width];
+ if (LCD_page)
+ {
+ for (x = 0; x < width; x++)
+ {
+ LCD_page[x] = new unsigned char[(height + 7) / 8];
+ memset(LCD_page[x], 0, (height + 7) / 8);
+ }
+ }
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ if (nSleepInit() != 0)
+ {
+ syslog(LOG_DEBUG, "%s: INFO: cannot change wait parameters (cDriver::Init)\n", config->name.c_str());
+ useSleepInit = false;
+ }
+ else
+ {
+ useSleepInit = true;
+ }
+
+ syslog(LOG_DEBUG, "%s: benchmark started.\n", config->name.c_str());
+ gettimeofday(&tv1, 0);
+ for (i = 0; i < 1000; i++)
+ {
+ port->WriteData(i % 0x100);
+ }
+ gettimeofday(&tv2, 0);
+ if (useSleepInit)
+ nSleepDeInit();
+ timeForPortCmdInNs = (tv2.tv_sec - tv1.tv_sec) * 1000000 + (tv2.tv_usec - tv1.tv_usec);
+ syslog(LOG_DEBUG, "%s: benchmark stopped. Time for Command: %ldns\n", config->name.c_str(), timeForPortCmdInNs);
+
+ // initialize graphic mode
+ InitGraphic();
+
+ port->Release();
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: SED1520 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverSED1520::DeInit()
+{
+ int x;
+
+ // free linear lcd array
+ if (LCD)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] LCD[x];
+ }
+ delete[] LCD;
+ }
+ // free the lcd array for the paged sed1520
+ if (LCD_page)
+ {
+ for (x = 0; x < width; x++)
+ {
+ delete[] LCD_page[x];
+ }
+ delete[] LCD_page;
+ }
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverSED1520::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+int cDriverSED1520::InitGraphic()
+{
+ // initialize controller1, set display start 0, set page 0, set y address 0, display on
+ SED1520Cmd(SEDS, 1);
+ SED1520Cmd(SEPA, 1);
+ SED1520Cmd(SEAD, 1);
+ SED1520Cmd(DION, 1);
+
+ // initialize controller2, set display start 0, set page 0, set y address 0, display on
+ SED1520Cmd(SEDS, 2);
+ SED1520Cmd(SEPA, 2);
+ SED1520Cmd(SEAD, 2);
+ SED1520Cmd(DION, 2);
+
+ return 0;
+}
+
+void cDriverSED1520::SED1520Cmd(unsigned char data, int cmdcs)
+{
+ if (useSleepInit)
+ nSleepInit();
+
+ switch (cmdcs)
+ {
+ case 1:
+ port->WriteControl(CDHI | CS1LO | CS2LO | LEDHI);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep(650 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteControl(CDHI | CS1HI | CS2LO | LEDHI);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ break;
+ case 2:
+ port->WriteControl(CDHI | CS1LO | CS2LO | LED);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep(650 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteControl(CDHI | CS1LO | CS2HI | LED);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ break;
+ }
+ if (useSleepInit)
+ nSleepDeInit();
+}
+
+void cDriverSED1520::SED1520Data(unsigned char data, int datacs)
+{
+ if (useSleepInit)
+ nSleepInit();
+
+ switch (datacs)
+ {
+ case 1:
+ port->WriteControl(CDLO | CS1LO | CS2LO | LEDHI);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep(650 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteControl(CDLO | CS1HI | CS2LO | LEDHI);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ break;
+ case 2:
+ port->WriteControl(CDLO | CS1LO | CS2LO | LED);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteData(data);
+ nSleep(650 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ port->WriteControl(CDLO | CS1LO | CS2HI | LED);
+ nSleep(450 - timeForPortCmdInNs + 100 * config->adjustTiming);
+ break;
+ }
+ if (useSleepInit)
+ nSleepDeInit();
+}
+
+void cDriverSED1520::Clear()
+{
+ for (int x = 0; x < (width + 7) / 8; x++)
+ memset(LCD[x], 0, height);
+}
+
+void cDriverSED1520::Set8Pixels (int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ LCD[x / 8][y] = LCD[x / 8][y] | data;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ LCD[x / 8][y] = LCD[x / 8][y] | ReverseBits(data);
+ }
+}
+
+void cDriverSED1520::Refresh(bool refreshAll)
+{
+ int x,y,xx,yy;
+ unsigned char dByte, oneBlock[8];
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ refreshAll = true; // differential update is not yet supported
+
+ if (refreshAll)
+ {
+ // draw all
+
+ // convert the linear lcd array to the paged array for the display
+ for (y = 0; y < (height + 7) / 8; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ for (yy = 0; yy < 8; yy++)
+ {
+ oneBlock[yy] = LCD[x][yy + (y * 8)] ^ (config->invert ? 0xff : 0x00);
+ }
+ for (xx = 0; xx < 8; xx++)
+ {
+ dByte = 0;
+ for (yy = 0; yy < 8; yy++)
+ {
+ if (oneBlock[yy] & bitmask[xx])
+ {
+ dByte += (1 << yy);
+ }
+ }
+ LCD_page[x * 8 + xx][y] = dByte;
+ }
+ }
+ }
+
+ port->Claim();
+
+ // send lcd_soll data to display, controller 1
+ // set page and start address
+ for (y = 0; y < (height + 7) / 8; y++)
+ {
+ SED1520Cmd(SEAD, 1);
+ SED1520Cmd(SEPA + y, 1);
+ SED1520Data(0x00 ^ (config->invert ? 0xff : 0x00), 1); // fill first row with zero
+
+ for (x = 0; x < width / 2 + 1; x++)
+ {
+ SED1520Data(LCD_page[x][y], 1);
+ }
+
+ SED1520Cmd(SEAD, 2);
+ SED1520Cmd(SEPA + y, 2);
+
+ for (x = width / 2; x < width; x++)
+ {
+ SED1520Data(LCD_page[x][y], 2);
+ }
+
+ SED1520Data(0x00 ^ (config->invert ? 0xff : 0x00), 2); // fill last row with zero
+ }
+ port->Release();
+ }
+ else
+ {
+ // draw only the changed bytes
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/sed1520.h b/glcddrivers/sed1520.h
new file mode 100644
index 0000000..931d51b
--- /dev/null
+++ b/glcddrivers/sed1520.h
@@ -0,0 +1,72 @@
+/*
+ * GraphLCD driver library
+ *
+ * sed1520.h - SED1520 driver class
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003 Andreas 'randy' Weinberger <vdr AT smue.org>
+ */
+
+#ifndef _GLCDDRIVERS_SED1520_H_
+#define _GLCDDRIVERS_SED1520_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverSED1520 : public cDriver
+{
+private:
+ cParallelPort * port;
+ unsigned char ** LCD; // linear lcd display "memory"
+ unsigned char ** LCD_page; // paged lcd display "memory"
+ int refreshCounter;
+ long timeForPortCmdInNs;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ bool useSleepInit;
+
+ int SEAD;
+ int SEPA;
+ int SEDS;
+ int DION;
+ int DIOF;
+
+ int CS1LO;
+ int CS2LO;
+ int CS1HI;
+ int CS2HI;
+
+ int CDHI;
+ int CDLO;
+
+ int LED;
+ int LEDHI;
+
+ int CheckSetup();
+ int InitGraphic();
+ void SED1520Cmd(unsigned char data, int cmscd);
+ void SED1520Data(unsigned char data, int datacs);
+
+public:
+ cDriverSED1520(cDriverConfig * config);
+ virtual ~cDriverSED1520();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/serdisp.c b/glcddrivers/serdisp.c
new file mode 100644
index 0000000..d1bf6f1
--- /dev/null
+++ b/glcddrivers/serdisp.c
@@ -0,0 +1,467 @@
+/*
+ * GraphLCD driver library
+ *
+ * serdisp.h - include support for displays supported by serdisplib (if library is installed)
+ * http://serdisplib.sourceforge.net
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003-2005 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <dlfcn.h>
+
+#include "common.h"
+#include "config.h"
+#include "serdisp.h"
+
+#define SERDISP_VERSION(a,b) ((long)(((a) << 8) + (b)))
+#define SERDISP_VERSION_GET_MAJOR(_c) ((int)( (_c) >> 8 ))
+#define SERDISP_VERSION_GET_MINOR(_c) ((int)( (_c) & 0xFF ))
+
+// taken from serdisp_control.h
+#define FEATURE_CONTRAST 0x01
+#define FEATURE_REVERSE 0x02
+#define FEATURE_BACKLIGHT 0x03
+#define FEATURE_ROTATE 0x04
+
+#define SD_COL_BLACK 0xFF000000
+
+namespace GLCD
+{
+
+cDriverSerDisp::cDriverSerDisp(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ dd = (void *) NULL;
+}
+
+cDriverSerDisp::~cDriverSerDisp(void)
+{
+ delete oldConfig;
+}
+
+int cDriverSerDisp::Init(void)
+{
+ char* errmsg; // error message returned by dlerror()
+
+ std::string controller;
+ std::string optionstring = "";
+ std::string wiringstring;
+
+
+ // dynamically load serdisplib using dlopen() & co.
+
+ sdhnd = dlopen("libserdisp.so", RTLD_LAZY);
+ if (!sdhnd) { // try /usr/local/lib
+ sdhnd = dlopen("/usr/local/lib/libserdisp.so", RTLD_LAZY);
+ }
+
+ if (!sdhnd) { // serdisplib seems not to be installed
+ syslog(LOG_ERR, "%s: error: unable to dynamically load library '%s'. Err: %s (cDriver::Init)\n",
+ config->name.c_str(), "libserdisp.so", "not found");
+ return -1;
+ }
+
+ dlerror(); // clear error code
+
+ /* pre-init some flags, function pointers, ... */
+ supports_options = 0;
+ fg_colour = 1;
+ bg_colour = -1;
+
+ // get serdisp version
+ fp_serdisp_getversioncode = (long int (*)()) dlsym(sdhnd, "serdisp_getversioncode");
+
+ if (dlerror()) { // no serdisp_getversioncode() -> version of serdisplib is < 1.95
+ syslog(LOG_DEBUG, "%s: INFO: symbol serdisp_getversioncode unknown: autodetecting pre 1.95 serdisplib version (cDriver::Init)\n",
+ config->name.c_str());
+
+ fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
+ if (dlerror()) { // no SDCONN_open() -> version of serdisplib is < 1.93
+ serdisp_version = SERDISP_VERSION(1,92);
+ syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version <= 1.92 (cDriver::Init)\n", config->name.c_str());
+
+ fp_PP_open = (void*(*)(const char*))dlsym(sdhnd, "PP_open");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "PP_open", errmsg);
+ return -1;
+ }
+ fp_PP_close = (void*(*)(void*))dlsym(sdhnd, "PP_close");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "PP_close", errmsg);
+ return -1;
+ }
+ } else {
+ serdisp_version = SERDISP_VERSION(1,94); // no serdisp_getversioncode, but SDCONN_open: 1.93 or 1.94
+ syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version 1.93 or 1.94 (cDriver::Init)\n", config->name.c_str());
+
+ fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_quit", errmsg);
+ return -1;
+ }
+ }
+
+ fp_serdisp_setpixcol = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setpixel");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_setpixel", errmsg);
+ return -1;
+ }
+ fg_colour = 1; /* set foreground to 'pixel on' */
+
+ } else { // serdisp version >= 1.95
+ serdisp_version = fp_serdisp_getversioncode();
+ syslog(LOG_DEBUG, "%s: INFO: detected serdisplib version %d.%d (cDriver::Init)\n",
+ config->name.c_str(), SERDISP_VERSION_GET_MAJOR(serdisp_version), SERDISP_VERSION_GET_MINOR(serdisp_version));
+
+
+ fp_SDCONN_open = (void*(*)(const char*)) dlsym(sdhnd, "SDCONN_open");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "SDCONN_open", errmsg);
+ return -1;
+ }
+ fp_serdisp_quit = (void (*)(void*)) dlsym(sdhnd, "serdisp_quit");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_quit", errmsg);
+ return -1;
+ }
+ fp_serdisp_setpixcol = (void (*)(void*, int, int, long int)) dlsym(sdhnd, "serdisp_setcolour");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_setcolour", errmsg);
+ return -1;
+ }
+ fg_colour = SD_COL_BLACK; /* set foreground colour to black */
+
+ if (serdisp_version >= SERDISP_VERSION(1,96) ) {
+ supports_options = 1;
+
+ fp_serdisp_isoption = (int (*)(void*, const char*)) dlsym(sdhnd, "serdisp_isoption");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_isoption", errmsg);
+ return -1;
+ }
+ fp_serdisp_setoption = (void (*)(void*, const char*, long int)) dlsym(sdhnd, "serdisp_setoption");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_setoption", errmsg);
+ return -1;
+ }
+ } /* >= 1.96 */
+ }
+
+ // load other symbols that will be required
+ fp_serdisp_init = (void*(*)(void*, const char*, const char*)) dlsym(sdhnd, "serdisp_init");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_init", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_rewrite = (void (*)(void*)) dlsym(sdhnd, "serdisp_rewrite");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_rewrite", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_update = (void (*)(void*)) dlsym(sdhnd, "serdisp_update");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_update", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_clearbuffer = (void (*)(void*)) dlsym(sdhnd, "serdisp_clearbuffer");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_clearbuffer", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_feature = (int (*)(void*, int, int)) dlsym(sdhnd, "serdisp_feature");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_feature", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_close = (void (*)(void*))dlsym(sdhnd, "serdisp_close");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_close", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_getwidth = (int (*)(void*)) dlsym(sdhnd, "serdisp_getwidth");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_getwidth", errmsg);
+ return -1;
+ }
+
+ fp_serdisp_getheight = (int (*)(void*)) dlsym(sdhnd, "serdisp_getheight");
+ if ( (errmsg = dlerror()) != NULL ) { // should not happen
+ syslog(LOG_ERR, "%s: error: cannot load symbol %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), "serdisp_getheight", errmsg);
+ return -1;
+ }
+
+ // done loading all required symbols
+
+
+ // setting up the display
+ width = 0;
+ height = 0;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "Controller") {
+ controller = config->options[i].value;
+ } else if (config->options[i].name == "Options") {
+ optionstring = config->options[i].value;
+ } else if (config->options[i].name == "Wiring") {
+ wiringstring = config->options[i].value;
+ } else if (config->options[i].name == "FGColour") {
+ fg_colour = strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
+ fg_colour |= 0xFF000000L; /* force alpha to 0xFF */
+ } else if (config->options[i].name == "BGColour") {
+ bg_colour = strtoul(config->options[i].value.c_str(), (char **)NULL, 0);
+ bg_colour |= 0xFF000000L; /* force alpha to 0xFF */
+ }
+ }
+
+ if (wiringstring.length()) {
+ optionstring = "WIRING=" + wiringstring + ((optionstring != "") ? ";" + optionstring : "");
+ }
+
+ if (controller == "")
+ {
+ syslog(LOG_ERR, "%s error: no controller given!\n", config->name.c_str());
+ return -1;
+ }
+
+
+ if (config->device == "")
+ {
+ // use DirectIO
+
+ // neither device nor port is set
+ if (config->port == 0)
+ return -1;
+
+ char temp[10];
+ snprintf(temp, 8, "0x%x", config->port);
+
+ if (serdisp_version < SERDISP_VERSION(1,93) ) {
+ sdcd = fp_PP_open(temp);
+ } else {
+ sdcd = fp_SDCONN_open(temp);
+ }
+
+ if (sdcd == 0) {
+ syslog(LOG_ERR, "%s: error: unable to open port 0x%x for display %s. (cDriver::Init)\n",
+ config->name.c_str(), config->port, controller.c_str());
+ return -1;
+ }
+
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (serdisp_version < SERDISP_VERSION(1,93) ) {
+ sdcd = fp_PP_open(config->device.c_str());
+ } else {
+ sdcd = fp_SDCONN_open(config->device.c_str());
+ }
+
+ if (sdcd == 0) {
+ syslog(LOG_ERR, "%s: error: unable to open device %s for display %s. (cDriver::Init)\n",
+ config->name.c_str(), config->device.c_str(), controller.c_str());
+ return -1;
+ }
+ }
+
+ if (serdisp_version < SERDISP_VERSION(1,95) )
+ dd = fp_serdisp_init(sdcd, controller.c_str(), "");
+ else
+ dd = fp_serdisp_init(sdcd, controller.c_str(), optionstring.c_str());
+
+ if (!dd)
+ {
+ syslog(LOG_ERR, "%s: error: cannot open display %s. Err:%s (cDriver::Init)\n",
+ config->name.c_str(), controller.c_str(), "no handle");
+ return -1;
+ }
+
+ width = config->width;
+ if (width <= 0)
+ width = fp_serdisp_getwidth(dd);
+ height = config->height;
+ if (height <= 0)
+ height = fp_serdisp_getheight(dd);
+
+ if (serdisp_version < SERDISP_VERSION(1,96) ) {
+ fp_serdisp_feature(dd, FEATURE_ROTATE, config->upsideDown);
+ fp_serdisp_feature(dd, FEATURE_CONTRAST, config->contrast);
+ fp_serdisp_feature(dd, FEATURE_BACKLIGHT, config->backlight);
+ fp_serdisp_feature(dd, FEATURE_REVERSE, config->invert);
+ } else {
+ /* standard options */
+ fp_serdisp_setoption(dd, "ROTATE", config->upsideDown);
+ fp_serdisp_setoption(dd, "CONTRAST", config->contrast);
+ fp_serdisp_setoption(dd, "BACKLIGHT", config->backlight);
+ fp_serdisp_setoption(dd, "INVERT", config->invert);
+
+ /* driver dependend options */
+ for (unsigned int i = 0; i < config->options.size(); i++) {
+ std::string optionname = config->options[i].name;
+ if (optionname != "UpsideDown" && optionname != "Contrast" &&
+ optionname != "Backlight" && optionname != "Invert") {
+
+ if ( fp_serdisp_isoption(dd, optionname.c_str()) == 1 ) /* if == 1: option is existing AND r/w */
+ fp_serdisp_setoption(dd, optionname.c_str(), strtol(config->options[i].value.c_str(), NULL, 0));
+ }
+ }
+
+ }
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: SerDisp with %s initialized.\n", config->name.c_str(), controller.c_str());
+ return 0;
+}
+
+int cDriverSerDisp::DeInit(void)
+{
+ if (serdisp_version < SERDISP_VERSION(1,93) ) {
+ fp_serdisp_close(dd);
+ fp_PP_close(sdcd);
+ sdcd = NULL;
+ } else {
+ //fp_serdisp_quit(dd);
+ /* use serdisp_close instead of serdisp_quit so that showpic and showtext are usable together with serdisplib */
+ fp_serdisp_close(dd);
+ }
+ (int) dlclose(sdhnd);
+ sdhnd = NULL;
+
+ return 0;
+}
+
+int cDriverSerDisp::CheckSetup()
+{
+ bool update = false;
+
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->contrast != oldConfig->contrast)
+ {
+ fp_serdisp_feature(dd, FEATURE_CONTRAST, config->contrast);
+ oldConfig->contrast = config->contrast;
+ update = true;
+ }
+ if (config->backlight != oldConfig->backlight)
+ {
+ fp_serdisp_feature(dd, FEATURE_BACKLIGHT, config->backlight);
+ oldConfig->backlight = config->backlight;
+ update = true;
+ }
+ if (config->upsideDown != oldConfig->upsideDown)
+ {
+ fp_serdisp_feature(dd, FEATURE_ROTATE, config->upsideDown);
+ oldConfig->upsideDown = config->upsideDown;
+ update = true;
+ }
+ if (config->invert != oldConfig->invert)
+ {
+ fp_serdisp_feature(dd, FEATURE_REVERSE, config->invert);
+ oldConfig->invert = config->invert;
+ update = true;
+ }
+
+ /* driver dependend options */
+ for (unsigned int i = 0; i < config->options.size(); i++) {
+ std::string optionname = config->options[i].name;
+ if (optionname != "UpsideDown" && optionname != "Contrast" &&
+ optionname != "Backlight" && optionname != "Invert") {
+
+ if ( fp_serdisp_isoption(dd, optionname.c_str()) == 1 ) /* if == 1: option is existing AND r/w */
+ fp_serdisp_setoption(dd, optionname.c_str(), strtol(config->options[i].value.c_str(), NULL, 0));
+ oldConfig->options[i] = config->options[i];
+ update = true;
+ }
+ }
+
+
+ if (update)
+ return 1;
+ return 0;
+}
+
+void cDriverSerDisp::Clear(void)
+{
+ if (bg_colour == -1)
+ fp_serdisp_clearbuffer(dd);
+ else { /* if bg_colour is set, draw background 'by hand' */
+ int x,y;
+ for (y = 0; y < fp_serdisp_getheight(dd); y++)
+ for (x = 0; x < fp_serdisp_getwidth(dd); x++)
+ fp_serdisp_setpixcol(dd, x, y, bg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
+ }
+}
+
+void cDriverSerDisp::Set8Pixels(int x, int y, unsigned char data) {
+ int i, start, pixel;
+
+ data = ReverseBits(data);
+
+ start = (x >> 3) << 3;
+
+ for (i = 0; i < 8; i++) {
+ pixel = data & (1 << i);
+ if (pixel)
+ fp_serdisp_setpixcol(dd, start + i, y, fg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
+ else if (!pixel && bg_colour != -1) /* if bg_colour is set: use it if pixel is not set */
+ fp_serdisp_setpixcol(dd, start + i, y, bg_colour); /* >= 1.95: serdisp_setcolour(), < 1.95: serdisp_setpixel() */
+ }
+}
+
+void cDriverSerDisp::Refresh(bool refreshAll)
+{
+ if (CheckSetup() == 1)
+ refreshAll = true;
+
+ if (refreshAll)
+ fp_serdisp_rewrite(dd);
+ else
+ fp_serdisp_update(dd);
+}
+
+} // end of namespace
diff --git a/glcddrivers/serdisp.h b/glcddrivers/serdisp.h
new file mode 100644
index 0000000..ddd7827
--- /dev/null
+++ b/glcddrivers/serdisp.h
@@ -0,0 +1,78 @@
+/*
+ * GraphLCD driver library
+ *
+ * serdisp.h - include support for displays supported by serdisplib (if library is installed)
+ * http://serdisplib.sourceforge.net
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003-2005 Wolfgang Astleitner <mrwastl AT users.sourceforge.net>
+ */
+
+#ifndef _GLCDDRIVERS_SERDISP_H_
+#define _GLCDDRIVERS_SERDISP_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverSerDisp : public cDriver
+{
+private:
+
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ long serdisp_version;
+
+ int supports_options;
+ long fg_colour;
+ long bg_colour;
+
+ void* sdhnd; // serdisplib handle
+ void* dd; // display descriptor
+ void* sdcd; // serdisp connect descriptor
+
+ long (*fp_serdisp_getversioncode) ();
+
+ void* (*fp_SDCONN_open) (const char sdcdev[]);
+
+ void* (*fp_PP_open) (const char sdcdev[]);
+ void* (*fp_PP_close) (void* sdcd);
+
+ void* (*fp_serdisp_init) (void* sdcd, const char dispname[], const char extra[]);
+ void (*fp_serdisp_rewrite) (void* dd);
+ void (*fp_serdisp_update) (void* dd);
+ void (*fp_serdisp_clearbuffer) (void* dd);
+ void (*fp_serdisp_setpixcol) (void* dd, int x, int y, long colour); // serdisp_setpixel or serdisp_setcolour
+ int (*fp_serdisp_feature) (void* dd, int feature, int value);
+ int (*fp_serdisp_isoption) (void* dd, const char* optionname);
+ void (*fp_serdisp_setoption) (void* dd, const char* optionname, long value);
+ int (*fp_serdisp_getwidth) (void* dd);
+ int (*fp_serdisp_getheight) (void* dd);
+ void (*fp_serdisp_quit) (void* dd);
+ void (*fp_serdisp_close) (void* dd);
+
+ int CheckSetup();
+
+public:
+
+ cDriverSerDisp(cDriverConfig * config);
+ virtual ~cDriverSerDisp();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+#endif
+
+} // end of namespace
diff --git a/glcddrivers/simlcd.c b/glcddrivers/simlcd.c
new file mode 100644
index 0000000..82fad54
--- /dev/null
+++ b/glcddrivers/simlcd.c
@@ -0,0 +1,183 @@
+/*
+ * GraphLCD driver library
+ *
+ * simlcd.c - SimLCD driver class
+ * Output goes to a file instead of lcd.
+ * Use SimLCD tool to view this file.
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+
+#include "common.h"
+#include "config.h"
+#include "simlcd.h"
+
+
+namespace GLCD
+{
+
+cDriverSimLCD::cDriverSimLCD(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+}
+
+cDriverSimLCD::~cDriverSimLCD()
+{
+ delete oldConfig;
+}
+
+int cDriverSimLCD::Init()
+{
+ width = config->width;
+ if (width <= 0)
+ width = 240;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "")
+ {
+ }
+ }
+
+ // setup lcd array
+ LCD = new unsigned char *[(width + 7) / 8];
+ if (LCD)
+ {
+ for (int x = 0; x < (width + 7) / 8; x++)
+ {
+ LCD[x] = new unsigned char[height];
+ memset(LCD[x], 0, height);
+ }
+ }
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: SIMLCD initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverSimLCD::DeInit()
+{
+ // free lcd array
+ if (LCD)
+ {
+ for (int x = 0; x < (width + 7) / 8; x++)
+ {
+ delete[] LCD[x];
+ }
+ delete[] LCD;
+ }
+
+ return 0;
+}
+
+int cDriverSimLCD::CheckSetup()
+{
+ if (config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverSimLCD::Clear()
+{
+ for (int x = 0; x < (width + 7) / 8; x++)
+ memset(LCD[x], 0, height);
+}
+
+void cDriverSimLCD::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ LCD[x / 8][y] = LCD[x / 8][y] | data;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ LCD[x / 8][y] = LCD[x / 8][y] | ReverseBits(data);
+ }
+}
+
+void cDriverSimLCD::Refresh(bool refreshAll)
+{
+ FILE * fp = NULL;
+ int x;
+ int y;
+ int i;
+ unsigned char c;
+
+ if (CheckSetup() > 0)
+ refreshAll = true;
+
+ fp = fopen("/tmp/simlcd.sem", "r");
+ if (!fp || refreshAll)
+ {
+ if (fp)
+ fclose(fp);
+ fp = fopen("/tmp/simlcd.dat", "w");
+ if (fp)
+ {
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + 7) / 8; x++)
+ {
+ c = LCD[x][y] ^ (config->invert ? 0xff : 0x00);
+ for (i = 0; i < 8; i++)
+ {
+ if (c & 0x80)
+ {
+ fprintf(fp,"#");
+ }
+ else
+ {
+ fprintf(fp,".");
+ }
+ c = c << 1;
+ }
+ }
+ fprintf(fp,"\n");
+ }
+ fclose(fp);
+ }
+
+ fp = fopen("/tmp/simlcd.sem", "w");
+ fclose(fp);
+ }
+ else
+ {
+ fclose(fp);
+ }
+}
+
+} // end of namespace
diff --git a/glcddrivers/simlcd.h b/glcddrivers/simlcd.h
new file mode 100644
index 0000000..8b2aca8
--- /dev/null
+++ b/glcddrivers/simlcd.h
@@ -0,0 +1,48 @@
+/*
+ * GraphLCD driver library
+ *
+ * simlcd.h - SimLCD driver class
+ * Output goes to a file instead of lcd.
+ * Use SimLCD tool to view this file.
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ */
+
+#ifndef _GLCDDRIVERS_SIMLCD_H_
+#define _GLCDDRIVERS_SIMLCD_H_
+
+#include "driver.h"
+
+
+namespace GLCD
+{
+
+class cDriverConfig;
+
+class cDriverSimLCD : public cDriver
+{
+private:
+ unsigned char ** LCD;
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+
+ int CheckSetup();
+
+public:
+ cDriverSimLCD(cDriverConfig * config);
+ virtual ~cDriverSimLCD();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcddrivers/t6963c.c b/glcddrivers/t6963c.c
new file mode 100644
index 0000000..6c0460c
--- /dev/null
+++ b/glcddrivers/t6963c.c
@@ -0,0 +1,678 @@
+/*
+ * GraphLCD driver library
+ *
+ * t6963c.c - T6963C driver class
+ *
+ * low level routines based on lcdproc 0.5 driver, (c) 2001 Manuel Stahl
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003, 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <syslog.h>
+
+#include "common.h"
+#include "config.h"
+#include "port.h"
+#include "t6963c.h"
+
+
+namespace GLCD
+{
+
+// T6963 commands
+const unsigned char kSetCursorPointer = 0x21;
+const unsigned char kSetOffsetRegister = 0x22;
+const unsigned char kSetAddressPointer = 0x24;
+
+const unsigned char kSetTextHomeAddress = 0x40;
+const unsigned char kSetTextArea = 0x41;
+const unsigned char kSetGraphicHomeAddress = 0x42;
+const unsigned char kSetGraphicArea = 0x43;
+
+const unsigned char kSetMode = 0x80;
+const unsigned char kSetDisplayMode = 0x90;
+const unsigned char kSetCursorPattern = 0xA0;
+
+const unsigned char kDataWriteInc = 0xC0;
+const unsigned char kDataReadInc = 0xC1;
+const unsigned char kDataWriteDec = 0xC2;
+const unsigned char kDataReadDec = 0xC3;
+const unsigned char kDataWrite = 0xC4;
+const unsigned char kDataRead = 0xC5;
+
+const unsigned char kAutoWrite = 0xB0;
+const unsigned char kAutoRead = 0xB1;
+const unsigned char kAutoReset = 0xB2;
+
+
+// T6963 Parameters
+const unsigned char kModeOr = 0x00;
+const unsigned char kModeXor = 0x01;
+const unsigned char kModeAnd = 0x03;
+const unsigned char kModeTextAttribute = 0x04;
+const unsigned char kModeInternalCG = 0x00;
+const unsigned char kModeExternalCG = 0x08;
+
+const unsigned char kTextAttributeNormal = 0x00;
+const unsigned char kTextAttributeInverse = 0x05;
+const unsigned char kTextAttributeNoDisplay = 0x03;
+const unsigned char kTextAttributeBlink = 0x08;
+
+const unsigned char kDisplayModeBlink = 0x01;
+const unsigned char kDisplayModeCursor = 0x02;
+const unsigned char kDisplayModeText = 0x04;
+const unsigned char kDisplayModeGraphic = 0x08;
+
+const unsigned short kGraphicBase = 0x0000;
+const unsigned short kTextBase = 0x1500;
+const unsigned short kCGRAMBase = 0x1800;
+
+
+// T6963 Wirings
+static const std::string kWiringStandard = "Standard";
+static const std::string kWiringWindows = "Windows";
+static const std::string kWiringSerial = "Serial";
+
+const unsigned char kStandardWRHI = 0x00; // 01 / nSTRB
+const unsigned char kStandardWRLO = 0x01; //
+const unsigned char kStandardRDHI = 0x00; // 17 / nSELECT
+const unsigned char kStandardRDLO = 0x08; //
+const unsigned char kStandardCEHI = 0x00; // 14 / nLINEFEED
+const unsigned char kStandardCELO = 0x02; //
+const unsigned char kStandardCDHI = 0x04; // 16 / INIT
+const unsigned char kStandardCDLO = 0x00; //
+
+const unsigned char kWindowsWRHI = 0x04; // 16 / INIT
+const unsigned char kWindowsWRLO = 0x00; //
+const unsigned char kWindowsRDHI = 0x00; // 14 / nLINEFEED
+const unsigned char kWindowsRDLO = 0x02; //
+const unsigned char kWindowsCEHI = 0x00; // 01 / nSTRB
+const unsigned char kWindowsCELO = 0x01; //
+const unsigned char kWindowsCDHI = 0x00; // 17 / nSELECT
+const unsigned char kWindowsCDLO = 0x08; //
+
+const unsigned char kSerialWRHI = 0x01; // 01 / nSTRB
+const unsigned char kSerialWRLO = 0x00; //
+const unsigned char kSerialRDHI = 0x08; // 17 / nSELECT
+const unsigned char kSerialRDLO = 0x00; //
+const unsigned char kSerialCEHI = 0x02; // 14 / nLINEFEED
+const unsigned char kSerialCELO = 0x00; //
+const unsigned char kSerialCDHI = 0x00; // 16 / INIT
+const unsigned char kSerialCDLO = 0x04; //
+
+
+cDriverT6963C::cDriverT6963C(cDriverConfig * config)
+: config(config)
+{
+ oldConfig = new cDriverConfig(*config);
+
+ port = new cParallelPort();
+
+ //width = config->width;
+ //height = config->height;
+ refreshCounter = 0;
+ displayMode = 0;
+ bidirectLPT = 1;
+ autoWrite = false;
+ serial = 0;
+}
+
+cDriverT6963C::~cDriverT6963C()
+{
+ delete port;
+ delete oldConfig;
+}
+
+int cDriverT6963C::Init()
+{
+ int x;
+
+ width = config->width;
+ if (width <= 0)
+ width = 240;
+ height = config->height;
+ if (height <= 0)
+ height = 128;
+
+ // default values
+ FS = 6;
+ WRHI = kStandardWRHI;
+ WRLO = kStandardWRLO;
+ RDHI = kStandardRDHI;
+ RDLO = kStandardRDLO;
+ CEHI = kStandardCEHI;
+ CELO = kStandardCELO;
+ CDHI = kStandardCDHI;
+ CDLO = kStandardCDLO;
+ useAutoMode = true;
+ useStatusCheck = true;
+
+ for (unsigned int i = 0; i < config->options.size(); i++)
+ {
+ if (config->options[i].name == "FontSelect")
+ {
+ int fontSelect = atoi(config->options[i].value.c_str());
+ if (fontSelect == 6)
+ FS = 6;
+ else if (fontSelect == 8)
+ FS = 8;
+ else
+ syslog(LOG_ERR, "%s error: font select %d not supported, using default (%d)!\n",
+ config->name.c_str(), fontSelect, FS);
+ }
+ else if (config->options[i].name == "Wiring")
+ {
+ if (config->options[i].value == kWiringStandard)
+ {
+ WRHI = kStandardWRHI;
+ WRLO = kStandardWRLO;
+ RDHI = kStandardRDHI;
+ RDLO = kStandardRDLO;
+ CEHI = kStandardCEHI;
+ CELO = kStandardCELO;
+ CDHI = kStandardCDHI;
+ CDLO = kStandardCDLO;
+ }
+ else if (config->options[i].value == kWiringWindows)
+ {
+ WRHI = kWindowsWRHI;
+ WRLO = kWindowsWRLO;
+ RDHI = kWindowsRDHI;
+ RDLO = kWindowsRDLO;
+ CEHI = kWindowsCEHI;
+ CELO = kWindowsCELO;
+ CDHI = kWindowsCDHI;
+ CDLO = kWindowsCDLO;
+ }
+ else if (config->options[i].value == kWiringSerial)
+ {
+ serial = 1;
+ WRHI = kSerialWRHI;
+ WRLO = kSerialWRLO;
+ RDHI = kSerialRDHI;
+ RDLO = kSerialRDLO;
+ CEHI = kSerialCEHI;
+ CELO = kSerialCELO;
+ CDHI = kSerialCDHI;
+ CDLO = kSerialCDLO;
+ }
+ else
+ syslog(LOG_ERR, "%s error: wiring %s not supported, using default (Standard)!\n",
+ config->name.c_str(), config->options[i].value.c_str());
+ }
+ else if (config->options[i].name == "AutoMode")
+ {
+ if (config->options[i].value == "yes")
+ useAutoMode = true;
+ else if (config->options[i].value == "no")
+ useAutoMode = false;
+ else
+ syslog(LOG_ERR, "%s error: unknown auto mode setting %s, using default (%s)!\n",
+ config->name.c_str(), config->options[i].value.c_str(), useAutoMode ? "yes" : "no");
+ }
+ else if (config->options[i].name == "StatusCheck")
+ {
+ if (config->options[i].value == "yes")
+ useStatusCheck = true;
+ else if (config->options[i].value == "no")
+ useStatusCheck = false;
+ else
+ syslog(LOG_ERR, "%s error: unknown status check setting %s, using default (%s)!\n",
+ config->name.c_str(), config->options[i].value.c_str(), useStatusCheck ? "yes" : "no");
+ }
+ }
+
+ // setup lcd array (wanted state)
+ newLCD = new unsigned char*[(width + (FS - 1)) / FS];
+ if (newLCD)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ newLCD[x] = new unsigned char[height];
+ memset(newLCD[x], 0, height);
+ }
+ }
+ // setup lcd array (current state)
+ oldLCD = new unsigned char*[(width + (FS - 1)) / FS];
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ oldLCD[x] = new unsigned char[height];
+ memset(oldLCD[x], 0, height);
+ }
+ }
+
+ if (config->device == "")
+ {
+ // use DirectIO
+ if (port->Open(config->port) != 0)
+ return -1;
+ uSleep(10);
+ }
+ else
+ {
+ // use ppdev
+ if (port->Open(config->device.c_str()) != 0)
+ return -1;
+ }
+
+ // disable chip
+ // disable reading from LCD
+ // disable writing to LCD
+ // command/status mode
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI);
+ port->SetDirection(kForward); // make 8-bit parallel port an output port
+
+ // Test ECP mode
+ if (bidirectLPT == 1)
+ {
+ syslog(LOG_DEBUG, "%s: Testing ECP mode...\n", config->name.c_str());
+ int i = 0;
+ int ecp_input;
+ port->SetDirection(kReverse);
+ for (int i = 0; i < 100; i++)
+ {
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // wr, ce, cd, rd
+ T6963CSetControl(WRHI | CELO | CDHI | RDLO);
+ T6963CSetControl(WRHI | CELO | CDHI | RDLO);
+ T6963CSetControl(WRHI | CELO | CDHI | RDLO);
+ ecp_input = port->ReadData();
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI);
+ if ((ecp_input & 0x03) == 0x03)
+ break;
+ }
+ port->SetDirection(kForward);
+ if (i >= 100)
+ {
+ syslog(LOG_DEBUG, "%s: ECP mode not working! -> is now disabled\n", config->name.c_str());
+ bidirectLPT = 0;
+ }
+ else
+ syslog(LOG_DEBUG, "%s: working!\n", config->name.c_str());
+ }
+
+ T6963CCommandWord(kSetGraphicHomeAddress, kGraphicBase);
+ if (width % FS == 0)
+ T6963CCommandWord(kSetGraphicArea, width / FS);
+ else
+ T6963CCommandWord(kSetGraphicArea, width / FS + 1);
+
+ T6963CCommand(kSetMode | kModeOr | kModeInternalCG);
+
+ T6963CDisplayMode(kDisplayModeText, false);
+ T6963CDisplayMode(kDisplayModeGraphic, true);
+ T6963CDisplayMode(kDisplayModeCursor, false);
+ T6963CDisplayMode(kDisplayModeBlink, false);
+
+ port->Release();
+
+ *oldConfig = *config;
+
+ // clear display
+ Clear();
+
+ syslog(LOG_INFO, "%s: T6963 initialized.\n", config->name.c_str());
+ return 0;
+}
+
+int cDriverT6963C::DeInit()
+{
+ int x;
+ // free lcd array (wanted state)
+ if (newLCD)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ delete[] newLCD[x];
+ }
+ delete[] newLCD;
+ }
+ // free lcd array (current state)
+ if (oldLCD)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ delete[] oldLCD[x];
+ }
+ delete[] oldLCD;
+ }
+
+ if (port->Close() != 0)
+ return -1;
+ return 0;
+}
+
+int cDriverT6963C::CheckSetup()
+{
+ if (config->device != oldConfig->device ||
+ config->port != oldConfig->port ||
+ config->width != oldConfig->width ||
+ config->height != oldConfig->height)
+ {
+ DeInit();
+ Init();
+ return 0;
+ }
+
+ if (config->upsideDown != oldConfig->upsideDown ||
+ config->invert != oldConfig->invert)
+ {
+ oldConfig->upsideDown = config->upsideDown;
+ oldConfig->invert = config->invert;
+ return 1;
+ }
+ return 0;
+}
+
+void cDriverT6963C::Clear()
+{
+ for (int x = 0; x < (width + (FS - 1)) / FS; x++)
+ memset(newLCD[x], 0, height);
+}
+
+void cDriverT6963C::Set8Pixels(int x, int y, unsigned char data)
+{
+ if (x >= width || y >= height)
+ return;
+
+ if (FS == 6)
+ {
+ unsigned char data1 = 0;
+ unsigned char data2 = 0;
+ unsigned char data3 = 0;
+
+ if (!config->upsideDown)
+ {
+ // normal orientation
+ x = x - (x % 8);
+ data1 = data >> (2 + (x % 6));
+ if (x % 6 == 5)
+ {
+ data2 = data >> 1;
+ data3 = data << 5;
+ }
+ else
+ data2 = data << (4 - (x % 6));
+
+ newLCD[x / 6][y] |= data1;
+ if (x / 6 + 1 < (width + 5) / 6)
+ newLCD[x / 6 + 1][y] |= data2;
+ if (x / 6 + 2 < (width + 5) / 6)
+ if (x % 6 == 5)
+ newLCD[x / 6 + 2][y] |= data3;
+ }
+ else
+ {
+ // upside down orientation
+ x = width - 1 - x;
+ y = height - 1 - y;
+ x = x - (x % 8);
+ data = ReverseBits(data);
+
+ data1 = data >> (2 + (x % 6));
+ if (x % 6 == 5)
+ {
+ data2 = data >> 1;
+ data3 = data << 5;
+ }
+ else
+ data2 = data << (4 - (x % 6));
+
+ newLCD[x / 6][y] |= data1;
+ if (x / 6 + 1 < (width + 5) / 6)
+ newLCD[x / 6 + 1][y] |= data2;
+ if (x / 6 + 2 < (width + 5) / 6)
+ if (x % 6 == 5)
+ newLCD[x / 6 + 2][y] |= data3;
+ }
+ }
+ else
+ {
+ if (!config->upsideDown)
+ {
+ newLCD[x / 8][y] |= data;
+ }
+ else
+ {
+ x = width - 1 - x;
+ y = height - 1 - y;
+ newLCD[x / 8][y] |= ReverseBits(data);
+ }
+ }
+}
+
+void cDriverT6963C::Refresh(bool refreshAll)
+{
+ int x,y;
+ int addr = 0;
+
+ if (CheckSetup() == 1)
+ refreshAll = true;
+
+ if (config->refreshDisplay > 0)
+ {
+ refreshCounter = (refreshCounter + 1) % config->refreshDisplay;
+ if (!refreshAll && !refreshCounter)
+ refreshAll = true;
+ }
+
+ port->Claim();
+ if (refreshAll)
+ {
+ // draw all
+ T6963CCommandWord(kSetAddressPointer, kGraphicBase);
+ if (useAutoMode)
+ {
+ T6963CCommand(kAutoWrite);
+ autoWrite = true;
+ }
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ if (autoWrite)
+ T6963CData((newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
+ else
+ T6963CCommandByte(kDataWriteInc, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
+ oldLCD[x][y] = newLCD[x][y];
+ }
+ }
+ if (autoWrite)
+ {
+ T6963CCommand(kAutoReset);
+ autoWrite = false;
+ }
+ // and reset RefreshCounter
+ refreshCounter = 0;
+ }
+ else
+ {
+ // draw only the changed bytes
+
+ bool cs = false;
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < (width + (FS - 1)) / FS; x++)
+ {
+ if (oldLCD[x][y] != newLCD[x][y])
+ {
+ if (!cs)
+ {
+ if (width % FS == 0)
+ addr = (y * (width / FS)) + x;
+ else
+ addr = (y * (width / FS + 1)) + x;
+ T6963CCommandWord(kSetAddressPointer, kGraphicBase + addr);
+ if (useAutoMode)
+ {
+ T6963CCommand(kAutoWrite);
+ autoWrite = true;
+ }
+ cs = true;
+ }
+ if (autoWrite)
+ T6963CData((newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
+ else
+ T6963CCommandByte(kDataWriteInc, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00));
+ oldLCD[x][y] = newLCD[x][y];
+ }
+ else
+ {
+ if (autoWrite)
+ {
+ T6963CCommand(kAutoReset);
+ autoWrite = false;
+ }
+ cs = false;
+ }
+ }
+ }
+ if (autoWrite)
+ {
+ T6963CCommand(kAutoReset);
+ autoWrite = false;
+ }
+ }
+ port->Release();
+}
+
+void cDriverT6963C::T6963CSetControl(unsigned char flags)
+{
+ unsigned char status = port->ReadControl();
+ status &= 0xF0; // mask 4 bits
+ status |= flags; // add new flags
+ port->WriteControl(status);
+}
+
+void cDriverT6963C::T6963CDSPReady()
+{
+ int input = 0;
+
+ port->SetDirection(kReverse);
+ if (bidirectLPT == 1)
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI);
+ T6963CSetControl(WRHI | CELO | CDHI | RDLO);
+ input = port->ReadData();
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI);
+ if (!autoWrite && (input & 3) == 3)
+ break;
+ if (autoWrite && (input & 8) == 8)
+ break;
+ }
+ }
+ else
+ {
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI);
+ T6963CSetControl(WRHI | CELO | CDHI | RDLO);
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI);
+ }
+ port->SetDirection(kForward);
+}
+
+void cDriverT6963C::T6963CData(unsigned char data)
+{
+ if (serial)
+ {
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO);
+ for (int i = 128; i; i>>=1)
+ {
+ if (data & i)
+ {
+ T6963CSetControl(WRLO | CEHI | CDHI | RDLO);
+ T6963CSetControl(WRHI | CEHI | CDHI | RDLO);
+ }
+ else
+ {
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO);
+ T6963CSetControl(WRHI | CEHI | CDLO | RDLO);
+ }
+ }
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO); // CD down (data)
+ T6963CSetControl(WRLO | CELO | CDLO | RDLO); // CE down
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO); // CE up
+ }
+ else
+ {
+ if (useStatusCheck)
+ T6963CDSPReady();
+ T6963CSetControl(WRHI | CEHI | CDLO | RDHI); // CD down (data)
+ T6963CSetControl(WRLO | CELO | CDLO | RDHI); // CE & WR down
+ port->WriteData(data);
+ T6963CSetControl(WRHI | CEHI | CDLO | RDHI); // CE & WR up again
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // CD up again
+ }
+}
+
+void cDriverT6963C::T6963CCommand(unsigned char cmd)
+{
+ if (serial)
+ {
+ syslog(LOG_DEBUG, "Serial cmd out: ");
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO);
+ for (int i = 128; i; i>>=1)
+ {
+ if (cmd & i)
+ {
+ T6963CSetControl(WRLO | CEHI | CDHI | RDLO);
+ T6963CSetControl(WRHI | CEHI | CDHI | RDLO);
+ }
+ else
+ {
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO);
+ T6963CSetControl(WRHI | CEHI | CDLO | RDLO);
+ }
+ }
+ T6963CSetControl(WRLO | CEHI | CDHI | RDLO); // CD up (command)
+ T6963CSetControl(WRLO | CELO | CDHI | RDLO); // CE down
+ T6963CSetControl(WRLO | CEHI | CDHI | RDLO); // CE up
+ T6963CSetControl(WRLO | CEHI | CDLO | RDLO); // CD down
+ }
+ else
+ {
+ if (useStatusCheck)
+ T6963CDSPReady();
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // CD up (command)
+ T6963CSetControl(WRLO | CELO | CDHI | RDHI); // CE & WR down
+ port->WriteData(cmd);
+ T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // CE & WR up again
+ T6963CSetControl(WRHI | CEHI | CDLO | RDHI); // CD down again
+ }
+}
+
+void cDriverT6963C::T6963CCommandByte(unsigned char cmd, unsigned char data)
+{
+ T6963CData(data);
+ T6963CCommand(cmd);
+}
+
+void cDriverT6963C::T6963CCommand2Bytes(unsigned char cmd, unsigned char data1, unsigned char data2)
+{
+ T6963CData(data1);
+ T6963CData(data2);
+ T6963CCommand(cmd);
+}
+
+void cDriverT6963C::T6963CCommandWord(unsigned char cmd, unsigned short data)
+{
+ T6963CData(data % 256);
+ T6963CData(data >> 8);
+ T6963CCommand(cmd);
+}
+
+void cDriverT6963C::T6963CDisplayMode(unsigned char mode, bool enable)
+{
+ if (enable)
+ displayMode |= mode;
+ else
+ displayMode &= ~mode;
+ T6963CCommand(kSetDisplayMode | displayMode);
+}
+
+}
diff --git a/glcddrivers/t6963c.h b/glcddrivers/t6963c.h
new file mode 100644
index 0000000..88be16b
--- /dev/null
+++ b/glcddrivers/t6963c.h
@@ -0,0 +1,76 @@
+/*
+ * GraphLCD driver library
+ *
+ * t6963c.h - T6963C driver class
+ *
+ * low level routines based on lcdproc 0.5 driver, (c) 2001 Manuel Stahl
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2003, 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDDRIVERS_T6963C_H_
+#define _GLCDDRIVERS_T6963C_H_
+
+#include "driver.h"
+
+namespace GLCD
+{
+
+class cDriverConfig;
+class cParallelPort;
+
+class cDriverT6963C : public cDriver
+{
+private:
+ cParallelPort * port;
+ unsigned char ** newLCD; // wanted state
+ unsigned char ** oldLCD; // current state
+ cDriverConfig * config;
+ cDriverConfig * oldConfig;
+ int refreshCounter;
+ int bidirectLPT;
+ int displayMode;
+ bool useAutoMode;
+ bool useStatusCheck;
+
+ int serial;
+ int FS;
+ int WRHI;
+ int WRLO;
+ int RDHI;
+ int RDLO;
+ int CEHI;
+ int CELO;
+ int CDHI;
+ int CDLO;
+ bool autoWrite;
+
+ void T6963CSetControl(unsigned char flags);
+ void T6963CDSPReady();
+ void T6963CData(unsigned char data);
+ void T6963CCommand(unsigned char cmd);
+ void T6963CCommandByte(unsigned char cmd, unsigned char data);
+ void T6963CCommand2Bytes(unsigned char cmd, unsigned char data1, unsigned char data2);
+ void T6963CCommandWord(unsigned char cmd, unsigned short data);
+ void T6963CDisplayMode(unsigned char mode, bool enable);
+
+ int CheckSetup();
+
+public:
+ cDriverT6963C(cDriverConfig * config);
+ virtual ~cDriverT6963C();
+
+ virtual int Init();
+ virtual int DeInit();
+
+ virtual void Clear();
+ virtual void Set8Pixels(int x, int y, unsigned char data);
+ virtual void Refresh(bool refreshAll = false);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/Makefile b/glcdgraphics/Makefile
new file mode 100644
index 0000000..fb072ab
--- /dev/null
+++ b/glcdgraphics/Makefile
@@ -0,0 +1,68 @@
+#
+# Makefile for the GraphLCD graphics library
+#
+
+-include ../Make.config
+
+CXXFLAGS += -fPIC
+
+VERMAJOR = 2
+VERMINOR = 0
+VERMICRO = 0
+
+BASENAME = libglcdgraphics.so
+
+LIBNAME = $(BASENAME).$(VERMAJOR).$(VERMINOR).$(VERMICRO)
+
+OBJS = bitmap.o common.o font.o glcd.o image.o imagefile.o pbm.o
+
+HEADERS = bitmap.h font.h glcd.h image.h imagefile.h pbm.h
+
+### Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = g++ -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+ifdef HAVE_FREETYPE2
+ ifneq ($(shell which freetype-config),)
+ INCLUDES += $(shell freetype-config --cflags)
+ LIBS += $(shell freetype-config --libs)
+ else
+ INCLUDES += -I/usr/include/freetype -I/usr/local/include/freetype
+ LIBS += -lfreetype
+ endif
+ DEFINES += -DHAVE_FREETYPE2
+endif### Targets:
+
+all: $(LIBNAME)
+
+$(LIBNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) $(LIBS) -Wl,-soname="$(BASENAME).$(VERMAJOR)" -o $@
+ ln -sf $(LIBNAME) $(BASENAME)
+
+install: all
+ install -d $(LIBDIR)
+ install -m 755 $(LIBNAME) $(LIBDIR)/
+ install -d $(INCDIR)/glcdgraphics
+ install -m 644 $(HEADERS) $(INCDIR)/glcdgraphics/
+ ( cd $(LIBDIR); ln -sf $(LIBNAME) $(BASENAME).$(VERMAJOR); ln -sf $(LIBNAME) $(BASENAME) )
+
+uninstall:
+ rm -f $(LIBDIR)/$(BASENAME)
+ rm -f $(LIBDIR)/$(BASENAME).$(VERMAJOR)
+ rm -f $(LIBDIR)/$(LIBNAME)
+ (for i in $(HEADERS); do rm -f $(INCDIR)/glcdgraphics/$$i; done)
+ rmdir $(INCDIR)/glcdgraphics
+
+clean:
+ rm -f $(OBJS) $(DEPFILE) $(LIBNAME) $(BASENAME) *~
+
diff --git a/glcdgraphics/bitmap.c b/glcdgraphics/bitmap.c
new file mode 100644
index 0000000..d5ba159
--- /dev/null
+++ b/glcdgraphics/bitmap.c
@@ -0,0 +1,807 @@
+/*
+ * GraphLCD graphics library
+ *
+ * bitmap.c - cBitmap class
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "bitmap.h"
+#include "common.h"
+#include "font.h"
+
+
+namespace GLCD
+{
+
+const unsigned char bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+const unsigned char bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
+const unsigned char bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+
+cBitmap::cBitmap(int width, int height, unsigned char * data)
+: width(width),
+ height(height),
+ bitmap(NULL)
+{
+ // lines are byte aligned
+ lineSize = (width + 7) / 8;
+
+ bitmap = new unsigned char[lineSize * height];
+ if (data)
+ memcpy(bitmap, data, lineSize * height);
+}
+
+cBitmap::cBitmap(const cBitmap & b)
+{
+ width = b.width;
+ height = b.height;
+ lineSize = b.lineSize;
+ bitmap = new unsigned char[lineSize * height];
+ if (b.bitmap)
+ memcpy(bitmap, b.bitmap, lineSize * height);
+}
+
+cBitmap::~cBitmap()
+{
+ delete[] bitmap;
+}
+
+void cBitmap::Clear()
+{
+ memset(bitmap, 0, lineSize * height);
+}
+
+void cBitmap::Invert()
+{
+ int i;
+
+ for (i = 0; i < lineSize * height; i++)
+ {
+ bitmap[i] ^= 0xFF;
+ }
+}
+
+void cBitmap::DrawPixel(int x, int y, eColor color)
+{
+ if (x < 0 || x > width - 1)
+ return;
+ if (y < 0 || y > height - 1)
+ return;
+
+ unsigned char c = 0x80 >> (x % 8);
+ if (color == clrBlack)
+ bitmap[lineSize * y + x / 8] |= c;
+ else
+ bitmap[lineSize * y + x / 8] &= ~c;
+}
+
+void cBitmap::Draw8Pixels(int x, int y, unsigned char pixels, eColor color)
+{
+ if (x < 0 || x > width - 1)
+ return;
+ if (y < 0 || y > height - 1)
+ return;
+
+ if (color == clrBlack)
+ bitmap[lineSize * y + x / 8] |= pixels;
+ else
+ bitmap[lineSize * y + x / 8] &= ~pixels;
+}
+
+void cBitmap::DrawLine(int x1, int y1, int x2, int y2, eColor color)
+{
+ int d, sx, sy, dx, dy;
+ unsigned int ax, ay;
+
+ dx = x2 - x1;
+ ax = abs(dx) << 1;
+ if (dx < 0)
+ sx = -1;
+ else
+ sx = 1;
+
+ dy = y2 - y1;
+ ay = abs(dy) << 1;
+ if (dy < 0)
+ sy = -1;
+ else
+ sy = 1;
+
+ DrawPixel(x1, y1, color);
+ if (ax > ay)
+ {
+ d = ay - (ax >> 1);
+ while (x1 != x2)
+ {
+ if (d >= 0)
+ {
+ y1 += sy;
+ d -= ax;
+ }
+ x1 += sx;
+ d += ay;
+ DrawPixel(x1, y1, color);
+ }
+ }
+ else
+ {
+ d = ax - (ay >> 1);
+ while (y1 != y2)
+ {
+ if (d >= 0)
+ {
+ x1 += sx;
+ d -= ay;
+ }
+ y1 += sy;
+ d += ax;
+ DrawPixel(x1, y1, color);
+ }
+ }
+}
+
+void cBitmap::DrawHLine(int x1, int y, int x2, eColor color)
+{
+ sort(x1,x2);
+
+ if (x1 / 8 == x2 / 8)
+ {
+ // start and end in the same byte
+ Draw8Pixels(x1, y, bitmaskr[x1 % 8] & bitmaskl[x2 % 8], color);
+ }
+ else
+ {
+ // start and end in different bytes
+ Draw8Pixels(x1, y, bitmaskr[x1 % 8], color);
+ x1 = ((x1 + 8) / 8) * 8;
+ while (x1 < (x2 / 8) * 8)
+ {
+ Draw8Pixels(x1, y, 0xff, color);
+ x1 += 8;
+ }
+ Draw8Pixels(x2, y, bitmaskl[x2 % 8], color);
+ }
+}
+
+void cBitmap::DrawVLine(int x, int y1, int y2, eColor color)
+{
+ int y;
+
+ sort(y1,y2);
+
+ for (y = y1; y <= y2; y++)
+ DrawPixel(x, y, color);
+}
+
+void cBitmap::DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled)
+{
+ int y;
+
+ sort(x1,x2);
+ sort(y1,y2);
+
+ if (!filled)
+ {
+ DrawHLine(x1, y1, x2, color);
+ DrawVLine(x1, y1, y2, color);
+ DrawHLine(x1, y2, x2, color);
+ DrawVLine(x2, y1, y2, color);
+ }
+ else
+ {
+ for (y = y1; y <= y2; y++)
+ {
+ DrawHLine(x1, y, x2, color);
+ }
+ }
+}
+
+void cBitmap::DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled, int type)
+{
+ sort(x1,x2);
+ sort(y1,y2);
+
+ if (type > (x2 - x1) / 2)
+ type = (x2 - x1) / 2;
+ if (type > (y2 - y1) / 2)
+ type = (y2 - y1) / 2;
+
+ if (filled)
+ {
+ DrawHLine(x1 + type, y1, x2 - type, color);
+ for (int y = y1 + 1; y < y1 + type; y++)
+ DrawHLine(x1 + 1, y, x2 - 1, color);
+ for (int y = y1 + type; y <= y2 - type; y++)
+ DrawHLine(x1, y, x2, color);
+ for (int y = y2 - type + 1; y < y2; y++)
+ DrawHLine(x1 + 1, y, x2 - 1, color);
+ DrawHLine(x1 + type, y2, x2 - type, color);
+ if (type == 4)
+ {
+ // round the ugly fat box...
+ DrawPixel(x1 + 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite);
+ DrawPixel(x1 + 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite);
+ DrawPixel(x2 - 1, y1 + 1, color == clrWhite ? clrBlack : clrWhite);
+ DrawPixel(x2 - 1, y2 - 1, color == clrWhite ? clrBlack : clrWhite);
+ }
+ }
+ else
+ {
+ DrawHLine(x1 + type, y1, x2 - type, color);
+ DrawVLine(x1, y1 + type, y2 - type, color);
+ DrawVLine(x2, y1 + type, y2 - type, color);
+ DrawHLine(x1 + type, y2, x2 - type, color);
+ if (type > 1)
+ {
+ DrawHLine(x1 + 1, y1 + 1, x1 + type - 1, color);
+ DrawHLine(x2 - type + 1, y1 + 1, x2 - 1, color);
+ DrawHLine(x1 + 1, y2 - 1, x1 + type - 1, color);
+ DrawHLine(x2 - type + 1, y2 - 1, x2 - 1, color);
+ DrawVLine(x1 + 1, y1 + 1, y1 + type - 1, color);
+ DrawVLine(x1 + 1, y2 - 1, y2 - type + 1, color);
+ DrawVLine(x2 - 1, y1 + 1, y1 + type - 1, color);
+ DrawVLine(x2 - 1, y2 - 1, y2 - type + 1, color);
+ }
+ }
+}
+
+void cBitmap::DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool filled, int quadrants)
+{
+ // Algorithm based on http://homepage.smc.edu/kennedy_john/BELIPSE.PDF
+ int rx = x2 - x1;
+ int ry = y2 - y1;
+ int cx = (x1 + x2) / 2;
+ int cy = (y1 + y2) / 2;
+ switch (abs(quadrants))
+ {
+ case 0: rx /= 2; ry /= 2; break;
+ case 1: cx = x1; cy = y2; break;
+ case 2: cx = x2; cy = y2; break;
+ case 3: cx = x2; cy = y1; break;
+ case 4: cx = x1; cy = y1; break;
+ case 5: cx = x1; ry /= 2; break;
+ case 6: cy = y2; rx /= 2; break;
+ case 7: cx = x2; ry /= 2; break;
+ case 8: cy = y1; rx /= 2; break;
+ }
+ int TwoASquare = 2 * rx * rx;
+ int TwoBSquare = 2 * ry * ry;
+ int x = rx;
+ int y = 0;
+ int XChange = ry * ry * (1 - 2 * rx);
+ int YChange = rx * rx;
+ int EllipseError = 0;
+ int StoppingX = TwoBSquare * rx;
+ int StoppingY = 0;
+ while (StoppingX >= StoppingY)
+ {
+ if (filled)
+ {
+ switch (quadrants)
+ {
+ case 5: DrawRectangle(cx, cy + y, cx + x, cy + y, color, filled); // no break
+ case 1: DrawRectangle(cx, cy - y, cx + x, cy - y, color, filled); break;
+ case 7: DrawRectangle(cx - x, cy + y, cx, cy + y, color, filled); // no break
+ case 2: DrawRectangle(cx - x, cy - y, cx, cy - y, color, filled); break;
+ case 3: DrawRectangle(cx - x, cy + y, cx, cy + y, color, filled); break;
+ case 4: DrawRectangle(cx, cy + y, cx + x, cy + y, color, filled); break;
+ case 0:
+ case 6: DrawRectangle(cx - x, cy - y, cx + x, cy - y, color, filled); if (quadrants == 6) break;
+ case 8: DrawRectangle(cx - x, cy + y, cx + x, cy + y, color, filled); break;
+ case -1: DrawRectangle(cx + x, cy - y, x2, cy - y, color, filled); break;
+ case -2: DrawRectangle(x1, cy - y, cx - x, cy - y, color, filled); break;
+ case -3: DrawRectangle(x1, cy + y, cx - x, cy + y, color, filled); break;
+ case -4: DrawRectangle(cx + x, cy + y, x2, cy + y, color, filled); break;
+ }
+ }
+ else
+ {
+ switch (quadrants)
+ {
+ case 5: DrawPixel(cx + x, cy + y, color); // no break
+ case -1:
+ case 1: DrawPixel(cx + x, cy - y, color); break;
+ case 7: DrawPixel(cx - x, cy + y, color); // no break
+ case -2:
+ case 2: DrawPixel(cx - x, cy - y, color); break;
+ case -3:
+ case 3: DrawPixel(cx - x, cy + y, color); break;
+ case -4:
+ case 4: DrawPixel(cx + x, cy + y, color); break;
+ case 0:
+ case 6: DrawPixel(cx - x, cy - y, color); DrawPixel(cx + x, cy - y, color); if (quadrants == 6) break;
+ case 8: DrawPixel(cx - x, cy + y, color); DrawPixel(cx + x, cy + y, color); break;
+ }
+ }
+ y++;
+ StoppingY += TwoASquare;
+ EllipseError += YChange;
+ YChange += TwoASquare;
+ if (2 * EllipseError + XChange > 0)
+ {
+ x--;
+ StoppingX -= TwoBSquare;
+ EllipseError += XChange;
+ XChange += TwoBSquare;
+ }
+ }
+ x = 0;
+ y = ry;
+ XChange = ry * ry;
+ YChange = rx * rx * (1 - 2 * ry);
+ EllipseError = 0;
+ StoppingX = 0;
+ StoppingY = TwoASquare * ry;
+ while (StoppingX <= StoppingY)
+ {
+ if (filled)
+ {
+ switch (quadrants)
+ {
+ case 5: DrawRectangle(cx, cy + y, cx + x, cy + y, color, filled); // no break
+ case 1: DrawRectangle(cx, cy - y, cx + x, cy - y, color, filled); break;
+ case 7: DrawRectangle(cx - x, cy + y, cx, cy + y, color, filled); // no break
+ case 2: DrawRectangle(cx - x, cy - y, cx, cy - y, color, filled); break;
+ case 3: DrawRectangle(cx - x, cy + y, cx, cy + y, color, filled); break;
+ case 4: DrawRectangle(cx, cy + y, cx + x, cy + y, color, filled); break;
+ case 0:
+ case 6: DrawRectangle(cx - x, cy - y, cx + x, cy - y, color, filled); if (quadrants == 6) break;
+ case 8: DrawRectangle(cx - x, cy + y, cx + x, cy + y, color, filled); break;
+ case -1: DrawRectangle(cx + x, cy - y, x2, cy - y, color, filled); break;
+ case -2: DrawRectangle(x1, cy - y, cx - x, cy - y, color, filled); break;
+ case -3: DrawRectangle(x1, cy + y, cx - x, cy + y, color, filled); break;
+ case -4: DrawRectangle(cx + x, cy + y, x2, cy + y, color, filled); break;
+ }
+ }
+ else
+ {
+ switch (quadrants)
+ {
+ case 5: DrawPixel(cx + x, cy + y, color); // no break
+ case -1:
+ case 1: DrawPixel(cx + x, cy - y, color); break;
+ case 7: DrawPixel(cx - x, cy + y, color); // no break
+ case -2:
+ case 2: DrawPixel(cx - x, cy - y, color); break;
+ case -3:
+ case 3: DrawPixel(cx - x, cy + y, color); break;
+ case -4:
+ case 4: DrawPixel(cx + x, cy + y, color); break;
+ case 0:
+ case 6: DrawPixel(cx - x, cy - y, color); DrawPixel(cx + x, cy - y, color); if (quadrants == 6) break;
+ case 8: DrawPixel(cx - x, cy + y, color); DrawPixel(cx + x, cy + y, color); break;
+ }
+ }
+ x++;
+ StoppingX += TwoBSquare;
+ EllipseError += XChange;
+ XChange += TwoBSquare;
+ if (2 * EllipseError + YChange > 0)
+ {
+ y--;
+ StoppingY -= TwoASquare;
+ EllipseError += YChange;
+ YChange += TwoASquare;
+ }
+ }
+}
+
+void cBitmap::DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type)
+{
+ bool upper = type & 0x01;
+ bool falling = type & 0x02;
+ bool vertical = type & 0x04;
+ if (vertical)
+ {
+ for (int y = y1; y <= y2; y++)
+ {
+ double c = cos((y - y1) * M_PI / (y2 - y1 + 1));
+ if (falling)
+ c = -c;
+ int x = int((x2 - x1 + 1) * c / 2);
+ if (upper && !falling || !upper && falling)
+ DrawRectangle(x1, y, (x1 + x2) / 2 + x, y, color, true);
+ else
+ DrawRectangle((x1 + x2) / 2 + x, y, x2, y, color, true);
+ }
+ }
+ else
+ {
+ for (int x = x1; x <= x2; x++)
+ {
+ double c = cos((x - x1) * M_PI / (x2 - x1 + 1));
+ if (falling)
+ c = -c;
+ int y = int((y2 - y1 + 1) * c / 2);
+ if (upper)
+ DrawRectangle(x, y1, x, (y1 + y2) / 2 + y, color, true);
+ else
+ DrawRectangle(x, (y1 + y2) / 2 + y, x, y2, color, true);
+ }
+ }
+}
+
+void cBitmap::DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color)
+{
+ unsigned char cl = 0;
+ int xt, yt;
+ const unsigned char * data = bitmap.Data();
+ unsigned short temp;
+ int h, w;
+
+ w = bitmap.Width();
+ h = bitmap.Height();
+
+ if (data)
+ {
+ if (!(x % 8))
+ {
+ // Bitmap is byte alligned (0,8,16,...)
+ for (yt = 0; yt < h; yt++)
+ {
+ for (xt = 0; xt < (w / 8); xt++)
+ {
+ cl = *data;
+ Draw8Pixels(x + (xt * 8), y + yt, cl, color);
+ data++;
+ }
+ if (w % 8)
+ {
+ cl = *data;
+ Draw8Pixels(x + ((w / 8) * 8), y + yt, cl & bitmaskl[w % 8 - 1], color);
+ data++;
+ }
+ }
+ }
+ else
+ {
+ // Bitmap is not byte alligned
+ for (yt = 0; yt < h; yt++)
+ {
+ temp = 0;
+ for (xt = 0; xt < (w + (x % 8)) / 8; xt++)
+ {
+ cl = *(data + yt * ((w + 7) / 8) + xt);
+ temp = temp | ((unsigned short) cl << (8 - (x % 8)));
+ cl = (temp & 0xff00) >> 8;
+ if (!xt)
+ {
+ // first byte
+ Draw8Pixels(x - (x % 8) + (xt * 8), y + yt, cl & bitmaskr[x % 8], color);
+ }
+ else
+ {
+ // not the first byte
+ Draw8Pixels(x - (x % 8) + (xt * 8), y + yt, cl, color);
+ }
+ temp <<= 8;
+ }
+ if ((w + (x % 8) + 7) / 8 != (w + (x % 8)) / 8)
+ {
+ // print the rest
+ cl = *(data + (yt + 1) * ((w + 7) / 8) - 1);
+ temp = temp | ((unsigned short) cl << (8 - (x % 8)));
+ cl = (temp & 0xff00) >> 8;
+ Draw8Pixels(x - (x % 8) + (((w + (x % 8)) / 8) * 8), y + yt, cl & bitmaskl[(w + x) % 8 - 1], color);
+ }
+ }
+ }
+ }
+}
+
+int cBitmap::DrawText(int x, int y, int xmax, const std::string & text, const cFont * font,
+ eColor color, bool proportional, int skipPixels)
+{
+ int xt;
+ int yt;
+ int i;
+ char c;
+ int start;
+
+ clip(x, 0, width - 1);
+ clip(y, 0, height - 1);
+
+ xt = x;
+ yt = y;
+ start = 0;
+
+ if (text.length() > 0)
+ {
+ if (skipPixels > 0)
+ {
+ if (!proportional)
+ {
+ if (skipPixels >= (int) text.length() * font->TotalWidth())
+ start = text.length();
+ else
+ while (skipPixels > font->TotalWidth())
+ {
+ skipPixels -= font->TotalWidth();
+ start++;
+ }
+ }
+ else
+ {
+ if (skipPixels >= font->Width(text))
+ start = text.length();
+ else
+ while (skipPixels > font->Width(text[start]))
+ {
+ skipPixels -= font->Width(text[start]);
+ skipPixels -= font->SpaceBetween();
+ start++;
+ }
+ }
+ }
+ for (i = start; i < (int) text.length(); i++)
+ {
+ c = text[i];
+ if (xt > xmax)
+ {
+ i = text.length();
+ }
+ else
+ {
+ if (!proportional)
+ {
+ if (skipPixels > 0)
+ {
+ DrawCharacter(xt, yt, xmax, c, font, color, skipPixels);
+ xt += font->TotalWidth() - skipPixels;
+ skipPixels = 0;
+ }
+ else
+ {
+ DrawCharacter(xt, yt, xmax, c, font, color);
+ xt += font->TotalWidth();
+ }
+ }
+ else
+ {
+ if (skipPixels > 0)
+ {
+ xt += DrawCharacter(xt, yt, xmax, c, font, color, skipPixels);
+ skipPixels = 0;
+ }
+ else
+ {
+ xt += DrawCharacter(xt, yt, xmax, c, font, color);
+ }
+ if (xt <= xmax)
+ {
+ xt += font->SpaceBetween();
+ }
+ }
+ }
+ }
+ }
+ return xt;
+}
+
+int cBitmap::DrawCharacter(int x, int y, int xmax, char c, const cFont * font,
+ eColor color, int skipPixels)
+{
+ const cBitmap * charBitmap;
+
+ clip(x, 0, width - 1);
+ clip(y, 0, height - 1);
+
+ charBitmap = font->GetCharacter(c);
+ if (charBitmap)
+ {
+ cBitmap * drawBitmap = charBitmap->SubBitmap(skipPixels, 0, xmax - x + skipPixels, charBitmap->Height() - 1);
+ if (drawBitmap)
+ DrawBitmap(x, y, *drawBitmap, color);
+ delete drawBitmap;
+ return charBitmap->Width() - skipPixels;
+ }
+ return 0;
+}
+
+unsigned char cBitmap::GetPixel(int x, int y) const
+{
+ unsigned char value;
+
+ value = bitmap[y * lineSize + x / 8];
+ value = (value >> (7 - (x % 8))) & 1;
+ return value;
+}
+
+cBitmap * cBitmap::SubBitmap(int x1, int y1, int x2, int y2) const
+{
+ int w, h;
+ int xt, yt;
+ cBitmap * bmp;
+ unsigned char cl;
+ unsigned char * data;
+ unsigned short temp;
+
+ sort(x1,x2);
+ sort(y1,y2);
+ if (x1 < 0 || x1 > width - 1)
+ return NULL;
+ if (y1 < 0 || y1 > height - 1)
+ return NULL;
+ clip(x2, 0, width - 1);
+ clip(y2, 0, height - 1);
+
+ w = x2 - x1 + 1;
+ h = y2 - y1 + 1;
+ bmp = new cBitmap(w, h);
+ if (!bmp || !bmp->Data())
+ return NULL;
+ bmp->Clear();
+ if (x1 % 8 == 0)
+ {
+ // Bitmap is byte alligned (0,8,16,...)
+ for (yt = 0; yt < h; yt++)
+ {
+ data = &bitmap[(y1 + yt) * lineSize + x1 / 8];
+ for (xt = 0; xt < (w / 8) * 8; xt += 8)
+ {
+ cl = *data;
+ bmp->Draw8Pixels(xt, yt, cl, clrBlack);
+ data++;
+ }
+ if (w % 8 != 0)
+ {
+ cl = *data;
+ bmp->Draw8Pixels(xt, yt, cl & bitmaskl[w % 8 - 1], clrBlack);
+ }
+ }
+ }
+ else
+ {
+ // Bitmap is not byte alligned
+ for (yt = 0; yt < h; yt++)
+ {
+ temp = 0;
+ data = &bitmap[(y1 + yt) * lineSize + x1 / 8];
+ for (xt = 0; xt <= ((w / 8)) * 8; xt += 8)
+ {
+ cl = *data;
+ temp = temp | ((unsigned short) cl << (x1 % 8));
+ cl = (temp & 0xff00) >> 8;
+ if (xt > 0)
+ {
+ bmp->Draw8Pixels(xt - 8, yt, cl, clrBlack);
+ }
+ temp <<= 8;
+ data++;
+ }
+ if (w % 8 != 0)
+ {
+ // print the rest
+ if (8 - (x1 % 8) < w % 8)
+ {
+ cl = *data;
+ temp = temp | ((unsigned short) cl << (x1 % 8));
+ }
+ cl = (temp & 0xff00) >> 8;
+ bmp->Draw8Pixels(xt - 8, yt, cl & bitmaskl[(w % 8) - 1], clrBlack);
+ }
+ }
+ }
+ return bmp;
+}
+
+bool cBitmap::LoadPBM(const std::string & fileName)
+{
+ FILE * pbmFile;
+ char str[32];
+ int i;
+ int ch;
+ int w;
+ int h;
+
+ pbmFile = fopen(fileName.c_str(), "rb");
+ if (!pbmFile)
+ return false;
+
+ i = 0;
+ while ((ch = getc(pbmFile)) != EOF && i < 31)
+ {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ break;
+ str[i] = ch;
+ i++;
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ str[i] = 0;
+ if (strcmp(str, "P4") != 0)
+ return false;
+
+ while ((ch = getc(pbmFile)) == '#')
+ {
+ while ((ch = getc(pbmFile)) != EOF)
+ {
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ i = 0;
+ str[i] = ch;
+ i += 1;
+ while ((ch = getc(pbmFile)) != EOF && i < 31)
+ {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ break;
+ str[i] = ch;
+ i++;
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ str[i] = 0;
+ w = atoi(str);
+
+ i = 0;
+ while ((ch = getc(pbmFile)) != EOF && i < 31)
+ {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ break;
+ str[i] = ch;
+ i++;
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ str[i] = 0;
+ h = atoi(str);
+
+ delete[] bitmap;
+ width = w;
+ height = h;
+ // lines are byte aligned
+ lineSize = (width + 7) / 8;
+ bitmap = new unsigned char[lineSize * height];
+ fread(bitmap, lineSize * height, 1, pbmFile);
+ fclose(pbmFile);
+
+ return true;
+}
+
+void cBitmap::SavePBM(const std::string & fileName)
+{
+ int i;
+ char str[32];
+ FILE * fp;
+
+ fp = fopen(fileName.c_str(), "wb");
+ if (fp)
+ {
+ sprintf(str, "P4\n%d %d\n", width, height);
+ fwrite(str, strlen(str), 1, fp);
+ for (i = 0; i < lineSize * height; i++)
+ {
+ fwrite(&bitmap[i], 1, 1, fp);
+ }
+ fclose(fp);
+ }
+}
+
+} // end of namespace
diff --git a/glcdgraphics/bitmap.h b/glcdgraphics/bitmap.h
new file mode 100644
index 0000000..b6446a0
--- /dev/null
+++ b/glcdgraphics/bitmap.h
@@ -0,0 +1,75 @@
+/*
+ * GraphLCD graphics library
+ *
+ * bitmap.h - cBitmap class
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_BITMAP_H_
+#define _GLCDGRAPHICS_BITMAP_H_
+
+#include <string>
+
+namespace GLCD
+{
+
+enum eColor
+{
+ clrBlack,
+ clrWhite
+};
+
+class cFont;
+
+class cBitmap
+{
+protected:
+ int width;
+ int height;
+ int lineSize;
+ unsigned char * bitmap;
+
+public:
+ cBitmap(int width, int height, unsigned char * data = NULL);
+ cBitmap(const cBitmap & b);
+ ~cBitmap();
+
+ int Width() const { return width; }
+ int Height() const { return height; }
+ int LineSize() const { return lineSize; }
+ const unsigned char * Data() const { return bitmap; }
+
+ void Clear();
+ void Invert();
+ void DrawPixel(int x, int y, eColor color);
+ void Draw8Pixels(int x, int y, unsigned char pixels, eColor color);
+ void DrawLine(int x1, int y1, int x2, int y2, eColor color);
+ void DrawHLine(int x1, int y, int x2, eColor color);
+ void DrawVLine(int x, int y1, int y2, eColor color);
+ void DrawRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled);
+ void DrawRoundRectangle(int x1, int y1, int x2, int y2, eColor color, bool filled, int size);
+ void DrawEllipse(int x1, int y1, int x2, int y2, eColor color, bool filled, int quadrants);
+ void DrawSlope(int x1, int y1, int x2, int y2, eColor color, int type);
+ void DrawBitmap(int x, int y, const cBitmap & bitmap, eColor color);
+ int DrawText(int x, int y, int xmax, const std::string & text, const cFont * font,
+ eColor color = clrBlack, bool proportional = true, int skipPixels = 0);
+ int DrawCharacter(int x, int y, int xmax, char c, const cFont * font,
+ eColor color = clrBlack, int skipPixels = 0);
+
+ cBitmap * SubBitmap(int x1, int y1, int x2, int y2) const;
+ unsigned char GetPixel(int x, int y) const;
+
+ bool LoadPBM(const std::string & fileName);
+ void SavePBM(const std::string & fileName);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/common.c b/glcdgraphics/common.c
new file mode 100644
index 0000000..8942424
--- /dev/null
+++ b/glcdgraphics/common.c
@@ -0,0 +1,60 @@
+/*
+ * GraphLCD graphics library
+ *
+ * common.c - various functions
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <ctype.h>
+
+#include "common.h"
+
+
+namespace GLCD
+{
+
+void clip(int & value, int min, int max)
+{
+ if (value < min)
+ value = min;
+ if (value > max)
+ value = max;
+}
+
+void sort(int & value1, int & value2)
+{
+ if (value2 < value1)
+ {
+ int tmp;
+ tmp = value2;
+ value2 = value1;
+ value1 = tmp;
+ }
+}
+
+std::string trim(const std::string & s)
+{
+ std::string::size_type start, end;
+
+ start = 0;
+ while (start < s.length())
+ {
+ if (!isspace(s[start]))
+ break;
+ start++;
+ }
+ end = s.length() - 1;
+ while (end >= 0)
+ {
+ if (!isspace(s[end]))
+ break;
+ end--;
+ }
+ return s.substr(start, end - start + 1);
+}
+
+} // end of namespace
diff --git a/glcdgraphics/common.h b/glcdgraphics/common.h
new file mode 100644
index 0000000..2865602
--- /dev/null
+++ b/glcdgraphics/common.h
@@ -0,0 +1,26 @@
+/*
+ * GraphLCD graphics library
+ *
+ * common.h - various functions
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_COMMON_H_
+#define _GLCDGRAPHICS_COMMON_H_
+
+#include <string>
+
+namespace GLCD
+{
+
+void clip(int & value, int min, int max);
+void sort(int & value1, int & value2);
+std::string trim(const std::string & s);
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/font.c b/glcdgraphics/font.c
new file mode 100644
index 0000000..1735cf2
--- /dev/null
+++ b/glcdgraphics/font.c
@@ -0,0 +1,581 @@
+/*
+ * GraphLCD graphics library
+ *
+ * font.c - font handling
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#include "common.h"
+#include "font.h"
+
+#ifdef HAVE_FREETYPE2
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <iconv.h>
+#endif
+
+namespace GLCD
+{
+
+static const char * kFontFileSign = "FNT3";
+static const uint32_t kFontHeaderSize = 16;
+static const uint32_t kCharHeaderSize = 4;
+
+//#pragma pack(1)
+//struct tFontHeader
+//{
+// char sign[4]; // = FONTFILE_SIGN
+// unsigned short height; // total height of the font
+// unsigned short ascent; // ascender of the font
+// unsigned short line; // line height
+// unsigned short reserved;
+// unsigned short space; // space between characters of a string
+// unsigned short count; // number of chars in this file
+//};
+//
+//struct tCharHeader
+//{
+// unsigned short character;
+// unsigned short width;
+//};
+//#pragma pack()
+
+cFont::cFont()
+{
+ Init();
+}
+
+cFont::~cFont()
+{
+ Unload();
+}
+
+bool cFont::LoadFNT(const std::string & fileName)
+{
+ // cleanup if we already had a loaded font
+ Unload();
+
+ FILE * fontFile;
+ int i;
+ uint8_t buffer[10000];
+ uint16_t fontHeight;
+ uint16_t numChars;
+ int maxWidth = 0;
+
+ fontFile = fopen(fileName.c_str(), "rb");
+ if (!fontFile)
+ return false;
+
+ fread(buffer, kFontHeaderSize, 1, fontFile);
+ if (buffer[0] != kFontFileSign[0] ||
+ buffer[1] != kFontFileSign[1] ||
+ buffer[2] != kFontFileSign[2] ||
+ buffer[3] != kFontFileSign[3])
+ {
+ fclose(fontFile);
+ return false;
+ }
+
+ fontHeight = buffer[4] | (buffer[5] << 8);
+ totalAscent = buffer[6] | (buffer[7] << 8);
+ lineHeight = buffer[8] | (buffer[9] << 8);
+ spaceBetween = buffer[12] | (buffer[13] << 8);
+ numChars = buffer[14] | (buffer[15] << 8);
+ for (i = 0; i < numChars; i++)
+ {
+ uint8_t chdr[kCharHeaderSize];
+ uint16_t charWidth;
+ uint16_t character;
+ fread(chdr, kCharHeaderSize, 1, fontFile);
+ character = chdr[0] | (chdr[1] << 8);
+ charWidth = chdr[2] | (chdr[3] << 8);
+ fread(buffer, fontHeight * ((charWidth + 7) / 8), 1, fontFile);
+ if (characters[character])
+ delete characters[character];
+ characters[character] = new cBitmap(charWidth, fontHeight, buffer);
+ if (characters[character]->Width() > maxWidth)
+ maxWidth = characters[character]->Width();
+ }
+ fclose(fontFile);
+
+ totalWidth = maxWidth;
+ totalHeight = fontHeight;
+
+ return true;
+}
+
+bool cFont::SaveFNT(const std::string & fileName) const
+{
+ FILE * fontFile;
+ uint8_t fhdr[kFontHeaderSize];
+ uint8_t chdr[kCharHeaderSize];
+ uint16_t numChars;
+ int i;
+
+ fontFile = fopen(fileName.c_str(),"w+b");
+ if (!fontFile)
+ {
+ syslog(LOG_ERR, "cFont::SaveFNT(): Cannot open file: %s for writing\n",fileName.c_str());
+ return false;
+ }
+
+ numChars = 0;
+ for (i = 0; i < 256; i++)
+ {
+ if (characters[i])
+ {
+ numChars++;
+ }
+ }
+
+ memcpy(fhdr, kFontFileSign, 4);
+ fhdr[4] = (uint8_t) totalHeight;
+ fhdr[5] = (uint8_t) (totalHeight >> 8);
+ fhdr[6] = (uint8_t) totalAscent;
+ fhdr[7] = (uint8_t) (totalAscent >> 8);
+ fhdr[8] = (uint8_t) lineHeight;
+ fhdr[9] = (uint8_t) (lineHeight >> 8);
+ fhdr[10] = 0;
+ fhdr[11] = 0;
+ fhdr[12] = (uint8_t) spaceBetween;
+ fhdr[13] = (uint8_t) (spaceBetween >> 8);
+ fhdr[14] = (uint8_t) numChars;
+ fhdr[15] = (uint8_t) (numChars >> 8);
+
+ // write font file header
+ fwrite(fhdr, kFontHeaderSize, 1, fontFile);
+
+ for (i = 0; i < 256; i++)
+ {
+ if (characters[i])
+ {
+ chdr[0] = (uint8_t) i;
+ chdr[1] = (uint8_t) (i >> 8);
+ chdr[2] = (uint8_t) characters[i]->Width();
+ chdr[3] = (uint8_t) (characters[i]->Width() >> 8);
+ fwrite(chdr, kCharHeaderSize, 1, fontFile);
+ fwrite(characters[i]->Data(), totalHeight * characters[i]->LineSize(), 1, fontFile);
+ }
+ }
+
+ fclose(fontFile);
+
+ syslog(LOG_DEBUG, "cFont::SaveFNT(): Font file '%s' written successfully\n", fileName.c_str());
+
+ return true;
+}
+
+bool cFont::LoadFT2(const std::string & fileName, const std::string & encoding,
+ int size, bool dingBats)
+{
+ // cleanup if we already had a loaded font
+ Unload();
+#ifdef HAVE_FREETYPE2
+ if (access(fileName.c_str(), F_OK) != 0)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: Font file (%s) does not exist!!", fileName.c_str());
+ return false;
+ }
+ // file exists
+ FT_Library library;
+ FT_Face face;
+ FT_GlyphSlot slot;
+
+ int error = FT_Init_FreeType(&library);
+ if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: Could not init freetype library");
+ return false;
+ }
+ error = FT_New_Face(library, fileName.c_str(), 0, &face);
+ // everything ok?
+ if (error == FT_Err_Unknown_File_Format)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: Font file (%s) could be opened and read, but it appears that its font format is unsupported", fileName.c_str());
+ error = FT_Done_Face(face);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error);
+ error = FT_Done_FreeType(library);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error);
+ return false;
+ }
+ else if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: Font file (%s) could not be opened or read, or simply it is broken,\n error code was %x", fileName.c_str(), error);
+ error = FT_Done_Face(face);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error);
+ error = FT_Done_FreeType(library);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error);
+ return false;
+ }
+
+ // set slot
+ slot = face->glyph;
+
+ // set Size
+ FT_Set_Char_Size(face, 0, size * 64, 0, 0);
+
+ wchar_t utf_buff[256];
+ if (dingBats)
+ {
+/*
+ FT_CharMap charmap = 0;
+ for (int n = 0; n < face->num_charmaps; n++)
+ {
+ if (face->charmaps[n]->platform_id == 3 &&
+ face->charmaps[n]->encoding_id == 0)
+ {
+ charmap = face->charmaps[n];
+ //break;
+ }
+ }
+ if (charmap)
+ syslog(LOG_ERR, "cFont::LoadFT2: platform_id: %d, encoding_id: %d", charmap->platform_id, charmap->encoding_id);
+ error = FT_Set_Charmap(_face, charmap);
+ if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Select_Charmap encoding not supported: %d", charmap->encoding_id);
+ }
+*/
+ }
+ else
+ {
+ iconv_t cd;
+ if ((cd = iconv_open("WCHAR_T", encoding.c_str())) == (iconv_t) -1)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: Iconv encoding not supported: %s", encoding.c_str());
+ error = FT_Done_Face(face);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error);
+ error = FT_Done_FreeType(library);
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error);
+ return false;
+ }
+ for (int c = 0; c < 256; c++)
+ {
+ char char_buff = c;
+ wchar_t wchar_buff;
+ char * in_buff,* out_buff;
+ size_t in_len, out_len, count;
+
+ in_len = 1;
+ out_len = 4;
+ in_buff = (char *) &char_buff;
+ out_buff = (char *) &wchar_buff;
+ count = iconv(cd, &in_buff, &in_len, &out_buff, &out_len);
+ if ((size_t) -1 == count)
+ {
+ utf_buff[c] = 0;
+ }
+ utf_buff[c] = wchar_buff;
+ }
+ iconv_close(cd);
+ }
+
+ // get some global parameters
+ totalHeight = (face->size->metrics.ascender >> 6) - (face->size->metrics.descender >> 6);
+ totalWidth = face->size->metrics.max_advance >> 6;
+ totalAscent = face->size->metrics.ascender >> 6;
+ lineHeight = face->size->metrics.height >> 6;
+ spaceBetween = 0;
+#if 0
+ syslog(LOG_DEBUG, "cFont::LoadFT2: totalHeight = %d", totalHeight);
+ syslog(LOG_DEBUG, "cFont::LoadFT2: totalWidth = %d", totalWidth);
+ syslog(LOG_DEBUG, "cFont::LoadFT2: totalAscent = %d", totalAscent);
+ syslog(LOG_DEBUG, "cFont::LoadFT2: lineHeight = %d", lineHeight);
+ syslog(LOG_DEBUG, "cFont::LoadFT2: spaceBetween = %d", spaceBetween);
+#endif
+ // render glyphs for ASCII codes 0 to 255 in our bitmap class
+ FT_UInt glyph_index;
+ int num_char;
+
+ for (num_char = 0; num_char < 256; num_char++)
+ {
+ if (dingBats)
+ {
+ //Get FT char index & load the char
+ error = FT_Load_Char(face, num_char, FT_LOAD_DEFAULT);
+ }
+ else
+ {
+ //Get FT char index
+ glyph_index = FT_Get_Char_Index(face, utf_buff[num_char]);
+ //Load the char
+ error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
+ }
+ if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Load_Glyph: %x", error);
+ }
+
+ // convert to a mono bitmap
+ error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);
+ if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: ERROR when calling FT_Render_Glyph: %x", error);
+ }
+
+ // now, fill our pixel data
+ cBitmap * charBitmap = new cBitmap(face->glyph->advance.x >> 6, totalHeight);
+ charBitmap->Clear();
+ unsigned char * bufPtr = face->glyph->bitmap.buffer;
+ unsigned char pixel;
+ for (int y = 0; y < face->glyph->bitmap.rows; y++)
+ {
+ for (int x = 0; x < face->glyph->bitmap.width; x++)
+ {
+ pixel = (bufPtr[x / 8] >> (7 - x % 8)) & 1;
+ if (pixel)
+ charBitmap->DrawPixel((face->glyph->metrics.horiBearingX >> 6) + x,
+ (face->size->metrics.ascender >> 6) - (face->glyph->metrics.horiBearingY >> 6) + y,
+ GLCD::clrBlack);
+ }
+ bufPtr += face->glyph->bitmap.pitch;
+ }
+ SetCharacter((char) num_char, charBitmap);
+ }
+ error = FT_Done_Face(face);
+ if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_Face(..) returned (%d)", error);
+ }
+ error = FT_Done_FreeType(library);
+ if (error)
+ {
+ syslog(LOG_ERR, "cFont::LoadFT2: FT_Done_FreeType(..) returned (%d)", error);
+ }
+ return true;
+#else
+ syslog(LOG_ERR, "cFont::LoadFT2: glcdgraphics was compiled without FreeType2 support!!!");
+ return false;
+#endif
+}
+
+int cFont::Width(char ch) const
+{
+ if (characters[(unsigned char) ch])
+ return characters[(unsigned char) ch]->Width();
+ else
+ return 0;
+}
+
+int cFont::Width(const std::string & str) const
+{
+ unsigned int i;
+ int sum = 0;
+
+ for (i = 0; i < str.length(); i++)
+ {
+ sum += Width(str[i]);
+ }
+ if (str.length() > 1)
+ {
+ sum += spaceBetween * (str.length() - 1);
+ }
+ return sum;
+}
+
+int cFont::Width(const std::string & str, unsigned int len) const
+{
+ unsigned int i;
+ int sum = 0;
+
+ for (i = 0; i < str.length() && i < len; i++)
+ {
+ sum += Width(str[i]);
+ }
+ if (std::min(str.length(), (size_t) len) > 1)
+ {
+ sum += spaceBetween * (std::min(str.length(), (size_t) len) - 1);
+ }
+ return sum;
+}
+
+int cFont::Height(char ch) const
+{
+ if (characters[(unsigned char) ch])
+ return characters[(unsigned char) ch]->Height();
+ else
+ return 0;
+}
+
+int cFont::Height(const std::string & str) const
+{
+ unsigned int i;
+ int sum = 0;
+
+ for (i = 0; i < str.length(); i++)
+ sum = std::max(sum, Height(str[i]));
+ return sum;
+}
+
+int cFont::Height(const std::string & str, unsigned int len) const
+{
+ unsigned int i;
+ int sum = 0;
+
+ for (i = 0; i < str.length() && i < len; i++)
+ sum = std::max(sum, Height(str[i]));
+ return sum;
+}
+
+const cBitmap * cFont::GetCharacter(char ch) const
+{
+ return characters[(unsigned char) ch];
+}
+
+void cFont::SetCharacter(char ch, cBitmap * bitmapChar)
+{
+ // adjust maxwidth if necessary
+ if (totalWidth < bitmapChar->Width())
+ totalWidth = bitmapChar->Width();
+
+ // delete if already allocated
+ if (characters[(unsigned char) ch])
+ delete characters[(unsigned char) ch];
+
+ // store new character
+ characters[(unsigned char) ch] = bitmapChar;
+}
+
+void cFont::Init()
+{
+ totalWidth = 0;
+ totalHeight = 0;
+ totalAscent = 0;
+ spaceBetween = 0;
+ lineHeight = 0;
+ for (int i = 0; i < 256; i++)
+ {
+ characters[i] = NULL;
+ }
+}
+
+void cFont::Unload()
+{
+ // cleanup
+ for (int i = 0; i < 256; i++)
+ {
+ if (characters[i])
+ {
+ delete characters[i];
+ }
+ }
+ // re-init
+ Init();
+}
+
+void cFont::WrapText(int Width, int Height, std::string & Text,
+ std::vector <std::string> & Lines, int * ActualWidth) const
+{
+ int maxLines;
+ int lineCount;
+ int textWidth;
+ std::string::size_type start;
+ std::string::size_type pos;
+ std::string::size_type posLast;
+
+ Lines.clear();
+ maxLines = 2000;
+ if (Height > 0)
+ {
+ maxLines = Height / LineHeight();
+ if (maxLines == 0)
+ maxLines = 1;
+ }
+ lineCount = 0;
+
+ pos = 0;
+ start = 0;
+ posLast = 0;
+ textWidth = 0;
+ while (pos < Text.length() && (Height == 0 || lineCount < maxLines))
+ {
+ if (Text[pos] == '\n')
+ {
+ Lines.push_back(trim(Text.substr(start, pos - start)));
+ start = pos + 1;
+ posLast = pos + 1;
+ textWidth = 0;
+ lineCount++;
+ }
+ else if (textWidth > Width && (lineCount + 1) < maxLines)
+ {
+ if (posLast > start)
+ {
+ Lines.push_back(trim(Text.substr(start, posLast - start)));
+ start = posLast + 1;
+ posLast = start;
+ textWidth = this->Width(Text.substr(start, pos - start + 1)) + spaceBetween;
+ }
+ else
+ {
+ Lines.push_back(trim(Text.substr(start, pos - start)));
+ start = pos + 1;
+ posLast = start;
+ textWidth = this->Width(Text[pos]) + spaceBetween;
+ }
+ lineCount++;
+ }
+ else if (Text[pos] == ' ')
+ {
+ posLast = pos;
+ textWidth += this->Width(Text[pos]) + spaceBetween;
+ }
+ else
+ {
+ textWidth += this->Width(Text[pos]) + spaceBetween;
+ }
+ pos++;
+ }
+
+ if (Height == 0 || lineCount < maxLines)
+ {
+ if (textWidth > Width && (lineCount + 1) < maxLines)
+ {
+ if (posLast > start)
+ {
+ Lines.push_back(trim(Text.substr(start, posLast - start)));
+ start = posLast + 1;
+ posLast = start;
+ textWidth = this->Width(Text.substr(start, pos - start + 1)) + spaceBetween;
+ }
+ else
+ {
+ Lines.push_back(trim(Text.substr(start, pos - start)));
+ start = pos + 1;
+ posLast = start;
+ textWidth = this->Width(Text[pos]) + spaceBetween;
+ }
+ lineCount++;
+ }
+ if (pos > start)
+ {
+ Lines.push_back(trim(Text.substr(start)));
+ lineCount++;
+ }
+ textWidth = 0;
+ for (int i = 0; i < lineCount; i++)
+ textWidth = std::max(textWidth, this->Width(Lines[i]));
+ textWidth = std::min(textWidth, Width);
+ }
+ else
+ textWidth = Width;
+ if (ActualWidth)
+ *ActualWidth = textWidth;
+}
+
+} // end of namespace
diff --git a/glcdgraphics/font.h b/glcdgraphics/font.h
new file mode 100644
index 0000000..b36d5ac
--- /dev/null
+++ b/glcdgraphics/font.h
@@ -0,0 +1,75 @@
+/*
+ * GraphLCD graphics library
+ *
+ * font.h - font handling
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_FONT_H_
+#define _GLCDGRAPHICS_FONT_H_
+
+#include <string>
+#include <vector>
+
+#include "bitmap.h"
+
+namespace GLCD
+{
+
+class cFont
+{
+private:
+ int totalWidth;
+ int totalHeight;
+ int totalAscent;
+ int spaceBetween;
+ int lineHeight;
+
+ cBitmap * characters[256];
+protected:
+ void Init();
+ void Unload();
+public:
+ cFont();
+ ~cFont();
+
+ bool LoadFNT(const std::string & fileName);
+ bool SaveFNT(const std::string & fileName) const;
+ bool LoadFT2(const std::string & fileName, const std::string & encoding,
+ int size, bool dingBats = false);
+ int TotalWidth() const { return totalWidth; };
+ int TotalHeight() const { return totalHeight; };
+ int TotalAscent() const { return totalAscent; };
+ int SpaceBetween() const { return spaceBetween; };
+ int LineHeight() const { return lineHeight; };
+
+ void SetTotalWidth(int width) { totalWidth = width; };
+ void SetTotalHeight(int height) { totalHeight = height; };
+ void SetTotalAscent(int ascent) { totalAscent = ascent; };
+ void SetSpaceBetween(int width) { spaceBetween = width; };
+ void SetLineHeight(int height) { lineHeight = height; };
+
+ int Width(char ch) const;
+ int Width(const std::string & str) const;
+ int Width(const std::string & str, unsigned int len) const;
+ int Height(char ch) const;
+ int Height(const std::string & str) const;
+ int Height(const std::string & str, unsigned int len) const;
+
+ const cBitmap * GetCharacter(char ch) const;
+ void SetCharacter(char ch, cBitmap * bitmapChar);
+
+ void WrapText(int Width, int Height, std::string & Text,
+ std::vector <std::string> & Lines, int * TextWidth = NULL) const;
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/glcd.c b/glcdgraphics/glcd.c
new file mode 100644
index 0000000..6a74c33
--- /dev/null
+++ b/glcdgraphics/glcd.c
@@ -0,0 +1,277 @@
+/*
+ * GraphLCD graphics library
+ *
+ * glcd.c - GLCD file loading and saving
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <syslog.h>
+
+#include <string>
+
+#include "bitmap.h"
+#include "glcd.h"
+#include "image.h"
+
+
+namespace GLCD
+{
+
+using namespace std;
+
+const char * kGLCDFileSign = "GLC";
+
+/*
+#pragma pack(1)
+struct tGLCDHeader
+{
+ char sign[3]; // = "GLC"
+ char format; // D - single image, A - animation
+ uint16_t width; // width in pixels
+ uint16_t height; // height in pixels
+ // only for animations
+ uint16_t count; // number of pictures
+ uint32_t delay; // delay in ms
+};
+#pragma pack()
+*/
+
+cGLCDFile::cGLCDFile()
+{
+}
+
+cGLCDFile::~cGLCDFile()
+{
+}
+
+bool cGLCDFile::Load(cImage & image, const string & fileName)
+{
+ FILE * fp;
+ long fileSize;
+ char sign[4];
+ uint8_t buf[6];
+ uint16_t width;
+ uint16_t height;
+ uint16_t count;
+ uint32_t delay;
+
+ fp = fopen(fileName.c_str(), "rb");
+ if (!fp)
+ {
+ syslog(LOG_ERR, "glcdgraphics: open %s failed (cGLCDFile::Load).", fileName.c_str());
+ return false;
+ }
+
+ // get len of file
+ if (fseek(fp, 0, SEEK_END) != 0)
+ {
+ fclose(fp);
+ return false;
+ }
+ fileSize = ftell(fp);
+
+ // rewind and get Header
+ if (fseek(fp, 0, SEEK_SET) != 0)
+ {
+ fclose(fp);
+ return false;
+ }
+
+ // read header sign
+ if (fread(sign, 4, 1, fp) != 1)
+ {
+ fclose(fp);
+ return false;
+ }
+
+ // check header sign
+ if (strncmp(sign, kGLCDFileSign, 3) != 0)
+ {
+ syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
+ fclose(fp);
+ return false;
+ }
+
+ // read width and height
+ if (fread(buf, 4, 1, fp) != 1)
+ {
+ fclose(fp);
+ return false;
+ }
+
+ width = (buf[1] << 8) | buf[0];
+ height = (buf[3] << 8) | buf[2];
+ if (width == 0 || height == 0)
+ {
+ syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
+ fclose(fp);
+ return false;
+ }
+
+ if (sign[3] == 'D')
+ {
+ count = 1;
+ delay = 10;
+ // check file length
+ if (fileSize != (long) (height * ((width + 7) / 8) + 8))
+ {
+ syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong size (cGLCDFile::Load).", fileName.c_str());
+ fclose(fp);
+ return false;
+ }
+ }
+ else if (sign[3] == 'A')
+ {
+ // read count and delay
+ if (fread(buf, 6, 1, fp) != 1)
+ {
+ syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
+ fclose(fp);
+ return false;
+ }
+ count = (buf[1] << 8) | buf[0];
+ delay = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ // check file length
+ if (count == 0 ||
+ fileSize != (long) (count * (height * ((width + 7) / 8)) + 14))
+ {
+ syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong size (cGLCDFile::Load).", fileName.c_str());
+ fclose(fp);
+ return false;
+ }
+ // Set minimal limit for next image
+ if (delay < 10)
+ delay = 10;
+ }
+ else
+ {
+ syslog(LOG_ERR, "glcdgraphics: load %s failed, wrong header (cGLCDFile::Load).", fileName.c_str());
+ fclose(fp);
+ return false;
+ }
+
+ image.Clear();
+ image.SetWidth(width);
+ image.SetHeight(height);
+ image.SetDelay(delay);
+ unsigned char * bmpdata = new unsigned char[height * ((width + 7) / 8)];
+ if (bmpdata)
+ {
+ for (unsigned int n = 0; n < count; n++)
+ {
+ if (fread(bmpdata, height * ((width + 7) / 8), 1, fp) != 1)
+ {
+ delete[] bmpdata;
+ fclose(fp);
+ image.Clear();
+ return false;
+ }
+ image.AddBitmap(new cBitmap(width, height, bmpdata));
+ }
+ delete[] bmpdata;
+ }
+ else
+ {
+ syslog(LOG_ERR, "glcdgraphics: malloc failed (cGLCDFile::Load).");
+ fclose(fp);
+ image.Clear();
+ return false;
+ }
+ fclose(fp);
+
+ syslog(LOG_DEBUG, "glcdgraphics: image %s loaded.", fileName.c_str());
+ return true;
+}
+
+bool cGLCDFile::Save(cImage & image, const string & fileName)
+{
+ FILE * fp;
+ uint8_t buf[14];
+ uint16_t width;
+ uint16_t height;
+ uint16_t count;
+ uint32_t delay;
+ const cBitmap * bitmap;
+ int i;
+
+ if (image.Count() == 0)
+ return false;
+
+ fp = fopen(fileName.c_str(), "wb");
+ if (!fp)
+ {
+ syslog(LOG_ERR, "glcdgraphics: open %s failed (cGLCDFile::Save).", fileName.c_str());
+ return false;
+ }
+
+ memcpy(buf, kGLCDFileSign, 3);
+ count = image.Count();
+ delay = image.Delay();
+ if (count == 1)
+ {
+ buf[3] = 'D';
+ }
+ else
+ {
+ buf[3] = 'A';
+ }
+ bitmap = image.GetBitmap(0);
+ width = bitmap->Width();
+ height = bitmap->Height();
+ buf[4] = (uint8_t) width;
+ buf[5] = (uint8_t) (width >> 8);
+ buf[6] = (uint8_t) height;
+ buf[7] = (uint8_t) (height >> 8);
+ if (count == 1)
+ {
+ if (fwrite(buf, 8, 1, fp) != 1)
+ {
+ fclose(fp);
+ return false;
+ }
+ }
+ else
+ {
+ buf[8] = (uint8_t) count;
+ buf[9] = (uint8_t) (count >> 8);
+ buf[10] = (uint8_t) delay;
+ buf[11] = (uint8_t) (delay >> 8);
+ buf[12] = (uint8_t) (delay >> 16);
+ buf[13] = (uint8_t) (delay >> 24);
+ if (fwrite(buf, 14, 1, fp) != 1)
+ {
+ fclose(fp);
+ return false;
+ }
+ }
+ for (i = 0; i < count; i++)
+ {
+ bitmap = image.GetBitmap(i);
+ if (bitmap)
+ {
+ if (bitmap->Width() == width && bitmap->Height() == height)
+ {
+ if (fwrite(bitmap->Data(), height * ((width + 7) / 8), 1, fp) != 1)
+ {
+ fclose(fp);
+ return false;
+ }
+ }
+ }
+ }
+ fclose(fp);
+
+ syslog(LOG_DEBUG, "glcdgraphics: image %s saved.", fileName.c_str());
+ return true;
+}
+
+} // end of namespace
diff --git a/glcdgraphics/glcd.h b/glcdgraphics/glcd.h
new file mode 100644
index 0000000..7f811aa
--- /dev/null
+++ b/glcdgraphics/glcd.h
@@ -0,0 +1,36 @@
+/*
+ * GraphLCD graphics library
+ *
+ * glcd.h - GLCD file loading and saving
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_GLCD_H_
+#define _GLCDGRAPHICS_GLCD_H_
+
+#include "imagefile.h"
+
+namespace GLCD
+{
+
+class cImage;
+
+class cGLCDFile : public cImageFile
+{
+public:
+ cGLCDFile();
+ virtual ~cGLCDFile();
+ virtual bool Load(cImage & image, const std::string & fileName);
+ virtual bool Save(cImage & image, const std::string & fileName);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/image.c b/glcdgraphics/image.c
new file mode 100644
index 0000000..72003b1
--- /dev/null
+++ b/glcdgraphics/image.c
@@ -0,0 +1,67 @@
+/*
+ * GraphLCD graphics library
+ *
+ * image.c - image and animation handling
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include "bitmap.h"
+#include "image.h"
+
+
+namespace GLCD
+{
+
+using namespace std;
+
+cImage::cImage()
+: width(0),
+ height(0),
+ delay(0),
+ curBitmap(0),
+ lastChange(0)
+{
+}
+
+cImage::~cImage()
+{
+ Clear();
+}
+
+cBitmap * cImage::GetBitmap() const
+{
+ if (curBitmap < bitmaps.size())
+ return bitmaps[curBitmap];
+ return NULL;
+}
+
+cBitmap * cImage::GetBitmap(unsigned int nr) const
+{
+ if (nr < bitmaps.size())
+ return bitmaps[nr];
+ return NULL;
+}
+
+void cImage::Clear()
+{
+ vector <cBitmap *>::iterator it;
+ for (it = bitmaps.begin(); it != bitmaps.end(); it++)
+ {
+ delete *it;
+ }
+ bitmaps.clear();
+ width = 0;
+ height = 0;
+ delay = 0;
+ curBitmap = 0;
+ lastChange = 0;
+}
+
+} // end of namespace
diff --git a/glcdgraphics/image.h b/glcdgraphics/image.h
new file mode 100644
index 0000000..888d942
--- /dev/null
+++ b/glcdgraphics/image.h
@@ -0,0 +1,58 @@
+/*
+ * GraphLCD graphics library
+ *
+ * image.h - image and animation handling
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_IMAGE_H_
+#define _GLCDGRAPHICS_IMAGE_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+namespace GLCD
+{
+
+class cBitmap;
+
+class cImage
+{
+private:
+ unsigned int width;
+ unsigned int height;
+ unsigned int delay;
+ unsigned int curBitmap;
+ uint64_t lastChange;
+ std::vector <cBitmap *> bitmaps;
+public:
+ cImage();
+ ~cImage();
+
+ unsigned int Width() const { return width; }
+ unsigned int Height() const { return height; }
+ unsigned int Count() const { return bitmaps.size(); }
+ unsigned int Delay() const { return delay; }
+ uint64_t LastChange() const { return lastChange; }
+ void First(uint64_t t) { lastChange = t; curBitmap = 0; }
+ bool Next(uint64_t t) { lastChange = t; curBitmap++; return curBitmap < bitmaps.size(); }
+ void SetWidth(unsigned int Width) { width = Width; }
+ void SetHeight(unsigned int Height) { height = Height; }
+ void SetDelay(unsigned int d) { delay = d; }
+ cBitmap * GetBitmap(unsigned int nr) const;
+ cBitmap * GetBitmap() const;
+ void AddBitmap(cBitmap * Bitmap) { bitmaps.push_back(Bitmap); }
+ void Clear();
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/imagefile.c b/glcdgraphics/imagefile.c
new file mode 100644
index 0000000..2f56f4a
--- /dev/null
+++ b/glcdgraphics/imagefile.c
@@ -0,0 +1,35 @@
+/*
+ * GraphLCD graphics library
+ *
+ * imagefile.h - base class for file loading and saving
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include "image.h"
+#include "imagefile.h"
+
+namespace GLCD
+{
+
+cImageFile::cImageFile(void)
+{
+}
+cImageFile::~cImageFile(void)
+{
+}
+
+bool cImageFile::Load(cImage & image, const std::string & fileName)
+{
+ return false;
+}
+
+bool cImageFile::Save(cImage & image, const std::string & fileName)
+{
+ return false;
+}
+
+} // end of namespace
diff --git a/glcdgraphics/imagefile.h b/glcdgraphics/imagefile.h
new file mode 100644
index 0000000..bf5ff5e
--- /dev/null
+++ b/glcdgraphics/imagefile.h
@@ -0,0 +1,33 @@
+/*
+ * GraphLCD graphics library
+ *
+ * imagefile.h - base class for file loading and saving
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_IMAGEFILE_H_
+#define _GLCDGRAPHICS_IMAGEFILE_H_
+
+#include <string>
+
+namespace GLCD
+{
+
+class cImage;
+
+class cImageFile
+{
+public:
+ cImageFile();
+ virtual ~cImageFile();
+ virtual bool Load(cImage & image, const std::string & fileName);
+ virtual bool Save(cImage & image, const std::string & fileName);
+};
+
+} // end of namespace
+
+#endif
diff --git a/glcdgraphics/pbm.c b/glcdgraphics/pbm.c
new file mode 100644
index 0000000..fe60104
--- /dev/null
+++ b/glcdgraphics/pbm.c
@@ -0,0 +1,187 @@
+/*
+ * GraphLCD graphics library
+ *
+ * pbm.c - PBM file loading and saving
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <syslog.h>
+
+#include <string>
+
+#include "bitmap.h"
+#include "pbm.h"
+#include "image.h"
+
+
+namespace GLCD
+{
+
+cPBMFile::cPBMFile()
+{
+}
+
+cPBMFile::~cPBMFile()
+{
+}
+
+bool cPBMFile::Load(cImage & image, const std::string & fileName)
+{
+ FILE * pbmFile;
+ char str[32];
+ int i;
+ int ch;
+ int w;
+ int h;
+
+ pbmFile = fopen(fileName.c_str(), "rb");
+ if (!pbmFile)
+ return false;
+
+ i = 0;
+ while ((ch = getc(pbmFile)) != EOF && i < 31)
+ {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ break;
+ str[i] = ch;
+ i++;
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ str[i] = 0;
+ if (strcmp(str, "P4") != 0)
+ return false;
+
+ while ((ch = getc(pbmFile)) == '#')
+ {
+ while ((ch = getc(pbmFile)) != EOF)
+ {
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ i = 0;
+ str[i] = ch;
+ i += 1;
+ while ((ch = getc(pbmFile)) != EOF && i < 31)
+ {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ break;
+ str[i] = ch;
+ i++;
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ str[i] = 0;
+ w = atoi(str);
+
+ i = 0;
+ while ((ch = getc(pbmFile)) != EOF && i < 31)
+ {
+ if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ break;
+ str[i] = ch;
+ i++;
+ }
+ if (ch == EOF)
+ {
+ fclose(pbmFile);
+ return false;
+ }
+ str[i] = 0;
+ h = atoi(str);
+
+ image.Clear();
+ image.SetWidth(w);
+ image.SetHeight(h);
+ image.SetDelay(100);
+ unsigned char * bmpdata = new unsigned char[h * ((w + 7) / 8)];
+ if (bmpdata)
+ {
+ if (fread(bmpdata, h * ((w + 7) / 8), 1, pbmFile) != 1)
+ {
+ delete[] bmpdata;
+ fclose(pbmFile);
+ image.Clear();
+ return false;
+ }
+ image.AddBitmap(new cBitmap(w, h, bmpdata));
+ delete[] bmpdata;
+ }
+ else
+ {
+ syslog(LOG_ERR, "glcdgraphics: malloc failed (cPBMFile::Load).");
+ fclose(pbmFile);
+ return false;
+ }
+ fclose(pbmFile);
+ syslog(LOG_DEBUG, "glcdgraphics: image %s loaded.", fileName.c_str());
+
+ return true;
+}
+
+bool cPBMFile::Save(cImage & image, const std::string & fileName)
+{
+ FILE * fp;
+ char str[32];
+ const cBitmap * bitmap;
+
+ if (image.Count() == 1)
+ {
+ fp = fopen(fileName.c_str(), "wb");
+ if (fp)
+ {
+ bitmap = image.GetBitmap(0);
+ if (bitmap)
+ {
+ sprintf(str, "P4\n%d %d\n", bitmap->Width(), bitmap->Height());
+ fwrite(str, strlen(str), 1, fp);
+ fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp);
+ }
+ fclose(fp);
+ }
+ }
+ else
+ {
+ uint16_t i;
+ char tmpStr[256];
+
+ for (i = 0; i < image.Count(); i++)
+ {
+ sprintf(tmpStr, "%.248s.%05d", fileName.c_str(), i);
+ fp = fopen(tmpStr, "wb");
+ if (fp)
+ {
+ bitmap = image.GetBitmap(i);
+ if (bitmap)
+ {
+ sprintf(str, "P4\n%d %d\n", bitmap->Width(), bitmap->Height());
+ fwrite(str, strlen(str), 1, fp);
+ fwrite(bitmap->Data(), bitmap->LineSize() * bitmap->Height(), 1, fp);
+ }
+ fclose(fp);
+ }
+ }
+ }
+ return true;
+}
+
+} // end of namespace
+
diff --git a/glcdgraphics/pbm.h b/glcdgraphics/pbm.h
new file mode 100644
index 0000000..8e9535f
--- /dev/null
+++ b/glcdgraphics/pbm.h
@@ -0,0 +1,34 @@
+/*
+ * GraphLCD graphics library
+ *
+ * pbm.h - PBM file loading and saving
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2006 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#ifndef _GLCDGRAPHICS_PBM_H_
+#define _GLCDGRAPHICS_PBM_H_
+
+#include "imagefile.h"
+
+namespace GLCD
+{
+
+class cImage;
+
+class cPBMFile : public cImageFile
+{
+public:
+ cPBMFile();
+ virtual ~cPBMFile();
+ virtual bool Load(cImage & image, const std::string & fileName);
+ virtual bool Save(cImage & image, const std::string & fileName);
+};
+
+} // end of namespace
+
+#endif
+
diff --git a/graphlcd.conf b/graphlcd.conf
new file mode 100644
index 0000000..07a33e4
--- /dev/null
+++ b/graphlcd.conf
@@ -0,0 +1,528 @@
+# graphlcd.conf.sample
+#
+# This file contains a sample configuration for the graphlcd driver
+# library.
+#
+# The format is ini-file-like. It is divided into sections that start
+# at markers that look like [section]. Comments are all line-based
+# comments, and are lines that start with '#'.
+#
+# The file starts with general settings, that are used by several
+# drivers, followed by the sections. Each section represents a single
+# display with a driver definition and specific settings which define
+# how the driver acts. Some of these parameters like device, port and
+# size are already parsed by the library but the drivers can also read
+# their own options from the config file. The library passes them to
+# the drivers.
+
+# WaitMethod
+# Select the method that is used for sleeping.
+# Possible values:
+# 0 - usleep
+# 1 - nanosleep
+# 2 - nanosleep (sched_rr) - This is recommended on kernel 2.4 systems
+# 3 - gettimeofday - This is recommended on kernel 2.6 systems
+# Defaukt value: 3
+WaitMethod=3
+
+# WaitPriority
+# Select the process priority that is used when sleeping.
+# Possible values: -20 <= x <= 19
+# Default value: 0
+WaitPriority=0
+
+# General driver settings
+# This section lists the display settings that are parsed and
+# recognized by the driver library.
+#
+# Driver
+# Sets the display's driver.
+# Currently available are: framebuffer, gu140x32f, gu256x64-372,
+# gu256x64C-3xx0, hd61830, image, ks0108,
+# sed1520, sed1330, simlcd, t6963c,
+# gu126x64D-K610A4
+#
+# Device
+# Instead of using the direct output via port address (see Port), you
+# can use the parport device (/dev/parportX). The advantage over the
+# direct output via port address is that this works for non-root users
+# also. But it's a little bit slower. The modules ppdev.o, parport.o
+# and parport_pc.o must be loaded or compiled into the kernel.
+#
+# Port
+# Sets the port address of the parallel port. If this parameter is not
+# given, 0x378 is used. To use this direct output, the program that
+# uses the driver library has to be started with user 'root'.
+#
+# Width
+# Sets the horizontal size of the display. If this parameter is not
+# given, a default one specific to the driver is used.
+#
+# Height
+# Sets the vertical size of the display. If this parameter is not
+# given, a default one specific to the driver is used.
+#
+# UpsideDown
+# Rotates the display output by 180 degrees. This might be useful, if
+# the LCD is mounted upside-down.
+# Possible values: 'yes', 'no'
+# Default value: 'no'
+#
+# Invert
+# Inverts the display.
+# Possible values: 'yes', 'no'
+# Default value: 'no'
+#
+# Brightness
+# Sets the brightness of your display's backlight if supported by its
+# driver.
+# Supported by: gu140x32f, gu256x64-372, gu256x64-3900, gu126x64D-K610A4
+# Possible values: 0 <= x <= 100)
+# Default value: 100
+#
+# Contrast
+# Sets the contrast of your display if supported by its driver.
+# Supported by: serdisplib
+# Possible values: 0 <= x <= 10
+# Default value: 5
+#
+# Backlight
+# Switches the backlight of your display on and off if supported by
+# its driver.
+# Supported by: serdisplib
+# Possible values: 'yes', 'no'
+# Default value: 'yes'
+#
+# AdjustTiming
+# To get a timing that is as accurate as possible, the drivers measure
+# the time for port commands (see: benchmark in syslog). You might
+# decrease or increase the time to wait after port commands with this
+# parameter. Normally, there is no need to change this parameter.
+# (used by gu140x32f, gu256x64-372, gu256x64-3900, hd61830, ks0108,
+# sed1330, sed1520, gu126x64D-K610A4)
+# Possible values: -50 <= x <= 50
+# Default value: 0
+#
+# RefreshDisplay
+# Normally, most of the drivers do not update the whole display, but
+# only the areas that have changed since last update. So it might be,
+# that some faulty pixels would stay a longer time. To avoid this, the
+# plugin makes a complete refresh from time to time. This parameter
+# defines how often a complete refresh will be done.
+# e.g.: A value of 5 means, that the plugin will make a complete
+# refresh on every 5th update.
+# A value of 0 completely disables complete refreshs.
+# Possible values: 0 <= x <= 50
+# Default value: 5
+
+########################################################################
+
+[framebuffer]
+# framebuffer driver
+# Output goes to a framebuffer device
+# Default size: 320 x 240
+Driver=framebuffer
+
+#Width=320
+#Height=240
+#UpsideDown=no
+#Invert=no
+
+# Zoom
+# Determines if pixels should be drawn double sized.
+# Possible values: 0, 1
+Zoom=1
+
+########################################################################
+
+[gu140x32f]
+# gu140x32f driver
+# This is an 8-bit driver module for Noritake GU140x32-F7806 VFD
+# displays. The VFD is operating in it's 8 bit-mode connected to a
+# single PC parallel port.
+# Default size: 140 x 32
+Driver=gu140x32f
+
+Port=0x378
+#Device=/dev/parport0
+#Width=140
+#Height=32
+#UpsideDown=no
+#Invert=no
+#Brightness=100
+#AdjustTiming=0
+#RefreshDisplay=1
+
+# Wiring
+# Select the type of wiring your display is connected with.
+# Possible values: 'Standard', 'Windows'
+# Default value: 'Standard'
+Wiring=Standard
+
+########################################################################
+
+[gu256x64-372]
+# gu256x64-372 driver
+# This is an 8-bit driver module for Noritake GU256x64-372 VFD
+# displays. The VFD is operating in it's 8 bit-mode connected to a
+# single PC parallel port.
+# Default size: 256 x 64
+Driver=gu256x64-372
+
+Port=0x378
+#Device=/dev/parport0
+#Width=256
+#Height=64
+#UpsideDown=no
+#Invert=no
+#Brightness=100
+#AdjustTiming=0
+#RefreshDisplay=1
+
+########################################################################
+
+[gu256x64-3900]
+# gu256x64-3900 driver
+# This is a driver module for Noritake GU256X64x-3900 VFD displays. The
+# VFD is either operating in 8 bit-mode connected to a single PC
+# parallel port or in serial mode connected to a single PC serial port.
+# Default size: 256 x 64
+Driver=gu256x64-3900
+
+Port=0x378
+#Device=/dev/parport0
+#Width=256
+#Height=64
+#UpsideDown=no
+#Invert=no
+#Brightness=100
+#AdjustTiming=0
+#RefreshDisplay=1
+
+# Wiring
+# Select the type of wiring your display is connected with.
+# Possible values: 'Standard', 'Satyr'
+# Default value: 'Standard'
+Wiring=Standard
+
+# Interface
+# Select the interface your display is connnected to.
+# Possible values: 'Parallel', 'Serial'
+# Default value: 'Parallel'
+Interface=Parallel
+
+# DMA
+# Enables/disables the usage of the controller's DMA mode which
+# increases writing speed. This only works in parallel interface mode.
+# Possible values: 'yes', 'no'
+# Default value: 'yes'
+DMA=yes
+
+########################################################################
+
+[gu126x64D-K610A4]
+# GU126x64D-K610A4 driver
+# This is a driver module for Noritake GU126x64D-K610A4 VFD displays.
+# The VFD is operating in 8 bit-mode connected to a single PC
+# parallel port.
+# Default size: 126 x 64
+Driver=gu126x64D-K610A4
+
+Port=0x378
+# Device=/dev/parport0
+
+#Width=126
+#Height=64
+#UpsideDown=no
+#Invert=no
+#Brightness=100
+#RefreshDisplay=1
+#AdjustTiming=30
+
+# Debug some methods of the driver
+# (add the values of interest)
+#
+# 1: show a log at the start of a refresh
+# 2: show a log at the end of a refresh with timing information
+# 4: show the rows (8 pixel) refreshed
+# 8: show every commands/bytes sent to the display
+# 16: log every unsuccessful waiting for display acknowledge
+#
+#Debug=0
+
+########################################################################
+
+[hd61830]
+# hd61830 driver
+# This is a driver module for the Hitachi HD61830 LCD controller.
+# Default size: 240 x 128
+Driver=hd61830
+Port=0x378
+#Device=/dev/parport0
+#Width=240
+#Height=128
+#UpsideDown=no
+#Invert=no
+#AdjustTiming=0
+#RefreshDisplay=1
+
+########################################################################
+
+[image]
+# image driver
+# This is a driver module for writing image sequences in PBM (Portable
+# Bit Map) format that show the plugin's output.
+# Default size: 240 x 128
+Driver=image
+#Width=240
+#Height=128
+#UpsideDown=no
+#Invert=no
+
+########################################################################
+
+[ks0108]
+# ks0108 driver
+# This is a driver module for the Samsung KS0108 LCD controller.
+# Default size: 128 x 64
+Driver=ks0108
+Port=0x378
+#Device=/dev/parport0
+#Width=128
+#Height=64
+#UpsideDown=no
+#Invert=no
+#AdjustTiming=0
+#RefreshDisplay=1
+
+# Control
+# Select the variant of triggering the display's control lines.
+# Possible values: '0', '1'
+# Default value: '1'
+Control=1
+
+########################################################################
+
+[sed1330]
+# sed1330 driver
+# This is a driver module for the Epson SED1330/1335 LCD controller.
+# Default size: 320 x 240
+Driver=sed1330
+Port=0x378
+#Device=/dev/parport0
+#Width=320
+#Height=240
+#UpsideDown=no
+#Invert=no
+#AdjustTiming=0
+#refreshDisplay=1
+
+# Wiring
+# Select the type of wiring your display is connected with.
+# Possible values: 'Original', 'PowerLCD', 'LCDProc', 'Tweakers',
+# 'YASEDW'
+# Default value: 'Original'
+Wiring=Original
+
+# OscillatorFrequency
+# Select the frequency the oscillator on your LCD board uses in kHz.
+# Possible values: 1000 <= x <= 15000)
+# Default value: 9600
+OscillatorFrequency=9600
+
+# Interface
+# Select the interface mode your display is connected with.
+# Possible values: '6800', '8080'
+# Default value: '6800'
+Interface=6800
+
+########################################################################
+
+[sed1520]
+# sed1520 driver
+# This is a driver module for the Epson SED1520 LCD controller.
+# Default size: 120 x 32
+Driver=sed1520
+Port=0x378
+#Device=/dev/parport0
+#Width=120
+#Height=32
+#UpsideDown=no
+#Invert=no
+#AdjustTiming=0
+#RefreshDisplay=1
+
+########################################################################
+
+[simlcd]
+# simlcd driver
+# This is the SimLCD driver module. Output goes to a file instead of
+# LCD. Use SimLCD tool to view this file.
+# Default size: 240 x 128
+Driver=simlcd
+#Width=240
+#Height=128
+#UpsideDown=no
+#Invert=no
+
+########################################################################
+
+[t6963c]
+# t6963c driver
+# This is a driver module for the Toshiba T6963C LCD controller.
+# Default size: 240 x 128
+Driver=t6963c
+Port=0x378
+#Device=/dev/parport0
+#Width=240
+#Height=128
+#UpsideDown=no
+#Invert=no
+#RefreshDisplay=1
+
+# Wiring
+# Select the type of wiring your display is connected with.
+# Possible values: 'Standard', 'Windows', 'Serial'
+# Default value: 'Standard'
+Wiring=Standard
+
+# FontSelect
+# Select the font width your display uses for text mode. In most cases
+# this is selectable through one of the pins of your LCD board
+# Possible values: '6', '8'
+# Default value: '6'
+FontSelect=6
+
+# AutoMode
+# Enables or disables the usage of T6963C's auto mode which doubles
+# writing speed when enabled.
+# Possible values: 'yes', 'no'
+# Default value: 'yes'
+AutoMode=yes
+
+# StatusCheck
+# Enables or disables the usage of T6963C's status check. When using a
+# shielded cable for connecting your display, the disabling may be
+# possible. This results in doubling the speed of writing data to the
+# LCD.
+# Possible values: 'yes', 'no'
+# Default value: 'yes'
+StatusCheck=yes
+
+########################################################################
+
+[serdisp]
+Driver=serdisp
+# Controller
+# Select the serdisplib name of your display.
+# Possible values: See README in serdisplib package or http://serdisplib.sourceforge.net
+#Controller=nokia7110
+#Controller=sed1335
+Controller=optrex323
+
+# Options
+# Pass display specific options
+# Possible values: See driver-specific hardware page at http://serdisplib.sourceforge.net
+#
+# IMPORTANT: when using generic controllers like sed1330,sed1335,t6963c, width and height
+# need to be set here (if different from default settings)!
+# (serdisplib needs to be extended to be able to use 'Width' and 'Height'
+# settings directly - this will be added later)
+#
+#Options=MODE=8080
+#Options=DELAY=2000;FONTWIDTH=8;CHECK=1
+#Options=WIDTH=128;HEIGHT=64
+#Options=WIDTH=128;HEIGHT=64;DELAY=2000;FONTWIDTH=8;CHECK=1
+
+# Wiring
+# Select Wiring
+# Possible values: See driver-specific hardware page at http://serdisplib.sourceforge.net
+#Wiring=1
+#Wiring=PowerLCD
+#Wiring=DATA8,CS:nAUTO,A0:INIT,WR:nSTRB,RD:nSELIN
+
+# FGColour
+# Drawing colour for non-monochrome displays
+# Possible values: 0xRRGGBB (eg.: 0xFF0000)
+# Defaults to black (0x000000) if not set
+#FGColour=0x000000
+
+# BGColour
+# Background colour for non-monochrome displays
+# Possible values: 0xRRGGBB (eg.: 0x00FFFF)
+# Defaults to white (0xFFFFFF) if not set
+#BGColour=0xFFFFFF
+
+Port=0x378
+#Device=/dev/parport0
+#UpsideDown=no
+#Invert=no
+Contrast=5
+Backlight=yes
+
+# Settings 'Width' and 'Height' are ignored at the moment. For generic controllers # (sed1330/1335, t6963) width and height need to be set using setting 'Options' (look above)
+##Width=240
+##Height=128
+
+########################################################################
+
+[noritake800]
+# noritake800 driver
+# This is an 8-bit driver module for Noritake Noritake 800(A) series VFD
+# displays. The VFD is operating in it's 8 bit-mode connected to a
+# single PC parallel port.
+# Default size: 128 x 64
+Driver=noritake800
+Port=0x378
+#Device=/dev/parport0
+Width=128
+Height=64
+#UpsideDown=no
+#Invert=no
+Brightness=50
+#AdjustTiming=0 # not used
+#RefreshDisplay=0 # not used
+
+# Wiring
+# Select the type of wiring your display is connected with.
+# Possible values: 'LiquidMp3', 'MZ'
+# Default value: 'LiquidMp3'
+Wiring=LiquidMp3
+
+########################################################################
+
+[avrctl]
+# avrctl driver
+# This is an driver module for my AVR controlled LCD display connected via
+# USB port. It uses some simple commands to update the display content.
+# Default size: 256 x 128
+Driver=avrctl
+Device=/dev/ttyUSB0
+Width=256
+Height=128
+#UpsideDown=no
+#Invert=no
+Brightness=50
+RefreshDisplay=1
+
+########################################################################
+
+[g15daemon]
+# pseudo device for the g15daemon meta driver
+# Output goes to the g15daemon which then displays it
+Driver=g15daemon
+Width=160
+Height=43
+
+########################################################################
+
+[network]
+# network driver
+# Default size: 240 x 128
+Driver=network
+Width=256
+Height=128
+UpsideDown=no
+Invert=no
+Brightness=10
+RefreshDisplay=1
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..572067b
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,47 @@
+#
+# Makefile for the graphlcd tools
+#
+
+
+-include ../Make.config
+
+### Targets:
+
+all:
+ @$(MAKE) -C convpic all
+ @$(MAKE) -C crtfont all
+ifdef HAVE_FREETYPE2
+ @$(MAKE) -C genfont all
+endif
+ @$(MAKE) -C showpic all
+ @$(MAKE) -C showtext all
+ @$(MAKE) -C lcdtestpattern all
+
+install:
+ @$(MAKE) -C convpic install
+ @$(MAKE) -C crtfont install
+ifdef HAVE_FREETYPE2
+ @$(MAKE) -C genfont install
+endif
+ @$(MAKE) -C showpic install
+ @$(MAKE) -C showtext install
+ @$(MAKE) -C lcdtestpattern install
+
+uninstall:
+ @$(MAKE) -C convpic uninstall
+ @$(MAKE) -C crtfont uninstall
+ifdef HAVE_FREETYPE2
+ @$(MAKE) -C genfont uninstall
+endif
+ @$(MAKE) -C showpic uninstall
+ @$(MAKE) -C showtext uninstall
+ @$(MAKE) -C lcdtestpattern uninstall
+
+clean:
+ @$(MAKE) -C convpic clean
+ @$(MAKE) -C crtfont clean
+ @$(MAKE) -C genfont clean
+ @$(MAKE) -C showpic clean
+ @$(MAKE) -C showtext clean
+ @$(MAKE) -C lcdtestpattern clean
+
diff --git a/tools/convpic/Makefile b/tools/convpic/Makefile
new file mode 100644
index 0000000..91aaed4
--- /dev/null
+++ b/tools/convpic/Makefile
@@ -0,0 +1,46 @@
+#
+# Makefile for the GraphLCD tool convpic
+#
+
+-include ../../Make.config
+
+PRGNAME = convpic
+
+OBJS = $(PRGNAME).o bmp.o tiff.o tuxbox.o
+
+INCLUDES += -I../../
+LIBDIRS += -L../../glcdgraphics/
+
+
+all: $(PRGNAME)
+.PHONY: all
+
+# Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+# The main program:
+
+$(PRGNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBS) $(LIBDIRS) -lglcdgraphics -lstdc++ -o $(PRGNAME)
+
+install: $(PRGNAME)
+ install -d $(BINDIR)
+ install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR)
+
+uninstall:
+ rm -f $(BINDIR)/$(PRGNAME)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~
+
diff --git a/tools/convpic/bmp.c b/tools/convpic/bmp.c
new file mode 100644
index 0000000..2316b6c
--- /dev/null
+++ b/tools/convpic/bmp.c
@@ -0,0 +1,375 @@
+/**
+ * GraphLCD plugin for the Video Disk Recorder
+ *
+ * bmp.c - bmp logo class
+ *
+ * (C) 2004 Andreas Brachold <vdr04 AT deltab de>
+ * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/image.h>
+
+#include "bmp.h"
+
+
+#pragma pack(1)
+typedef struct BMPH {
+ uint16_t bmpIdentifier;
+ uint32_t bmpFileSize;
+ uint32_t bmpReserved;
+ uint32_t bmpBitmapDataOffset;
+ uint32_t bmpBitmapHeaderSize;
+ uint32_t bmpWidth;
+ uint32_t bmpHeight;
+ uint16_t bmpPlanes;
+ uint16_t bmpBitsPerPixel;
+ uint32_t bmpCompression;
+ uint32_t bmpBitmapDataSize;
+ uint32_t bmpHResolution;
+ uint32_t bmpVResolution;
+ uint32_t bmpColors;
+ uint32_t bmpImportantColors;
+} BMPHEADER; // 54 bytes
+
+typedef struct RGBQ {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ uint8_t rgbReserved;
+} RGBQUAD; // 4 bytes
+#pragma pack()
+
+
+uint8_t bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+uint8_t bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
+uint8_t bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+
+cBMPFile::cBMPFile()
+{
+}
+
+cBMPFile::~cBMPFile()
+{
+}
+
+bool cBMPFile::Load(GLCD::cImage & image, const std::string & fileName)
+{
+ FILE *fIN;
+ BMPHEADER bmpHeader;
+ RGBQUAD *pPalette;
+ char *pByte;
+ char Dummy;
+ long iNumColors;
+ long iSize;
+ uint32_t x, y;
+ uint16_t iRead;
+ uint8_t * bitmap = NULL;
+ bool bInvert = false;
+
+ if (fileName.length() > 0)
+ {
+ fIN = fopen(fileName.c_str(), "rb");
+ if (fIN)
+ {
+ if (fread(&bmpHeader, sizeof(BMPHEADER), 1, fIN)!=1)
+ {
+ fclose(fIN);
+ return false;
+ }
+
+ // check for Windows BMP
+ if (bmpHeader.bmpBitmapHeaderSize != 0x00000028 )
+ {
+ fprintf(stderr, "ERROR: only Windows BMP images are allowed.\n");
+ fclose(fIN);
+ return false;
+ }
+
+ // check for 2 color
+ iNumColors = (1 << bmpHeader.bmpBitsPerPixel);
+ if (iNumColors != 2)
+ {
+ fprintf(stderr, "ERROR: the image has %ld colors, but only images with 2 colors are allowed.\n", iNumColors);
+ fclose(fIN);
+ return false;
+ }
+
+ iSize = bmpHeader.bmpHeight * bmpHeader.bmpWidth;
+
+ pPalette = (RGBQUAD *) malloc( iNumColors*sizeof(RGBQUAD));
+ if (!pPalette)
+ {
+ fprintf(stderr, "ERROR: cannot allocate memory\n");
+ fclose(fIN);
+ return false;
+ }
+
+ if (fread( pPalette, iNumColors*sizeof(RGBQUAD), 1, fIN)!=1)
+ {
+ free(pPalette);
+ fclose(fIN);
+ return false;
+ }
+
+ // check colors
+ if (pPalette->rgbBlue+pPalette->rgbGreen+pPalette->rgbRed <
+ (pPalette+1)->rgbBlue+(pPalette+1)->rgbGreen+(pPalette+1)->rgbRed)
+ {
+ // index 0 represents 'black', index 1 'white'
+ bInvert = !bInvert;
+ }
+ else
+ {
+ // index 0 represents 'white', index 1 'black'
+ }
+
+ if (fseek(fIN, bmpHeader.bmpBitmapDataOffset, SEEK_SET)==EOF)
+ {
+ free(pPalette);
+ fclose(fIN);
+ return false;
+ }
+
+ switch (bmpHeader.bmpCompression)
+ {
+ case 0: // BI_RGB no compression
+ image.Clear();
+ image.SetWidth(bmpHeader.bmpWidth);
+ image.SetHeight(bmpHeader.bmpHeight);
+ image.SetDelay(100);
+ bitmap = new unsigned char[bmpHeader.bmpHeight * ((bmpHeader.bmpWidth + 7) / 8)];
+ if (!bitmap)
+ {
+ fprintf(stderr, "ERROR: cannot allocate memory\n");
+ free(pPalette);
+ fclose(fIN);
+ image.Clear();
+ return false;
+ }
+
+ for (y = bmpHeader.bmpHeight; y > 0; y--)
+ {
+ pByte = (char*)bitmap + (y-1)*((bmpHeader.bmpWidth+7)/8);
+ iRead = 0;
+ for (x = 0; x < bmpHeader.bmpWidth / 8; x++)
+ {
+ if (fread(pByte, sizeof(char), 1, fIN) != 1)
+ {
+ delete[] bitmap;
+ free(pPalette);
+ fclose(fIN);
+ image.Clear();
+ return false;
+ }
+ iRead++;
+ if (bInvert)
+ *pByte = *pByte ^ 0xff;
+ pByte++;
+ }
+
+ if (bmpHeader.bmpWidth % 8)
+ {
+ if (fread(pByte, sizeof(char), 1, fIN) != 1)
+ {
+ delete [] bitmap;
+ free(pPalette);
+ fclose(fIN);
+ image.Clear();
+ return false;
+ }
+ iRead++;
+ if (bInvert)
+ *pByte = *pByte^0xff;
+ *pByte = *pByte & bitmaskl[bmpHeader.bmpWidth%8];
+ pByte++;
+ }
+
+ // Scan line must be 4-byte-alligned
+ while (iRead % 4)
+ {
+ if (fread(&Dummy, sizeof(char), 1, fIN) != 1)
+ {
+ delete [] bitmap;
+ free(pPalette);
+ fclose(fIN);
+ image.Clear();
+ return false;
+ }
+ iRead++;
+ }
+ }
+ image.AddBitmap(new GLCD::cBitmap(bmpHeader.bmpWidth, bmpHeader.bmpHeight, bitmap));
+ break;
+ case 1: // BI_RLE4 RLE 4bit/pixel
+ case 2: // BI_RLE8 RLE 8bit/pixel
+ case 3: // BI_BITFIELDS
+ default:
+ fprintf(stderr, "ERROR: only uncompressed RGB images are allowed.\n");
+
+ free(pPalette);
+ fclose(fIN);
+ return false;
+ }
+ fclose(fIN);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str());
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: no FileName given!\n");
+ }
+ return true;
+}
+
+bool cBMPFile::Save(const GLCD::cBitmap * bitmap, const std::string & fileName)
+{
+ FILE *fOut;
+ BMPHEADER bmpHeader;
+ RGBQUAD bmpColor1, bmpColor2;
+ uint32_t dBDO, dBDSx, dBDS;
+ char *pByte;
+ char Dummy = 0x00;
+ uint32_t x, y;
+ uint16_t iWrote;
+ const uint8_t * bmpdata = bitmap->Data();
+
+ if (bitmap
+ && bitmap->Width() > 0
+ && bitmap->Height() > 0)
+ {
+ memset(&bmpHeader, 0, sizeof(BMPHEADER));
+
+ dBDO = sizeof(BMPHEADER)+2*sizeof(RGBQUAD);
+ dBDSx = ((bitmap->Width() + 7) / 8 + 3) & 0xfffffffc;
+ dBDS = dBDSx * bitmap->Height();
+
+ bmpHeader.bmpIdentifier = 0x4d42; // "BM"
+ bmpHeader.bmpFileSize = dBDO + dBDS;
+ bmpHeader.bmpBitmapDataOffset = dBDO;
+ bmpHeader.bmpBitmapHeaderSize = 0x28;
+ bmpHeader.bmpWidth = bitmap->Width();
+ bmpHeader.bmpHeight = bitmap->Height();
+ bmpHeader.bmpPlanes = 0x01;
+ bmpHeader.bmpBitsPerPixel = 0x01;
+ bmpHeader.bmpCompression = 0x00;
+ bmpHeader.bmpBitmapDataSize = dBDS;
+ bmpHeader.bmpHResolution = 0xb13; // 72dpi
+ bmpHeader.bmpVResolution = 0xb13; // 72dpi
+ bmpHeader.bmpColors = 0x02;
+ bmpHeader.bmpImportantColors = 0x02;
+
+ bmpColor1.rgbBlue = 0x00;
+ bmpColor1.rgbGreen = 0x00;
+ bmpColor1.rgbRed = 0x00;
+ bmpColor1.rgbReserved = 0x00;
+ bmpColor2.rgbBlue = 0xff;
+ bmpColor2.rgbGreen = 0xff;
+ bmpColor2.rgbRed = 0xff;
+ bmpColor2.rgbReserved = 0x00;
+
+
+ fOut = fopen(fileName.c_str(), "wb");
+ if (!fOut)
+ {
+ fprintf(stderr,"Cannot create file: %s\n", fileName.c_str());
+ return false;
+ }
+ fwrite(&bmpHeader, sizeof(BMPHEADER), 1, fOut);
+ fwrite(&bmpColor1, sizeof(RGBQUAD), 1, fOut);
+ fwrite(&bmpColor2, sizeof(RGBQUAD), 1, fOut);
+
+ for (y=bitmap->Height(); y>0; y--)
+ {
+ pByte = (char*)bmpdata + (y-1)*((bitmap->Width()+7)/8);
+ iWrote = 0;
+ for (x=0; x<(uint32_t) bitmap->Width()/8; x++)
+ {
+ *pByte = *pByte^0xff;
+ if (fwrite(pByte, sizeof(char), 1, fOut)!=1)
+ {
+ fclose(fOut);
+ return false;
+ }
+ iWrote++;
+ pByte++;
+ }
+ // Scan line must be 4-byte-alligned
+ while (iWrote%4)
+ {
+ if (fwrite(&Dummy, sizeof(char), 1, fOut)!=1)
+ {
+ fclose(fOut);
+ return 3;
+ }
+ iWrote++;
+ }
+ }
+ fclose(fOut);
+ }
+ return true;
+}
+
+bool cBMPFile::Save(GLCD::cImage & image, const std::string & fileName)
+{
+ const GLCD::cBitmap * bitmap;
+
+ if (image.Count() == 1)
+ {
+ bitmap = image.GetBitmap(0);
+ if (bitmap)
+ {
+ if (!Save(bitmap, fileName))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ uint16_t i;
+ char tmpStr[256];
+
+ for (i = 0; i < image.Count(); i++)
+ {
+ sprintf(tmpStr, "%.248s.%05d", fileName.c_str(), i);
+ bitmap = image.GetBitmap(i);
+ if (bitmap)
+ {
+ if (!Save(bitmap, tmpStr))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
diff --git a/tools/convpic/bmp.h b/tools/convpic/bmp.h
new file mode 100644
index 0000000..8419838
--- /dev/null
+++ b/tools/convpic/bmp.h
@@ -0,0 +1,45 @@
+/**
+ * GraphLCD plugin for the Video Disk Recorder
+ *
+ * bmp.h - bmp logo class
+ *
+ * (C) 2004 Andreas Brachold <vdr04 AT deltab de>
+ * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+
+#ifndef _BMP_H_
+#define _BMP_H_
+
+#include <glcdgraphics/imagefile.h>
+
+class cBMPFile : public GLCD::cImageFile
+{
+private:
+ bool Save(const GLCD::cBitmap * bitmap, const std::string & fileName);
+public:
+ cBMPFile();
+ virtual ~cBMPFile();
+ virtual bool Load(GLCD::cImage & image, const std::string & fileName);
+ virtual bool Save(GLCD::cImage & image, const std::string & fileName);
+};
+
+#endif
diff --git a/tools/convpic/c_bmp2glcd b/tools/convpic/c_bmp2glcd
new file mode 100755
index 0000000..b629ee6
--- /dev/null
+++ b/tools/convpic/c_bmp2glcd
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Converts all BMP images to *.glcd
+
+old=bmp
+new=glcd
+
+for file in ./*."$old"; do
+ convpic -i "$file" -o "`basename \"$file\" \"$old\"`$new"
+done
+
diff --git a/tools/convpic/c_tif2glcd b/tools/convpic/c_tif2glcd
new file mode 100755
index 0000000..d3983b8
--- /dev/null
+++ b/tools/convpic/c_tif2glcd
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Converts all TIFF images to *.glcd
+
+old=tif
+new=glcd
+
+for file in ./*."$old"; do
+ convpic -i "$file" -o "`basename \"$file\" \"$old\"`$new"
+done
+
diff --git a/tools/convpic/convall b/tools/convpic/convall
new file mode 100755
index 0000000..f0f0207
--- /dev/null
+++ b/tools/convpic/convall
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Converts all images in current directory
+
+old=$1
+new=$2
+
+for file in ./*."$old"; do
+ convpic -i "$file" -o "`basename \"$file\" \"$old\"`$new"
+done
+
diff --git a/tools/convpic/convpic.c b/tools/convpic/convpic.c
new file mode 100644
index 0000000..732738c
--- /dev/null
+++ b/tools/convpic/convpic.c
@@ -0,0 +1,279 @@
+/**
+ * convpic.c - a tool to convert images to
+ * own proprietary format of the logos and pictures
+ * for graphlcd plugin
+ *
+ * (C) 2004 Andreas Brachold <vdr04 AT deltab de>
+ * (C) 2001-2003 by Carsten Siebholz <c.siebholz AT t-online.de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/image.h>
+#include <glcdgraphics/imagefile.h>
+#include <glcdgraphics/glcd.h>
+#include <glcdgraphics/pbm.h>
+
+#include "bmp.h"
+#include "tiff.h"
+#include "tuxbox.h"
+
+static const char *prgname = "convpic";
+static const char *VERSION = "0.1.1";
+
+unsigned int delay = 250;
+
+
+enum ePicFormat
+{
+ pfUndefined,
+ pfTIFF,
+ pfBMP,
+ pfGLCD,
+ pfPBM,
+ pfTUXBOX
+};
+
+void usage(void);
+
+ePicFormat getFormat(const char* szFile)
+{
+ static const struct tagformats {const char* szExt; ePicFormat picformat;} formats[] =
+ {
+ {".tiff", pfTIFF },
+ {".tif", pfTIFF },
+ {".bmp", pfBMP },
+ {".glcd", pfGLCD },
+ {".pbm", pfPBM },
+ {".ani", pfTUXBOX}
+ };
+ ePicFormat pf = pfUndefined;
+
+ if (szFile)
+ {
+ for (int i = strlen(szFile) - 1; i >= 0; i--)
+ {
+ if (*(szFile+i) == '.' && strlen(szFile + i + 1))
+ {
+ for (unsigned int n = 0; n < sizeof(formats)/sizeof(*formats); n++)
+ {
+ if (!strcasecmp((szFile+i), formats[n].szExt))
+ {
+ return formats[n].picformat;
+ }
+ }
+ }
+ }
+ }
+ return pf;
+}
+
+GLCD::cImageFile * GetFileTranslator(ePicFormat Format)
+{
+ switch (Format)
+ {
+ case pfGLCD:
+ return new GLCD::cGLCDFile();
+
+ case pfPBM:
+ return new GLCD::cPBMFile();
+
+ case pfBMP:
+ return new cBMPFile();
+
+ case pfTIFF:
+ return new cTIFFFile();
+
+ case pfTUXBOX:
+ return new cTuxBoxFile();
+
+ default:
+ return NULL;
+ }
+
+}
+
+int main(int argc, char *argv[]) {
+ ePicFormat inFormat = pfUndefined;
+ ePicFormat outFormat = pfUndefined;
+ std::string inFile = "";
+ std::string outFile = "";
+ GLCD::cImage image;
+ GLCD::cImage nextImage;
+ GLCD::cImageFile * pInBitmap = NULL;
+ GLCD::cImageFile * pOutBitmap = NULL;
+ bool bError = false;
+ bool bInvert = false;
+ bool bDelay = false;
+
+
+ static struct option long_options[] =
+ {
+ {"invert", no_argument, NULL, 'n'},
+ {"infile", required_argument, NULL, 'i'},
+ {"outfile", required_argument, NULL, 'o'},
+ {"delay", required_argument, NULL, 'd'},
+ { NULL}
+ };
+
+ int c, option_index = 0;
+ while ((c=getopt_long(argc,argv,"ni:o:d:",long_options, &option_index))!=-1) {
+ switch (c) {
+ case 'n':
+ bInvert = true;
+ break;
+
+ case 'i':
+ inFile = optarg;
+ break;
+
+ case 'o':
+ outFile = optarg;
+ break;
+
+ case 'd':
+ delay = atoi(optarg);
+ bDelay = true;
+ if (delay < 10)
+ {
+ fprintf(stderr, "Warning: You have specify a to short delay, minimum are 10 ms\n");
+ delay = 10;
+ }
+ break;
+
+ default:
+ return 1;
+ }
+ }
+
+ if (inFile.length() == 0)
+ {
+ fprintf(stderr, "ERROR: You have to specify the infile (-i filename)\n");
+ bError = true;
+ }
+
+ if (pfUndefined == (inFormat = getFormat(inFile.c_str())))
+ {
+ fprintf(stderr, "ERROR: You have to specify a correct extension for the %s\n", inFile.c_str());
+ bError = true;
+ }
+
+ if (outFile.length() == 0)
+ {
+ fprintf(stderr, "ERROR: You have to specify the outfile (-o filename)\n");
+ bError = true;
+ }
+
+ if (pfUndefined == (outFormat = getFormat(outFile.c_str())))
+ {
+ fprintf(stderr, "ERROR: You have to specify a correct extension for the %s \n", outFile.c_str());
+ bError = true;
+ }
+
+ if (bError)
+ {
+ usage();
+ return 1;
+ }
+
+
+ pInBitmap = GetFileTranslator(inFormat);
+ if (!pInBitmap)
+ return 2;
+
+ pOutBitmap = GetFileTranslator(outFormat);
+ if (!pOutBitmap)
+ return 3;
+
+ // Load Picture
+ fprintf(stdout, "loading %s\n", inFile.c_str());
+ bError = !pInBitmap->Load(image, inFile);
+ if (!bError)
+ {
+ // Load more in files
+ while (optind < argc && !bError)
+ {
+ inFile = argv[optind++];
+ inFormat = getFormat(inFile.c_str());
+ if (inFormat == pfUndefined)
+ {
+ fprintf(stderr, "ERROR: You have to specify a correct extension for the %s\n", inFile.c_str());
+ bError = true;
+ break;
+ }
+ pInBitmap = GetFileTranslator(inFormat);
+ if (!pInBitmap)
+ break;
+
+ fprintf(stdout, "loading %s\n", inFile.c_str());
+ if (pInBitmap->Load(nextImage, inFile))
+ {
+ uint16_t i;
+ for (i = 0; i < nextImage.Count(); i++)
+ {
+ image.AddBitmap(new GLCD::cBitmap(*nextImage.GetBitmap(i)));
+ }
+ }
+ }
+ if (bDelay)
+ image.SetDelay(delay);
+ if (bInvert)
+ {
+ uint16_t i;
+ for (i = 0; i < image.Count(); i++)
+ {
+ image.GetBitmap(i)->Invert();
+ }
+ }
+ fprintf(stdout, "saving %s\n", outFile.c_str());
+ bError = !pOutBitmap->Save(image, outFile);
+ }
+ if (bError) {
+ return 4;
+ }
+
+ fprintf(stdout, "conversion compeleted successfully.\n\n");
+
+ return 0;
+}
+
+void usage(void)
+{
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%s v%s\n", prgname, VERSION);
+ fprintf(stdout, "%s is a tool to convert images to a simple format (*.glcd)\n", prgname);
+ fprintf(stdout, " that is used by the graphlcd plugin for VDR.\n\n");
+ fprintf(stdout, " Usage: %s [-n] -i file[s...] -o outfile \n\n", prgname);
+ fprintf(stdout, " -n --invert inverts the output (default: none)\n");
+ fprintf(stdout, " -i --infile specifies the name of the input file[s]\n");
+ fprintf(stdout, " -o --outfile specifies the name of the output file\n");
+ fprintf(stdout, " -d --delay specifies the delay between multiple images [Default: %d ms] \n",delay);
+ fprintf(stdout, "\n" );
+ fprintf(stdout, " example: %s -i vdr-logo.bmp -o vdr-logo.glcd \n", prgname );
+}
diff --git a/tools/convpic/formats.txt b/tools/convpic/formats.txt
new file mode 100644
index 0000000..578a211
--- /dev/null
+++ b/tools/convpic/formats.txt
@@ -0,0 +1,32 @@
+Dateiformat von "Graphlcd-Logo"
+
+
+Einzelbild für LCD
+=================================
+
+HEADER
+Position Typ Name Bedeutung
+0x0000 char[4] magic - "GLCD"
+0x0004 word width - Breite der Bilder (LE)
+0x0006 word height - Höhe der Bilder (LE)
+0x0008 char[] data - Einzel-Bild
+
+DATEN
+char[height][width/8], pro Byte 8 nebeneinander liegende Pixel
+
+Animation für LCD
+=================================
+
+HEADER
+Position Typ Name Bedeutung
+0x0000 char[4] magic - "GLCA"
+0x0004 word width - Breite der Bilder (LE)
+0x0006 word height - Höhe der Bilder (LE)
+0x0008 word count - Anzahl der Bilder (LE)
+0x000a long delay - Wartezeit zwischen den Bildern (in ms; LE)
+0x0010 char[] data - Einzel-Bilder
+
+DATEN
+char[height][width/8], pro Byte 8 nebeneinander liegende Pixel (1 = Pixel gesetzt)
+
+LE = Little Endian byte order = wie bei intel ;)
diff --git a/tools/convpic/tiff.c b/tools/convpic/tiff.c
new file mode 100644
index 0000000..4b8bf0e
--- /dev/null
+++ b/tools/convpic/tiff.c
@@ -0,0 +1,201 @@
+/**
+ * GraphLCD plugin for the Video Disk Recorder
+ *
+ * tiff.c - tiff logo class
+ *
+ * (c) 2004 Andreas Brachold <vdr04 AT deltab de>
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/image.h>
+
+#include "tiff.h"
+
+
+#pragma pack(1)
+typedef struct TIFFT{
+ unsigned short tag;
+ unsigned short type;
+ unsigned long length;
+ /* 1 = BYTE. 8-bit unsigned integer. */
+ /* 2 = ASCII. 8-bit bytes that store ASCII codes; the last byte must be null. */
+ /* 3 = SHORT. A 16-bit (2-byte) unsigned integer. */
+ /* 4 = LONG. A 32-bit (4-byte) unsigned integer. */
+ /* 5 = RATIONAL. Two LONGs: the first represents the numerator of a fraction, the second the denominator. */
+ unsigned long off_val;
+} TIFFTAG;
+#pragma pack()
+
+#define GETANDCHECK { t=fgetc(fIN);if(t==EOF) {fclose(fIN);return false;};}
+
+cTIFFFile::cTIFFFile()
+{
+}
+
+cTIFFFile::~cTIFFFile()
+{
+}
+
+bool cTIFFFile::Load(GLCD::cImage & image, const std::string & fileName)
+{
+ FILE *fIN;
+ TIFFTAG tifftag;
+ unsigned int tiff_header, tiff_anztags, tiff_data;
+ unsigned char cl,ch,y,i;
+ unsigned char height, width, strip, invert;
+ unsigned char fLittleEndian=0;
+ int j;
+ int t;
+ unsigned char *bitmap = NULL;
+ bool bInvert = false;
+
+ if (fileName.length() > 0)
+ {
+ fIN = fopen(fileName.c_str(), "rb");
+ if (fIN)
+ {
+ // isyslog("graphlcd plugin: try to load logo %s.", szFileName);
+ if (fseek(fIN, 0, SEEK_SET)==EOF)
+ {
+ fclose(fIN);
+ return false;
+ }
+ GETANDCHECK; cl=(unsigned char)t;
+ GETANDCHECK; ch=(unsigned char)t;
+ if ((cl==0x49) && (ch==0x49))
+ {
+ fLittleEndian=1;
+ }
+
+ if (fseek(fIN, 4, SEEK_SET)==EOF)
+ {
+ fclose(fIN);
+ return false;
+ }
+ GETANDCHECK; cl=(unsigned char)t;
+ GETANDCHECK; ch=(unsigned char)t;
+ tiff_header = cl+256*ch;
+ //printf("tiff_header:%d %x\n", tiff_header, tiff_header);
+
+ if (fseek(fIN, tiff_header, SEEK_SET)==EOF)
+ {
+ fclose(fIN);
+ return false;
+ }
+
+ GETANDCHECK; cl=(unsigned char)t;
+ GETANDCHECK; ch=(unsigned char)t;
+ tiff_anztags = cl+256*ch;
+ //printf("tiff_anztags:%d %x\n", tiff_anztags, tiff_anztags);
+
+ height=0;
+ width=0;
+ strip=0;
+ invert=0;
+ for (i=0; (i<tiff_anztags)&&(!height||!width||!strip||!invert); i++)
+ {
+ if (fread(&tifftag, sizeof(tifftag), 1, fIN)!=1)
+ {
+ fclose(fIN);
+ return false;
+ }
+ if (tifftag.tag==0x0100) width=tifftag.off_val;
+ if (tifftag.tag==0x0101) height=tifftag.off_val;
+ if (tifftag.tag==0x0111) strip=tifftag.off_val;
+ if (tifftag.tag==0x0106) invert=tifftag.off_val+1;
+ //printf("tag%d: %d %d %ld %ld\n", i,tifftag.tag, tifftag.type, tifftag.length, tifftag.off_val );
+ }
+
+ if (fseek(fIN,strip, SEEK_SET)==EOF)
+ {
+ fclose(fIN);
+ return false;
+ }
+ GETANDCHECK; cl=(unsigned char)t;
+ GETANDCHECK; ch=(unsigned char)t;
+ tiff_data = cl+256*ch;
+ //printf("tiff_data:%d %x\n", tiff_data, tiff_data);
+
+ if (fseek(fIN, tiff_data, SEEK_SET)==EOF)
+ {
+ fclose(fIN);
+ return false;
+ }
+
+
+ image.Clear();
+ image.SetWidth(width);
+ image.SetHeight(height);
+ image.SetDelay(100);
+ bitmap = new unsigned char[height * ((width + 7) / 8)];
+ if (bitmap)
+ {
+ if (fread(bitmap, height*((width+7)/8), 1, fIN)!=1)
+ {
+ delete [] bitmap;
+ fclose(fIN);
+ image.Clear();
+ return false;
+ }
+
+ if (invert-1==1) bInvert = !bInvert; // 'Black is zero'
+ if (bInvert)
+ {
+ for (j=0; j < height * ((width+7)/8); j++)
+ {
+ (*(bitmap+j)) = (*(bitmap+j))^0xff;
+ }
+ }
+
+ // cut the rest of the line
+ if (width%8)
+ {
+ for (y=1; y<=height; y++) {
+ j=y*((width+7)/8)-1;
+ (*(bitmap+j)) = ((*(bitmap+j))>>(8-width%8))<<(8-width%8);
+ }
+ }
+ image.AddBitmap(new GLCD::cBitmap(width, height, bitmap));
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: cannot allocate memory\n");
+ }
+ fclose(fIN);
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str());
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: no szFileName given!\n");
+ }
+ return true;
+}
diff --git a/tools/convpic/tiff.h b/tools/convpic/tiff.h
new file mode 100644
index 0000000..f6e66c1
--- /dev/null
+++ b/tools/convpic/tiff.h
@@ -0,0 +1,42 @@
+/**
+ * GraphLCD plugin for the Video Disk Recorder
+ *
+ * tiff.h - tiff logo class
+ *
+ * (c) 2004 Andreas Brachold <vdr04 AT deltab de>
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+
+#ifndef _TIFF_H_
+#define _TIFF_H_
+
+#include <glcdgraphics/imagefile.h>
+
+class cTIFFFile : public GLCD::cImageFile
+{
+public:
+ cTIFFFile();
+ virtual ~cTIFFFile();
+ virtual bool Load(GLCD::cImage & image, const std::string & fileName);
+};
+
+#endif
diff --git a/tools/convpic/tuxbox.c b/tools/convpic/tuxbox.c
new file mode 100644
index 0000000..55d6e1d
--- /dev/null
+++ b/tools/convpic/tuxbox.c
@@ -0,0 +1,280 @@
+/**
+ * GraphLCD plugin for the Video Disk Recorder
+ *
+ * tuxbox.c - tuxbox logo class
+ *
+ * (c) 2004 Andreas Brachold <vdr04 AT deltab de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/image.h>
+
+#include "tuxbox.h"
+
+#pragma pack(1)
+struct ani_header {
+ unsigned char magic[4]; // = "LCDA"
+ unsigned short format; // Format
+ unsigned short width; // Breite
+ unsigned short height; // Höhe
+ unsigned short count; // Anzahl Einzelbilder
+ unsigned long delay; // µs zwischen Einzelbildern
+};
+#pragma pack()
+
+cTuxBoxFile::cTuxBoxFile()
+{
+}
+
+cTuxBoxFile::~cTuxBoxFile()
+{
+}
+
+bool cTuxBoxFile::Load(GLCD::cImage & image, const std::string & fileName)
+{
+ bool ret = false;
+ FILE * fIN;
+ long fileLen;
+ struct ani_header header;
+ bool bInvert = false;
+
+ fIN = fopen(fileName.c_str(), "rb");
+ if (fIN)
+ {
+ // get len of file
+ if (fseek(fIN, 0, SEEK_END))
+ {
+ fclose(fIN);
+ return false;
+ }
+ fileLen = ftell(fIN);
+
+ // rewind and get Header
+ if (fseek(fIN, 0, SEEK_SET))
+ {
+ fclose(fIN);
+ return false;
+ }
+
+ // Read header
+ if (fread(&header, sizeof(header), 1, fIN) != 1)
+ {
+ fclose(fIN);
+ return false;
+ }
+
+ image.Clear();
+ image.SetWidth(ntohs(header.width));
+ image.SetHeight(ntohs(header.height));
+ image.SetDelay(ntohl(header.delay) / 1000);
+
+ // check Header
+ if (strncmp((const char*)header.magic, "LCDA", sizeof(header.magic)) ||
+ !image.Width() || !image.Height() || ntohs(header.format) != 0)
+ {
+ fprintf(stderr, "ERROR: load %s failed, wrong header.\n", fileName.c_str());
+ fclose(fIN);
+ return false;
+ }
+
+ //fprintf(stderr,"%d %dx%d (%d %d) %d\n",ntohs(header.count),image.Width(),image.Height(),fileLen, ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header)),lhdr.delay);
+
+ // check file length
+ if (!ntohs(header.count)
+ || (fileLen != (long) ( (ntohs(header.count) * (image.Width() * ((image.Height() + 7) / 8))) + sizeof(header))))
+ {
+ fprintf(stderr, "ERROR: load %s failed, wrong size.\n", fileName.c_str());
+ fclose(fIN);
+ return false;
+ }
+ // Set minimal limit for next image
+ if (image.Delay() < 10)
+ image.SetDelay(10);
+ for (unsigned int n=0;n<ntohs(header.count);++n)
+ {
+ ret = false;
+ unsigned int nBmpSize = image.Height() * ((image.Width() + 7) / 8);
+ unsigned char *bitmap = new unsigned char[nBmpSize];
+ if (!bitmap)
+ {
+ fprintf(stderr, "ERROR: malloc failed.");
+ break;
+ }
+ unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8);
+ unsigned char *pAni = new unsigned char[nAniSize];
+ if (!pAni)
+ {
+ delete[] bitmap;
+ fprintf(stderr, "ERROR: malloc failed.");
+ break;
+ }
+
+ if (1 != fread(pAni, nAniSize, 1, fIN))
+ {
+ fprintf(stderr,"ERROR: Cannot read filedata: %s\n", fileName.c_str());
+ delete[] bitmap;
+ delete[] pAni;
+ break;
+ }
+
+ vert2horz(pAni,bitmap, image.Width(), image.Height());
+ delete[] pAni;
+
+ if (bInvert)
+ for (unsigned int i=0;i<nBmpSize;++i)
+ bitmap[i] ^= 0xFF;
+
+ image.AddBitmap(new GLCD::cBitmap(image.Width(), image.Height(), bitmap));
+ ret = true;
+ }
+ fclose(fIN);
+ if (!ret)
+ image.Clear();
+ }
+ return ret;
+}
+
+
+bool cTuxBoxFile::Save(GLCD::cImage & image, const std::string & fileName)
+{
+ FILE * fOut;
+ struct ani_header header;
+ bool bRet = false;
+
+ if (image.Count() > 0
+ && image.Width()
+ && image.Height())
+ {
+ memcpy(header.magic, "LCDA", 4);
+ header.format = htons(0);
+ header.width = htons(image.Width());
+ header.height = htons(image.Height());
+ header.count = htons(image.Count());
+ header.delay = htonl(image.Delay() * 1000);
+
+
+ if (image.Width() != 120 || image.Height() != 64)
+ {
+ fprintf(stderr,"WARNING: Maybe wrong image dimension (for all I know is 120x64 wanted) %s\n", fileName.c_str());
+ }
+
+ fOut = fopen(fileName.c_str(), "wb");
+ if (!fOut) {
+ fprintf(stderr,"ERROR: Cannot create file: %s\n", fileName.c_str());
+ return false;
+ }
+
+ if (1 != fwrite(&header, sizeof(header), 1, fOut))
+ {
+ fprintf(stderr,"ERROR: Cannot write fileheader: %s\n", fileName.c_str());
+ fclose(fOut);
+ return false;
+ }
+
+ for (unsigned int n = 0; n < image.Count(); n++)
+ {
+ bRet = false;
+ unsigned int nAniSize = image.Width() * ((image.Height() + 7) / 8);
+ unsigned char *pAni = new unsigned char[nAniSize];
+ if (!pAni)
+ {
+ fprintf(stderr, "ERROR: malloc failed.");
+ break;
+ }
+ horz2vert(image.GetBitmap(n)->Data(), pAni, image.Width(), image.Height());
+
+ if (1 != fwrite(pAni, nAniSize, 1, fOut))
+ {
+ delete [] pAni;
+ fprintf(stderr,"ERROR: Cannot write filedata: %s\n", fileName.c_str());
+ break;
+ }
+ delete [] pAni;
+ bRet = true;
+ }
+
+ fclose(fOut);
+ }
+ return bRet;
+}
+
+/** Translate memory alignment from vertical to horizontal
+rotate from {Byte} to {Byte}
+{o}[o][o][o][o][o][o][o] => { oooooooo }
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]
+{o}[o][o][o][o][o][o][o] => [ oooooooo ]*/
+void cTuxBoxFile::vert2horz(const unsigned char* source, unsigned char* dest, int width, int height) {
+ int x, y, off;
+ memset(dest,0,height*((width+7)/8));
+
+ for (y=0; y<height; ++y)
+ {
+ for (x=0; x<width; ++x)
+ {
+ off = x + ((y/8) * width);
+ if (source[off] & (0x1 << (y % 8)))
+ {
+ off = (x / 8) + (y * ((width+7)/8));
+ dest[off] |= (unsigned char)(0x80 >> (x % 8));
+ }
+ }
+ }
+}
+
+/** Translate memory alignment from horizontal to vertical (rotate byte)
+rotate from {Byte} to {Byte}
+{ oooooooo } => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]
+[ oooooooo ] => {o}[o][o][o][o][o][o][o]*/
+void cTuxBoxFile::horz2vert(const unsigned char* source, unsigned char* dest, int width, int height) {
+ int x, y, off;
+ memset(dest,0,width*((height+7)/8));
+
+ for (y=0; y<height; ++y)
+ {
+ for (x=0; x<width; ++x)
+ {
+ off = (x / 8) + ((y) * ((width+7)/8));
+ if (source[off] & (0x80 >> (x % 8)))
+ {
+ off = x + ((y/8) * width);
+ dest[off] |= (unsigned char)(0x1 << (y % 8));
+ }
+ }
+ }
+}
diff --git a/tools/convpic/tuxbox.h b/tools/convpic/tuxbox.h
new file mode 100644
index 0000000..1214fb5
--- /dev/null
+++ b/tools/convpic/tuxbox.h
@@ -0,0 +1,44 @@
+/**
+ * GraphLCD plugin for the Video Disk Recorder
+ *
+ * tuxbox.h - tuxbox logo class
+ *
+ * (c) 2004 Andreas Brachold <vdr04 AT deltab de>
+ **/
+
+/***************************************************************************
+ * *
+ * 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 *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; *
+ * if not, write to the Free Software Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ * *
+ ***************************************************************************/
+#ifndef _TUXBOX_H_
+#define _TUXBOX_H_
+
+#include <glcdgraphics/imagefile.h>
+
+class cTuxBoxFile : public GLCD::cImageFile
+{
+private:
+ void vert2horz(const unsigned char* source, unsigned char* dest, int width, int height);
+ void horz2vert(const unsigned char* source, unsigned char* dest, int width, int height);
+public:
+ cTuxBoxFile();
+ virtual ~cTuxBoxFile();
+ virtual bool Load(GLCD::cImage & image, const std::string & fileName);
+ virtual bool Save(GLCD::cImage & image, const std::string & fileName);
+};
+
+#endif
diff --git a/tools/crtfont/Makefile b/tools/crtfont/Makefile
new file mode 100644
index 0000000..9151c2f
--- /dev/null
+++ b/tools/crtfont/Makefile
@@ -0,0 +1,45 @@
+#
+# Makefile for the GraphLCD tool crtfont
+#
+
+-include ../../Make.config
+
+PRGNAME = crtfont
+
+OBJS = crtfont.o
+
+INCLUDES += -I../../
+LIBDIRS += -L../../glcdgraphics/
+
+all: $(PRGNAME)
+.PHONY: all
+
+# Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+# The main program:
+
+$(PRGNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBDIRS) -lglcdgraphics -lstdc++ -o $(PRGNAME)
+
+install: $(PRGNAME)
+ install -d $(BINDIR)
+ install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR)
+
+uninstall:
+ rm -f $(BINDIR)/$(PRGNAME)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~
+
diff --git a/tools/crtfont/crtfont.c b/tools/crtfont/crtfont.c
new file mode 100644
index 0000000..97e57fe
--- /dev/null
+++ b/tools/crtfont/crtfont.c
@@ -0,0 +1,305 @@
+/*
+ * GraphLCD tool crtfont
+ *
+ * crtfont.c - a tool to create *.fnt files for use with the GraphLCD
+ * graphics library
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/font.h>
+
+static const char *prgname = "crtfont";
+static const char *version = "0.1.6";
+
+const int kMaxLineLength = 1024;
+
+enum ePicFormat
+{
+ undefined,
+ PBM
+};
+
+
+void usage(void);
+
+char * trimleft(char * str)
+{
+ char * s = str;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ strcpy(str, s);
+ return str;
+}
+
+char * trimright(char * str)
+{
+ char * s = str + strlen(str) - 1;
+ while (s >= str && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
+ *s-- = 0;
+ return str;
+}
+
+char * trim(char * str)
+{
+ return trimleft(trimright(str));
+}
+
+
+int main(int argc, char *argv[])
+{
+ ePicFormat picFormat = undefined;
+ GLCD::cFont font;
+ char * picName = NULL;
+ char * descName = NULL;
+ char * fontName = NULL;
+ FILE * descFile;
+ bool error = false;
+ GLCD::cBitmap * bitmap = NULL;
+ GLCD::cBitmap * tmpBitmap = NULL;
+ GLCD::cBitmap * charBitmap = NULL;
+ char line[kMaxLineLength];
+ int l = 0;
+ char * token;
+ int startOffset, endOffset;
+ int spaceWidth;
+ int version;
+ char * ptr;
+
+ static struct option long_options[] =
+ {
+ { "format", required_argument, NULL, 'f'},
+ { "bmpfile", required_argument, NULL, 'b'},
+ { "descfile", required_argument, NULL, 'd'},
+ { "outfile", required_argument, NULL, 'o'},
+ { NULL}
+ };
+
+ int c, option_index = 0;
+ while ((c = getopt_long(argc, argv, "f:b:d:o:", long_options, &option_index)) != -1)
+ {
+ switch (c)
+ {
+ case 'f':
+ if (strcasecmp(optarg, "PBM") == 0)
+ picFormat = PBM;
+ break;
+
+ case 'b':
+ picName = strdup(optarg);
+ break;
+
+ case 'd':
+ descName = strdup(optarg);
+ break;
+
+ case 'o':
+ fontName = strdup(optarg);
+ break;
+
+ default:
+ return 1;
+ }
+ }
+
+ if (picFormat == undefined)
+ {
+ fprintf(stderr, "ERROR: You have to specify the format (-f <format>)\n");
+ error = true;
+ }
+ if (!picName)
+ {
+ fprintf(stderr, "ERROR: You have to specify the bmpfile (-b bmpfile)\n");
+ error = true;
+ }
+ if (!descName)
+ {
+ fprintf(stderr, "ERROR: You have to specify the descfile (-d descfile)\n");
+ error = true;
+ }
+ if (!fontName)
+ {
+ fprintf(stderr, "ERROR: You have to specify the outfile (-o outfile)\n");
+ error = true;
+ }
+
+ if (error)
+ {
+ usage();
+ return 1;
+ }
+
+ descFile = fopen(descName,"r");
+ if (!descFile)
+ {
+ fprintf(stderr, "Cannot open file: %s\n",descName);
+ return 2;
+ }
+
+ // Load Picture
+ switch (picFormat)
+ {
+ case PBM:
+ bitmap = new GLCD::cBitmap(0, 0);
+ bitmap->LoadPBM(picName);
+ if (!bitmap)
+ {
+ fprintf(stderr, "Cannot open file: %s\n",picName);
+ return 2;
+ }
+ break;
+
+ default:
+ return 2;
+ }
+
+ if (!bitmap)
+ return 3;
+
+ spaceWidth = 0;
+
+ version = 0;
+ fgets(line, sizeof(line), descFile);
+ trim(line);
+ if (strstr(line, "version") != NULL)
+ {
+ ptr = strstr(line, ":");
+ version = atoi(ptr + 1);
+ }
+ if (version != 1)
+ {
+ fprintf(stderr, "Wrong description file format version (found %d, expected 1)!\n", version);
+ return 2;
+ }
+ while (!feof(descFile))
+ {
+ fgets(line, sizeof(line), descFile);
+ trim(line);
+ if (strstr(line, "fontheight") != NULL)
+ {
+ ptr = strstr(line, ":");
+ font.SetTotalHeight(atoi(ptr + 1));
+ }
+ else if (strstr(line, "fontascent") != NULL)
+ {
+ ptr = strstr(line, ":");
+ font.SetTotalAscent(atoi(ptr + 1));
+ }
+ else if (strstr(line, "lineheight") != NULL)
+ {
+ ptr = strstr(line, ":");
+ font.SetLineHeight(atoi(ptr + 1));
+ }
+ else if (strstr(line, "spacebetween") != NULL)
+ {
+ ptr = strstr(line, ":");
+ font.SetSpaceBetween(atoi(ptr + 1));
+ }
+ else if (strstr(line, "spacewidth") != NULL)
+ {
+ ptr = strstr(line, ":");
+ spaceWidth = atoi(ptr + 1);
+ }
+ else
+ {
+ token = strtok(line, " ");
+ if (token)
+ {
+ startOffset = atoi(token);
+
+ // get character
+ token = strtok(NULL, " ");
+ while (token)
+ {
+ uint16_t character;
+ if (strlen(token) == 1)
+ character = (uint8_t) token[0];
+ else
+ character = atoi(token);
+
+ // get EndOffset
+ token = strtok(NULL, " ");
+ endOffset = atoi(token);
+ tmpBitmap = bitmap->SubBitmap(startOffset, l * font.TotalHeight(), endOffset - 1, (l + 1) * font.TotalHeight() - 1);
+ if (spaceWidth > 0)
+ {
+ // calculate width of this character
+ int x;
+ int y;
+ int left = 255;
+ int right = 0;
+ for (y = 0; y < tmpBitmap->Height(); y++)
+ {
+ for (x = 0; x < tmpBitmap->Width(); x++)
+ {
+ if (tmpBitmap->GetPixel(x, y))
+ break;
+ }
+ if (x < tmpBitmap->Width() && x < left)
+ left = x;
+ for (x = tmpBitmap->Width() - 1; x >= 0; x--)
+ {
+ if (tmpBitmap->GetPixel(x, y))
+ break;
+ }
+ if (x >= 0 && x > right)
+ right = x;
+ }
+ if (left > right)
+ {
+ left = 0;
+ right = spaceWidth - 1;
+ }
+ charBitmap = tmpBitmap->SubBitmap(left, 0, right, font.TotalHeight() - 1);
+ font.SetCharacter(character, charBitmap);
+ delete tmpBitmap;
+ }
+ else
+ {
+ font.SetCharacter(character, tmpBitmap);
+ }
+ startOffset = endOffset;
+
+ // get next character
+ token = strtok(NULL, " ");
+ }
+ }
+ l++;
+ }
+ }
+ fclose(descFile);
+ delete bitmap;
+
+ if (font.SaveFNT(fontName))
+ fprintf(stdout,"Font '%s' created successfully\n", fontName);
+
+ return 0;
+}
+
+void usage(void)
+{
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%s v%s\n", prgname, version);
+ fprintf(stdout, "%s is a tool to create *.fnt files that are used by the\n", prgname);
+ fprintf(stdout, " graphlcd plugin for VDR.\n\n");
+ fprintf(stdout, " Usage: %s -f <format> -b bmpfile -d descfile -o outfile\n\n", prgname);
+ fprintf(stdout, " -f --format specifies the format of the bitmap. Possible values are:\n");
+ fprintf(stdout, " PBM : file is an binary PBM file\n" );
+ fprintf(stdout, " -b --bmpfile specifies the name of the bitmap file (*.pbm)\n");
+ fprintf(stdout, " -d --descfile specifies the name of the description file (*.desc)\n");
+ fprintf(stdout, " -o --outfile specifies the name of the output file (*.fnt)\n");
+ fprintf(stdout, "\n" );
+ fprintf(stdout, " example: %s -f PBM -b f12.pbm -d f12.desc -o f12.fnt\n", prgname);
+}
diff --git a/tools/genfont/Makefile b/tools/genfont/Makefile
new file mode 100644
index 0000000..584e433
--- /dev/null
+++ b/tools/genfont/Makefile
@@ -0,0 +1,48 @@
+#
+# Makefile for the GraphLCD tool crtfont
+#
+
+-include ../../Make.config
+
+PRGNAME = genfont
+
+OBJS = genfont.o
+
+INCLUDES += -I../../
+INCLUDES += `freetype-config --cflags`
+
+LIBDIRS += -L../../glcdgraphics/
+LIBS += `freetype-config --libs`
+
+all: $(PRGNAME)
+.PHONY: all
+
+# Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+# The main program:
+
+$(PRGNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBDIRS) $(LIBS) -lglcdgraphics -lstdc++ -o $(PRGNAME)
+
+install: $(PRGNAME)
+ install -d $(BINDIR)
+ install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR)
+
+uninstall:
+ rm -f $(BINDIR)/$(PRGNAME)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~
+
diff --git a/tools/genfont/genfont.c b/tools/genfont/genfont.c
new file mode 100644
index 0000000..7553e4c
--- /dev/null
+++ b/tools/genfont/genfont.c
@@ -0,0 +1,167 @@
+/*
+ * GraphLCD tool genfont
+ *
+ * genfont.c - a tool to create *.fnt files for use with the GraphLCD
+ * graphics library
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/font.h>
+
+static const char *prgname = "genfont";
+static const char *version = "0.0.2";
+
+void usage(void)
+{
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%s v%s\n", prgname, version);
+ fprintf(stdout, "%s is a tool to create *.fnt files that are used by the\n", prgname);
+ fprintf(stdout, " graphlcd plugin for VDR.\n\n");
+ fprintf(stdout, " Usage: %s -f <format> -i infile -o outfile -s size\n\n", prgname);
+ fprintf(stdout, " -f --format specifies the format of the output files:\n");
+ fprintf(stdout, " 0 - fnt (default)\n");
+ fprintf(stdout, " 1 - pbm & desc\n");
+ fprintf(stdout, " -i --input specifies the name of the input font file (*.ttf)\n");
+ fprintf(stdout, " -o --output specifies the base name of the output files\n");
+ fprintf(stdout, " -s --size font size of the generated font file\n");
+ fprintf(stdout, "\n" );
+ fprintf(stdout, " example: %s -i verdana.ttf -o verdana20 -s 20\n", prgname);
+ fprintf(stdout, " %s -f 1 -i verdana.ttf -o verdana20 -s 20\n", prgname);
+}
+
+
+int main(int argc, char *argv[])
+{
+ static struct option long_options[] =
+ {
+ { "format", required_argument, NULL, 'f'},
+ { "input", required_argument, NULL, 'i'},
+ { "output", required_argument, NULL, 'o'},
+ { "size", required_argument, NULL, 's'},
+ { NULL}
+ };
+
+ int c;
+ int option_index = 0;
+ int format = 0;
+ std::string inputFontFile = "";
+ std::string outputName = "";
+ int size = 30;
+
+ while ((c = getopt_long(argc, argv, "f:i:o:s:", long_options, &option_index)) != -1)
+ {
+ switch (c)
+ {
+ case 'f':
+ format = atoi(optarg);
+ break;
+
+ case 'i':
+ inputFontFile = optarg;
+ break;
+
+ case 'o':
+ outputName = optarg;
+ break;
+
+ case 's':
+ size = atoi(optarg);
+ break;
+
+ default:
+ usage();
+ break;
+ }
+ }
+ if (format > 1)
+ {
+ usage();
+ return 1;
+ }
+ if (inputFontFile == "")
+ {
+ usage();
+ return 1;
+ }
+ if (outputName == "")
+ {
+ outputName = inputFontFile;
+ }
+
+ GLCD::cFont font;
+ if (!font.LoadFT2(inputFontFile, "iso-8859-1", size, false))
+ {
+ return 1;
+ }
+
+ GLCD::cBitmap * bitmap = NULL;
+ std::string fileName;
+ FILE * descFile = NULL;
+ int posX = 0;
+ int posY = 0;
+
+ if (format == 0)
+ {
+ fileName = outputName + ".fnt";
+ if (!font.SaveFNT(fileName))
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ fileName = outputName + ".desc";
+ descFile = fopen(fileName.c_str(), "wb");
+ if (!descFile)
+ {
+ fprintf(stderr, "Cannot open file: %s\n", fileName.c_str());
+ return 1;
+ }
+ bitmap = new GLCD::cBitmap(32 * font.TotalWidth(), 8 * font.TotalHeight());
+ bitmap->Clear();
+ fprintf(descFile, "version:1\n");
+ fprintf(descFile, "fontheight:%d\n", font.TotalHeight());
+ fprintf(descFile, "fontascent:%d\n", font.TotalAscent());
+ fprintf(descFile, "lineheight:%d\n", font.LineHeight());
+ fprintf(descFile, "spacebetween:%d\n", 0);
+ fprintf(descFile, "spacewidth:%d\n", 0);
+
+ for (unsigned int i = 0; i < 256; i++)
+ {
+ const GLCD::cBitmap * charBitmap = font.GetCharacter((char) i);
+ if (charBitmap == NULL)
+ continue;
+
+ bitmap->DrawBitmap(posX, posY, *charBitmap, GLCD::clrBlack);
+ fprintf(descFile, "%d %d ", posX, i);
+ posX += charBitmap->Width();
+ if ((i % 32) == 31)
+ {
+ fprintf(descFile, "%d\n", posX);
+ posY += font.TotalHeight();
+ posX = 0;
+ }
+ }
+
+ if (posX > 0) // write last end marker
+ fprintf(descFile, "%d\n", posX);
+ fileName = outputName + ".pbm";
+ bitmap->SavePBM(fileName);
+ delete bitmap;
+ fclose(descFile);
+ }
+
+ fprintf(stdout, "Font successfully generated.\n");
+
+ return 0;
+}
diff --git a/tools/lcdtestpattern/Makefile b/tools/lcdtestpattern/Makefile
new file mode 100644
index 0000000..5aa1aba
--- /dev/null
+++ b/tools/lcdtestpattern/Makefile
@@ -0,0 +1,46 @@
+#
+# Makefile for the GraphLCD tool showpic
+#
+
+-include ../../Make.config
+
+PRGNAME = lcdtestpattern
+
+OBJS = lcdtestpattern.o
+
+INCLUDES += -I../../
+LIBDIRS += -L../../glcdgraphics/ -L../../glcddrivers/
+
+
+all: $(PRGNAME)
+.PHONY: all
+
+# Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+# The main program:
+
+$(PRGNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBS) $(LIBDIRS) -lglcdgraphics -lglcddrivers -lstdc++ -o $(PRGNAME)
+
+install: $(PRGNAME)
+ install -d $(BINDIR)
+ install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR)
+
+uninstall:
+ rm -f $(BINDIR)/$(PRGNAME)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~
+
diff --git a/tools/lcdtestpattern/lcdtestpattern.c b/tools/lcdtestpattern/lcdtestpattern.c
new file mode 100644
index 0000000..6e9e067
--- /dev/null
+++ b/tools/lcdtestpattern/lcdtestpattern.c
@@ -0,0 +1,260 @@
+/*
+ * GraphLCD tool lcdtestpattern
+ *
+ * lcdtestpattern.c - a tool to display some testpattern on an GLCD
+ *
+ * based on showpic.c of graphlcd-base
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2007 Alexander Rieger (Alexander.Rieger AT inka.de)
+ */
+
+//-----------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/glcd.h>
+#include <glcdgraphics/image.h>
+#include <glcddrivers/config.h>
+#include <glcddrivers/common.h>
+#include <glcddrivers/driver.h>
+#include <glcddrivers/drivers.h>
+
+//-----------------------------------------------------------------------------
+static const char *prgname = "lcdtestpattern";
+static const char *version = "0.1.0";
+
+static const int kDefaultSleepMs = 0;
+static const char * kDefaultConfigFile = "/etc/graphlcd.conf";
+
+static volatile bool stopProgramm = false;
+
+//-----------------------------------------------------------------------------
+static void sighandler(int signal)
+{
+ switch (signal)
+ {
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTERM:
+ stopProgramm = true;
+ } // switch
+} // sighandler()
+
+//-----------------------------------------------------------------------------
+void usage()
+{
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%s v%s\n", prgname, version);
+ fprintf(stdout, "%s is a tool to show test patterns on a LCD.\n", prgname);
+ fprintf(stdout, "\n");
+ fprintf(stdout, " Usage: %s [-c CONFIGFILE] [-d DISPLAY] [-s SLEEP] [-uie]\n\n", prgname);
+ fprintf(stdout, " -c --config specifies the location of the config file\n");
+ fprintf(stdout, " (default: /etc/graphlcd.conf)\n");
+ fprintf(stdout, " -d --display specifies the output display (default is the first one)\n");
+ fprintf(stdout, " -u --upsidedown rotates the output by 180 degrees (default: no)\n");
+ fprintf(stdout, " -i --invert inverts the output (default: no)\n");
+ fprintf(stdout, " -e --endless show all images in endless loop (default: no)\n");
+ fprintf(stdout, " -s --sleep set sleeptime between two patterns [ms] (default: %d ms)\n", kDefaultSleepMs);
+ fprintf(stdout, " -b --brightness set brightness for display if driver support it [%%]\n");
+ fprintf(stdout, " (default: config file value)\n");
+ fprintf(stdout, "\n" );
+ fprintf(stdout, " examples: %s -c /etc/graphlcd.conf\n", prgname);
+ fprintf(stdout, " %s -c /etc/graphlcd.conf -d LCD_T6963 -u -i\n", prgname);
+ fprintf(stdout, "\n" );
+} // usage()
+
+//-----------------------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+ static struct option long_options[] =
+ {
+ {"config", required_argument, NULL, 'c'},
+ {"display", required_argument, NULL, 'd'},
+ {"sleep", required_argument, NULL, 's'},
+ {"endless", no_argument, NULL, 'e'},
+ {"upsidedown", no_argument, NULL, 'u'},
+ {"invert", no_argument, NULL, 'i'},
+ {"brightness", required_argument, NULL, 'b'},
+ {NULL}
+ };
+
+ std::string configName = "";
+ std::string displayName = "";
+ bool upsideDown = false;
+ bool invert = false;
+ int brightness = -1;
+ bool delay = false;
+ int sleepMs = kDefaultSleepMs;
+ bool endless = false;
+ unsigned int displayNumber = 0;
+
+ int c, option_index = 0;
+ while ((c = getopt_long(argc, argv, "c:d:s:euib:", long_options, &option_index)) != -1)
+ {
+ switch(c)
+ {
+ case 'c':
+ configName = optarg;
+ break;
+
+ case 'd':
+ displayName = optarg;
+ break;
+
+ case 'u':
+ upsideDown = true;
+ break;
+
+ case 'i':
+ invert = true;
+ break;
+
+ case 's':
+ sleepMs = atoi(optarg);
+ delay = true;
+ break;
+
+ case 'e':
+ endless = true;
+ break;
+
+ case 'b':
+ brightness = atoi(optarg);
+ if (brightness < 0) brightness = 0;
+ if (brightness > 100) brightness = 100;
+ break;
+
+ default:
+ usage();
+ return 1;
+ } // switch
+ } // while
+
+ if (configName.length() == 0)
+ {
+ configName = kDefaultConfigFile;
+ syslog(LOG_INFO, "Error: No config file specified, using default (%s).\n", configName.c_str());
+ } // if
+
+ if (GLCD::Config.Load(configName) == false)
+ {
+ fprintf(stdout, "Error loading config file!\n");
+ return 2;
+ } // if
+
+ if (GLCD::Config.driverConfigs.size() > 0)
+ {
+ if (displayName.length() > 0)
+ {
+ for (displayNumber = 0; displayNumber < GLCD::Config.driverConfigs.size(); displayNumber++)
+ {
+ if (GLCD::Config.driverConfigs[displayNumber].name == displayName)
+ break;
+ } // for
+
+ if (displayNumber == GLCD::Config.driverConfigs.size())
+ {
+ fprintf(stdout, "ERROR: Specified display %s not found in config file!\n", displayName.c_str());
+ return 3;
+ } // if
+ }
+ else
+ {
+ fprintf(stdout, "WARNING: No display specified, using first one.\n");
+ displayNumber = 0;
+ } // if
+ }
+ else
+ {
+ fprintf(stdout, "ERROR: No displays specified in config file!\n");
+ return 4;
+ } // if
+
+ GLCD::Config.driverConfigs[displayNumber].upsideDown ^= upsideDown;
+ GLCD::Config.driverConfigs[displayNumber].invert ^= invert;
+
+ if (brightness != -1)
+ {
+ GLCD::Config.driverConfigs[displayNumber].brightness = brightness;
+ } // if
+
+ GLCD::cDriver * lcd = GLCD::CreateDriver(GLCD::Config.driverConfigs[displayNumber].id, &GLCD::Config.driverConfigs[displayNumber]);
+ if (!lcd)
+ {
+ fprintf(stderr, "ERROR: Failed creating display object %s\n", displayName.c_str());
+ return 6;
+ } // if
+
+ if (lcd->Init() != 0)
+ {
+ fprintf(stderr, "ERROR: Failed initializing display %s\n", displayName.c_str());
+ delete lcd;
+ return 7;
+ } // if
+
+ lcd->SetBrightness(GLCD::Config.driverConfigs[displayNumber].brightness);
+
+ signal(SIGINT, sighandler);
+ signal(SIGQUIT, sighandler);
+ signal(SIGTERM, sighandler);
+ signal(SIGHUP, sighandler);
+
+ //----- show horizontal lines -----
+ for (int aByte = 1; aByte <= 255 && !stopProgramm; ++aByte)
+ {
+ unsigned char aData = GLCD::ReverseBits(aByte);
+ printf("clear and test byte: 0x%02X\n", aByte);
+ lcd->Clear();
+
+ for (int y = 0; y < lcd->Height() && !stopProgramm; ++y)
+ {
+ for (int x = 0; x < lcd->Width() && !stopProgramm; x += 8)
+ {
+ lcd->Set8Pixels(x, y, aData);
+ } // for
+ } // for
+
+ lcd->Refresh(true);
+ usleep(sleepMs * 1000);
+ } // for
+
+ //----- show vertial lines -----
+ for (int aByte = 1; aByte <= 255 && !stopProgramm; ++aByte)
+ {
+ printf("clear and test byte: 0x%02X\n", aByte);
+ lcd->Clear();
+
+ for (int y = 0; y < lcd->Height() && !stopProgramm; ++y)
+ {
+ unsigned char aData = (((1 << (y % 8)) & aByte) == 0) ? 0x00 : 0xFF;
+ for (int x = 0; x < lcd->Width() && !stopProgramm; x += 8)
+ {
+ lcd->Set8Pixels(x, y, aData);
+ } // for
+ } // for
+
+ lcd->Refresh(true);
+ usleep(sleepMs * 1000);
+ } // for
+
+ //----- cleanup -----
+ lcd->Clear();
+ lcd->Refresh(true);
+ lcd->DeInit();
+ delete lcd;
+
+ return 0;
+} // main()
diff --git a/tools/showpic/Makefile b/tools/showpic/Makefile
new file mode 100644
index 0000000..82970e7
--- /dev/null
+++ b/tools/showpic/Makefile
@@ -0,0 +1,46 @@
+#
+# Makefile for the GraphLCD tool showpic
+#
+
+-include ../../Make.config
+
+PRGNAME = showpic
+
+OBJS = showpic.o
+
+INCLUDES += -I../../
+LIBDIRS += -L../../glcdgraphics/ -L../../glcddrivers/
+
+
+all: $(PRGNAME)
+.PHONY: all
+
+# Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+# The main program:
+
+$(PRGNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBS) $(LIBDIRS) -lglcdgraphics -lglcddrivers -lstdc++ -o $(PRGNAME)
+
+install: $(PRGNAME)
+ install -d $(BINDIR)
+ install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR)
+
+uninstall:
+ rm -f $(BINDIR)/$(PRGNAME)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~
+
diff --git a/tools/showpic/showpic.c b/tools/showpic/showpic.c
new file mode 100644
index 0000000..f17f361
--- /dev/null
+++ b/tools/showpic/showpic.c
@@ -0,0 +1,256 @@
+/*
+ * GraphLCD tool showpic
+ *
+ * showpic.c - a tool to show image files in GLCD format on a LCD
+ *
+ * based on graphlcd plugin 0.1.1 for the Video Disc Recorder
+ * (c) 2001-2004 Carsten Siebholz <c.siebholz AT t-online.de>
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <signal.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/glcd.h>
+#include <glcdgraphics/image.h>
+#include <glcddrivers/config.h>
+#include <glcddrivers/driver.h>
+#include <glcddrivers/drivers.h>
+
+static const char *prgname = "showpic";
+static const char *version = "0.1.2";
+
+static const int kDefaultSleepMs = 100;
+static const char * kDefaultConfigFile = "/etc/graphlcd.conf";
+
+static volatile bool stopProgramm = false;
+
+static void sighandler(int signal)
+{
+ switch (signal)
+ {
+ case SIGINT:
+ case SIGQUIT:
+ case SIGTERM:
+ stopProgramm = true;
+ }
+}
+
+void usage()
+{
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%s v%s\n", prgname, version);
+ fprintf(stdout, "%s is a tool to show an image on a LCD.\n", prgname);
+ fprintf(stdout, "The image must be in a special format (*.glcd).\n");
+ fprintf(stdout, "You can create such images with the convpic tool.\n\n");
+ fprintf(stdout, " Usage: %s [-c CONFIGFILE] [-d DISPLAY] [-s SLEEP] [-uie] file [more files]\n\n", prgname);
+ fprintf(stdout, " -c --config specifies the location of the config file\n");
+ fprintf(stdout, " (default: /etc/graphlcd.conf)\n");
+ fprintf(stdout, " -d --display specifies the output display (default is the first one)\n");
+ fprintf(stdout, " -u --upsidedown rotates the output by 180 degrees (default: no)\n");
+ fprintf(stdout, " -i --invert inverts the output (default: no)\n");
+ fprintf(stdout, " -e --endless show all images in endless loop (default: no)\n");
+ fprintf(stdout, " -s --sleep set sleeptime between two images [ms] (default: %d ms)\n", kDefaultSleepMs);
+ fprintf(stdout, " -b --brightness set brightness for display if driver support it [%%]\n");
+ fprintf(stdout, " (default: config file value)\n");
+ fprintf(stdout, "\n" );
+ fprintf(stdout, " examples: %s -c /etc/graphlcd.conf vdr-logo.glcd\n", prgname);
+ fprintf(stdout, " %s -c /etc/graphlcd.conf -d LCD_T6963 -u -i vdr-logo.glcd\n", prgname);
+ fprintf(stdout, "\n" );
+}
+
+int main(int argc, char *argv[])
+{
+ static struct option long_options[] =
+ {
+ {"config", required_argument, NULL, 'c'},
+ {"display", required_argument, NULL, 'd'},
+ {"sleep", required_argument, NULL, 's'},
+ {"endless", no_argument, NULL, 'e'},
+ {"upsidedown", no_argument, NULL, 'u'},
+ {"invert", no_argument, NULL, 'i'},
+ {"brightness", required_argument, NULL, 'b'},
+ {NULL}
+ };
+
+ std::string configName = "";
+ std::string displayName = "";
+ bool upsideDown = false;
+ bool invert = false;
+ int brightness = -1;
+ bool delay = false;
+ int sleepMs = 100;
+ bool endless = false;
+ unsigned int displayNumber = 0;
+
+ int c, option_index = 0;
+ while ((c = getopt_long(argc, argv, "c:d:s:euib:", long_options, &option_index)) != -1)
+ {
+ switch(c)
+ {
+ case 'c':
+ configName = optarg;
+ break;
+
+ case 'd':
+ displayName = optarg;
+ break;
+
+ case 'u':
+ upsideDown = true;
+ break;
+
+ case 'i':
+ invert = true;
+ break;
+
+ case 's':
+ sleepMs = atoi(optarg);
+ delay = true;
+ break;
+
+ case 'e':
+ endless = true;
+ break;
+
+ case 'b':
+ brightness = atoi(optarg);
+ if (brightness < 0) brightness = 0;
+ if (brightness > 100) brightness = 100;
+ break;
+
+ default:
+ usage();
+ return 1;
+ }
+ }
+
+ if (configName.length() == 0)
+ {
+ configName = kDefaultConfigFile;
+ syslog(LOG_INFO, "Error: No config file specified, using default (%s).\n", configName.c_str());
+ }
+
+ if (GLCD::Config.Load(configName) == false)
+ {
+ fprintf(stdout, "Error loading config file!\n");
+ return 2;
+ }
+ if (GLCD::Config.driverConfigs.size() > 0)
+ {
+ if (displayName.length() > 0)
+ {
+ for (displayNumber = 0; displayNumber < GLCD::Config.driverConfigs.size(); displayNumber++)
+ {
+ if (GLCD::Config.driverConfigs[displayNumber].name == displayName)
+ break;
+ }
+ if (displayNumber == GLCD::Config.driverConfigs.size())
+ {
+ fprintf(stdout, "ERROR: Specified display %s not found in config file!\n", displayName.c_str());
+ return 3;
+ }
+ }
+ else
+ {
+ fprintf(stdout, "WARNING: No display specified, using first one.\n");
+ displayNumber = 0;
+ }
+ }
+ else
+ {
+ fprintf(stdout, "ERROR: No displays specified in config file!\n");
+ return 4;
+ }
+
+ if (optind == argc)
+ {
+ usage();
+ fprintf(stderr, "ERROR: You have to specify the image\n");
+ return 5;
+ }
+
+ GLCD::Config.driverConfigs[displayNumber].upsideDown ^= upsideDown;
+ GLCD::Config.driverConfigs[displayNumber].invert ^= invert;
+ if (brightness != -1)
+ GLCD::Config.driverConfigs[displayNumber].brightness = brightness;
+ GLCD::cDriver * lcd = GLCD::CreateDriver(GLCD::Config.driverConfigs[displayNumber].id, &GLCD::Config.driverConfigs[displayNumber]);
+ if (!lcd)
+ {
+ fprintf(stderr, "ERROR: Failed creating display object %s\n", displayName.c_str());
+ return 6;
+ }
+ if (lcd->Init() != 0)
+ {
+ fprintf(stderr, "ERROR: Failed initializing display %s\n", displayName.c_str());
+ delete lcd;
+ return 7;
+ }
+ lcd->SetBrightness(GLCD::Config.driverConfigs[displayNumber].brightness);
+
+ signal(SIGINT, sighandler);
+ signal(SIGQUIT, sighandler);
+ signal(SIGTERM, sighandler);
+ signal(SIGHUP, sighandler);
+
+ const GLCD::cBitmap * bitmap;
+ GLCD::cImage image;
+ GLCD::cGLCDFile glcd;
+ int optFile;
+ std::string picFile;
+
+ optFile = optind;
+ while (optFile < argc && !stopProgramm)
+ {
+ picFile = argv[optFile++];
+ if (glcd.Load(image, picFile) == false)
+ {
+ fprintf(stderr, "ERROR: Failed loading file %s\n", picFile.c_str());
+ return 8;
+ }
+
+ if (delay)
+ image.SetDelay(sleepMs);
+
+ while ((bitmap = image.GetBitmap()) != NULL && !stopProgramm)
+ {
+ lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height(), bitmap->LineSize());
+ lcd->Refresh(true);
+
+ if (image.Next(0)) // Select next image
+ {
+ usleep(image.Delay() * 1000);
+ }
+ else if (endless && argc == (optind + 1)) // Endless and one and only image
+ {
+ image.First(0);
+ usleep(image.Delay() * 1000);
+ }
+ else
+ break;
+ }
+
+ if (optFile < argc || endless)
+ usleep(sleepMs * 1000);
+ if (optFile >= argc && endless)
+ optFile = optind;
+ }
+
+ lcd->DeInit();
+ delete lcd;
+
+ return 0;
+}
diff --git a/tools/showtext/Makefile b/tools/showtext/Makefile
new file mode 100644
index 0000000..f787bb3
--- /dev/null
+++ b/tools/showtext/Makefile
@@ -0,0 +1,46 @@
+#
+# Makefile for the GraphLCD tool showtext
+#
+
+-include ../../Make.config
+
+PRGNAME = showtext
+
+OBJS = showtext.o
+
+INCLUDES += -I../../
+LIBDIRS += -L../../glcdgraphics/ -L../../glcddrivers/
+
+
+all: $(PRGNAME)
+.PHONY: all
+
+# Implicit rules:
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+# The main program:
+
+$(PRGNAME): $(OBJS)
+ $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBS) $(LIBDIRS) -lglcdgraphics -lglcddrivers -lstdc++ -o $(PRGNAME)
+
+install: $(PRGNAME)
+ install -d $(BINDIR)
+ install -m 755 -o root -g root -s $(PRGNAME) $(BINDIR)
+
+uninstall:
+ rm -f $(BINDIR)/$(PRGNAME)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) $(PRGNAME) *~
+
diff --git a/tools/showtext/showtext.c b/tools/showtext/showtext.c
new file mode 100644
index 0000000..2621db1
--- /dev/null
+++ b/tools/showtext/showtext.c
@@ -0,0 +1,279 @@
+/*
+ * GraphLCD tool showtext
+ *
+ * showtext.c - a tool to show a text on a LCD
+ *
+ * This file is released under the GNU General Public License. Refer
+ * to the COPYING file distributed with this package.
+ *
+ * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <glcdgraphics/bitmap.h>
+#include <glcdgraphics/font.h>
+#include <glcddrivers/config.h>
+#include <glcddrivers/driver.h>
+#include <glcddrivers/drivers.h>
+
+static const char *prgname = "showtext";
+static const char *version = "0.0.3";
+
+static const char * kDefaultConfigFile = "/etc/graphlcd.conf";
+
+static const int kFontFNT = 0;
+static const int kFontFT2 = 1;
+
+void usage()
+{
+ fprintf(stdout, "\n");
+ fprintf(stdout, "%s v%s\n", prgname, version);
+ fprintf(stdout, "%s is a tool to show a text on a LCD.\n", prgname);
+ fprintf(stdout, "\n");
+ fprintf(stdout, " Usage: %s [-c CONFIGFILE] [-d DISPLAY] [-f FONT] [-x XPOS] [-y YPOS] [-uib] text [more text]\n\n", prgname);
+ fprintf(stdout, " -c --config specifies the location of the config file\n");
+ fprintf(stdout, " (default: /etc/graphlcd.conf)\n");
+ fprintf(stdout, " -d --display specifies the output display (default is the first one)\n");
+ fprintf(stdout, " -f --font specifies the font that is used for the text:\n");
+ fprintf(stdout, " fnt:/path/to/font.fnt for GraphLCD font format\n");
+ fprintf(stdout, " ft2:/path/to/font.ttf:size for FreeType2 supported fonts\n");
+ fprintf(stdout, " -e --encoding specifies the encoding that is used for the text\n");
+ fprintf(stdout, " (p.e. iso8859-1)\n");
+ fprintf(stdout, " -x --xpos specifies the x-position where the text starts\n");
+ fprintf(stdout, " -y --ypos specifies the y-position where the text starts\n");
+ fprintf(stdout, " -u --upsidedown rotates the output by 180 degrees (default: no)\n");
+ fprintf(stdout, " -i --invert inverts the output (default: no)\n");
+ fprintf(stdout, " -b --brightness set brightness for display if driver support it [%%]\n");
+ fprintf(stdout, " (default: config file value)\n");
+ fprintf(stdout, "\n" );
+ fprintf(stdout, " example: %s -c /etc/graphlcd.conf -f fnt:f17.fnt \"Line1\" \"Line2\"\n", prgname);
+ fprintf(stdout, "\n" );
+}
+
+int main(int argc, char *argv[])
+{
+ static struct option long_options[] =
+ {
+ {"config", required_argument, NULL, 'c'},
+ {"display", required_argument, NULL, 'd'},
+ {"font", required_argument, NULL, 'f'},
+ {"encoding", required_argument, NULL, 'e'},
+ {"upsidedown", no_argument, NULL, 'u'},
+ {"invert", no_argument, NULL, 'i'},
+ {"brightness", required_argument, NULL, 'b'},
+ {"xpos", required_argument, NULL, 'x'},
+ {"ypos", required_argument, NULL, 'y'},
+ {NULL}
+ };
+
+ std::string configName = "";
+ std::string displayName = "";
+ std::string fontName;
+ std::string fontFileName = "";
+ std::string encoding = "";
+ int fontType;
+ int fontSize = 16;
+ bool upsideDown = false;
+ bool invert = false;
+ int brightness = -1;
+ int x = 0;
+ int y = 0;
+ unsigned int displayNumber = 0;
+
+ int c, option_index = 0;
+ while ((c = getopt_long(argc, argv, "c:d:f:e:uib:x:y:", long_options, &option_index)) != -1)
+ {
+ switch (c)
+ {
+ case 'c':
+ configName = optarg;
+ break;
+
+ case 'd':
+ displayName = optarg;
+ break;
+
+ case 'f':
+ fontName = optarg;
+ break;
+
+ case 'e':
+ encoding = optarg;
+ break;
+
+ case 'u':
+ upsideDown = true;
+ break;
+
+ case 'i':
+ invert = true;
+ break;
+
+ case 'b':
+ brightness = atoi(optarg);
+ if (brightness < 0) brightness = 0;
+ if (brightness > 100) brightness = 100;
+ break;
+
+ case 'x':
+ x = atoi(optarg);
+ break;
+
+ case 'y':
+ y = atoi(optarg);
+ break;
+
+ default:
+ usage();
+ return 1;
+ }
+ }
+
+ if (configName.length() == 0)
+ {
+ configName = kDefaultConfigFile;
+ fprintf(stdout, "WARNING: No config file specified, using default (%s).\n", configName.c_str());
+ }
+
+ if (GLCD::Config.Load(configName) == false)
+ {
+ fprintf(stderr, "Error loading config file!\n");
+ return 2;
+ }
+ if (GLCD::Config.driverConfigs.size() > 0)
+ {
+ if (displayName.length() > 0)
+ {
+ for (displayNumber = 0; displayNumber < GLCD::Config.driverConfigs.size(); displayNumber++)
+ {
+ if (GLCD::Config.driverConfigs[displayNumber].name == displayName)
+ break;
+ }
+ if (displayNumber == GLCD::Config.driverConfigs.size())
+ {
+ fprintf(stderr, "ERROR: Specified display %s not found in config file!\n", displayName.c_str());
+ return 3;
+ }
+ }
+ else
+ {
+ fprintf(stdout, "WARNING: No display specified, using first one.\n");
+ displayNumber = 0;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: No displays specified in config file!\n");
+ return 4;
+ }
+
+ if (encoding.length() == 0)
+ {
+ encoding = "iso8859-1";
+ fprintf(stdout, "WARNING: No encoding specified, using default (%s).\n", encoding.c_str());
+ }
+
+ if (fontName.length() == 0)
+ {
+ fprintf(stderr, "Error: No font specified!\n");
+ return 5;
+ }
+ if (fontName.find("fnt:") == 0)
+ {
+ fontType = kFontFNT;
+ fontFileName = fontName.substr(4);
+ }
+ else if (fontName.find("ft2:") == 0)
+ {
+ fontType = kFontFT2;
+ std::string::size_type pos = fontName.find(":", 4);
+ if (pos == std::string::npos)
+ {
+ fontSize = 16;
+ fprintf(stdout, "WARNING: No font size specified, using default (%d).\n", fontSize);
+ fontFileName = fontName.substr(4);
+ }
+ else
+ {
+ std::string tmp = fontName.substr(pos + 1);
+ fontSize = atoi(tmp.c_str());
+ fontFileName = fontName.substr(4, pos - 4);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Error: Unknown font type!\n");
+ return 6;
+ }
+
+ if (optind == argc)
+ {
+ usage();
+ fprintf(stderr, "ERROR: You have to specify a text\n");
+ return 7;
+ }
+
+ GLCD::Config.driverConfigs[displayNumber].upsideDown ^= upsideDown;
+ GLCD::Config.driverConfigs[displayNumber].invert ^= invert;
+ if (brightness != -1)
+ GLCD::Config.driverConfigs[displayNumber].brightness = brightness;
+
+ GLCD::cFont font;
+ if (fontType == kFontFNT)
+ {
+ if (font.LoadFNT(fontFileName) == false)
+ {
+ fprintf(stderr, "ERROR: Failed loading font file %s\n", fontFileName.c_str());
+ return 8;
+ }
+ }
+ else
+ {
+ if (font.LoadFT2(fontFileName, encoding, fontSize) == false)
+ {
+ fprintf(stderr, "ERROR: Failed loading font file %s\n", fontFileName.c_str());
+ return 8;
+ }
+ }
+ GLCD::cDriver * lcd = GLCD::CreateDriver(GLCD::Config.driverConfigs[displayNumber].id, &GLCD::Config.driverConfigs[displayNumber]);
+ if (!lcd)
+ {
+ fprintf(stderr, "ERROR: Failed creating display object %s\n", displayName.c_str());
+ return 9;
+ }
+ if (lcd->Init() != 0)
+ {
+ fprintf(stderr, "ERROR: Failed initializing display %s\n", displayName.c_str());
+ delete lcd;
+ return 10;
+ }
+
+ GLCD::cBitmap * bitmap = new GLCD::cBitmap(lcd->Width(), lcd->Height());
+ int optText;
+ std::string text;
+
+ bitmap->Clear();
+ optText = optind;
+ while (optText < argc)
+ {
+ text = argv[optText];
+ optText++;
+
+ bitmap->DrawText(x, y, bitmap->Width() - 1, text, &font);
+ y += font.LineHeight();
+ }
+ lcd->SetScreen(bitmap->Data(), bitmap->Width(), bitmap->Height(), bitmap->LineSize());
+ lcd->Refresh(true);
+
+ lcd->DeInit();
+ delete lcd;
+
+ return 0;
+}