I posted about this already, in this thread:
http://www.sudomod.com/forum/viewtopic. ... =373#p3993
But I went the joystick route for my GBZ. Here's the code I used:
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());
}
}
One thing that wasn't immediately obvious was that if you don't initialize all the analog axes to their resting states (512), then as soon as any button is input they all go to zero and cause anything expecting analog inputs to glitch out. Also, to get the d-pad working as a hat switch I borrowed some code I found on github which nicely handles all possible combinations of d-pad input.