Last active
November 20, 2017 11:40
-
-
Save halferty/89d7720ddc892b58a665aadee47a47c0 to your computer and use it in GitHub Desktop.
Arduino Leonardo Gamepad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "HID.h" | |
#define BUTTON1_PIN 2 | |
#define BUTTON2_PIN 3 | |
#define BUTTON3_PIN 4 | |
#define BUTTON4_PIN 5 | |
#define BUTTON5_PIN 6 | |
#define BUTTON6_PIN 7 | |
#define BUTTON7_PIN 8 | |
#define BUTTON8_PIN 9 | |
#define BUTTON9_PIN 10 | |
#define BUTTON10_PIN 16 | |
#define UP_PIN 14 | |
#define RIGHT_PIN 15 | |
#define DOWN_PIN A0 | |
#define LEFT_PIN A1 | |
// Let's make it mimic the xbox controller button mappings... | |
#define B_BUTTON_MAPPING 1 | |
#define X_BUTTON_MAPPING 2 | |
#define Y_BUTTON_MAPPING 3 | |
#define A_BUTTON_MAPPING 0 | |
#define LT_BUTTON_MAPPING 8 | |
#define RT_BUTTON_MAPPING 9 | |
#define LB_BUTTON_MAPPING 4 | |
#define RB_BUTTON_MAPPING 5 | |
#define BACK_BUTTON_MAPPING 6 | |
#define START_BUTTON_MAPPING 7 | |
static const uint8_t _hidReportDescriptor[] PROGMEM = { | |
0x05, 0x01, // USAGE_PAGE (Generic Desktop) | |
0x09, 0x04, // USAGE (Joystick) | |
0xa1, 0x01, // COLLECTION (Application) | |
0x85, 0x03, // REPORT_ID | |
0x05, 0x09, // USAGE_PAGE (Button) | |
0x19, 0x01, // USAGE_MINIMUM (Button 1) | |
0x29, 0x10, // USAGE_MAXIMUM (Button 16) | |
0x15, 0x00, // LOGICAL_MINIMUM (0) | |
0x25, 0x01, // LOGICAL_MAXIMUM (1) | |
0x75, 0x01, // REPORT_SIZE (1) | |
0x95, 0x10, // REPORT_COUNT (16) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
0x05, 0x01, // USAGE_PAGE (Generic Desktop) | |
0xa1, 0x00, // COLLECTION (Physical) | |
0x09, 0x30, // USAGE (X) | |
0x09, 0x31, // USAGE (Y) | |
0x09, 0x33, // USAGE (Rx) | |
0x09, 0x34, // USAGE (Ry) | |
0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768) | |
0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767) | |
0x75, 0x10, // REPORT_SIZE (16) | |
0x95, 0x04, // REPORT_COUNT (4) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
0x09, 0x32, // USAGE (Z) | |
0x09, 0x35, // USAGE (Rz) | |
0x15, 0x80, // LOGICAL_MINIMUM (-128) | |
0x25, 0x7F, // LOGICAL_MAXIMUM (127) | |
0x75, 0x08, // REPORT_SIZE (8) | |
0x95, 0x02, // REPORT_COUNT (2) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
0xc0, // END_COLLECTION | |
0x05, 0x01, // USAGE_PAGE (Generic Desktop) | |
0x09, 0x39, // USAGE (Hat switch) | |
0x09, 0x39, // USAGE (Hat switch) | |
0x15, 0x01, // LOGICAL_MINIMUM (1) | |
0x25, 0x08, // LOGICAL_MAXIMUM (8) | |
0x95, 0x02, // REPORT_COUNT (2) | |
0x75, 0x04, // REPORT_SIZE (4) | |
0x81, 0x02, // INPUT (Data,Var,Abs) | |
0xc0 // END_COLLECTION | |
}; | |
typedef struct { | |
uint16_t buttons; | |
int16_t xAxis; | |
int16_t yAxis; | |
int16_t rxAxis; | |
int16_t ryAxis; | |
int8_t zAxis; | |
int8_t rzAxis; | |
uint8_t dpad; | |
} PadReport; | |
class Gamepad { | |
private: | |
PadReport padReport; | |
public: | |
Gamepad(void) { | |
static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor)); | |
HID().AppendDescriptor(&node); | |
padReport.buttons = 0; | |
} | |
void begin(void) {} | |
void end(void) {} | |
void sendUpdate(void) { HID().SendReport(0x03, &padReport, sizeof(PadReport)); } | |
void setButtonState(uint8_t button, bool state) { | |
(state == true) ? bitSet(padReport.buttons, button) : bitClear(padReport.buttons, button); | |
} | |
void setDPad(bool up, bool right, bool down, bool left) { | |
padReport.dpad = 0; | |
if (up && right) { | |
padReport.dpad = 0x20; | |
} else if (up && left) { | |
padReport.dpad = 0x80; | |
} else if (down && right) { | |
padReport.dpad = 0x40; | |
} else if (down && left) { | |
padReport.dpad = 0x60; | |
} else if (up) { | |
padReport.dpad = 0x10; | |
} else if (right) { | |
padReport.dpad = 0x30; | |
} else if (down) { | |
padReport.dpad = 0x50; | |
} else if (left) { | |
padReport.dpad = 0x70; | |
} | |
} | |
}; | |
Gamepad gamepad; | |
void setup() { | |
pinMode(BUTTON1_PIN, INPUT_PULLUP); | |
pinMode(BUTTON2_PIN, INPUT_PULLUP); | |
pinMode(BUTTON3_PIN, INPUT_PULLUP); | |
pinMode(BUTTON4_PIN, INPUT_PULLUP); | |
pinMode(BUTTON5_PIN, INPUT_PULLUP); | |
pinMode(BUTTON6_PIN, INPUT_PULLUP); | |
pinMode(BUTTON7_PIN, INPUT_PULLUP); | |
pinMode(BUTTON8_PIN, INPUT_PULLUP); | |
pinMode(BUTTON9_PIN, INPUT_PULLUP); | |
pinMode(BUTTON10_PIN, INPUT_PULLUP); | |
pinMode(UP_PIN, INPUT_PULLUP); | |
pinMode(RIGHT_PIN, INPUT_PULLUP); | |
pinMode(DOWN_PIN, INPUT_PULLUP); | |
pinMode(LEFT_PIN, INPUT_PULLUP); | |
} | |
void loop() { | |
gamepad.setButtonState(B_BUTTON_MAPPING, !digitalRead(BUTTON1_PIN)); | |
gamepad.setButtonState(X_BUTTON_MAPPING, !digitalRead(BUTTON2_PIN)); | |
gamepad.setButtonState(Y_BUTTON_MAPPING, !digitalRead(BUTTON3_PIN)); | |
gamepad.setButtonState(A_BUTTON_MAPPING, !digitalRead(BUTTON4_PIN)); | |
gamepad.setButtonState(LT_BUTTON_MAPPING, !digitalRead(BUTTON5_PIN)); | |
gamepad.setButtonState(RT_BUTTON_MAPPING, !digitalRead(BUTTON6_PIN)); | |
gamepad.setButtonState(LB_BUTTON_MAPPING, !digitalRead(BUTTON7_PIN)); | |
gamepad.setButtonState(RB_BUTTON_MAPPING, !digitalRead(BUTTON8_PIN)); | |
gamepad.setButtonState(BACK_BUTTON_MAPPING, !digitalRead(BUTTON9_PIN)); | |
gamepad.setButtonState(START_BUTTON_MAPPING, !digitalRead(BUTTON10_PIN)); | |
gamepad.setDPad(!digitalRead(UP_PIN),!digitalRead(RIGHT_PIN),!digitalRead(DOWN_PIN),!digitalRead(LEFT_PIN)); | |
gamepad.sendUpdate(); | |
delay(10); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment