1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-07-28 18:03:45 +02:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Asbelos
c699eb3492 JMRI_SENSOR_NOPULLUP
and associated dump for <S>
2025-07-25 09:29:57 +01:00
Asbelos
d84e354142 esp32 sensorgroup 2025-07-24 20:41:31 +01:00
Asbelos
823ceef338 SensorGroup 2025-07-24 18:19:13 +01:00
Asbelos
940d7d70e2 Low ram sensor groups 2025-07-24 15:49:20 +01:00
7 changed files with 156 additions and 14 deletions

View File

@@ -1135,12 +1135,7 @@ bool DCCEXParser::parseS(Print *stream, int16_t params, int16_t p[])
return true;
case 0: // <S> list sensor definitions
if (Sensor::firstSensor == NULL)
return false;
for (Sensor *tt = Sensor::firstSensor; tt != NULL; tt = tt->nextSensor)
{
StringFormatter::send(stream, F("<Q %d %d %d>\n"), tt->data.snum, tt->data.pin, tt->data.pullUp);
}
Sensor::dumpAll(stream);
return true;
default: // invalid number of arguments

View File

@@ -98,6 +98,7 @@
#undef IFBITMAP_ANY
#undef INVERT_DIRECTION
#undef JMRI_SENSOR
#undef JMRI_SENSOR_NOPULLUP
#undef JOIN
#undef KILLALL
#undef LATCH
@@ -684,11 +685,18 @@
#define INVERT_DIRECTION
/**
* @def JMRI_SENSOR(vpin,count...)
* @brief Defines multiple JMRI <s> type sensor feedback definitions each with id matching vpin
* @brief Defines multiple JMRI <s> type sensor feedback definitions each with id matching vpin and INPUT_PULLUP
* @param vpin first vpin number
* @param count... Number of consecutine VPINS for which to create JMRI sensor feedbacks. Default 1.
*/
#define JMRI_SENSOR(vpin,count...)
/**
* @def JMRI_SENSOR_NOPULLUP(vpin,count...)
* @brief Defines multiple JMRI <s> type sensor feedback definitions each with id matching vpin
* @param vpin first vpin number
* @param count... Number of consecutine VPINS for which to create JMRI sensor feedbacks. Default 1.
*/
#define JMRI_SENSOR_NOPULLUP(vpin,count...)
/**
* @def JOIN
* @brief Switches PROG track to receive MAIN track DCC packets. (Drive on PROG track)

View File

@@ -113,11 +113,36 @@ bool exrailHalSetup1() {
// the first pass from the opcode table.
#include "EXRAIL2MacroReset.h"
#undef JMRI_SENSOR
#define JMRI_SENSOR(vpin,count...) Sensor::createMultiple(vpin,##count);
#define JMRI_SENSOR(vpin,count...) \
{ \
const int npins=#count[0]? count+0:1; \
static byte state_map[(npins+7)/8]; \
SensorGroup::doSensorGroup(vpin,npins,state_map,action,&USB_SERIAL,true); \
}
#undef JMRI_SENSOR_NOPULLUP
#define JMRI_SENSOR_NOPULLUP(vpin,count...) \
{ \
const int npins=#count[0]? count+0:1; \
static byte state_map[(npins+7)/8]; \
SensorGroup::doSensorGroup(vpin,npins,state_map,action,&USB_SERIAL,false); \
}
void SensorGroup::doExrailSensorGroup(GroupProcess action, Print * stream) {
(void) action; // suppress unused warnings if no groups
(void) stream;
#include "myAutomation.h"
}
// Pass 1s Implements servos by creating exrailHalSetup2
// TODO Turnout and turntable creation should be moved to here instead of
// the first pass from the opcode table.
#include "EXRAIL2MacroReset.h"
#undef CONFIGURE_SERVO
#define CONFIGURE_SERVO(vpin,pos1,pos2,profile) IODevice::configureServo(vpin,pos1,pos2,PCA9685::profile);
void exrailHalSetup2() {
#include "myAutomation.h"
// pullup any group sensors
SensorGroup::prepareAll();
}
// Pass 1c detect compile time featurtes
@@ -495,6 +520,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define IFBITMAP_ANY(vpin,mask) OPCODE_IFBITMAP_ANY,V(vpin),OPCODE_PAD,V(mask),
#define INVERT_DIRECTION OPCODE_INVERT_DIRECTION,0,0,
#define JMRI_SENSOR(vpin,count...)
#define JMRI_SENSOR_NOPULLUP(vpin,count...)
#define JOIN OPCODE_JOIN,0,0,
#define KILLALL OPCODE_KILLALL,0,0,
#define LATCH(sensor_id) OPCODE_LATCH,V(sensor_id),

67
SensorGroup.cpp Normal file
View File

@@ -0,0 +1,67 @@
#include "SensorGroup.h"
#ifdef EXRAIL_ACTIVE
// called in loop to check sensors
void SensorGroup::checkAll() {
doExrailSensorGroup(GroupProcess::check, & USB_SERIAL);
}
// called by command to get sensor list
void SensorGroup::printAll(Print * serial) {
(void)serial; // suppress unused warning
doExrailSensorGroup(GroupProcess::print,serial);
}
void SensorGroup::prepareAll() {
doExrailSensorGroup(GroupProcess::prepare, & USB_SERIAL);
}
void SensorGroup::dumpAll(Print * stream) {
doExrailSensorGroup(GroupProcess::dump, stream);
}
#else
// if EXRAIL is not active, these functions are empty
void SensorGroup::checkAll() {}
void SensorGroup::printAll(Print * serial) {(void)serial;}
void SensorGroup::prepareAll() {}
#endif
// called by EXRAIL constructed doExrailSensorGroup for each group
void SensorGroup::doSensorGroup(VPIN firstVpin, int nPins, byte* statebits,
GroupProcess action, Print * serial, bool pullup) {
// Loop through the pins in the group
for (auto i=0;i<nPins;i++) {
// locate position of state bit
byte stateByte=i/8;
byte stateMask=1<<(i%8);
VPIN vpin= firstVpin+i;
switch(action) {
case GroupProcess::prepare:
IODevice::configureInput(vpin, pullup);
__attribute__ ((fallthrough)); // to check the current state
case GroupProcess::check:
// check for state change
if ((bool)(statebits[stateByte]&stateMask) ==IODevice::read(vpin)) break; // no change
// flip state bit
statebits[stateByte]^=stateMask;
if (action==GroupProcess::prepare) break;
// fall through to print the changed value
__attribute__ ((fallthrough));
case GroupProcess::print:
StringFormatter::send(serial, F("<%c %d>\n"),
(statebits[stateByte]&stateMask)?'Q':'q', vpin);
break;
case GroupProcess::dump:
StringFormatter::send(serial, F("<Q %d %d %c>\n"),
vpin, vpin, pullup?'1':'0');
break;
}
}
}

28
SensorGroup.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef SensorGroup_h
#define SensorGroup_h
#include <Arduino.h>
#include "defines.h"
#include "IODevice.h"
#include "StringFormatter.h"
// reference to the optional exrail built function which contains the
// calls to SensorGroup::doSensorGroup
enum GroupProcess:byte {prepare,print,check,dump};
class SensorGroup {
public:
static void checkAll();
static void printAll(Print * serial);
static void prepareAll();
static void dumpAll(Print* serial);
// doSensorGroup is called from the automatically
// built doExrailSensorGroup, once for each user defined group.
static void doSensorGroup(VPIN vpin, int nPins, byte* statebits,
GroupProcess action, Print * serial, bool pullup=false);
private:
static void doExrailSensorGroup(GroupProcess action, Print * stream);
};
#endif // SensorGroup_h

View File

@@ -91,6 +91,9 @@ decide to ignore the <q ID> return and only react to <Q ID> triggers.
///////////////////////////////////////////////////////////////////////////////
void Sensor::checkAll(){
SensorGroup::checkAll();
uint16_t sensorCount = 0;
#ifdef USE_NOTIFY
@@ -181,13 +184,25 @@ void Sensor::inputChangeCallback(VPIN vpin, int state) {
///////////////////////////////////////////////////////////////////////////////
void Sensor::printAll(Print *stream){
if (stream == NULL) return; // Nothing to do
SensorGroup::printAll(stream);
for(Sensor * tt=firstSensor;tt!=NULL;tt=tt->nextSensor){
StringFormatter::send(stream, F("<%c %d>\n"), tt->active ? 'Q' : 'q', tt->data.snum);
}
}
if (stream != NULL) {
for(Sensor * tt=firstSensor;tt!=NULL;tt=tt->nextSensor){
StringFormatter::send(stream, F("<%c %d>\n"), tt->active ? 'Q' : 'q', tt->data.snum);
}
} // loop over all sensors
} // Sensor::printAll
void Sensor::dumpAll(Print *stream){
if (stream == NULL) return; // Nothing to do
SensorGroup::dumpAll(stream);
for(Sensor * tt=firstSensor;tt!=NULL;tt=tt->nextSensor){
StringFormatter::send(stream, F("<Q %d %d %d>\n"),
tt->data.snum, tt->data.pin,tt->data.pullUp);
}
} // Sensor::dumpAll
///////////////////////////////////////////////////////////////////////////////
// Static Function to create/find Sensor object.

View File

@@ -24,6 +24,7 @@
#include "Arduino.h"
#include "IODevice.h"
#include "SensorGroup.h"
// Uncomment the following #define statement to use callback notification
// where the driver supports it.
@@ -81,6 +82,8 @@ public:
static bool remove(int id);
static void checkAll();
static void printAll(Print *stream);
static void dumpAll(Print* stream);
static unsigned long lastReadCycle; // value of micros at start of last read cycle
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.