Skip to content

Instantly share code, notes, and snippets.

@skogaby
Last active November 23, 2022 04:08
Show Gist options
  • Save skogaby/59331321ba9427996ff1c941a32b05f4 to your computer and use it in GitHub Desktop.
Save skogaby/59331321ba9427996ff1c941a32b05f4 to your computer and use it in GitHub Desktop.
/**
* Before you can use this code, make sure to download needed libraries
* - https://github.com/dmadison/ArduinoXInput
* - https://github.com/FastLED/FastLED
*
* You will also need to add this to your arduino IDE's hardware folder
* - https://github.com/dmadison/ArduinoXInput_AVR
*
* This file was created with the Arduino Leonardo or Pro Micro board in mind.
*
* USAGE: This will cover your basic XInput controller for ONGEKI
*/
#include <EEPROM.h>
#include <FastLED.h>
#include <XInput.h>
// Constants to define which buttons are on which pins
#define BUTTON_L_R 5
#define BUTTON_L_G 4
#define BUTTON_L_B 6
#define BUTTON_R_R 2
#define BUTTON_R_G 1
#define BUTTON_R_B 0
#define MENU_L 7
#define MENU_R 8
#define SIDE_L 9
#define SIDE_R 10
// Pin that the lever potentiometer outputs to
#define LEVER_PIN A0
// Min and max values for the triggers for XInput
#define TRIGGER_MIN 0
#define TRIGGER_MAX 512
// Flag to check in EEPROM for whether we've calibrated
#define CALIBRATION_FLAG 0xAE
// LED config for the button lights
#define LED_PIN 11
#define NUM_LEDS 12
CRGB leds[NUM_LEDS];
// All the button pins
byte buttonPins[] = {
BUTTON_L_R, BUTTON_L_G, BUTTON_L_B, // Left face buttons
BUTTON_R_R, BUTTON_R_G, BUTTON_R_B, // Right face buttons
MENU_L, MENU_R, // Menu buttons
SIDE_L, SIDE_R // Side buttons
};
// The min and max values of the lever pot, so we can map them to the trigger values correctly
int leverMin;
int leverMax;
int leverCenter;
int leverValue;
// Function prototypes
void setFinalLEDColors();
void setAllLEDs(CRGB color);
void calibrateLever();
// Init
void setup() {
// Pin setup
pinMode(LEVER_PIN, INPUT);
for (int i = 0; i < sizeof(buttonPins); i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
// LED setup
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
// Controller setup
XInput.setTriggerRange(TRIGGER_MIN, TRIGGER_MAX);
XInput.setAutoSend(false);
XInput.begin();
// Flash all LEDs 3 times
for (int i = 0; i < 3; i++) {
setAllLEDs(CRGB::Purple);
delay(500);
setAllLEDs(CRGB::Yellow);
delay(500);
}
// Calibrate the lever
calibrateLever();
// Set the final LED colors
setFinalLEDColors();
}
// Main loop
void loop() {
// Read all the inputs and set the outputs according to how Segatools processes the XInput.
// The left RGB buttons are mapped to the d-pad: up (green), left (red), and right (blue)
XInput.setDpad(!digitalRead(BUTTON_L_G), !digitalRead(BUTTON_L_G), !digitalRead(BUTTON_L_R), !digitalRead(BUTTON_L_B), false);
// The right RGB buttons, side buttons, and menu buttons are mapped to controller buttons
XInput.setButton(BUTTON_X, !digitalRead(BUTTON_R_R));
XInput.setButton(BUTTON_Y, !digitalRead(BUTTON_R_G));
XInput.setButton(BUTTON_B, !digitalRead(BUTTON_R_B));
XInput.setButton(BUTTON_LB, !digitalRead(SIDE_L));
XInput.setButton(BUTTON_RB, !digitalRead(SIDE_R));
XInput.setButton(BUTTON_BACK, !digitalRead(MENU_L));
XInput.setButton(BUTTON_START, !digitalRead(MENU_R));
// The lever is mapped to the triggers. Left half of the lever maps to left trigger,
// right half of the lever maps to right trigger. Both triggers unpressed is center of the lever.
leverValue = analogRead(LEVER_PIN);
XInput.setTrigger(TRIGGER_LEFT, min(TRIGGER_MAX, max(0, map(leverValue, leverCenter, leverMin, TRIGGER_MIN, TRIGGER_MAX))));
XInput.setTrigger(TRIGGER_RIGHT, min(TRIGGER_MAX, max(0, map(leverValue, leverCenter, leverMax, TRIGGER_MIN, TRIGGER_MAX))));
// Send control data to the computer
XInput.send();
}
// Initialize the LEDs to the correct colors
void setFinalLEDColors() {
leds[0] = CRGB::Purple; // Side-L
leds[1] = CRGB::Purple; // Side-L
leds[2] = CRGB::Yellow; // Menu-R
leds[3] = CRGB::Blue; // Right Blue
leds[4] = CRGB::Green; // Right Green
leds[5] = CRGB::Red; // Right Red
leds[6] = CRGB::Blue; // Left Blue
leds[7] = CRGB::Green; // Left Green
leds[8] = CRGB::Red; // Left Red
leds[9] = CRGB::Red; // Menu-L
leds[10] = CRGB::Purple; // Side-R
leds[11] = CRGB::Purple; // Side-R
FastLED.show();
}
// Sets all the LEDs to the given color
void setAllLEDs(CRGB color) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = color;
}
FastLED.show();
}
// Calibrate the lever so we can map the pot values to trigger inputs
void calibrateLever() {
// We'll only calibrate if:
// * We have never calibrated before according to the flag in EEPROM, or
// * The left-side RGB buttons are being held
boolean needsCalibration = false;
byte calibrationFlag;
EEPROM.get(0, calibrationFlag);
if (calibrationFlag != CALIBRATION_FLAG) {
needsCalibration = true;
}
// If the flag was set in EEPROM, still check the buttons
if (!digitalRead(BUTTON_L_R) &&
!digitalRead(BUTTON_L_G) &&
!digitalRead(BUTTON_L_B)) {
needsCalibration = true;
}
if (needsCalibration) {
// Recalibrate if needed and store the values in EEPROM.
// First, just set all the lights red.
setAllLEDs(CRGB::Red);
// Now, we'll wait for input from the Menu-L button, this signifies that
// we should read the current value as leverMin
while (digitalRead(MENU_L)) {
delay(50);
}
leverMin = analogRead(LEVER_PIN);
// Next, set the lights yellow so we know step 1 is done
setAllLEDs(CRGB::Yellow);
// Now, wait for input from the Menu-R button, this signifies that
// we should read the current value as leverMax
while (digitalRead(MENU_R)) {
delay(50);
}
leverMax = analogRead(LEVER_PIN);
// Pre-calculate the values we need during lever->trigger conversion
leverCenter = ((leverMax + leverMin) / 2);
// Write leverMin and leverMax to EEPROM, as well as the calibration flag
EEPROM.put(0, CALIBRATION_FLAG);
EEPROM.put(1, leverMin);
EEPROM.put(5, leverMax);
// Finally, set all the lights to green
setAllLEDs(CRGB::Green);
delay(2000);
} else {
// Just load leverMin and leverMax from EEPROM
EEPROM.get(1, leverMin);
EEPROM.get(5, leverMax);
leverCenter = ((leverMax + leverMin) / 2);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment