Pages: [1] 2 3   Go Down
Author Topic: Multi-tap keypad library (or just one function)  (Read 5211 times)
0 Members and 1 Guest are viewing this topic.
Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I wrote a multi-tap keypad library for anyone to easily input letters and some symbols on a numerical keypad:
Layout here:
This is what it would do to a typical keypad (I have one but didn't hook it up)


This is on my custom pad, which I tested with the help of my wife smiley. The directional keys and ent esc are actually to the right but my PPT slide is not that wide.


I will upload some videos tomorrow. If you want code, do a reply and don't just lurk smiley-wink
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 27425
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you change between letter mode and # mode?
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you change between letter mode and # mode?

In the "standard" keypad library, you call keypad.getKey() to get a key, which is mapped into ASCII characters '0' to '9', and '*', '#' or NO_KEY if no key is pressed. If you just take these return values you get direct mode (face value of '0'-'9' and two more keys). If you instead pass these values to my multi-tap function call like

int multi_tap_result=multi_tap(keypad.getKey());

then the returned multi_tap_result tells you whether a key press has been made via the multi-tap mode (either by long enough wait or by pressing a subsequent key or there is no key press.

Say if you press the '2' key two times and pause, then the straignt key.getKey() will give you some '0' before you press the key, then '2' for your first key press, some 0 between key press, another '2', then all zeros after your second key press. You can use these results to display two '2'. If you instead pass all these numbers('0', '0', ... '2', '0', '0',..., '2', '0', '0', ...) to the multi_tap(), your return would be a bunch of 'A' after your initial key press, then a bunch of 'B' after your second key press, and finally after a long wait you made, a value of 256+'B'. So your receiving end needs to sense if the high byte of the return is 0. If it is, render the returned key in place as the user is still pressing/cycling through the list of characters, if it returns a key with 1 in the high byte, the user has made the choice and you can render this character in place and put it in an input array or something.
Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is my program that interacts with the multi_tap function. It writes on an HD44780 display. The guy outside in the courtyard has been on the ride-on lawn mower since like 2pm and I would have recorded a video if he weren't making so much noise.:

Code:
void loop()
{
  int ret=0;
  byte key=panel_keypad.getKey(); // Get a key press from the keypad
  ret=multi_tap(key); // Feed the key press to the multi_tap function.
  if ((ret&256)!=0) // If this is non-zero, we got a key. Handle some special keys or just print the key on screen
  {
    switch (ret&255)
    {
      case '\b':
      if ((pointer%lcd_columns)==0)
      {
        if (rowp>0)
        {
          rowp--;
          pointer=lcd_columns-2;
        }
      }
      else pointer--;
      lcd.setCursor(pointer,rowp);
      lcd.write(' ');
      lcd.setCursor(pointer,rowp);
      return;
      break;
      case '\n':
      pointer=0;
      rowp++;
      rowp%=lcd_rows;
      lcd.setCursor(pointer,rowp);
      return;
      break;
    }
    lcd.setCursor(pointer,rowp);
    lcd.write(lowByte(ret));
    pointer++;
    if (pointer>=lcd_columns)
    {
      pointer=0;
      rowp++;
    }
  }
  else if (ret) // We don't have a key but the user is still cycling through characters on one key so we need to update the screen
  {
    lcd.setCursor(pointer,rowp);
    lcd.write(lowByte(ret));
  }
}


He's probably done now. BTW, the courtyard is big.


Here is a picture. I'll be recording a video soon.
Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here we go:

Using the multi-tap library on my phi-panel. This is my latest design. Find out details here:



Quick look around phi-panel:

Logged


Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Anyone interested in multi-tap code at all?! I thought there would be more interest.
Logged


Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 27425
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I find it interesting. Don't have a project in mind yet. Still have your previous board to populate, got a 4x20 plasma screen to play with, got a LCD panel that I've never unpackaged. And now a hot air solder station to check out.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Full Member
***
Karma: 2
Posts: 159
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Heh; I did the very same thing last week using a 4x4 telephone-style keypad.
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok I just posted my code. It's compatible with standard keypads library for arduino and my own version of library.

http://liudr.wordpress.com/2011/09/04/multi-tap-function/
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi! I have a problem compiling your code error says "multi_tap_threshold was not declared in this code". What should be the value of multi_tap_threshold and where should I declare it?

here's my code and I'm not sure if this is correct. I'm not good in programming though.

Code:
#include <Keypad.h>
#define RESET_MTP '~'

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
int pointer;
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {11,6,7,9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10,12,8}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
}
 
void loop()
{
  int mtKey=0;
  byte key=keypad.getKey(); // Get a key press from the keypad
  mtKey=multi_tap(key); // Feed the key press to the multi_tap function.
  Serial.print(mtKey);
}

int multi_tap(byte key)
{
  static boolean upperCase=true;
  static byte prevKeyPress=NO_KEY,cyclicPtr=0;
  static unsigned long prevKeyMillis=0;
  static const char multi_tap_mapping[10][5]={{'0','#','$','.','?'},{'1','+','-','*','/'},{'A','B','C','2','!'},{'D','E','F','3','%'},{'G','H','I','4','('},{'J','K','L','5',')'},{'M','N','O','6','@'},{'P','Q','R','S','7'},{'T','U','V','8',','},{'W','X','Y','Z','9'}};
  if (key==RESET_MTP) // Received reset command. Flush everything and get ready for restart.
  {
    upperCase=true;
    prevKeyPress=NO_KEY;
    cyclicPtr=0;
    return 0;
  }
  if (key!=NO_KEY) // A key is pressed at this iteration.
  {
    if ((key>'9')||(key<'0')) // Function keys
    {
      if ((key==1)||(key=='#')) // Up for case change
      {
        upperCase=!upperCase;
        return 0;
      }
      else // Other function keys. These keys produce characters so they need to terminate the last keypress.
      {
        if (prevKeyPress!=NO_KEY)
        {
          char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
          if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
          cyclicPtr=0;
          prevKeyMillis=0;
          switch (key)
          {
            case 2:
            // Call symbol list
            return 0; // Clear the buffer.
            break;
            case 3:
            prevKeyPress='\b';
            break;
            case 4:
            case '*':
            prevKeyPress=' ';
            break;
            case 5:
            prevKeyPress='\n';
            break;
            case 6:
            prevKeyPress=NO_KEY; // Clear the buffer.
            break;
          }
          return(256+(unsigned int)(temp1));
        }
        else
        {
          prevKeyPress=NO_KEY;
          cyclicPtr=0;
          prevKeyMillis=0;
          switch (key)
          {
            case 2:
            // Call symbol list
            return 0; // Clear the buffer.
            break;
            case 3:
            return (256+(unsigned int)('\b'));
            break;
            case 4:
            return (256+(unsigned int)(' '));
            break;
            case 5:
            return (256+(unsigned int)('\n'));
            break;
            case 6:
            return 0; // Clear the buffer.
            break;
          }
        }
      }
   
    }
    if (prevKeyPress!=NO_KEY)
    {
      if (prevKeyPress==key)
      {
        char temp1;
        cyclicPtr++;
        if ((multi_tap_mapping[key-'0'][cyclicPtr]==0)||(cyclicPtr==5)) cyclicPtr=0; //Cycle key
        prevKeyMillis=millis();
        temp1=multi_tap_mapping[key-'0'][cyclicPtr];
        if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
        return ((unsigned int)(temp1));
      }
      else
      {
        char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
        if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
        prevKeyPress=key;
        cyclicPtr=0;
        prevKeyMillis=millis();
        //Print key on cursor+1
        return(256+(unsigned int)(temp1));
      }
    }
    else
    {
      char temp1=multi_tap_mapping[key-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      prevKeyPress=key;
      prevKeyMillis=millis();
      cyclicPtr=0;
      return ((unsigned int)(temp1));
    }
 
  }
  else // No key is pressed at this iteration.
  {
    if (prevKeyPress==NO_KEY) return 0; // No key was previously pressed.
    else if (millis()-prevKeyMillis<multi_tap_threshold) // Key was pressed previously but within threshold
    {
      char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      return((unsigned int)(temp1));
    }
    else // Key was pressed previously and threshold has passed
    {
      char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      prevKeyPress=NO_KEY;
      cyclicPtr=0;
      return(256+(unsigned int)(temp1));
    }
  }
  return 0;
}
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi! I have a problem compiling your code error says "multi_tap_threshold was not declared in this code". What should be the value of multi_tap_threshold and where should I declare it?

here's my code and I'm not sure if this is correct. I'm not good in programming though.

Code:
#include <Keypad.h>
#define RESET_MTP '~'

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
int pointer;
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {11,6,7,9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10,12,8}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
}
 
void loop()
{
  int mtKey=0;
  byte key=keypad.getKey(); // Get a key press from the keypad
  mtKey=multi_tap(key); // Feed the key press to the multi_tap function.
  Serial.print(mtKey);
}

int multi_tap(byte key)
{
  static boolean upperCase=true;
  static byte prevKeyPress=NO_KEY,cyclicPtr=0;
  static unsigned long prevKeyMillis=0;
  static const char multi_tap_mapping[10][5]={{'0','#','$','.','?'},{'1','+','-','*','/'},{'A','B','C','2','!'},{'D','E','F','3','%'},{'G','H','I','4','('},{'J','K','L','5',')'},{'M','N','O','6','@'},{'P','Q','R','S','7'},{'T','U','V','8',','},{'W','X','Y','Z','9'}};
  if (key==RESET_MTP) // Received reset command. Flush everything and get ready for restart.
  {
    upperCase=true;
    prevKeyPress=NO_KEY;
    cyclicPtr=0;
    return 0;
  }
  if (key!=NO_KEY) // A key is pressed at this iteration.
  {
    if ((key>'9')||(key<'0')) // Function keys
    {
      if ((key==1)||(key=='#')) // Up for case change
      {
        upperCase=!upperCase;
        return 0;
      }
      else // Other function keys. These keys produce characters so they need to terminate the last keypress.
      {
        if (prevKeyPress!=NO_KEY)
        {
          char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
          if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
          cyclicPtr=0;
          prevKeyMillis=0;
          switch (key)
          {
            case 2:
            // Call symbol list
            return 0; // Clear the buffer.
            break;
            case 3:
            prevKeyPress='\b';
            break;
            case 4:
            case '*':
            prevKeyPress=' ';
            break;
            case 5:
            prevKeyPress='\n';
            break;
            case 6:
            prevKeyPress=NO_KEY; // Clear the buffer.
            break;
          }
          return(256+(unsigned int)(temp1));
        }
        else
        {
          prevKeyPress=NO_KEY;
          cyclicPtr=0;
          prevKeyMillis=0;
          switch (key)
          {
            case 2:
            // Call symbol list
            return 0; // Clear the buffer.
            break;
            case 3:
            return (256+(unsigned int)('\b'));
            break;
            case 4:
            return (256+(unsigned int)(' '));
            break;
            case 5:
            return (256+(unsigned int)('\n'));
            break;
            case 6:
            return 0; // Clear the buffer.
            break;
          }
        }
      }
   
    }
    if (prevKeyPress!=NO_KEY)
    {
      if (prevKeyPress==key)
      {
        char temp1;
        cyclicPtr++;
        if ((multi_tap_mapping[key-'0'][cyclicPtr]==0)||(cyclicPtr==5)) cyclicPtr=0; //Cycle key
        prevKeyMillis=millis();
        temp1=multi_tap_mapping[key-'0'][cyclicPtr];
        if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
        return ((unsigned int)(temp1));
      }
      else
      {
        char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
        if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
        prevKeyPress=key;
        cyclicPtr=0;
        prevKeyMillis=millis();
        //Print key on cursor+1
        return(256+(unsigned int)(temp1));
      }
    }
    else
    {
      char temp1=multi_tap_mapping[key-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      prevKeyPress=key;
      prevKeyMillis=millis();
      cyclicPtr=0;
      return ((unsigned int)(temp1));
    }
 
  }
  else // No key is pressed at this iteration.
  {
    if (prevKeyPress==NO_KEY) return 0; // No key was previously pressed.
    else if (millis()-prevKeyMillis<multi_tap_threshold) // Key was pressed previously but within threshold
    {
      char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      return((unsigned int)(temp1));
    }
    else // Key was pressed previously and threshold has passed
    {
      char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      prevKeyPress=NO_KEY;
      cyclicPtr=0;
      return(256+(unsigned int)(temp1));
    }
  }
  return 0;
}
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi! I have a problem compiling your code error says "multi_tap_threshold was not declared in this code". What should be the value of multi_tap_threshold and where should I declare it?

here's my code and I'm not sure if this is correct. I'm not good in programming though.

Just do #define multi_tap_threshold 1000

This is the time the function waits until a letter is confirmed. Say you press "2" three times, and wait for 1000 ms then the letter C becomes the output. If you want a longer wait, you can increase the 1000.

Updated code:

I made changes so that you only see the real output, the C, not the temporary such as A then B then C.

The multi-tap only works well on a display, not a serial port, although you can do your preliminary test over a serial port, you can't render a character in place.

Code:
#include <Keypad.h>
#define multi_tap_threshold 1000
#define RESET_MTP '~'

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
int pointer;
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {11,6,7,9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10,12,8}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
}
 
void loop()
{
  int mtKey=0;
  byte key=keypad.getKey(); // Get a key press from the keypad
  mtKey=multi_tap(key); // Feed the key press to the multi_tap function.
  if(!(mtKey&10000000B)) Serial.print(mtKey);
}

int multi_tap(byte key)
{
  static boolean upperCase=true;
  static byte prevKeyPress=NO_KEY,cyclicPtr=0;
  static unsigned long prevKeyMillis=0;
  static const char multi_tap_mapping[10][5]={{'0','#','$','.','?'},{'1','+','-','*','/'},{'A','B','C','2','!'},{'D','E','F','3','%'},{'G','H','I','4','('},{'J','K','L','5',')'},{'M','N','O','6','@'},{'P','Q','R','S','7'},{'T','U','V','8',','},{'W','X','Y','Z','9'}};
  if (key==RESET_MTP) // Received reset command. Flush everything and get ready for restart.
  {
    upperCase=true;
    prevKeyPress=NO_KEY;
    cyclicPtr=0;
    return 0;
  }
  if (key!=NO_KEY) // A key is pressed at this iteration.
  {
    if ((key>'9')||(key<'0')) // Function keys
    {
      if ((key==1)||(key=='#')) // Up for case change
      {
        upperCase=!upperCase;
        return 0;
      }
      else // Other function keys. These keys produce characters so they need to terminate the last keypress.
      {
        if (prevKeyPress!=NO_KEY)
        {
          char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
          if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
          cyclicPtr=0;
          prevKeyMillis=0;
          switch (key)
          {
            case 2:
            // Call symbol list
            return 0; // Clear the buffer.
            break;
            case 3:
            prevKeyPress='\b';
            break;
            case 4:
            case '*':
            prevKeyPress=' ';
            break;
            case 5:
            prevKeyPress='\n';
            break;
            case 6:
            prevKeyPress=NO_KEY; // Clear the buffer.
            break;
          }
          return(256+(unsigned int)(temp1));
        }
        else
        {
          prevKeyPress=NO_KEY;
          cyclicPtr=0;
          prevKeyMillis=0;
          switch (key)
          {
            case 2:
            // Call symbol list
            return 0; // Clear the buffer.
            break;
            case 3:
            return (256+(unsigned int)('\b'));
            break;
            case 4:
            return (256+(unsigned int)(' '));
            break;
            case 5:
            return (256+(unsigned int)('\n'));
            break;
            case 6:
            return 0; // Clear the buffer.
            break;
          }
        }
      }
   
    }
    if (prevKeyPress!=NO_KEY)
    {
      if (prevKeyPress==key)
      {
        char temp1;
        cyclicPtr++;
        if ((multi_tap_mapping[key-'0'][cyclicPtr]==0)||(cyclicPtr==5)) cyclicPtr=0; //Cycle key
        prevKeyMillis=millis();
        temp1=multi_tap_mapping[key-'0'][cyclicPtr];
        if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
        return ((unsigned int)(temp1));
      }
      else
      {
        char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
        if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
        prevKeyPress=key;
        cyclicPtr=0;
        prevKeyMillis=millis();
        //Print key on cursor+1
        return(256+(unsigned int)(temp1));
      }
    }
    else
    {
      char temp1=multi_tap_mapping[key-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      prevKeyPress=key;
      prevKeyMillis=millis();
      cyclicPtr=0;
      return ((unsigned int)(temp1));
    }
 
  }
  else // No key is pressed at this iteration.
  {
    if (prevKeyPress==NO_KEY) return 0; // No key was previously pressed.
    else if (millis()-prevKeyMillis<multi_tap_threshold) // Key was pressed previously but within threshold
    {
      char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      return((unsigned int)(temp1));
    }
    else // Key was pressed previously and threshold has passed
    {
      char temp1=multi_tap_mapping[prevKeyPress-'0'][cyclicPtr];
      if ((!upperCase)&&(temp1>='A')&&(temp1<='Z')) temp1+='a'-'A';
      prevKeyPress=NO_KEY;
      cyclicPtr=0;
      return(256+(unsigned int)(temp1));
    }
  }
  return 0;
}
Logged


Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Just do #define multi_tap_threshold 1000

This is the time the function waits until a letter is confirmed. Say you press "2" three times, and wait for 1000 ms then the letter C becomes the output. If you want a longer wait, you can increase the 1000.

Hi! Well as for the code that you updated, it doesn't compile "error: invalid suffix 'B' on integer constant". I tried removing the 'B' on the if (!mtkey&10000000B) which becomes if (!mtkey&10000000), it compiles but no output..

And may I ask, how can I store the input from the keypad? By the way I'm using 4x3 keypad. Say I entered, '1' then 'a' then 'b', those letters will be saved and stored to char output[4] so if I do lcd.print(output), it will display '1ab'. Thank you!
« Last Edit: October 08, 2011, 10:36:02 am by brutal_magnet » Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7305
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Typo. Should be B10000000.

You should read these lines at the beginning of my code before you started, especially step 3:

Also, remapping your 'A' key into '#' key will make it into upper/lower case function.

Quote
This portion of code is the multi-tap function written by Dr. John Liu. It is provided to you without any warranty. Your use is limited to not-for-profit activities.
You may change the definition of the multi-tap keypad, which contains 5 symbols per numerical key for all 10 numerical keys.
To use the function:
1) Call your keypad's getKey method to receive a key. This key has to be '0' to '9' or other symbols such as '#' or NO_KEY or scan codes for phi_keypads objects.
2) Call multi_tap and pass the received key to it.
3) The returned value indicates what is going on.
If the most significant bit (MSB) is set to 1, then the multi-tap is in process. You should print the return value (with MSB reset to 0) in place.
If MSB is reset to 0, then the multi-tap has concluded and a final character is produced. You should print this character in place and move cursor to the next position.
If the return value is NO-KEY, then nothing is happening.
Pressing the '#' key engages or disengages shift to switch between upper and lower cases.
Calling the multi_tap with RESET_MTP will result in the multi_tap process to reset, useful if you are unsure of the function's status. Say you didn't finish a multi-tap process and switch to another piece of code and then later want to use multi-tap, you should reset it before using. The return value for this call is to be discarded.
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 227
Posts: 14048
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


HI liudr,

your layout of the multitap resembles the layout ot letters on mobile phones which is/was be patented. might be a point of attention if it still is (or some variation)

There are some differences though on your custom pad e.g. the 2x5 layout.

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1] 2 3   Go Up
Jump to: