Arduino Sim Racing Library v2.0.0
Loading...
Searching...
No Matches
SimRacing.h
Go to the documentation of this file.
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) 2022 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#ifndef SIM_RACING_LIB_H
24#define SIM_RACING_LIB_H
25
26#include <Arduino.h>
27
33namespace SimRacing {
37 using PinNum = int16_t;
38
43 const PinNum UnusedPin = -1;
44
45
49 enum Axis : uint8_t {
50 X = 0,
51 Y = 1,
52 };
53
54
60 public:
74
84 DeviceConnection(PinNum pin, bool activeLow = false, unsigned long detectTime = 250);
85
91 void poll();
92
99
106 bool isConnected() const;
107
115 void setStablePeriod(unsigned long t);
116
117 private:
123 bool readPin() const;
124
125 PinNum pin;
126 bool inverted;
127 unsigned long stablePeriod;
128
129 ConnectionState state;
130 bool pinState;
131 unsigned long lastChange;
132 };
133
134
139 public:
140 static const int Min = 0;
141 static const int Max = 1023;
142
148 AnalogInput(PinNum pin);
149
155 virtual bool read();
156
169 long getPosition(long rMin = Min, long rMax = Max) const;
170
176 int getPositionRaw() const;
177
183 int getMin() const { return this->cal.min; }
184
190 int getMax() const { return this->cal.max; }
191
197 bool isInverted() const;
198
207 void setPosition(int newPos);
208
216 void setInverted(bool invert = true);
217
229 struct Calibration {
230 int min;
231 int max;
232 };
233
239 void setCalibration(Calibration newCal);
240
241 private:
242 PinNum pin;
243 int position;
244 Calibration cal;
245 };
246
247
252 public:
256 virtual ~Peripheral() {}
257
261 virtual void begin() {};
262
268 bool update();
269
276 bool isConnected() const;
277
279 void setStablePeriod(unsigned long t);
280
281 protected:
294 virtual bool updateState(bool connected) = 0;
295
309
310 private:
311 DeviceConnection* detector;
312 };
313
314
324 enum Pedal {
325 Gas = 0,
326 Accelerator = Gas,
327 Throttle = Gas,
328 Brake = 1,
329 Clutch = 2,
330 };
331
335 class Pedals : public Peripheral {
336 public:
339
347 Pedals(
348 AnalogInput* dataPtr, uint8_t nPedals
349 );
350
352 virtual void begin();
353
366 long getPosition(PedalID pedal, long rMin = 0, long rMax = 100) const;
367
375 int getPositionRaw(PedalID pedal) const;
376
383 bool hasPedal(PedalID pedal) const;
384
390 int getNumPedals() const { return this->NumPedals; }
391
397 bool positionChanged() const { return changed; }
398
406
413 void serialCalibration(Stream& iface = Serial);
414
421 static String getPedalName(PedalID pedal);
422
423 protected:
425 virtual bool updateState(bool connected);
426
427 private:
428 AnalogInput* pedalData;
429 const int NumPedals;
430 bool changed;
431 };
432
433
437 class TwoPedals : public Pedals {
438 public:
445 TwoPedals(
446 PinNum pinGas, PinNum pinBrake
447 );
448
456
457 private:
458 static const uint8_t NumPedals = 2;
459 AnalogInput pedalData[NumPedals];
460 };
461
462
466 class ThreePedals : public Pedals {
467 public:
476 PinNum pinGas, PinNum pinBrake, PinNum pinClutch
477 );
478
487
488 private:
489 static const uint8_t NumPedals = 3;
490 AnalogInput pedalData[NumPedals];
491 };
492
494
495
505 class Shifter : public Peripheral {
506 public:
510 using Gear = int8_t;
511
518 Shifter(Gear min, Gear max);
519
528 Gear getGear() const { return currentGear; }
529
538 static char getGearChar(int gear);
539
546 char getGearChar() const;
547
557 static String getGearString(int gear);
558
565 String getGearString() const;
566
572 bool gearChanged() const {
573 return this->currentGear != this->previousGear;
574 }
575
581 Gear getGearMin() { return MinGear; }
582
588 Gear getGearMax() { return MaxGear; }
589
590 protected:
600 void setGear(Gear gear);
601
602 private:
603 const Gear MinGear;
604 const Gear MaxGear;
605
606 Gear currentGear;
607 Gear previousGear;
608 };
609
610
614 class AnalogShifter : public Shifter {
615 public:
632 Gear gearMin, Gear gearMax,
633 PinNum pinX, PinNum pinY,
634 PinNum pinRev = UnusedPin
635 );
636
642 virtual void begin();
643
647 long getPosition(Axis ax, long rMin = AnalogInput::Min, long rMax = AnalogInput::Max) const;
648
652 int getPositionRaw(Axis ax) const;
653
661 bool getReverseButton() const;
662
667 int x;
668 int y;
669 };
670
698 void setCalibration(
699 GearPosition neutral,
701 float engagePoint = CalEngagementPoint, float releasePoint = CalReleasePoint, float edgeOffset = CalEdgeOffset);
702
709 void serialCalibration(Stream& iface = Serial);
710
711 protected:
713 virtual bool updateState(bool connected);
714
715 private:
725 virtual bool readReverseButton();
726
732 static const float CalEngagementPoint;
733
739 static const float CalReleasePoint;
740
746 static const float CalEdgeOffset;
747
748 /*** Internal calibration struct */
749 struct Calibration {
750 int neutralX;
751 int neutralY;
752 int oddTrigger;
753 int oddRelease;
754 int evenTrigger;
755 int evenRelease;
756 int leftEdge;
757 int rightEdge;
758 } calibration;
759
760 AnalogInput analogAxis[2];
761 PinNum pinReverse;
762 bool reverseState;
763 };
764
766
767
771 class Handbrake : public Peripheral {
772 public:
778 Handbrake(PinNum pinAx);
779
783 virtual void begin();
784
796 long getPosition(long rMin = 0, long rMax = 100) const;
797
804 int getPositionRaw() const;
805
811 bool positionChanged() const { return this->changed; }
812
815
817 void serialCalibration(Stream& iface = Serial);
818
819 protected:
821 virtual bool updateState(bool connected);
822
823 private:
824 AnalogInput analogAxis;
825 bool changed;
826 };
827
828
836 public:
846 LogitechPedals(PinNum pinGas, PinNum pinBrake, PinNum pinClutch, PinNum pinDetect = UnusedPin);
847
848 private:
849 DeviceConnection detectObj;
850 };
851
862 public:
871 LogitechDrivingForceGT_Pedals(PinNum pinGas, PinNum pinBrake, PinNum pinDetect = UnusedPin);
872
873 private:
874 DeviceConnection detectObj;
875 };
876
884 public:
897 LogitechShifter(PinNum pinX, PinNum pinY, PinNum pinRev = UnusedPin, PinNum pinDetect = UnusedPin);
898
899 private:
900 DeviceConnection detectObj;
901 };
902
910
918
926
938 public:
967
982 PinNum pinX, PinNum pinY,
983 PinNum pinLatch, PinNum pinClock, PinNum pinData,
984 PinNum pinLed = UnusedPin,
985 PinNum pinDetect = UnusedPin
986 );
987
992 virtual void begin();
993
1000 bool getButton(Button button) const;
1001
1008 bool getButtonChanged(Button button) const;
1009
1018 int getDpadAngle() const;
1019
1025 bool buttonsChanged() const;
1026
1040 void setPowerLED(bool state);
1041
1048 bool getPowerLED() const { return this->ledState; }
1049
1050 protected:
1052 virtual bool updateState(bool connected);
1053
1054 private:
1063 static bool extractButton(Button button, uint16_t data) {
1064 // convert button to single bit with offset, and perform
1065 // a bitwise 'AND' to get the bit value
1066 return data & (1 << (uint8_t) button);
1067 }
1068
1075 void cacheButtons(uint16_t newStates);
1076
1083 void setPinModes(bool enabled);
1084
1090 uint16_t readShiftRegisters();
1091
1093 virtual bool readReverseButton();
1094
1095 // Pins for the shift register interface
1096 PinNum pinLatch;
1097 PinNum pinClock;
1098 PinNum pinData;
1099
1100 // Generic I/O pins
1101 PinNum pinLed;
1102
1103 // I/O state
1104 bool pinModesSet;
1105 bool ledState;
1106
1107 // Button states
1108 uint16_t buttonStates;
1109 uint16_t previousButtons;
1110 };
1111
1124 public:
1139 PinNum pinX, PinNum pinY,
1140 PinNum pinLatch, PinNum pinClock, PinNum pinData,
1141 PinNum pinLed = UnusedPin,
1142 PinNum pinDetect = UnusedPin
1143 );
1144
1146 virtual void begin();
1147
1154 bool inSequentialMode() const;
1155
1162 bool getShiftUp() const;
1163
1170 bool getShiftDown() const;
1171
1185 void setCalibrationSequential(int neutral, int up, int down,
1186 float engagePoint = LogitechShifterG25::CalEngagementPoint,
1187 float releasePoint = LogitechShifterG25::CalReleasePoint
1188 );
1189
1191 void serialCalibrationSequential(Stream& iface = Serial);
1192
1193 protected:
1195 virtual bool updateState(bool connected);
1196
1197 private:
1203 static const float CalEngagementPoint;
1204
1210 static const float CalReleasePoint;
1211
1212 bool sequentialProcess;
1213 int8_t sequentialState;
1214
1215 /*** Internal calibration struct */
1216 struct SequentialCalibration {
1217 int upTrigger;
1218 int upRelease;
1219 int downTrigger;
1220 int downRelease;
1221 } seqCalibration;
1222 };
1223
1224
1225#if defined(__AVR_ATmega32U4__) || defined(SIM_RACING_DOXYGEN)
1266 template<class T, uint8_t Version>
1268
1272 template<>
1273 LogitechPedals CreateShieldObject<LogitechPedals, 1>();
1274
1278 template<>
1279 LogitechPedals CreateShieldObject<LogitechPedals, 2>();
1280
1284 template<>
1285 LogitechShifter CreateShieldObject<LogitechShifter, 1>();
1286
1290 template<>
1291 LogitechShifter CreateShieldObject<LogitechShifter, 2>();
1292
1296 template<>
1297 LogitechShifterG27 CreateShieldObject<LogitechShifterG27, 2>();
1298
1302 template<>
1303 LogitechShifterG25 CreateShieldObject<LogitechShifterG25, 2>();
1304#endif
1305
1306} // end SimRacing namespace
1307
1308#endif
T CreateShieldObject()
Create an object for use with one of the Sim Racing Shields, designed for the SparkFun Pro Micro (32U...
Axis
Enumeration for analog axis names, mapped to integers.
Definition SimRacing.h:49
@ X
Cartesian X axis.
Definition SimRacing.h:50
@ Y
Cartesian Y axis.
Definition SimRacing.h:51
const PinNum UnusedPin
Dummy pin number signaling that a pin is unused and can be safely ignored.
Definition SimRacing.h:43
int16_t PinNum
Type alias for pin numbers, using Arduino numbering.
Definition SimRacing.h:37
Handle I/O for analog (ADC) inputs.
Definition SimRacing.h:138
void setInverted(bool invert=true)
Set the 'inverted' state of the axis.
bool isInverted() const
Check whether the axis is inverted or not.
long getPosition(long rMin=Min, long rMax=Max) const
Retrieves the buffered position for the analog axis, rescaled to a nominal range using the calibratio...
int getPositionRaw() const
Retrieves the buffered position for the analog axis.
static const int Max
Maximum value of the analog to digital (ADC) converter. 10-bit by default.
Definition SimRacing.h:141
int getMax() const
Retrieves the calibrated maximum position.
Definition SimRacing.h:190
void setCalibration(Calibration newCal)
Calibrate the axis' min/max values for rescaling.
virtual bool read()
Updates the current value of the axis by polling the ADC.
int getMin() const
Retrieves the calibrated minimum position.
Definition SimRacing.h:183
void setPosition(int newPos)
Override the current position with a custom value.
static const int Min
Minimum value of the analog to digital (ADC) converter.
Definition SimRacing.h:140
AnalogInput(PinNum pin)
Class constructor.
Interface with shifters using two potentiometers for gear position.
Definition SimRacing.h:614
void setCalibration(GearPosition neutral, GearPosition g1, GearPosition g2, GearPosition g3, GearPosition g4, GearPosition g5, GearPosition g6, float engagePoint=CalEngagementPoint, float releasePoint=CalReleasePoint, float edgeOffset=CalEdgeOffset)
Calibrate the gear shifter for more accurate shifting.
void serialCalibration(Stream &iface=Serial)
Runs an interactive calibration tool using the serial interface.
bool getReverseButton() const
Checks the current state of the "reverse" button at the bottom of the shift column.
AnalogShifter(Gear gearMin, Gear gearMax, PinNum pinX, PinNum pinY, PinNum pinRev=UnusedPin)
Class constructor.
int getPositionRaw(Axis ax) const
Retrieves the buffered position for the analog axis.
virtual bool updateState(bool connected)
Perform an internal poll of the hardware to refresh the class state.
virtual void begin()
Initializes the hardware pins for reading the gear states.
long getPosition(Axis ax, long rMin=AnalogInput::Min, long rMax=AnalogInput::Max) const
Retrieves the buffered position for the analog axis, rescaled to a nominal range using the calibratio...
Used for tracking whether a device is connected to a specific pin and stable.
Definition SimRacing.h:59
void poll()
Checks if the pin detects a connection.
void setStablePeriod(unsigned long t)
Set how long the detection pin must be stable for before the device is considered to be 'connected'.
ConnectionState getState() const
Retrieves the current ConnectionState from the instance.
DeviceConnection(PinNum pin, bool activeLow=false, unsigned long detectTime=250)
Class constructor.
ConnectionState
The state of the connection, whether it is connected, disconnected, and everywhere in-between.
Definition SimRacing.h:68
@ Unplug
Device was just removed (connection ends)
Definition SimRacing.h:72
@ PlugIn
Device was just plugged in (connection starts), unstable.
Definition SimRacing.h:70
@ Disconnected
No connection present.
Definition SimRacing.h:69
@ Connected
Connection present and stable.
Definition SimRacing.h:71
bool isConnected() const
Check if the device is physically connected to the board.
Interface with analog handbrakes that use hall effect sensors.
Definition SimRacing.h:771
virtual void begin()
Initializes the pin for reading from the handbrake.
long getPosition(long rMin=0, long rMax=100) const
Retrieves the buffered position for the handbrake axis, rescaled to a nominal range using the calibra...
void setCalibration(AnalogInput::Calibration newCal)
Calibrate the axis' min/max values for rescaling.
int getPositionRaw() const
Retrieves the buffered position for the handbrake, ignoring the calibration data.
bool positionChanged() const
Checks whether the handbrake's position has changed since the last update.
Definition SimRacing.h:811
Handbrake(PinNum pinAx)
Class constructor.
virtual bool updateState(bool connected)
Perform an internal poll of the hardware to refresh the class state.
void serialCalibration(Stream &iface=Serial)
Runs an interactive calibration tool using the serial interface.
Interface with the Logitech Driving Force GT pedals (Gas + Brake)
Definition SimRacing.h:861
LogitechDrivingForceGT_Pedals(PinNum pinGas, PinNum pinBrake, PinNum pinDetect=UnusedPin)
Class constructor.
Interface with the Logitech pedals (Gas, Brake, and Clutch)
Definition SimRacing.h:835
LogitechPedals(PinNum pinGas, PinNum pinBrake, PinNum pinClutch, PinNum pinDetect=UnusedPin)
Class constructor.
Interface with the Logitech G25 shifter.
Definition SimRacing.h:1123
bool getShiftDown() const
Check if the sequential shifter is shifted down.
LogitechShifterG25(PinNum pinX, PinNum pinY, PinNum pinLatch, PinNum pinClock, PinNum pinData, PinNum pinLed=UnusedPin, PinNum pinDetect=UnusedPin)
Class constructor.
void serialCalibrationSequential(Stream &iface=Serial)
Runs an interactive calibration tool using the serial interface.
virtual bool updateState(bool connected)
Perform an internal poll of the hardware to refresh the class state.
bool getShiftUp() const
Check if the sequential shifter is shifted up.
bool inSequentialMode() const
Check if the shifter is in sequential shifting mode.
void setCalibrationSequential(int neutral, int up, int down, float engagePoint=LogitechShifterG25::CalEngagementPoint, float releasePoint=LogitechShifterG25::CalReleasePoint)
Calibrate the sequential shifter for more accurate shifting.
virtual void begin()
Initializes the hardware pins for reading the gear states and the buttons.
Interface with the Logitech G27 shifter.
Definition SimRacing.h:937
int getDpadAngle() const
Get the directional pad angle in degrees.
Button
Enumeration of button values.
Definition SimRacing.h:949
@ BUTTON_REVERSE
Reverse button (press down on the shifter)
Definition SimRacing.h:951
@ BUTTON_SEQUENTIAL
Sequential mode button (turn the dial counter-clockwise)
Definition SimRacing.h:953
@ DPAD_DOWN
Down button of the directional pad.
Definition SimRacing.h:964
@ BUTTON_3
3rd red button (mid right)
Definition SimRacing.h:954
@ DPAD_RIGHT
Right button of the directional pad.
Definition SimRacing.h:962
@ BUTTON_WEST
The left black button.
Definition SimRacing.h:960
@ BUTTON_EAST
The right black button.
Definition SimRacing.h:959
@ BUTTON_2
2nd red button (mid left)
Definition SimRacing.h:955
@ BUTTON_UNUSED2
Unused shift register pin.
Definition SimRacing.h:952
@ BUTTON_SOUTH
The bottom black button.
Definition SimRacing.h:961
@ BUTTON_UNUSED1
Unused shift register pin.
Definition SimRacing.h:950
@ BUTTON_NORTH
The top black button.
Definition SimRacing.h:958
@ BUTTON_4
4th red button (far right)
Definition SimRacing.h:956
@ BUTTON_1
1st red button (far left)
Definition SimRacing.h:957
@ DPAD_UP
Top button of the directional pad.
Definition SimRacing.h:965
@ DPAD_LEFT
Left button of the directional pad.
Definition SimRacing.h:963
bool getPowerLED() const
Gets the commanded state of the shifter's power LED.
Definition SimRacing.h:1048
bool getButton(Button button) const
Retrieve the state of a single button.
bool buttonsChanged() const
Checks if any of the buttons have changed since the last update.
LogitechShifterG27(PinNum pinX, PinNum pinY, PinNum pinLatch, PinNum pinClock, PinNum pinData, PinNum pinLed=UnusedPin, PinNum pinDetect=UnusedPin)
Class constructor.
bool getButtonChanged(Button button) const
Checks whether a button has changed between updates.
virtual void begin()
Initializes the hardware pins for reading the gear states and the buttons.
virtual bool updateState(bool connected)
Perform an internal poll of the hardware to refresh the class state.
void setPowerLED(bool state)
Sets the state of the shifter's power LED.
Interface with the Logitech Driving Force shifter.
Definition SimRacing.h:883
LogitechShifter(PinNum pinX, PinNum pinY, PinNum pinRev=UnusedPin, PinNum pinDetect=UnusedPin)
Class constructor.
Base class for all pedals instances.
Definition SimRacing.h:335
SimRacing::Pedal PedalID
Scoped alias for SimRacing::Pedal.
Definition SimRacing.h:338
void serialCalibration(Stream &iface=Serial)
Runs an interactive calibration tool using the serial interface.
void setCalibration(PedalID pedal, AnalogInput::Calibration cal)
Calibrate a pedal's min/max values for rescaling.
Pedals(AnalogInput *dataPtr, uint8_t nPedals)
Class constructor.
static String getPedalName(PedalID pedal)
Utility function to get the string name for each pedal.
virtual bool updateState(bool connected)
Perform an internal poll of the hardware to refresh the class state.
bool hasPedal(PedalID pedal) const
Checks if a given pedal is present in the class.
bool positionChanged() const
Checks whether the current pedal positions have changed since the last update.
Definition SimRacing.h:397
int getPositionRaw(PedalID pedal) const
Retrieves the buffered position for the pedal, ignoring the calibration data.
virtual void begin()
Initialize the hardware (if necessary)
long getPosition(PedalID pedal, long rMin=0, long rMax=100) const
Retrieves the buffered position for the pedal, rescaled to a nominal range using the calibration valu...
int getNumPedals() const
Retrieves the number of pedals handled by the class.
Definition SimRacing.h:390
Abstract class for all peripherals.
Definition SimRacing.h:251
bool isConnected() const
Check if the device is physically connected to the board.
void setDetectPtr(DeviceConnection *d)
Sets the pointer to the detector object.
bool update()
Perform a poll of the hardware to refresh the class state.
virtual ~Peripheral()
Class destructor.
Definition SimRacing.h:256
virtual bool updateState(bool connected)=0
Perform an internal poll of the hardware to refresh the class state.
virtual void begin()
Initialize the hardware (if necessary)
Definition SimRacing.h:261
void setStablePeriod(unsigned long t)
Set how long the detection pin must be stable for before the device is considered to be 'connected'.
Base class for all shifter instances.
Definition SimRacing.h:505
String getGearString() const
Returns a String that represents the current gear.
Gear getGearMin()
Retrieves the minimum possible gear index.
Definition SimRacing.h:581
void setGear(Gear gear)
Changes the currently set gear, internally.
Gear getGearMax()
Retrieves the maximum possible gear index.
Definition SimRacing.h:588
Shifter(Gear min, Gear max)
Class constructor.
int8_t Gear
Type alias for gear numbers.
Definition SimRacing.h:510
char getGearChar() const
Returns a character that represents the current gear.
Gear getGear() const
Returns the currently selected gear.
Definition SimRacing.h:528
bool gearChanged() const
Checks whether the current gear has changed since the last update.
Definition SimRacing.h:572
Pedal implementation for devices with gas, brake, and clutch.
Definition SimRacing.h:466
ThreePedals(PinNum pinGas, PinNum pinBrake, PinNum pinClutch)
Class constructor.
void setCalibration(AnalogInput::Calibration gasCal, AnalogInput::Calibration brakeCal, AnalogInput::Calibration clutchCal)
Sets the calibration data (min/max) for the pedals.
Pedal implementation for devices with only gas and brake.
Definition SimRacing.h:437
void setCalibration(AnalogInput::Calibration gasCal, AnalogInput::Calibration brakeCal)
Sets the calibration data (min/max) for the pedals.
TwoPedals(PinNum pinGas, PinNum pinBrake)
Class constructor.
Pedal
Pedal ID names.
Definition SimRacing.h:324
Simple struct containing min/max values for axis calibration.
Definition SimRacing.h:229
int max
Maximum value of the analog axis.
Definition SimRacing.h:231
int min
Minimum value of the analog axis.
Definition SimRacing.h:230
Simple struct to store X/Y coordinates for the calibration function.
Definition SimRacing.h:666
int y
Y coordinate of the gear position from the ADC.
Definition SimRacing.h:668
int x
X coordinate of the gear position from the ADC.
Definition SimRacing.h:667