Skip to content

Commit 24c9742

Browse files
committed
Add Logitech G25 and G27 shifter examples
1 parent 9d1fb71 commit 24c9742

4 files changed

Lines changed: 593 additions & 0 deletions

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Project Sim Racing Library for Arduino
3+
* @author David Madison
4+
* @link github.com/dmadison/Sim-Racing-Arduino
5+
* @license LGPLv3 - Copyright (c) 2024 David Madison
6+
*
7+
* This file is part of the Sim Racing Library for Arduino.
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
/**
24+
* @details Emulates the Logitech G25 shifter as a joystick over USB.
25+
* @example LogitechShifterG25_Joystick.ino
26+
*/
27+
28+
// This example requires the Arduino Joystick Library
29+
// Download Here: https://github.com/MHeironimus/ArduinoJoystickLibrary
30+
31+
#include <SimRacing.h>
32+
#include <Joystick.h>
33+
34+
const int Pin_ShifterX = A0; // DE-9 pin 4
35+
const int Pin_ShifterY = A2; // DE-9 pin 8
36+
37+
const int Pin_ShifterLatch = 5; // DE-9 pin 3
38+
const int Pin_ShifterClock = 6; // DE-9 pin 7
39+
const int Pin_ShifterData = 7; // DE-9 pin 2
40+
41+
// These pins require extra resistors! If you have made the proper
42+
// connections, change the pin numbers to the ones you're using
43+
const int Pin_ShifterDetect = SimRacing::UnusedPin; // DE-9 pin 1, requires pull-down resistor
44+
const int Pin_ShifterLED = SimRacing::UnusedPin; // DE-9 pin 5, requires 100-120 Ohm series resistor
45+
46+
SimRacing::LogitechShifterG25 shifter(
47+
Pin_ShifterX, Pin_ShifterY,
48+
Pin_ShifterLatch, Pin_ShifterClock, Pin_ShifterData,
49+
Pin_ShifterDetect, Pin_ShifterLED
50+
);
51+
52+
// Set this option to 'true' to send the shifter's X/Y position
53+
// as a joystick. This is not needed for most games.
54+
const bool SendAnalogAxis = false;
55+
56+
const int Gears[] = { 1, 2, 3, 4, 5, 6, -1 };
57+
const int NumGears = sizeof(Gears) / sizeof(Gears[0]);
58+
59+
using ShifterButton = SimRacing::LogitechShifterG25::Button;
60+
const ShifterButton Buttons[] = {
61+
ShifterButton::BUTTON_SOUTH,
62+
ShifterButton::BUTTON_EAST,
63+
ShifterButton::BUTTON_WEST,
64+
ShifterButton::BUTTON_NORTH,
65+
ShifterButton::BUTTON_1,
66+
ShifterButton::BUTTON_2,
67+
ShifterButton::BUTTON_3,
68+
ShifterButton::BUTTON_4,
69+
};
70+
const int NumButtons = sizeof(Buttons) / sizeof(Buttons[0]);
71+
72+
const int ADC_Max = 1023; // 10-bit on AVR
73+
74+
Joystick_ Joystick(
75+
JOYSTICK_DEFAULT_REPORT_ID, // default report (no additional pages)
76+
JOYSTICK_TYPE_JOYSTICK, // so that this shows up in Windows joystick manager
77+
NumGears + NumButtons + 2, // number of buttons (7 gears: reverse and 1-6, 8 buttons, 2 sequential gears)
78+
1, // number of hat switches (1, the directional pad)
79+
SendAnalogAxis, SendAnalogAxis, // include X and Y axes for analog output, if set above
80+
false, false, false, false, false, false, false, false, false); // no other axes
81+
82+
void updateJoystick(); // forward-declared function for non-Arduino environments
83+
84+
85+
void setup() {
86+
shifter.begin();
87+
88+
// if you have one, your calibration line should go here
89+
90+
Joystick.begin(false); // 'false' to disable auto-send
91+
Joystick.setXAxisRange(0, ADC_Max);
92+
Joystick.setYAxisRange(ADC_Max, 0); // invert axis so 'up' is up
93+
94+
updateJoystick(); // send initial state
95+
}
96+
97+
void loop() {
98+
bool dataChanged = shifter.update();
99+
100+
if (dataChanged || SendAnalogAxis == true) {
101+
updateJoystick();
102+
}
103+
}
104+
105+
void updateJoystick() {
106+
// keep track of which button we're updating
107+
// in the joystick output
108+
int currentButton = 0;
109+
110+
// set the buttons corresponding to the gears
111+
for (int i = 0; i < NumGears; i++) {
112+
if (shifter.getGear() == Gears[i]) {
113+
Joystick.pressButton(currentButton);
114+
}
115+
else {
116+
Joystick.releaseButton(currentButton);
117+
}
118+
119+
currentButton++;
120+
}
121+
122+
// set the analog axes (if the option is set)
123+
if (SendAnalogAxis == true) {
124+
int x = shifter.getPosition(SimRacing::X, 0, ADC_Max);
125+
int y = shifter.getPosition(SimRacing::Y, 0, ADC_Max);
126+
Joystick.setXAxis(x);
127+
Joystick.setYAxis(y);
128+
}
129+
130+
// set the buttons
131+
for (int i = 0; i < NumButtons; i++) {
132+
bool state = shifter.getButton(Buttons[i]);
133+
Joystick.setButton(currentButton, state);
134+
135+
currentButton++;
136+
}
137+
138+
// set the hatswitch (directional pad)
139+
int angle = shifter.getDpadAngle();
140+
Joystick.setHatSwitch(0, angle);
141+
142+
// set the sequential shifting buttons
143+
bool shiftUp = shifter.getShiftUp();
144+
Joystick.setButton(currentButton, shiftUp);
145+
currentButton++;
146+
147+
bool shiftDown = shifter.getShiftDown();
148+
Joystick.setButton(currentButton, shiftDown);
149+
currentButton++;
150+
151+
// send the updated data via USB
152+
Joystick.sendState();
153+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
* Project Sim Racing Library for Arduino
3+
* @author David Madison
4+
* @link github.com/dmadison/Sim-Racing-Arduino
5+
* @license LGPLv3 - Copyright (c) 2024 David Madison
6+
*
7+
* This file is part of the Sim Racing Library for Arduino.
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* GNU Lesser General Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public License
20+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
21+
*/
22+
23+
/**
24+
* @details Reads from the Logitech G25 shifter and prints the data over serial.
25+
* @example LogitechShifterG25_Print.ino
26+
*/
27+
28+
#include <SimRacing.h>
29+
30+
const int Pin_ShifterX = A0; // DE-9 pin 4
31+
const int Pin_ShifterY = A2; // DE-9 pin 8
32+
33+
const int Pin_ShifterLatch = 5; // DE-9 pin 3
34+
const int Pin_ShifterClock = 6; // DE-9 pin 7
35+
const int Pin_ShifterData = 7; // DE-9 pin 2
36+
37+
// These pins require extra resistors! If you have made the proper
38+
// connections, change the pin numbers to the ones you're using
39+
const int Pin_ShifterDetect = SimRacing::UnusedPin; // DE-9 pin 1, requires pull-down resistor
40+
const int Pin_ShifterLED = SimRacing::UnusedPin; // DE-9 pin 5, requires 100-120 Ohm series resistor
41+
42+
SimRacing::LogitechShifterG25 shifter(
43+
Pin_ShifterX, Pin_ShifterY,
44+
Pin_ShifterLatch, Pin_ShifterClock, Pin_ShifterData,
45+
Pin_ShifterDetect, Pin_ShifterLED
46+
);
47+
48+
// alias so we don't need to type so much
49+
using ShifterButton = SimRacing::LogitechShifterG25::Button;
50+
51+
// forward-declared functions for non-Arduino environments
52+
void printConditional(bool state, char pressed);
53+
void printButton(ShifterButton button, char pressed);
54+
void printShifter();
55+
56+
const unsigned long PrintSpeed = 1500; // ms
57+
unsigned long lastPrint = 0;
58+
59+
60+
void setup() {
61+
shifter.begin();
62+
63+
// if you have one, your calibration line should go here
64+
65+
Serial.begin(115200);
66+
while (!Serial); // wait for connection to open
67+
68+
Serial.println("Logitech G25 Starting...");
69+
}
70+
71+
void loop() {
72+
// send some serial data to run conversational calibration
73+
if (Serial.read() != -1) {
74+
shifter.serialCalibration();
75+
shifter.serialCalibrationSequential();
76+
delay(2000);
77+
}
78+
79+
bool dataChanged = shifter.update();
80+
81+
// if data has changed, print immediately
82+
if (dataChanged) {
83+
Serial.print("! ");
84+
printShifter();
85+
}
86+
87+
// otherwise, print if we've been idle for awhile
88+
if (millis() - lastPrint >= PrintSpeed) {
89+
Serial.print(" ");
90+
printShifter();
91+
}
92+
}
93+
94+
void printConditional(bool state, char pressed) {
95+
if (state == true) {
96+
Serial.print(pressed);
97+
}
98+
else {
99+
Serial.print('_');
100+
}
101+
}
102+
103+
void printButton(ShifterButton button, char pressed) {
104+
bool state = shifter.getButton(button);
105+
printConditional(state, pressed);
106+
}
107+
108+
void printShifter() {
109+
// if in sequential mode, print up/down
110+
if (shifter.inSequentialMode()) {
111+
Serial.print("S:[");
112+
printConditional(shifter.getShiftUp(), '+');
113+
printConditional(shifter.getShiftDown(), '-');
114+
Serial.print(']');
115+
}
116+
// otherwise in H-pattern mode, print the gear
117+
else {
118+
Serial.print("H: [");
119+
Serial.print(shifter.getGearChar());
120+
Serial.print("]");
121+
}
122+
123+
// print X/Y position of shifter
124+
Serial.print(" - XY: (");
125+
Serial.print(shifter.getPositionRaw(SimRacing::X));
126+
Serial.print(", ");
127+
Serial.print(shifter.getPositionRaw(SimRacing::Y));
128+
Serial.print(") ");
129+
130+
// print directional pad
131+
printButton(ShifterButton::DPAD_LEFT, '<');
132+
printButton(ShifterButton::DPAD_UP, '^');
133+
printButton(ShifterButton::DPAD_DOWN, 'v');
134+
printButton(ShifterButton::DPAD_RIGHT, '>');
135+
Serial.print(' ');
136+
137+
// print black buttons
138+
printButton(ShifterButton::BUTTON_NORTH, 'N');
139+
printButton(ShifterButton::BUTTON_SOUTH, 'S');
140+
printButton(ShifterButton::BUTTON_EAST, 'E');
141+
printButton(ShifterButton::BUTTON_WEST, 'W');
142+
Serial.print(' ');
143+
144+
// print red buttons
145+
printButton(ShifterButton::BUTTON_1, '1');
146+
printButton(ShifterButton::BUTTON_2, '2');
147+
printButton(ShifterButton::BUTTON_3, '3');
148+
printButton(ShifterButton::BUTTON_4, '4');
149+
150+
Serial.println();
151+
152+
lastPrint = millis();
153+
}

0 commit comments

Comments
 (0)