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:
@@ -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)
|
||||||
|
|||||||
+92
-107
@@ -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++) {
|
||||||
|
if (p->led[i] != (state & (1 << i))) {
|
||||||
p->led[i] = state & (1 << i);
|
p->led[i] = state & (1 << i);
|
||||||
|
tele[1] = i + '1';
|
||||||
set_leds(p);
|
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
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user