Skip to content

Commit

Permalink
5.5.8 Cam parser cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Asbelos committed Jan 19, 2025
1 parent 137008c commit 95d90aa
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 47 deletions.
92 changes: 68 additions & 24 deletions CamParser.cpp
Original file line number Diff line number Diff line change
@@ -1,65 +1,90 @@
/*
* © 2023-2025, Barry Daniel
* © 2025 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 <https://www.gnu.org/licenses/>.
*/

//sensorCAM parser.cpp version 3.03 Sep 2024
//sensorCAM parser.cpp version 3.05 Jan 2025
#include "DCCEXParser.h"
#include "CamParser.h"
#include "FSH.h"
#include "IO_EXSensorCAM.h"

#ifndef SENSORCAM_VPIN //define CAM vpin (700?) in config.h
#define SENSORCAM_VPIN 0
#endif
#define CAM_VPIN SENSORCAM_VPIN
#ifndef SENSORCAM2_VPIN
#define SENSORCAM2_VPIN CAM_VPIN
#endif
#ifndef SENSORCAM3_VPIN
#define SENSORCAM3_VPIN 0
#endif
const int CAMVPINS[] = {CAM_VPIN,SENSORCAM_VPIN,SENSORCAM2_VPIN,SENSORCAM3_VPIN};
const int16_t ver=30177;
const int16_t ve =2899;

VPIN EXSensorCAM::CAMBaseVpin = CAM_VPIN;

// The CAMVPINS array will be filled by IO_EXSensorCam HAL drivers calling
// the CamParser::addVpin() function.
// The CAMBaseVpin is the one to be used when commands are given without a vpin.
VPIN CamParser::CAMBaseVpin = 0; // no vpins yet known
VPIN CamParser::CAMVPINS[] = {0,0,0,0}; // no vpins yet known
int CamParser::vpcount=sizeof(CAMVPINS)/sizeof(CAMVPINS[0]);

void CamParser::parse(Print * stream, byte & opcode, byte & paramCount, int16_t p[]) {
if (opcode!='N') return; // this is not for us.
if (parseN(stream,paramCount,p)) opcode=0; // we have consumed this
// If we fail, the caller will <X> the <N command.
}

bool CamParser::parseN(Print * stream, byte paramCount, int16_t p[]) {
(void)stream; // probably unused parameter
VPIN vpin=EXSensorCAM::CAMBaseVpin; //use current CAM selection
VPIN vpin=CAMBaseVpin; //use current CAM selection

if (paramCount==0) {
DIAG(F("vpin:%d EXSensorCAMs defined at Vpins #1@ %d #2@ %d #3@ %d"),vpin,CAMVPINS[1],CAMVPINS[2],CAMVPINS[3]);
DIAG(F("Cam base vpin:%d"),CAMBaseVpin);
for (auto i=0;i<vpcount;i++){
if (CAMVPINS[i]==0) break;
DIAG(F("EXSensorCam #%d vpin %d"),i+1,CAMVPINS[i]);
}
return true;
}
uint8_t camop=p[0]; // cam oprerator
int param1=0;
int16_t param3=9999; // =0 could invoke parameter changes. & -1 gives later errors

if(camop=='C'){
if(p[1]>=100) EXSensorCAM::CAMBaseVpin=p[1];
if(p[1]<4) EXSensorCAM::CAMBaseVpin=CAMVPINS[p[1]];
DIAG(F("CAM base Vpin: %c %d "),p[0],EXSensorCAM::CAMBaseVpin);
if(p[1]>=100) CAMBaseVpin=p[1];
if(p[1]<vpcount) CAMBaseVpin=CAMVPINS[p[1]];
DIAG(F("CAM base Vpin: %c %d "),p[0],CAMBaseVpin);
return true;
}
if (camop<100) { //switch CAM# if p[1] dictates
if(p[1]>=100 && p[1]<400) { //limits to CAM# 1 to 3 for now
if(p[1]>=100 && p[1]<(vpcount*100)) { //limits to CAM# 1 to 3 for now
vpin=CAMVPINS[p[1]/100];
EXSensorCAM::CAMBaseVpin=vpin;
CAMBaseVpin=vpin;
DIAG(F("switching to CAM %d baseVpin:%d"),p[1]/100,vpin);
p[1]=p[1]%100; //strip off CAM #
}
}
if (EXSensorCAM::CAMBaseVpin==0) return false; // no cam defined
if (CAMBaseVpin==0) return false; // no cam defined


// send UPPER case to sensorCAM to flag binary data from a DCCEX-CS parser
switch(paramCount) {
case 1: //<N ver> produces '^'
if((p[0] == ve) || (p[0] == ver) || (p[0] == 'V')) camop='^';
if((camop == 'V') || (p[0] == ve) || (p[0] == ver) ) camop='^';
if (STRCHR_P((const char *)F("EFGMQRVW^"),camop) == nullptr) return false;
if (camop=='Q') param3=10; //<NQ> for activation state of all 10 banks of sensors
if (camop=='F') camop=']'; //<NF> for Reset/Finish webCAM.
break; // F Coded as ']' else conflicts with <Nf %%>

case 2: //<N camop p1>
if (STRCHR_P((const char *)F("ABFILMNOPQRSTUV"),camop)==nullptr) return false;
if (STRCHR_P((const char *)F("ABFHILMNOPQRSTUV"),camop)==nullptr) return false;
param1=p[1];
break;

Expand Down Expand Up @@ -92,4 +117,23 @@ bool CamParser::parseN(Print * stream, byte paramCount, int16_t p[]) {
DIAG(F("CamParser: %d %c %d %d"),vpin,camop,param1,param3);
IODevice::writeAnalogue(vpin,param1,camop,param3);
return true;
}

void CamParser::addVpin(VPIN pin) {
// called by IO_EXSensorCam starting up a camera on a vpin
byte slot=255;
for (auto i=0;i<vpcount && slot==255;i++) {
if (CAMVPINS[i]==0) {
slot=i;
CAMVPINS[slot]=pin;
}
}
if (slot==255) {
DIAG(F("No more than %d cameras supported"),vpcount);
return;
}
if (slot==0) CAMBaseVpin=pin;
DIAG(F("CamParser Registered cam #%dvpin %d"),slot+1,pin);
// tell the DCCEXParser that we wish to filter commands
DCCEXParser::setCamParserFilter(&parse);
}
30 changes: 29 additions & 1 deletion CamParser.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
/*
* © 2023-2025, Barry Daniel
* © 2025 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 <https://www.gnu.org/licenses/>.
*/


#ifndef CamParser_H
#define CamParser_H
#include <Arduino.h>
#include "IODevice.h"

class CamParser {
public:
static bool parseN(Print * stream, byte paramCount, int16_t p[]);
static void parse(Print * stream, byte & opcode, byte & paramCount, int16_t p[]);
static void addVpin(VPIN pin);
private:
static bool parseN(Print * stream, byte paramCount, int16_t p[]);
static VPIN CAMBaseVpin;
static VPIN CAMVPINS[];
static int vpcount;
};


Expand Down
15 changes: 9 additions & 6 deletions DCCEXParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], byte *cmd,
extern __attribute__((weak)) void myFilter(Print * stream, byte & opcode, byte & paramCount, int16_t p[]);
FILTER_CALLBACK DCCEXParser::filterCallback = myFilter;
FILTER_CALLBACK DCCEXParser::filterRMFTCallback = 0;
FILTER_CALLBACK DCCEXParser::filterCamParserCallback = 0;
AT_COMMAND_CALLBACK DCCEXParser::atCommandCallback = 0;

// deprecated
Expand All @@ -249,6 +250,10 @@ void DCCEXParser::setRMFTFilter(FILTER_CALLBACK filter)
{
filterRMFTCallback = filter;
}
void DCCEXParser::setCamParserFilter(FILTER_CALLBACK filter)
{
filterCamParserCallback = filter;
}
void DCCEXParser::setAtCommandCallback(AT_COMMAND_CALLBACK callback)
{
atCommandCallback = callback;
Expand Down Expand Up @@ -304,6 +309,8 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
filterCallback(stream, opcode, params, p);
if (filterRMFTCallback && opcode!='\0')
filterRMFTCallback(stream, opcode, params, p);
if (filterCamParserCallback && opcode!='\0')
filterCamParserCallback(stream, opcode, params, p);

// Functions return from this switch if complete, break from switch implies error <X> to send
switch (opcode)
Expand Down Expand Up @@ -898,15 +905,11 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
if (parseI(stream, params, p))
return;
break;
#endif
#ifndef IO_NO_HAL
case 'N': // <N commands for SensorCam
if (CamParser::parseN(stream,params,p)) return;
break;
#endif
case '/': // implemented in EXRAIL parser
case 'L': // LCC interface implemented in EXRAIL parser
break; // Will <X> if not intercepted by EXRAIL
case 'N': // interface implemented in CamParser
break; // Will <X> if not intercepted by filters

#ifndef DISABLE_VDPY
case '@': // JMRI saying "give me virtual LCD msgs"
Expand Down
2 changes: 2 additions & 0 deletions DCCEXParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct DCCEXParser
static void parseOne(Print * stream, byte * command, RingStream * ringStream);
static void setFilter(FILTER_CALLBACK filter);
static void setRMFTFilter(FILTER_CALLBACK filter);
static void setCamParserFilter(FILTER_CALLBACK filter);
static void setAtCommandCallback(AT_COMMAND_CALLBACK filter);
static const int MAX_COMMAND_PARAMS=10; // Must not exceed this

Expand Down Expand Up @@ -77,6 +78,7 @@ struct DCCEXParser
static void callback_Vbyte(int16_t result);
static FILTER_CALLBACK filterCallback;
static FILTER_CALLBACK filterRMFTCallback;
static FILTER_CALLBACK filterCamParserCallback;
static AT_COMMAND_CALLBACK atCommandCallback;
static bool funcmap(int16_t cab, byte value, byte fstart, byte fstop);
static void sendFlashList(Print * stream,const int16_t flashList[]);
Expand Down
29 changes: 14 additions & 15 deletions IO_EXSensorCAM.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
* You should have received a copy of the GNU General Public License
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#define driverVer 305
#define driverVer 306
// v306 Pass vpin to regeister it in CamParser.
// Move base vpin to camparser.
// No more need for config.h settings.
// v305 less debug & alpha ordered switch
// v304 static oldb0; t(##[,%%];
// v303 zipped with CS 5.2.76 and uploaded to repo (with debug)
Expand All @@ -35,23 +38,18 @@
* This device driver will configure the device on startup, along with CamParser.cpp
* interacting with the sensorCAM device for all input/output duties.
*
* #include "CamParser.h" in DCCEXParser.cpp
* #include "IO_EXSensorCAM.h" in IODevice.h
* To create EX-SensorCAM devices, define them in myHal.cpp: with
* EXSensorCAM::create(baseVpin,num_vpins,i2c_address) or
* alternatively use HAL(EXSensorCAM baseVpin numpins i2c_address) in myAutomation.h
* also #define SENSORCAM_VPIN baseVpin in config.h
*
* void halSetup() {
* // EXSensorCAM::create(vpin, num_vpins, i2c_address);
* EXSensorCAM::create(700, 80, 0x11);
* }
* To create EX-SensorCAM devices,
* use HAL(EXSensorCAM, baseVpin, numpins, i2c_address) in myAutomation.h
* e.g.
* HAL(EXSensorCAM,700, 80, 0x11)
*
* or (deprecated) define them in myHal.cpp: with
* EXSensorCAM::create(baseVpin,num_vpins,i2c_address);
*
* I2C packet size of 32 bytes (in the Wire library).
*/
# define DIGITALREFRESH 20000UL // min uSec delay between digital reads of digitalInputStates
#ifndef IO_EX_EXSENSORCAM_H
#define IO_EX_EXSENSORCAM_H
#define DIGITALREFRESH 20000UL // min uSec delay between digital reads of digitalInputStates
#define SEND StringFormatter::send
#include "IODevice.h"
#include "I2CManager.h"
Expand All @@ -70,7 +68,7 @@ class EXSensorCAM : public IODevice {
new EXSensorCAM(vpin, nPins, i2cAddress);
}

static VPIN CAMBaseVpin;


private:
// Constructor
Expand All @@ -81,6 +79,7 @@ class EXSensorCAM : public IODevice {
_nPins = nPins;
_I2CAddress = i2cAddress;
addDevice(this);
CamParser::addVpin(firstVpin);
}
//*************************
void _begin() {
Expand Down
4 changes: 3 additions & 1 deletion version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include "StringFormatter.h"

#define VERSION "5.5.7"
#define VERSION "5.5.8"
// 5.5.8 - EXSensorCam clean up to match other filters and
// - avoid need for config.h settings
// 5.5.7 - ESP32 bugfix packet buffer race (as 5.4.1)
// 5.5.6 - Fix ESP32 build bug caused by include reference loop
// 5.5.5 - Railcom implementation with IO_I2CRailcom driver
Expand Down

0 comments on commit 95d90aa

Please sign in to comment.