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:
robijn
2001-11-01 00:37:12 +00:00
parent 0619f03774
commit faa4861eb3
9 changed files with 786 additions and 494 deletions
+323 -282
View File
@@ -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;
}