Teensy 4.0 keyboard issues.

NickM

Member
Hi,

I am new to this forum and hopefully this question has not been asked before…

I have been using a Teensy 3.2 to read 4 push buttons (using internal pull-ups grounded by a button press) and convert the button presses into USB keystrokes. This is used on a device that is running a stripped-down version of Windows XP SP3 (I have little control of this). The application has been, and still works fine.

The problems arise when this code is run on a Teensy 4.0. Initially, if one button is pressed, the intended keystroke is not sent to the device running the stripped-down version of XP but works fine running on a “normal” Windows XP SP3 computer. When sniffing the USB buss on the problem computer, we see that, when we physically press a button that the key press is not sent, however, when we physically release that same button, a release for that key is sent. In addition, if two buttons are physically pressed and then released simultaneously, both keystrokes are sent and then released normally. As kind of a “hacky” fix, I got it to accept keystrokes on the 4.0 by sending keyboard press and release information twice as follows:

Press:
Keyboard.set_modifier(0);
Keyboard.set_key2(KEY_2);
Keyboard.send_now();
Keyboard.send_now();

Release:
Keyboard.set_modifier(0);
Keyboard.set_key2(0);
Keyboard.send_now();
Keyboard.send_now();

Or…

Keyboard.print("12"); (drops the “1”)

Both of the above examples send a single “2” character on the stripped-down version of Windows XP or TWO characters on the “normal” Windows XP computer. I also have to send 2 releases for the problem system.

I could live with that, but, I also need to send a “return” character to the “Start Windows Normally” prompt on start-up if the stripped-down Windows XP computer was shutdown improperly. Again, this works fine on the “normal” XP computer and when using the Teensy 3.2 on either system.

I am using the following settings:
Board: “Teensy 4.0”
USB Type: “Keyboard”
CPU Speed: “600 Mhz”
Optimize: “Faster”
Keyboard Layout” “US English”

Any help to get this working on the Teensy 4.0 would be greatly appreciated.

Thank You.

-Nick.
 
Welcome Nick,
If a simple example sketch were posted (Forum rule) it would be easier for others to review/copy/edit to reproduce or resolve the issue.

What happens if the button code is removed, and loop() just waits some seconds between: Keyboard.print("12");

Where perhaps the string printed were char szKeys[5] = "1A";

and loop() had something like this that compiles:

// loop()
static char szKeys[5] = "1A";
static char cChange='A';
Keyboard.print( szKeys );
cChange++;
if ( cChange > 'G') {
cChange = 'A';
// maybe send a newline key so results don't scroll off right edge
}
szKeys[1] = cChange;
delay(2000);

If that works as expected {"1A1B1C..."} the issue is perhaps with the interrupt usage, if not then that helps say where to look.
 
Thanks for the quick reply!

Sorry! - I will post an example of my problem code shortly...

For now, here is the output for the version of the code you wanted me to try:

"Normal" XP: 1B1C1D1E1F1G1A1B1C1D1E1F1G

"Stripped Down" XP: BCDEFGABCDEFG

Thanks!



Code:
#include <Keyboard.h>
void setup()
{
} 
  static char szKeys[5] = {'1', 'A'};
  static char cChange = 'A';
1B
void loop()
{
Keyboard.print( szKeys );
cChange++;
if ( cChange > 'G') {
cChange = 'A';
// maybe send a newline key so results don't scroll off right edge
}
szKeys[1] = cChange;
delay(2000);
}
 
Board: “Teensy 4.0”
USB Type: “Keyboard”
CPU Speed: “600 Mhz”
Optimize: “Faster”
Keyboard Layout” “US English”

The output of this code running on a Teensy 4.0 after pressing buttons 1,2,3, then 4:

"Normal" XP: abcd

"Stripped Down" XP: <no output>

No output on "Stripped Down" XP system.

Board: “Teensy 3.1 / 3.2”
USB Type: “Keyboard”
CPU Speed: “72Mhz”
Optimize: “Faster”
Keyboard Layout” “US English”

The output of this code running on a Teensy 3.2 after pressing buttons 1,2,3, then 4:

"Normal" XP: abcd

"Stripped Down" XP: abcd

Works fine on both systems.

Code:
/*
Board: “Teensy 4.0”
USB Type: “Keyboard”
CPU Speed: “600 Mhz”
Optimize: “Faster”
Keyboard Layout” “US English”
 */
#include <Keyboard.h>

#define PIN_D0 0
#define PIN_D1 1
#define PIN_D2 2
#define PIN_D3 3

static int hardExitHold;

static bool LeftKeyIsPressed;
static bool UpKeyIsPressed;
static bool DownKeyIsPressed;
static bool RightKeyIsPressed;

void setup()
{
  delay(500);
  pinMode(PIN_D0, INPUT_PULLUP);
  pinMode(PIN_D1, INPUT_PULLUP);
  pinMode(PIN_D2, INPUT_PULLUP);
  pinMode(PIN_D3, INPUT_PULLUP);

  hardExitHold = 0;

  LeftKeyIsPressed = false;
  UpKeyIsPressed = false;
  DownKeyIsPressed = false;
  RightKeyIsPressed = false;

  Keyboard.begin();
}
void loop()
{
  if (digitalRead(PIN_D0) == 0)
  {
  
  if (!LeftKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key1(KEY_A);

      Keyboard.send_now();
//
      LeftKeyIsPressed = true;
    }
  }
   else
  {
    if (LeftKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key1(0);

      Keyboard.send_now();

      LeftKeyIsPressed = false;
    }
   }
  if (digitalRead(PIN_D1) == 0)
  {
    if (!UpKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key2(KEY_B);
      
      Keyboard.send_now();

      UpKeyIsPressed = true;
    }
  }
  else
  {
    if (UpKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key2(0);

      Keyboard.send_now();

      UpKeyIsPressed = false;
    }
  }

  if (digitalRead(PIN_D2) == 0)
  {
    if (!DownKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key3(KEY_C);

      Keyboard.send_now();

      DownKeyIsPressed = true;
    }
  }
  else
  {
    if (DownKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key3(0);

      Keyboard.send_now();


      DownKeyIsPressed = false;
    }
  }

  if (digitalRead(PIN_D3) == 0)
  {
    if (!RightKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key4(KEY_D);

      Keyboard.send_now();

      RightKeyIsPressed = true;
    }
  }
  else
  {
    if (RightKeyIsPressed)
    {
      Keyboard.set_modifier(0);
      Keyboard.set_key4(0);

      Keyboard.send_now();    

      RightKeyIsPressed = false;    
    }
  }
  //
  // Check for keyboard-mapped hard exit "ALT+F4" (On 3-second hold)
  //
  if (digitalRead(PIN_D0) == 0 && digitalRead(PIN_D1) == 0 && digitalRead(PIN_D2) == 0 && digitalRead(PIN_D3) == 0)
  {
    if (++hardExitHold == 40)
    {
      // Clear all keys, press and hold "ALT F4"
      Keyboard.releaseAll();
      Keyboard.press(KEY_LEFT_ALT);
      Keyboard.press(KEY_F4);

      // Hold for a bit...
      delay(100);

      // Release ALT F4
      Keyboard.releaseAll();

      delay(1000);
    }
  }
  else
  {
    hardExitHold = 0;
  }

  // Small delay, user tested to "feel good" optimization.
  
  delay(75);
}
 
Thanks for the quick reply!

Sorry! - I will post an example of my problem code shortly...

For now, here is the output for the version of the code you wanted me to try:

"Normal" XP: 1B1C1D1E1F1G1A1B1C1D1E1F1G

"Stripped Down" XP: BCDEFGABCDEFG

Thanks!

Cool - p#2 pseudo code looks a lot like that :) - good work. Not sure of the results seen there as "Stripped Down" ?

Here TeensyDuino 1.56 is in use with IDE 1.8.19 running on a Teensy 4.1.

Taking that code here to test ... with some edits to prevent the Teensy_Keyboard from killing my open files :)

Don't have buttons hooked up to test other code ...

I get this complete and expected output from the edited code below:
Code:
Hello World!
1A1B1C1D1E1F1G2A2B2C2D2E2F2G3A3B
Bye! Bye!

Code:
#include <Keyboard.h>
void setup()
{
  delay(2000); // Some delay is required to allow PC to connect 'Teensy_Keyboard'
  Keyboard.print( "Hello World!\n" );
}
static char szKeys[5] = {'1', 'A'};
static char cChange = 'A';
int lCnt = 0;
void loop()
{
  Keyboard.print( szKeys );
  cChange++;
  if ( cChange > 'G') {
    cChange = 'A';
    szKeys[0]++;
  }
  szKeys[1] = cChange;
  delay(2000);
  lCnt++;
  if ( lCnt > 15 ) {
    Keyboard.print( "\nBye! Bye!" );
    while (1);
  }
}
 
Thanks again!

TeensyDuino 1.56 with IDE 1.8.19 running on a Teensy 4.0.

Here is the results from the latest code on the 4.0...

"Normal" XP:

Hello World!
1A1B1C1D1E1F1G2A2B2C2D2E2F2G3A3B
Bye! Bye!

"Stripped Down" XP:

ello World!
1ABCDEFGABCDEFGABBye! Bye!

FYI: The button code seem to be working on my side and I will not be able to get back on this till tomorrow afternoon.


Code:
#include <Keyboard.h>
void setup()
{
  delay(2000); // Some delay is required to allow PC to connect 'Teensy_Keyboard'
  Keyboard.print( "Hello World!\n" );
}
static char szKeys[5] = {'1', 'A'};
static char cChange = 'A';
int lCnt = 0;
void loop()
{
  Keyboard.print( szKeys );
  cChange++;
  if ( cChange > 'G') {
    cChange = 'A';
    szKeys[0]++;
  }
  szKeys[1] = cChange;
  delay(2000);
  lCnt++;
  if ( lCnt > 15 ) {
    Keyboard.print( "\nBye! Bye!" );
    while (1);
  }
}
 
Seems the Teensy and Teensy code is doing the right thing. Problem appears to be in what is running on the "Stripped Down XP" - or how that assumably OLDER machine handle USB? Working right here on Win 11 as on the "Normal" XP.

Question: What would be done to take the "Normal" XP to the same state as the "Stripped Down" XP?

Haven't seen XP much lately - the last one I had to maintain went away a few months back. Not sure what 'stripped' implies/affects that would have it treating 'keyboard' differently. Assume that a physical keyboard attached doesn't show any lost keys? Teensy_Keyboard may present a bit differently having it looking for a specific driver versus the one used to service a physical keyboard - and picking something unfitting. Is there a USB HUB that could be inserted between the Teensy and Stripped XP machine? Perhaps ideally a USB 1 or 2 Hub?

Possibly the "Stripped Down" XP machine is not talking to the Teensy properly on connection creating the proper and complete USB connectivity? Can the "sniffing the USB buss on the problem computer" show any difference in the startup behavior between the two XP machines?
 
Update:

I haven't had time to do any real trouble shooting with the Teensy 4.0 but...

We purchased a Teensy LC and loaded the original code that we used on the 3.2. It works perfectly on the "Normal" and "Stripped Down" XP system (No double sending of any characters).

There must be something different with the 4.0 acting as a USB keyboard compared to the Teensy 3.2 and the LC.

Thanks again for the help!

- Nick.
 
Not surprising the T_4.x might have different "USB" behavior from T_LC given the chip hardware evolution from 12 Mbps to 480 Mbps requiring extensive new Teensy code.

It is perhaps interesting, or even telling, that T_LC works. But, finding or fixing such a problem would require it to be reproducible and understood where the behavior breaks.

Also, Windows USB handling likely evolves from XP >> {vista>>win7>>win8>>} Win 10 >> Win 11. Making it very unique to the 'Stripped XP' setup at hand.

The fact that T_4.0 works on 'normal' XP but not "Stripped", but T_LC does again can only be understood if it is clear what is 'stripped' and how that affects the pairing.
 
Back
Top