Update pyramid:

- Cache status of LEDs and only send on update, reduces communication
- Add prototypes for all and Doxygen comments to internal functions
- remove unused read_ACK()
This commit is contained in:
mmdolze
2011-02-10 22:53:15 +00:00
parent 565a861d91
commit 2b925d21d6
3 changed files with 115 additions and 111 deletions
+1
View File
@@ -18,6 +18,7 @@ v.0.5dev (ongoing development)
* lcdproc: Make the iface screen more readable on 2x16 displays * lcdproc: Make the iface screen more readable on 2x16 displays
* All drivers: sync functions with prototypes * All drivers: sync functions with prototypes
* Port remaining drivers to 0.5 API (glk, lcdm001, stv5730) * Port remaining drivers to 0.5 API (glk, lcdm001, stv5730)
* Pyramid: Only send LED state changes, doxygen-ize
v0.5.4 v0.5.4
* Update driver includes and LDFLAGS (fixed glk and bayrad binding error) * Update driver includes and LDFLAGS (fixed glk and bayrad binding error)
+93 -108
View File
@@ -49,6 +49,9 @@
* - correct escaping for characters 128-255 (also fixes the 'ß' issue) * - correct escaping for characters 128-255 (also fixes the 'ß' issue)
* - correct icons (custom chars 8-15 cannot be set, checkboxes were wrong) * - correct icons (custom chars 8-15 cannot be set, checkboxes were wrong)
* - Add a delay after set_char. This seems to fix occasional hangs * - Add a delay after set_char. This seems to fix occasional hangs
* - Cache status of LEDs and only send on update, reduces communication
* - Add prototypes for all and Doxygen comments to internal functions
* - remove unused read_ACK()
*/ */
#include <sys/types.h> #include <sys/types.h>
@@ -90,14 +93,21 @@ MODULE_EXPORT char *symbol_prefix = "pyramid_";
/* Prototypes: */ /* Prototypes: */
int send_ACK(PrivateData *); static int data_ready(PrivateData *p);
static int read_tele(PrivateData *p, char *buffer);
static int real_send_tele(PrivateData *p, char *buffer, int len);
static int send_tele(PrivateData *p, char *buffer);
static int send_ACK(PrivateData *p);
static unsigned long long timestamp(PrivateData *p);
static int initTTY(Driver *drvthis, int FD);
/* local functions for pylcd.c */ /* local functions for pylcd.c */
/* Performs an select on the device used. Returns if no data is available at the /**
moment. Used to keep reading-operations from blocking the driver. * Performs an select on the device used. Returns if no data is available at
* the moment. Used to keep reading-operations from blocking the driver.
*/ */
int static int
data_ready(PrivateData *p) data_ready(PrivateData *p)
{ {
FD_ZERO(&p->rdfs); FD_ZERO(&p->rdfs);
@@ -105,12 +115,17 @@ data_ready(PrivateData *p)
return select(p->FD+1, &p->rdfs, NULL, NULL, &p->timeout)>0; return select(p->FD+1, &p->rdfs, NULL, NULL, &p->timeout)>0;
} }
/* Reads one telegramm, stores the telegramm without ETX/STX in buffer
returns True on successful detection of a telegram, False if nothing was read /**
or the telegramm didn't match its CC or if MAXCOUNT was exeeded without * Reads one telegramm, stores the telegramm without ETX/STX in buffer.
reading a complete telegramm. * \param p Pointer to driver's private data
* \param buffer Pointer to memory to store the telegram in. Must be at least
* MAXOUNT size!
* \return True (1) on successful detection of a telegram, False (0) if
* nothing was read or the telegramm didn't match its CC or if
* MAXCOUNT was exeeded without reading a complete telegramm.
*/ */
int static int
read_tele(PrivateData *p, char *buffer) read_tele(PrivateData *p, char *buffer)
{ {
char zeichen=0; char zeichen=0;
@@ -166,27 +181,21 @@ read_tele(PrivateData *p, char *buffer)
} }
} }
/* Wrapper for reading an acknowledge telegramm. /**
*/ * Send the input as telegramm.
int
read_ACK(PrivateData *p)
{
char buffer[MAXCOUNT];
int retval=read_tele(p, buffer);
return (retval && buffer[0]=='Q');
}
/* Send the input as telegramm.
* *
* The telegram buffer just contains the raw telegram data * The telegram buffer just contains the raw telegram data:
* - It shall not contain <STX> and <ETX> marks * - It shall not contain STX and ETX marks.
* - It may contain bytes below 0x20, they are automatically escaped by * - It may contain bytes below 0x20, they are automatically escaped.
* real_sent_tele
* *
* NOTE: This function does not wait for any ACKs. * \param p Pointer to driver's private data
* \param buffer Buffer containing the data to send
* \param len Number of bytes to send from buffer
* \return Always 0
*
* \note This function does not wait for any ACKs.
*/ */
int static int
real_send_tele(PrivateData *p, char *buffer, int len) real_send_tele(PrivateData *p, char *buffer, int len)
{ {
char cc=0x00; char cc=0x00;
@@ -194,11 +203,11 @@ real_send_tele(PrivateData *p, char *buffer, int len)
char buffer2[255]; char buffer2[255];
i=0; j=0; i=0; j=0;
buffer2[j++]=2; // emit <STX> buffer2[j++]=2; /* emit <STX> */
/* copy the whole telegram package and escape /*
* characters below 0x20. * copy the whole telegram package and escape characters below 0x20.
* ie. 0x8 --> <ESC> 0x28 * ie. 0x8 --> <ESC> 0x28.
*/ */
while (len-- && j < 253) { while (len-- && j < 253) {
@@ -209,8 +218,8 @@ real_send_tele(PrivateData *p, char *buffer, int len)
buffer2[j++]=buffer[i++]; buffer2[j++]=buffer[i++];
} }
} }
buffer2[j++]=3; // emit <ETX> buffer2[j++]=3; /* emit <ETX> */
len=j; // new package length len=j; /* new package length */
/* calculate <BCC> over all bytes */ /* calculate <BCC> over all bytes */
for (i=0; i<len; i++) for (i=0; i<len; i++)
@@ -226,30 +235,32 @@ real_send_tele(PrivateData *p, char *buffer, int len)
return 0; return 0;
} }
/* If we know what our telegrams look like, we may use /**
* send_tele instead of real_send_tele. * Send the string given in buffer. The string must be NUL-terminated.
* NOTE: This only works when there are no NULL bytes *
* in the telegram * \param p Pointer to driver's private data
* \param buffer Pointer to the string to send
* \return Always 0
*/ */
static int
int
send_tele(PrivateData *p, char *buffer) send_tele(PrivateData *p, char *buffer)
{ {
return real_send_tele(p, buffer, strlen(buffer)); return real_send_tele(p, buffer, strlen(buffer));
} }
/* Wrapper for sending ACKs via real_send_tele /**
* Sends an acknowledge to the display.
*/ */
int static int
send_ACK(PrivateData *p) send_ACK(PrivateData *p)
{ {
return send_tele(p, "Q"); return send_tele(p, "Q");
} }
/* /**
* Returns the current time in microseconds since the Epoch. * Returns the current time in microseconds since the Epoch.
*/ */
unsigned long long static unsigned long long
timestamp(PrivateData *p) timestamp(PrivateData *p)
{ {
struct timeval tv; struct timeval tv;
@@ -259,9 +270,13 @@ timestamp(PrivateData *p)
} }
/* Sets the serial device, used for communication with the LCD, into raw mode /**
* Sets the serial device, used for communication with the LCD, into raw mode.
* \param drvthis Pointer to driver
* \param FD File descriptor of serial device to configure.
* \return -1 on error, 0 otherwise
*/ */
int static int
initTTY(Driver *drvthis, int FD) initTTY(Driver *drvthis, int FD)
{ {
struct termios tty_mode; struct termios tty_mode;
@@ -288,22 +303,6 @@ initTTY(Driver *drvthis, int FD)
return 0; return 0;
} }
/* This function sets all LEDs according to the private data structure */
int
set_leds(PrivateData *p)
{
int i;
char tele[]="L00";
for (i = 0; i < 7; i++) {
tele[1] = i + '1';
tele[2] = p->led[i] ? '1' : '0';
send_tele(p, tele);
}
return 0;
}
/* Driver functions according to current API-Version */ /* Driver functions according to current API-Version */
@@ -394,23 +393,20 @@ pyramid_init (Driver *drvthis)
send_tele(p, "C0101"); send_tele(p, "C0101");
send_tele(p, "M3"); send_tele(p, "M3");
/* invalidate LED status to make output(0) work */
for (i = 0; i < 7; i++)
p->led[i] = -1;
/* hardware selftest + clear all LEDs */ /* hardware selftest + clear all LEDs */
pyramid_output(drvthis, 0); /* needed, otherwise L11 won't work */
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
p->led[i?i-1:0] = 0; pyramid_output(drvthis, 1 << i);
p->led[i] = 1;
set_leds(p);
usleep(10000); usleep(10000);
} }
for (i = 6; i >= 0; i--) { for (i = 6; i >= 0; i--) {
p->led[i+1] = 0; pyramid_output(drvthis, 1 << i);
p->led[i] = 1;
set_leds(p);
usleep(10000); usleep(10000);
} }
for (i = 0; i < 7; i++) { pyramid_output(drvthis, 0);
p->led[i] = 0;
}
set_leds(p);
report(RPT_DEBUG, "%s: init() done", drvthis->name); report(RPT_DEBUG, "%s: init() done", drvthis->name);
@@ -496,22 +492,24 @@ pyramid_flush (Driver *drvthis)
{ {
memcpy(mesg, p->framebuffer, 33); memcpy(mesg, p->framebuffer, 33);
// we got the japanese HD44780U, so convert the german umlauts and /*
// other stuff * we got the japanese HD44780U, so convert the german umlauts and
* other stuff, assuming input is iso_8859-1.
*/
for (i=1; i<33; i++) { for (i=1; i<33; i++) {
switch ((unsigned char)mesg[i]) { switch ((unsigned char)mesg[i]) {
// assume input is iso_8859-1 case 0xe4: mesg[i]=0xe1; break; /* ä */
case 0xe4: mesg[i]=0xe1; break; // ä case 0xf6: mesg[i]=0xef; break; /* ö */
case 0xf6: mesg[i]=0xef; break; // ö case 0xfc: mesg[i]=0xf5; break; /* ü */
case 0xfc: mesg[i]=0xf5; break; // ü case 0xdf: mesg[i]=0xe2; break; /* ß */
case 0xdf: mesg[i]=0xe2; break; // ß case 0xb7: mesg[i]=0xa5; break; /* · */
case 0xb7: mesg[i]=0xa5; break; // · case 0xb0: mesg[i]=0xdf; break; /* ° */
case 0xb0: mesg[i]=0xdf; break; // °
} }
} }
/* We do not wait for the ACK here, these are read by get_key() */
send_tele(p, "C0101"); send_tele(p, "C0101");
real_send_tele(p, mesg, 33); /* We do not wait for the ACK here*/ real_send_tele(p, mesg, 33);
p->FB_modified=False; p->FB_modified=False;
p->last_buf_time=current_time; p->last_buf_time=current_time;
@@ -594,7 +592,7 @@ MODULE_EXPORT void pyramid_set_char (Driver *drvthis, int n, char *dat)
return; return;
} }
// which character? /* which character? */
tele[1]=n+0x40; tele[1]=n+0x40;
for (row = 0; row < p->cellheight; row++) { for (row = 0; row < p->cellheight; row++) {
@@ -603,9 +601,8 @@ MODULE_EXPORT void pyramid_set_char (Driver *drvthis, int n, char *dat)
pixels <<= 1; pixels <<= 1;
pixels |= (dat[(row * p->cellwidth) + column] != 0); pixels |= (dat[(row * p->cellwidth) + column] != 0);
} }
pixels |= 0x40; // pixel information is transferred with /* pixel information is transferred with an offset of 40h */
// an offset of 40h pixels |= 0x40;
tele[row+2]=pixels; tele[row+2]=pixels;
} }
real_send_tele(p, tele, 10); real_send_tele(p, tele, 10);
@@ -1077,11 +1074,9 @@ pyramid_icon (Driver *drvthis, int x, int y, int icon)
} }
/* /* TODO: Implement this after converting to 8 byte CC.
MODULE_EXPORT void MODULE_EXPORT void
pyramid_num (Driver *drvthis, int x, int num){}; pyramid_num (Driver *drvthis, int x, int num){};
MODULE_EXPORT void
pyramid_heartbeat (Driver *drvthis, int state){};
*/ */
/** /**
@@ -1118,21 +1113,6 @@ pyramid_cursor (Driver *drvthis, int x, int y, int state)
/* Hardware functions */ /* Hardware functions */
#if 0
// all of these are not supported by the display (data sheet)
MODULE_EXPORT int
pyramid_get_contrast (Driver *drvthis){return 0;};
MODULE_EXPORT void
pyramid_set_contrast (Driver *drvthis, int promille){};
MODULE_EXPORT int
pyramid_get_brightness (Driver *drvthis, int state){return 0;};
MODULE_EXPORT void
pyramid_set_brightness (Driver *drvthis, int state, int promille){};
MODULE_EXPORT void
pyramid_backlight (Driver *drvthis, int on)
#endif
/** /**
* Set output port. * Set output port.
* Setting an output port bit lights the associated LED; * Setting an output port bit lights the associated LED;
@@ -1145,11 +1125,16 @@ pyramid_output (Driver *drvthis, int state)
{ {
PrivateData *p = (PrivateData *) drvthis->private_data; PrivateData *p = (PrivateData *) drvthis->private_data;
int i; int i;
char tele[]= {"L00"};
for (i = 0; i < 7; i++) for (i = 0; i < 7; i++) {
p->led[i] = state & (1 << i); if (p->led[i] != (state & (1 << i))) {
p->led[i] = state & (1 << i);
set_leds(p); tele[1] = i + '1';
tele[2] = p->led[i] ? '1' : '0';
send_tele(p, tele);
}
}
if(state & (1 << 8)) { if(state & (1 << 8)) {
pyramid_init_custom1(drvthis); pyramid_init_custom1(drvthis);
@@ -1259,7 +1244,7 @@ pyramid_get_key (Driver *drvthis)
return "Escape+Enter"; return "Escape+Enter";
#endif #endif
return NULL; // Ignore combined key events return NULL; /* Ignore combined key events */
} }
+21 -3
View File
@@ -32,12 +32,10 @@
# include "config.h" # include "config.h"
#endif #endif
#define MAXCOUNT 10 #define MAXCOUNT 10 /* Including terminating NUL */
#define WIDTH 16 #define WIDTH 16
#define HEIGHT 2 #define HEIGHT 2
//Pyramid DS says 16, HD44780U DS says 8
//#define CUSTOMCHARS 16
#define CUSTOMCHARS 8 #define CUSTOMCHARS 8
#define CELLHEIGHT 8 #define CELLHEIGHT 8
@@ -79,5 +77,25 @@ typedef struct pyramid_private_data {
} PrivateData; } PrivateData;
MODULE_EXPORT int pyramid_init (Driver *drvthis);
MODULE_EXPORT void pyramid_close (Driver *drvthis);
MODULE_EXPORT int pyramid_width (Driver *drvthis);
MODULE_EXPORT int pyramid_height (Driver *drvthis);
MODULE_EXPORT int pyramid_cellwidth (Driver *drvthis);
MODULE_EXPORT int pyramid_cellheight (Driver *drvthis);
MODULE_EXPORT void pyramid_clear (Driver *drvthis);
MODULE_EXPORT void pyramid_flush (Driver *drvthis);
MODULE_EXPORT void pyramid_string (Driver *drvthis, int x, int y, const char string[]);
MODULE_EXPORT void pyramid_chr (Driver *drvthis, int x, int y, char c);
MODULE_EXPORT void pyramid_vbar (Driver *drvthis, int x, int y, int len, int promille, int options);
MODULE_EXPORT void pyramid_hbar (Driver *drvthis, int x, int y, int len, int promille, int options);
MODULE_EXPORT int pyramid_icon (Driver *drvthis, int x, int y, int icon);
MODULE_EXPORT void pyramid_cursor (Driver *drvthis, int x, int y, int state);
MODULE_EXPORT int pyramid_get_free_chars (Driver *drvthis);
MODULE_EXPORT void pyramid_set_char (Driver *drvthis, int n, char *dat);
MODULE_EXPORT void pyramid_output (Driver *drvthis, int state);
MODULE_EXPORT const char * pyramid_get_key (Driver *drvthis);
MODULE_EXPORT const char * pyramid_get_info (Driver *drvthis);
#endif #endif