mirror of
https://github.com/n-e-y-s/G27_Pedals_and_Shifter.git
synced 2024-08-30 18:22:10 +00:00
415 lines
11 KiB
C++
415 lines
11 KiB
C++
// G27_Pedals_and_Shifter.ino
|
|
// by Jason Duncan
|
|
|
|
// Partially adapted from the work done by isrtv.com forums members pascalh and xxValiumxx:
|
|
// http://www.isrtv.com/forums/topic/13189-diy-g25-shifter-interface-with-h-pattern-sequential-and-handbrake-modes/
|
|
|
|
#include "Joystick.h"
|
|
|
|
// for debugging, gives serial output rather than working as a joystick
|
|
//#define DEBUG true
|
|
|
|
#if defined(DEBUG)
|
|
#define DEBUG_PEDALS true
|
|
#define DEBUG_SHIFTER true
|
|
#endif
|
|
|
|
//#define DEBUG_PEDALS true
|
|
//#define DEBUG_SHIFTER true
|
|
|
|
// red for brake, green for gas, blue for clutch
|
|
//#define PEDAL_COLORS true
|
|
|
|
// LED PINS
|
|
#define RED_PIN 3
|
|
#define GREEN_PIN 5
|
|
#define BLUE_PIN 6
|
|
|
|
// PEDAL PINS
|
|
//| DB9 | Original | Harness | Description | Pro Micro |
|
|
//| 1 | Black | Red | +5v | +5v |
|
|
//| 2 | Orange | Yellow | Throttle | pin 18 (A0) |
|
|
//| 3 | White | White | Brake | pin 19 (A1) |
|
|
//| 4 | Green | Green | Clutch | pin 20 (A2) |
|
|
//| 5 | | | | |
|
|
//| 6 | Red | Black | GND | GND |
|
|
//| 7 | | | | |
|
|
//| 8 | | | | |
|
|
//| 9 | Red | Black | GND | GND |
|
|
#define GAS_PIN 18
|
|
#define BRAKE_PIN 19
|
|
#define CLUTCH_PIN 20
|
|
|
|
// SHIFTER PINS
|
|
//| DB9 | Original | Harness | Shifter | Description | Pro Micro |
|
|
//| 1 | Purple | Purple | 1 | Button Clock | pin 0 |
|
|
//| 2 | Grey | Blue | 7 | Button Data | pin 1 |
|
|
//| 3 | Yellow | Yellow | 5 | Button !CS & !PL (Mode) | pin 4 |
|
|
//| 4 | Orange | Orange | 3 | Shifter X axis | pin 8 (A8) |
|
|
//| 5 | White | White | 2 | SPI input | |
|
|
//| 6 | Black | Black | 8 | GND | GND |
|
|
//| 7 | Red | Red | 6 | +5V | VCC |
|
|
//| 8 | Green | Green | 4 | Shifter Y axis | pin 9 (A9) |
|
|
//| 9 | Red | Red | 1 | +5V | VCC |
|
|
#define SHIFTER_CLOCK_PIN 0
|
|
#define SHIFTER_DATA_PIN 1
|
|
#define SHIFTER_MODE_PIN 4
|
|
#define SHIFTER_X_PIN 8
|
|
#define SHIFTER_Y_PIN 9
|
|
|
|
// BUTTON DEFINITIONS
|
|
#define BUTTON_REVERSE 1
|
|
|
|
#define BUTTON_RED_CENTERRIGHT 4
|
|
#define BUTTON_RED_CENTERLEFT 5
|
|
#define BUTTON_RED_RIGHT 6
|
|
#define BUTTON_RED_LEFT 7
|
|
#define BUTTON_BLACK_TOP 8
|
|
#define BUTTON_BLACK_RIGHT 9
|
|
#define BUTTON_BLACK_LEFT 10
|
|
#define BUTTON_BLACK_BOTTOM 11
|
|
#define BUTTON_DPAD_RIGHT 12
|
|
#define BUTTON_DPAD_LEFT 13
|
|
#define BUTTON_DPAD_BOTTOM 14
|
|
#define BUTTON_DPAD_TOP 15
|
|
|
|
#define OUTPUT_BLACK_TOP 7
|
|
#define OUTPUT_BLACK_LEFT 8
|
|
#define OUTPUT_BLACK_RIGHT 9
|
|
#define OUTPUT_BLACK_BOTTOM 10
|
|
#define OUTPUT_DPAD_TOP 11
|
|
#define OUTPUT_DPAD_LEFT 12
|
|
#define OUTPUT_DPAD_RIGHT 13
|
|
#define OUTPUT_DPAD_BOTTOM 14
|
|
#define OUTPUT_RED_LEFT 15
|
|
#define OUTPUT_RED_CENTERLEFT 16
|
|
#define OUTPUT_RED_CENTERRIGHT 17
|
|
#define OUTPUT_RED_RIGHT 18
|
|
|
|
// SHIFTER AXIS THRESHOLDS
|
|
#define SHIFTER_XAXIS_12 330 //Gears 1,2
|
|
#define SHIFTER_XAXIS_56 620 //Gears 5,6, R
|
|
#define SHIFTER_YAXIS_135 600 //Gears 1,3,5
|
|
#define SHIFTER_YAXIS_246 300 //Gears 2,4,6, R
|
|
|
|
// MISC.
|
|
#define MAX_AXIS 127
|
|
#define SIGNAL_SETTLE_DELAY 10
|
|
|
|
// PEDAL CODE
|
|
typedef struct pedal {
|
|
int pin, min, max, cur, axis;
|
|
};
|
|
|
|
typedef struct pedal Pedal;
|
|
|
|
void* gasPedal;
|
|
void* brakePedal;
|
|
void* clutchPedal;
|
|
|
|
int axisValue(void* in) {
|
|
Pedal* input = (Pedal*)in;
|
|
|
|
int range = input->max - input->min;
|
|
if (range == 0) {
|
|
return -MAX_AXIS;
|
|
}
|
|
|
|
long step1 = input->cur - input->min;
|
|
long step2 = step1 * (MAX_AXIS * 2);
|
|
float step3 = step2 / range;
|
|
int result = step3 - MAX_AXIS;
|
|
|
|
if (result < -MAX_AXIS) {
|
|
return -MAX_AXIS;
|
|
}
|
|
if (result > MAX_AXIS) {
|
|
return MAX_AXIS;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void processPedal(void* in) {
|
|
Pedal* input = (Pedal*)in;
|
|
|
|
input->cur = analogRead(input->pin);
|
|
|
|
// calibrate, we want the highest this pedal has been
|
|
input->max = input->cur > input->max ? input->cur : input->max;
|
|
// same for lowest, but bottom out at current value rather than 0
|
|
input->min = input->min == 0 || input->cur < input->min ? input->cur : input->min;
|
|
|
|
input->axis = axisValue(input);
|
|
}
|
|
|
|
void describePedal(char* name, char* axisName, void* in) {
|
|
Pedal* input = (Pedal*)in;
|
|
Serial.print("\nPIN: ");
|
|
Serial.print(input->pin);
|
|
Serial.print(" ");
|
|
Serial.print(name);
|
|
Serial.print(": ");
|
|
Serial.print(input->cur);
|
|
Serial.print(" MIN: ");
|
|
Serial.print(input->min);
|
|
Serial.print(" MAX: ");
|
|
Serial.print(input->max);
|
|
Serial.print(" ");
|
|
Serial.print(axisName);
|
|
Serial.print(" VALUE: ");
|
|
Serial.print(input->axis);
|
|
}
|
|
|
|
void setXAxis(void* in) {
|
|
Pedal* input = (Pedal*)in;
|
|
Joystick.setXAxis(input->axis);
|
|
}
|
|
|
|
void setYAxis(void* in) {
|
|
Pedal* input = (Pedal*)in;
|
|
Joystick.setYAxis(input->axis);
|
|
}
|
|
|
|
void setZAxis(void* in) {
|
|
Pedal* input = (Pedal*)in;
|
|
Joystick.setZAxis(input->axis);
|
|
}
|
|
|
|
void pedalColor(void* inGas, void* inBrake, void* inClutch){
|
|
Pedal* gas = (Pedal*)inGas;
|
|
Pedal* brake = (Pedal*)inBrake;
|
|
Pedal* clutch = (Pedal*)inClutch;
|
|
|
|
setColor(brake->axis + MAX_AXIS, gas->axis + MAX_AXIS, clutch->axis + MAX_AXIS);
|
|
}
|
|
|
|
// SHIFTER CODE
|
|
int buttonTable[] = {
|
|
// first four are unused
|
|
0, 0, 0, 0,
|
|
OUTPUT_RED_CENTERRIGHT,
|
|
OUTPUT_RED_CENTERLEFT,
|
|
OUTPUT_RED_RIGHT,
|
|
OUTPUT_RED_LEFT,
|
|
OUTPUT_BLACK_TOP,
|
|
OUTPUT_BLACK_RIGHT,
|
|
OUTPUT_BLACK_LEFT,
|
|
OUTPUT_BLACK_BOTTOM,
|
|
OUTPUT_DPAD_RIGHT,
|
|
OUTPUT_DPAD_LEFT,
|
|
OUTPUT_DPAD_BOTTOM,
|
|
OUTPUT_DPAD_TOP
|
|
};
|
|
|
|
void waitForSignalToSettle() {
|
|
delayMicroseconds(SIGNAL_SETTLE_DELAY);
|
|
}
|
|
|
|
void getButtonStates(int *ret) {
|
|
digitalWrite(SHIFTER_MODE_PIN, LOW); // Switch to parallel mode: digital inputs are read into shift register
|
|
waitForSignalToSettle();
|
|
digitalWrite(SHIFTER_MODE_PIN, HIGH); // Switch to serial mode: one data bit is output on each clock falling edge
|
|
|
|
#if defined(DEBUG_SHIFTER)
|
|
Serial.print("\nBUTTON STATES:");
|
|
#endif
|
|
|
|
for(int i = 0; i < 16; ++i) { // Iteration over both 8 bit registers
|
|
digitalWrite(SHIFTER_CLOCK_PIN, LOW); // Generate clock falling edge
|
|
waitForSignalToSettle();
|
|
|
|
ret[i] = digitalRead(SHIFTER_DATA_PIN);
|
|
|
|
#if defined(DEBUG_SHIFTER)
|
|
if (!(i % 4)) Serial.print("\n");
|
|
Serial.print(" button");
|
|
if (i < 10) Serial.print(0);
|
|
Serial.print(i);
|
|
Serial.print(" = ");
|
|
Serial.print(ret[i]);
|
|
#endif
|
|
|
|
digitalWrite(SHIFTER_CLOCK_PIN, HIGH); // Generate clock rising edge
|
|
waitForSignalToSettle();
|
|
}
|
|
}
|
|
|
|
void getShifterPosition(int *ret) {
|
|
ret[0] = analogRead(SHIFTER_X_PIN);
|
|
ret[1] = analogRead(SHIFTER_Y_PIN);
|
|
}
|
|
|
|
int getCurrentGear(int shifterPosition[], int btns[]) {
|
|
int gear = 0; // default to neutral
|
|
int x = shifterPosition[0], y = shifterPosition[1];
|
|
|
|
if (x < SHIFTER_XAXIS_12) // Shifter on the left?
|
|
{
|
|
if (y > SHIFTER_YAXIS_135) gear = 1; // 1st gear
|
|
if (y < SHIFTER_YAXIS_246) gear = 2; // 2nd gear
|
|
}
|
|
else if (x > SHIFTER_XAXIS_56) // Shifter on the right?
|
|
{
|
|
if (y > SHIFTER_YAXIS_135) gear = 5; // 5th gear
|
|
if (y < SHIFTER_YAXIS_246) gear = 6; // 6th gear
|
|
}
|
|
else // Shifter is in the middle
|
|
{
|
|
if (y > SHIFTER_YAXIS_135) gear = 3; // 3rd gear
|
|
if (y < SHIFTER_YAXIS_246) gear = 4; // 4th gear
|
|
}
|
|
|
|
if (gear != 6) btns[BUTTON_REVERSE] = 0; // Reverse gear is allowed only on 6th gear position
|
|
if (btns[BUTTON_REVERSE] == 1) gear = 7; // Reverse is 7th gear (for the sake of argument)
|
|
|
|
return gear;
|
|
}
|
|
|
|
void setButtonStates(int buttons[], int gear) {
|
|
// release virtual buttons for all gears
|
|
for (byte i = 0; i < 7; ++i) {
|
|
Joystick.setButton(i, LOW);
|
|
}
|
|
|
|
if (gear > 0) {
|
|
Joystick.setButton(gear - 1, HIGH);
|
|
}
|
|
|
|
for (byte i = BUTTON_RED_CENTERRIGHT; i <= BUTTON_DPAD_TOP; ++i) {
|
|
Joystick.setButton(buttonTable[i], buttons[i]);
|
|
}
|
|
}
|
|
|
|
void describeButtonStates(int buttons[], int shifterPosition[], int gear) {
|
|
Serial.print("\nSHIFTER X: ");
|
|
Serial.print(shifterPosition[0]);
|
|
Serial.print(" Y: ");
|
|
Serial.print(shifterPosition[1]);
|
|
|
|
Serial.print(" GEAR: ");
|
|
Serial.print(gear);
|
|
Serial.print(" REVERSE: ");
|
|
Serial.print(buttons[BUTTON_REVERSE]);
|
|
|
|
Serial.print(" RED BUTTONS:");
|
|
if (buttons[BUTTON_RED_LEFT]) {
|
|
Serial.print(" 1");
|
|
}
|
|
if (buttons[BUTTON_RED_CENTERLEFT]) {
|
|
Serial.print(" 2");
|
|
}
|
|
if (buttons[BUTTON_RED_CENTERLEFT]) {
|
|
Serial.print(" 3");
|
|
}
|
|
if (buttons[BUTTON_RED_RIGHT]) {
|
|
Serial.print(" 4");
|
|
}
|
|
|
|
Serial.print(" BLACK BUTTONS:");
|
|
if (buttons[BUTTON_BLACK_LEFT]) {
|
|
Serial.print(" LEFT");
|
|
}
|
|
if (buttons[BUTTON_BLACK_TOP]) {
|
|
Serial.print(" TOP");
|
|
}
|
|
if (buttons[BUTTON_BLACK_BOTTOM]) {
|
|
Serial.print(" BOTTOM");
|
|
}
|
|
if (buttons[BUTTON_BLACK_RIGHT]) {
|
|
Serial.print(" RIGHT");
|
|
}
|
|
|
|
Serial.print(" D-PAD:");
|
|
if (buttons[BUTTON_DPAD_LEFT]) {
|
|
Serial.print(" LEFT");
|
|
}
|
|
if (buttons[BUTTON_DPAD_TOP]) {
|
|
Serial.print(" UP");
|
|
}
|
|
if (buttons[BUTTON_DPAD_BOTTOM]) {
|
|
Serial.print(" DOWN");
|
|
}
|
|
if (buttons[BUTTON_DPAD_RIGHT]) {
|
|
Serial.print(" RIGHT");
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(38400);
|
|
#if !defined(DEBUG_PEDALS) && !defined(DEBUG_SHIFTER)
|
|
Joystick.begin(false);
|
|
#endif
|
|
|
|
// lights
|
|
pinMode(RED_PIN, OUTPUT);
|
|
pinMode(GREEN_PIN, OUTPUT);
|
|
pinMode(BLUE_PIN, OUTPUT);
|
|
|
|
// shifter
|
|
pinMode(SHIFTER_MODE_PIN, OUTPUT);
|
|
pinMode(SHIFTER_CLOCK_PIN, OUTPUT);
|
|
|
|
digitalWrite(SHIFTER_MODE_PIN, HIGH);
|
|
digitalWrite(SHIFTER_CLOCK_PIN, HIGH);
|
|
|
|
// pedals
|
|
Pedal* gas = new Pedal();
|
|
Pedal* brake = new Pedal();
|
|
Pedal* clutch = new Pedal();
|
|
|
|
gas->pin = GAS_PIN;
|
|
brake->pin = BRAKE_PIN;
|
|
clutch->pin = CLUTCH_PIN;
|
|
|
|
gasPedal = gas;
|
|
brakePedal = brake;
|
|
clutchPedal = clutch;
|
|
}
|
|
|
|
void loop() {
|
|
// pedals
|
|
processPedal(gasPedal);
|
|
processPedal(brakePedal);
|
|
processPedal(clutchPedal);
|
|
|
|
#if defined(DEBUG_PEDALS)
|
|
describePedal("GAS", "X", gasPedal);
|
|
describePedal("BRAKE", "Y", brakePedal);
|
|
describePedal("CLUTCH", "Z", clutchPedal);
|
|
#else
|
|
setXAxis(gasPedal);
|
|
setYAxis(brakePedal);
|
|
setZAxis(clutchPedal);
|
|
#endif
|
|
|
|
#if defined(PEDAL_COLORS)
|
|
pedalColor(gasPedal, brakePedal, clutchPedal);
|
|
#endif
|
|
|
|
// shifter
|
|
int buttonStates[16];
|
|
getButtonStates(buttonStates);
|
|
int shifterPosition[2];
|
|
getShifterPosition(shifterPosition);
|
|
int gear = getCurrentGear(shifterPosition, buttonStates);
|
|
|
|
#if defined(DEBUG_SHIFTER)
|
|
describeButtonStates(buttonStates, shifterPosition, gear);
|
|
#else
|
|
setButtonStates(buttonStates, gear);
|
|
Joystick.sendState();
|
|
#endif
|
|
|
|
#if defined(DEBUG_PEDALS) || defined(DEBUG_SHIFTER)
|
|
Serial.print("\n----------------------------------------------------------------------------");
|
|
// slow the output down a bit
|
|
delay(500);
|
|
#endif
|
|
}
|
|
|
|
void setColor(int red, int green, int blue) {
|
|
analogWrite(RED_PIN, red);
|
|
analogWrite(GREEN_PIN, green);
|
|
analogWrite(BLUE_PIN, blue);
|
|
}
|