diff --git a/PinServoTurnout.cpp b/PinServoTurnout.cpp
new file mode 100644
index 0000000..f1f17da
--- /dev/null
+++ b/PinServoTurnout.cpp
@@ -0,0 +1,133 @@
+/*
+ * © 2023 Andrey Baboshin
+ * All rights reserved.
+ *
+ * This file is part of CommandStation-EX
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * It is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CommandStation. If not, see .
+ */
+
+#include "defines.h" // includes config.h
+#ifndef DISABLE_EEPROM
+#include "EEStore.h"
+#endif
+
+#include "PinServoTurnout.h"
+
+/*************************************************************************************
+ * PinServoTurnout - Turnout controlled by servo device connected to a processor pin.
+ *
+ *************************************************************************************/
+
+// Private Constructor
+PinServoTurnout::PinServoTurnout(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed) : Turnout(id, TURNOUT_SERVO, closed)
+{
+ _servoTurnoutData.vpin = vpin;
+ _servoTurnoutData.thrownPosition = thrownPosition;
+ _servoTurnoutData.closedPosition = closedPosition;
+ _servoTurnoutData.profile = profile;
+}
+
+// Create function
+/* static */ Turnout *PinServoTurnout::create(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed)
+{
+#ifndef IO_NO_HAL
+ Turnout *tt = get(id);
+ if (tt)
+ {
+ // Object already exists, check if it is usable
+ if (tt->isType(TURNOUT_PIN))
+ {
+ // Yes, so set parameters
+ PinServoTurnout *st = (PinServoTurnout *)tt;
+ st->_servoTurnoutData.vpin = vpin;
+ st->_servoTurnoutData.thrownPosition = thrownPosition;
+ st->_servoTurnoutData.closedPosition = closedPosition;
+ st->_servoTurnoutData.profile = profile;
+ // Don't touch the _closed parameter, retain the original value.
+
+ st->servo.attach(vpin);
+ st->servo.write(closed ? closedPosition : thrownPosition);
+
+ return tt;
+ }
+ else
+ {
+ // Incompatible object, delete and recreate
+ remove(id);
+ }
+ }
+ PinServoTurnout* ttnew = new PinServoTurnout(id, vpin, thrownPosition, closedPosition, profile, closed);
+ DIAG(F("PinServoTurnout 0x%x size %d size %d"), tt, sizeof(Turnout), sizeof(struct TurnoutData));
+
+ ttnew->servo.attach(vpin);
+ ttnew->servo.write(closed ? closedPosition : thrownPosition);
+ return (Turnout *)ttnew;
+#else
+ (void)id;
+ (void)vpin;
+ (void)thrownPosition;
+ (void)closedPosition;
+ (void)profile;
+ (void)closed; // avoid compiler warnings.
+ return NULL;
+#endif
+}
+
+// Load a Pin Servo turnout definition from EEPROM. The common Turnout data has already been read at this point.
+Turnout *PinServoTurnout::load(struct TurnoutData *turnoutData)
+{
+#ifndef DISABLE_EEPROM
+ PinServoTurnoutData servoTurnoutData;
+ // Read class-specific data from EEPROM
+ EEPROM.get(EEStore::pointer(), servoTurnoutData);
+ EEStore::advance(sizeof(servoTurnoutData));
+
+ // Create new object
+ Turnout *tt = PinServoTurnout::create(turnoutData->id, servoTurnoutData.vpin, servoTurnoutData.thrownPosition,
+ servoTurnoutData.closedPosition, servoTurnoutData.profile, turnoutData->closed);
+ return tt;
+#else
+ (void)turnoutData;
+ return NULL;
+#endif
+}
+
+// For DCC++ classic compatibility, state reported to JMRI is 1 for thrown and 0 for closed
+void PinServoTurnout::print(Print *stream)
+{
+ StringFormatter::send(stream, F("\n"), _turnoutData.id, _servoTurnoutData.vpin,
+ _servoTurnoutData.thrownPosition, _servoTurnoutData.closedPosition, _servoTurnoutData.profile,
+ !_turnoutData.closed);
+}
+
+// ServoTurnout-specific code for throwing or closing a servo turnout.
+bool PinServoTurnout::setClosedInternal(bool close)
+{
+ servo.write(close ? _servoTurnoutData.closedPosition : _servoTurnoutData.thrownPosition);
+ return true;
+}
+
+void PinServoTurnout::save()
+{
+#ifndef DISABLE_EEPROM
+ // Write turnout definition and current position to EEPROM
+ // First write common servo data, then
+ // write the servo-specific data
+ EEPROM.put(EEStore::pointer(), _turnoutData);
+ EEStore::advance(sizeof(_turnoutData));
+ EEPROM.put(EEStore::pointer(), _servoTurnoutData);
+ EEStore::advance(sizeof(_servoTurnoutData));
+#endif
+}
diff --git a/PinServoTurnout.h b/PinServoTurnout.h
new file mode 100644
index 0000000..b2dc443
--- /dev/null
+++ b/PinServoTurnout.h
@@ -0,0 +1,59 @@
+/*
+ * © 2023 Andrey Baboshin
+ * All rights reserved.
+ *
+ * This file is part of CommandStation-EX
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * It is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CommandStation. If not, see .
+ */
+
+#ifndef IO_PINSERVO_H
+#define IO_PINSERVO_H
+
+#include "Turnouts.h"
+#include
+
+class PinServoTurnout : public Turnout
+{
+private:
+ // PinServoTurnoutData contains data specific to this subclass that is
+ // written to EEPROM when the turnout is saved.
+ struct PinServoTurnoutData
+ {
+ VPIN vpin;
+ uint16_t closedPosition;
+ uint16_t thrownPosition;
+ uint8_t profile;
+ } _servoTurnoutData; // 6 bytes
+
+ Servo servo;
+
+ // Constructor
+ PinServoTurnout(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed);
+
+public:
+ // Create function
+ static Turnout *create(uint16_t id, VPIN vpin, uint16_t thrownPosition, uint16_t closedPosition, uint8_t profile, bool closed = true);
+
+ // Load a Servo turnout definition from EEPROM. The common Turnout data has already been read at this point.
+ static Turnout *load(struct TurnoutData *turnoutData);
+ void print(Print *stream) override;
+
+protected:
+ // PinServoTurnout-specific code for throwing or closing a servo turnout.
+ bool setClosedInternal(bool close) override;
+ void save() override;
+};
+
+#endif // IO_PINSERVO_H
diff --git a/Turnouts.h b/Turnouts.h
index 56b7f82..31a8d95 100644
--- a/Turnouts.h
+++ b/Turnouts.h
@@ -1,4 +1,5 @@
/*
+ * © 2023 Andrey Baboshin
* © 2021 Neil McKechnie
* © 2021 M Steve Todd
* © 2021 Fred Decker
@@ -6,7 +7,7 @@
* © 2020-2022 Chris Harlow
* © 2013-2016 Gregg E. Berman
* All rights reserved.
- *
+ *
* This file is part of CommandStation-EX
*
* This is free software: you can redistribute it and/or modify
@@ -26,7 +27,7 @@
#ifndef TURNOUTS_H
#define TURNOUTS_H
-//#define EESTOREDEBUG
+//#define EESTOREDEBUG
#include "Arduino.h"
#include "IODevice.h"
#include "StringFormatter.h"
@@ -37,20 +38,21 @@ enum {
TURNOUT_SERVO = 2,
TURNOUT_VPIN = 3,
TURNOUT_LCN = 4,
+ TURNOUT_PIN = 5
};
/*************************************************************************************
* Turnout - Base class for turnouts.
- *
+ *
*************************************************************************************/
class Turnout {
protected:
- /*
+ /*
* Object data
*/
- // The TurnoutData struct contains data common to all turnout types, that
+ // The TurnoutData struct contains data common to all turnout types, that
// is written to EEPROM when the turnout is saved.
// The first byte of this struct contains the 'closed' flag which is
// updated whenever the turnout changes from thrown to closed and
@@ -71,7 +73,7 @@ protected:
#ifndef DISABLE_EEPROM
// Address in eeprom of first byte of the _turnoutData struct (containing the closed flag).
- // Set to zero if the object has not been saved in EEPROM, e.g. for newly created Turnouts, and
+ // Set to zero if the object has not been saved in EEPROM, e.g. for newly created Turnouts, and
// for all LCN turnouts.
uint16_t _eepromAddress = 0;
#endif
@@ -90,35 +92,35 @@ protected:
add(this);
}
- /*
+ /*
* Static data
- */
+ */
static Turnout *_firstTurnout;
static int _turnoutlistHash;
- /*
+ /*
* Virtual functions
*/
virtual bool setClosedInternal(bool close) = 0; // Mandatory in subclass
virtual void save() {}
-
+
/*
* Static functions
*/
static void add(Turnout *tt);
-
+
public:
static Turnout *get(uint16_t id);
- /*
+ /*
* Static data
*/
static int turnoutlistHash;
static const bool useClassicTurnoutCommands;
-
+
/*
* Public base class functions
*/
@@ -130,7 +132,7 @@ public:
inline uint16_t getId() { return _turnoutData.id; }
inline Turnout *next() { return _nextTurnout; }
void printState(Print *stream);
- /*
+ /*
* Virtual functions
*/
virtual void print(Print *stream) {
@@ -189,11 +191,11 @@ public:
/*************************************************************************************
* ServoTurnout - Turnout controlled by servo device.
- *
+ *
*************************************************************************************/
class ServoTurnout : public Turnout {
private:
- // ServoTurnoutData contains data specific to this subclass that is
+ // ServoTurnoutData contains data specific to this subclass that is
// written to EEPROM when the turnout is saved.
struct ServoTurnoutData {
VPIN vpin;
@@ -222,11 +224,11 @@ protected:
/*************************************************************************************
* DCCTurnout - Turnout controlled by DCC Accessory Controller.
- *
+ *
*************************************************************************************/
class DCCTurnout : public Turnout {
private:
- // DCCTurnoutData contains data specific to this subclass that is
+ // DCCTurnoutData contains data specific to this subclass that is
// written to EEPROM when the turnout is saved.
struct DCCTurnoutData {
// DCC address (Address in bits 15-2, subaddress in bits 1-0)
@@ -257,11 +259,11 @@ protected:
/*************************************************************************************
* VpinTurnout - Turnout controlled through a HAL vpin.
- *
+ *
*************************************************************************************/
class VpinTurnout : public Turnout {
private:
- // VpinTurnoutData contains data specific to this subclass that is
+ // VpinTurnoutData contains data specific to this subclass that is
// written to EEPROM when the turnout is saved.
struct VpinTurnoutData {
VPIN vpin;
@@ -287,7 +289,7 @@ protected:
/*************************************************************************************
* LCNTurnout - Turnout controlled by Loconet
- *
+ *
*************************************************************************************/
class LCNTurnout : public Turnout {
private:
@@ -295,7 +297,7 @@ private:
// struct LCNTurnoutData {
// } _lcnTurnoutData; // 0 bytes
- // Constructor
+ // Constructor
LCNTurnout(uint16_t id, bool closed);
public: