USB host shield with pro mini and keypad question

Hello,

I am using a Pro Mini and a Circuits at Home USB Shield to translate keypad key presses to 4 bit codes.

Pressing any key causes the report parser return a single hex value for all but three keys. The three keys in question are the [ and ] and =. These three keys report 3 hex values in rapid succession when they are pressed. When the [ is pressed the parser returns 0x0 and 0x4 and 0x0. When the ] key is pressed the reply is 0x0 and 0x4 and 0x1. Pressing the = key results in a 0x0 and 0x6 and 0x0. With the exception of the three keys listed above the code is working as needed.

My code is as follows:

#include <hidboot.h>
#include <usbhub.h>
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

class KbdRptParser : public KeyboardReportParser
{
 protected:
 void OnKeyDown  (uint8_t mod, uint8_t key);
};

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
byte outputHoldMs = 50;
if ((key) == 0x63) {Serial.println("  U pressed . ");     PORTD |= 0B111010111; delay(outputHoldMs); PORTD &= 0B111000011;}  
if ((key) == 0x62) {Serial.println("  U pressed 0 ");     PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x59) {Serial.println("  U pressed 1 ");     PORTD |= 0B111011111; delay(outputHoldMs); PORTD &= 0B111000011;} 
if ((key) == 0x5A) {Serial.println("  U pressed 2 ");     PORTD |= 0B111111111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x5B) {Serial.println("  U pressed 3 ");     PORTD |= 0B111110111; delay(outputHoldMs); PORTD &= 0B111000011;} 
if ((key) == 0x5C) {Serial.println("  U pressed 4 ");     PORTD |= 0B111111011; delay(outputHoldMs); PORTD &= 0B111000011;}  
if ((key) == 0x5D) {Serial.println("  U pressed 5 ");     PORTD |= 0B111001111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x5E) {Serial.println("  U pressed 6 ");     PORTD |= 0B111101111; delay(outputHoldMs); PORTD &= 0B111000011;} 
if ((key) == 0x5F) {Serial.println("  U pressed 7 ");     PORTD |= 0B111110011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x60) {Serial.println("  U pressed 8 ");     PORTD |= 0B111010011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x61) {Serial.println("  U pressed 9 ");     PORTD |= 0B111100011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x58) {Serial.println("  U pressed ent");    PORTD |= 0B111000111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x54) {Serial.println("  U pressed / (F1)"); PORTD |= 0B111001011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x55) {Serial.println("  U pressed * (F2)"); PORTD |= 0B111101011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x2A) {Serial.println("  U pressed < (F3)"); PORTD |= 0B111011011; delay(outputHoldMs); PORTD &= 0B111000011;}

if ((key) == 0x57) {Serial.println("  U pressed (+) take frequncy up "); 
PORTC &= ~_BV(PC0);
PORTC &= ~_BV(PC1);
PORTC |= _BV(PC0);
delay(outputHoldMs);
PORTC |= _BV(PC1);
delay(outputHoldMs);
PORTC &= ~_BV(PC0);
delay(outputHoldMs);
PORTC &= ~_BV(PC1);
delay(outputHoldMs);
}

if ((key) == 0x56) {Serial.println("  U pressed (-) take frequency down "); 
PORTC &= ~_BV(PC0);
PORTC &= ~_BV(PC1);
PORTC |= _BV(PC1);
delay(outputHoldMs);
PORTC |= _BV(PC0);
delay(outputHoldMs);
PORTC &= ~_BV(PC1);
delay(outputHoldMs);
PORTC &= ~_BV(PC0);
delay(outputHoldMs);
}

if ((key) == 0x2B) {Serial.println("  U pressed (<>) change Frequency to 40m CW");   
PORTD |= 0B111110011; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111010111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111011111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111011111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111000111; delay(outputHoldMs); PORTD &= 0B111000011;
}

if ((key) == 0x2E) {Serial.println("  U pressed (=) change frequency to 80M CW");   
PORTD |= 0B111110111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111010111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111001111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111001111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;
}

}

USB     Usb;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);
KbdRptParser Prs;

void setup()
{
  Serial.begin( 115200 );
  Serial.println("Start");
  if (Usb.Init() == -1)
  Serial.println("OSC did not start.");
  delay( 200 );
  HidKeyboard.SetReportParser(0, &Prs);
  DDRD |= 0B000111100;
  DDRC |= 0B000000011;
}

void loop()
{
  Usb.Task();
 }

The report from the keypad is as follows:

Start
0000: 05 01 09 06 A1 01 05 08 19 01 29 03 15 00 25 01 
0010: 75 01 95 03 91 02 95 05 91 01 05 07 19 E0 29 E7 
0020: 95 08 81 02 75 08 95 01 81 01 19 00 29 91 26 FF 
0030: 00 95 06 81 00 C0 
Usage Page Gen Desktop Ctrls(01)
Usage Keypad
Collection Application
Usage Page LEDs(08)
Usage Min(01)
Usage Max(03)
Logical Min(00)
Logical Max(01)
Report Size(01)
Report Count(03)
Output(00000010)
Report Count(05)
Output(00000001)
Usage Page Kbrd/Keypad(07)
Usage Min(E0)
Usage Max(E7)
Report Count(08)
Input(00000010)
Report Size(08)
Report Count(01)
Input(00000001)
Usage Min(00)
Usage Max(91)
Logical Max(FF00)
Report Count(06)
Input(00000000)
End Collection

Unfortunately pressing any of the three keys mentioned above, [ or ] or =, results in the sending of a 4 bit code for each of the 3 hex digits returned by the parser. In other words, pressing any of the keys in question results in 3 codes being issued.

I can tell by using the standard program for the boot keyboard found in the Arduino IDE examples that the keys in question are linked to the LEFT ALT key. I have tried to use the report parser for the control keys as a means to set a flag that can be used to get the functionality I am looking for but this does not eliminate the reporting of the three hex digits which are the problem.

I would appreciate any suggestions and advice on how to turn the three values returned by onKeyDown parser when one of the keys in question is pressed into one unique value for that key.

Thank you,

Tony

When you receive a 0x0 character you know there are going to be two more characters. Set a counter to 2. Handle those two keys by putting them in a buffer. When the second key arrives, interpret the two keys.

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
  byte outputHoldMs = 50;
  
  static byte bufferCounter = 0;
  static byte buffer[2];
  
  if (bufferCounter == 2)
  {
    buffer[0] = key;
    bufferCounter--;
    return;
  }
  
  if (bufferCounter == 1)
  {
    buffer[1] = key;
    bufferCounter--;


    //  We now have both of the keys after the initial 0x00.
    if (buffer[0] == 0x04 && buffer[1] == 0x00) // Left Square Bracket
    {
      // Handle Left Square Bracket
    }


    if (buffer[0] == 0x04 && buffer[1] == 0x01) // Right Square Bracket
    {
      // Handle Right Square Bracket
    }


    if (buffer[0] == 0x06 && buffer[1] == 0x00) // Equal Sign
    {
      // Handle Equal Sign
    }


    return;
  }


  if (key == 0x00)  // Start of three-key sequence
  {
    bufferCounter = 2;  // Gather two more
    return;
  }

//  The rest of your code goes here

John,

Thank you for taking the time to reply and the perspective on the solution and finally the code.

After looking at the output using the original code I realized that the 0, 4 ,0 outputs were present because of the if statements in the code. The output from the parser was in fact the hex in the if statement that produced the 0,4,0…

I included your code with the correct hex values and tested. Now, when the [ or ] or = keys are pressed only one unique reply is issued by the ProMini. While the issue with the [ and ] and = was solved pressing the 0, zero, key no longer produced an output. This was solved by extending your line of thinking and adding an if statement to your code to check for true press of the zero key with a buffer with anything but the hex that was shown as 4 or 6.

Here is the modified code:

#include <hidboot.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the following include statments in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

class KbdRptParser : public KeyboardReportParser
{
 protected:
 void OnKeyDown  (uint8_t mod, uint8_t key);
};

  static byte bufferCounter = 0;
  static byte buffer[2];

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
{
  
byte outputHoldMs = 50;

if ((key)== 0x62);{

  if (bufferCounter == 2)
  {
    buffer[0] = key;
    bufferCounter--;
    return;
  }
  
  if (bufferCounter == 1)
  {
    buffer[1] = key;
    bufferCounter--;


    //  We now have both of the keys after the initial 0x00.

    if (buffer[0] == 0x5C && buffer[1] == 0x62) // Left Square Bracket
    {
     Serial.println("  U pressed left square bracket ");
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;
    }


    if (buffer[0] == 0x5C && buffer[1] == 0x59) // Right Square Bracket
    {
     Serial.println("  U pressed right square bracket ");     
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
    }


    if (buffer[0] == 0x5E && buffer[1] == 0x59) // Equal Sign
    {
      Serial.println("  U pressed equal ");
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;  delay(outputHoldMs);
     PORTD |= 0B111111111;  delay(outputHoldMs); PORTD &= 0B111000011;
    }

     
   return;
  }



  if (key == 0x62)  // Start of three-key sequence
  {
    bufferCounter = 2;  // Gather two more
  
  if (key==0x62 && (buffer[0] != 0x5C && buffer[0] != 0x5E) )
    {
      Serial.println("  U pressed 0 ");     
      PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;
    }
    
    return;
  }

}


if ((key) == 0x63) {Serial.println("  U pressed . ");     PORTD |= 0B111010111; delay(outputHoldMs); PORTD &= 0B111000011;}  
if ((key) == 0x62) {Serial.println("  U pressed 0 ");     PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x59) {Serial.println("  U pressed 1 ");     PORTD |= 0B111011111; delay(outputHoldMs); PORTD &= 0B111000011;} 
if ((key) == 0x5A) {Serial.println("  U pressed 2 ");     PORTD |= 0B111111111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x5B) {Serial.println("  U pressed 3 ");     PORTD |= 0B111110111; delay(outputHoldMs); PORTD &= 0B111000011;} 
if ((key) == 0x5C) {Serial.println("  U pressed 4 ");     PORTD |= 0B111111011; delay(outputHoldMs); PORTD &= 0B111000011;}  
if ((key) == 0x5D) {Serial.println("  U pressed 5 ");     PORTD |= 0B111001111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x5E) {Serial.println("  U pressed 6 ");     PORTD |= 0B111101111; delay(outputHoldMs); PORTD &= 0B111000011;} 
if ((key) == 0x5F) {Serial.println("  U pressed 7 ");     PORTD |= 0B111110011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x60) {Serial.println("  U pressed 8 ");     PORTD |= 0B111010011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x61) {Serial.println("  U pressed 9 ");     PORTD |= 0B111100011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x58) {Serial.println("  U pressed ent");    PORTD |= 0B111000111; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x54) {Serial.println("  U pressed / (F1)"); PORTD |= 0B111001011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x55) {Serial.println("  U pressed * (F2)"); PORTD |= 0B111101011; delay(outputHoldMs); PORTD &= 0B111000011;}
if ((key) == 0x2A) {Serial.println("  U pressed < (F3)"); PORTD |= 0B111011011; delay(outputHoldMs); PORTD &= 0B111000011;}

if ((key) == 0x57) {Serial.println("  U pressed (+) take frequncy up "); 
PORTC &= ~_BV(PC0);
PORTC &= ~_BV(PC1);
PORTC |= _BV(PC0);
delay(outputHoldMs);
PORTC |= _BV(PC1);
delay(outputHoldMs);
PORTC &= ~_BV(PC0);
delay(outputHoldMs);
PORTC &= ~_BV(PC1);
delay(outputHoldMs);
}

if ((key) == 0x56) {Serial.println("  U pressed (-) take frequency down "); 
PORTC &= ~_BV(PC0);
PORTC &= ~_BV(PC1);
PORTC |= _BV(PC1);
delay(outputHoldMs);
PORTC |= _BV(PC0);
delay(outputHoldMs);
PORTC &= ~_BV(PC1);
delay(outputHoldMs);
PORTC &= ~_BV(PC0);
delay(outputHoldMs);
}

if ((key) == 0x2B) {Serial.println("  U pressed (<>) change Frequency to 40m CW");   
PORTD |= 0B111110011; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111010111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111011111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111011111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111000111; delay(outputHoldMs); PORTD &= 0B111000011;
}

if ((key) == 0x67) {Serial.println("  U pressed (=) change frequency to 80M CW");   
PORTD |= 0B111110111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111010111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111001111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111001111; delay(outputHoldMs); PORTD &= 0B111000011;
PORTD |= 0B111100111; delay(outputHoldMs); PORTD &= 0B111000011;
}

}

USB     Usb;
HIDBoot<USB_HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);
KbdRptParser Prs;

void setup()
{
  Serial.begin( 115200 );
  Serial.println("Start");
  if (Usb.Init() == -1)
  Serial.println("OSC did not start.");
  delay( 200 );
  HidKeyboard.SetReportParser(0, &Prs);
  DDRD |= 0B000111100;
  DDRC |= 0B000000011;

}

void loop()
{
  Usb.Task();
}

Now that the [, ], =, keys are reporting correctly I will write some code to issue a series of instructions when they are pressed.

I really appreciate the help, code and thoughts on how to look at the problem.

Tony

if ((key)== 0x62);{

That ‘;’ is the only statement inside the ‘if’ to that ‘if’ statement is probably not doing what you intended.