From 1491da48134852b0f8623b8455eb8c356e566e53 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 20 Aug 2023 19:26:04 +1000 Subject: [PATCH 01/39] Starting, very broken --- CommandDistributor.cpp | 4 + CommandDistributor.h | 1 + DCCEXParser.cpp | 29 +++++++ DCCEXParser.h | 13 +-- IODevice.h | 1 + Turntables.cpp | 176 +++++++++++++++++++++++++++++++++++++++++ Turntables.h | 164 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 382 insertions(+), 6 deletions(-) create mode 100644 Turntables.cpp create mode 100644 Turntables.h diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index ab6b52f..eef84a9 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -161,6 +161,10 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) { #endif } +void CommandDistributor::broadcastTurntable(int16_t id, uint8_t position) { + broadcastReply(COMMAND_TYPE, F("\n"), id, position); +} + void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) { // The JMRI clock command is of the form : PFT65871<;>4 // The CS broadcast is of the form " + if (parseI(stream, params, p)) + return; + break; + default: //anything else will diagnose and drop out to DIAG(F("Opcode=%c params=%d"), opcode, params); for (int i = 0; i < params; i++) @@ -1013,6 +1019,29 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) return false; } +// ========================== +// Turntable +bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) +{ + switch (params) + { + case 0: // list turntable objects + return Turntable::printAll(stream); + + case 1: // delete turntable + if (!Turntable::remove(p[0])) + return false; + StringFormatter::send(stream, F("\n")); + return true; + + case 2: // - rotate to position for DCC turntables + case 3: // rotate to position for EX-Turntable + { + + } + } +} + // CALLBACKS must be static bool DCCEXParser::stashCallback(Print *stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream) { diff --git a/DCCEXParser.h b/DCCEXParser.h index bb05ebf..bf067a7 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -45,13 +45,14 @@ struct DCCEXParser static int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command, bool usehex); static bool parseT(Print * stream, int16_t params, int16_t p[]); - static bool parseZ(Print * stream, int16_t params, int16_t p[]); - static bool parseS(Print * stream, int16_t params, int16_t p[]); - static bool parsef(Print * stream, int16_t params, int16_t p[]); - static bool parseD(Print * stream, int16_t params, int16_t p[]); + static bool parseZ(Print * stream, int16_t params, int16_t p[]); + static bool parseS(Print * stream, int16_t params, int16_t p[]); + static bool parsef(Print * stream, int16_t params, int16_t p[]); + static bool parseD(Print * stream, int16_t params, int16_t p[]); + static bool parseI(Print * stream, int16_t params, int16_t p[]); - static Print * getAsyncReplyStream(); - static void commitAsyncReplyStream(); + static Print * getAsyncReplyStream(); + static void commitAsyncReplyStream(); static bool stashBusy; static byte stashTarget; diff --git a/IODevice.h b/IODevice.h index 769e111..8b8f3fe 100644 --- a/IODevice.h +++ b/IODevice.h @@ -542,6 +542,7 @@ protected: #include "IO_PCF8575.h" #include "IO_duinoNodes.h" #include "IO_EXIOExpander.h" +#include "IO_EXTurntable.h" #endif // iodevice_h diff --git a/Turntables.cpp b/Turntables.cpp new file mode 100644 index 0000000..45a1d05 --- /dev/null +++ b/Turntables.cpp @@ -0,0 +1,176 @@ +/* + * © 2023 Peter Cole + * 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" +#include +#include "Turntables.h" +#include "StringFormatter.h" +#include "CommandDistributor.h" +#include "EXRAIL2.h" +#include "DCC.h" + + +/* + * Protected static data + */ +Turntable *Turntable::_firstTurntable = 0; + + +/* + * Public static data + */ +int Turntable::_turntablelistHash = 0; + + +/* + * Protected static functions + */ +// Add new turntable to end of list +void Turntable::add(Turntable *tto) { + if (!_firstTurntable) { + _firstTurntable = tto; + } else { + Turntable *ptr = _firstTurntable; + for ( ; ptr->_nextTurntable!=0; ptr=ptr->_nextTurntable) {} + ptr->_nextTurntable = tto; + } + 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; +} + +// Remove specified turntable from list and delete it +bool Turntable::remove(uint16_t id) { + Turntable *tto, *pp=NULL; + + for (tto=_firstTurntable; tto!=NULL && tto->_turntableData.id!=id; pp=tto, tto=tto->_nextTurntable) {} + if (tto == NULL) return false; + if (tto == _firstTurntable) { + _firstTurntable = tto->_nextTurntable; + } else { + pp->_nextTurntable = tto->_nextTurntable; + } + + delete (EXTTTurntable *)tto; + + turntablelistHash++; + return true; +} + + +/* + * Public static functions + */ +bool Turntable::isPosition(uint16_t id, uint8_t position) { + Turntable *tto = get(id); + if (!tto) return false; + if (tto) { + if (tto->getPosition() == position) { + return true; + } else { + return false; + } + } +} + +bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position) { + Turntable *tto = get(id); + if (!tto) return false; + CommandDistributor::broadcastTurntable(id, position); +#if defined(EXRAIL_ACTIVE) + // RMFT2::turntableEvent(id, position); +#endif +} + +bool Turntable::setPosition(uint16_t id, uint8_t position) { +#if defined(DIAG_IO) + DIAG(F("Turntable(%d, %d)"), id, position); +#endif + Turntable *tto = Turntable::get(id); + if (!tto) return false; + bool ok = tto->setPositionInternal(position); + + if (ok) { + tto->setPositionStateOnly(id, position); + } + return ok; +} + +/************************************************************************************* + * EXTTTurntable - EX-Turntable device. + * + *************************************************************************************/ +// Private constructor +EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions) : + Turntable(id, TURNTABLE_EXTT) +{ + _exttTurntableData.i2caddress = i2caddress; + _exttTurntableData.vpin = vpin; + _exttTurntableData.positions = **positions; +} + +// Create function +#ifndef IO_NO_HAL + Turntable *EXTTTurntable::create(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions) { + Turntable *tto = get(id); + if (tto) { + if (tto->isType(TURNTABLE_EXTT)) { + EXTTTurntable *extt = (EXTTTurntable *)tto; + extt->_exttTurntableData.i2caddress = i2caddress; + extt->_exttTurntableData.vpin = vpin; + extt->_exttTurntableData.positions = positions; + return tto; + } else { + remove(id); + } + } + tto = (Turntable *)new EXTTTurntable(id, i2caddress, vpin, **positions); + DIAG(F("Turntable 0x%x"), tto); + return tto; +#else + (void)id; + (void)i2caddress; + (void)vpin; + (void)positions; + return NULL; +#endif + } + + void EXTTTurntable::print(Print *stream) { + StringFormatter::send(stream, F("\n"), _turntableData.id, _exttTurntableData.i2caddress, _exttTurntableData.vpin); + } + + // EX-Turntable specific code for moving to the specified position + bool EXTTTurntable::setPositionInternal(uint8_t position, uint8_t activity) { +#ifndef IO_NO_HAL + // Get step value from positions + int value = _exttTurntableData.positions[position]; + // Set position via device driver + EXTurntable::_writeAnalogue(vpin, value, activity, 0); +#else + (void)position; +#endif + return true; + } diff --git a/Turntables.h b/Turntables.h new file mode 100644 index 0000000..5a6f346 --- /dev/null +++ b/Turntables.h @@ -0,0 +1,164 @@ +/* + * © 2023 Peter Cole + * 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 TURNTABLES_H +#define TURNTABLES_H + +#include +#include "IODevice.h" +#include "StringFormatter.h" + +// Turntable type definitions +// EXTT = EX-Turntable +// DCC = DCC accessory turntables - to be added later +enum { + TURNTABLE_EXTT = 1, + // TURNTABLE_DCC = 2, +}; + +/************************************************************************************* + * Turntable - Base class for turntables. + * + *************************************************************************************/ + +class Turntable { +protected: + /* + * Object data + */ + + // Data common to all turntable types + struct TurntableData { + union { + struct { + bool hidden : 1; + uint8_t turntableType : 2; + uint8_t position : 5; // Allows up to 38 positions including 0/home + }; + uint8_t flags; + }; + uint16_t id; + } _turntableData; + + // Pointer to next turntable object + Turntable *_nextTurntable = 0; + + /* + * Constructor + */ + Turntable(uint16_t id, uint8_t turntableType) { + _turntableData.id = id; + _turntableData.turntableType = turntableType; + _turntableData.hidden = false; + add(this); + } + + /* + * Static data + */ + static Turntable *_firstTurntable; + static int _turntablelistHash; + + /* + * Virtual functions + */ + virtual bool setPositionInternal(uint8_t position, uint8_t activity) = 0; + + /* + * Static functions + */ + static void add(Turntable *tto); + +public: + static Turntable *get(uint16_t id); + + /* + * Static data + */ + static int turntablelistHash; + + /* + * Public base class functions + */ + inline uint8_t getPosition() { return _turntableData.position; } + inline bool isHidden() { return _turntableData.hidden; } + inline void setHidden(bool h) {_turntableData.hidden=h; } + inline bool isType(uint8_t type) { return _turntableData.turntableType == type; } + inline uint16_t getId() { return _turntableData.id; } + inline Turntable *next() { return _nextTurntable; } + void printState(Print *stream); + + /* + * Virtual functions + */ + virtual void print(Print *stream) { + (void)stream; // suppress compiler warnings + } + virtual ~Turntable() {} // Destructor + + /* + * Public static functions + */ + inline static bool exists(uint16_t id) { return get(id) != 0; } + static bool remove(uint16_t id); + static bool isPosition(uint16_t id, uint8_t position); + static bool setPosition(uint16_t id, uint8_t position); + static bool setPositionStateOnly(uint16_t id, uint8_t position); + inline static Turntable *first() { return _firstTurntable; } + static bool printAll(Print *stream) { + bool gotOne = false; + for (Turntable *tto = _firstTurntable; tto != 0; tto = tto->_nextTurntable) + if (!tto->isHidden()) { + gotOne = true; + StringFormatter::send(stream, F("\n"), tto->getId(), tto->getPosition()); + } + return gotOne; + } + +}; + +/************************************************************************************* + * EXTTTurntable - EX-Turntable device. + * + *************************************************************************************/ +class EXTTTurntable : public Turntable { +private: + // EXTTTurntableData contains device specific data + struct EXTTTurntableData { + uint8_t i2caddress; + VPIN vpin; + long **positions; // Array of longs to store step positions + } _exttTurntableData; + + // Constructor + EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions); + +public: + // Create function + static Turntable *create(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions); + void print(Print *stream) override; + +protected: + // EX-Turntable specific code for setting position + bool setPositionInternal(uint8_t position, uint8_t activity) override; + +}; + +#endif From 98f8022268ad536cf6e2183e472a56ba7a6bcf04 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 21 Aug 2023 06:43:06 +1000 Subject: [PATCH 02/39] Fix device driver, disable objects, start parser --- DCCEXParser.cpp | 33 +++++++++++++++++++++----- IODevice.h | 1 - IO_EXTurntable.h => IO_EXTurntable.cpp | 4 ++-- Turntables.cpp => Turntables.cpp.txt | 0 Turntables.h => Turntables.h.txt | 0 5 files changed, 29 insertions(+), 9 deletions(-) rename IO_EXTurntable.h => IO_EXTurntable.cpp (97%) rename Turntables.cpp => Turntables.cpp.txt (100%) rename Turntables.h => Turntables.h.txt (100%) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 4a32902..cfe2563 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -41,7 +41,7 @@ #include "TrackManager.h" #include "DCCTimer.h" #include "EXRAIL2.h" -#include "Turntables.h" +// #include "Turntables.h" // This macro can't be created easily as a portable function because the // flashlist requires a far pointer for high flash access. @@ -96,6 +96,7 @@ const int16_t HASH_KEYWORD_ANOUT = -26399; const int16_t HASH_KEYWORD_WIFI = -5583; const int16_t HASH_KEYWORD_ETHERNET = -30767; const int16_t HASH_KEYWORD_WIT = 31594; +const int16_t HASH_KEYWORD_EXTT = 8573; int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS]; bool DCCEXParser::stashBusy; @@ -1021,25 +1022,45 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) // ========================== // Turntable +// - list all +// - delete +// - operate (DCC) +// - operate (EXTT) +// - create EXTT +// - create DCC? - This TBA bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) { switch (params) { case 0: // list turntable objects - return Turntable::printAll(stream); + StringFormatter::send(stream, F("\n")); + return true; + // return Turntable::printAll(stream); case 1: // delete turntable - if (!Turntable::remove(p[0])) - return false; - StringFormatter::send(stream, F("\n")); + // if (!Turntable::remove(p[0])) + // return false; + StringFormatter::send(stream, F("\n")); return true; case 2: // - rotate to position for DCC turntables case 3: // rotate to position for EX-Turntable { - + DIAG(F("Got %d parameters (2 or 3)"), params); + return true; } + + default: + { + if (params < 40) { + DIAG(F("Create turntable with %d parameters"), params); + return true; + } + } + break; + } + return false; } // CALLBACKS must be static diff --git a/IODevice.h b/IODevice.h index 8b8f3fe..769e111 100644 --- a/IODevice.h +++ b/IODevice.h @@ -542,7 +542,6 @@ protected: #include "IO_PCF8575.h" #include "IO_duinoNodes.h" #include "IO_EXIOExpander.h" -#include "IO_EXTurntable.h" #endif // iodevice_h diff --git a/IO_EXTurntable.h b/IO_EXTurntable.cpp similarity index 97% rename from IO_EXTurntable.h rename to IO_EXTurntable.cpp index 29ce679..f1a108b 100644 --- a/IO_EXTurntable.h +++ b/IO_EXTurntable.cpp @@ -20,9 +20,9 @@ /* * The IO_EXTurntable device driver is used to control a turntable via an Arduino with a stepper motor over I2C. * -* The EX-Turntable code lives in a separate repo (https://github.com/DCC-EX/Turntable-EX) and contains the stepper motor logic. +* The EX-Turntable code lives in a separate repo (https://github.com/DCC-EX/EX-Turntable) and contains the stepper motor logic. * -* This device driver sends a step position to Turntable-EX to indicate the step position to move to using either of these commands: +* This device driver sends a step position to EX-Turntable to indicate the step position to move to using either of these commands: * in the serial console * MOVETT(vpin, steps, activity) in EX-RAIL * Refer to the documentation for further information including the valid activities. diff --git a/Turntables.cpp b/Turntables.cpp.txt similarity index 100% rename from Turntables.cpp rename to Turntables.cpp.txt diff --git a/Turntables.h b/Turntables.h.txt similarity index 100% rename from Turntables.h rename to Turntables.h.txt From c4febd1d0f15d2dec5fbba1784c84d9b3f58327c Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 21 Aug 2023 19:33:45 +1000 Subject: [PATCH 03/39] More parser --- DCCEXParser.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index cfe2563..55a6cf7 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1044,18 +1044,23 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) return true; case 2: // - rotate to position for DCC turntables + DIAG(F("Rotate DCC turntable %d to position %d"), p[0], p[1]); + return true; + case 3: // rotate to position for EX-Turntable - { - DIAG(F("Got %d parameters (2 or 3)"), params); - return true; - } + DIAG(F("Rotate EXTT turntable %d to angle %d with activity %d"), p[0], p[1], p[2]); + return true; - default: + default: // If we're here, it must be creating a turntable object { - if (params < 40) { - DIAG(F("Create turntable with %d parameters"), params); + if (params < 41 && p[1] == HASH_KEYWORD_EXTT) { + DIAG(F("Create EXTT turntable %d on vpin %d and address %s with %d positions"), p[0], p[2], p[3], params - 4); + return true; + } else if (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); return true; } + } break; From b277d204f00b171b6d32407d3910da422a2334e8 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Tue, 22 Aug 2023 19:30:22 +1000 Subject: [PATCH 04/39] Progress! --- DCCEXParser.cpp | 28 ++++++++++++---------------- Turntables.cpp.txt => Turntables.cpp | 26 +++++++++++++------------- Turntables.h.txt => Turntables.h | 8 +++++--- 3 files changed, 30 insertions(+), 32 deletions(-) rename Turntables.cpp.txt => Turntables.cpp (88%) rename Turntables.h.txt => Turntables.h (96%) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 55a6cf7..4823e8e 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -41,7 +41,7 @@ #include "TrackManager.h" #include "DCCTimer.h" #include "EXRAIL2.h" -// #include "Turntables.h" +#include "Turntables.h" // This macro can't be created easily as a portable function because the // flashlist requires a far pointer for high flash access. @@ -1033,14 +1033,12 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) switch (params) { case 0: // list turntable objects - StringFormatter::send(stream, F("\n")); - return true; - // return Turntable::printAll(stream); + return Turntable::printAll(stream); case 1: // delete turntable - // if (!Turntable::remove(p[0])) - // return false; - StringFormatter::send(stream, F("\n")); + if (!Turntable::remove(p[0])) + return false; + StringFormatter::send(stream, F("\n")); return true; case 2: // - rotate to position for DCC turntables @@ -1053,19 +1051,17 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) default: // If we're here, it must be creating a turntable object { - if (params < 41 && p[1] == HASH_KEYWORD_EXTT) { - DIAG(F("Create EXTT turntable %d on vpin %d and address %s with %d positions"), p[0], p[2], p[3], params - 4); - return true; - } else if (params < 39 && p[1] == HASH_KEYWORD_DCC) { + if (params > 5 && params < 41 && p[1] == HASH_KEYWORD_EXTT) { + DIAG(F("Create EXTT turntable %d on vpin %d and address %d with %d positions"), p[0], p[2], p[3], params - 4); + if (!EXTTTurntable::create(p[0], (uint8_t)p[1], (VPIN)p[2])) return false; + } 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); - return true; + } else { + return false; } - } - break; - + return true; } - return false; } // CALLBACKS must be static diff --git a/Turntables.cpp.txt b/Turntables.cpp similarity index 88% rename from Turntables.cpp.txt rename to Turntables.cpp index 45a1d05..67dc8c0 100644 --- a/Turntables.cpp.txt +++ b/Turntables.cpp @@ -36,13 +36,14 @@ Turntable *Turntable::_firstTurntable = 0; /* * Public static data */ -int Turntable::_turntablelistHash = 0; +int Turntable::turntablelistHash = 0; /* * Protected static functions */ // Add new turntable to end of list + void Turntable::add(Turntable *tto) { if (!_firstTurntable) { _firstTurntable = tto; @@ -73,25 +74,25 @@ bool Turntable::remove(uint16_t id) { pp->_nextTurntable = tto->_nextTurntable; } - delete (EXTTTurntable *)tto; + // delete (EXTTTurntable *)tto; turntablelistHash++; return true; } - /* * Public static functions */ bool Turntable::isPosition(uint16_t id, uint8_t position) { Turntable *tto = get(id); - if (!tto) return false; if (tto) { if (tto->getPosition() == position) { return true; } else { return false; } + } else { + return false; } } @@ -102,15 +103,16 @@ bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position) { #if defined(EXRAIL_ACTIVE) // RMFT2::turntableEvent(id, position); #endif + return true; } -bool Turntable::setPosition(uint16_t id, uint8_t position) { +bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { #if defined(DIAG_IO) DIAG(F("Turntable(%d, %d)"), id, position); #endif Turntable *tto = Turntable::get(id); if (!tto) return false; - bool ok = tto->setPositionInternal(position); + bool ok = tto->setPositionInternal(position, activity); if (ok) { tto->setPositionStateOnly(id, position); @@ -123,30 +125,28 @@ bool Turntable::setPosition(uint16_t id, uint8_t position) { * *************************************************************************************/ // Private constructor -EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions) : +EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin) : Turntable(id, TURNTABLE_EXTT) { _exttTurntableData.i2caddress = i2caddress; _exttTurntableData.vpin = vpin; - _exttTurntableData.positions = **positions; } // Create function #ifndef IO_NO_HAL - Turntable *EXTTTurntable::create(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions) { + Turntable *EXTTTurntable::create(uint16_t id, uint8_t i2caddress, VPIN vpin) { Turntable *tto = get(id); if (tto) { if (tto->isType(TURNTABLE_EXTT)) { EXTTTurntable *extt = (EXTTTurntable *)tto; extt->_exttTurntableData.i2caddress = i2caddress; extt->_exttTurntableData.vpin = vpin; - extt->_exttTurntableData.positions = positions; return tto; } else { remove(id); } } - tto = (Turntable *)new EXTTTurntable(id, i2caddress, vpin, **positions); + tto = (Turntable *)new EXTTTurntable(id, i2caddress, vpin); DIAG(F("Turntable 0x%x"), tto); return tto; #else @@ -166,9 +166,9 @@ EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin, long ** bool EXTTTurntable::setPositionInternal(uint8_t position, uint8_t activity) { #ifndef IO_NO_HAL // Get step value from positions - int value = _exttTurntableData.positions[position]; + // int value = _exttTurntableData.positions[position]; // Set position via device driver - EXTurntable::_writeAnalogue(vpin, value, activity, 0); + // EXTurntable::_writeAnalogue(vpin, value, activity, 0); #else (void)position; #endif diff --git a/Turntables.h.txt b/Turntables.h similarity index 96% rename from Turntables.h.txt rename to Turntables.h index 5a6f346..2fa4255 100644 --- a/Turntables.h.txt +++ b/Turntables.h @@ -104,6 +104,7 @@ public: inline uint16_t getId() { return _turntableData.id; } inline Turntable *next() { return _nextTurntable; } void printState(Print *stream); + /* * Virtual functions @@ -112,6 +113,7 @@ public: (void)stream; // suppress compiler warnings } virtual ~Turntable() {} // Destructor + /* * Public static functions @@ -119,7 +121,7 @@ public: inline static bool exists(uint16_t id) { return get(id) != 0; } static bool remove(uint16_t id); static bool isPosition(uint16_t id, uint8_t position); - static bool setPosition(uint16_t id, uint8_t position); + static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); static bool setPositionStateOnly(uint16_t id, uint8_t position); inline static Turntable *first() { return _firstTurntable; } static bool printAll(Print *stream) { @@ -148,11 +150,11 @@ private: } _exttTurntableData; // Constructor - EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions); + EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin); public: // Create function - static Turntable *create(uint16_t id, uint8_t i2caddress, VPIN vpin, long **positions); + static Turntable *create(uint16_t id, uint8_t i2caddress, VPIN vpin); void print(Print *stream) override; protected: From ff9c558b61b9213f54d68e3db2e667cf040e91e4 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Wed, 23 Aug 2023 19:08:04 +1000 Subject: [PATCH 05/39] Not much progress --- DCCEXParser.cpp | 6 +++--- Turntables.cpp | 2 +- Turntables.h | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 4823e8e..e6bd814 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1035,17 +1035,17 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) case 0: // list turntable objects return Turntable::printAll(stream); - case 1: // delete turntable + case 1: // delete turntable if (!Turntable::remove(p[0])) return false; StringFormatter::send(stream, F("\n")); return true; - case 2: // - rotate to position for DCC turntables + case 2: // - rotate to position for DCC turntables DIAG(F("Rotate DCC turntable %d to position %d"), p[0], p[1]); return true; - case 3: // rotate to position for EX-Turntable + case 3: // rotate to position for EX-Turntable DIAG(F("Rotate EXTT turntable %d to angle %d with activity %d"), p[0], p[1], p[2]); return true; diff --git a/Turntables.cpp b/Turntables.cpp index 67dc8c0..5aaf9f0 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -74,7 +74,7 @@ bool Turntable::remove(uint16_t id) { pp->_nextTurntable = tto->_nextTurntable; } - // delete (EXTTTurntable *)tto; + delete (EXTTTurntable *)tto; turntablelistHash++; return true; diff --git a/Turntables.h b/Turntables.h index 2fa4255..c7bb394 100644 --- a/Turntables.h +++ b/Turntables.h @@ -57,6 +57,12 @@ protected: uint16_t id; } _turntableData; + // Linked list to store either positions (EXTT) or DCC addresses (DCC) + struct Position { + int16_t position; + Position *next; + }; + // Pointer to next turntable object Turntable *_nextTurntable = 0; @@ -146,7 +152,6 @@ private: struct EXTTTurntableData { uint8_t i2caddress; VPIN vpin; - long **positions; // Array of longs to store step positions } _exttTurntableData; // Constructor From 57d4655d54be41357d7a87469c45847044b8f51b Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 24 Aug 2023 07:22:37 +1000 Subject: [PATCH 06/39] Fix Uno/Nano build errors --- Turntables.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Turntables.cpp b/Turntables.cpp index 5aaf9f0..2f2a05e 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -133,8 +133,8 @@ EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin) : } // Create function -#ifndef IO_NO_HAL Turntable *EXTTTurntable::create(uint16_t id, uint8_t i2caddress, VPIN vpin) { +#ifndef IO_NO_HAL Turntable *tto = get(id); if (tto) { if (tto->isType(TURNTABLE_EXTT)) { @@ -153,7 +153,6 @@ EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin) : (void)id; (void)i2caddress; (void)vpin; - (void)positions; return NULL; #endif } From b823a647ac82a90ad1f95b3797933e92854d0eca Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Sat, 26 Aug 2023 10:26:01 +1000 Subject: [PATCH 07/39] Some progress --- DCCEXParser.cpp | 26 ++++++++++++++++++++------ Turntables.cpp | 29 ++++++++++++++--------------- Turntables.h | 49 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 75 insertions(+), 29 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index e6bd814..835dd32 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1035,18 +1035,27 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) case 0: // list turntable objects return Turntable::printAll(stream); - case 1: // delete turntable - if (!Turntable::remove(p[0])) - return false; - StringFormatter::send(stream, F("\n")); - return true; + case 1: // nothing here for the moment at least + return false; case 2: // - rotate to position for DCC turntables DIAG(F("Rotate DCC turntable %d to position %d"), p[0], p[1]); return true; case 3: // rotate to position for EX-Turntable - DIAG(F("Rotate EXTT turntable %d to angle %d with activity %d"), p[0], p[1], p[2]); + { + Turntable *tto = Turntable::get(p[0]); + if (tto) { + uint16_t value = tto->getPositionValue(p[1]); + if (value) { + DIAG(F("Position %d value is %d"), p[1], value); + } else { + return false; + } + } else { + return false; + } + } return true; default: // If we're here, it must be creating a turntable object @@ -1054,6 +1063,11 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) if (params > 5 && params < 41 && p[1] == HASH_KEYWORD_EXTT) { DIAG(F("Create EXTT turntable %d on vpin %d and address %d with %d positions"), p[0], p[2], p[3], params - 4); if (!EXTTTurntable::create(p[0], (uint8_t)p[1], (VPIN)p[2])) return false; + Turntable *tto = Turntable::get(p[0]); + for ( uint8_t i = 0; i < params - 4; i++) { + tto->addPosition(p[i + 3]); + DIAG(F("Add position %d"), p[i + 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 { diff --git a/Turntables.cpp b/Turntables.cpp index 2f2a05e..1ab5a70 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -62,22 +62,23 @@ Turntable *Turntable::get(uint16_t id) { return NULL; } -// Remove specified turntable from list and delete it -bool Turntable::remove(uint16_t id) { - Turntable *tto, *pp=NULL; +// Add a position +void Turntable::addPosition(uint16_t value) { + _turntablePositions.insert(value); +} - for (tto=_firstTurntable; tto!=NULL && tto->_turntableData.id!=id; pp=tto, tto=tto->_nextTurntable) {} - if (tto == NULL) return false; - if (tto == _firstTurntable) { - _firstTurntable = tto->_nextTurntable; - } else { - pp->_nextTurntable = tto->_nextTurntable; +// Get value for position +uint16_t Turntable::getPositionValue(size_t position) { + TurntablePosition* currentPosition = _turntablePositions.getHead(); + for (size_t i = 0; i < position && currentPosition; i++) { + currentPosition = currentPosition->next; } - delete (EXTTTurntable *)tto; - - turntablelistHash++; - return true; + if (currentPosition) { + return currentPosition->data; + } else { + return false; + } } /* @@ -142,8 +143,6 @@ EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin) : extt->_exttTurntableData.i2caddress = i2caddress; extt->_exttTurntableData.vpin = vpin; return tto; - } else { - remove(id); } } tto = (Turntable *)new EXTTTurntable(id, i2caddress, vpin); diff --git a/Turntables.h b/Turntables.h index c7bb394..3708d2a 100644 --- a/Turntables.h +++ b/Turntables.h @@ -33,6 +33,41 @@ enum { // TURNTABLE_DCC = 2, }; +/************************************************************************************* + * Turntable positions. + * + *************************************************************************************/ +struct TurntablePosition { + uint16_t data; + TurntablePosition* next; + + TurntablePosition(uint16_t value) : data(value), next(nullptr) {} +}; + +class TurntablePositionList { +public: + TurntablePositionList() : head(nullptr) {} + + void insert(uint16_t value) { + TurntablePosition* newPosition = new TurntablePosition(value); + if(!head) { + head = newPosition; + } else { + newPosition->next = head; + head = newPosition; + } + } + + TurntablePosition* getHead() { + return head; + } + +private: + TurntablePosition* head; + +}; + + /************************************************************************************* * Turntable - Base class for turntables. * @@ -57,15 +92,12 @@ protected: uint16_t id; } _turntableData; - // Linked list to store either positions (EXTT) or DCC addresses (DCC) - struct Position { - int16_t position; - Position *next; - }; - // Pointer to next turntable object Turntable *_nextTurntable = 0; + // Linked list for positions + TurntablePositionList _turntablePositions; + /* * Constructor */ @@ -73,6 +105,7 @@ protected: _turntableData.id = id; _turntableData.turntableType = turntableType; _turntableData.hidden = false; + _turntableData.position = 0; add(this); } @@ -110,7 +143,8 @@ public: inline uint16_t getId() { return _turntableData.id; } inline Turntable *next() { return _nextTurntable; } void printState(Print *stream); - + void addPosition(uint16_t value); + uint16_t getPositionValue(size_t position); /* * Virtual functions @@ -125,7 +159,6 @@ public: * Public static functions */ inline static bool exists(uint16_t id) { return get(id) != 0; } - static bool remove(uint16_t id); static bool isPosition(uint16_t id, uint8_t position); static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); static bool setPositionStateOnly(uint16_t id, uint8_t position); From 1425da20b500f254f7f16b2a1ba4493f463753ce Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sat, 26 Aug 2023 19:41:17 +1000 Subject: [PATCH 08/39] Correct order --- DCCEXParser.cpp | 5 +++-- IO_EXTurntable.cpp | 1 + Turntables.cpp | 12 ++++++------ Turntables.h | 6 +++--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 835dd32..995162b 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1060,11 +1060,12 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) default: // If we're here, it must be creating a turntable object { + DIAG(F("Params: %d"), params); if (params > 5 && params < 41 && p[1] == HASH_KEYWORD_EXTT) { DIAG(F("Create EXTT turntable %d on vpin %d and address %d with %d positions"), p[0], p[2], p[3], params - 4); - if (!EXTTTurntable::create(p[0], (uint8_t)p[1], (VPIN)p[2])) return false; + if (!EXTTTurntable::create(p[0], (VPIN)p[2], (uint8_t)p[3])) return false; Turntable *tto = Turntable::get(p[0]); - for ( uint8_t i = 0; i < params - 4; i++) { + for ( uint8_t i = params - 4; i > 0; i--) { tto->addPosition(p[i + 3]); DIAG(F("Add position %d"), p[i + 3]); } diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index f1a108b..b57fa25 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -100,6 +100,7 @@ int EXTurntable::_read(VPIN vpin) { // Acc_Off = 9 // Turn accessory pin off void EXTurntable::_writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_t duration) { if (_deviceState == DEVSTATE_FAILED) return; + if (value < 0) return; uint8_t stepsMSB = value >> 8; uint8_t stepsLSB = value & 0xFF; #ifdef DIAG_IO diff --git a/Turntables.cpp b/Turntables.cpp index 1ab5a70..f75b30d 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -126,26 +126,26 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { * *************************************************************************************/ // Private constructor -EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin) : +EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : Turntable(id, TURNTABLE_EXTT) { - _exttTurntableData.i2caddress = i2caddress; _exttTurntableData.vpin = vpin; + _exttTurntableData.i2caddress = i2caddress; } // Create function - Turntable *EXTTTurntable::create(uint16_t id, uint8_t i2caddress, VPIN vpin) { + Turntable *EXTTTurntable::create(uint16_t id, VPIN vpin, uint8_t i2caddress) { #ifndef IO_NO_HAL Turntable *tto = get(id); if (tto) { if (tto->isType(TURNTABLE_EXTT)) { EXTTTurntable *extt = (EXTTTurntable *)tto; - extt->_exttTurntableData.i2caddress = i2caddress; extt->_exttTurntableData.vpin = vpin; + extt->_exttTurntableData.i2caddress = i2caddress; return tto; } } - tto = (Turntable *)new EXTTTurntable(id, i2caddress, vpin); + tto = (Turntable *)new EXTTTurntable(id, vpin, i2caddress); DIAG(F("Turntable 0x%x"), tto); return tto; #else @@ -157,7 +157,7 @@ EXTTTurntable::EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin) : } void EXTTTurntable::print(Print *stream) { - StringFormatter::send(stream, F("\n"), _turntableData.id, _exttTurntableData.i2caddress, _exttTurntableData.vpin); + StringFormatter::send(stream, F("\n"), _turntableData.id, _exttTurntableData.vpin, _exttTurntableData.i2caddress); } // EX-Turntable specific code for moving to the specified position diff --git a/Turntables.h b/Turntables.h index 3708d2a..303c542 100644 --- a/Turntables.h +++ b/Turntables.h @@ -183,16 +183,16 @@ class EXTTTurntable : public Turntable { private: // EXTTTurntableData contains device specific data struct EXTTTurntableData { - uint8_t i2caddress; VPIN vpin; + uint8_t i2caddress; } _exttTurntableData; // Constructor - EXTTTurntable(uint16_t id, uint8_t i2caddress, VPIN vpin); + EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress); public: // Create function - static Turntable *create(uint16_t id, uint8_t i2caddress, VPIN vpin); + static Turntable *create(uint16_t id, VPIN vpin, uint8_t i2caddress); void print(Print *stream) override; protected: From 2202cb0c5eddbc4ca3c1a3df1c95604278f64353 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 27 Aug 2023 19:30:56 +1000 Subject: [PATCH 09/39] Minor progress --- DCCEXParser.cpp | 6 +++--- IO_EXTurntable.cpp | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 995162b..48c45fb 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1060,15 +1060,15 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) default: // If we're here, it must be creating a turntable object { - DIAG(F("Params: %d"), params); if (params > 5 && params < 41 && p[1] == HASH_KEYWORD_EXTT) { DIAG(F("Create EXTT turntable %d on vpin %d and address %d with %d positions"), p[0], p[2], p[3], params - 4); + if (Turntable::get(p[0])) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2], (uint8_t)p[3])) return false; Turntable *tto = Turntable::get(p[0]); - for ( uint8_t i = params - 4; i > 0; i--) { + for (uint8_t i = params - 4; i > 0; i--) { tto->addPosition(p[i + 3]); - DIAG(F("Add position %d"), p[i + 3]); } + tto->addPosition(0); // Need to add position 0 as 0 so positions start at 1 } 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 { diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index b57fa25..8c7057b 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -51,6 +51,7 @@ EXTurntable::EXTurntable(VPIN firstVpin, int nPins, I2CAddress I2CAddress) { void EXTurntable::_begin() { I2CManager.begin(); if (I2CManager.exists(_I2CAddress)) { + DIAG(F("EX-Turntable device found, I2C:%s"), _I2CAddress.toString()); #ifdef DIAG_IO _display(); #endif From df4a501e8a34fd7748675bf3801be10419334649 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:36:09 +1000 Subject: [PATCH 10/39] Writing to driver --- DCCEXParser.cpp | 23 +++++++++++++++-------- Turntables.cpp | 22 ++++++---------------- Turntables.h | 1 - 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 48c45fb..45e8a73 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1039,19 +1039,27 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) return false; case 2: // - rotate to position for DCC turntables - DIAG(F("Rotate DCC turntable %d to position %d"), p[0], p[1]); + { + Turntable *tto = Turntable::get(p[0]); + if (tto) { + if (tto->getPosition() == p[1]) return true; + 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 { + return false; + } + } return true; case 3: // rotate to position for EX-Turntable { Turntable *tto = Turntable::get(p[0]); if (tto) { - uint16_t value = tto->getPositionValue(p[1]); - if (value) { - DIAG(F("Position %d value is %d"), p[1], value); - } else { - return false; - } + if (!tto->setPosition(p[0], p[1], p[2])) return false; } else { return false; } @@ -1061,7 +1069,6 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) default: // If we're here, it must be creating a turntable object { if (params > 5 && params < 41 && p[1] == HASH_KEYWORD_EXTT) { - DIAG(F("Create EXTT turntable %d on vpin %d and address %d with %d positions"), p[0], p[2], p[3], params - 4); if (Turntable::get(p[0])) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2], (uint8_t)p[3])) return false; Turntable *tto = Turntable::get(p[0]); diff --git a/Turntables.cpp b/Turntables.cpp index f75b30d..ec31a00 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -84,19 +84,6 @@ uint16_t Turntable::getPositionValue(size_t position) { /* * Public static functions */ -bool Turntable::isPosition(uint16_t id, uint8_t position) { - Turntable *tto = get(id); - if (tto) { - if (tto->getPosition() == position) { - return true; - } else { - return false; - } - } else { - return false; - } -} - bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position) { Turntable *tto = get(id); if (!tto) return false; @@ -117,6 +104,7 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { if (ok) { tto->setPositionStateOnly(id, position); + tto->_turntableData.position = position; } return ok; } @@ -163,10 +151,12 @@ EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : // EX-Turntable specific code for moving to the specified position bool EXTTTurntable::setPositionInternal(uint8_t position, uint8_t activity) { #ifndef IO_NO_HAL - // Get step value from positions - // int value = _exttTurntableData.positions[position]; + DIAG(F("Set EXTT %d to position %d with activity %d"), _exttTurntableData.vpin, position, activity); + // Get position value from position list + int16_t value = getPositionValue(position); + if (!value) return false; // Return false if it's not a valid position // Set position via device driver - // EXTurntable::_writeAnalogue(vpin, value, activity, 0); + EXTurntable::writeAnalogue(_exttTurntableData.vpin, value, activity); #else (void)position; #endif diff --git a/Turntables.h b/Turntables.h index 303c542..f3a3321 100644 --- a/Turntables.h +++ b/Turntables.h @@ -159,7 +159,6 @@ public: * Public static functions */ inline static bool exists(uint16_t id) { return get(id) != 0; } - static bool isPosition(uint16_t id, uint8_t position); static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); static bool setPositionStateOnly(uint16_t id, uint8_t position); inline static Turntable *first() { return _firstTurntable; } From 3bfdd16288af0424c7d162f6f13787a79030dc25 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:11:37 +1000 Subject: [PATCH 11/39] Start on JO --- DCCEXParser.cpp | 26 +++++++++++++++++++++++++- Turntables.cpp | 4 ++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 45e8a73..f8dd9d4 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -85,6 +85,7 @@ const int16_t HASH_KEYWORD_A='A'; const int16_t HASH_KEYWORD_C='C'; const int16_t HASH_KEYWORD_G='G'; const int16_t HASH_KEYWORD_I='I'; +const int16_t HASH_KEYWORD_O='O'; const int16_t HASH_KEYWORD_R='R'; const int16_t HASH_KEYWORD_T='T'; const int16_t HASH_KEYWORD_X='X'; @@ -691,6 +692,29 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) } StringFormatter::send(stream, F(">\n")); return; + case HASH_KEYWORD_O: // + for ( Turntable * tto=Turntable::first(); tto; tto=tto->next()) { + if (tto->isHidden()) continue; + StringFormatter::send(stream, F(" %d"),tto->getId()); + } + } else { // + Turntable *tto=Turntable::get(id); + if (!tto || tto->isHidden()) { + StringFormatter::send(stream, F(" %d X"), id); + } else { + uint8_t pos = tto->getPosition(); + const FSH *todesc = NULL; +#ifdef EXRAIL_ACTIVE + // todesc = RMFT2::getTurntableDescription(id); +#endif + if (todesc == NULL) todesc = F(""); + StringFormatter::send(stream, F(" %d %d"), id, pos); + } + } + StringFormatter::send(stream, F(">\n")); + return; default: break; } // switch(p[1]) break; // case J @@ -1075,7 +1099,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) for (uint8_t i = params - 4; i > 0; i--) { tto->addPosition(p[i + 3]); } - tto->addPosition(0); // Need to add position 0 as 0 so positions start at 1 + tto->addPosition(p[3]); // Allow setting a value for the home angle for throttles to draw it } 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 { diff --git a/Turntables.cpp b/Turntables.cpp index ec31a00..5332aa5 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -152,8 +152,8 @@ EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : bool EXTTTurntable::setPositionInternal(uint8_t position, uint8_t activity) { #ifndef IO_NO_HAL DIAG(F("Set EXTT %d to position %d with activity %d"), _exttTurntableData.vpin, position, activity); - // Get position value from position list - int16_t value = getPositionValue(position); + if (position == 0) return false; // Position 0 is just so throttles know where home is + int16_t value = getPositionValue(position); // Get position value from position list if (!value) return false; // Return false if it's not a valid position // Set position via device driver EXTurntable::writeAnalogue(_exttTurntableData.vpin, value, activity); From b0d85101275b3184f902547a9b0f6a684571e5e9 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:38:52 +1000 Subject: [PATCH 12/39] Working but limited --- DCCEXParser.cpp | 17 +++++++++++------ Turntables.cpp | 32 +++++++++++++++++++++++++------- Turntables.h | 2 ++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index f8dd9d4..9047cad 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -695,7 +695,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) case HASH_KEYWORD_O: // - for ( Turntable * tto=Turntable::first(); tto; tto=tto->next()) { + for (Turntable * tto=Turntable::first(); tto; tto=tto->next()) { if (tto->isHidden()) continue; StringFormatter::send(stream, F(" %d"),tto->getId()); } @@ -705,12 +705,18 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) StringFormatter::send(stream, F(" %d X"), id); } else { uint8_t pos = tto->getPosition(); + uint8_t type = tto->getType(); + uint8_t posCount = tto->getPositionCount(); const FSH *todesc = NULL; #ifdef EXRAIL_ACTIVE // todesc = RMFT2::getTurntableDescription(id); #endif if (todesc == NULL) todesc = F(""); - StringFormatter::send(stream, F(" %d %d"), id, pos); + StringFormatter::send(stream, F(" %d %d %d %d"), id, type, pos, posCount); + for (uint8_t p = 0; p < posCount; p++) { + int16_t value = tto->getPositionValue(p); + StringFormatter::send(stream, F(" %d"), value); + } } } StringFormatter::send(stream, F(">\n")); @@ -1047,7 +1053,6 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) // ========================== // Turntable // - list all -// - delete // - operate (DCC) // - operate (EXTT) // - create EXTT @@ -1096,10 +1101,10 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) if (Turntable::get(p[0])) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2], (uint8_t)p[3])) return false; Turntable *tto = Turntable::get(p[0]); - for (uint8_t i = params - 4; i > 0; i--) { - tto->addPosition(p[i + 3]); + for (uint8_t i = params - 5; i > 0; i--) { + tto->addPosition(p[i + 4]); } - tto->addPosition(p[3]); // Allow setting a value for the home angle for throttles to draw it + tto->addPosition(p[4]); // Allow setting a value for the home angle for throttles to draw it } 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 { diff --git a/Turntables.cpp b/Turntables.cpp index 5332aa5..bcc0a94 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -81,6 +81,17 @@ uint16_t Turntable::getPositionValue(size_t position) { } } +// Get the count of positions associated with the turntable +uint8_t Turntable::getPositionCount() { + TurntablePosition* currentPosition = _turntablePositions.getHead(); + uint8_t count = 0; + while (currentPosition) { + count++; + currentPosition = currentPosition->next; + } + return count; +} + /* * Public static functions */ @@ -103,8 +114,11 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { bool ok = tto->setPositionInternal(position, activity); if (ok) { - tto->setPositionStateOnly(id, position); - tto->_turntableData.position = position; + // Broadcast a position change only if non zero has been set, or home/calibration sent + if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) { + tto->setPositionStateOnly(id, position); + tto->_turntableData.position = position; + } } return ok; } @@ -134,7 +148,7 @@ EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : } } tto = (Turntable *)new EXTTTurntable(id, vpin, i2caddress); - DIAG(F("Turntable 0x%x"), tto); + DIAG(F("Turntable 0x%x size %d size %d"), tto, sizeof(Turntable), sizeof(struct TurntableData)); return tto; #else (void)id; @@ -151,10 +165,14 @@ EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : // EX-Turntable specific code for moving to the specified position bool EXTTTurntable::setPositionInternal(uint8_t position, uint8_t activity) { #ifndef IO_NO_HAL - DIAG(F("Set EXTT %d to position %d with activity %d"), _exttTurntableData.vpin, position, activity); - if (position == 0) return false; // Position 0 is just so throttles know where home is - int16_t value = getPositionValue(position); // Get position value from position list - if (!value) return false; // Return false if it's not a valid position + int16_t value; + if (position == 0) { + value = 0; // Position 0 is just to send activities + } else { + if (activity > 1) return false; // If sending a position update, only phase changes valid (0|1) + value = getPositionValue(position); // Get position value from position list + } + if (position > 0 && !value) return false; // Return false if it's not a valid position // Set position via device driver EXTurntable::writeAnalogue(_exttTurntableData.vpin, value, activity); #else diff --git a/Turntables.h b/Turntables.h index f3a3321..1016140 100644 --- a/Turntables.h +++ b/Turntables.h @@ -140,11 +140,13 @@ public: inline bool isHidden() { return _turntableData.hidden; } inline void setHidden(bool h) {_turntableData.hidden=h; } inline bool isType(uint8_t type) { return _turntableData.turntableType == type; } + inline uint8_t getType() { return _turntableData.turntableType; } inline uint16_t getId() { return _turntableData.id; } inline Turntable *next() { return _nextTurntable; } void printState(Print *stream); void addPosition(uint16_t value); uint16_t getPositionValue(size_t position); + uint8_t getPositionCount(); /* * Virtual functions From 6cad794411f60f2022548cb9fb9c6272a0daafd2 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Tue, 29 Aug 2023 19:04:45 +1000 Subject: [PATCH 13/39] Working with 15 positions --- DCCEXParser.cpp | 10 +++++++++- DCCEXParser.h | 5 ++++- IODevice.h | 6 ------ Turntables.cpp | 4 ++++ Turntables.h | 5 +++++ defines.h | 20 ++++++++++++++++++++ 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 9047cad..a37e5d0 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -692,6 +692,8 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) } StringFormatter::send(stream, F(">\n")); return; +// No turntables without HAL support +#ifndef IO_NO_HAL case HASH_KEYWORD_O: // @@ -721,15 +723,19 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) } StringFormatter::send(stream, F(">\n")); return; +#endif default: break; } // switch(p[1]) break; // case J } +// No turntables without HAL support +#ifndef IO_NO_HAL case 'I': // TURNTABLE if (parseI(stream, params, p)) return; break; +#endif default: //anything else will diagnose and drop out to DIAG(F("Opcode=%c params=%d"), opcode, params); @@ -1051,12 +1057,13 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) } // ========================== -// Turntable +// Turntable - no support if no HAL // - list all // - operate (DCC) // - operate (EXTT) // - create EXTT // - create DCC? - This TBA +#ifndef IO_NO_HAL bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) { switch (params) @@ -1114,6 +1121,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) return true; } } +#endif // CALLBACKS must be static bool DCCEXParser::stashCallback(Print *stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream) diff --git a/DCCEXParser.h b/DCCEXParser.h index bf067a7..a3d5e10 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -24,6 +24,7 @@ #include #include "FSH.h" #include "RingStream.h" +#include "defines.h" typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int16_t p[]); typedef void (*AT_COMMAND_CALLBACK)(HardwareSerial * stream,const byte * command); @@ -37,7 +38,7 @@ struct DCCEXParser static void setFilter(FILTER_CALLBACK filter); static void setRMFTFilter(FILTER_CALLBACK filter); static void setAtCommandCallback(AT_COMMAND_CALLBACK filter); - static const int MAX_COMMAND_PARAMS=10; // Must not exceed this + static const int MAX_COMMAND_PARAMS=MAX_PARSER_PARAMS; // Must not exceed this private: @@ -49,7 +50,9 @@ struct DCCEXParser static bool parseS(Print * stream, int16_t params, int16_t p[]); static bool parsef(Print * stream, int16_t params, int16_t p[]); static bool parseD(Print * stream, int16_t params, int16_t p[]); +#ifndef IO_NO_HAL static bool parseI(Print * stream, int16_t params, int16_t p[]); +#endif static Print * getAsyncReplyStream(); static void commitAsyncReplyStream(); diff --git a/IODevice.h b/IODevice.h index 769e111..d2c80a4 100644 --- a/IODevice.h +++ b/IODevice.h @@ -27,12 +27,6 @@ // Define symbol DIAG_LOOPTIMES to enable CS loop execution time to be reported //#define DIAG_LOOPTIMES -// Define symbol IO_NO_HAL to reduce FLASH footprint when HAL features not required -// The HAL is disabled by default on Nano and Uno platforms, because of limited flash space. -#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO) -#define IO_NO_HAL -#endif - // Define symbol IO_SWITCH_OFF_SERVO to set the PCA9685 output to 0 when an // animation has completed. This switches off the servo motor, preventing // the continuous buzz sometimes found on servos, and reducing the diff --git a/Turntables.cpp b/Turntables.cpp index bcc0a94..6b4260f 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -26,6 +26,8 @@ #include "EXRAIL2.h" #include "DCC.h" +// No turntable support without HAL +#ifndef IO_NO_HAL /* * Protected static data @@ -180,3 +182,5 @@ EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : #endif return true; } + +#endif diff --git a/Turntables.h b/Turntables.h index 1016140..67017df 100644 --- a/Turntables.h +++ b/Turntables.h @@ -25,6 +25,9 @@ #include "IODevice.h" #include "StringFormatter.h" +// No turntable support without HAL +#ifndef IO_NO_HAL + // Turntable type definitions // EXTT = EX-Turntable // DCC = DCC accessory turntables - to be added later @@ -203,3 +206,5 @@ protected: }; #endif + +#endif diff --git a/defines.h b/defines.h index f3822ca..342d1b6 100644 --- a/defines.h +++ b/defines.h @@ -213,6 +213,26 @@ // #define WIFI_SERIAL_LINK_SPEED 115200 +//////////////////////////////////////////////////////////////////////////////// +// +// Define symbol IO_NO_HAL to reduce FLASH footprint when HAL features not required +// The HAL is disabled by default on Nano and Uno platforms, because of limited flash space. +// +#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO) +#define IO_NO_HAL +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// This defines the maximum number of parameters DCCEXParser will accept. +// The increase is required to allow for a sufficient number of turntable positions. +// +#ifdef IO_NO_HAL + #define MAX_PARSER_PARAMS 10 +#else + #define MAX_PARSER_PARAMS 20 +#endif + #if __has_include ( "myAutomation.h") #if defined(HAS_ENOUGH_MEMORY) || defined(DISABLE_EEPROM) || defined(DISABLE_PROG) #define EXRAIL_ACTIVE From 232ac993ecf58451457d6b959cd0845616ff18b0 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 30 Aug 2023 08:45:11 +1000 Subject: [PATCH 14/39] Separate add from create --- DCCEXParser.cpp | 65 +++++++++++++++++++++++++++++++------------------ Turntables.cpp | 14 +++++------ Turntables.h | 18 ++++++++------ 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index a37e5d0..24a7914 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -98,6 +98,7 @@ const int16_t HASH_KEYWORD_WIFI = -5583; const int16_t HASH_KEYWORD_ETHERNET = -30767; const int16_t HASH_KEYWORD_WIT = 31594; const int16_t HASH_KEYWORD_EXTT = 8573; +const int16_t HASH_KEYWORD_ADD = 3201; int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS]; bool DCCEXParser::stashBusy; @@ -714,7 +715,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) // todesc = RMFT2::getTurntableDescription(id); #endif if (todesc == NULL) todesc = F(""); - StringFormatter::send(stream, F(" %d %d %d %d"), id, type, pos, posCount); + StringFormatter::send(stream, F(" %d %d %d"), id, type, pos); for (uint8_t p = 0; p < posCount; p++) { int16_t value = tto->getPositionValue(p); StringFormatter::send(stream, F(" %d"), value); @@ -1059,10 +1060,12 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) // ========================== // Turntable - no support if no HAL // - list all +// - broadcast type and current position +// - create DCC - This is TBA // - operate (DCC) // - operate (EXTT) -// - create EXTT -// - create DCC? - This TBA +// - add position +// - create EXTT #ifndef IO_NO_HAL bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) { @@ -1071,47 +1074,58 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) case 0: // list turntable objects return Turntable::printAll(stream); - case 1: // nothing here for the moment at least + case 1: // broadcast type and current position return false; case 2: // - rotate to position for DCC turntables { - Turntable *tto = Turntable::get(p[0]); - if (tto) { - if (tto->getPosition() == p[1]) return true; - uint16_t value = tto->getPositionValue(p[1]); - if (value) { - DIAG(F("Rotate DCC turntable %d to position %d"), p[0], p[1]); + if (p[1] == HASH_KEYWORD_DCC) { // Create a DCC turntable + DIAG(F("Create DCC turntable %d"), p[0]); + } else { // Otherwise move a DCC turntable + Turntable *tto = Turntable::get(p[0]); + if (tto) { + if (tto->getPosition() == p[1]) return true; + 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 { return false; } - } else { - return false; } } return true; - case 3: // rotate to position for EX-Turntable + case 3: { - Turntable *tto = Turntable::get(p[0]); - if (tto) { - if (!tto->setPosition(p[0], p[1], p[2])) return false; - } else { - return false; + if (p[1] == HASH_KEYWORD_ADD) { // add position value to turntable + Turntable *tto = Turntable::get(p[0]); + if (tto) { + tto->addPosition(p[2]); + StringFormatter::send(stream, F("\n")); + } else { + return false; + } + } else { // rotate to position for EX-Turntable + Turntable *tto = Turntable::get(p[0]); + if (tto) { + if (!tto->setPosition(p[0], p[1], p[2])) return false; + } else { + return false; + } } } return true; - default: // If we're here, it must be creating a turntable object + case 5: // create an EXTT turntable { - if (params > 5 && params < 41 && p[1] == HASH_KEYWORD_EXTT) { + if (p[1] == HASH_KEYWORD_EXTT) { if (Turntable::get(p[0])) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2], (uint8_t)p[3])) return false; Turntable *tto = Turntable::get(p[0]); - for (uint8_t i = params - 5; i > 0; i--) { - tto->addPosition(p[i + 4]); - } - tto->addPosition(p[4]); // Allow setting a value for the home angle for throttles to draw it + tto->addPosition(p[4]); } 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 { @@ -1119,6 +1133,9 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) } } return true; + + default: // Anything else is invalid + return false; } } #endif diff --git a/Turntables.cpp b/Turntables.cpp index 6b4260f..a7d42ab 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -70,17 +70,15 @@ void Turntable::addPosition(uint16_t value) { } // Get value for position -uint16_t Turntable::getPositionValue(size_t position) { +uint16_t Turntable::getPositionValue(uint8_t position) { TurntablePosition* currentPosition = _turntablePositions.getHead(); - for (size_t i = 0; i < position && currentPosition; i++) { + while (currentPosition) { + if (currentPosition->index == position) { + return currentPosition->data; + } currentPosition = currentPosition->next; } - - if (currentPosition) { - return currentPosition->data; - } else { - return false; - } + return false; } // Get the count of positions associated with the turntable diff --git a/Turntables.h b/Turntables.h index 67017df..36f5b90 100644 --- a/Turntables.h +++ b/Turntables.h @@ -32,8 +32,8 @@ // EXTT = EX-Turntable // DCC = DCC accessory turntables - to be added later enum { - TURNTABLE_EXTT = 1, - // TURNTABLE_DCC = 2, + TURNTABLE_EXTT = 0, + TURNTABLE_DCC = 1, }; /************************************************************************************* @@ -41,18 +41,19 @@ enum { * *************************************************************************************/ struct TurntablePosition { + uint8_t index; uint16_t data; TurntablePosition* next; - TurntablePosition(uint16_t value) : data(value), next(nullptr) {} + TurntablePosition(uint8_t idx, uint16_t value) : index(idx), data(value), next(nullptr) {} }; class TurntablePositionList { public: - TurntablePositionList() : head(nullptr) {} + TurntablePositionList() : head(nullptr), currentIndex(0) {} void insert(uint16_t value) { - TurntablePosition* newPosition = new TurntablePosition(value); + TurntablePosition* newPosition = new TurntablePosition(currentIndex++, value); if(!head) { head = newPosition; } else { @@ -67,6 +68,7 @@ public: private: TurntablePosition* head; + uint8_t currentIndex; }; @@ -87,8 +89,8 @@ protected: union { struct { bool hidden : 1; - uint8_t turntableType : 2; - uint8_t position : 5; // Allows up to 38 positions including 0/home + bool turntableType : 1; + uint8_t position : 6; // Allows up to 63 positions including 0/home }; uint8_t flags; }; @@ -148,7 +150,7 @@ public: inline Turntable *next() { return _nextTurntable; } void printState(Print *stream); void addPosition(uint16_t value); - uint16_t getPositionValue(size_t position); + uint16_t getPositionValue(uint8_t position); uint8_t getPositionCount(); /* From dbf053858b61d5315790427adb5ed4da08e7a8ae Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 30 Aug 2023 13:40:09 +1000 Subject: [PATCH 15/39] Undo max params --- DCCEXParser.h | 2 +- defines.h | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/DCCEXParser.h b/DCCEXParser.h index a3d5e10..8a7367a 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -38,7 +38,7 @@ struct DCCEXParser static void setFilter(FILTER_CALLBACK filter); static void setRMFTFilter(FILTER_CALLBACK filter); static void setAtCommandCallback(AT_COMMAND_CALLBACK filter); - static const int MAX_COMMAND_PARAMS=MAX_PARSER_PARAMS; // Must not exceed this + static const int MAX_COMMAND_PARAMS=10; // Must not exceed this private: diff --git a/defines.h b/defines.h index 342d1b6..3286aca 100644 --- a/defines.h +++ b/defines.h @@ -222,17 +222,6 @@ #define IO_NO_HAL #endif -//////////////////////////////////////////////////////////////////////////////// -// -// This defines the maximum number of parameters DCCEXParser will accept. -// The increase is required to allow for a sufficient number of turntable positions. -// -#ifdef IO_NO_HAL - #define MAX_PARSER_PARAMS 10 -#else - #define MAX_PARSER_PARAMS 20 -#endif - #if __has_include ( "myAutomation.h") #if defined(HAS_ENOUGH_MEMORY) || defined(DISABLE_EEPROM) || defined(DISABLE_PROG) #define EXRAIL_ACTIVE From a0c1ad182cb9f76be7da471a6f18ea7698431cde Mon Sep 17 00:00:00 2001 From: peteGSX Date: Wed, 30 Aug 2023 19:48:30 +1000 Subject: [PATCH 16/39] Start on callback --- CommandDistributor.cpp | 4 ++-- CommandDistributor.h | 2 +- DCCEXParser.cpp | 5 +++++ DCCEXParser.h | 1 + Turntables.cpp | 10 +++++++--- Turntables.h | 5 ++++- 6 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index eef84a9..ee760b0 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -161,8 +161,8 @@ void CommandDistributor::broadcastTurnout(int16_t id, bool isClosed ) { #endif } -void CommandDistributor::broadcastTurntable(int16_t id, uint8_t position) { - broadcastReply(COMMAND_TYPE, F("\n"), id, position); +void CommandDistributor::broadcastTurntable(int16_t id, uint8_t position, bool moving) { + broadcastReply(COMMAND_TYPE, F("\n"), id, position, moving); } void CommandDistributor::broadcastClockTime(int16_t time, int8_t rate) { diff --git a/CommandDistributor.h b/CommandDistributor.h index b1af10a..a51d58a 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -49,7 +49,7 @@ public : static void broadcastLoco(byte slot); static void broadcastSensor(int16_t id, bool value); static void broadcastTurnout(int16_t id, bool isClosed); - static void broadcastTurntable(int16_t id, uint8_t position); + static void broadcastTurntable(int16_t id, uint8_t position, bool moving); static void broadcastClockTime(int16_t time, int8_t rate); static void setClockTime(int16_t time, int8_t rate, byte opt); static int16_t retClockTime(); diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 24a7914..2b0e06f 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1226,3 +1226,8 @@ void DCCEXParser::callback_Wloco(int16_t result) StringFormatter::send(getAsyncReplyStream(), F("\n"), result); commitAsyncReplyStream(); } + +void DCCEXParser::callback_Imoving(bool moving) { + if (!moving) StringFormatter::send(getAsyncReplyStream(), F("")); + commitAsyncReplyStream(); +} diff --git a/DCCEXParser.h b/DCCEXParser.h index 8a7367a..7a7ef89 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -72,6 +72,7 @@ struct DCCEXParser static void callback_Wloco(int16_t result); static void callback_Vbit(int16_t result); static void callback_Vbyte(int16_t result); + static void callback_Imoving(bool moving); static FILTER_CALLBACK filterCallback; static FILTER_CALLBACK filterRMFTCallback; static AT_COMMAND_CALLBACK atCommandCallback; diff --git a/Turntables.cpp b/Turntables.cpp index a7d42ab..a0419b1 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -95,10 +95,10 @@ uint8_t Turntable::getPositionCount() { /* * Public static functions */ -bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position) { +bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool moving) { Turntable *tto = get(id); if (!tto) return false; - CommandDistributor::broadcastTurntable(id, position); + CommandDistributor::broadcastTurntable(id, position, moving); #if defined(EXRAIL_ACTIVE) // RMFT2::turntableEvent(id, position); #endif @@ -116,7 +116,11 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { if (ok) { // Broadcast a position change only if non zero has been set, or home/calibration sent if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) { - tto->setPositionStateOnly(id, position); + if (tto->getType() == TURNTABLE_EXTT) { + tto->setPositionStateOnly(id, position, 1); + } else { + tto->setPositionStateOnly(id, position, 0); + } tto->_turntableData.position = position; } } diff --git a/Turntables.h b/Turntables.h index 36f5b90..d59bc80 100644 --- a/Turntables.h +++ b/Turntables.h @@ -36,6 +36,9 @@ enum { TURNTABLE_DCC = 1, }; +// Callback needs to return a bool: 1 = moving, 0 = stopped +typedef void (*EXTT_CALLBACK)(bool moving); + /************************************************************************************* * Turntable positions. * @@ -167,7 +170,7 @@ public: */ inline static bool exists(uint16_t id) { return get(id) != 0; } static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); - static bool setPositionStateOnly(uint16_t id, uint8_t position); + static bool setPositionStateOnly(uint16_t id, uint8_t position, bool moving); inline static Turntable *first() { return _firstTurntable; } static bool printAll(Print *stream) { bool gotOne = false; From 9fa213e198f66c877a8fdc6db7bb03ee9ea3e1e4 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 31 Aug 2023 13:51:25 +1000 Subject: [PATCH 17/39] Undo callback --- DCCEXParser.cpp | 5 ----- DCCEXParser.h | 1 - 2 files changed, 6 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 2b0e06f..24a7914 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1226,8 +1226,3 @@ void DCCEXParser::callback_Wloco(int16_t result) StringFormatter::send(getAsyncReplyStream(), F("\n"), result); commitAsyncReplyStream(); } - -void DCCEXParser::callback_Imoving(bool moving) { - if (!moving) StringFormatter::send(getAsyncReplyStream(), F("")); - commitAsyncReplyStream(); -} diff --git a/DCCEXParser.h b/DCCEXParser.h index 7a7ef89..8a7367a 100644 --- a/DCCEXParser.h +++ b/DCCEXParser.h @@ -72,7 +72,6 @@ struct DCCEXParser static void callback_Wloco(int16_t result); static void callback_Vbit(int16_t result); static void callback_Vbyte(int16_t result); - static void callback_Imoving(bool moving); static FILTER_CALLBACK filterCallback; static FILTER_CALLBACK filterRMFTCallback; static AT_COMMAND_CALLBACK atCommandCallback; From f40d57d8bde35ef7b075a602e65ec213a7058b2f Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 1 Sep 2023 08:44:32 +1000 Subject: [PATCH 18/39] Add DCC type, EXTT broadcast from driver --- DCCEXParser.cpp | 55 ++++++++++++++-------------- IODevice.cpp | 7 ++++ IODevice.h | 5 +++ IO_EXTurntable.cpp | 16 +++++++++ Turntables.cpp | 90 +++++++++++++++++++++++++++++++++++++--------- Turntables.h | 29 ++++++++++++--- 6 files changed, 152 insertions(+), 50 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 24a7914..7473c26 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -708,7 +708,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) StringFormatter::send(stream, F(" %d X"), id); } else { uint8_t pos = tto->getPosition(); - uint8_t type = tto->getType(); + uint8_t type = tto->isEXTT(); uint8_t posCount = tto->getPositionCount(); const FSH *todesc = NULL; #ifdef EXRAIL_ACTIVE @@ -1075,22 +1075,29 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) return Turntable::printAll(stream); case 1: // 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("\n"), type, position); + } else { + return false; + } + } + return true; case 2: // - rotate to position for DCC turntables { + Turntable *tto = Turntable::get(p[0]); if (p[1] == HASH_KEYWORD_DCC) { // Create a DCC turntable - DIAG(F("Create DCC turntable %d"), p[0]); - } else { // Otherwise move a DCC turntable + if (tto) return false; + if (!DCCTurntable::create(p[0])) return false; Turntable *tto = Turntable::get(p[0]); + tto->addPosition(0); + } else { // Otherwise move a DCC turntable if (tto) { - if (tto->getPosition() == p[1]) return true; - 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; - } + if (!tto->setPosition(p[0], p[1])) return false; } else { return false; } @@ -1100,34 +1107,24 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) case 3: { + Turntable *tto = Turntable::get(p[0]); + if (!tto) return false; if (p[1] == HASH_KEYWORD_ADD) { // add position value to turntable - Turntable *tto = Turntable::get(p[0]); - if (tto) { - tto->addPosition(p[2]); - StringFormatter::send(stream, F("\n")); - } else { - return false; - } + tto->addPosition(p[2]); + StringFormatter::send(stream, F("\n")); } else { // rotate to position for EX-Turntable - Turntable *tto = Turntable::get(p[0]); - if (tto) { - if (!tto->setPosition(p[0], p[1], p[2])) return false; - } else { - return false; - } + if (!tto->setPosition(p[0], p[1], p[2])) return false; } } return true; - case 5: // create an EXTT turntable + case 4: // create an EXTT turntable { if (p[1] == HASH_KEYWORD_EXTT) { 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]); - tto->addPosition(p[4]); - } 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); + tto->addPosition(p[3]); } else { return false; } diff --git a/IODevice.cpp b/IODevice.cpp index 2ed21b6..e811fff 100644 --- a/IODevice.cpp +++ b/IODevice.cpp @@ -176,6 +176,13 @@ bool IODevice::exists(VPIN vpin) { 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. bool IODevice::hasCallback(VPIN vpin) { IODevice *dev = findDevice(vpin); diff --git a/IODevice.h b/IODevice.h index d2c80a4..a03a64d 100644 --- a/IODevice.h +++ b/IODevice.h @@ -154,6 +154,9 @@ public: // exists checks whether there is a device owning the specified 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 // 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 @@ -405,9 +408,11 @@ private: void _begin() override; void _loop(unsigned long currentMicros) 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 _display() override; uint8_t _stepperStatus; + uint8_t _previousStatus; }; ///////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index 8c7057b..fc1f9c1 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -34,6 +34,8 @@ #include "IODevice.h" #include "I2CManager.h" #include "DIAG.h" +#include "Turntables.h" +#include "CommandDistributor.h" void EXTurntable::create(VPIN firstVpin, int nPins, I2CAddress I2CAddress) { new EXTurntable(firstVpin, nPins, I2CAddress); @@ -44,6 +46,8 @@ EXTurntable::EXTurntable(VPIN firstVpin, int nPins, I2CAddress I2CAddress) { _firstVpin = firstVpin; _nPins = nPins; _I2CAddress = I2CAddress; + _stepperStatus = 0; + _previousStatus = 0; addDevice(this); } @@ -80,10 +84,22 @@ int EXTurntable::_read(VPIN vpin) { if (_stepperStatus > 1) { return false; } else { + if (_stepperStatus != _previousStatus) { + _broadcastStatus(vpin, _stepperStatus); + _previousStatus = _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. // Sends 3 bytes containing the MSB and LSB of the step count, and activity. // value contains the steps, bit shifted to MSB + LSB. diff --git a/Turntables.cpp b/Turntables.cpp index a0419b1..3e33d2b 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -57,13 +57,6 @@ void Turntable::add(Turntable *tto) { 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 void Turntable::addPosition(uint16_t value) { _turntablePositions.insert(value); @@ -95,16 +88,39 @@ uint8_t Turntable::getPositionCount() { /* * 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(tto); + if (exttTto->getVpin() == vpin) { + return tto; + } + } + } + return nullptr; +} + +// Broadcast position changes bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool moving) { Turntable *tto = get(id); 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) // RMFT2::turntableEvent(id, position); #endif return true; } +// Initiate a turntable move bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { #if defined(DIAG_IO) 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) { // 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 (tto->getType() == TURNTABLE_EXTT) { + tto->_turntableData.position = position; + if (tto->isEXTT()) { tto->setPositionStateOnly(id, position, 1); } else { tto->setPositionStateOnly(id, position, 0); } - tto->_turntableData.position = position; } } return ok; @@ -132,38 +148,39 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { * *************************************************************************************/ // Private constructor -EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress) : +EXTTTurntable::EXTTTurntable(uint16_t id, VPIN vpin) : Turntable(id, TURNTABLE_EXTT) { _exttTurntableData.vpin = vpin; - _exttTurntableData.i2caddress = i2caddress; } +using DevState = IODevice::DeviceStateEnum; + // 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 Turntable *tto = get(id); if (tto) { if (tto->isType(TURNTABLE_EXTT)) { EXTTTurntable *extt = (EXTTTurntable *)tto; extt->_exttTurntableData.vpin = vpin; - extt->_exttTurntableData.i2caddress = i2caddress; 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)); return tto; #else (void)id; - (void)i2caddress; (void)vpin; return NULL; #endif } void EXTTTurntable::print(Print *stream) { - StringFormatter::send(stream, F("\n"), _turntableData.id, _exttTurntableData.vpin, _exttTurntableData.i2caddress); + StringFormatter::send(stream, F("\n"), _turntableData.id, _exttTurntableData.vpin); } // 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; } +/************************************************************************************* + * 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("\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 diff --git a/Turntables.h b/Turntables.h index d59bc80..e318724 100644 --- a/Turntables.h +++ b/Turntables.h @@ -135,6 +135,7 @@ protected: public: static Turntable *get(uint16_t id); + static Turntable *getByVpin(VPIN vpin); /* * Static data @@ -148,7 +149,7 @@ public: inline bool isHidden() { return _turntableData.hidden; } inline void setHidden(bool h) {_turntableData.hidden=h; } 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 Turntable *next() { return _nextTurntable; } void printState(Print *stream); @@ -193,16 +194,16 @@ private: // EXTTTurntableData contains device specific data struct EXTTTurntableData { VPIN vpin; - uint8_t i2caddress; } _exttTurntableData; // Constructor - EXTTTurntable(uint16_t id, VPIN vpin, uint8_t i2caddress); + EXTTTurntable(uint16_t id, VPIN vpin); public: // 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; + VPIN getVpin() const { return _exttTurntableData.vpin; } protected: // 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 From df2f09f4d2efaaf61722d1f98072e1ee13330898 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 1 Sep 2023 09:04:48 +1000 Subject: [PATCH 19/39] Fix build errors --- IODevice.h | 2 ++ IO_EXTurntable.cpp | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/IODevice.h b/IODevice.h index a03a64d..4803f56 100644 --- a/IODevice.h +++ b/IODevice.h @@ -380,6 +380,7 @@ private: uint8_t *_pinInUse; }; +#ifndef IO_NO_HAL ///////////////////////////////////////////////////////////////////////////////////////////////////// /* * IODevice subclass for EX-Turntable. @@ -414,6 +415,7 @@ private: uint8_t _stepperStatus; uint8_t _previousStatus; }; +#endif ///////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index fc1f9c1..8741c0c 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -28,8 +28,7 @@ * Refer to the documentation for further information including the valid activities. */ -#ifndef IO_EXTurntable_h -#define IO_EXTurntable_h +#ifndef IO_NO_HAL #include "IODevice.h" #include "I2CManager.h" From 798241927f1909e0fb30272f1d4170d842d7fb22 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 1 Sep 2023 13:28:24 +1000 Subject: [PATCH 20/39] Really fix build errors --- IO_EXTurntable.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index 8741c0c..bf06e62 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -28,14 +28,14 @@ * Refer to the documentation for further information including the valid activities. */ -#ifndef IO_NO_HAL - #include "IODevice.h" #include "I2CManager.h" #include "DIAG.h" #include "Turntables.h" #include "CommandDistributor.h" +#ifndef IO_NO_HAL + void EXTurntable::create(VPIN firstVpin, int nPins, I2CAddress I2CAddress) { new EXTurntable(firstVpin, nPins, I2CAddress); } From bcb250bacfc8b2e7a60810dd5b20d0f1da737863 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Fri, 1 Sep 2023 18:30:02 +1000 Subject: [PATCH 21/39] Broadcasts working --- IO_EXTurntable.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index bf06e62..59a65d9 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -71,6 +71,12 @@ void EXTurntable::_loop(unsigned long currentMicros) { uint8_t readBuffer[1]; I2CManager.read(_I2CAddress, readBuffer, 1); _stepperStatus = readBuffer[0]; + if (_stepperStatus < 2) { + if (_stepperStatus != _previousStatus) { + _broadcastStatus(_firstVpin, _stepperStatus); + _previousStatus = _stepperStatus; + } + } // DIAG(F("Turntable-EX returned status: %d"), _stepperStatus); delayUntil(currentMicros + 500000); // Wait 500ms before checking again, turntables turn slowly } @@ -83,10 +89,6 @@ int EXTurntable::_read(VPIN vpin) { if (_stepperStatus > 1) { return false; } else { - if (_stepperStatus != _previousStatus) { - _broadcastStatus(vpin, _stepperStatus); - _previousStatus = _stepperStatus; - } return _stepperStatus; } } From e734661d1b83eb0f3d79d5116e5e9404f07e4b36 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sat, 2 Sep 2023 08:29:49 +1000 Subject: [PATCH 22/39] EXRAIL ready for testing --- EXRAIL2.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++ EXRAIL2.h | 8 +++++++ EXRAIL2MacroReset.h | 28 +++++++++++++++++------- EXRAILMacros.h | 32 ++++++++++++++++++++++++++- Turntables.cpp | 12 +++++++++- Turntables.h | 1 + 6 files changed, 124 insertions(+), 10 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 0e17ea9..c01189c 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -52,6 +52,7 @@ #include "Turnouts.h" #include "CommandDistributor.h" #include "TrackManager.h" +#include "Turntables.h" // Command parsing keywords const int16_t HASH_KEYWORD_EXRAIL=15435; @@ -94,6 +95,7 @@ LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onChangeLookup=NULL; LookList * RMFT2::onClockLookup=NULL; +LookList * RMFT2::onRotateLookup=NULL; #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 @@ -175,6 +177,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onGreenLookup=LookListLoader(OPCODE_ONGREEN); onChangeLookup=LookListLoader(OPCODE_ONCHANGE); onClockLookup=LookListLoader(OPCODE_ONTIME); + onRotateLookup=LookListLoader(OPCODE_ONROTATE); // Second pass startup, define any turnouts or servos, set signals red @@ -238,6 +241,32 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { setTurnoutHiddenState(VpinTurnout::create(id,pin)); break; } + + case OPCODE_DCCTURNTABLE: { + VPIN id=operand; + setTurntableHiddenState(DCCTurntable::create(id)); + Turntable *tto=Turntable::get(id); + tto->addPosition(0); + break; + } + + case OPCODE_EXTTTURNTABLE: { + VPIN id=operand; + VPIN pin=getOperand(progCounter,1); + int home=getOperand(progCounter,2); + setTurntableHiddenState(EXTTTurntable::create(id,pin)); + Turntable *tto=Turntable::get(id); + tto->addPosition(home); + break; + } + + case OPCODE_TTADDPOSITION: { + VPIN id=operand; + int value=getOperand(progCounter,1); + Turntable *tto=Turntable::get(id); + tto->addPosition(value); + break; + } case OPCODE_AUTOSTART: // automatically create a task from here at startup. @@ -263,6 +292,10 @@ void RMFT2::setTurnoutHiddenState(Turnout * t) { t->setHidden(GETFLASH(getTurnoutDescription(t->getId()))==0x01); } +void RMFT2::setTurntableHiddenState(Turntable * tto) { + tto->setHidden(GETFLASH(getTurntableDescription(tto->getId()))==0x01); +} + char RMFT2::getRouteType(int16_t id) { for (int16_t i=0;;i+=2) { int16_t rid= GETHIGHFLASHW(routeIdList,i); @@ -598,6 +631,13 @@ void RMFT2::loop2() { case OPCODE_CLOSE: Turnout::setClosed(operand, true); break; + + case OPCODE_ROTATE: + uint8_t activity; + activity=getOperand(2); + if (!activity) activity=0; + Turntable::setPosition(operand,getOperand(1),activity); + break; case OPCODE_REV: forward = false; @@ -788,6 +828,10 @@ void RMFT2::loop2() { case OPCODE_IFCLOSED: skipIf=Turnout::isThrown(operand); break; + + case OPCODE_IFTTPOSITION: // do block if turntable at this position + skipIf=Turntable::getPosition(operand)!=(int)getOperand(1); + break; case OPCODE_ENDIF: break; @@ -986,6 +1030,10 @@ void RMFT2::loop2() { case OPCODE_ONGREEN: case OPCODE_ONCHANGE: case OPCODE_ONTIME: + case OPCODE_DCCTURNTABLE: // Turntable definition ignored at runtime + case OPCODE_EXTTTURNTABLE: // Turntable definition ignored at runtime + case OPCODE_TTADDPOSITION: // Turntable position definition ignored at runtime + case OPCODE_ONROTATE: break; @@ -1130,6 +1178,11 @@ void RMFT2::changeEvent(int16_t vpin, bool change) { if (change) handleEvent(F("CHANGE"),onChangeLookup,vpin); } +void RMFT2::rotateEvent(int16_t turntableId, bool change) { + // Hunt or an ONROTATE for this turntable + if (change) handleEvent(F("ROTATE"),onRotateLookup,turntableId); +} + void RMFT2::clockEvent(int16_t clocktime, bool change) { // Hunt for an ONTIME for this time if (Diag::CMD) diff --git a/EXRAIL2.h b/EXRAIL2.h index 4d106e6..96bc7db 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -25,6 +25,7 @@ #include "FSH.h" #include "IODevice.h" #include "Turnouts.h" +#include "Turntables.h" // The following are the operation codes (or instructions) for a kind of virtual machine. // Each instruction is normally 3 bytes long with an operation code followed by a parameter. @@ -62,6 +63,8 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_ONCHANGE, OPCODE_ONCLOCKTIME, OPCODE_ONTIME, + OPCODE_TTADDPOSITION,OPCODE_DCCTURNTABLE,OPCODE_EXTTTURNTABLE, + OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_IFTTPOSITION, // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -130,6 +133,7 @@ class LookList { static void activateEvent(int16_t addr, bool active); static void changeEvent(int16_t id, bool change); static void clockEvent(int16_t clocktime, bool change); + static void rotateEvent(int16_t id, bool change); static const int16_t SERVO_SIGNAL_FLAG=0x4000; static const int16_t ACTIVE_HIGH_SIGNAL_FLAG=0x2000; static const int16_t DCC_SIGNAL_FLAG=0x1000; @@ -144,6 +148,8 @@ class LookList { static const FSH * getTurnoutDescription(int16_t id); static const FSH * getRosterName(int16_t id); static const FSH * getRosterFunctions(int16_t id); + static const FSH * getTurntableDescription(int16_t id); + // static const FSH * getTurntablePositionDescription(int16_t id, uint8_t position); private: static void ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16_t p[]); @@ -156,6 +162,7 @@ private: static bool isSignal(int16_t id,char rag); static int16_t getSignalSlot(int16_t id); static void setTurnoutHiddenState(Turnout * t); + static void setTurntableHiddenState(Turntable * tto); static LookList* LookListLoader(OPCODE op1, OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL); static void handleEvent(const FSH* reason,LookList* handlers, int16_t id); @@ -188,6 +195,7 @@ private: static LookList * onGreenLookup; static LookList * onChangeLookup; static LookList * onClockLookup; + static LookList * onRotateLookup; // Local variables - exist for each instance/task RMFT2 *next; // loop chain diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 588a417..7c690b7 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -40,6 +40,7 @@ #undef CALL #undef CLOSE #undef DCC_SIGNAL +#undef DCC_TURNTABLE #undef DEACTIVATE #undef DEACTIVATEL #undef DELAY @@ -51,8 +52,9 @@ #undef ENDEXRAIL #undef ENDIF #undef ENDTASK -#undef ESTOP -#undef EXRAIL +#undef ESTOP +#undef EXRAIL +#undef EXTT_TURNTABLE #undef FADE #undef FOFF #undef FOLLOW @@ -75,6 +77,7 @@ #undef IFRESERVE #undef IFTHROWN #undef IFTIMEOUT +#undef IFTTPOSITION #undef IFRE #undef INVERT_DIRECTION #undef JOIN @@ -95,6 +98,7 @@ #undef ONCLOCKMINS #undef ONGREEN #undef ONRED +#undef ONROTATE #undef ONTHROW #undef ONCHANGE #undef PARSE @@ -113,7 +117,8 @@ #undef RESUME #undef RETURN #undef REV -#undef ROSTER +#undef ROSTER +#undef ROTATE #undef ROUTE #undef SENDLOCO #undef SEQUENCE @@ -136,7 +141,8 @@ #undef SPEED #undef START #undef STOP -#undef THROW +#undef THROW +#undef TT_ADDPOSITION #undef TURNOUT #undef TURNOUTL #undef UNJOIN @@ -165,6 +171,7 @@ #define CALL(route) #define CLOSE(id) #define DCC_SIGNAL(id,add,subaddr) +#define DCC_TURNTABLE(id,description) #define DEACTIVATE(addr,subaddr) #define DEACTIVATEL(addr) #define DELAY(mindelay) @@ -177,7 +184,8 @@ #define ENDIF #define ENDTASK #define ESTOP -#define EXRAIL +#define EXRAIL +#define EXTT_TURNTABLE(id,vpin,home,description) #define FADE(pin,value,ms) #define FOFF(func) #define FOLLOW(route) @@ -200,6 +208,7 @@ #define IFTHROWN(turnout_id) #define IFRESERVE(block) #define IFTIMEOUT +#define IFTTPOSITION(turntable_id,position) #define IFRE(sensor_id,value) #define INVERT_DIRECTION #define JOIN @@ -219,7 +228,8 @@ #define ONDEACTIVATEL(linear) #define ONCLOSE(turnout_id) #define ONGREEN(signal_id) -#define ONRED(signal_id) +#define ONRED(signal_id) +#define ONROTATE(turntable_id) #define ONTHROW(turnout_id) #define ONCHANGE(sensor_id) #define PAUSE @@ -238,8 +248,9 @@ #define RESUME #define RETURN #define REV(speed) -#define ROUTE(id,description) +#define ROTATE(turntable_id,position,activity) #define ROSTER(cab,name,funcmap...) +#define ROUTE(id,description) #define SENDLOCO(cab,route) #define SEQUENCE(id) #define SERIAL(msg) @@ -261,7 +272,8 @@ #define SPEED(speed) #define START(route) #define STOP -#define THROW(id) +#define THROW(id) +#define TT_ADDPOSITION(turntable_id,value,description) #define TURNOUT(id,addr,subaddr,description...) #define TURNOUTL(id,addr,description...) #define UNJOIN diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 66b0111..fc8dbca 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -187,6 +187,30 @@ const FSH * RMFT2::getTurnoutDescription(int16_t turnoutid) { return NULL; } +// Pass to get turntable descriptions (optional) +#include "EXRAIL2MacroReset.h" +#undef DCC_TURNTABLE +#define DCC_TURNTABLE(id,description...) O_DESC(id,description) +#undef EXTT_TURNTABLE +#define EXTT_TURNTABLE(id,vpin,home,description...) O_DESC(id,description) + +const FSH * RMFT2::getTurntableDescription(int16_t turntableId) { + switch (turntableId) { + #include "myAutomation.h" + default:break; + } + return NULL; +} + +// Pass to get turntable position descriptions (optional) +// #include "EXRAIL2MacroReset.h" +// #undef TT_ADDPOSITION +// #define TT_ADDPOSITION(turntable_id,value,description...) 0_DESC(id,description) + +// const FSH * RMFT2::getTurntablePositionDescription(int16_t turntableId, uint8_t positionId) { + +// } + // Pass 6: Roster IDs (count) #include "EXRAIL2MacroReset.h" #undef ROSTER @@ -268,6 +292,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define BROADCAST(msg) PRINT(msg) #define CALL(route) OPCODE_CALL,V(route), #define CLOSE(id) OPCODE_CLOSE,V(id), +#define DCC_TURNTABLE(id,description...) OPCODE_DCCTURNTABLE,V(id), #define DEACTIVATE(addr,subaddr) OPCODE_DCCACTIVATE,V(addr<<3 | subaddr<<1), #define DEACTIVATEL(addr) OPCODE_DCCACTIVATE,V((addr+3)<<1), #define DELAY(ms) ms<30000?OPCODE_DELAYMS:OPCODE_DELAY,V(ms/(ms<30000?1L:100L)), @@ -281,7 +306,8 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ENDIF OPCODE_ENDIF,0,0, #define ENDTASK OPCODE_ENDTASK,0,0, #define ESTOP OPCODE_SPEED,V(1), -#define EXRAIL +#define EXRAIL +#define EXTT_TURNTABLE(id,vpin,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(home), #define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L), #define FOFF(func) OPCODE_FOFF,V(func), #define FOLLOW(route) OPCODE_FOLLOW,V(route), @@ -304,6 +330,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define IFRESERVE(block) OPCODE_IFRESERVE,V(block), #define IFTHROWN(turnout_id) OPCODE_IFTHROWN,V(turnout_id), #define IFTIMEOUT OPCODE_IFTIMEOUT,0,0, +#define IFTTPOSITION(id,position) OPCODE_IFTTPOSITION,V(id),OPCODE_PAD,V(position), #define IFRE(sensor_id,value) OPCODE_IFRE,V(sensor_id),OPCODE_PAD,V(value), #define INVERT_DIRECTION OPCODE_INVERT_DIRECTION,0,0, #define JOIN OPCODE_JOIN,0,0, @@ -324,6 +351,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id), #define ONRED(signal_id) OPCODE_ONRED,V(signal_id), +#define ONROTATE(id) OPCODE_ONROTATE,V(id), #define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id), #define ONCHANGE(sensor_id) OPCODE_ONCHANGE,V(sensor_id), #define PAUSE OPCODE_PAUSE,0,0, @@ -343,6 +371,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define RETURN OPCODE_RETURN,0,0, #define REV(speed) OPCODE_REV,V(speed), #define ROSTER(cabid,name,funcmap...) +#define ROTATE(id,position,activity) OPCODE_ROTATE,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(activity), #define ROUTE(id, description) OPCODE_ROUTE, V(id), #define SENDLOCO(cab,route) OPCODE_SENDLOCO,V(cab),OPCODE_PAD,V(route), #define SEQUENCE(id) OPCODE_SEQUENCE, V(id), @@ -366,6 +395,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define START(route) OPCODE_START,V(route), #define STOP OPCODE_SPEED,V(0), #define THROW(id) OPCODE_THROW,V(id), +#define TT_ADDPOSITION(id,value,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(value), #define TURNOUT(id,addr,subaddr,description...) OPCODE_TURNOUT,V(id),OPCODE_PAD,V(addr),OPCODE_PAD,V(subaddr), #define TURNOUTL(id,addr,description...) TURNOUT(id,(addr-1)/4+1,(addr-1)%4, description) #define UNJOIN OPCODE_UNJOIN,0,0, diff --git a/Turntables.cpp b/Turntables.cpp index 3e33d2b..dcf50a0 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -108,6 +108,13 @@ Turntable *Turntable::getByVpin(VPIN vpin) { return nullptr; } +// Get the current position for turntable with the specified ID +uint8_t Turntable::getPosition(uint16_t id) { + Turntable *tto = get(id); + if (!tto) return false; + return tto->getPosition(); +} + // Broadcast position changes bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool moving) { Turntable *tto = get(id); @@ -234,7 +241,10 @@ DCCTurntable::DCCTurntable(uint16_t id) : Turntable(id, TURNTABLE_DCC) {} 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 + int16_t addr=value>>3; + int16_t subaddr=(value>>1) & 0x03; + bool active=value & 0x01; + DCC::setAccessory(addr, subaddr, active); #else (void)position; #endif diff --git a/Turntables.h b/Turntables.h index e318724..b95c9c0 100644 --- a/Turntables.h +++ b/Turntables.h @@ -172,6 +172,7 @@ public: inline static bool exists(uint16_t id) { return get(id) != 0; } static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); static bool setPositionStateOnly(uint16_t id, uint8_t position, bool moving); + static uint8_t getPosition(uint16_t id); inline static Turntable *first() { return _firstTurntable; } static bool printAll(Print *stream) { bool gotOne = false; From 004d10ee586a5efb5eb6ae7c2704b75e4fe8b100 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sat, 2 Sep 2023 18:45:59 +1000 Subject: [PATCH 23/39] Fix build errors --- EXRAIL2.cpp | 14 +++++++++++--- EXRAIL2.h | 2 ++ EXRAILMacros.h | 12 ++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index c01189c..77a9f88 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -242,6 +242,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { break; } +#ifndef IO_NO_HAL case OPCODE_DCCTURNTABLE: { VPIN id=operand; setTurntableHiddenState(DCCTurntable::create(id)); @@ -267,7 +268,8 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { tto->addPosition(value); break; } - +#endif + case OPCODE_AUTOSTART: // automatically create a task from here at startup. // Removed if (progCounter>0) check 4.2.31 because @@ -292,9 +294,11 @@ void RMFT2::setTurnoutHiddenState(Turnout * t) { t->setHidden(GETFLASH(getTurnoutDescription(t->getId()))==0x01); } +#ifndef IO_NO_HAL void RMFT2::setTurntableHiddenState(Turntable * tto) { tto->setHidden(GETFLASH(getTurntableDescription(tto->getId()))==0x01); } +#endif char RMFT2::getRouteType(int16_t id) { for (int16_t i=0;;i+=2) { @@ -631,13 +635,15 @@ void RMFT2::loop2() { case OPCODE_CLOSE: Turnout::setClosed(operand, true); break; - + +#ifndef IO_NO_HAL case OPCODE_ROTATE: uint8_t activity; activity=getOperand(2); if (!activity) activity=0; Turntable::setPosition(operand,getOperand(1),activity); break; +#endif case OPCODE_REV: forward = false; @@ -829,10 +835,12 @@ void RMFT2::loop2() { skipIf=Turnout::isThrown(operand); break; +#ifndef IO_NO_HAL case OPCODE_IFTTPOSITION: // do block if turntable at this position skipIf=Turntable::getPosition(operand)!=(int)getOperand(1); break; - +#endif + case OPCODE_ENDIF: break; diff --git a/EXRAIL2.h b/EXRAIL2.h index 96bc7db..16fff82 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -162,7 +162,9 @@ private: static bool isSignal(int16_t id,char rag); static int16_t getSignalSlot(int16_t id); static void setTurnoutHiddenState(Turnout * t); + #ifndef IO_NO_HAL static void setTurntableHiddenState(Turntable * tto); + #endif static LookList* LookListLoader(OPCODE op1, OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL); static void handleEvent(const FSH* reason,LookList* handlers, int16_t id); diff --git a/EXRAILMacros.h b/EXRAILMacros.h index fc8dbca..f5d905e 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -292,7 +292,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define BROADCAST(msg) PRINT(msg) #define CALL(route) OPCODE_CALL,V(route), #define CLOSE(id) OPCODE_CLOSE,V(id), +#ifndef IO_NO_HAL #define DCC_TURNTABLE(id,description...) OPCODE_DCCTURNTABLE,V(id), +#endif #define DEACTIVATE(addr,subaddr) OPCODE_DCCACTIVATE,V(addr<<3 | subaddr<<1), #define DEACTIVATEL(addr) OPCODE_DCCACTIVATE,V((addr+3)<<1), #define DELAY(ms) ms<30000?OPCODE_DELAYMS:OPCODE_DELAY,V(ms/(ms<30000?1L:100L)), @@ -307,7 +309,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ENDTASK OPCODE_ENDTASK,0,0, #define ESTOP OPCODE_SPEED,V(1), #define EXRAIL +#ifndef IO_NO_HAL #define EXTT_TURNTABLE(id,vpin,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(home), +#endif #define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L), #define FOFF(func) OPCODE_FOFF,V(func), #define FOLLOW(route) OPCODE_FOLLOW,V(route), @@ -330,7 +334,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define IFRESERVE(block) OPCODE_IFRESERVE,V(block), #define IFTHROWN(turnout_id) OPCODE_IFTHROWN,V(turnout_id), #define IFTIMEOUT OPCODE_IFTIMEOUT,0,0, +#ifndef IO_NO_HAL #define IFTTPOSITION(id,position) OPCODE_IFTTPOSITION,V(id),OPCODE_PAD,V(position), +#endif #define IFRE(sensor_id,value) OPCODE_IFRE,V(sensor_id),OPCODE_PAD,V(value), #define INVERT_DIRECTION OPCODE_INVERT_DIRECTION,0,0, #define JOIN OPCODE_JOIN,0,0, @@ -351,7 +357,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ONDEACTIVATEL(linear) OPCODE_ONDEACTIVATE,V(linear+3), #define ONGREEN(signal_id) OPCODE_ONGREEN,V(signal_id), #define ONRED(signal_id) OPCODE_ONRED,V(signal_id), +#ifndef IO_NO_HAL #define ONROTATE(id) OPCODE_ONROTATE,V(id), +#endif #define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id), #define ONCHANGE(sensor_id) OPCODE_ONCHANGE,V(sensor_id), #define PAUSE OPCODE_PAUSE,0,0, @@ -371,7 +379,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define RETURN OPCODE_RETURN,0,0, #define REV(speed) OPCODE_REV,V(speed), #define ROSTER(cabid,name,funcmap...) +#ifndef IO_NO_HAL #define ROTATE(id,position,activity) OPCODE_ROTATE,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(activity), +#endif #define ROUTE(id, description) OPCODE_ROUTE, V(id), #define SENDLOCO(cab,route) OPCODE_SENDLOCO,V(cab),OPCODE_PAD,V(route), #define SEQUENCE(id) OPCODE_SEQUENCE, V(id), @@ -395,7 +405,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define START(route) OPCODE_START,V(route), #define STOP OPCODE_SPEED,V(0), #define THROW(id) OPCODE_THROW,V(id), +#ifndef IO_NO_HAL #define TT_ADDPOSITION(id,value,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(value), +#endif #define TURNOUT(id,addr,subaddr,description...) OPCODE_TURNOUT,V(id),OPCODE_PAD,V(addr),OPCODE_PAD,V(subaddr), #define TURNOUTL(id,addr,description...) TURNOUT(id,(addr-1)/4+1,(addr-1)%4, description) #define UNJOIN OPCODE_UNJOIN,0,0, From 1e48c59cd8d4b0a16370731078e60e8abb949999 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 3 Sep 2023 18:54:56 +1000 Subject: [PATCH 24/39] Capture progress --- IO_EXTurntable.cpp | 12 +++++------- Turntables.cpp | 5 ++++- Turntables.h | 3 +++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index 59a65d9..eba8321 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -71,14 +71,11 @@ void EXTurntable::_loop(unsigned long currentMicros) { uint8_t readBuffer[1]; I2CManager.read(_I2CAddress, readBuffer, 1); _stepperStatus = readBuffer[0]; - if (_stepperStatus < 2) { - if (_stepperStatus != _previousStatus) { - _broadcastStatus(_firstVpin, _stepperStatus); - _previousStatus = _stepperStatus; - } + if (_stepperStatus != _previousStatus && _stepperStatus == 0) { // Broadcast when a rotation finishes + _broadcastStatus(_firstVpin, _stepperStatus); + _previousStatus = _stepperStatus; } - // DIAG(F("Turntable-EX returned status: %d"), _stepperStatus); - delayUntil(currentMicros + 500000); // Wait 500ms before checking again, turntables turn slowly + delayUntil(currentMicros + 100000); // Wait 100ms before checking again } // Read returns status as obtained in our loop. @@ -128,6 +125,7 @@ void EXTurntable::_writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_ _I2CAddress.toString(), stepsMSB, stepsLSB, activity); #endif _stepperStatus = 1; // Tell the device driver Turntable-EX is busy + _broadcastStatus(vpin, _stepperStatus); // Broadcast when the rotation starts I2CManager.write(_I2CAddress, 3, stepsMSB, stepsLSB, activity); } diff --git a/Turntables.cpp b/Turntables.cpp index dcf50a0..f7b2a46 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -122,7 +122,9 @@ bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool 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) - // RMFT2::turntableEvent(id, position); + bool rotated = false; + if (position != tto->_previousPosition) rotated = true; + if (!tto->isEXTT()) { RMFT2::rotateEvent(id, rotated); } #endif return true; } @@ -138,6 +140,7 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { if (ok) { // Broadcast a position change only if non zero has been set, or home/calibration sent + tto->_previousPosition = tto->getPosition(); if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) { tto->_turntableData.position = position; if (tto->isEXTT()) { diff --git a/Turntables.h b/Turntables.h index b95c9c0..67ab0e3 100644 --- a/Turntables.h +++ b/Turntables.h @@ -105,6 +105,9 @@ protected: // Linked list for positions TurntablePositionList _turntablePositions; + + // Store the previous position to allow checking for changes + uint8_t _previousPosition = 0; /* * Constructor From dd890e65bfe2b307ff19c501ac3b87c69f0b8256 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 4 Sep 2023 07:38:26 +1000 Subject: [PATCH 25/39] Add move check --- IO_EXTurntable.cpp | 1 + Turntables.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index eba8321..dcbe018 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -95,6 +95,7 @@ void EXTurntable::_broadcastStatus (VPIN vpin, uint8_t status) { Turntable *tto = Turntable::getByVpin(vpin); if (tto) { CommandDistributor::broadcastTurntable(tto->getId(), tto->getPosition(), status); + tto->setMoving(status); } } diff --git a/Turntables.h b/Turntables.h index 67ab0e3..30cba82 100644 --- a/Turntables.h +++ b/Turntables.h @@ -109,6 +109,9 @@ protected: // Store the previous position to allow checking for changes uint8_t _previousPosition = 0; + // Store the current state of the turntable + bool _isMoving = false; + /* * Constructor */ @@ -159,6 +162,8 @@ public: void addPosition(uint16_t value); uint16_t getPositionValue(uint8_t position); uint8_t getPositionCount(); + bool isMoving() { return _isMoving; } + void setMoving(bool moving) { _isMoving=moving; } /* * Virtual functions From 86f45675565ab4df0d4beddd0d07e52b06c340b1 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 4 Sep 2023 18:46:28 +1000 Subject: [PATCH 26/39] Revisiting logic --- DCCEXParser.cpp | 9 +++++---- Turntables.cpp | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 7473c26..2014762 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1087,7 +1087,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) } return true; - case 2: // - rotate to position for DCC turntables + case 2: // | - rotate or create DCC turntable { Turntable *tto = Turntable::get(p[0]); if (p[1] == HASH_KEYWORD_DCC) { // Create a DCC turntable @@ -1096,7 +1096,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) Turntable *tto = Turntable::get(p[0]); tto->addPosition(0); } else { // Otherwise move a DCC turntable - if (tto) { + if (tto && !tto->isEXTT()) { if (!tto->setPosition(p[0], p[1])) return false; } else { return false; @@ -1105,14 +1105,15 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) } return true; - case 3: + case 3: // | { Turntable *tto = Turntable::get(p[0]); if (!tto) return false; - if (p[1] == HASH_KEYWORD_ADD) { // add position value to turntable + if (p[1] == HASH_KEYWORD_ADD) { // Add position value to turntable tto->addPosition(p[2]); StringFormatter::send(stream, F("\n")); } else { // rotate to position for EX-Turntable + if (!tto->isEXTT()) return false; if (!tto->setPosition(p[0], p[1], p[2])) return false; } } diff --git a/Turntables.cpp b/Turntables.cpp index f7b2a46..f96a3a8 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -140,8 +140,8 @@ bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { if (ok) { // Broadcast a position change only if non zero has been set, or home/calibration sent - tto->_previousPosition = tto->getPosition(); if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) { + tto->_previousPosition = tto->getPosition(); tto->_turntableData.position = position; if (tto->isEXTT()) { tto->setPositionStateOnly(id, position, 1); @@ -179,6 +179,7 @@ using DevState = IODevice::DeviceStateEnum; } if (!IODevice::exists(vpin)) return nullptr; if (IODevice::getStatus(vpin) == DevState::DEVSTATE_FAILED) return nullptr; + if (Turntable::getByVpin(vpin)) return nullptr; tto = (Turntable *)new EXTTTurntable(id, vpin); DIAG(F("Turntable 0x%x size %d size %d"), tto, sizeof(Turntable), sizeof(struct TurntableData)); return tto; From 3094c52bf8509d600fa829995d8cf7be263b6365 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 5 Sep 2023 08:38:37 +1000 Subject: [PATCH 27/39] Ready to test --- IO_EXTurntable.cpp | 2 +- Turntables.cpp | 39 +++++++++++++++------------------------ Turntables.h | 1 - 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index dcbe018..b36237f 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -94,8 +94,8 @@ int EXTurntable::_read(VPIN vpin) { void EXTurntable::_broadcastStatus (VPIN vpin, uint8_t status) { Turntable *tto = Turntable::getByVpin(vpin); if (tto) { - CommandDistributor::broadcastTurntable(tto->getId(), tto->getPosition(), status); tto->setMoving(status); + CommandDistributor::broadcastTurntable(tto->getId(), tto->getPosition(), status); } } diff --git a/Turntables.cpp b/Turntables.cpp index f96a3a8..120ac2f 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -115,40 +115,27 @@ uint8_t Turntable::getPosition(uint16_t id) { return tto->getPosition(); } -// Broadcast position changes -bool Turntable::setPositionStateOnly(uint16_t id, uint8_t position, bool moving) { - Turntable *tto = get(id); - if (!tto) return false; - // 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) - bool rotated = false; - if (position != tto->_previousPosition) rotated = true; - if (!tto->isEXTT()) { RMFT2::rotateEvent(id, rotated); } -#endif - return true; -} - // Initiate a turntable move bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { #if defined(DIAG_IO) - DIAG(F("Turntable(%d, %d)"), id, position); + DIAG(F("Rotate turntable %d to position %d, activity %d)"), id, position, activity); #endif Turntable *tto = Turntable::get(id); if (!tto) return false; + if (tto->isMoving()) return false; bool ok = tto->setPositionInternal(position, activity); if (ok) { - // Broadcast a position change only if non zero has been set, or home/calibration sent - if (position > 0 || (position == 0 && (activity == 2 || activity == 3))) { - tto->_previousPosition = tto->getPosition(); - tto->_turntableData.position = position; - if (tto->isEXTT()) { - tto->setPositionStateOnly(id, position, 1); - } else { - tto->setPositionStateOnly(id, position, 0); - } + // We only deal with broadcasts for DCC turntables here, EXTT in the device driver + if (!tto->isEXTT()) { + CommandDistributor::broadcastTurntable(id, position, false); } + // Trigger EXRAIL rotateEvent for both types here if changed +#if defined(EXRAIL_ACTIVE) + bool rotated = false; + if (position != tto->_previousPosition) rotated = true; + RMFT2::rotateEvent(id, rotated); +#endif } return ok; } @@ -206,6 +193,8 @@ using DevState = IODevice::DeviceStateEnum; } if (position > 0 && !value) return false; // Return false if it's not a valid position // Set position via device driver + _previousPosition = _turntableData.position; + _turntableData.position = position; EXTurntable::writeAnalogue(_exttTurntableData.vpin, value, activity); #else (void)position; @@ -248,6 +237,8 @@ DCCTurntable::DCCTurntable(uint16_t id) : Turntable(id, TURNTABLE_DCC) {} int16_t addr=value>>3; int16_t subaddr=(value>>1) & 0x03; bool active=value & 0x01; + _previousPosition = _turntableData.position; + _turntableData.position = position; DCC::setAccessory(addr, subaddr, active); #else (void)position; diff --git a/Turntables.h b/Turntables.h index 30cba82..de0151c 100644 --- a/Turntables.h +++ b/Turntables.h @@ -179,7 +179,6 @@ public: */ inline static bool exists(uint16_t id) { return get(id) != 0; } static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); - static bool setPositionStateOnly(uint16_t id, uint8_t position, bool moving); static uint8_t getPosition(uint16_t id); inline static Turntable *first() { return _firstTurntable; } static bool printAll(Print *stream) { From 152f9850bbd0bd8c1ff7f5cfe4a8c5a8ecad8b90 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Tue, 5 Sep 2023 19:05:18 +1000 Subject: [PATCH 28/39] Working --- IO_EXTurntable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IO_EXTurntable.cpp b/IO_EXTurntable.cpp index b36237f..af220a3 100644 --- a/IO_EXTurntable.cpp +++ b/IO_EXTurntable.cpp @@ -82,7 +82,6 @@ void EXTurntable::_loop(unsigned long currentMicros) { // Return false if our status value is invalid. int EXTurntable::_read(VPIN vpin) { if (_deviceState == DEVSTATE_FAILED) return 0; - // DIAG(F("_read status: %d"), _stepperStatus); if (_stepperStatus > 1) { return false; } else { @@ -126,6 +125,7 @@ void EXTurntable::_writeAnalogue(VPIN vpin, int value, uint8_t activity, uint16_ _I2CAddress.toString(), stepsMSB, stepsLSB, activity); #endif _stepperStatus = 1; // Tell the device driver Turntable-EX is busy + _previousStatus = _stepperStatus; _broadcastStatus(vpin, _stepperStatus); // Broadcast when the rotation starts I2CManager.write(_I2CAddress, 3, stepsMSB, stepsLSB, activity); } From 6adff43f4b0f5b7231ca61e555318232c1fd98f5 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 6 Sep 2023 07:59:43 +1000 Subject: [PATCH 29/39] Update add position --- DCCEXParser.cpp | 24 ++++++++++++------------ EXRAIL2.cpp | 9 +++++---- EXRAIL2MacroReset.h | 2 +- EXRAILMacros.h | 2 +- Turntables.cpp | 4 ++-- Turntables.h | 9 ++++----- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 2014762..de1618c 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1094,7 +1094,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) if (tto) return false; if (!DCCTurntable::create(p[0])) return false; Turntable *tto = Turntable::get(p[0]); - tto->addPosition(0); + tto->addPosition(0, 0); } else { // Otherwise move a DCC turntable if (tto && !tto->isEXTT()) { if (!tto->setPosition(p[0], p[1])) return false; @@ -1105,27 +1105,27 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) } return true; - case 3: // | + case 3: // rotate to position for EX-Turntable { Turntable *tto = Turntable::get(p[0]); if (!tto) return false; - if (p[1] == HASH_KEYWORD_ADD) { // Add position value to turntable - tto->addPosition(p[2]); - StringFormatter::send(stream, F("\n")); - } else { // rotate to position for EX-Turntable - if (!tto->isEXTT()) return false; - if (!tto->setPosition(p[0], p[1], p[2])) return false; - } + if (!tto->isEXTT()) return false; + if (!tto->setPosition(p[0], p[1], p[2])) return false; } return true; - case 4: // create an EXTT turntable + case 4: // | create an EXTT turntable or add position { + Turntable *tto = Turntable::get(p[0]); if (p[1] == HASH_KEYWORD_EXTT) { - if (Turntable::get(p[0])) return false; + if (tto) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2])) return false; Turntable *tto = Turntable::get(p[0]); - tto->addPosition(p[3]); + tto->addPosition(0, p[3]); + } else if (p[1] == HASH_KEYWORD_ADD) { + if (!tto) return false; + tto->addPosition(p[2], p[3]); + StringFormatter::send(stream, F("\n")); } else { return false; } diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 77a9f88..d88a6f4 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -247,7 +247,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { VPIN id=operand; setTurntableHiddenState(DCCTurntable::create(id)); Turntable *tto=Turntable::get(id); - tto->addPosition(0); + tto->addPosition(0,0); break; } @@ -257,15 +257,16 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { int home=getOperand(progCounter,2); setTurntableHiddenState(EXTTTurntable::create(id,pin)); Turntable *tto=Turntable::get(id); - tto->addPosition(home); + tto->addPosition(0,home); break; } case OPCODE_TTADDPOSITION: { VPIN id=operand; - int value=getOperand(progCounter,1); + int position=getOperand(progCounter,1); + int value=getOperand(progCounter,2); Turntable *tto=Turntable::get(id); - tto->addPosition(value); + tto->addPosition(position,value); break; } #endif diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 7c690b7..21d4f18 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -273,7 +273,7 @@ #define START(route) #define STOP #define THROW(id) -#define TT_ADDPOSITION(turntable_id,value,description) +#define TT_ADDPOSITION(turntable_id,position,value,description) #define TURNOUT(id,addr,subaddr,description...) #define TURNOUTL(id,addr,description...) #define UNJOIN diff --git a/EXRAILMacros.h b/EXRAILMacros.h index f5d905e..68f3bf0 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -406,7 +406,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define STOP OPCODE_SPEED,V(0), #define THROW(id) OPCODE_THROW,V(id), #ifndef IO_NO_HAL -#define TT_ADDPOSITION(id,value,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(value), +#define TT_ADDPOSITION(id,position,value,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(value), #endif #define TURNOUT(id,addr,subaddr,description...) OPCODE_TURNOUT,V(id),OPCODE_PAD,V(addr),OPCODE_PAD,V(subaddr), #define TURNOUTL(id,addr,description...) TURNOUT(id,(addr-1)/4+1,(addr-1)%4, description) diff --git a/Turntables.cpp b/Turntables.cpp index 120ac2f..abbac81 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -58,8 +58,8 @@ void Turntable::add(Turntable *tto) { } // Add a position -void Turntable::addPosition(uint16_t value) { - _turntablePositions.insert(value); +void Turntable::addPosition(uint8_t idx, uint16_t value) { + _turntablePositions.insert(idx, value); } // Get value for position diff --git a/Turntables.h b/Turntables.h index de0151c..15333c9 100644 --- a/Turntables.h +++ b/Turntables.h @@ -53,10 +53,10 @@ struct TurntablePosition { class TurntablePositionList { public: - TurntablePositionList() : head(nullptr), currentIndex(0) {} + TurntablePositionList() : head(nullptr) {} - void insert(uint16_t value) { - TurntablePosition* newPosition = new TurntablePosition(currentIndex++, value); + void insert(uint8_t idx, uint16_t value) { + TurntablePosition* newPosition = new TurntablePosition(idx, value); if(!head) { head = newPosition; } else { @@ -71,7 +71,6 @@ public: private: TurntablePosition* head; - uint8_t currentIndex; }; @@ -159,7 +158,7 @@ public: inline uint16_t getId() { return _turntableData.id; } inline Turntable *next() { return _nextTurntable; } void printState(Print *stream); - void addPosition(uint16_t value); + void addPosition(uint8_t idx, uint16_t value); uint16_t getPositionValue(uint8_t position); uint8_t getPositionCount(); bool isMoving() { return _isMoving; } From 1f5f7754c1a4b5c928fadf10046715cd4099aea5 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:16:46 +1000 Subject: [PATCH 30/39] Start on position description --- DCCEXParser.cpp | 5 +++-- EXRAIL2.h | 2 +- EXRAILMacros.h | 8 ++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index de1618c..404685d 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -712,10 +712,11 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) uint8_t posCount = tto->getPositionCount(); const FSH *todesc = NULL; #ifdef EXRAIL_ACTIVE - // todesc = RMFT2::getTurntableDescription(id); + todesc = RMFT2::getTurntableDescription(id); #endif if (todesc == NULL) todesc = F(""); - StringFormatter::send(stream, F(" %d %d %d"), id, type, pos); + StringFormatter::send(stream, F(" %d %d %d"), id, type, pos, todesc); + for (uint8_t p = 0; p < posCount; p++) { int16_t value = tto->getPositionValue(p); StringFormatter::send(stream, F(" %d"), value); diff --git a/EXRAIL2.h b/EXRAIL2.h index 16fff82..f6c4807 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -149,7 +149,7 @@ class LookList { static const FSH * getRosterName(int16_t id); static const FSH * getRosterFunctions(int16_t id); static const FSH * getTurntableDescription(int16_t id); - // static const FSH * getTurntablePositionDescription(int16_t id, uint8_t position); + static const FSH * getTurntablePositionDescription(int16_t turntableId, uint8_t positionId); private: static void ComandFilter(Print * stream, byte & opcode, byte & paramCount, int16_t p[]); diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 68f3bf0..c413989 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -205,10 +205,14 @@ const FSH * RMFT2::getTurntableDescription(int16_t turntableId) { // Pass to get turntable position descriptions (optional) // #include "EXRAIL2MacroReset.h" // #undef TT_ADDPOSITION -// #define TT_ADDPOSITION(turntable_id,value,description...) 0_DESC(id,description) +// #define TT_ADDPOSITION(turntable_id,value,description...) O_DESC(turntable_id,description) // const FSH * RMFT2::getTurntablePositionDescription(int16_t turntableId, uint8_t positionId) { - +// switch (turntableId) { +// #include "myAutomation.h" +// default:break; +// } +// return NULL; // } // Pass 6: Roster IDs (count) From 21ce87eb3e72a7d8925ea5fec407222ffbd2ce6c Mon Sep 17 00:00:00 2001 From: peteGSX Date: Thu, 7 Sep 2023 05:33:26 +1000 Subject: [PATCH 31/39] Descriptions available --- DCCEXParser.cpp | 13 ++++++++++--- EXRAILMacros.h | 19 +++++++++---------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 404685d..405512c 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -702,6 +702,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) if (tto->isHidden()) continue; StringFormatter::send(stream, F(" %d"),tto->getId()); } + StringFormatter::send(stream, F(">\n")); } else { // Turntable *tto=Turntable::get(id); if (!tto || tto->isHidden()) { @@ -711,19 +712,25 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) uint8_t type = tto->isEXTT(); uint8_t posCount = tto->getPositionCount(); const FSH *todesc = NULL; + const FSH *tpdesc = NULL; #ifdef EXRAIL_ACTIVE todesc = RMFT2::getTurntableDescription(id); #endif if (todesc == NULL) todesc = F(""); - StringFormatter::send(stream, F(" %d %d %d"), id, type, pos, todesc); + StringFormatter::send(stream, F(" %d %d %d %d \"%S\">\n"), id, type, pos, posCount, todesc); for (uint8_t p = 0; p < posCount; p++) { + StringFormatter::send(stream, F("jO>")); int16_t value = tto->getPositionValue(p); - StringFormatter::send(stream, F(" %d"), value); +#ifdef EXRAIL_ACTIVE + tpdesc = RMFT2::getTurntablePositionDescription(id, p); +#endif + if (tpdesc == NULL) todesc = F(""); + StringFormatter::send(stream, F(" %d \"%S\""), value, tpdesc); + StringFormatter::send(stream, F(">\n")); } } } - StringFormatter::send(stream, F(">\n")); return; #endif default: break; diff --git a/EXRAILMacros.h b/EXRAILMacros.h index c413989..97604c5 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -54,6 +54,8 @@ // helper macro for turnout descriptions, creates NULL for missing description #define O_DESC(id, desc) case id: return ("" desc)[0]?F("" desc):NULL; +// helper macro for turntable descriptions, creates NULL for missing description +#define T_DESC(tid,pid,desc) if(turntableId==tid && positionId==pid) return ("" desc)[0]?F("" desc):NULL; // helper macro for turnout description as HIDDEN #define HIDDEN "\x01" @@ -203,17 +205,14 @@ const FSH * RMFT2::getTurntableDescription(int16_t turntableId) { } // Pass to get turntable position descriptions (optional) -// #include "EXRAIL2MacroReset.h" -// #undef TT_ADDPOSITION -// #define TT_ADDPOSITION(turntable_id,value,description...) O_DESC(turntable_id,description) +#include "EXRAIL2MacroReset.h" +#undef TT_ADDPOSITION +#define TT_ADDPOSITION(turntable_id,position,value,description...) T_DESC(turntable_id,position,description) -// const FSH * RMFT2::getTurntablePositionDescription(int16_t turntableId, uint8_t positionId) { -// switch (turntableId) { -// #include "myAutomation.h" -// default:break; -// } -// return NULL; -// } +const FSH * RMFT2::getTurntablePositionDescription(int16_t turntableId, uint8_t positionId) { + #include "myAutomation.h" + return NULL; +} // Pass 6: Roster IDs (count) #include "EXRAIL2MacroReset.h" From 004d7b66317f34a43006e4319cdbc7bf3a0f066d Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 7 Sep 2023 07:32:54 +1000 Subject: [PATCH 32/39] JO and JP working --- DCCEXParser.cpp | 24 ++++++++++++++++++------ platformio.ini | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 405512c..94b711e 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -86,6 +86,7 @@ const int16_t HASH_KEYWORD_C='C'; const int16_t HASH_KEYWORD_G='G'; const int16_t HASH_KEYWORD_I='I'; const int16_t HASH_KEYWORD_O='O'; +const int16_t HASH_KEYWORD_P='P'; const int16_t HASH_KEYWORD_R='R'; const int16_t HASH_KEYWORD_T='T'; const int16_t HASH_KEYWORD_X='X'; @@ -706,30 +707,41 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) } else { // Turntable *tto=Turntable::get(id); if (!tto || tto->isHidden()) { - StringFormatter::send(stream, F(" %d X"), id); + StringFormatter::send(stream, F(" %d X>\n"), id); } else { uint8_t pos = tto->getPosition(); uint8_t type = tto->isEXTT(); uint8_t posCount = tto->getPositionCount(); const FSH *todesc = NULL; - const FSH *tpdesc = NULL; #ifdef EXRAIL_ACTIVE todesc = RMFT2::getTurntableDescription(id); #endif if (todesc == NULL) todesc = F(""); StringFormatter::send(stream, F(" %d %d %d %d \"%S\">\n"), id, type, pos, posCount, todesc); - + } + } + return; + case HASH_KEYWORD_P: // returns turntable position list for the turntable id + if (params==2) { // + Turntable *tto=Turntable::get(id); + if (!tto || tto->isHidden()) { + StringFormatter::send(stream, F(" %d X>\n"), id); + } else { + uint8_t posCount = tto->getPositionCount(); + const FSH *tpdesc = NULL; for (uint8_t p = 0; p < posCount; p++) { - StringFormatter::send(stream, F("jO>")); + StringFormatter::send(stream, F("getPositionValue(p); #ifdef EXRAIL_ACTIVE tpdesc = RMFT2::getTurntablePositionDescription(id, p); #endif - if (tpdesc == NULL) todesc = F(""); - StringFormatter::send(stream, F(" %d \"%S\""), value, tpdesc); + if (tpdesc == NULL) tpdesc = F(""); + StringFormatter::send(stream, F(" %d %d %d \"%S\""), id, p, value, tpdesc); StringFormatter::send(stream, F(">\n")); } } + } else { + StringFormatter::send(stream, F("\n")); } return; #endif diff --git a/platformio.ini b/platformio.ini index 1a87770..ac2d598 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,7 +30,7 @@ include_dir = . [env] build_flags = -Wall -Wextra -monitor_filters = time +; monitor_filters = time ; lib_deps = adafruit/Adafruit ST7735 and ST7789 Library @ ^1.10.0 [env:samd21-dev-usb] From bd02d1c15bf4cc35848d07b15c5630dcc352ebd8 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 7 Sep 2023 07:58:19 +1000 Subject: [PATCH 33/39] WAITFORTT ready for testing --- EXRAIL2.cpp | 20 ++++++++++++++++++-- EXRAIL2.h | 6 +++++- EXRAIL2MacroReset.h | 6 ++++++ EXRAILMacros.h | 3 +++ Turntables.cpp | 6 ++++++ Turntables.h | 1 + 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index d88a6f4..2d379a7 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -95,7 +95,9 @@ LookList * RMFT2::onAmberLookup=NULL; LookList * RMFT2::onGreenLookup=NULL; LookList * RMFT2::onChangeLookup=NULL; LookList * RMFT2::onClockLookup=NULL; +#ifndef IO_NO_HAL LookList * RMFT2::onRotateLookup=NULL; +#endif #define GET_OPCODE GETHIGHFLASH(RMFT2::RouteCode,progCounter) #define SKIPOP progCounter+=3 @@ -177,8 +179,9 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { onGreenLookup=LookListLoader(OPCODE_ONGREEN); onChangeLookup=LookListLoader(OPCODE_ONCHANGE); onClockLookup=LookListLoader(OPCODE_ONTIME); +#ifndef IO_NO_HAL onRotateLookup=LookListLoader(OPCODE_ONROTATE); - +#endif // Second pass startup, define any turnouts or servos, set signals red // add sequences onRoutines to the lookups @@ -1014,7 +1017,16 @@ void RMFT2::loop2() { return; } break; - + +#ifndef IO_NO_HAL + case OPCODE_WAITFORTT: // OPCODE_WAITFOR,V(turntable_id) + if (Turntable::ttMoving(operand)) { + delayMe(100); + return; + } + break; +#endif + case OPCODE_PRINT: printMessage(operand); break; @@ -1039,10 +1051,12 @@ void RMFT2::loop2() { case OPCODE_ONGREEN: case OPCODE_ONCHANGE: case OPCODE_ONTIME: +#ifndef IO_NO_HAL case OPCODE_DCCTURNTABLE: // Turntable definition ignored at runtime case OPCODE_EXTTTURNTABLE: // Turntable definition ignored at runtime case OPCODE_TTADDPOSITION: // Turntable position definition ignored at runtime case OPCODE_ONROTATE: +#endif break; @@ -1187,10 +1201,12 @@ void RMFT2::changeEvent(int16_t vpin, bool change) { if (change) handleEvent(F("CHANGE"),onChangeLookup,vpin); } +#ifndef IO_NO_HAL void RMFT2::rotateEvent(int16_t turntableId, bool change) { // Hunt or an ONROTATE for this turntable if (change) handleEvent(F("ROTATE"),onRotateLookup,turntableId); } +#endif void RMFT2::clockEvent(int16_t clocktime, bool change) { // Hunt for an ONTIME for this time diff --git a/EXRAIL2.h b/EXRAIL2.h index f6c4807..5247e3e 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -63,8 +63,10 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_ONCHANGE, OPCODE_ONCLOCKTIME, OPCODE_ONTIME, +#ifndef IO_NO_HAL OPCODE_TTADDPOSITION,OPCODE_DCCTURNTABLE,OPCODE_EXTTTURNTABLE, - OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_IFTTPOSITION, + OPCODE_ONROTATE,OPCODE_ROTATE,OPCODE_IFTTPOSITION,OPCODE_WAITFORTT, +#endif // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group @@ -197,7 +199,9 @@ private: static LookList * onGreenLookup; static LookList * onChangeLookup; static LookList * onClockLookup; +#ifndef IO_NO_HAL static LookList * onRotateLookup; +#endif // Local variables - exist for each instance/task RMFT2 *next; // loop chain diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 21d4f18..efe91a5 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -150,6 +150,9 @@ #undef VIRTUAL_SIGNAL #undef VIRTUAL_TURNOUT #undef WAITFOR +#ifndef IO_NO_HAL +#undef WAITFORTT +#endif #undef WITHROTTLE #undef XFOFF #undef XFON @@ -281,6 +284,9 @@ #define VIRTUAL_SIGNAL(id) #define VIRTUAL_TURNOUT(id,description...) #define WAITFOR(pin) +#ifndef IO_NO_HAL +#define WAITFORTT(turntable_id) +#endif #define WITHROTTLE(msg) #define XFOFF(cab,func) #define XFON(cab,func) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 97604c5..e3ce129 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -419,6 +419,9 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define VIRTUAL_TURNOUT(id,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(0), #define WITHROTTLE(msg) PRINT(msg) #define WAITFOR(pin) OPCODE_WAITFOR,V(pin), +#ifndef IO_NO_HAL +#define WAITFORTT(turntable_id) OPCODE_WAITFORTT,V(turntable_id), +#endif #define XFOFF(cab,func) OPCODE_XFOFF,V(cab),OPCODE_PAD,V(func), #define XFON(cab,func) OPCODE_XFON,V(cab),OPCODE_PAD,V(func), diff --git a/Turntables.cpp b/Turntables.cpp index abbac81..d43a515 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -115,6 +115,12 @@ uint8_t Turntable::getPosition(uint16_t id) { return tto->getPosition(); } +bool Turntable::ttMoving(uint16_t id) { + Turntable *tto = get(id); + if (!tto) return false; + return tto->isMoving(); +} + // Initiate a turntable move bool Turntable::setPosition(uint16_t id, uint8_t position, uint8_t activity) { #if defined(DIAG_IO) diff --git a/Turntables.h b/Turntables.h index 15333c9..e7b7415 100644 --- a/Turntables.h +++ b/Turntables.h @@ -179,6 +179,7 @@ public: inline static bool exists(uint16_t id) { return get(id) != 0; } static bool setPosition(uint16_t id, uint8_t position, uint8_t activity=0); static uint8_t getPosition(uint16_t id); + static bool ttMoving(uint16_t id); inline static Turntable *first() { return _firstTurntable; } static bool printAll(Print *stream) { bool gotOne = false; From be10be5a1a9e55ef6bbb35cfac156966f5612a45 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sat, 9 Sep 2023 07:22:10 +1000 Subject: [PATCH 34/39] Added angles --- DCCEXParser.cpp | 57 +++++++++++++++++++++++++++------------------ EXRAIL2.cpp | 9 ++++--- EXRAIL2MacroReset.h | 6 +++-- EXRAILMacros.h | 11 +++++---- Turntables.cpp | 17 ++++++++++++-- Turntables.h | 13 +++++------ 6 files changed, 71 insertions(+), 42 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 94b711e..40ea635 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -732,11 +732,12 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) for (uint8_t p = 0; p < posCount; p++) { StringFormatter::send(stream, F("getPositionValue(p); + int16_t angle = tto->getPositionAngle(p); #ifdef EXRAIL_ACTIVE tpdesc = RMFT2::getTurntablePositionDescription(id, p); #endif if (tpdesc == NULL) tpdesc = F(""); - StringFormatter::send(stream, F(" %d %d %d \"%S\""), id, p, value, tpdesc); + StringFormatter::send(stream, F(" %d %d %d %d \"%S\""), id, p, value, angle, tpdesc); StringFormatter::send(stream, F(">\n")); } } @@ -1107,44 +1108,54 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) } return true; - case 2: // | - rotate or create DCC turntable + case 2: // - rotate a DCC turntable { Turntable *tto = Turntable::get(p[0]); - if (p[1] == HASH_KEYWORD_DCC) { // Create a DCC turntable - if (tto) return false; - if (!DCCTurntable::create(p[0])) return false; - Turntable *tto = Turntable::get(p[0]); - tto->addPosition(0, 0); - } else { // Otherwise move a DCC turntable - if (tto && !tto->isEXTT()) { - if (!tto->setPosition(p[0], p[1])) return false; - } else { - return false; - } + if (tto && !tto->isEXTT()) { + if (!tto->setPosition(p[0], p[1])) return false; + } else { + return false; } } return true; - case 3: // rotate to position for EX-Turntable + case 3: // | - rotate to position for EX-Turntable or create DCC turntable { Turntable *tto = Turntable::get(p[0]); - if (!tto) return false; - if (!tto->isEXTT()) return false; - if (!tto->setPosition(p[0], p[1], p[2])) return false; + if (p[1] == HASH_KEYWORD_DCC) { + if (tto || p[2] < 0 || p[2] > 3600) return false; + if (!DCCTurntable::create(p[0])) return false; + Turntable *tto = Turntable::get(p[0]); + tto->addPosition(0, 0, p[2]); + } else { + if (!tto) return false; + if (!tto->isEXTT()) return false; + if (!tto->setPosition(p[0], p[1], p[2])) return false; + } } return true; - case 4: // | create an EXTT turntable or add position + case 4: // create an EXTT turntable { Turntable *tto = Turntable::get(p[0]); if (p[1] == HASH_KEYWORD_EXTT) { - if (tto) return false; + if (tto || p[3] < 0 || p[3] > 3600) return false; if (!EXTTTurntable::create(p[0], (VPIN)p[2])) return false; Turntable *tto = Turntable::get(p[0]); - tto->addPosition(0, p[3]); - } else if (p[1] == HASH_KEYWORD_ADD) { - if (!tto) return false; - tto->addPosition(p[2], p[3]); + tto->addPosition(0, 0, p[3]); + } else { + return false; + } + } + return true; + + case 5: // add a position + { + Turntable *tto = Turntable::get(p[0]); + if (p[1] == HASH_KEYWORD_ADD) { + // tto must exist, no more than 48 positions, angle 0 - 3600 + if (!tto || p[2] > 48 || p[4] < 0 || p[4] > 3600) return false; + tto->addPosition(p[2], p[3], p[4]); StringFormatter::send(stream, F("\n")); } else { return false; diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 2d379a7..32d2795 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -53,6 +53,7 @@ #include "CommandDistributor.h" #include "TrackManager.h" #include "Turntables.h" +#include "IODevice.h" // Command parsing keywords const int16_t HASH_KEYWORD_EXRAIL=15435; @@ -248,9 +249,10 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { #ifndef IO_NO_HAL case OPCODE_DCCTURNTABLE: { VPIN id=operand; + int home=getOperand(progCounter,1); setTurntableHiddenState(DCCTurntable::create(id)); Turntable *tto=Turntable::get(id); - tto->addPosition(0,0); + tto->addPosition(0,0,home); break; } @@ -260,7 +262,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { int home=getOperand(progCounter,2); setTurntableHiddenState(EXTTTurntable::create(id,pin)); Turntable *tto=Turntable::get(id); - tto->addPosition(0,home); + tto->addPosition(0,0,home); break; } @@ -268,8 +270,9 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { VPIN id=operand; int position=getOperand(progCounter,1); int value=getOperand(progCounter,2); + int angle=getOperand(progCounter,3); Turntable *tto=Turntable::get(id); - tto->addPosition(position,value); + tto->addPosition(position,value,angle); break; } #endif diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index efe91a5..b54a9d9 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -119,6 +119,7 @@ #undef REV #undef ROSTER #undef ROTATE +#undef ROTATE_DCC #undef ROUTE #undef SENDLOCO #undef SEQUENCE @@ -174,7 +175,7 @@ #define CALL(route) #define CLOSE(id) #define DCC_SIGNAL(id,add,subaddr) -#define DCC_TURNTABLE(id,description) +#define DCC_TURNTABLE(id,home,description) #define DEACTIVATE(addr,subaddr) #define DEACTIVATEL(addr) #define DELAY(mindelay) @@ -252,6 +253,7 @@ #define RETURN #define REV(speed) #define ROTATE(turntable_id,position,activity) +#define ROTATE_DCC(turntable_id,position) #define ROSTER(cab,name,funcmap...) #define ROUTE(id,description) #define SENDLOCO(cab,route) @@ -276,7 +278,7 @@ #define START(route) #define STOP #define THROW(id) -#define TT_ADDPOSITION(turntable_id,position,value,description) +#define TT_ADDPOSITION(turntable_id,position,value,angle,description...) #define TURNOUT(id,addr,subaddr,description...) #define TURNOUTL(id,addr,description...) #define UNJOIN diff --git a/EXRAILMacros.h b/EXRAILMacros.h index e3ce129..440a619 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -192,7 +192,7 @@ const FSH * RMFT2::getTurnoutDescription(int16_t turnoutid) { // Pass to get turntable descriptions (optional) #include "EXRAIL2MacroReset.h" #undef DCC_TURNTABLE -#define DCC_TURNTABLE(id,description...) O_DESC(id,description) +#define DCC_TURNTABLE(id,home,description...) O_DESC(id,description) #undef EXTT_TURNTABLE #define EXTT_TURNTABLE(id,vpin,home,description...) O_DESC(id,description) @@ -207,7 +207,7 @@ const FSH * RMFT2::getTurntableDescription(int16_t turntableId) { // Pass to get turntable position descriptions (optional) #include "EXRAIL2MacroReset.h" #undef TT_ADDPOSITION -#define TT_ADDPOSITION(turntable_id,position,value,description...) T_DESC(turntable_id,position,description) +#define TT_ADDPOSITION(turntable_id,position,value,home,description...) T_DESC(turntable_id,position,description) const FSH * RMFT2::getTurntablePositionDescription(int16_t turntableId, uint8_t positionId) { #include "myAutomation.h" @@ -296,7 +296,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define CALL(route) OPCODE_CALL,V(route), #define CLOSE(id) OPCODE_CLOSE,V(id), #ifndef IO_NO_HAL -#define DCC_TURNTABLE(id,description...) OPCODE_DCCTURNTABLE,V(id), +#define DCC_TURNTABLE(id,home,description...) OPCODE_DCCTURNTABLE,V(id),OPCODE_PAD,V(home), #endif #define DEACTIVATE(addr,subaddr) OPCODE_DCCACTIVATE,V(addr<<3 | subaddr<<1), #define DEACTIVATEL(addr) OPCODE_DCCACTIVATE,V((addr+3)<<1), @@ -383,7 +383,8 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define REV(speed) OPCODE_REV,V(speed), #define ROSTER(cabid,name,funcmap...) #ifndef IO_NO_HAL -#define ROTATE(id,position,activity) OPCODE_ROTATE,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(activity), +#define ROTATE(id,position,activity) OPCODE_ROTATE,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(EXTurntable::activity), +#define ROTATE_DCC(id,position) OPCODE_ROTATE,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(0), #endif #define ROUTE(id, description) OPCODE_ROUTE, V(id), #define SENDLOCO(cab,route) OPCODE_SENDLOCO,V(cab),OPCODE_PAD,V(route), @@ -409,7 +410,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define STOP OPCODE_SPEED,V(0), #define THROW(id) OPCODE_THROW,V(id), #ifndef IO_NO_HAL -#define TT_ADDPOSITION(id,position,value,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(value), +#define TT_ADDPOSITION(id,position,value,angle,description...) OPCODE_TTADDPOSITION,V(id),OPCODE_PAD,V(position),OPCODE_PAD,V(value),OPCODE_PAD,V(angle), #endif #define TURNOUT(id,addr,subaddr,description...) OPCODE_TURNOUT,V(id),OPCODE_PAD,V(addr),OPCODE_PAD,V(subaddr), #define TURNOUTL(id,addr,description...) TURNOUT(id,(addr-1)/4+1,(addr-1)%4, description) diff --git a/Turntables.cpp b/Turntables.cpp index d43a515..ba143cb 100644 --- a/Turntables.cpp +++ b/Turntables.cpp @@ -58,8 +58,8 @@ void Turntable::add(Turntable *tto) { } // Add a position -void Turntable::addPosition(uint8_t idx, uint16_t value) { - _turntablePositions.insert(idx, value); +void Turntable::addPosition(uint8_t idx, uint16_t value, uint16_t angle) { + _turntablePositions.insert(idx, value, angle); } // Get value for position @@ -74,6 +74,18 @@ uint16_t Turntable::getPositionValue(uint8_t position) { return false; } +// Get value for position +uint16_t Turntable::getPositionAngle(uint8_t position) { + TurntablePosition* currentPosition = _turntablePositions.getHead(); + while (currentPosition) { + if (currentPosition->index == position) { + return currentPosition->angle; + } + currentPosition = currentPosition->next; + } + return false; +} + // Get the count of positions associated with the turntable uint8_t Turntable::getPositionCount() { TurntablePosition* currentPosition = _turntablePositions.getHead(); @@ -115,6 +127,7 @@ uint8_t Turntable::getPosition(uint16_t id) { return tto->getPosition(); } +// Got the moving state of the specified turntable bool Turntable::ttMoving(uint16_t id) { Turntable *tto = get(id); if (!tto) return false; diff --git a/Turntables.h b/Turntables.h index e7b7415..6c15bab 100644 --- a/Turntables.h +++ b/Turntables.h @@ -36,9 +36,6 @@ enum { TURNTABLE_DCC = 1, }; -// Callback needs to return a bool: 1 = moving, 0 = stopped -typedef void (*EXTT_CALLBACK)(bool moving); - /************************************************************************************* * Turntable positions. * @@ -46,17 +43,18 @@ typedef void (*EXTT_CALLBACK)(bool moving); struct TurntablePosition { uint8_t index; uint16_t data; + uint16_t angle; TurntablePosition* next; - TurntablePosition(uint8_t idx, uint16_t value) : index(idx), data(value), next(nullptr) {} + TurntablePosition(uint8_t idx, uint16_t value, uint16_t angle) : index(idx), data(value), angle(angle), next(nullptr) {} }; class TurntablePositionList { public: TurntablePositionList() : head(nullptr) {} - void insert(uint8_t idx, uint16_t value) { - TurntablePosition* newPosition = new TurntablePosition(idx, value); + void insert(uint8_t idx, uint16_t value, uint16_t angle) { + TurntablePosition* newPosition = new TurntablePosition(idx, value, angle); if(!head) { head = newPosition; } else { @@ -158,8 +156,9 @@ public: inline uint16_t getId() { return _turntableData.id; } inline Turntable *next() { return _nextTurntable; } void printState(Print *stream); - void addPosition(uint8_t idx, uint16_t value); + void addPosition(uint8_t idx, uint16_t value, uint16_t angle); uint16_t getPositionValue(uint8_t position); + uint16_t getPositionAngle(uint8_t position); uint8_t getPositionCount(); bool isMoving() { return _isMoving; } void setMoving(bool moving) { _isMoving=moving; } From dba5d35aa231ebbe732a755462f8b95043554c64 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sat, 9 Sep 2023 09:23:10 +1000 Subject: [PATCH 35/39] Add response to create --- DCCEXParser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 40ea635..05e0eca 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1127,6 +1127,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) if (!DCCTurntable::create(p[0])) return false; Turntable *tto = Turntable::get(p[0]); tto->addPosition(0, 0, p[2]); + StringFormatter::send(stream, F("\n")); } else { if (!tto) return false; if (!tto->isEXTT()) return false; @@ -1143,6 +1144,7 @@ bool DCCEXParser::parseI(Print *stream, int16_t params, int16_t p[]) if (!EXTTTurntable::create(p[0], (VPIN)p[2])) return false; Turntable *tto = Turntable::get(p[0]); tto->addPosition(0, 0, p[3]); + StringFormatter::send(stream, F("\n")); } else { return false; } From 7ee2c29a526078d2f5a395adc0cd671f1d1df0a9 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 10 Sep 2023 05:30:48 +1000 Subject: [PATCH 36/39] Include HAL create with EXTT_TURNTABLE --- EXRAIL2.cpp | 2 +- EXRAIL2MacroReset.h | 2 +- EXRAILMacros.h | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 32d2795..c8ff8f3 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -259,7 +259,7 @@ LookList* RMFT2::LookListLoader(OPCODE op1, OPCODE op2, OPCODE op3) { case OPCODE_EXTTTURNTABLE: { VPIN id=operand; VPIN pin=getOperand(progCounter,1); - int home=getOperand(progCounter,2); + int home=getOperand(progCounter,3); setTurntableHiddenState(EXTTTurntable::create(id,pin)); Turntable *tto=Turntable::get(id); tto->addPosition(0,0,home); diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index b54a9d9..c8ff395 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -189,7 +189,7 @@ #define ENDTASK #define ESTOP #define EXRAIL -#define EXTT_TURNTABLE(id,vpin,home,description) +#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description) #define FADE(pin,value,ms) #define FOFF(func) #define FOLLOW(route) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 440a619..39e5dda 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -69,10 +69,13 @@ #define ALIAS(name,value...) const int name= 1##value##0 ==10 ? -__COUNTER__ : value##0/10; #include "myAutomation.h" -// Pass 1h Implements HAL macro by creating exrailHalSetup function +// Pass 1h Implements HAL macro by creating exrailHalSetup function +// Also allows creating EXTurntable object #include "EXRAIL2MacroReset.h" #undef HAL #define HAL(haltype,params...) haltype::create(params); +#undef EXTT_TURNTABLE +#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) EXTurntable::create(vpin,1,i2c_address); void exrailHalSetup() { #include "myAutomation.h" } @@ -194,7 +197,7 @@ const FSH * RMFT2::getTurnoutDescription(int16_t turnoutid) { #undef DCC_TURNTABLE #define DCC_TURNTABLE(id,home,description...) O_DESC(id,description) #undef EXTT_TURNTABLE -#define EXTT_TURNTABLE(id,vpin,home,description...) O_DESC(id,description) +#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) O_DESC(id,description) const FSH * RMFT2::getTurntableDescription(int16_t turntableId) { switch (turntableId) { @@ -313,7 +316,7 @@ const HIGHFLASH int16_t RMFT2::SignalDefinitions[] = { #define ESTOP OPCODE_SPEED,V(1), #define EXRAIL #ifndef IO_NO_HAL -#define EXTT_TURNTABLE(id,vpin,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(home), +#define EXTT_TURNTABLE(id,vpin,i2c_address,home,description...) OPCODE_EXTTTURNTABLE,V(id),OPCODE_PAD,V(vpin),OPCODE_PAD,V(i2c_address),OPCODE_PAD,V(home), #endif #define FADE(pin,value,ms) OPCODE_SERVO,V(pin),OPCODE_PAD,V(value),OPCODE_PAD,V(PCA9685::ProfileType::UseDuration|PCA9685::NoPowerOff),OPCODE_PAD,V(ms/100L), #define FOFF(func) OPCODE_FOFF,V(func), From a0562fdf5c0e1af6ffb0a95091535d827d3e0343 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 10 Sep 2023 07:06:27 +1000 Subject: [PATCH 37/39] Update defines to match changes in devel --- defines.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/defines.h b/defines.h index 3286aca..49aff71 100644 --- a/defines.h +++ b/defines.h @@ -218,8 +218,12 @@ // Define symbol IO_NO_HAL to reduce FLASH footprint when HAL features not required // The HAL is disabled by default on Nano and Uno platforms, because of limited flash space. // -#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO) -#define IO_NO_HAL +#if defined(ARDUINO_AVR_NANO) || defined(ARDUINO_AVR_UNO) + #if defined(DISABLE_DIAG) && defined(DISABLE_EEPROM) && defined(DISABLE_PROG) + #warning you have sacrificed DIAG for HAL + #else + #define IO_NO_HAL + #endif #endif #if __has_include ( "myAutomation.h") From 4fcd81a118a1ee8b89410bd5a30f2b0d73b4c61c Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 10 Sep 2023 07:18:54 +1000 Subject: [PATCH 38/39] Update version --- version.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/version.h b/version.h index abcc577..e8ee138 100644 --- a/version.h +++ b/version.h @@ -3,7 +3,10 @@ #include "StringFormatter.h" -#define VERSION "5.1.4" +#define VERSION "5.1.5" +// 5.1.5 - Added turntable object and EXRAIL commands +// - , , - turntable commands +// - DCC_TURNTABLE, EXTT_TURNTABLE, IFTTPOSITION, ONROTATE, ROTATE, ROTATE_DCC, TT_ADDPOSITION, WAITFORTT EXRAIL // 5.1.4 - Added ONOVERLOAD & AFTEROVERLOAD to EXRAIL // 5.1.3 - Make parser more fool proof // 5.1.2 - Bugfix: ESP32 30ms off time From da6a3c442f66d8802112b3b676ec47228f0a94b1 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 10 Sep 2023 18:41:14 +1000 Subject: [PATCH 39/39] Remove redundant line --- EXRAIL2.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index fae6add..d6d2597 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -650,7 +650,6 @@ void RMFT2::loop2() { case OPCODE_ROTATE: uint8_t activity; activity=getOperand(2); - if (!activity) activity=0; Turntable::setPosition(operand,getOperand(1),activity); break; #endif