436 lines
14 KiB
Plaintext
436 lines
14 KiB
Plaintext
<sect1 id="driver-shared-files">
|
|
<title>Shared files specific for drivers</title>
|
|
|
|
<para>
|
|
Driving an LCD display is not easy; you need to address ports, to send bytes
|
|
in a certain order, to respect timing, and unfortunaly no two operating system
|
|
let you do this in the same way. But don't dispair! There's hope! Someone in
|
|
a galaxy far far away, has allready done the dirty job for you! This dirty job
|
|
has been put in shared files. These shared files are full cross platform and
|
|
are automagically configured by the configure script. You only need to include
|
|
them and use their functions to benefit from them.
|
|
</para>
|
|
|
|
<para>
|
|
These files are provided only for drivers, others are provided for all of
|
|
LCDproc. These files are located in the shared directory, they have a
|
|
dedicated chapter in this book.
|
|
</para>
|
|
|
|
<sect2 id="port.h">
|
|
<title>port.h : Parallel port I/O</title>
|
|
|
|
<para>
|
|
The file <filename>port.h</filename>, located in the <filename>server/drivers/</filename>
|
|
directory provide Input/Output and port permissions for the PC compatible
|
|
parallel port, also known as the LPT port.
|
|
</para>
|
|
|
|
<para>
|
|
Of course, these functions will only work if the computer where LCDproc runs
|
|
has parallel port! In these situations, the configure script will see this and
|
|
disable drivers that need a parallel port.
|
|
</para>
|
|
|
|
<para>
|
|
The functions in <filename>port.h</filename> are defined and as 'static inline'.
|
|
Therefore each driver including this header file gets its own copy of the
|
|
functions and they are inlined into the driver's code. As a result calls to
|
|
port_in() and port_out() are directly translated to inb() or outb() or
|
|
assembly code by the compiler. There is less to no overhead in using them.
|
|
</para>
|
|
|
|
<para><filename>port.h</filename> file defines 6 static inline functions for port I/O:</para>
|
|
|
|
<sect3 id="port-in">
|
|
<title>Read a byte from port</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>static inline int <function>port_in</function></funcdef>
|
|
<paramdef>unsigned short int <parameter>port</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
<para>
|
|
Returns the content of the byte.
|
|
</para>
|
|
|
|
</sect3>
|
|
<sect3 id="port-out">
|
|
<title>Write a char(byte) 'val' to port</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>static inline void <function>port_out</function></funcdef>
|
|
<paramdef>unsigned short int <parameter>port</parameter></paramdef>
|
|
<paramdef>unsigned char <parameter>val</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
<para>
|
|
Returns nothing (void).
|
|
</para>
|
|
|
|
</sect3>
|
|
<sect3 id="port-access">
|
|
<title>Get access to a specific port</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>static inline int <function>port_access</function></funcdef>
|
|
<paramdef>unsigned short int <parameter>port</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
<para>
|
|
Returns <literal>0</literal> if successful, <literal>-1</literal> if failed.
|
|
</para>
|
|
|
|
|
|
</sect3>
|
|
<sect3 id="port-deny">
|
|
<title>Close access to a specific port</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>static inline int <function>port_deny</function></funcdef>
|
|
<paramdef>unsigned short int <parameter>port</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
<para>
|
|
Returns <literal>0</literal> if successful, <literal>-1</literal> if failed.
|
|
</para>
|
|
|
|
|
|
</sect3>
|
|
<sect3 id="port-access-multiple">
|
|
<title>Get access to multiple sequential ports</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>static inline int <function>port_access_full</function></funcdef>
|
|
<paramdef>unsigned short int <parameter>port</parameter></paramdef>
|
|
<paramdef>unsigned short int <parameter>count</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
<para>
|
|
Returns <literal>0</literal> if successful, <literal>-1</literal> if failed.
|
|
</para>
|
|
|
|
</sect3>
|
|
<sect3 id="port-deny-multiple">
|
|
<title>Close access to multiple sequential ports</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>static inline int <function>port_deny_full</function></funcdef>
|
|
<paramdef>unsigned short int <parameter>port</parameter></paramdef>
|
|
<paramdef>unsigned short int <parameter>count</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
<para>
|
|
Returns <literal>0</literal> if successful, <literal>-1</literal> if failed.
|
|
</para>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="port.h-example">
|
|
<title>Example use</title>
|
|
|
|
<screen>
|
|
#include "port.h"
|
|
|
|
/*
|
|
* Get access to these 3 ports:
|
|
* 0x378 (CONTROL),
|
|
* 0x379 (STATUS) and
|
|
* 0x37A (DATA)
|
|
*/
|
|
if (port_access_multiple(0x378, 3) == -1) {
|
|
/* Access denied, do something */
|
|
}
|
|
|
|
/* Write a 'A' to the control port */
|
|
port_out(0x378, 'A');
|
|
|
|
/* Read from the status port */
|
|
char status = port_in(0x379);
|
|
|
|
/* Close the 3 ports */
|
|
port_deny_multiple(0x378, 3);
|
|
</screen>
|
|
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
|
|
<sect2 id="adv_bignum.h">
|
|
<title>adv_bignum.h : Write Big-Numbers</title>
|
|
|
|
<para>
|
|
<filename>adv_bignum.h</filename> is the headerfile for <filename>libbignum.a</filename>
|
|
(made from <filename>adv_bignum.c</filename>) which contains everything needed to show big-numbers,
|
|
including the fonts for the different displays.
|
|
(All files are located in the <filename>server/drivers/</filename> directory.) </para>
|
|
<para/>
|
|
|
|
<para>
|
|
There are only a few requirements to the calling driver:
|
|
</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
The following functions have to be implemented by the driver:
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><function>height()</function></term>
|
|
<listitem>
|
|
<para>
|
|
to determine the display's height and thus the maximal height of the
|
|
big numbers to be displayed.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><function>get_free_chars()</function></term>
|
|
<listitem>
|
|
<para>
|
|
to determine the number of user-defineable characters that can be
|
|
used in the generation of big numbers.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><function>set_char()</function></term>
|
|
<listitem>
|
|
<para>
|
|
to define a character necessary to write a big number.
|
|
Of course this is only necessary if there really are user-definieable
|
|
characters, i.e. only if <function>get_free_chars()</function> returns
|
|
a value greater <literal>0</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><function>chr()</function></term>
|
|
<listitem>
|
|
<para>
|
|
to actually write the characters the big numbers consist of.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
The display's <replaceable>cellwidth</replaceable> has to be <literal>5</literal>
|
|
(<literal>6</literal> works also in some cases) and the <replaceable>cellheight</replaceable>
|
|
<literal>7</literal> or <literal>8</literal>.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
The custom-characters (if any) have to be at character positions
|
|
<replaceable>offset</replaceable><literal>+0</literal>,
|
|
<replaceable>offset</replaceable><literal>+1</literal>,
|
|
<replaceable>offset</replaceable><literal>+2</literal>, ...
|
|
<replaceable>offset</replaceable><literal>+</literal>
|
|
<function>get_free_chars()</function><literal>-1</literal>,
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<replaceable>offset</replaceable><literal>+</literal>
|
|
<function>get_free_chars()</function><literal>-1</literal> must be less than <literal>32</literal>,
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>
|
|
The library determines the correct font, depending on the display size and the number
|
|
of user-defined characters itself.
|
|
So it is easy to integrate into the driver.
|
|
</para>
|
|
|
|
|
|
|
|
<sect3 id="adv_bignum.h-usage">
|
|
<title>Provided Functions</title>
|
|
|
|
<funcsynopsis>
|
|
<funcprototype>
|
|
<funcdef>void <function>lib_adv_bignum</function></funcdef>
|
|
<paramdef>Driver *<parameter>drvthis</parameter></paramdef>
|
|
<paramdef>int <parameter>x</parameter></paramdef>
|
|
<paramdef>int <parameter>num</parameter></paramdef>
|
|
<paramdef>int <parameter>offset</parameter></paramdef>
|
|
<paramdef>int <parameter>do_init</parameter></paramdef>
|
|
</funcprototype>
|
|
</funcsynopsis>
|
|
|
|
<para>
|
|
The main thing the driver has to do is to call this function from its <function>num()</function>
|
|
function with the parameters described below.
|
|
</para>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><parameter>drvthis</parameter></term>
|
|
<listitem>
|
|
<para>
|
|
the pointer pointing to the Driver structure passed to thea driver's
|
|
<function>num()</function> function.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>x</parameter></term>
|
|
<listitem>
|
|
<para>
|
|
the horizontal position of the top-left corner of the big-number
|
|
(the big-numbers don't have a y position).
|
|
The placing of the characters is done by the client, so the driver only has to forward
|
|
the position to the lib. The bignumlib has no influence on the placing of the characters.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>num</parameter></term>
|
|
<listitem>
|
|
<para>
|
|
the number (legal: <literal>0</literal> - <literal>9</literal>,
|
|
and <literal>:</literal>) to be written.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>offset</parameter></term>
|
|
<listitem>
|
|
<para>
|
|
the character position where the user-defineable characters start
|
|
(usually <literal>0</literal>).
|
|
The user-defineable characters (if any) are then expected to be at the character positions
|
|
<replaceable>offset</replaceable><literal>+0</literal>,
|
|
<replaceable>offset</replaceable><literal>+1</literal>,
|
|
<replaceable>offset</replaceable><literal>+2</literal>, ...
|
|
<replaceable>offset</replaceable><literal>+</literal>
|
|
<function>get_free_chars()</function><literal>-1</literal>
|
|
and <replaceable>offset</replaceable><literal>+</literal>
|
|
<function>get_free_chars()</function><literal>-1</literal> is required to be less than
|
|
<literal>32</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>do_init</parameter></term>
|
|
<listitem>
|
|
<para>
|
|
if not <literal>0</literal>, lib_adv_bignum will set the
|
|
custom characters of the display for the big-numbers.
|
|
</para>
|
|
<para>
|
|
The driver has to check if the custom-characters have to be set or if it is
|
|
already done and tell it to the lib (using the <parameter>do_init</parameter> parameter).
|
|
The common way is to use variable called <replaceable>p->ccmode</replaceable> or similar.
|
|
In the different drivers there are some differences in the naming and handling of this variable.
|
|
So the responsibility of checking and setting is left to the driver.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
<example id="lib_adv_bignum-example">
|
|
<title>Calling <function>lib_adv_bignum()</function></title>
|
|
|
|
<programlisting>
|
|
<emphasis>#include "adv_bignum.h"</emphasis>
|
|
|
|
MODULE_EXPORT void
|
|
myDriver_num( Driver * drvthis, int x, int num )
|
|
{
|
|
PrivateData *p = drvthis->private_data;
|
|
int do_init = 0;
|
|
|
|
if (p->ccmode != CCMODE_BIGNUM){ // Are the custom-characters set up correctly? If not:
|
|
do_init = 1; // Lib_adv_bignum has to set the custom-characters.
|
|
p->ccmode = CCMODE_BIGNUM; // Switch custom-charactermode to bignum.
|
|
}
|
|
|
|
// Lib_adv_bignum does everything needed to show the big-numbers.
|
|
<emphasis>lib_adv_bignum(drvthis, x, num, 0, do_init);</emphasis>
|
|
}
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
<para>
|
|
All that's left to do is to add <filename>libbignum.a</filename> to the libs and
|
|
<filename>adv_bignum.h</filename> sources of your driver in the <filename>Makefile</filename>
|
|
(or the file that generates the
|
|
<filename>Makefile</filename>).
|
|
</para>
|
|
|
|
<example id="adv_bignum.h-Makefile.am-example">
|
|
<title>Enabling adv_bignum support in <filename>Makefile.am</filename></title>
|
|
|
|
<programlisting>
|
|
myDriver_LDADD: libLCD.a <emphasis>libbignum.a</emphasis>
|
|
|
|
myDriver_SOURCES: lcd.h lcd_lib.h myDriver.c myDriver.h report.h <emphasis>adv_bignum.h</emphasis>
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</sect3>
|
|
|
|
<sect3 id="adv_bignum.h-intern">
|
|
<title>Internal Structure and Functions</title>
|
|
|
|
<para>
|
|
The only purpose of <function>lib_adv_bignum()</function> is to determine the best
|
|
display-dependent big-number function, based upon the values of the driver's
|
|
<function>height()</function> and <function>get_free_chars()</function> functions,
|
|
and call it.
|
|
</para>
|
|
|
|
<para>
|
|
The display-dependent functions are named
|
|
<function>adv_bignum_num_<replaceable>N_M</replaceable>()</function>,
|
|
where <replaceable>N</replaceable> is the display's height in lines and <replaceable>M</replaceable>
|
|
the number of used user-defineable characters.
|
|
The bits of the user-characters are stored in <replaceable>static char bignum</replaceable>
|
|
(take a look at the source and you will see what I mean). (On a display with a
|
|
<replaceable>cellheight</replaceable> of 7 the lowest line stored is not shown.)
|
|
While <replaceable>static char num_map</replaceable> defines the placing in the big number.
|
|
(A big number is always 3 characters wide and 4 characters high.
|
|
On a big number for 2 line displays the 2 lower lines are not in use.)
|
|
</para>
|
|
|
|
<para>
|
|
If user-defineable characters have to be set, the driver's <function>set_char()</function> function
|
|
will be called once for every user-idefneable character.
|
|
</para>
|
|
|
|
<para>
|
|
Now <function>adv_bignum_write_num()</function> is called.
|
|
This function places the 6 or 12 characters the big-number consists of in the framebuffer
|
|
using the drivers <function>chr()</function> function.
|
|
</para>
|
|
|
|
</sect3>
|
|
|
|
</sect2>
|
|
|
|
</sect1>
|