HD44780 update:
- supports new API - major clean up, more consistent code - uses configfile options - serialLpt works also with only 2 output lines - serialLpt can now use keypad
This commit is contained in:
+323
-282
@@ -25,12 +25,14 @@
|
||||
* Character mapping for correct display of some special ASCII chars added
|
||||
* Sep 2001, Mark Haemmerling <mail@markh.de>.
|
||||
*
|
||||
* Modified October 2001 to read the configfile.
|
||||
*
|
||||
* This file is released under the GNU General Public License. Refer to the
|
||||
* COPYING file distributed with this package.
|
||||
*
|
||||
* Copyright (c) 2000, 1999, 1995 Benjamin Tse <blt@Comports.com>
|
||||
* 2001 Joris Robijn <joris@robijn.net>
|
||||
* 2001 Mark Haemmerling <mail@markh.de>
|
||||
* 2001 Mark Haemmerling <mail@markh.de>
|
||||
* 2000 Charles Steinkuehler <cstein@newtek.com>
|
||||
* 1999 Andrew McMeikan <andrewm@engineer.com>
|
||||
* 1998 Richard Rognlie <rrognlie@gamerz.net>
|
||||
@@ -48,8 +50,6 @@
|
||||
#endif
|
||||
#include "port.h"
|
||||
|
||||
#define atest(i)
|
||||
|
||||
// Uncomment one of the lines below to select your desired delay generation
|
||||
// mechanism. If both defines are commented, the original I/O read timing
|
||||
// loop is used. Using DELAY_NANOSLEEP seems to provide the best performance.
|
||||
@@ -76,7 +76,7 @@
|
||||
#endif
|
||||
|
||||
#include "shared/str.h"
|
||||
|
||||
#include "render.h"
|
||||
#include "lcd.h"
|
||||
#include "hd44780.h"
|
||||
// #include "drv_base.h"
|
||||
@@ -97,7 +97,7 @@ HD44780_functions *hd44780_functions;
|
||||
|
||||
// default value
|
||||
static enum connectionType connection = HD_4bit;
|
||||
static int connIdx = 0;
|
||||
static int connectiontype_index = 0;
|
||||
|
||||
// spanList[line number] = display line number is in
|
||||
static int *spanList = NULL;
|
||||
@@ -112,15 +112,13 @@ static int numDisplays = 0;
|
||||
// input span list but is kept to save some cpu cycles.
|
||||
static int *dispSizes = NULL;
|
||||
|
||||
// Keypad option
|
||||
// Keypad and backlight option
|
||||
char have_keypad = 0; // off by default
|
||||
// This var is not static, so it's accessable from all sub-drivers
|
||||
char have_backlight = 0; // off by default
|
||||
char extIF = 0; // off by default
|
||||
// These vars is not static, so it's accessable from all sub-drivers
|
||||
// Indeed, this should become cleaner... later...
|
||||
|
||||
// Maximum sizes of the keypad
|
||||
// DO NOT CHANGE THESE 2 VALUES, unless you change the functions too
|
||||
#define KEYPAD_MAXX 5
|
||||
#define KEYPAD_MAXY 11
|
||||
// Autorepeat values
|
||||
#define KEYPAD_AUTOREPEAT_DELAY 500
|
||||
#define KEYPAD_AUTOREPEAT_FREQ 15
|
||||
@@ -132,25 +130,28 @@ static char keyMapDirect[KEYPAD_MAXX] = { 'A', 'B', 'C', 'D', 'E' };
|
||||
// keyMapMatrix contrains an array with arrays of the ascii-codes that should be generated
|
||||
// when a key in the matrix is pressed.
|
||||
static char keyMapMatrix[KEYPAD_MAXY][KEYPAD_MAXX] = {
|
||||
{ '1', '2', '3', 'A', 0 },
|
||||
{ '4', '5', '6', 'B', 0 },
|
||||
{ '7', '8', '9', 'C', 0 },
|
||||
{ '*', '0', '#', 'D', 0 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0 }};
|
||||
{ '1', '2', '3', 'A', 'E' },
|
||||
{ '4', '5', '6', 'B', 'F' },
|
||||
{ '7', '8', '9', 'C', 'G' },
|
||||
{ '*', '0', '#', 'D', 'H' },
|
||||
{ 'I', 'J', 'K', 'L', 'M' },
|
||||
{ 'N', 'O', 'P', 'Q', 'R' },
|
||||
{ 'S', 'T', 'U', 'V', 'W' },
|
||||
{ 'X', 'Y', 'Z', 'a', 'b' },
|
||||
{ 'c', 'd', 'e', 'f', 'g' },
|
||||
{ 'h', 'i', 'j', 'k', 'l' },
|
||||
{ 'm', 'n', 'o', 'p', 'q' }};
|
||||
|
||||
static char pressed_key = 0;
|
||||
static int pressed_key_repetitions = 0;
|
||||
static struct timeval pressed_key_time;
|
||||
|
||||
|
||||
// function declarations
|
||||
void HD44780_close ();
|
||||
void HD44780_flush ();
|
||||
void HD44780_clear ();
|
||||
void HD44780_chr (int x, int y, char ch);
|
||||
void HD44780_string (int x, int y, char *s);
|
||||
void HD44780_flush_box (int lft, int top, int rgt, int bot);
|
||||
void HD44780_backlight (int on);
|
||||
void HD44780_init_vbar ();
|
||||
@@ -159,22 +160,15 @@ void HD44780_vbar (int x, int len);
|
||||
void HD44780_hbar (int x, int y, int len);
|
||||
void HD44780_init_num ();
|
||||
void HD44780_num (int x, int num);
|
||||
void HD44780_heartbeat (int type);
|
||||
void HD44780_set_char (int n, char *dat);
|
||||
void HD44780_icon (int which, char dest);
|
||||
void HD44780_draw_frame (char *dat);
|
||||
void HD44780_close ();
|
||||
char HD44780_getkey ();
|
||||
|
||||
static void HD44780_linewrap (int on);
|
||||
static void HD44780_autoscroll (int on);
|
||||
static void HD44780_position (int x, int y);
|
||||
static void HD44780_chr (int x, int y, char ch);
|
||||
|
||||
static void common_position (int display, int DDaddr);
|
||||
static void common_autoscroll (int on);
|
||||
void HD44780_position (int x, int y);
|
||||
static void uPause (int delayCalls);
|
||||
static void HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
|
||||
static char HD44780_getkey ();
|
||||
|
||||
unsigned char HD44780_scankeypad();
|
||||
static int parse_span_list (int *spanListArray[], int *spLsize, int *dispOffsets[], int *dOffsize, int *dispSizeArray[], char *spanlist);
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -185,96 +179,52 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
{
|
||||
// TODO: remove the two magic numbers below
|
||||
// TODO: single point of return
|
||||
char *argv[64], *str;
|
||||
int argc, i;
|
||||
//char *argv[64];
|
||||
//int i;
|
||||
char buf[40];
|
||||
char *s;
|
||||
|
||||
HD44780 = driver;
|
||||
|
||||
// get_args inserts \0 into args - nasty !
|
||||
if (args)
|
||||
if ((str = (char *) malloc (strlen (args) + 1)))
|
||||
strcpy (str, args);
|
||||
else {
|
||||
fprintf (stderr, "Error mallocing\n");
|
||||
return -1;
|
||||
// TODO: replace DriverName with driver->name when that field exists.
|
||||
#define DriverName "HD44780"
|
||||
|
||||
|
||||
//// READ THE CONFIG FILE
|
||||
|
||||
port = driver->config_get_int( DriverName, "port", 0, 0x278 );
|
||||
|
||||
// Get and search for the connection type
|
||||
s = driver->config_get_string( DriverName, "connectiontype", 0, "4bit" );
|
||||
for (connectiontype_index = 0; strcmp (s, connectionMapping[connectiontype_index].connectionTypeStr) != 0 && connectionMapping[connectiontype_index].type != HD_unknown; ++connectiontype_index);
|
||||
|
||||
if (connectionMapping[connectiontype_index].type == HD_unknown) {
|
||||
fprintf (stderr, "HD44780_init: Unknown connection type: %s\n", s);
|
||||
return -1; // fatal error
|
||||
} else
|
||||
str = NULL;
|
||||
connection = connectionMapping[connectiontype_index].type;
|
||||
|
||||
argc = get_args (argv, args, 64);
|
||||
|
||||
// arguments are passed in with -d HD44780 "-p 0x278"
|
||||
// getopt will work well here
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (0 == strcmp (argv[i], "-p") || 0 == strcmp (argv[i], "--port")) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf (stderr, "HD44780_init: %s requires an argument\n", argv[i]);
|
||||
return -1;
|
||||
} else {
|
||||
int myport;
|
||||
if (sscanf (argv[i + 1], "%i", &myport) != 1) {
|
||||
fprintf (stderr, "HD44780_init: Couldn't read port address -" " using default value 0x%x\n", port);
|
||||
return -1;
|
||||
} else {
|
||||
port = myport;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
} else if (0 == strcmp (argv[i], "-c") || 0 == strcmp (argv[i], "--connect")) {
|
||||
int j = 0;
|
||||
if (i + 1 >= argc) {
|
||||
fprintf (stderr, "HD44780_init: %s requires an argument\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
// search the next argument for the connection type
|
||||
for (j = 0; strcmp (argv[i + 1], connectionMapping[j].connectionTypeStr) != 0 && connectionMapping[j].type != HD_unknown; ++j);
|
||||
|
||||
if (connectionMapping[j].type == HD_unknown) {
|
||||
fprintf (stderr, "HD44780_init: Unknown connection type - using default %s driver\n", connectionMapping[0].connectionTypeStr);
|
||||
connection = connectionMapping[0].type;
|
||||
j = 0;
|
||||
} else
|
||||
connection = connectionMapping[j].type;
|
||||
|
||||
connIdx = j;
|
||||
++i;
|
||||
} else if (0 == strcmp (argv[i], "-v") || 0 == strcmp (argv[i], "--vspan")) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf (stderr, "HD44780_init: %s requires an argument\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
if (parse_span_list (&spanList, &numLines, &dispVOffset, &numDisplays, &dispSizes, argv[i + 1]) == -1) {
|
||||
fprintf (stderr, "HD44780_init: invalid vspan argument\n");
|
||||
return -1;
|
||||
}
|
||||
++i;
|
||||
} else if (strcmp (argv[i], "-k") == 0 || strcmp (argv[i], "--keypad") == 0) {
|
||||
have_keypad = 1;
|
||||
printf( "HD44780 keypad extension enabled\n" );
|
||||
|
||||
} else if (0 == strcmp (argv[i], "-h") || 0 == strcmp (argv[i], "--help")) {
|
||||
int i;
|
||||
printf ("LCDproc HD44780 driver\n" "\t-p n\t--port n\tSelect the output device to use port n\n" "\t-c type\t--connect type\tSet the connection type (default 4 bit)\n" "\t\t\t\ttype = %s", connectionMapping[0].connectionTypeStr);
|
||||
for (i = 1; connectionMapping[i].type != HD_unknown; ++i)
|
||||
printf (" | %s", connectionMapping[i].connectionTypeStr);
|
||||
printf ("\n\t-v spanlist\t--vspan spanlist\tvertical span n{,m}\n" "\t-h\t--help\t\tShow this help information\n" "\n\tNote that the '-t' option should precede the '-d' option\n");
|
||||
|
||||
if (connectionMapping[connIdx].type != HD_unknown) {
|
||||
printf ("\n Parameters for %s driver\n", connectionMapping[connIdx].connectionTypeStr);
|
||||
printf ("%s", connectionMapping[connIdx].helpMsg);
|
||||
}
|
||||
// Get and parse vspan only when specified
|
||||
s = driver->config_get_string( DriverName, "vspan", 0, "" );
|
||||
if( s[0] != 0 ) {
|
||||
if (parse_span_list (&spanList, &numLines, &dispVOffset, &numDisplays, &dispSizes, s) == -1) {
|
||||
fprintf (stderr, "HD44780_init: invalid vspan value: %s\n", s );
|
||||
return -1;
|
||||
}
|
||||
/* ignore invalid arguments as they might be valid to the lower-level init
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
extIF = driver->config_get_bool( DriverName, "extended", 0, 0 );
|
||||
have_keypad = driver->config_get_bool( DriverName, "keypad", 0, 0 );
|
||||
have_backlight = driver->config_get_bool( DriverName, "backlight", 0, 0 );
|
||||
|
||||
// Get and parse size
|
||||
s = driver->config_get_string( DriverName, "size", 0, "20x4" );
|
||||
if( sscanf( s, "%dx%d", &(driver->wid), &(driver->hgt) ) != 2 ) {
|
||||
fprintf( stderr, "HD44780_init: Cannot read size: %s\n", s );
|
||||
}
|
||||
|
||||
// default case for when spans aren't indicated
|
||||
// - add a sanity check against HD44780->hgt ??
|
||||
// - this only works if the -t option is specified before -d
|
||||
if (numLines == 0) {
|
||||
if ((spanList = (int *) malloc (sizeof (int) * HD44780->hgt))) {
|
||||
int i;
|
||||
@@ -293,6 +243,8 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
} else
|
||||
fprintf (stderr, "Error mallocing for display sizes list\n");
|
||||
}
|
||||
|
||||
|
||||
#if defined DELAY_NANOSLEEP
|
||||
// Change to Round-Robin scheduling for nanosleep
|
||||
{
|
||||
@@ -306,8 +258,6 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
}
|
||||
#endif
|
||||
|
||||
atest( port );
|
||||
|
||||
// Make sure the frame buffer is there...
|
||||
if (!HD44780->framebuf)
|
||||
HD44780->framebuf = (unsigned char *) malloc (HD44780->wid * HD44780->hgt);
|
||||
@@ -318,27 +268,31 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
}
|
||||
// Set the functions the driver supports...
|
||||
// These are the default HD44780 functions
|
||||
driver->clear = (void *) -1;
|
||||
driver->string = (void *) -1;
|
||||
driver->chr = HD44780_chr;
|
||||
driver->vbar = HD44780_vbar;
|
||||
driver->init_vbar = HD44780_init_vbar;
|
||||
driver->hbar = HD44780_hbar;
|
||||
driver->init_hbar = HD44780_init_hbar;
|
||||
driver->num = HD44780_num;
|
||||
driver->init_num = HD44780_init_num;
|
||||
|
||||
driver->init = HD44780_init;
|
||||
driver->close = (void *) -1;
|
||||
driver->close = HD44780_close;
|
||||
driver->flush = HD44780_flush;
|
||||
driver->flush_box = HD44780_flush_box;
|
||||
//driver->contrast = HD44780_contrast; // contrast by potmeter
|
||||
driver->backlight = HD44780_backlight;
|
||||
driver->clear = HD44780_clear;
|
||||
driver->chr = HD44780_chr;
|
||||
driver->string = HD44780_string;
|
||||
driver->flush_box = HD44780_flush_box; // TO BE REMOVED
|
||||
//driver->contrast = HD44780_contrast; // contrast is set by potmeter we assume
|
||||
|
||||
//driver->output = HD44780_output; // not implemented
|
||||
driver->init_vbar = HD44780_init_vbar;
|
||||
driver->init_hbar = HD44780_init_hbar;
|
||||
driver->vbar = HD44780_vbar;
|
||||
driver->hbar = HD44780_hbar;
|
||||
driver->init_num = HD44780_init_num;
|
||||
driver->num = HD44780_num;
|
||||
driver->heartbeat = HD44780_heartbeat;
|
||||
driver->set_char = HD44780_set_char;
|
||||
driver->icon = HD44780_icon;
|
||||
driver->draw_frame = HD44780_draw_frame;
|
||||
driver->draw_frame = HD44780_draw_frame; // TO BE REMOVED
|
||||
|
||||
if( have_keypad ) {
|
||||
if ( have_backlight ) {
|
||||
driver->backlight = HD44780_backlight;
|
||||
}
|
||||
if ( have_keypad ) {
|
||||
driver->getkey = HD44780_getkey;
|
||||
}
|
||||
|
||||
@@ -346,21 +300,27 @@ HD44780_init (lcd_logical_driver * driver, char *args)
|
||||
return -1;
|
||||
}
|
||||
hd44780_functions->uPause = uPause;
|
||||
hd44780_functions->position = common_position;
|
||||
hd44780_functions->autoscroll = common_autoscroll;
|
||||
hd44780_functions->scankeypad = HD44780_scankeypad;
|
||||
|
||||
connectionMapping[connIdx].init_fn (hd44780_functions, driver, str, port);
|
||||
connectionMapping[connectiontype_index].init_fn (hd44780_functions, driver, args, port);
|
||||
|
||||
HD44780_autoscroll (0);
|
||||
HD44780_clear ();
|
||||
sprintf (buf, "HD44780 %dx%d", HD44780->wid, HD44780->hgt );
|
||||
HD44780_string (1, 1, buf);
|
||||
sprintf (buf, "LPT 0x%x %s %s", port, (have_backlight?"bl":""), (have_keypad?"key":"") );
|
||||
HD44780_string (1, 2, buf);
|
||||
HD44780_flush ();
|
||||
sleep (1);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Common initialisation sequence - sets cursor off and not blinking,
|
||||
// clear display and homecursor
|
||||
// Does not set twoline mode nor small characters (5x8). The init function of
|
||||
// the connectiontype should do this.
|
||||
|
||||
//
|
||||
void
|
||||
common_init ()
|
||||
{
|
||||
@@ -372,7 +332,9 @@ common_init ()
|
||||
hd44780_functions->uPause (1600);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// IO delay to avoid a task switch
|
||||
//
|
||||
void
|
||||
uPause (int delayCalls)
|
||||
{
|
||||
@@ -408,26 +370,18 @@ uPause (int delayCalls)
|
||||
#endif
|
||||
}
|
||||
|
||||
// displayID - ID of display to use (0 = all displays)
|
||||
static void
|
||||
HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
|
||||
{
|
||||
hd44780_functions->senddata (displayID, flags, ch);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clean-up
|
||||
//
|
||||
/*
|
||||
void HD44780_close()
|
||||
{
|
||||
drv_base_close();
|
||||
}
|
||||
*/
|
||||
void HD44780_close()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Set position (not part of API)
|
||||
//
|
||||
// x and y here are for the virtual HD44780->hgt x HD44780->wid display
|
||||
static void
|
||||
void
|
||||
HD44780_position (int x, int y)
|
||||
{
|
||||
int dispID = spanList[y];
|
||||
@@ -435,37 +389,74 @@ HD44780_position (int x, int y)
|
||||
int DDaddr;
|
||||
|
||||
// 16x1 is a special case
|
||||
if (dispSizes[dispID - 1] == 1 && HD44780->wid == 16)
|
||||
if (dispSizes[dispID - 1] == 1 && HD44780->wid == 16) {
|
||||
if (x >= 8) {
|
||||
x -= 8;
|
||||
relY = 1;
|
||||
}
|
||||
}
|
||||
|
||||
DDaddr = x + (relY % 2) * 0x40;
|
||||
if ((relY % 4) >= 2)
|
||||
DDaddr += HD44780->wid;
|
||||
|
||||
hd44780_functions->position (dispID, DDaddr);
|
||||
}
|
||||
|
||||
void
|
||||
common_position (int display, int DDaddr)
|
||||
{
|
||||
hd44780_functions->senddata (display, RS_INSTR, POSITION | DDaddr);
|
||||
hd44780_functions->senddata (dispID, RS_INSTR, POSITION | DDaddr);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
|
||||
void HD44780_chr (int x, int y, char ch)
|
||||
{
|
||||
HD44780->framebuf[ (y * HD44780->wid) + x] = ch;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Flush the framebuffer to the display
|
||||
//
|
||||
void
|
||||
HD44780_flush ()
|
||||
{
|
||||
HD44780_draw_frame (HD44780->framebuf);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clear the framebuffer
|
||||
//
|
||||
void HD44780_clear ()
|
||||
{
|
||||
memset(HD44780->framebuf, ' ', HD44780->wid * HD44780->hgt);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Place a character in the framebuffer
|
||||
//
|
||||
void
|
||||
HD44780_chr (int x, int y, char ch)
|
||||
{
|
||||
y--;
|
||||
x--;
|
||||
|
||||
HD44780->framebuf[ (y * HD44780->wid) + x] = ch;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Place a string in the framebuffer
|
||||
//
|
||||
void
|
||||
HD44780_string (int x, int y, char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
x --; // Convert 1-based coords to 0-based
|
||||
y --;
|
||||
|
||||
for (i = 0; s[i]; i++) {
|
||||
// Check for buffer overflows...
|
||||
if ((y * HD44780->wid) + x + i > (HD44780->wid * HD44780->hgt))
|
||||
break;
|
||||
HD44780->framebuf[(y*HD44780->wid) + x + i] = s[i];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Flush box
|
||||
//
|
||||
// TO BE REMOVED
|
||||
//
|
||||
void
|
||||
HD44780_flush_box (int lft, int top, int rgt, int bot)
|
||||
{
|
||||
@@ -477,7 +468,9 @@ HD44780_flush_box (int lft, int top, int rgt, int bot)
|
||||
HD44780_position (lft, y);
|
||||
//printf("\n%d,%d :",lft,y);
|
||||
for (x = lft; x <= rgt; x++) {
|
||||
HD44780_senddata (spanList[y], RS_DATA, HD44780->framebuf[(y * HD44780->wid) + x]);
|
||||
|
||||
hd44780_functions->senddata (spanList[y], RS_DATA, HD44780->framebuf[(y * HD44780->wid) + x]);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
//write(fd, HD44780->framebuf[(y*HD44780->wid)+lft, rgt-lft+1]);
|
||||
}
|
||||
@@ -490,31 +483,7 @@ HD44780_flush_box (int lft, int top, int rgt, int bot)
|
||||
void
|
||||
HD44780_backlight (int on)
|
||||
{
|
||||
//hd44780_functions->backlight (on);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in linewrapping feature
|
||||
//
|
||||
static void
|
||||
HD44780_linewrap (int on)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in automatic scrolling feature
|
||||
//
|
||||
static void
|
||||
HD44780_autoscroll (int on)
|
||||
{
|
||||
hd44780_functions->autoscroll (on);
|
||||
}
|
||||
|
||||
void
|
||||
common_autoscroll (int on)
|
||||
{
|
||||
hd44780_functions->senddata (0, RS_INSTR, ENTRYMODE | E_MOVERIGHT | ((on) ? EDGESCROLL : NOSCROLL));
|
||||
hd44780_functions->uPause (40);
|
||||
hd44780_functions->backlight (on);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -703,7 +672,7 @@ HD44780_hbar (int x, int y, int len)
|
||||
void
|
||||
HD44780_init_num ()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -716,6 +685,38 @@ HD44780_num (int x, int num)
|
||||
HD44780->framebuf[x+offset] = num + '0';
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Does the heartbeat...
|
||||
//
|
||||
void
|
||||
HD44780_heartbeat (int type)
|
||||
{
|
||||
static int timer = 0;
|
||||
int whichIcon;
|
||||
static int saved_type = HEARTBEAT_ON;
|
||||
|
||||
if (type)
|
||||
saved_type = type;
|
||||
|
||||
if (type == HEARTBEAT_ON) {
|
||||
// Set this to pulsate like a real heart beat...
|
||||
whichIcon = (! ((timer + 4) & 5));
|
||||
|
||||
// This defines a custom character EVERY time...
|
||||
// not efficient... is this necessary?
|
||||
HD44780_icon (whichIcon, 0);
|
||||
|
||||
// Put character on screen...
|
||||
HD44780_chr (HD44780->wid, 1, 0);
|
||||
|
||||
// change display...
|
||||
HD44780_flush ();
|
||||
}
|
||||
|
||||
timer++;
|
||||
timer &= 0x0f;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets a custom character from 0-7...
|
||||
//
|
||||
@@ -734,7 +735,8 @@ HD44780_set_char (int n, char *dat)
|
||||
if (!dat)
|
||||
return;
|
||||
|
||||
HD44780_senddata (0, RS_INSTR, SETCHAR | n * 8);
|
||||
hd44780_functions->senddata (0, RS_INSTR, SETCHAR | n * 8);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
|
||||
for (row = 0; row < HD44780->cellhgt; row++) {
|
||||
letter = 0;
|
||||
@@ -742,10 +744,14 @@ HD44780_set_char (int n, char *dat)
|
||||
letter <<= 1;
|
||||
letter |= (dat[(row * HD44780->cellwid) + col] > 0);
|
||||
}
|
||||
HD44780_senddata (0, RS_DATA, letter);
|
||||
hd44780_functions->senddata (0, RS_DATA, letter);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Set default icon into a userdef char
|
||||
//
|
||||
void
|
||||
HD44780_icon (int which, char dest)
|
||||
{
|
||||
@@ -793,6 +799,7 @@ HD44780_icon (int which, char dest)
|
||||
//
|
||||
// Input is a character array, sized HD44780->wid*hgt
|
||||
//
|
||||
// TO BE REMOVED (move it into flush())
|
||||
void
|
||||
HD44780_draw_frame (char *dat)
|
||||
{
|
||||
@@ -802,15 +809,136 @@ HD44780_draw_frame (char *dat)
|
||||
return;
|
||||
|
||||
for (y = 0; y < HD44780->hgt; y++) {
|
||||
HD44780_position (0, y);
|
||||
//printf("\n%d :",y);
|
||||
for (x = 0; x < HD44780->wid; x++) {
|
||||
HD44780_senddata (spanList[y], RS_DATA, HD44780_charmap[(unsigned char)dat[(y * HD44780->wid) + x]]);
|
||||
|
||||
if( x % 8 == 0 )
|
||||
HD44780_position (x, y);
|
||||
hd44780_functions->senddata (spanList[y], RS_DATA, HD44780_charmap[(unsigned char)dat[(y * HD44780->wid) + x]]);
|
||||
hd44780_functions->uPause (40); // Minimum exec time for all commands
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Get a key from the keypad (if there is one)
|
||||
//
|
||||
char HD44780_getkey()
|
||||
{
|
||||
unsigned char scancode;
|
||||
char ch;
|
||||
struct timeval curr_time, time_diff;
|
||||
|
||||
gettimeofday(&curr_time,NULL);
|
||||
|
||||
scancode = hd44780_functions->scankeypad();
|
||||
if( scancode ) {
|
||||
if( scancode & 0xF0 ) {
|
||||
ch = keyMapMatrix[((scancode&0xF0)>>4)-1][(scancode&0x0F)-1];
|
||||
}
|
||||
else {
|
||||
ch = keyMapDirect[scancode - 1];
|
||||
}
|
||||
}
|
||||
else {
|
||||
ch = 0;
|
||||
}
|
||||
|
||||
if (ch) {
|
||||
if (ch == pressed_key) {
|
||||
timersub (&curr_time, &pressed_key_time, &time_diff);
|
||||
if (((time_diff.tv_usec / 1000 + time_diff.tv_sec * 1000) - KEYPAD_AUTOREPEAT_DELAY) < 1000 * 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
|
||||
return 0;
|
||||
}
|
||||
// Otherwise a keypress will be returned
|
||||
pressed_key_repetitions ++;
|
||||
}
|
||||
else {
|
||||
// It's a new keypress
|
||||
pressed_key_time = curr_time;
|
||||
pressed_key_repetitions = 0;
|
||||
printf( "Key: %c (%d,%d)\n", ch, scancode&0x0F, (scancode&0xF0)>>4 );
|
||||
}
|
||||
}
|
||||
|
||||
// Store the key for the next round
|
||||
pressed_key = ch;
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Scan the keypad
|
||||
//
|
||||
unsigned char HD44780_scankeypad()
|
||||
{
|
||||
unsigned int keybits;
|
||||
unsigned int shiftcount;
|
||||
unsigned int shiftingbit;
|
||||
unsigned int Ypattern;
|
||||
unsigned int Yval;
|
||||
char exp;
|
||||
|
||||
unsigned char scancode = 0;
|
||||
|
||||
// First check if a directly connected key is pressed
|
||||
// Put all zeros on Y of keypad
|
||||
keybits = hd44780_functions->readkeypad (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;
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Now check the matrix
|
||||
// First check with all 1's
|
||||
Ypattern = (1 << KEYPAD_MAXY) - 1;
|
||||
if( hd44780_functions->readkeypad (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 = hd44780_functions->readkeypad (Ypattern);
|
||||
if (!keybits) {
|
||||
Yval += (1 << exp);
|
||||
}
|
||||
}
|
||||
|
||||
// Which key is pressed in that row ?
|
||||
keybits = hd44780_functions->readkeypad (1<<Yval);
|
||||
shiftingbit=1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !scancode; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found !
|
||||
scancode = (Yval+1) << 4 | (shiftcount+1);
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return scancode;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Parse the span list
|
||||
// spanListArray - array to store vertical spans
|
||||
// spLsize - size of spanListArray
|
||||
@@ -862,90 +990,3 @@ parse_span_list (int *spanListArray[], int *spLsize, int *dispOffsets[], int *dO
|
||||
return retVal;
|
||||
}
|
||||
|
||||
char HD44780_getkey()
|
||||
{
|
||||
unsigned int keybits;
|
||||
unsigned int shiftcount;
|
||||
unsigned int shiftingbit;
|
||||
unsigned int Ypattern;
|
||||
unsigned int Yval;
|
||||
char exp;
|
||||
char ch = 0;
|
||||
char ch_set = 0;
|
||||
struct timeval curr_time, time_diff;
|
||||
|
||||
gettimeofday(&curr_time,NULL);
|
||||
|
||||
// First check if a directly connected key is pressed
|
||||
// Put all zeros on Y of keypad
|
||||
keybits = hd44780_functions->readkeypad (0);
|
||||
|
||||
if (keybits) {
|
||||
// A directly connected key was pressed
|
||||
// Which key was it ?
|
||||
shiftingbit = 1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !ch; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found ! Return from function.
|
||||
ch = keyMapDirect[shiftcount];
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Now check the matrix
|
||||
// First check with all 1's
|
||||
Ypattern = (1 << KEYPAD_MAXY) - 1;
|
||||
if( hd44780_functions->readkeypad (Ypattern)) {
|
||||
// Yes, a key on the matrix is pressed
|
||||
|
||||
// OK, now we know a key is pressed.
|
||||
// Determine which one it is
|
||||
// Do a 'binary search' to determine in what row a key is pressed
|
||||
Ypattern = 0;
|
||||
Yval = 0;
|
||||
for (exp=3; exp>=0; exp--) {
|
||||
Ypattern = ((1 << (1 << exp)) - 1) << Yval;
|
||||
keybits = hd44780_functions->readkeypad (Ypattern);
|
||||
if (!keybits) {
|
||||
Yval += (1 << exp);
|
||||
}
|
||||
}
|
||||
|
||||
// Which key is pressed in that row ?
|
||||
keybits = hd44780_functions->readkeypad (1<<Yval);
|
||||
shiftingbit=1;
|
||||
for (shiftcount=0; shiftcount<KEYPAD_MAXX && !ch; shiftcount++) {
|
||||
if ( keybits & shiftingbit) {
|
||||
// Found !
|
||||
ch = keyMapMatrix[Yval][shiftcount];
|
||||
}
|
||||
shiftingbit <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch) {
|
||||
if (ch == pressed_key) {
|
||||
timersub (&curr_time, &pressed_key_time, &time_diff);
|
||||
if (((time_diff.tv_usec / 1000 + time_diff.tv_sec * 1000) - KEYPAD_AUTOREPEAT_DELAY) < 1000 * 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
|
||||
return 0;
|
||||
}
|
||||
// Otherwise a keypress will be returned
|
||||
pressed_key_repetitions ++;
|
||||
}
|
||||
else {
|
||||
// It's a new keypress
|
||||
pressed_key_time = curr_time;
|
||||
pressed_key_repetitions = 0;
|
||||
printf( "Key: %c\n", ch );
|
||||
}
|
||||
}
|
||||
|
||||
// Store the key for the next round
|
||||
pressed_key = ch;
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user