Teensy LC as USB Joystick with Teensyduino on Windows - Buttons not working

JayArrr

New member
Hi,

I've successfully completed Teensy Projects with the Teenys 2.0 before and wanted to get into the Teensy LC. For this, I came up with a PCB design for a custom gamepad with 16 (on)-off-(on) switches and had in manufactured.

Both assembly and HW testing went well. Now, i am struggling with the Software part.
Initially I had planned on using QMK to program the Teensy but soon gave up due to the (from what I could tell) bad Joystick-support for the Teensy MCU within QMK.

Now, I am using Teensyduino but I have trouble getting the Joystick buttons to work

Here is what I am trying so far
1) use the KeyPad library to get the state-changes of the switches (note for anyone who stumbles upon this: I had to modify KeyPad.cpp to not be active-low in Keypad::scanKeys() so it works with a Keyboard matrix with diodes)
2) if a switch is "pressed", send
Code:
Joystick.button(idx, 1);
3) if a switch is "released", send
Code:
Joystick.button(idx, 0);
Note: I'm tryuing to use the useManualSend feature but the effect is the same with or without it

Complete code:
Code:
/* @file MultiKey.ino
|| @version 1.0
|| @author Mark Stanley
|| @contact mstanley@technologist.com
||
|| @description
|| | The latest version, 3.0, of the keypad library supports up to 10
|| | active keys all being pressed at the same time. This sketch is an
|| | example of how you can get multiple key presses from a keypad or
|| | keyboard.
|| #
*/

#include <Keypad.h>

const byte ROWS = 8;
const byte COLS = 4;

char keys[ROWS][COLS] = {
  {'0', '1', '2', '3'},
  {'4', '5', '6', '7'},
  {'8', '9', 'a', 'b'},
  {'c', 'd', 'e', 'f'},
  {'g', 'h', 'i', 'j'},
  {'k', 'l', 'm', 'n'},
  {'o', 'p', 'q', 'r'},
  {'s', 't', 'u', 'v'}
};
byte rowPins[ROWS] = {8, 4, 1, 3, 23, 22, 15, 19};
byte colPins[COLS] = {5, 16, 17, 21};

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

unsigned long loopCount;
unsigned long startTime;
String msg;


void setup() {
    Serial.begin(115200);
    loopCount = 0;
    startTime = millis();
    msg = "";

    Joystick.useManualSend(true);
}


void loop() {
    loopCount++;
    if ( (millis()-startTime)>5000 ) {
        Serial.print("Average loops per second = ");
        Serial.println(loopCount/5);
        startTime = millis();
        loopCount = 0;
    }

    // Fills kpd.key[ ] array with up-to 10 active keys.
    // Returns true if there are ANY active keys.
    if (kpd.getKeys())
    {
        for (int i=0; i<LIST_MAX; i++)   // Scan the whole key list.
        {
            if ( kpd.key[i].stateChanged )   // Only find keys that have changed state.
            {
                switch (kpd.key[i].kstate) {  // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
                    case PRESSED:
                    msg = " PRESSED.";
                    Joystick.button(kpd.key[i].kcode, 1);
                break;
                case HOLD:
                    msg = " HOLD.";
                break;
                    case RELEASED:
                    msg = " RELEASED.";
                    Joystick.button(kpd.key[i].kcode, 0);
                break;
                case IDLE:
                    msg = " IDLE.";
                }
                Joystick.send_now();
                
                Serial.print("Key ");
                Serial.print(kpd.key[i].kchar);
                Serial.print(" Code: ");
                Serial.print(kpd.key[i].kcode);
                Serial.println(msg);
            }
        }
    }
}  // End loop

From the serial port, I can see, that the switch press/releases are detected very well. However, Windows does not recognize any Joystick button presses:
2022-07-29 17_40_00-COM8 (Teensy) Serial+Keyboard+Mouse+Joystick.png
2022-07-29 17_40_54-mfd-switchpanel _ Arduino 1.8.19.png

Do you folks have an idea on why the joystick buttons might not be registered by windows?
Any help is greatly appreciated.
Cheers
JR
 
I could be wrong, but I am thinking it is probably the lines like:
Code:
Joystick.button(kpd.key[i].kcode, 1)

Where I believe the values for the keycode are something like ASCII '0' '1' ...

Where I believe the joystick buttons are a numeric value between 0 and 31

And '0' has a ascii value of 48 decimal so it will probably fail the call.

Edit probably wrong as the code looks like it is different
 
Hi, thanks for jumping in :)

I just had a look at the source of KeyPad.cpp. Keycode is calculated like this:
Code:
int keyCode = r * sizeKpd.columns + c;
so I assume it is a numeric value.

Besides that, I have good news and bad news:
bad: I tried settting values for slider/axis etc in the code as well but they do not show up in windows.

good news: I found two programs, that in fact DO recognize the switch-actuations: Joystick Gremlin and DCS (Digital Combat Simulator, which is the game, I wanted to use this gamepad in the first place)
So even though windows is acting up a bit, it seems like I can proceed like this.
 
Back
Top