1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-24 16:46:13 +01:00

Compare commits

...

3 Commits

Author SHA1 Message Date
peteGSX
798241927f Really fix build errors 2023-09-01 13:28:24 +10:00
peteGSX
df2f09f4d2 Fix build errors 2023-09-01 09:04:48 +10:00
peteGSX
f40d57d8bd Add DCC type, EXTT broadcast from driver 2023-09-01 08:44:32 +10:00
6 changed files with 156 additions and 53 deletions

View File

@ -708,7 +708,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
StringFormatter::send(stream, F(" %d X"), id); StringFormatter::send(stream, F(" %d X"), id);
} else { } else {
uint8_t pos = tto->getPosition(); uint8_t pos = tto->getPosition();
uint8_t type = tto->getType(); uint8_t type = tto->isEXTT();
uint8_t posCount = tto->getPositionCount(); uint8_t posCount = tto->getPositionCount();
const FSH *todesc = NULL; const FSH *todesc = NULL;
#ifdef EXRAIL_ACTIVE #ifdef EXRAIL_ACTIVE
@ -1075,22 +1075,29 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
return Turntable::printAll(stream); return Turntable::printAll(stream);
case 1: // <I id> broadcast type and current position case 1: // <I id> broadcast type and current position
return false; {
Turntable *tto = Turntable::get(p[0]);
if (tto) {
bool type = tto->isEXTT();
uint8_t position = tto->getPosition();
StringFormatter::send(stream, F("<i %d %d>\n"), type, position);
} else {
return false;
}
}
return true;
case 2: // <I id position> - rotate to position for DCC turntables case 2: // <I id position> - rotate to position for DCC turntables
{ {
Turntable *tto = Turntable::get(p[0]);
if (p[1] == HASH_KEYWORD_DCC) { // Create a DCC turntable if (p[1] == HASH_KEYWORD_DCC) { // Create a DCC turntable
DIAG(F("Create DCC turntable %d"), p[0]); if (tto) return false;
} else { // Otherwise move a DCC turntable if (!DCCTurntable::create(p[0])) return false;
Turntable *tto = Turntable::get(p[0]); Turntable *tto = Turntable::get(p[0]);
tto->addPosition(0);
} else { // Otherwise move a DCC turntable
if (tto) { if (tto) {
if (tto->getPosition() == p[1]) return true; if (!tto->setPosition(p[0], p[1])) return false;
uint16_t value = tto->getPositionValue(p[1]);
if (value) {
DIAG(F("Rotate DCC turntable %d to position %d"), p[0], p[1]);
} else {
return false;
}
} else { } else {
return false; return false;
} }
@ -1100,34 +1107,24 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[])
case 3: case 3:
{ {
Turntable *tto = Turntable::get(p[0]);
if (!tto) return false;
if (p[1] == HASH_KEYWORD_ADD) { // <I id ADD value> add position value to turntable if (p[1] == HASH_KEYWORD_ADD) { // <I id ADD value> add position value to turntable
Turntable *tto = Turntable::get(p[0]); tto->addPosition(p[2]);
if (tto) { StringFormatter::send(stream, F("<i>\n"));
tto->addPosition(p[2]);
StringFormatter::send(stream, F("<i>\n"));
} else {
return false;
}
} else { // <I id position activity> rotate to position for EX-Turntable } else { // <I id position activity> rotate to position for EX-Turntable
Turntable *tto = Turntable::get(p[0]); if (!tto->setPosition(p[0], p[1], p[2])) return false;
if (tto) {
if (!tto->setPosition(p[0], p[1], p[2])) return false;
} else {
return false;
}
} }
} }
return true; return true;
case 5: // <I id EXTT vpin i2caddress home> create an EXTT turntable case 4: // <I id EXTT vpin home> create an EXTT turntable
{ {
if (p[1] == HASH_KEYWORD_EXTT) { if (p[1] == HASH_KEYWORD_EXTT) {
if (Turntable::get(p[0])) return false; if (Turntable::get(p[0])) return false;
if (!EXTTTurntable::create(p[0], (VPIN)p[2], (uint8_t)p[3])) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2])) return false;
Turntable *tto = Turntable::get(p[0]); Turntable *tto = Turntable::get(p[0]);
tto->addPosition(p[4]); tto->addPosition(p[3]);
} else if (params > 3 && params < 39 && p[1] == HASH_KEYWORD_DCC) {
DIAG(F("Create DCC turntable %d at base address %d with %d positions"), p[0], p[2], params - 2);
} else { } else {
return false; return false;
} }

View File

@ -176,6 +176,13 @@ bool IODevice::exists(VPIN vpin) {
return findDevice(vpin) != NULL; return findDevice(vpin) != NULL;
} }
// Return the status of the device att vpin.
uint8_t IODevice::getStatus(VPIN vpin) {
IODevice *dev = findDevice(vpin);
if (!dev) return false;
return dev->_deviceState;
}
// check whether the pin supports notification. If so, then regular _read calls are not required. // check whether the pin supports notification. If so, then regular _read calls are not required.
bool IODevice::hasCallback(VPIN vpin) { bool IODevice::hasCallback(VPIN vpin) {
IODevice *dev = findDevice(vpin); IODevice *dev = findDevice(vpin);

View File

@ -154,6 +154,9 @@ public:
// exists checks whether there is a device owning the specified vpin // exists checks whether there is a device owning the specified vpin
static bool exists(VPIN vpin); static bool exists(VPIN vpin);
// getStatus returns the state of the device at the specified vpin
static uint8_t getStatus(VPIN vpin);
// Enable shared interrupt on specified pin for GPIO extender modules. The extender module // Enable shared interrupt on specified pin for GPIO extender modules. The extender module
// should pull down this pin when requesting a scan. The pin may be shared by multiple modules. // should pull down this pin when requesting a scan. The pin may be shared by multiple modules.
// Without the shared interrupt, input states are scanned periodically to detect changes on // Without the shared interrupt, input states are scanned periodically to detect changes on
@ -377,6 +380,7 @@ private:
uint8_t *_pinInUse; uint8_t *_pinInUse;
}; };
#ifndef IO_NO_HAL
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////
/* /*
* IODevice subclass for EX-Turntable. * IODevice subclass for EX-Turntable.
@ -405,10 +409,13 @@ private:
void _begin() override; void _begin() override;
void _loop(unsigned long currentMicros) override; void _loop(unsigned long currentMicros) override;
int _read(VPIN vpin) override; int _read(VPIN vpin) override;
void _broadcastStatus (VPIN vpin, uint8_t status);
void _writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_t duration) override; void _writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_t duration) override;
void _display() override; void _display() override;
uint8_t _stepperStatus; uint8_t _stepperStatus;
uint8_t _previousStatus;
}; };
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -28,12 +28,13 @@
* Refer to the documentation for further information including the valid activities. * Refer to the documentation for further information including the valid activities.
*/ */
#ifndef IO_EXTurntable_h
#define IO_EXTurntable_h
#include "IODevice.h" #include "IODevice.h"
#include "I2CManager.h" #include "I2CManager.h"
#include "DIAG.h" #include "DIAG.h"
#include "Turntables.h"
#include "CommandDistributor.h"
#ifndef IO_NO_HAL
void EXTurntable::create(VPIN firstVpin, int nPins, I2CAddress I2CAddress) { void EXTurntable::create(VPIN firstVpin, int nPins, I2CAddress I2CAddress) {
new EXTurntable(firstVpin, nPins, I2CAddress); new EXTurntable(firstVpin, nPins, I2CAddress);
@ -44,6 +45,8 @@ EXTurntable::EXTurntable(VPIN firstVpin, int nPins, I2CAddress I2CAddress) {
_firstVpin = firstVpin; _firstVpin = firstVpin;
_nPins = nPins; _nPins = nPins;
_I2CAddress = I2CAddress; _I2CAddress = I2CAddress;
_stepperStatus = 0;
_previousStatus = 0;
addDevice(this); addDevice(this);
} }
@ -80,10 +83,22 @@ int EXTurntable::_read(VPIN vpin) {
if (_stepperStatus > 1) { if (_stepperStatus > 1) {
return false; return false;
} else { } else {
if (_stepperStatus != _previousStatus) {
_broadcastStatus(vpin, _stepperStatus);
_previousStatus = _stepperStatus;
}
return _stepperStatus; return _stepperStatus;
} }
} }
// If a status change has occurred for a turntable object, broadcast it
void EXTurntable::_broadcastStatus (VPIN vpin, uint8_t status) {
Turntable *tto = Turntable::getByVpin(vpin);
if (tto) {
CommandDistributor::broadcastTurntable(tto->getId(), tto->getPosition(), status);
}
}
// writeAnalogue to send the steps and activity to Turntable-EX. // writeAnalogue to send the steps and activity to Turntable-EX.
// Sends 3 bytes containing the MSB and LSB of the step count, and activity. // Sends 3 bytes containing the MSB and LSB of the step count, and activity.
// value contains the steps, bit shifted to MSB + LSB. // value contains the steps, bit shifted to MSB + LSB.

View File

@ -57,13 +57,6 @@ void Turntable::add(Turntable *tto) {
turntablelistHash++; turntablelistHash++;
} }
// Find turntable from list
Turntable *Turntable::get(uint16_t id) {
for (Turntable *tto = _firstTurntable; tto != NULL; tto = tto->_nextTurntable)
if (tto->_turntableData.id == id) return tto;
return NULL;
}
// Add a position // Add a position
void Turntable::addPosition(uint16_t value) { void Turntable::addPosition(uint16_t value) {
_turntablePositions.insert(value); _turntablePositions.insert(value);
@ -95,16 +88,39 @@ uint8_t Turntable::getPositionCount() {
/* /*
* Public static functions * Public static functions
*/ */
// Find turntable from list
Turntable *Turntable::get(uint16_t id) {
for (Turntable *tto = _firstTurntable; tto != nullptr; tto = tto->_nextTurntable)
if (tto->_turntableData.id == id) return tto;
return NULL;
}
// Find turntable via Vpin
Turntable *Turntable::getByVpin(VPIN vpin) {
for (Turntable *tto = _firstTurntable; tto != nullptr; tto = tto->_nextTurntable) {
if (tto->isEXTT()) {
EXTTTurntable *exttTto = static_cast<EXTTTurntable*>(tto);
if (exttTto->getVpin() == vpin) {
return tto;
}
}
}
return nullptr;
}
// Broadcast position changes
bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool moving) { bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool moving) {
Turntable *tto = get(id); Turntable *tto = get(id);
if (!tto) return false; if (!tto) return false;
CommandDistributor::broadcastTurntable(id, position, moving); // Only need to broadcast from here if it's a DCC type, device driver broadcasts EXTT
if (!tto->isEXTT()) { CommandDistributor::broadcastTurntable(id, position, moving); }
#if defined(EXRAIL_ACTIVE) #if defined(EXRAIL_ACTIVE)
// RMFT2::turntableEvent(id, position); // RMFT2::turntableEvent(id, position);
#endif #endif
return true; return true;
} }
// Initiate a turntable move
bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) {
#if defined(DIAG_IO) #if defined(DIAG_IO)
DIAG(F("Turntable(%d, %d)"), id, position); DIAG(F("Turntable(%d, %d)"), id, position);
@ -116,12 +132,12 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) {
if (ok) { if (ok) {
// Broadcast a position change only if non zero has been set, or home/calibration sent // Broadcast a position change only if non zero has been set, or home/calibration sent
if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) { if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) {
if (tto->getType() == TURNTABLE_EXTT) { tto->_turntableData.position = position;
if (tto->isEXTT()) {
tto->setPositionStateOnly(id, position, 1); tto->setPositionStateOnly(id, position, 1);
} else { } else {
tto->setPositionStateOnly(id, position, 0); tto->setPositionStateOnly(id, position, 0);
} }
tto->_turntableData.position = position;
} }
} }
return ok; return ok;
@ -132,38 +148,39 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) {
* *
*************************************************************************************/ *************************************************************************************/
// Private constructor // Private constructor
EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin) :
Turntable(id, TURNTABLE_EXTT) Turntable(id, TURNTABLE_EXTT)
{ {
_exttTurntableData.vpin = vpin; _exttTurntableData.vpin = vpin;
_exttTurntableData.i2caddress = i2caddress;
} }
using DevState = IODevice::DeviceStateEnum;
// Create function // Create function
Turntable *EXTTTurntable::create(uint16_t id, VPIN vpin, uint8_t i2caddress) { Turntable *EXTTTurntable::create(uint16_t id, VPIN vpin) {
#ifndef IO_NO_HAL #ifndef IO_NO_HAL
Turntable *tto = get(id); Turntable *tto = get(id);
if (tto) { if (tto) {
if (tto->isType(TURNTABLE_EXTT)) { if (tto->isType(TURNTABLE_EXTT)) {
EXTTTurntable *extt = (EXTTTurntable *)tto; EXTTTurntable *extt = (EXTTTurntable *)tto;
extt->_exttTurntableData.vpin = vpin; extt->_exttTurntableData.vpin = vpin;
extt->_exttTurntableData.i2caddress = i2caddress;
return tto; return tto;
} }
} }
tto = (Turntable *)new EXTTTurntable(id, vpin, i2caddress); if (!IODevice::exists(vpin)) return nullptr;
if (IODevice::getStatus(vpin) == DevState::DEVSTATE_FAILED) return nullptr;
tto = (Turntable *)new EXTTTurntable(id, vpin);
DIAG(F("Turntable 0x%x size %d size %d"), tto, sizeof(Turntable), sizeof(struct TurntableData)); DIAG(F("Turntable 0x%x size %d size %d"), tto, sizeof(Turntable), sizeof(struct TurntableData));
return tto; return tto;
#else #else
(void)id; (void)id;
(void)i2caddress;
(void)vpin; (void)vpin;
return NULL; return NULL;
#endif #endif
} }
void EXTTTurntable::print(Print *stream) { void EXTTTurntable::print(Print *stream) {
StringFormatter::send(stream, F("<i %d EXTURNTABLE %d %d>\n"), _turntableData.id, _exttTurntableData.vpin, _exttTurntableData.i2caddress); StringFormatter::send(stream, F("<i %d EXTURNTABLE %d>\n"), _turntableData.id, _exttTurntableData.vpin);
} }
// EX-Turntable specific code for moving to the specified position // EX-Turntable specific code for moving to the specified position
@ -185,4 +202,43 @@ EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) :
return true; return true;
} }
/*************************************************************************************
* DCCTurntable - DCC Turntable device.
*
*************************************************************************************/
// Private constructor
DCCTurntable::DCCTurntable(uint16_t id) : Turntable(id, TURNTABLE_DCC) {}
// Create function
Turntable *DCCTurntable::create(uint16_t id) {
#ifndef IO_NO_HAL
Turntable *tto = get(id);
if (!tto) {
tto = (Turntable *)new DCCTurntable(id);
DIAG(F("Turntable 0x%x size %d size %d"), tto, sizeof(Turntable), sizeof(struct TurntableData));
}
return tto;
#else
(void)id;
return NULL;
#endif
}
void DCCTurntable::print(Print *stream) {
StringFormatter::send(stream, F("<i %d DCCTURNTABLE>\n"), _turntableData.id);
}
// EX-Turntable specific code for moving to the specified position
bool DCCTurntable::setPositionInternal(uint8_t position, uint8_t activity) {
#ifndef IO_NO_HAL
int16_t value = getPositionValue(position);
if (position == 0 || !value) return false; // Return false if it's not a valid position
// Set position via device driver
// DCC activate function here
#else
(void)position;
#endif
return true;
}
#endif #endif

View File

@ -135,6 +135,7 @@ protected:
public: public:
static Turntable *get(uint16_t id); static Turntable *get(uint16_t id);
static Turntable *getByVpin(VPIN vpin);
/* /*
* Static data * Static data
@ -148,7 +149,7 @@ public:
inline bool isHidden() { return _turntableData.hidden; } inline bool isHidden() { return _turntableData.hidden; }
inline void setHidden(bool h) {_turntableData.hidden=h; } inline void setHidden(bool h) {_turntableData.hidden=h; }
inline bool isType(uint8_t type) { return _turntableData.turntableType == type; } inline bool isType(uint8_t type) { return _turntableData.turntableType == type; }
inline uint8_t getType() { return _turntableData.turntableType; } inline bool isEXTT() const { return _turntableData.turntableType == TURNTABLE_EXTT; }
inline uint16_t getId() { return _turntableData.id; } inline uint16_t getId() { return _turntableData.id; }
inline Turntable *next() { return _nextTurntable; } inline Turntable *next() { return _nextTurntable; }
void printState(Print *stream); void printState(Print *stream);
@ -193,16 +194,16 @@ private:
// EXTTTurntableData contains device specific data // EXTTTurntableData contains device specific data
struct EXTTTurntableData { struct EXTTTurntableData {
VPIN vpin; VPIN vpin;
uint8_t i2caddress;
} _exttTurntableData; } _exttTurntableData;
// Constructor // Constructor
EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress); EXTTTurntable(uint16_t id, VPIN vpin);
public: public:
// Create function // Create function
static Turntable *create(uint16_t id, VPIN vpin, uint8_t i2caddress); static Turntable *create(uint16_t id, VPIN vpin);
void print(Print *stream) override; void print(Print *stream) override;
VPIN getVpin() const { return _exttTurntableData.vpin; }
protected: protected:
// EX-Turntable specific code for setting position // EX-Turntable specific code for setting position
@ -210,6 +211,26 @@ protected:
}; };
/*************************************************************************************
* DCCTurntable - DCC accessory Turntable device.
*
*************************************************************************************/
class DCCTurntable : public Turntable {
private:
// Constructor
DCCTurntable(uint16_t id);
public:
// Create function
static Turntable *create(uint16_t id);
void print(Print *stream) override;
protected:
// DCC specific code for setting position
bool setPositionInternal(uint8_t position, uint8_t activity=0) override;
};
#endif #endif
#endif #endif