Skip to content

Commit d0cefac

Browse files
committed
Move detector implementation to base class
In implementing the G25 shifter I was running into synchronicity issues since each 'update()' function polled the connection state independently. In some updates the buttons would be connected while the shifter wasn't, in other updates it was the other way around. Moving the detector behavior to the base class makes it so that the detector is only polled once per update(), and it's *always* polled per update(). Using a pointer here also allows future classes to take advantage of polymorphism for more complicated 'detection' systems.
1 parent bdc3428 commit d0cefac

2 files changed

Lines changed: 205 additions & 138 deletions

File tree

src/SimRacing.cpp

Lines changed: 104 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -345,43 +345,83 @@ void AnalogInput::setCalibration(AnalogInput::Calibration newCal) {
345345
this->cal = newCal;
346346
}
347347

348+
//#########################################################
349+
// Peripheral #
350+
//#########################################################
351+
352+
Peripheral::Peripheral(DeviceConnection* detector)
353+
: detector(detector)
354+
{}
355+
356+
bool Peripheral::update() {
357+
// if the detector exists, poll for state
358+
if (this->detector) {
359+
this->detector->poll();
360+
}
361+
362+
// get the connected state from the detector
363+
const bool connected = this->isConnected();
364+
365+
// call the derived class update function
366+
return this->updateState(connected);
367+
}
368+
369+
bool Peripheral::isConnected() {
370+
// if detector exists, return state
371+
if (this->detector) {
372+
return this->detector->isConnected();
373+
}
374+
375+
// otherwise, assume always connected
376+
return true;
377+
}
378+
379+
void Peripheral::setStablePeriod(unsigned long t) {
380+
// if detector exists, set the stable period
381+
if (this->detector) {
382+
this->detector->setStablePeriod(t);
383+
}
384+
}
348385

349386
//#########################################################
350387
// Pedals #
351388
//#########################################################
352389

353-
Pedals::Pedals(AnalogInput* dataPtr, uint8_t nPedals, PinNum detectPin, bool detectActiveLow)
390+
Pedals::Pedals(AnalogInput* dataPtr, uint8_t nPedals, DeviceConnection* detector)
354391
:
392+
Peripheral(detector),
355393
pedalData(dataPtr),
356394
NumPedals(nPedals),
357-
detector(detectPin, detectActiveLow),
358395
changed(false)
359396
{}
360397

361398
void Pedals::begin() {
362399
update(); // set initial pedal position
363400
}
364401

365-
bool Pedals::update() {
366-
changed = false;
402+
bool Pedals::updateState(bool connected) {
403+
this->changed = false;
367404

368-
detector.poll();
369-
if (detector.getState() == DeviceConnection::Connected) {
370-
// if connected, read all pedal positions
405+
// if we're connected, read all pedal positions
406+
if (connected) {
371407
for (int i = 0; i < getNumPedals(); ++i) {
372408
changed |= pedalData[i].read();
373409
}
374410
}
375-
else if (detector.getState() == DeviceConnection::Unplug) {
376-
// on unplug event, zero all pedals
411+
412+
// otherwise, zero all pedals
413+
else {
377414
for (int i = 0; i < getNumPedals(); ++i) {
378415
const int min = pedalData[i].getMin();
379-
pedalData[i].setPosition(min);
416+
const int prev = pedalData[i].getPositionRaw();
417+
if (min != prev) {
418+
pedalData[i].setPosition(min);
419+
changed = true;
420+
}
380421
}
381-
changed = true; // set flag so we know everything moved to 0
382422
}
383423

384-
return changed;
424+
return this->changed;
385425
}
386426

387427
long Pedals::getPosition(PedalID pedal, long rMin, long rMax) const {
@@ -555,8 +595,8 @@ void Pedals::serialCalibration(Stream& iface) {
555595
}
556596

557597

558-
TwoPedals::TwoPedals(PinNum gasPin, PinNum brakePin, PinNum detectPin, bool detectActiveLow)
559-
: Pedals(pedalData, NumPedals, detectPin, detectActiveLow),
598+
TwoPedals::TwoPedals(PinNum gasPin, PinNum brakePin, DeviceConnection* detector)
599+
: Pedals(pedalData, NumPedals, detector),
560600
pedalData{ AnalogInput(gasPin), AnalogInput(brakePin) }
561601
{}
562602

@@ -566,8 +606,8 @@ void TwoPedals::setCalibration(AnalogInput::Calibration gasCal, AnalogInput::Cal
566606
}
567607

568608

569-
ThreePedals::ThreePedals(PinNum gasPin, PinNum brakePin, PinNum clutchPin, PinNum detectPin, bool detectActiveLow)
570-
: Pedals(pedalData, NumPedals, detectPin, detectActiveLow),
609+
ThreePedals::ThreePedals(PinNum gasPin, PinNum brakePin, PinNum clutchPin, DeviceConnection* detector)
610+
: Pedals(pedalData, NumPedals, detector),
571611
pedalData{ AnalogInput(gasPin), AnalogInput(brakePin), AnalogInput(clutchPin) }
572612
{}
573613

@@ -578,12 +618,10 @@ void ThreePedals::setCalibration(AnalogInput::Calibration gasCal, AnalogInput::C
578618
}
579619

580620

581-
582621
LogitechPedals::LogitechPedals(PinNum gasPin, PinNum brakePin, PinNum clutchPin, PinNum detectPin)
583-
: ThreePedals(
584-
gasPin, brakePin, clutchPin,
585-
detectPin, false // active high
586-
)
622+
:
623+
ThreePedals(gasPin, brakePin, clutchPin, &this->detectObj),
624+
detectObj(detectPin, false) // active high
587625
{
588626
// taken from calibrating my own pedals. the springs are pretty stiff so while
589627
// this covers the whole travel range, users may want to back it down for casual
@@ -592,10 +630,9 @@ LogitechPedals::LogitechPedals(PinNum gasPin, PinNum brakePin, PinNum clutchPin,
592630
}
593631

594632
LogitechDrivingForceGT_Pedals::LogitechDrivingForceGT_Pedals(PinNum gasPin, PinNum brakePin, PinNum detectPin)
595-
: TwoPedals(
596-
gasPin, brakePin,
597-
detectPin, false // active high
598-
)
633+
:
634+
TwoPedals(gasPin, brakePin, &this->detectObj),
635+
detectObj(detectPin, false) // active high
599636
{
600637
this->setCalibration({ 646, 0 }, { 473, 1023 }); // taken from calibrating my own pedals
601638
}
@@ -605,8 +642,10 @@ LogitechDrivingForceGT_Pedals::LogitechDrivingForceGT_Pedals(PinNum gasPin, PinN
605642
// Shifter #
606643
//#########################################################
607644

608-
Shifter::Shifter(Gear min, Gear max)
609-
: MinGear(min), MaxGear(max)
645+
Shifter::Shifter(Gear min, Gear max, DeviceConnection* detector)
646+
:
647+
Peripheral(detector),
648+
MinGear(min), MaxGear(max)
610649
{
611650
this->currentGear = this->previousGear = 0; // neutral
612651
}
@@ -695,15 +734,14 @@ const float AnalogShifter::CalEdgeOffset = 0.60;
695734
AnalogShifter::AnalogShifter(
696735
Gear gearMin, Gear gearMax,
697736
PinNum pinX, PinNum pinY, PinNum pinRev,
698-
PinNum detectPin, bool detectActiveLow
737+
DeviceConnection* detector
699738
) :
700-
Shifter(gearMin, gearMax),
739+
Shifter(gearMin, gearMax, detector),
701740

702741
/* Two axes, X and Y */
703742
analogAxis{ AnalogInput(pinX), AnalogInput(pinY) },
704743

705-
pinReverse(sanitizePin(pinRev)),
706-
detector(detectPin, detectActiveLow)
744+
pinReverse(sanitizePin(pinRev))
707745
{}
708746

709747
void AnalogShifter::begin() {
@@ -713,45 +751,32 @@ void AnalogShifter::begin() {
713751
update(); // set initial gear position
714752
}
715753

716-
bool AnalogShifter::update() {
717-
detector.poll();
718-
719-
switch (detector.getState()) {
720-
721-
// connected! poll the ADC for new analog axis data
722-
case(DeviceConnection::Connected):
723-
analogAxis[Axis::X].read();
724-
analogAxis[Axis::Y].read();
725-
break;
726-
727-
// on an unplug event, we want to reset our position back to
728-
// neutral and then immediately return
729-
case(DeviceConnection::Unplug):
730-
754+
bool AnalogShifter::updateState(bool connected) {
755+
// if not connected, reset our position back to neutral
756+
// and immediately return
757+
if (!connected) {
731758
// set axis values to calibrated neutral
732759
analogAxis[Axis::X].setPosition(calibration.neutralX);
733760
analogAxis[Axis::Y].setPosition(calibration.neutralY);
734761

735762
// set gear to neutral
736763
this->setGear(0);
737764

765+
// status changed if gear changed
738766
return this->gearChanged();
739-
break;
740-
741-
// if the device is either disconnected or just plugged in and unstable,
742-
// immediately return false to save on processing
743-
case(DeviceConnection::PlugIn):
744-
case(DeviceConnection::Disconnected):
745-
return false;
746-
break;
747767
}
748768

769+
// poll the analog axes for new data
770+
analogAxis[Axis::X].read();
771+
analogAxis[Axis::Y].read();
772+
const int x = analogAxis[Axis::X].getPosition();
773+
const int y = analogAxis[Axis::Y].getPosition();
774+
775+
// check previous gears for comparison
749776
const Gear previousGear = this->getGear();
750777
const bool prevOdd = ((previousGear != -1) && (previousGear & 1)); // were we previously in an odd gear
751778
const bool prevEven = (!prevOdd && previousGear != 0); // were we previously in an even gear
752-
753-
const int x = analogAxis[Axis::X].getPosition();
754-
const int y = analogAxis[Axis::Y].getPosition();
779+
755780
Gear newGear = 0;
756781

757782
// If we're below the 'release' thresholds, we must still be in the previous gear
@@ -812,7 +837,7 @@ int AnalogShifter::getPositionRaw(Axis ax) const {
812837
bool AnalogShifter::getReverseButton() const {
813838
// if the reverse pin is not set *or* if the device is not currently
814839
// connected, avoid reading the floating input and just return 'false'
815-
if (pinReverse == UnusedPin || detector.getState() != DeviceConnection::Connected) {
840+
if (pinReverse == UnusedPin) {
816841
return false;
817842
}
818843
return digitalRead(pinReverse);
@@ -1015,9 +1040,9 @@ void AnalogShifter::serialCalibration(Stream& iface) {
10151040
LogitechShifter::LogitechShifter(PinNum pinX, PinNum pinY, PinNum pinRev, PinNum detectPin)
10161041
: AnalogShifter(
10171042
-1, 6, // includes reverse and gears 1-6
1018-
pinX, pinY, pinRev,
1019-
detectPin, false // active high
1020-
)
1043+
pinX, pinY, pinRev, &this->detectObj),
1044+
1045+
detectObj(detectPin, false) // active high
10211046
{
10221047
this->setCalibration({ 490, 440 }, { 253, 799 }, { 262, 86 }, { 460, 826 }, { 470, 76 }, { 664, 841 }, { 677, 77 });
10231048
}
@@ -1028,28 +1053,36 @@ LogitechShifter::LogitechShifter(PinNum pinX, PinNum pinY, PinNum pinRev, PinNum
10281053

10291054
Handbrake::Handbrake(PinNum pinAx, PinNum detectPin, boolean detectActiveLow)
10301055
:
1056+
Peripheral(&this->detectObj),
10311057
analogAxis(pinAx),
1032-
detector(detectPin, detectActiveLow),
1058+
detectObj(detectPin, detectActiveLow),
10331059
changed(false)
10341060
{}
10351061

10361062
void Handbrake::begin() {
10371063
update(); // set initial handbrake position
10381064
}
10391065

1040-
bool Handbrake::update() {
1041-
changed = false;
1066+
bool Handbrake::updateState(bool connected) {
1067+
this->changed = false;
10421068

1043-
detector.poll();
1044-
if (detector.getState() == DeviceConnection::Connected) {
1045-
changed = analogAxis.read();
1069+
// if connected, read state of the axis
1070+
if (connected) {
1071+
this->changed = this->analogAxis.read();
10461072
}
1047-
else if (detector.getState() == DeviceConnection::Unplug) {
1048-
analogAxis.setPosition(analogAxis.getMin());
1049-
changed = true;
1073+
1074+
// otherwise, set axis to its minimum (idle) position
1075+
else {
1076+
const int min = this->analogAxis.getMin();
1077+
const int prev = this->analogAxis.getPositionRaw();
1078+
1079+
if (min != prev) {
1080+
this->analogAxis.setPosition(min);
1081+
this->changed = true;
1082+
}
10501083
}
10511084

1052-
return changed;
1085+
return this->changed;
10531086
}
10541087

10551088
long Handbrake::getPosition(long rMin, long rMax) const {

0 commit comments

Comments
 (0)