diff --git a/docs/lcdproc-user/Makefile.am b/docs/lcdproc-user/Makefile.am index e16d6d7..79ff064 100644 --- a/docs/lcdproc-user/Makefile.am +++ b/docs/lcdproc-user/Makefile.am @@ -19,7 +19,7 @@ EXTRA_DIST = bookinfo.docbook \ ## convenience targets xmlto ?= /usr/bin/xmlto -userguidedir = $(DESTDIR)$(htmldir)/user-guide/ +userguidedir ?= $(DESTDIR)$(htmldir)/user-guide/ .PHONY: install-html-userguide diff --git a/docs/lcdproc-user/drivers/sed1330.docbook b/docs/lcdproc-user/drivers/sed1330.docbook index 374d1ec..4bf35f3 100644 --- a/docs/lcdproc-user/drivers/sed1330.docbook +++ b/docs/lcdproc-user/drivers/sed1330.docbook @@ -8,7 +8,8 @@ new names: S1D13300 (= SED1330) and S1D13305 (= SED1335). -The displays are driven in text mode using their built-in character generator. +The displays are driven in text mode using their built-in character generator +and the graphic mode for bars and the heartbeat icon (a bouncing ball). @@ -16,423 +17,246 @@ The displays are driven in text mode using their built-in character generator. -Connections below are for the G242C, G121C and G321D displays. -Always consult documentation about the specific display before asuming -the connections given here are also correct for your display ! +Displays using SED1330/1335 chipset come in a variety of pin-outs and power +configurations. They usually require negative voltage for contrast and some +displays have a negative voltage generator onboard. + + +Connections below are for the G242C, G121C and G321D displays. Always consult +documentation about the specific display before asuming the connections given +here are also correct for your display! - -ConnectionType <literal>classic</literal> ordered by LCD pins +
+ConnectionType <literal>classic</literal> ordered by LPT port pins - - + + - - + + - LCD - <-> LPT port + <-> + LCD - name - pin pin name + name + pin - ^RESET - 1 - 1 ^STROBE + + ^RESET + 1 - ^RD - 2 - +5V - + 2-9 + D0-D7 + D0-D7 + 8-15 - ^WR - 3 - 16 ^INIT + + ^WR + 3 - SEL1 - 4 - GND - - - - - SEL2 - 5 - GND - - - - - ^CS - 6 - GND - - - - - A0 - 7 - 17 ^SELECT_IN - - - D0 - 8 - - 2 - D0 - - - D1 - 9 - - 3 - D1 - - - D2 - 10 - - 4 - D2 - - - D3 - 11 - - 5 - D3 - - - D4 - 12 - - 6 - D4 - - - D5 - 13 + A0 7 - D5 - - - D6 - 14 - - 8 - D6 - - - D7 - 15 - - 9 - D7 - - - VCC - 16 - +5V - - + 18-25 + GND + GND VEE 17 - GND - 18..25 - GND + + + +5V + ^RD + 2 + + + + + GND + SEL1 + 4 + + + + + GND + SEL2 + 5 + + + + + GND + ^CS + 6 + + + + + +5V + VCC + 16 + + + + + potentiometer V0 18 - potentiometer - - + + + -24V (not required for G242C) VLC 19 - -24V (not required for G242C) - - - Frame + + + GND + FGND 20 - GND - - - - - - - - 10 - ^ACK - - - - - GND - 11 - BUSY - - - - - - 12 - PAPEREND - - - - - - 13 - ^SELECT - - - - - - 14 - ^LF - - - - - - 15 - ^ERROR
- -ConnectionType <literal>classic</literal> ordered by LPT port pins +
+ConnectionType <literal>bitshaker</literal> ordered by LPT port pins - - + + - - + + - LCD - <-> LPT port + <-> + LCD - name - pin pin name + name + pin - ^RESET - 1 - 1 ^STROBE - - - D0 - 8 - 2 - D0 - - - D1 - 9 - - 3 - D1 - - - D2 - 10 - - 4 - D2 - - - D3 - 11 - - 5 - D3 - - - D4 - 12 - - 6 - D4 - - - D5 - 13 - - 7 - D5 - - - D6 - 14 - - 8 - D6 - - - D7 - 15 - - 9 - D7 - - - - - - 10 - ^ACK - - - - - GND - 11 - BUSY - - - - - - 12 - PAPEREND - - - - - - 13 - ^SELECT - - - - - - 14 - ^LF - - - - - - 15 - ^ERROR - - ^WR 3 - - 16 - ^INIT + 2-9 + D0-D7 + + D0-D7 + 8-15 + + + 14 + ^LF + A0 7 - - 17 - ^SELECT_IN + 16 + ^INIT + + ^RESET + 1 + + + 18-25 + GND + GND VEE 17 - GND - 18..25 - GND + + + +5V ^RD 2 - +5V - - + + + GND SEL1 4 - GND - - + + + GND SEL2 5 - GND - - + + + GND ^CS 6 - GND - - + + + +5V VCC 16 - +5V - - + + + potentiometer V0 18 - potentiometer - - + + + -24V (not required for G242C) VLC 19 - -24V (not required for G242C) - - - Frame - 20 + + GND - - + FGND + 20 @@ -504,6 +328,14 @@ use the following circuit. + +Keypad + +The sed1330 driver supports the same direct keys and matrix keypad +connections as the hd44780 driver. See . + + + @@ -523,6 +355,12 @@ use the following circuit. legal values for HEIGHT range from 7 to 16. If not given CellSize defaults to 6x10. + + + Contrary to other drivers the character size of an LCD using the sed1330 + driver is not given directly. Instead it is determined by the pixel size + of the display, which is derived from the display type setting and the + character cell size specified with this setting. @@ -536,30 +374,8 @@ use the following circuit. - Select the type of the wiring. + Select the type of the wiring, see . - - - - - - ConnectionType - Wiring - - - - - classic - ^WR = LPT pin 16, A0 = LPT pin 17, ^RESET = LPT pin 1 - - - bitshaker - ^WR = LPT pin 1, A0 = LPT pin 14, ^RESET = LPT pin 16 - - - - - If not given, it defaults to classic. @@ -646,13 +462,6 @@ use the following circuit. - -Contrary to other drivers the character size of an LCD using the sed1330 -driver is not given directly. -Instead it is determined by the pixel size of the display, which is derived from -the display type setting and the character cell size. - - diff --git a/server/drivers/sed1330.c b/server/drivers/sed1330.c index 9dc390d..0cdf5f5 100644 --- a/server/drivers/sed1330.c +++ b/server/drivers/sed1330.c @@ -1,27 +1,25 @@ /** \file server/drivers/sed1330.c * LCDd \c sed1330 driver for SED1330/1335 graphical displays. + * + * EPSON has changed the the chip-labeling. SED1330 now is S1D13300 and + * SED1335 is S1D13305. + * + * This driver drives the LCD in text mode and uses graphic mode to draw + * the heartbeart and bars. */ -/* +/*- * Driver for SED1330/1335 graphical displays * - * EPSON has changed the the chip-labeling. - * SED1330 now is S1D13300 and SED1335 is S1D13305 - * - * This driver drives the LCD in text mode. - * Probably the driver can easily be adapted to work for 1336 too. - * - * Moved the delay timing code by Charles Steinkuehler to timing.h. - * Guillaume Filion , December 2001 - * - * This file is released under the GNU General Public License. Refer to the - * COPYING file distributed with this package. - * * Copyright (c) 2001-2003, Joris Robijn * 2003, Michael Rohde * 2006, Benjamin Wiedmann * - * + * This file is released under the GNU General Public License. Refer to the + * COPYING file distributed with this package. + */ + +/*- * Changelog: * * November 2001, Joris Robijn: @@ -29,6 +27,8 @@ * - Parts copied from HD44780 driver * December 2001, Joris Robijn: * - Adapted to v0.5 API + * December 2001, Guillaume Filion: + * - Moved the delay timing code by Charles Steinkuehler to timing.h. * June 2002, Joris Robijn: * - Modified init things to support multiple font sizes * - More calculations v.s. static init data @@ -56,204 +56,37 @@ * December 2006, Benjamin Wiedmann (additional changes, fixup) * - wiring scheme can now be changed at run time using "ConnectionType" config parameter * in sed1330 driver section - * Usage of ConnectionType in LCDd.conf: - * ConnectionType= + * Usage of ConnectionType in LCDd.conf: + * ConnectionType= * - if no ConnectionType is set it defaults to "classic" wiring - * - * IMPORTANT: MODULES OTHER THAN G321D - * =================================== - * If you are using a module other than the G321D, beware that the software - * has not been tested. You may need to adapt the initialization parameters - * to get it working properly. - * - * - * - * - * Connections - * =========== - * - * Connections below are for the G242C, G121C and G321D displays. - * Always consult documentation about the specific display before asuming - * the connections given here are also correct for your display ! - * - * Ordered by LCD pins - * LCD pin? <---> pin LPT port - * ^RESET 1 1 ^STROBE - * ^RD 2 +5V - * ^WR 3 16 ^INIT - * SEL1 4 GND - * SEL2 5 GND - * ^CS 6 GND - * A0 7 17 ^SELECT_IN - * D0 8 2 D0 - * D1 9 3 D1 - * D2 10 4 D2 - * D3 11 5 D3 - * D4 12 6 D4 - * D5 13 7 D5 - * D6 14 8 D6 - * D7 15 9 D7 - * Vdd 16 +5V - * Vss 17 GND 18..25 GND - * V0 18 potmeter - * Vlc 19 -24V - * Frame 20 GND - * 10 ^ACK - * GND 11 BUSY - * 12 PAPEREND - * 13 ^SELECT - * 14 ^LF - * 15 ^ERROR - * - * Or ordered by the LPT port pins: - * LCD pin? <---> pin LPT port - * ^RESET 1 1 ^STROBE - * D0 8 2 D0 - * D1 9 3 D1 - * D2 10 4 D2 - * D3 11 5 D3 - * D4 12 6 D4 - * D5 13 7 D5 - * D6 14 8 D6 - * D7 15 9 D7 - * 10 ^ACK - * GND 11 BUSY - * 12 PAPEREND - * 13 ^SELECT - * 14 ^LF - * 15 ^ERROR - * ^WR 3 16 ^INIT - * A0 7 17 ^SELECT_IN - * Vss 17 GND 18..25 GND - * ^RD 2 +5V - * SEL1 4 GND - * SEL2 5 GND - * ^CS 6 GND - * Vdd 16 +5V - * V0 18 potmeter - * Vlc 19 -24V (not required for G242C) - * Frame 20 GND - * - * The potmeter should be connected like this on these display modules: - * - * === GND - * | - * .-. - * | | - * | |5k - * '-' - * | - * | - * .-.10k potmeter - * | | - * | |<----------------o V0 - * | | - * '-' - * | - * O Vlc (= -24V) - * - * The G242C generates -24V internally. It is available on Vlc. - * - * Connections below are for the HG25504 displays. - * Always consult documentation about the specific display before asuming - * the connections given here are also correct for your display ! - * - * Ordered by LCD pins - * LCD pin? <---> pin LPT port - * Frame 1 GND - * Vss 2 GND 18..25 GND - * Vdd 3 +5V - * Vo 3 potmeter - * ^RESET 5 1 ^STROBE - * ^RD 6 +5V - * ^WR 7 16 ^INIT - * ^CS 8 GND - * A0 9 17 ^SELECT_IN - * D0 10 2 D0 - * D1 11 3 D1 - * D2 12 4 D2 - * D3 13 5 D3 - * D4 14 6 D4 - * D5 15 7 D5 - * D6 16 8 D6 - * D7 17 9 D7 - * - * To generate -24 from the +5V without an external power source, you can - * use the following circuit. - * - * 5V O------+----------+ pinout: - * | | _____ - * | --- 100uF | _ | - * | --- 10V | (_) | <-3 - * | | |_____| - * | +--------+--------+--------+ | max | - * |5 | | | | | 724 | - * --------- === GND C - | |_____| - * | | C coil | | | ||||| - * | | C 47uH | |10k | |||||. - * | |4 | - | | | | - * | MAX724 |--------------+ | | 12345 - * | or | | | | - * | MAX726 |1 | | |+ - * | |-----------------------+ --- 47uF - * | | | | --- 50V - * | | | | | - * --------- | - | - * |2 |3 | | | | - * | | '---, | |1k | - * --- | SB160 / \ - | - * 100nF--- | ^T^ | | - * | | | | | - * +-----+----------------+--------+--------+----O -24V out - * - * - * - * - * Config options - * ============== - * - * With the display= option you should specify what display module you have. - * Accepted values are: - * type=G121C - * type=G242C - * type=G321D - * type=G191D - * type=G2446 - * type=SP14Q002 - * - * You can also change the wiring scheme by using the ConnectionType= option: - * ConnectionType= - * If not set, classic wiring is used. - * - * The port= value should be set to the LPT port address that the LCD is - * connected to. Examples: - * port=0x378 - * port=0x278 - * port=0x3BC - * - * The cellsize= value indicates the size of a character. Default: - * cellsize=6x10 - * + * January 2011, Markus Dolze: + * - Add support for HG25504 (bye L. Lagendijk). + * - Remove instructions that have been transfered to the User's Guide. + * - Convert function comments to Doxygen. + * - Remove the unused line drawing function. */ -#include "lcd.h" -#include "sed1330.h" - -#include "port.h" -#include "lpt-port.h" -#include "report.h" -#include "timing.h" -#define uPause timing_uPause - #include #include #include -// Autorepeat values +#include "lcd.h" +#include "sed1330.h" +#include "port.h" +#include "lpt-port.h" +#include "report.h" +#include "timing.h" + +/* Use uPause from timing.h */ +#define uPause timing_uPause + +/* Keypad settings */ #define KEYPAD_AUTOREPEAT_DELAY 500 #define KEYPAD_AUTOREPEAT_FREQ 15 +#define KEYPAD_MAXX 5 +#define KEYPAD_MAXY 8 -// Command definitions +/* Command definitions */ #define CMD_SYSTEM_SET 0x40 #define CMD_SLEEP_IN 0x53 #define CMD_DISP_DIS 0x58 @@ -272,19 +105,17 @@ #define CMD_MWRITE 0x42 #define CMD_MREAD 0x43 -// Data definitions -#define KEYPAD_MAXX 5 -#define KEYPAD_MAXY 8 +/* LCD types known */ +#define TYPE_G321D 1 +#define TYPE_G121C 2 +#define TYPE_G242C 3 +#define TYPE_G191D 4 +#define TYPE_G2446 5 +#define TYPE_SP14Q002 6 +#define TYPE_HG25504 7 -#define TYPE_G321D 1 -#define TYPE_G121C 2 -#define TYPE_G242C 3 -#define TYPE_G191D 4 -#define TYPE_G2446 5 -#define TYPE_SP14Q002 6 -#define TYPE_HG25504 7 - -#define SCR1_L 0x00 // Memory locations +/* Memory locations */ +#define SCR1_L 0x00 #define SCR1_H 0x00 #define SCR2_L 0x00 #define SCR2_H 0x06 @@ -292,14 +123,14 @@ /** private data for the \c sed1330 driver */ typedef struct sed1330_private_data { - int type; /**< display type */ + int type; /**< display type */ - // wiring scheme variables to be set by sed1330_init() + /* wiring scheme variables to be set by sed1330_init() */ int A0; int nRESET; int nWR; - int port; /**< LPT port to use */ + int port; /**< LPT port to use */ unsigned char *framebuf_text; unsigned char *lcd_contents_text; @@ -313,12 +144,17 @@ typedef struct sed1330_private_data { char have_keypad; - // keyMapDirect contains an array of the ascii-codes that should be generated - // when a directly connected key is pressed (not in matrix). + /* + * keyMapDirect contains an array of the ascii-codes that should be + * generated when a directly connected key is pressed (not in + * matrix). + */ char *keyMapDirect[KEYPAD_MAXX]; - // keyMapMatrix contrains an array with arrays of the ascii-codes that should be generated - // when a key in the matrix is pressed. + /* + * keyMapMatrix contrains an array with arrays of the ascii-codes + * that should be generated when a key in the matrix is pressed. + */ char *keyMapMatrix[KEYPAD_MAXY][KEYPAD_MAXX]; char *pressed_key; @@ -328,195 +164,198 @@ typedef struct sed1330_private_data { int stuckinputs; } PrivateData; -static char *defaultKeyMapDirect[KEYPAD_MAXX] = { "Enter", "Up", "Down", "Escape", "F1" }; +static char *defaultKeyMapDirect[KEYPAD_MAXX] = {"Enter", "Up", "Down", "Escape", "F1"}; static char *defaultKeyMapMatrix[KEYPAD_MAXY][KEYPAD_MAXX] = { - { "1", "2", "3", "A", "E" }, - { "4", "5", "6", "B", "F" }, - { "7", "8", "9", "C", "G" }, - { "*", "0", "#", "D", "H" }, - { NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL }}; + {"1", "2", "3", "A", "E"}, + {"4", "5", "6", "B", "F"}, + {"7", "8", "9", "C", "G"}, + {"*", "0", "#", "D", "H"}, + {NULL, NULL, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL}}; - -// Vars for the server core -MODULE_EXPORT char * api_version = API_VERSION; +/* Vars for the server core */ +MODULE_EXPORT char *api_version = API_VERSION; MODULE_EXPORT int stay_in_foreground = 0; -MODULE_EXPORT int supports_multiple = 1; // yes, we have no global variables (except for constants) +MODULE_EXPORT int supports_multiple = 1; MODULE_EXPORT char *symbol_prefix = "sed1330_"; -// Local functions -//void uPause (int usecs); -void sed1330_command( PrivateData * p, char command, int datacount, unsigned char * data ); -void sed1330_rect( PrivateData * p, int x1, int y1, int x2, int y2, char pattern ); -void sed1330_line ( PrivateData * p, int x1, int y1, int x2, int y2, char pattern ); -inline void sed1330_set_pixel( PrivateData * p, int x, int y, int value ); -unsigned char sed1330_scankeypad(PrivateData *p); -unsigned char sed1330_readkeypad (PrivateData *p, unsigned int YData); +/* Local functions */ +void sed1330_command(PrivateData * p, char command, int datacount, unsigned char *data); +void sed1330_rect(PrivateData * p, int x1, int y1, int x2, int y2, char pattern); +inline void sed1330_set_pixel(PrivateData * p, int x, int y, int value); +unsigned char sed1330_scankeypad(PrivateData * p); +unsigned char sed1330_readkeypad(PrivateData * p, unsigned int YData); -///////////////////////////////////////////////////////////////// -// Init the driver and display -// +/** + * API: Init the driver and display + */ MODULE_EXPORT int -sed1330_init( Driver * drvthis ) +sed1330_init(Driver * drvthis) { const char *s; - PrivateData * p; + PrivateData *p; unsigned char data[8]; debug(RPT_DEBUG, "%s( %p )", __FUNCTION__, drvthis); - // Alocate and store private p + /* Allocate and store private data */ p = (PrivateData *) calloc(1, sizeof(PrivateData)); if (p == NULL) return -1; if (drvthis->store_private_ptr(drvthis, p)) return -1; - // initialize PrivateData + /* initialize PrivateData */ p->framebuf_text = NULL; p->lcd_contents_text = NULL; p->framebuf_graph = NULL; p->lcd_contents_graph = NULL; - // READ THE CONFIG FILE + /* READ THE CONFIG FILE */ - // Port + /* Port. Default: 0x278 (second parallel port!) */ p->port = drvthis->config_get_int(drvthis->name, "Port", 0, 0x278); - // Char size + /* Char size */ s = drvthis->config_get_string(drvthis->name, "CellSize", 0, "6x10"); if (sscanf(s, "%dx%d", &(p->cellwidth), &(p->cellheight)) != 2) { report(RPT_ERR, "%s: cannot interpret CellSize %s", - drvthis->name, s); + drvthis->name, s); return -1; } if ((p->cellwidth < 6) || (p->cellwidth > 8) - || (p->cellheight < 7) || (p->cellheight > 16)) { + || (p->cellheight < 7) || (p->cellheight > 16)) { report(RPT_ERR, "%s: CellSize exceeds allowed range of 6x7 to 8x16", - drvthis->name); + drvthis->name); return -1; } - // Type + /* Type */ s = drvthis->config_get_string(drvthis->name, "Type", 0, NULL); if (s == NULL) { report(RPT_ERR, "%s: you need to specify the display type", - drvthis->name); + drvthis->name); return -1; - } else if (strcmp(s, "G321D") == 0) { + } + else if (strcmp(s, "G321D") == 0) { p->type = TYPE_G321D; p->graph_width = 320; p->graph_height = 200; - } else if (strcmp(s, "G121C") == 0) { + } + else if (strcmp(s, "G121C") == 0) { p->type = TYPE_G121C; p->graph_width = 128; p->graph_height = 128; - } else if (strcmp(s, "G242C") == 0) { + } + else if (strcmp(s, "G242C") == 0) { p->type = TYPE_G242C; p->graph_width = 240; p->graph_height = 128; - } else if (strcmp(s, "G191D") == 0) { + } + else if (strcmp(s, "G191D") == 0) { p->type = TYPE_G191D; p->graph_width = 192; p->graph_height = 192; - } else if (strcmp(s, "G2446") == 0) { + } + else if (strcmp(s, "G2446") == 0) { p->type = TYPE_G2446; p->graph_width = 240; p->graph_height = 64; - } else if(strcmp(s, "SP14Q002") == 0) { + } + else if (strcmp(s, "SP14Q002") == 0) { p->type = TYPE_SP14Q002; p->graph_width = 320; p->graph_height = 240; - } else if(strcmp(s, "HG25504") == 0) { + } + else if (strcmp(s, "HG25504") == 0) { p->type = TYPE_HG25504; p->graph_width = 256; p->graph_height = 128; - } else { + } + else { report(RPT_ERR, "%s: Unknown display type %s", drvthis->name, s); return -1; } report(RPT_INFO, "%s: Using LCD type %s", drvthis->name, s); - // Set wiring scheme to be used - // - // Valid ConnectionTypes: - // - classic (default) - // - bitshaker - // - // Get ConnectionType, if no type is set, default to "classic" wiring so it even - // works with config files missing that ConnectionType entry in sed1330 driver section + /* + * Get ConnectionType, if no type is set, default to "classic" wiring + * so it even works with config files missing that ConnectionType entry + * in sed1330 driver section. + */ s = drvthis->config_get_string(drvthis->name, "ConnectionType", 0, "classic"); - // Set wiring initialization parameters based on ConnectionType + /* Set wiring initialization parameters based on ConnectionType */ if (strcmp(s, "classic") == 0) { - // Use classic wiring - p->A0 = SEL; // port 17 - p->nRESET = STRB; // port 1 - p->nWR = INIT; // port 16 - } else if(strcmp(s, "bitshaker") == 0) { - // Use bitshaker wiring - p->A0 = nLF; // port 14 - p->nRESET = INIT; // port 16 - p->nWR = STRB; // port 1 - } else { + p->A0 = SEL; /* port 17 */ + p->nRESET = STRB; /* port 1 */ + p->nWR = INIT; /* port 16 */ + } + else if (strcmp(s, "bitshaker") == 0) { + p->A0 = nLF; /* port 14 */ + p->nRESET = INIT; /* port 16 */ + p->nWR = STRB; /* port 1 */ + } + else { report(RPT_ERR, "%s: Unknown ConnectionType %s", drvthis->name, s); return -1; } report(RPT_INFO, "%s: Using ConnectionType %s", drvthis->name, s); - // Keypad ? + /* Is a keypad attached? Default: no */ p->have_keypad = drvthis->config_get_bool(drvthis->name, "keypad", 0, 0); - // Keymap + /* Set up keymap */ if (p->have_keypad) { int x, y; - // Read keymap + /* Set up direct keys first */ for (x = 0; x < KEYPAD_MAXX; x++) { char buf[40]; - // First fill with default value + /* First fill with default value */ p->keyMapDirect[x] = defaultKeyMapDirect[x]; - // Read config value - sprintf(buf, "keydirect_%1d", x+1); + /* Read config value */ + sprintf(buf, "keydirect_%1d", x + 1); s = drvthis->config_get_string(drvthis->name, buf, 0, NULL); - // Was a key specified in the config file ? + /* Was a key specified in the config file ? */ if (s != NULL) { p->keyMapDirect[x] = strdup(s); report(RPT_INFO, "%s: Direct key %d: \"%s\"", - drvthis->name, x, s ); + drvthis->name, x, s); } } + /* Then set up matrix keys */ for (x = 0; x < KEYPAD_MAXX; x++) { for (y = 0; y < KEYPAD_MAXY; y++) { char buf[40]; - // First fill with default value + /* First fill with default value */ p->keyMapMatrix[y][x] = defaultKeyMapMatrix[y][x]; - // Read config value - sprintf(buf, "keymatrix_%1d_%d", x+1, y+1); + /* Read config value */ + sprintf(buf, "keymatrix_%1d_%d", x + 1, y + 1); s = drvthis->config_get_string(drvthis->name, buf, 0, NULL); - // Was a key specified in the config file ? + /* Was a key specified in the config file ? */ if (s != NULL) { p->keyMapMatrix[y][x] = strdup(s); report(RPT_INFO, "%s: Matrix key %d,%d: \"%s\"", - drvthis->name, x, y, s); + drvthis->name, x, y, s); } } } } - // Calculate some sizes + /* Calculate some sizes */ p->width = p->graph_width / p->cellwidth; p->height = p->graph_height / p->cellheight; p->bytesperline = (p->graph_width - 1) / p->cellwidth + 1; @@ -526,111 +365,122 @@ sed1330_init( Driver * drvthis ) report(RPT_INFO, "%s: Cell size: %dx%d", drvthis->name, p->cellwidth, p->cellheight); report(RPT_INFO, "%s: Graphical size: %dx%d", drvthis->name, p->graph_width, p->graph_height); - // Allocate framebuffer - p->framebuf_text = (unsigned char *) malloc(p->bytesperline * p->textlines_in_memory); + /* Allocate and clear framebuffers for text and graphic */ + p->framebuf_text = (unsigned char *)malloc(p->bytesperline * p->textlines_in_memory); if (p->framebuf_text == NULL) { report(RPT_ERR, "%s: error allocating text framebuffer", drvthis->name); return -1; } memset(p->framebuf_text, ' ', p->bytesperline * p->textlines_in_memory); - p->lcd_contents_text = (unsigned char *) malloc(p->bytesperline * p->textlines_in_memory); + p->lcd_contents_text = (unsigned char *)malloc(p->bytesperline * p->textlines_in_memory); if (p->lcd_contents_text == NULL) { report(RPT_ERR, "%s: error allocating lcd_contents_text", drvthis->name); return -1; } memset(p->lcd_contents_text, 0, p->bytesperline * p->textlines_in_memory); - p->framebuf_graph = (unsigned char *) malloc(p->bytesperline * p->graph_height); + p->framebuf_graph = (unsigned char *)malloc(p->bytesperline * p->graph_height); if (p->framebuf_graph == NULL) { report(RPT_ERR, "%s: error allocating graphical framebuffer", drvthis->name); return -1; } memset(p->framebuf_graph, 0, p->bytesperline * p->graph_height); - p->lcd_contents_graph = (unsigned char *) malloc(p->bytesperline * p->graph_height); + p->lcd_contents_graph = (unsigned char *)malloc(p->bytesperline * p->graph_height); if (p->lcd_contents_graph == NULL) { report(RPT_ERR, "%s: error allocating lcd_contents_graph", drvthis->name); return -1; } memset(p->lcd_contents_graph, 0xFF, p->bytesperline * p->graph_height); - // Arrange for access to port + /* Arrange for access to port */ debug(RPT_DEBUG, "%s: getting port access", __FUNCTION__); - if (port_access_multiple(p->port,3)) { + if (port_access_multiple(p->port, 3)) { report(RPT_ERR, "%s: cannot get IO-permission for 0x%03X: %s", - drvthis->name, p->port, strerror(errno)); + drvthis->name, p->port, strerror(errno)); return -1; } if (timing_init() == -1) { report(RPT_ERR, "%s: timing_init() failed (%s)", - drvthis->name, strerror(errno)); + drvthis->name, strerror(errno)); return -1; } - // INITIALIZE THE LCD - // End reset-state + /* INITIALIZE THE LCD */ + + /* End reset-state */ debug(RPT_DEBUG, "%s: initializing LCD", __FUNCTION__); - port_out(p->port+2, (p->nWR) ^ OUTMASK); // raise ^RD and ^WR - port_out(p->port+2, (p->nRESET|p->nWR) ^ OUTMASK); // lower RESET + port_out(p->port+2, (p->nWR) ^ OUTMASK); /* raise ^WR */ + port_out(p->port+2, (p->nRESET | p->nWR) ^ OUTMASK); /* lower RESET */ uPause(200); - port_out(p->port+2, (p->nWR) ^ OUTMASK); // raise RESET + port_out(p->port+2, (p->nWR) ^ OUTMASK); /* raise RESET */ uPause(200); - port_out(p->port+2, (p->nRESET|p->nWR) ^ OUTMASK); // lower RESET + port_out(p->port+2, (p->nRESET | p->nWR) ^ OUTMASK); /* lower RESET */ uPause(4000); switch (p->type) { - case TYPE_G321D: + case TYPE_G321D: data[4] = 0x38; break; - case TYPE_SP14Q002: + case TYPE_SP14Q002: data[4] = 0x38; break; - case TYPE_G121C: - data[4] = 0x7F; // ? please confirm these numbers + case TYPE_G121C: + data[4] = 0x7F; /* ? FIXME: please confirm these numbers */ break; - case TYPE_G242C: - data[4] = 0x7F; // ? + case TYPE_G242C: + data[4] = 0x7F; /* ? */ break; - case TYPE_G2446: - data[4] = 0x7F; // ? + case TYPE_G2446: + data[4] = 0x7F; /* ? */ break; - case TYPE_G191D: - data[4] = 0x5c; // ? + case TYPE_G191D: + data[4] = 0x5c; /* ? */ break; - case TYPE_HG25504: - data[4] = 0x7F; // Confirmed + case TYPE_HG25504: + data[4] = 0x7F; /* Confirmed! */ break; - default: + default: return -1; } - data[0] = 0x30; - data[1] = 0x80 + p->cellwidth - 1; + /* Prepare and send SYSTEM SET command */ + data[0] = 0x30; /* Int. CGROM, no D6 cor., 8-pixel height, single-panel */ + data[1] = 0x80 + p->cellwidth - 1; /* two-frame AC drive, cellwidth */ data[2] = p->cellheight - 1; - data[3] = p->width - 1; - // data[4] should be filled already - // TC/R = ((clock / (refresh * (L/F - 1))) - 1) / 9 - data[5] = p->graph_height - 1; - data[6] = p->bytesperline; - data[7] = 0; + data[3] = p->width - 1; /* C/R: address range by one display line */ + /* data[4] should be filled already */ + /* C/R = ((clock / (refresh * (L/F - 1))) - 1) / 9 */ + data[5] = p->graph_height - 1; /* L/F: frame height */ + data[6] = p->bytesperline; /* APL: horizontal address range low */ + data[7] = 0; /* APH: horizontal address range high */ sed1330_command(p, CMD_SYSTEM_SET, 8, data); - // TODO: The memory locations need to be calculated ! - sed1330_command(p, CMD_SCROLL, 6, ((unsigned char[6]) {SCR1_L,SCR1_H,0xC7,SCR2_L,SCR2_H,0xC7})); // screen1 and screen2 memory locations + /* Set screen1 and screen2 memory locations */ + /* FIXME: The memory locations need to be calculated! */ + sed1330_command(p, CMD_SCROLL, 6, ((unsigned char[6]) {SCR1_L, SCR1_H, 0xC7, SCR2_L, SCR2_H, 0xC7})); - data[0] = p->cellwidth-1; - data[1] = 7; - sed1330_command(p, CMD_CSR_FORM, 2, data); // set cursor size + /* Prepare and send 'set cursor size' command */ + data[0] = p->cellwidth - 1; + data[1] = 7; /* underscore type, 8 pixels high */ + sed1330_command(p, CMD_CSR_FORM, 2, data); - sed1330_command(p, CMD_HDOT_SCR, 1, ((unsigned char[1]) {0x00})); // horizontal pixel shift=0 - sed1330_command(p, CMD_OVLAY, 1, ((unsigned char[1]) {0x01})); // XOR mode, screen1 text, screen3 text (screen2 and screen4 are always graph) - sed1330_command(p, CMD_DISP_DIS, 1, ((unsigned char[1]) {0x14})); // display off,set cursor off, screen1 on, screen2 on, screen3 off - sed1330_command(p, CMD_CSR_DIR_R, 0, NULL); // cursor move right + /* horizontal pixel shift=0 */ + sed1330_command(p, CMD_HDOT_SCR, 1, ((unsigned char[1]) {0x00})); + /* + * XOR mode, set screen1 and screen3 as text (screen2 and screen4 are + * always graphic) + */ + sed1330_command(p, CMD_OVLAY, 1, ((unsigned char[1]) {0x01})); + /* set display off, cursor off, screen1 on, screen2 on, screen3 off */ + sed1330_command(p, CMD_DISP_DIS, 1, ((unsigned char[1]) {0x14})); + /* set cursor move right */ + sed1330_command(p, CMD_CSR_DIR_R, 0, NULL); - sed1330_flush(drvthis); // Clear the contents of the LCD - sed1330_command(p, CMD_DISP_EN, 0, NULL); // And display on + sed1330_flush(drvthis); + sed1330_command(p, CMD_DISP_EN, 0, NULL); /* And display on */ report(RPT_DEBUG, "%s: init() done", drvthis->name); @@ -638,37 +488,41 @@ sed1330_init( Driver * drvthis ) } -///////////////////////////////////////////////////////////////// -// Send a command and accompanying p -// INTERNAL -// +/** + * Send a command and optionally accompanying data. + * \param p Pointer to private data + * \param command Command byte + * \param datacount Number of data bytes to send + * \param data Pointer to data buffer + */ void -sed1330_command( PrivateData * p, char command, int datacount, unsigned char * data ) +sed1330_command(PrivateData * p, char command, int datacount, unsigned char *data) { int i; int port = p->port; - port_out(port+2, (p->nRESET|p->nWR|p->A0) ^ OUTMASK); // set A0 to indicate command - port_out(port, command); // set up p - port_out(port+2, (p->nRESET|p->A0) ^ OUTMASK); // activate ^WR - port_out(port+2, (p->nRESET|p->nWR|p->A0) ^ OUTMASK); // deactivate ^WR again - port_out(port+2, (p->nRESET|p->nWR) ^ OUTMASK); // clear A0 to indicate p + port_out(port+2, (p->nRESET | p->nWR | p->A0) ^ OUTMASK); /* set A0 to indicate command */ + port_out(port, command); /* set up command */ + port_out(port+2, (p->nRESET | p->A0) ^ OUTMASK); /* lower ^WR */ + port_out(port+2, (p->nRESET | p->nWR | p->A0) ^ OUTMASK); /* rise ^WR again */ + port_out(port+2, (p->nRESET | p->nWR) ^ OUTMASK); /* clear A0 to indicate data */ + /* Optionally output data */ for (i = 0; i < datacount; i++) { - port_out(port, data[i]); // set up data - port_out(port+2, (p->nRESET) ^ OUTMASK); // activate ^WR - port_out(port+2, (p->nRESET|p->nWR) ^ OUTMASK); // deactivate ^WR again + port_out(port, data[i]); /* set up data */ + port_out(port + 2, (p->nRESET) ^ OUTMASK); /* lower ^WR */ + port_out(port + 2, (p->nRESET | p->nWR) ^ OUTMASK); /* rise ^WR again */ } } -///////////////////////////////////////////////////////////////// -// Close the display -// +/** + * API: Close the display + */ MODULE_EXPORT void -sed1330_close( Driver * drvthis ) +sed1330_close(Driver * drvthis) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s()", __FUNCTION__); @@ -699,13 +553,13 @@ sed1330_close( Driver * drvthis ) } -///////////////////////////////////////////////////////////////// -// Returns the display width -// +/** + * API: Returns the display width + */ MODULE_EXPORT int -sed1330_width( Driver * drvthis ) +sed1330_width(Driver * drvthis) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_INFO, "%s()", __FUNCTION__); @@ -713,13 +567,13 @@ sed1330_width( Driver * drvthis ) } -///////////////////////////////////////////////////////////////// -// Returns the display height -// +/** + * API: Returns the display height + */ MODULE_EXPORT int -sed1330_height( Driver * drvthis ) +sed1330_height(Driver * drvthis) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_INFO, "%s()", __FUNCTION__); @@ -733,9 +587,9 @@ sed1330_height( Driver * drvthis ) * \return Number of pixel columns a character cell is wide. */ MODULE_EXPORT int -sed1330_cellwidth(Driver *drvthis) +sed1330_cellwidth(Driver * drvthis) { -PrivateData *p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s: returning cellwidth", drvthis->name); @@ -749,9 +603,9 @@ PrivateData *p = drvthis->private_data; * \return Number of pixel lines a character cell is high. */ MODULE_EXPORT int -sed1330_cellheight(Driver *drvthis) +sed1330_cellheight(Driver * drvthis) { -PrivateData *p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s: returning cellheight", drvthis->name); @@ -759,13 +613,13 @@ PrivateData *p = drvthis->private_data; } -///////////////////////////////////////////////////////////////// -// Clear the framebuffer -// +/** + * API: Clear the framebuffers + */ MODULE_EXPORT void -sed1330_clear( Driver * drvthis ) +sed1330_clear(Driver * drvthis) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s()", __FUNCTION__); @@ -774,79 +628,81 @@ sed1330_clear( Driver * drvthis ) } -///////////////////////////////////////////////////////////////// -// Place a string in the framebuffer -// +/** + * API: Place a string in the (text) framebuffer + */ MODULE_EXPORT void -sed1330_string( Driver * drvthis, int x, int y, char *str ) +sed1330_string(Driver * drvthis, int x, int y, char *str) { - PrivateData * p = drvthis->private_data; - unsigned char * dest; + PrivateData *p = drvthis->private_data; + unsigned char *dest; int offset, len; debug(RPT_DEBUG, "%s( x=%d, y=%d, str=\"%s\" )", __FUNCTION__, x, y, str); if ((y < 1) || (y > p->height)) { - return; // outside framebuf + return; /* outside framebuf */ } - // Calculate offset and length to write + + /* Calculate offset and length to write */ if (x < 1) { offset = (1 - x); x = 1; - } else { + } + else { offset = 0; } len = strlen(str) - offset; if (len > p->width - x + 1) { len = p->width - x + 1; } - // Calculate destination address - dest = p->framebuf_text + (y-1)*p->bytesperline + (x-1); - // And write + /* Calculate destination address */ + dest = p->framebuf_text + (y - 1) * p->bytesperline + (x - 1); + + /* And write */ memcpy(dest, str, len); } -///////////////////////////////////////////////////////////////// -// Place a character in the framebuffer -// +/** + * API: Place a single character in the text framebuffer + */ MODULE_EXPORT void -sed1330_chr( Driver * drvthis, int x, int y, char c ) +sed1330_chr(Driver * drvthis, int x, int y, char c) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s( x=%d, y=%d, c='%c' )", __FUNCTION__, x, y, c); if ((y < 1) || (y > p->height) || (x < 1) || (x > p->width)) { - return; // outside framebuf + return; /* outside framebuf */ } - p->framebuf_text[(y-1)*p->bytesperline + (x-1)] = c; + p->framebuf_text[(y - 1) * p->bytesperline + (x - 1)] = c; } -///////////////////////////////////////////////////////////////// -// Flush the framebuffer to the display -// +/** + * API: Flush the framebuffer to the display. On call to this function + * both framebuffers (text and graphic) are written to the display. + */ MODULE_EXPORT void -sed1330_flush( Driver * drvthis ) +sed1330_flush(Driver * drvthis) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; unsigned int pos, start_pos, nr_equal, fblen, len, cursor_pos; unsigned char csrloc[2]; debug(RPT_DEBUG, "%s()", __FUNCTION__); - /* sed1330_command(p, CMD_DISP_EN, 1, ((char[1]) {0x14})); // cursor off */ - // TODO: Flickering here needs to be prevented - fblen = p->bytesperline * p->textlines_in_memory; - for (pos = 0; pos < fblen; ) { + for (pos = 0; pos < fblen;) { start_pos = pos; - for (nr_equal = 0; poslcd_contents_text[pos] == p->framebuf_text[pos]) { - nr_equal ++; - } else { + nr_equal++; + } + else { nr_equal = 0; } } @@ -862,12 +718,13 @@ sed1330_flush( Driver * drvthis ) } fblen = p->bytesperline * p->graph_height; - for (pos = 0; pos < fblen; ) { + for (pos = 0; pos < fblen;) { start_pos = pos; for (nr_equal = 0; pos < fblen && nr_equal < 4; pos++) { if (p->lcd_contents_graph[pos] == p->framebuf_graph[pos]) { - nr_equal ++; - } else { + nr_equal++; + } + else { nr_equal = 0; } } @@ -884,30 +741,21 @@ sed1330_flush( Driver * drvthis ) } -///////////////////////////////////////////////////////////////// -// Sets the backlight on or off -// -MODULE_EXPORT void -sed1330_backlight( Driver * drvthis, int on ) -{ - //PrivateData * p = drvthis->private_data; - - debug(RPT_DEBUG, "%s( on=%d )", __FUNCTION__, on); - // unimplemented -} - - -///////////////////////////////////////////////////////////////// -// Draws a rectangle -// INTERNAL -// +/** + * Draws a rectangle into the graphic framebuffer. + * \param p Pointer to driver's private data + * \param x1 X-coordinate of start point + * \param y1 Y-coordinate of start point + * \param x2 X-coordinate of end point + * \param y2 Y-coordinate of end point + * \param pattern 0 = clear, 1 = set + */ void -sed1330_rect ( PrivateData * p, int x1, int y1, int x2, int y2, char pattern ) -/* pattern: 0=clear 1=set later more patterns ? */ +sed1330_rect(PrivateData * p, int x1, int y1, int x2, int y2, char pattern) { int x, y; - // Swap coordinates if needed + /* Swap coordinates if needed */ if (x1 > x2) { int swap; swap = x1; @@ -928,169 +776,116 @@ sed1330_rect ( PrivateData * p, int x1, int y1, int x2, int y2, char pattern ) } -///////////////////////////////////////////////////////////////// -// Draws a line -// INTERNAL -// -void -sed1330_line ( PrivateData * p, int x1, int y1, int x2, int y2, char pattern ) -/* pattern: 0=clear 1=set later more patterns ? */ -{ - int x, y; - int more_x; - - /* Swap coordinates if needed. We want to draw the line from left - * to right. - */ - if (x1 > x2) { - int swap; - swap = x1; x1 = x2; x2 = swap; - swap = y1; y1 = y2; y2 = swap; - } - - /* Draw from left to right... */ - more_x = 1; - for (x = x1, y = y1; x <= x2; x++) { - int more_y = 1; /* always draw one pixel */ - - while (more_y) { - /* set the pixel */ - sed1330_set_pixel(p, x, y, pattern); - - /* Check what we need to do next */ - if (y1 < y2) { - more_y = (y <= y2); - if (x1 != x2) { - more_y &= ((float)y+0.5-y1) < ((float) x+0.5-x1) * (y2-y1) / ((float) x2-x1) ; - } - } else { - more_y = (y>=y2); - if (x1 != x2) { - more_y &= ((float)y+0.5-y1) > ((float) x+0.5-x1) * (y2-y1) / ((float) x2-x1) ; - } - } - /* Increment y if we should draw a other pixel for this x value */ - if (more_y) { - if (y1 < y2) { - y ++; - } else { - y --; - } - } - } - } -} - - -///////////////////////////////////////////////////////////////// -// Sets a specified pixel -// INTERNAL -// +/** + * Set or clear a single pixel in the graphic framebuffer. + * \param p Pointer to driver's private data + * \param x LCD x coordinate (0-based) + * \param y LCD y coordinate (0-based) + * \param value 0 = clear, 1 = set + */ inline void -sed1330_set_pixel( PrivateData * p, int x, int y, int value ) -/* x, y are graph LCD coordinates, 0-based */ -/* value: 0=clear 1=set */ +sed1330_set_pixel(PrivateData * p, int x, int y, int value) { unsigned int bytepos; char bitmask; - bytepos = y*p->bytesperline + x/p->cellwidth; + bytepos = y * p->bytesperline + x / p->cellwidth; bitmask = 0x80 >> (x % p->cellwidth); if (value) { - p->framebuf_graph[bytepos] |= bitmask; /* set it */ - } else { - p->framebuf_graph[bytepos] &= ~bitmask; /* clear it */ + p->framebuf_graph[bytepos] |= bitmask; /* set it */ + } + else { + p->framebuf_graph[bytepos] &= ~bitmask; /* clear it */ } } -///////////////////////////////////////////////////////////////// -// Draws a vertical bar at the bottom -// +/** + * API: Draws a vertical bar at the bottom. Internally this in implemented by + * drawing a filled rectangle to the graphic framebuffer. + */ MODULE_EXPORT void -sed1330_vbar( Driver * drvthis, int x, int y, int len, int promille, int pattern ) +sed1330_vbar(Driver * drvthis, int x, int y, int len, int promille, int pattern) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s( x=%d, y=%d, len=%d, promille=%d, pattern=%d )", __FUNCTION__, x, y, len, promille, pattern); - sed1330_rect(p, (x-1) * p->cellwidth, y * p->cellheight, - x * p->cellwidth - 2, y * p->cellheight - (long) len * p->cellheight * promille / 1000 - 1, 1); + sed1330_rect(p, (x - 1) * p->cellwidth, y * p->cellheight, + x * p->cellwidth - 2, y * p->cellheight - (long)len * p->cellheight * promille / 1000 - 1, 1); } -///////////////////////////////////////////////////////////////// -// Draws a horizontal bar to the right (len=pos) -// or to the left (len=neg) -// +/** + * API: Draws a horizontal bar to the right (len=pos) or to the left (len=neg). + * Internally this in implemented by drawing a filled rectangle to the graphic + * framebuffer. + */ MODULE_EXPORT void -sed1330_hbar( Driver * drvthis, int x, int y, int len, int promille, int pattern ) +sed1330_hbar(Driver * drvthis, int x, int y, int len, int promille, int pattern) { - PrivateData * p = drvthis->private_data; + PrivateData *p = drvthis->private_data; debug(RPT_DEBUG, "%s( x=%d, y=%d, len=%d, promille=%d, pattern=%d )", __FUNCTION__, x, y, len, promille, pattern); - sed1330_rect(p, (x-1) * p->cellwidth, (y-1) * p->cellheight, - (x-1) * p->cellwidth + (long) len * p->cellwidth * promille / 1000 - 1, y * p->cellheight - 3, 1); + sed1330_rect(p, (x - 1) * p->cellwidth, (y - 1) * p->cellheight, + (x - 1) * p->cellwidth + (long)len * p->cellwidth * promille / 1000 - 1, y * p->cellheight - 3, 1); } -///////////////////////////////////////////////////////////////// -// Writes a big number. -// +/** + * API: Writes a big number. + * \note This is currently only a stub and prevents the alternate big + * characters from core to be used. + */ MODULE_EXPORT void -sed1330_num( Driver * drvthis, int x, int y, int num ) +sed1330_num(Driver * drvthis, int x, int y, int num) { //PrivateData * p = drvthis->private_data; debug(RPT_DEBUG, "%s( x=%d, y=%d, num=%d )", __FUNCTION__, x, y, num); - - // TODO: add code here :) } -///////////////////////////////////////////////////////////// -// Does the heartbeat... -// Or in fact a bouncing ball :) -// +/** + * API: Does the heartbeat. + * Or in fact a bouncing ball :) + */ MODULE_EXPORT void -sed1330_heartbeat( Driver * drvthis, int type ) +sed1330_heartbeat(Driver * drvthis, int type) { - PrivateData * p = drvthis->private_data; - static int timer = 0; + PrivateData *p = drvthis->private_data; + static int timer = 0; /* 'timer' for the bouncing ball */ int pos; - //int whichIcon; int n; - //char heartdata[2][CHARHEIGHT] = { - // { 0xFF, 0xFF, 0xAF, 0x07, 0x8F, 0xDF, 0xFF, 0xFF, 0x00, 0x00 }, - // { 0xFF, 0xAF, 0x07, 0x07, 0x07, 0x8F, 0xDF, 0xFF, 0x00, 0x00 } - //}; - char bouncing_ball[8][8] = { - { 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0x87, 0x87, 0xCF }, - { 0xFF, 0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF }, - { 0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0x87, 0x87, 0x87, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0x87, 0x87, 0x87, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF, 0xFF }, - { 0xFF, 0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF }, + static char bouncing_ball[8][8] = { + {0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0x87, 0x87, 0xCF}, + {0xFF, 0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF}, + {0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x87, 0x87, 0x87, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0x87, 0x87, 0x87, 0xFF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF, 0xFF}, + {0xFF, 0xFF, 0xCF, 0x87, 0x87, 0xCF, 0xFF, 0xFF}, }; debug(RPT_DEBUG, "%s( type=%d )", __FUNCTION__, type); + /* Do nothing if heartbeat is disabled */ if (type == HEARTBEAT_OFF) return; - p->framebuf_text[p->width-1] = ' '; - //whichIcon = (! ((timer + 4) & 5)); + pos = p->width - 1; /* Draw into top right corner */ + p->framebuf_text[pos] = ' '; /* Clear the text framebuffer there */ - pos = p->width - 1; + /* Draw the bouncing ball based on timer into graphic framebuffer */ for (n = 0; n < p->cellheight; n++) { - //p->framebuf_graph[pos] = heartdata[whichIcon][n]; + /* We only have data for 8 rows */ if (n < 8) { p->framebuf_graph[pos] = bouncing_ball[timer][n]; - } else { + } + else { p->framebuf_graph[pos] = 0; } pos += p->bytesperline; @@ -1101,82 +896,92 @@ sed1330_heartbeat( Driver * drvthis, int type ) } -///////////////////////////////////////////////////////////// -// Place an icon -// +/** + * API: Place an icon on the screen. Currently no icons are supported except + * ICON_BLOCK_FILLED. + */ MODULE_EXPORT int -sed1330_icon( Driver * drvthis, int x, int y, int icon ) +sed1330_icon(Driver * drvthis, int x, int y, int icon) { switch (icon) { - case ICON_BLOCK_FILLED: + case ICON_BLOCK_FILLED: sed1330_chr(drvthis, x, y, 255); break; - default: + default: return -1; } return 0; } -///////////////////////////////////////////////////////////// -// Get a key from the keypad (if there is one) -// +/** + * API: Get a key from the keypad (if there is one) + */ MODULE_EXPORT const char * -sed1330_get_key(Driver *drvthis) +sed1330_get_key(Driver * drvthis) { PrivateData *p = (PrivateData *) drvthis->private_data; unsigned char scancode; - char * keystr = NULL; + char *keystr = NULL; struct timeval curr_time, time_diff; if (!p->have_keypad) return NULL; - gettimeofday(&curr_time,NULL); + gettimeofday(&curr_time, NULL); + /* Get the key! */ scancode = sed1330_scankeypad(p); if (scancode) { if (scancode & 0xF0) { - keystr = p->keyMapMatrix[((scancode&0xF0)>>4)-1][(scancode&0x0F)-1]; + keystr = p->keyMapMatrix[((scancode & 0xF0) >> 4) - 1][(scancode & 0x0F) - 1]; } else { keystr = p->keyMapDirect[scancode - 1]; } } + /* Check if a new or repeated key press event is to be reported */ if (keystr != NULL) { if (keystr == p->pressed_key) { - timersub (&curr_time, &(p->pressed_key_time), &time_diff); + timersub(&curr_time, &(p->pressed_key_time), &time_diff); if (((time_diff.tv_usec / 1000 + time_diff.tv_sec * 1000) - KEYPAD_AUTOREPEAT_DELAY) < 1000 * p->pressed_key_repetitions / KEYPAD_AUTOREPEAT_FREQ) { - // The key is already pressed quite some time - // but it's not yet time to return a repeated keypress + /* + * The key is already pressed quite some time + * but it's not yet time to return a repeated + * keypress + */ return NULL; } - // Otherwise a keypress will be returned - p->pressed_key_repetitions ++; + /* Otherwise a keypress will be returned */ + p->pressed_key_repetitions++; } else { - // It's a new keypress + /* It's a new keypress */ p->pressed_key_time = curr_time; p->pressed_key_repetitions = 0; report(RPT_INFO, "%s: Key pressed: %s (%d,%d)", - drvthis->name, keystr, scancode&0x0F, (scancode&0xF0)>>4); + drvthis->name, keystr, scancode & 0x0F, (scancode & 0xF0) >> 4); } } - // Store the key for the next round + /* Store the key for the next round */ p->pressed_key = keystr; return keystr; } -///////////////////////////////////////////////////////////// -// Scan the keypad -// -// Called by get_key -// -unsigned char sed1330_scankeypad(PrivateData *p) +/** + * Scan the keypad. This is identical in function to the scankeypad function + * in hd44780.c (except it does not have connection type specific low-level + * read function), so read there for a complete description of this algorithm. + * + * \param p Pointer to PrivateData structure. + * \return Scancode of the key. + */ +unsigned char +sed1330_scankeypad(PrivateData * p) { unsigned int keybits; unsigned int shiftcount; @@ -1187,81 +992,70 @@ unsigned char sed1330_scankeypad(PrivateData *p) unsigned char scancode = 0; - // First check if a directly connected key is pressed - // Put all zeros on Y of keypad - keybits = sed1330_readkeypad (p, 0); + keybits = sed1330_readkeypad(p, 0); if (keybits) { - // A directly connected key was pressed - // Which key was it ? shiftingbit = 1; for (shiftcount = 0; shiftcount < KEYPAD_MAXX && !scancode; shiftcount++) { if (keybits & shiftingbit) { - // Found ! Return from function. - scancode = shiftcount+1; + scancode = shiftcount + 1; } shiftingbit <<= 1; } } else { - // Now check the matrix - // First check with all 1's Ypattern = (1 << KEYPAD_MAXY) - 1; + if (sed1330_readkeypad(p, Ypattern)) { - // Yes, a key on the matrix is pressed - - // OK, now we know a key is pressed. - // Determine which one it is - - // First determine the row - // Do a 'binary search' to minimize I/O Ypattern = 0; Yval = 0; for (exp = 3; exp >= 0; exp--) { Ypattern = ((1 << (1 << exp)) - 1) << Yval; - keybits = sed1330_readkeypad (p, Ypattern); + keybits = sed1330_readkeypad(p, Ypattern); if (!keybits) { Yval += (1 << exp); } } - // Which key is pressed in that row ? keybits = sed1330_readkeypad(p, 1 << Yval); shiftingbit = 1; for (shiftcount = 0; shiftcount < KEYPAD_MAXX && !scancode; shiftcount++) { if (keybits & shiftingbit) { - // Found ! - scancode = (Yval+1) << 4 | (shiftcount+1); + scancode = (Yval + 1) << 4 | (shiftcount + 1); } shiftingbit <<= 1; } } } + return scancode; } -///////////////////////////////////////////////////////////// -// Read a keypad byte -// -// Called by scankeypad -// -unsigned char sed1330_readkeypad (PrivateData *p, unsigned int YData) +/** + * Read keypress. + * \param p Pointer to driver's private data structure. + * \param YData Bitmap of rows / lines to enable. + * \return Bitmap of the pressed keys. + */ +unsigned char +sed1330_readkeypad(PrivateData * p, unsigned int YData) { unsigned char readval; - // 8 bits output - // Convert the positive logic to the negative logic on the LPT port + /* + * Output 8 bits. Convert the positive logic to the negative logic on + * the LPT port. + */ port_out(p->port, ~YData & 0x00FF); - // Read inputs - readval = ~ port_in (p->port + 1) ^ INMASK; + /* Read inputs */ + readval = ~port_in(p->port + 1) ^ INMASK; - // And convert value back (MSB first). - return (((readval & FAULT) / FAULT <<4) | /* pin 15 */ - ((readval & SELIN) / SELIN <<3) | /* pin 13 */ - ((readval & PAPEREND) / PAPEREND <<2) | /* pin 12 */ - ((readval & BUSY) / BUSY <<1) | /* pin 11 */ + /* And convert value back (MSB first). */ + return (((readval & FAULT) / FAULT << 4) | /* pin 15 */ + ((readval & SELIN) / SELIN << 3) | /* pin 13 */ + ((readval & PAPEREND) / PAPEREND << 2) | /* pin 12 */ + ((readval & BUSY) / BUSY << 1) | /* pin 11 */ ((readval & ACK) / ACK)) & ~p->stuckinputs; /* pin 10 */ } - diff --git a/server/drivers/sed1330.h b/server/drivers/sed1330.h index 6af4592..47e8353 100644 --- a/server/drivers/sed1330.h +++ b/server/drivers/sed1330.h @@ -1,19 +1,16 @@ -/* - * Driver for SED1330 graphical displays - * Header file +/** \file server/drivers/sed1330.h + * Driver for SED1330/1335 graphical displays. */ #ifndef SED1330_H #define SED1330_H -#include "lcd.h" - MODULE_EXPORT int sed1330_init(Driver *drvthis); MODULE_EXPORT void sed1330_close(Driver *drvthis); MODULE_EXPORT int sed1330_width(Driver *drvthis); MODULE_EXPORT int sed1330_height(Driver *drvthis); -MODULE_EXPORT int sed1330_cellheight(Driver *drvthis); -MODULE_EXPORT int sed1330_cellwidth(Driver *drvthis); +MODULE_EXPORT int sed1330_cellheight(Driver *drvthis); +MODULE_EXPORT int sed1330_cellwidth(Driver *drvthis); MODULE_EXPORT void sed1330_clear(Driver *drvthis); MODULE_EXPORT void sed1330_flush(Driver *drvthis); MODULE_EXPORT void sed1330_string(Driver *drvthis, int x, int y, char lcd[]); @@ -23,10 +20,8 @@ MODULE_EXPORT void sed1330_vbar(Driver *drvthis, int x, int y, int len, int prom MODULE_EXPORT void sed1330_hbar(Driver *drvthis, int x, int y, int len, int promille, int pattern); MODULE_EXPORT void sed1330_num(Driver *drvthis, int x, int y, int num); MODULE_EXPORT void sed1330_heartbeat(Driver *drvthis, int type); -// No cursor function: use software cursor to prevent flickering ! */ MODULE_EXPORT int sed1330_icon(Driver *drvthis, int x, int y, int icon); -MODULE_EXPORT void sed1330_backlight(Driver *drvthis, int on); -MODULE_EXPORT const char * sed1330_get_key(Driver *drvthis); +MODULE_EXPORT const char *sed1330_get_key(Driver *drvthis); #endif