Logic for 9 key keyboard to print qwerty keys
I have a device which has got 9 keys just like an ordinary mobile phone. I want to print normal alphabets like ABCD using these 9 keys e开发者_开发技巧xactly the way mobile phones let you do it.
This is an embedded system programming project. I am unable to figure out the logic to implement this functionality.
I am detecting keys by polling and not by interrupt.
Can someone help? I will appreciate if you can point out related resources as well.
Here is a little keyboard decoding demo that should get you well on your way. You'll need to rewrite the key scanning routine for your hardware. In addition, there will be some kind of timeout needed to select the same digit twice in a row. You should also have little trouble figuring out how to add support for capitalization, punctuation, and meta keys...
#include <stdio.h>
#define NUM_KEYS 10
#define NUM_PHASES 6
char KeyMap[NUM_KEYS][NUM_PHASES] =
{ { '0', 0, 0, 0, 0, 0 },
{ '1', 0, 0, 0, 0, 0 },
{ '2', 'A', 'B', 'C', 0, 0 },
{ '3', 'D', 'E', 'F', 0, 0 },
{ '4', 'G', 'H', 'I', 0, 0 },
{ '5', 'J', 'K', 'L', 0, 0 },
{ '6', 'M', 'N', 'O', 0, 0 },
{ '7', 'P', 'Q', 'R', 'S', 0 },
{ '8', 'T', 'U', 'V', 0, 0 },
{ '9', 'W', 'X', 'Y', 'Z', 0 } };
char KeyGet()
{
char key;
/* do whatever it takes to scan your
keyboard and return the _numeric_ digit. */
/* for this test simulate with console input */
key = getc(stdin);
if ((key >= '0') && (key <= '9'))
{
key -= 0x30;
}
else
{
key = 0;
}
return key;
}
char DecodeKey(char NewKey, char *pOldKey, int *pPhase)
{
char ch = 0;
/* Validate Phase */
if ((*pPhase < 0) || (*pPhase >= NUM_PHASES))
{
*pPhase = 0;
}
/* see if a different key was pressed than last time */
/* if it was then restart the phase counter */
if (NewKey != *pOldKey)
{
*pPhase = 0;
*pOldKey = NewKey;
}
/* Validate Key */
if ((NewKey >= 0) && (NewKey < NUM_KEYS))
{
ch = KeyMap[(int)NewKey][*pPhase];
/* if the phase position is NULL, just get the numeric digit */
if (ch == 0)
{
*pPhase = 0;
ch = KeyMap[(int)NewKey][*pPhase];
}
/* bump the phase */
++(*pPhase);
if (*pPhase >= NUM_PHASES)
{
*pPhase = 0;
}
}
return ch;
}
int main()
{
char nk; /* new key */
char ok = 0; /* old key */
char c; /* resulting character */
int phase = 0; /* tracks the key presses */
while (1)
{
/* get a key */
nk = KeyGet();
/* convert it to a character */
c = DecodeKey(nk, &ok, &phase);
if (c != 0)
{
printf("%c", c);
}
}
return 0;
}
To do a really good design, you'll need a keyboard input routine which can tell when keys have been held for awhile, and when they have been released for awhile. For a short time after a digit is pressed, you should keep the cursor on the newly-typed character; if the same digit is pushed again, you should change the newly-typed character. If another digit is typed, make the selected digit 'permanent' and show the cursor on the character for the new key. If no key is pushed for a second or so, advance the cursor to the next position. If enter is pushed when the cursor is on a newly-typed digit, just advance the cursor. If it's pushed within about 1/4 second of the cursor auto-advancing, do nothing. If it's pushed when the cursor isn't on a character and hasn't just auto-advanced, confirm entry.
Take your controller`s 6 pins for keyboard P0->P6.Connect your 3 columns P0->P3and 3 rows to P4->P6.Make all pins high by code. Scan each rows by giving low on each columns. So by getting the particular row and column you will be able to get the entered key.. Hope you look for this..
Adapting Amardeep's answer:
char KeyMap[NUM_KEYS][NUM_PHASES] =
{ { '0', 0, 0, 0, 0, 0 },
{ '1', 0, 0, 0, 0, 0 },
{ '2', 'A', 'B', 'C', 0, 0 },
{ '3', 'D', 'E', 'F', 0, 0 },
{ '4', 'G', 'H', 'I', 0, 0 },
{ '5', 'J', 'K', 'L', 0, 0 },
{ '6', 'M', 'N', 'O', 0, 0 },
{ '7', 'P', 'Q', 'R', 'S', 0 },
{ '8', 'T', 'U', 'V', 0, 0 },
{ '9', 'W', 'X', 'Y', 'Z', 0 } };
//Gets the system time, e.g. as number of timer ticks since power up. You write this.
sometype GetSystemTime();
//Checks if key has been pressed. Returns 0-9 if a key was pressed or -1 if no key was pressed. You write this.
int KeyAvailable();
int main()
{
const sometype PHASE_WAIT = somevalue; //The delay before shifting to the next character.
char keyBuffer[BUFFER_SIZE]; //The input buffer.
int keyIndex = 0; //The index into keyBuffer.
int keyPress1 = -1, keyPress2; // keyboard inputs.
sometype lastKeyPressTime; // The time a key was last pressed.
int numKeyPresses; // The number of times the same key has been pressed this phase.
/* keyboard processing loop. */
while ( 1 )
{
if ( ( GetSystemTime() - lastKeyPressTime > PHASE_WAIT ) && ( -1 != keyPress1 ) )
{
// Phase timed out. Commit current character.
keyBuffer[keyIndex++] = KeyMap[keyPress1][numKeyPresses - 1];
keyPress1 = -1;
}
if ( ( keyPress2 = KeyAvailable() ) > -1 )
{
// Key pressed.
lastKeyPressTime = GetSystemTime();
if ( ( keyPress2 != keyPress1 ) && ( -1 != keyPress1 ) )
{
// Different than last key. Commit current character and start a new one.
keyBuffer[keyIndex++] = KeyMap[keypress1][numKeyPresses - 1];
numKeyPresses = 1; // Yes, I"m using 1-based indexing. Deal.
}else if ( keyPress2 == keyPress1 )
{
// Pressed same key multiple times in same phase.
numKeyPresses = ((numKeyPresses) % KEYMAPROWSIZE) + 1;
if ( 0 == KeyMap[keypress2][numKeyPresses - 1] )
{
//Loop back to first 'valid' character associated with this key.
numKeyPresses = 1;
}
}else // -1 == keyPress1
{
// Pressed new key. Start new phase.
numKeyPresses = 1;
}
keyPress1 = keyPress2.
}
}
}
精彩评论