From 4aa97e1731e108651d372c947772485d3974cf10 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sat, 13 Apr 2024 08:12:35 +0100 Subject: [PATCH] Squashed commit of the following: commit 3fc90c916c54ceae4364f79a4b9a2001bc75fcd5 Merge: 132e2d0 91e60b3 Author: Asbelos Date: Fri Apr 12 15:08:49 2024 +0100 Merge branch 'devel' into devel_chris commit 132e2d0de2c6e72b1a3d85520936fb7cddd8d739 Author: Asbelos Date: Fri Apr 12 15:07:31 2024 +0100 Revert "Merge branch 'master' into devel_chris" This reverts commit 23845f2df2035333c43b4aa05d76e9f7600efe29, reversing changes made to 76755993f146a1deaf46993d22e850b899dcf603. commit 23845f2df2035333c43b4aa05d76e9f7600efe29 Merge: 7675599 28d60d4 Author: Asbelos Date: Fri Apr 12 14:38:22 2024 +0100 Merge branch 'master' into devel_chris commit 76755993f146a1deaf46993d22e850b899dcf603 Author: Asbelos Date: Fri Apr 12 14:37:34 2024 +0100 ONSENSOR/ONBUTTON commit 8987d622e60fb27174203ce47b49462a01ecb61c Author: Asbelos Date: Tue Apr 9 20:44:47 2024 +0100 doc note commit 8f0a5c1ec0fde18dbb262311a1ef5ef79d571807 Author: Asbelos Date: Thu Apr 4 09:45:58 2024 +0100 Exrail notes commit 94083b9ab8a2322c39b7087c522730569194b732 Merge: 72ef199 02bf50b Author: Asbelos Date: Thu Apr 4 09:08:26 2024 +0100 Merge branch 'devel' into devel_chris commit 72ef199315d1c7717331864abb11730890fd3162 Author: Asbelos Date: Thu Apr 4 09:06:50 2024 +0100 TOGGLE_TURNOUT commit e69b777a2f62104dd8b74ba688b950fa92919d54 Author: Asbelos Date: Wed Apr 3 15:17:40 2024 +0100 BLINK command commit c7ed47400d5d89c0b8425ec12b1828e710fb23ec Author: Asbelos Date: Tue Apr 2 10:12:45 2024 +0100 FTOGGLE,XFTOGGLE commit 7a93cf7be856afd30f6976a483b1db4bfc4073a1 Author: Asbelos Date: Fri Mar 29 13:21:35 2024 +0000 EXRAIL STEALTH_GLOBAL commit 28d60d49849c8fc4b0ff0f933222c052ba7c90aa Author: Peter Akers Date: Fri Feb 16 18:02:40 2024 +1000 Update README.md commit 3b162996ad42546486b812e22d3ed6daee857d19 Author: peteGSX Date: Sun Jan 21 07:13:53 2024 +1000 EX-IO fixes in version commit fb414a7a506f078d2a075d65c7b171ae4399ef63 Author: Harald Barth Date: Thu Jan 18 08:20:33 2024 +0100 Bugfix: allocate enough bytes for digital pins. Add more sanity checks when allocating memory commit 818e05b4253a1a0980abb3a0bbef38a8c662bb1a Author: Harald Barth Date: Wed Jan 10 08:37:54 2024 +0100 version 5.0.8 commit c5168f030fa64330a1f0e09d6637a3817fe5e067 Author: Harald Barth Date: Wed Jan 10 08:15:30 2024 +0100 Do not crash on turnouts without description commit 387ea019bdc483667bcbcf45205a56330d615aee Author: Harald Barth Date: Mon Nov 6 22:11:56 2023 +0100 version 5.0.7 commit a981f83bb9c376d01245c328c5de7d7bf25ebfb2 Author: Harald Barth Date: Mon Nov 6 22:11:31 2023 +0100 Only flag 2.2.0.0-dev as broken, not 2.2.0.0 commit 749a859db551113567faae3248c575dbf6440ece Author: Asbelos Date: Wed Nov 1 20:13:05 2023 +0000 Bugfix TURNOUTL commit 659c58b30766a7b8dd2b4d2677d90663af8fefcf Author: Harald Barth Date: Sat Oct 28 19:20:33 2023 +0200 version 5.0.5 commit 0b9ec7460ba461d5602b6e06843d6be8468f385f Author: Harald Barth Date: Sat Oct 28 19:18:59 2023 +0200 Bugfix version detection logic and better message --- EXRAIL2.cpp | 10 +++ EXRAIL2.h | 2 +- EXRAIL2MacroReset.h | 4 ++ EXRAILMacros.h | 2 + EXRAILSensor.cpp | 104 ++++++++++++++++++++++++++++++ EXRAILSensor.h | 50 ++++++++++++++ Release_Notes/EXRAIL additions.md | 38 +++++++++++ 7 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 EXRAILSensor.cpp create mode 100644 EXRAILSensor.h create mode 100644 Release_Notes/EXRAIL additions.md diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 9293c96c..adea99e5 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -54,6 +54,7 @@ #include "TrackManager.h" #include "Turntables.h" #include "IODevice.h" +#include "EXRAILSensor.h" // One instance of RMFT clas is used for each "thread" in the automation. @@ -251,6 +252,12 @@ if (compileFeatures & FEATURE_SIGNAL) { break; } + case OPCODE_ONSENSOR: + new EXRAILSensor(operand,progCounter+3,true ); + break; + case OPCODE_ONBUTTON: + new EXRAILSensor(operand,progCounter+3,false ); + break; case OPCODE_TURNOUT: { VPIN id=operand; int addr=getOperand(progCounter,1); @@ -480,6 +487,7 @@ bool RMFT2::skipIfBlock() { } void RMFT2::loop() { + EXRAILSensor::checkAll(); // Round Robin call to a RMFT task each time if (loopTask==NULL) return; @@ -1084,6 +1092,8 @@ void RMFT2::loop2() { case OPCODE_ONGREEN: case OPCODE_ONCHANGE: case OPCODE_ONTIME: + case OPCODE_ONBUTTON: + case OPCODE_ONSENSOR: #ifndef IO_NO_HAL case OPCODE_DCCTURNTABLE: // Turntable definition ignored at runtime case OPCODE_EXTTTURNTABLE: // Turntable definition ignored at runtime diff --git a/EXRAIL2.h b/EXRAIL2.h index 7075f265..1042d53e 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -73,7 +73,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,OPCODE_TOGGLE_TURNOUT, OPCODE_ROUTE_ACTIVE,OPCODE_ROUTE_INACTIVE,OPCODE_ROUTE_HIDDEN, OPCODE_ROUTE_DISABLED, OPCODE_STASH,OPCODE_CLEAR_STASH,OPCODE_CLEAR_ALL_STASH,OPCODE_PICKUP_STASH, - + OPCODE_ONBUTTON,OPCODE_ONSENSOR, // OPcodes below this point are skip-nesting IF operations // placed here so that they may be skipped as a group // see skipIfBlock() diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index ce242ea3..c799ddfd 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -114,6 +114,8 @@ #undef ONGREEN #undef ONRED #undef ONROTATE +#undef ONBUTTON +#undef ONSENSOR #undef ONTHROW #undef ONCHANGE #undef PARSE @@ -279,6 +281,8 @@ #define ONROTATE(turntable_id) #define ONTHROW(turnout_id) #define ONCHANGE(sensor_id) +#define ONSENSOR(sensor_id) +#define ONBUTTON(sensor_id) #define PAUSE #define PIN_TURNOUT(id,pin,description...) #define PRINT(msg) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 7db52dc0..508540a7 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -553,6 +553,8 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup]; #endif #define ONTHROW(turnout_id) OPCODE_ONTHROW,V(turnout_id), #define ONCHANGE(sensor_id) OPCODE_ONCHANGE,V(sensor_id), +#define ONSENSOR(sensor_id) OPCODE_ONSENSOR,V(sensor_id), +#define ONBUTTON(sensor_id) OPCODE_ONBUTTON,V(sensor_id), #define PAUSE OPCODE_PAUSE,0,0, #define PICKUP_STASH(id) OPCODE_PICKUP_STASH,V(id), #define PIN_TURNOUT(id,pin,description...) OPCODE_PINTURNOUT,V(id),OPCODE_PAD,V(pin), diff --git a/EXRAILSensor.cpp b/EXRAILSensor.cpp new file mode 100644 index 00000000..b0a5fa05 --- /dev/null +++ b/EXRAILSensor.cpp @@ -0,0 +1,104 @@ +/* + * © 2024 Chris Harlow + * 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 . + */ + +/********************************************************************** +EXRAILSensor represents a sensor that should be monitored in order +to call an exrail ONBUTTON or ONCHANGE handler. +These are created at EXRAIL startup and thus need no delete or listing +capability. +The basic logic is similar to that found in the Sensor class +except that on the relevant change an EXRAIL thread is started. +**********************************************************************/ + +#include "EXRAILSensor.h" +#include "EXRAIL2.h" + +void EXRAILSensor::checkAll() { + if (firstSensor == NULL) return; // No sensors to be scanned + if (readingSensor == NULL) { + // Not currently scanning sensor list + unsigned long thisTime = micros(); + if (thisTime - lastReadCycle < cycleInterval) return; + // Required time has elapsed since last read cycle started, + // so initiate new scan through the sensor list + readingSensor = firstSensor; + lastReadCycle = thisTime; + } + + // Loop until either end of list is encountered or we pause for some reason + byte sensorCount = 0; + + while (readingSensor != NULL) { + bool pause=readingSensor->check(); + // Move to next sensor in list. + readingSensor = readingSensor->nextSensor; + // Currently process max of 16 sensors per entry. + // Performance measurements taken during development indicate that, with 128 sensors configured + // on 8x 16-pin MCP23017 GPIO expanders with polling (no change notification), all inputs can be read from the devices + // within 1.4ms (400Mhz I2C bus speed), and a full cycle of checking 128 sensors for changes takes under a millisecond. + if (pause || (++sensorCount)>=16) return; + } +} + +bool EXRAILSensor::check() { + // check for debounced change in this sensor + inputState = IODevice::read(pin); + + // Check if changed since last time, and process changes. + if (inputState == active) {// no change + latchDelay = minReadCount; // Reset counter + return false; // no change + } + + // Change detected ... has it stayed changed for long enough + if (latchDelay > 0) { + latchDelay--; + return false; + } + + // change validated, act on it. + active = inputState; + latchDelay = minReadCount; // Reset debounce counter + if (onChange || active) { + new RMFT2(progCounter); + return true; // Don't check any more sensors on this entry + } + return false; +} + +EXRAILSensor::EXRAILSensor(VPIN _pin, int _progCounter, bool _onChange) { + // Add to the start of the list + //DIAG(F("ONthing vpin=%d at %d"), _pin, _progCounter); + nextSensor = firstSensor; + firstSensor = this; + + pin=_pin; + progCounter=_progCounter; + onChange=_onChange; + + IODevice::configureInput(pin, true); + active = IODevice::read(pin); + inputState = active; + latchDelay = minReadCount; +} + +EXRAILSensor *EXRAILSensor::firstSensor=NULL; +EXRAILSensor *EXRAILSensor::readingSensor=NULL; +unsigned long EXRAILSensor::lastReadCycle=0; diff --git a/EXRAILSensor.h b/EXRAILSensor.h new file mode 100644 index 00000000..b5b00c65 --- /dev/null +++ b/EXRAILSensor.h @@ -0,0 +1,50 @@ +/* + * © 2024 Chris Harlow + * 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 EXRAILSensor_h +#define EXRAILSensor_h +#include "IODevice.h" +class EXRAILSensor { + static EXRAILSensor * firstSensor; + static EXRAILSensor * readingSensor; + static unsigned long lastReadCycle; + + public: + static void checkAll(); + + EXRAILSensor(VPIN _pin, int _progCounter, bool _onChange); + bool check(); + + private: + static const unsigned int cycleInterval = 10000; // min time between consecutive reads of each sensor in microsecs. + // should not be less than device scan cycle time. + static const byte minReadCount = 4; // number of additional scans before acting on change + // E.g. 1 means that a change is ignored for one scan and actioned on the next. + // Max value is 63 + + EXRAILSensor* nextSensor; + VPIN pin; + int progCounter; + bool active; + bool inputState; + bool onChange; + byte latchDelay; +}; +#endif \ No newline at end of file diff --git a/Release_Notes/EXRAIL additions.md b/Release_Notes/EXRAIL additions.md new file mode 100644 index 00000000..690ff0ae --- /dev/null +++ b/Release_Notes/EXRAIL additions.md @@ -0,0 +1,38 @@ + +BLINK(vpin, onMs,offMs) + +which will start a vpin blinking until such time as it is SET, RESET or set by a signal operation such as RED, AMBER, GREEN. + +BLINK returns immediately, the blinking is autonomous. + +This means a signal that always blinks amber could be done like this: +``` +SIGNAL(30,31,32) +ONAMBER(30) BLINK(31,500,500) DONE +``` +The RED or GREEN calls will turn off the amber blink automatically. + +Alternatively a signal that has normal AMBER and flashing AMBER could be like this: + +#define FLASHAMBER(signal) \ + AMBER(signal) \ + BLINK(signal+1,500,500) + + (Caution: this issumes that the amber pin is redpin+1) + + == + + FTOGGLE(function) + Toggles the current loco function (see FON and FOFF) + + XFTOGGLE(loco,function) + Toggles the function on given loco. (See XFON, XFOFF) + + TOGGLE_TURNOUT(id) + Toggles the turnout (see CLOSE, THROW) + + STEALTH_GLOBAL(code) + ADVANCED C++ users only. + Inserts code such as static variables and functions that + may be utilised by multiple STEALTH operations. + \ No newline at end of file