Page 1 of 1

Teensy gamepad code

Posted: Sat May 28, 2016 10:03 pm
by hencethus
I wanted my buttons to be recognized as a gamepad rather than triggers for keyboard events, so I got it working with this code. It's mostly just example code from Teensyduino, but I did make some modifications, including some extra code to get the d-pad to work as a hat switch. The inputs are in the order of helder's button PCB. I don't think there's probably any practical advantage to this over keyboard events, but I like it better. I don't really write C code, so this could probably use some refactoring, but it works.

Code: Select all

/* Modified example code from Teensyduino
   You must select Joystick from the "Tools > USB Type" menu
*/

#include <Bounce.h>

// Create Bounce objects for each button. The Bounce object
// automatically deals with contact chatter or "bounce", and
// it makes detecting changes very simple.
  Bounce GBZ_LEFT = Bounce(0, 10);
  Bounce GBZ_UP = Bounce(1, 10);  // 10 = 10 ms debounce time
  Bounce GBZ_DOWN = Bounce(2, 10);  // which is appropriate for
  Bounce GBZ_RIGHT = Bounce(3, 10);  // most mechanical pushbuttons
  Bounce GBZ_SELECT = Bounce(4, 10);
  Bounce GBZ_START = Bounce(5, 10);
  Bounce GBZ_X = Bounce(6, 10);
  Bounce GBZ_Y = Bounce(7, 10);
  Bounce GBZ_B = Bounce(8, 10);
  Bounce GBZ_A = Bounce(9, 10);
  Bounce GBZ_L = Bounce(10, 10);
  Bounce GBZ_R = Bounce(11, 10);

  const int numButtons = 12;

  uint8_t hatu = 0;
  uint8_t hatr = 0;
  uint8_t hatd = 0;
  uint8_t hatl = 0;

  // ganked this bit from https://gist.github.com/cleure/5820004
  // bitwise operations return 4 possible states of each d-pad axis
  // so that d-pad value can be looked up from 4x4 array
  /*
  
          0
          UP
      315    45
 270 LT   -1   RT 90
      225    135
          DN
          180
  
  */
  int GetHatState() {
    uint8_t x, y;
    const static int16_t dpad_lookup[4][4] = {
      { -1, 270,  90, -1},
      {  0, 315,  45, -1},
      {180, 225, 135, -1},
      { -1,  -1,  -1, -1}
    };
    
    y = hatu | (hatd << 1);
    x = hatl | (hatr << 1);
    
    return dpad_lookup[y][x];
  }

void setup() {
  // Configure the pins for input mode with pullup resistors.
  // The pushbuttons connect from each pin to ground.  When
  // the button is pressed, the pin reads LOW because the button
  // shorts it to ground.  When released, the pin reads HIGH
  // because the pullup resistor connects to +5 volts inside
  // the chip.
  for (int i=0; i<numButtons; i++) {
    pinMode(i, INPUT_PULLUP);
  }
  
  //  Set all axes to defaults
  Joystick.X(512);
  Joystick.Y(512);
  Joystick.Z(512);
  Joystick.Zrotate(512);
  Joystick.sliderLeft(512);
  Joystick.sliderRight(512);
  Joystick.hat(-1);
}

void loop() {
  // Update all the buttons.  There should not be any long
  // delays in loop(), so this runs repetitively at a rate
  // faster than the buttons could be pressed and released.
  GBZ_LEFT.update();   // 0
  GBZ_UP.update();     // 1
  GBZ_DOWN.update();   // 2
  GBZ_RIGHT.update();  // 3
  GBZ_SELECT.update(); // 4
  GBZ_START.update();  // 5
  GBZ_X.update();      // 6
  GBZ_Y.update();      // 7
  GBZ_B.update();      // 8
  GBZ_A.update();      // 9
  GBZ_L.update();      // 10
  GBZ_R.update();      // 11

  // Check each button for "falling" edge.
  // Update the Joystick buttons only upon changes.

  if (GBZ_B.fallingEdge()) {
    Joystick.button(1, 1);
  }
  if (GBZ_A.fallingEdge()) {
    Joystick.button(2, 1);
  }
  if (GBZ_Y.fallingEdge()) {
    Joystick.button(3, 1);
  }
  if (GBZ_X.fallingEdge()) {
    Joystick.button(4, 1);
  }
  if (GBZ_L.fallingEdge()) {
    Joystick.button(5, 1);
  }
  if (GBZ_R.fallingEdge()) {
    Joystick.button(6, 1);
  }
  if (GBZ_SELECT.fallingEdge()) {
    Joystick.button(7, 1);
  }
  if (GBZ_START.fallingEdge()) {
    Joystick.button(8, 1);
  }
  if (GBZ_UP.fallingEdge()) {
    hatu = 1;
    Joystick.hat(GetHatState());
  }
  if (GBZ_RIGHT.fallingEdge()) {
    hatr = 1;
    Joystick.hat(GetHatState());
  }
  if (GBZ_DOWN.fallingEdge()) {
    hatd = 1;
    Joystick.hat(GetHatState());
  }
  if (GBZ_LEFT.fallingEdge()) {
    hatl = 1;
    Joystick.hat(GetHatState());
  }

  // Check each button for "rising" edge
  // Update the Joystick buttons only upon changes.

  if (GBZ_B.risingEdge()) {
    Joystick.button(1, 0);
  }
  if (GBZ_A.risingEdge()) {
    Joystick.button(2, 0);
  }
  if (GBZ_Y.risingEdge()) {
    Joystick.button(3, 0);
  }
  if (GBZ_X.risingEdge()) {
    Joystick.button(4, 0);
  }
  if (GBZ_L.risingEdge()) {
    Joystick.button(5, 0);
  }
  if (GBZ_R.risingEdge()) {
    Joystick.button(6, 0);
  }
  if (GBZ_SELECT.risingEdge()) {
    Joystick.button(7, 0);
  }
  if (GBZ_START.risingEdge()) {
    Joystick.button(8, 0);
  }
  if (GBZ_UP.risingEdge()) {
    hatu = 0;
    Joystick.hat(GetHatState());
  }
  if (GBZ_RIGHT.risingEdge()) {
    hatr = 0;
    Joystick.hat(GetHatState());
  }
  if (GBZ_DOWN.risingEdge()) {
    hatd = 0;
    Joystick.hat(GetHatState());
  }
  if (GBZ_LEFT.risingEdge()) {
    hatl = 0;
    Joystick.hat(GetHatState());
  }
}

Re: Teensy gamepad code

Posted: Fri Nov 16, 2018 7:05 am
by murrman92
I just built my first GBZ and I used your code for my Teensy! I like that it registers as a gamepad instead of keyboard strokes as it makes it easier to navigate the RetroPie config menus. Did you have any trouble with buttons double tapping when you used this code?

Re: Teensy gamepad code

Posted: Mon Apr 29, 2019 2:24 pm
by George.p
hi, how do you wire the analog joystick to the teensy? thanks a lot

Re: Teensy gamepad code

Posted: Sun May 05, 2019 8:56 am
by BlastoSupreme
This is really neat! Thanks for putting in all the comments in the code. It really helps someone like me who has absolutely no idea what they're doing code wise. <3

Re: Teensy gamepad code

Posted: Sat Aug 03, 2019 11:19 am
by Theconartist03
My button pcb is the same layout but I wired it to the teensy as gnd, up, down, left, right, start, select, a, b, x, y. Will this code work for that.

Re: Teensy gamepad code

Posted: Sat Aug 03, 2019 12:15 pm
by infinitLoop
Theconartist03 wrote:
Sat Aug 03, 2019 11:19 am
My button pcb is the same layout but I wired it to the teensy as gnd, up, down, left, right, start, select, a, b, x, y. Will this code work for that.
just link the pin (number) with the button in the script:

Bounce GBZ_X = Bounce(6, 10);

that links "X" button with pin 6 (with a 10 milisecond bounce)


.

Re: Teensy gamepad code

Posted: Sat Aug 03, 2019 7:04 pm
by Theconartist03
Do I also need to edit the update all the buttons, the falling edge or the rising edge?