Skip to content

Instantly share code, notes, and snippets.

@kesslern
Created February 22, 2020 19:56
Show Gist options
  • Select an option

  • Save kesslern/444b1f49612dc6f4959b5077736223e0 to your computer and use it in GitHub Desktop.

Select an option

Save kesslern/444b1f49612dc6f4959b5077736223e0 to your computer and use it in GitHub Desktop.
Firmware for Kevin's Toggle Box Gamepad
// Kevin's Toggle Box gamepad firmware v1.0
//
// Copyright 2020 Nathan Kessler
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee
// is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Compiling this firmware first requires installing the Arduino Joystick Library:
// https://github.com/MHeironimus/ArduinoJoystickLibrary
//
// Configuration:
// - Choose between TOGGLE and TAP functionality for each gamepad switch.
// - Reorder the buttons
//
// Current button order:
//
// +----------------------------------+
// | |
// | 0 1 3 5 7 9 |
// | + + + + + + |
// | | | | | | | |
// | +++ +++ +++ +++ +++ +++ |
// | 2 4 6 8 10 |
// | |
// +----------------------------------+
//
// Note: all toggles are bidirectional but the left-most toggle.
#include <Joystick.h>
#define TOGGLE 1
#define TAP 2
// The number of loops to hold buttons when tap button is activated
#define HOLD_CYCLES 25
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD,
11, 0, // Button Count, Hat Switch Count
false, false, false, // X and Y, but no Z Axis
false, false, false, // No Rx, Ry, or Rz
false, false, // No rudder or throttle
false, false, false); // No accelerator, brake, or steering
// The pin each button uses
int buttonPins[11] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 14};
// The gamepad button number that each pin corresponds to
int buttonMapping[11] = { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 0 };
// The type of each button. Ordered by gamepad buttons 0 - 11
int buttonTypes[11] = { TOGGLE, TAP, TAP, TAP, TAP, TAP, TAP, TAP, TAP, TAP, TAP };
void setup() {
// Initialize Button Pins
for (int index = 0; index < 11; index++) {
int pin = buttonPins[index];
pinMode(pin, INPUT_PULLUP);
}
Joystick.begin();
}
// Last state of the buttons
// For toggle buttons, 1 == on, 0 == off
// For tap buttons, and number > 0 is on. This number counts up to HOLD_CYCLES. It is reset when the button is deactivated.
int lastButtonState[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
void loop() {
// Read pin values
for (int index = 0; index < 11; index++) {
int pin = buttonPins[index];
int joystickButton = buttonMapping[index];
int type = buttonTypes[joystickButton];
int currentButtonState = !digitalRead(pin);
int lastState = lastButtonState[index];
if (type == TOGGLE && currentButtonState != lastState) {
Joystick.setButton(joystickButton, currentButtonState);
lastButtonState[index] = currentButtonState;
} else if (type == TAP) {
if (lastState > 0 && lastState < HOLD_CYCLES) {
if (++lastButtonState[index] == HOLD_CYCLES) {
Joystick.setButton(joystickButton, 0);
}
} else if (lastState >= HOLD_CYCLES && currentButtonState == 0) {
lastButtonState[index] = 0;
} else if (lastButtonState[index] == 0 && currentButtonState == 1) {
lastButtonState[index] = 1;
Joystick.setButton(joystickButton, 1);
}
}
}
delay(10);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment