Skip to content

Instantly share code, notes, and snippets.

@steffex
Forked from cleure/teensy-gamepad.c
Created January 13, 2014 21:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steffex/8408624 to your computer and use it in GitHub Desktop.
Save steffex/8408624 to your computer and use it in GitHub Desktop.
#include <stdint.h>
// GPIO pins used for connected gamepad
#define CLOCK 21
#define LATCH 20
#define DATA 19
#define DEVICE_TYPE_NES 0
#define DEVICE_TYPE_SNES 1
enum {
NES_BUTTON_A,
NES_BUTTON_B,
NES_BUTTON_SELECT,
NES_BUTTON_START,
NES_DPAD_UP,
NES_DPAD_DOWN,
NES_DPAD_LEFT,
NES_DPAD_RIGHT
} NES_BUTTON_MAP;
enum {
SNES_BUTTON_B,
SNES_BUTTON_Y,
SNES_BUTTON_SELECT,
SNES_BUTTON_START,
SNES_DPAD_UP,
SNES_DPAD_DOWN,
SNES_DPAD_LEFT,
SNES_DPAD_RIGHT,
SNES_BUTTON_A,
SNES_BUTTON_X,
SNES_BUTTON_L,
SNES_BUTTON_R,
} SNES_BUTTON_MAP;
uint8_t BUTTON_STATE[16];
uint8_t DEVICE_TYPE = 0;
// Delay for approx 100ns. Assumes 16Mhz AtMega CPU
void delay100ns()
{
__asm__ __volatile__ ("nop\n\t");
__asm__ __volatile__ ("nop\n\t");
}
void ReadInput(uint8_t *data, int num)
{
int i;
// Init
digitalWrite(CLOCK, HIGH);
// Take sample
digitalWrite(LATCH, HIGH);
delay100ns();
digitalWrite(LATCH, LOW);
// Read output
for (i = 0; i < num; i++) {
delay100ns();
digitalWrite(CLOCK, LOW);
// 1 = Off, 0 = On... Bit must be inverted
data[i] = (~digitalRead(DATA)) & 0x1;
delay100ns();
digitalWrite(CLOCK, HIGH);
}
}
int GetHatState()
{
/*
0
UP
315 45
270 LT RT 90
225 135
DN
180
*/
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 = BUTTON_STATE[NES_DPAD_UP] | (BUTTON_STATE[NES_DPAD_DOWN] << 1);
x = BUTTON_STATE[NES_DPAD_LEFT] | (BUTTON_STATE[NES_DPAD_RIGHT] << 1);
return dpad_lookup[y][x];
}
void ProcessInputNES()
{
int hat0;
ReadInput((uint8_t *)&BUTTON_STATE, 8);
hat0 = GetHatState();
Joystick.button(1, BUTTON_STATE[NES_BUTTON_A]);
Joystick.button(2, BUTTON_STATE[NES_BUTTON_B]);
Joystick.button(3, BUTTON_STATE[NES_BUTTON_SELECT]);
Joystick.button(4, BUTTON_STATE[NES_BUTTON_START]);
Joystick.hat(hat0);
}
void ProcessInputSNES()
{
int hat0;
ReadInput((uint8_t *)&BUTTON_STATE, 8);
hat0 = GetHatState();
Joystick.button(1, BUTTON_STATE[SNES_BUTTON_A]);
Joystick.button(2, BUTTON_STATE[SNES_BUTTON_B]);
Joystick.button(3, BUTTON_STATE[SNES_BUTTON_X]);
Joystick.button(4, BUTTON_STATE[SNES_BUTTON_Y]);
Joystick.button(5, BUTTON_STATE[SNES_BUTTON_L]);
Joystick.button(6, BUTTON_STATE[SNES_BUTTON_R]);
Joystick.button(7, BUTTON_STATE[SNES_BUTTON_SELECT]);
Joystick.button(8, BUTTON_STATE[SNES_BUTTON_START]);
Joystick.hat(hat0);
}
void setup() {
pinMode(CLOCK, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(DATA, INPUT);
}
void loop() {
if (DEVICE_TYPE == DEVICE_TYPE_NES) {
ProcessInputNES();
} else {
ProcessInputSNES();
}
delayMicroseconds(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment