1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-22 15:46:14 +01:00

Use aspect maps and add ability to use alternate light config (#422)

Idea to use a map to control the pins set for the different signal aspects,
instead of just straight RED->redpin, AMBER->amberpin, GREEN->greenpin. There
is a main map which does this and then an alternate map which may do anything.
In the example, we use red -> amber/green -> green, which is the Deutsche Bahn
signalling resolution (where physical signals are used rather than in-cab).

This rewrites the LED section of the RMFT2::doSignal(), making it use the
aspect map for even the features of merging red and green together for amber
and the high-is-off setting. It adds 2 new automations: SIGNALA and SIGNALAH
to allow the use of the alternate maps.
This commit is contained in:
Matthew Byng-Maddick 2024-10-01 16:43:09 +02:00
parent 4e491a1e56
commit 445bfe7ebb
5 changed files with 58 additions and 34 deletions

View File

@ -1074,37 +1074,41 @@ int16_t RMFT2::getSignalSlot(int16_t id) {
return;
}
if (sigtype== DCC_SIGNAL_FLAG) {
// redpin,amberpin are the DCC addr,subaddr
DCC::setAccessory(redpin,amberpin, rag!=SIGNAL_RED);
return;
}
// LED or similar 3 pin signal, (all pins zero would be a virtual signal)
// If amberpin is zero, synthesise amber from red+green
const byte SIMAMBER=0x00;
if (rag==SIGNAL_AMBER && (amberpin==0)) rag=SIMAMBER; // special case this func only
// Manage invert (HIGH on) pins
bool aHigh=sigid & ACTIVE_HIGH_SIGNAL_FLAG;
// set the three pins
if (redpin) {
bool redval=(rag==SIGNAL_RED || rag==SIMAMBER);
if (!aHigh) redval=!redval;
IODevice::write(redpin,redval);
}
if (amberpin) {
bool amberval=(rag==SIGNAL_AMBER);
if (!aHigh) amberval=!amberval;
IODevice::write(amberpin,amberval);
}
if (greenpin) {
bool greenval=(rag==SIGNAL_GREEN || rag==SIMAMBER);
if (!aHigh) greenval=!greenval;
IODevice::write(greenpin,greenval);
// we duck out early for a virtual signal
if (!(redpin | amberpin | greenpin)) return;
// at this point we have some kind of LED signal, so we're going to do everything by manipulation of the aspect map
int16_t aspect_map = (sigid & SIGNAL_USE_ALT_MAP_FLAG) ? SIGNAL_ALT_ASPECT : SIGNAL_MAIN_ASPECT;
// in the case of red and green available and amber not, synthesise SIGNAL_AMBER from red
// and green aspects, leaving the other bits of the aspect untouched
if (redpin && greenpin && !amberpin)
aspect_map = (aspect_map & 0707) | ((aspect_map & 0700) >> 3) | ((aspect_map & 07) << 3);
// invert the aspect map if HIGH is "off"
if (sigid & ACTIVE_HIGH_SIGNAL_FLAG)
aspect_map = 0777 - (aspect_map & 0777)
int8_t pin_map = 0;
switch (rag) {
case SIGNAL_RED:
pin_map = (aspect_map & 0700) >> 6; break;
case SIGNAL_AMBER:
pin_map = (aspect_map & 070) >> 3; break;
case SIGNAL_GREEN:
pin_map = aspect_map & 07; break;
}
if (redpin) IODevice::write(redpin, !!(pin_map & 04));
if (amberpin) IODevice::write(amberpin, !!(pin_map & 02));
if (greenpin) IODevice::write(greenpin, !!(pin_map & 01));
}
/* static */ bool RMFT2::isSignal(int16_t id,char rag) {

View File

@ -130,6 +130,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 const int16_t SIGNAL_USE_ALT_MAP_FLAG=0x8000;
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;

View File

@ -130,17 +130,19 @@
#undef SERVO_SIGNAL
#undef SET
#undef SET_TRACK
#undef SETLOCO
#undef SIGNAL
#undef SIGNALH
#undef SPEED
#undef START
#undef STOP
#undef THROW
#undef TURNOUT
#undef SETLOCO
#undef SIGNAL
#undef SIGNALH
#undef SIGNALA
#undef SIGNALAH
#undef SPEED
#undef START
#undef STOP
#undef THROW
#undef TURNOUT
#undef TURNOUTL
#undef UNJOIN
#undef UNLATCH
#undef UNLATCH
#undef VIRTUAL_SIGNAL
#undef VIRTUAL_TURNOUT
#undef WAITFOR

View File

@ -234,6 +234,11 @@ const FSH * RMFT2::getRosterFunctions(int16_t id) {
#define SIGNAL(redpin,amberpin,greenpin) redpin,redpin,amberpin,greenpin,
#undef SIGNALH
#define SIGNALH(redpin,amberpin,greenpin) redpin | RMFT2::ACTIVE_HIGH_SIGNAL_FLAG,redpin,amberpin,greenpin,
#undef SIGNALA
#define SIGNALA(redpin,amberpin,greenpin) redpin | RMFT2::SIGNAL_USE_ALT_MAP_FLAG,redpin,amberpin,greenpin,
#undef SIGNALAH
#define SIGNALAH(redpin,amberpin,greenpin) redpin | RMFT2::ACTIVE_HIGH_SIGNAL_FLAG | RMFT2::SIGNAL_USE_ALT_MAP_FLAG, \
redpin,amberpin,greenpin,
#undef SERVO_SIGNAL
#define SERVO_SIGNAL(vpin,redval,amberval,greenval) vpin | RMFT2::SERVO_SIGNAL_FLAG,redval,amberval,greenval,
#undef DCC_SIGNAL

View File

@ -261,7 +261,7 @@ The configuration file for DCC-EX Command Station
// 2. The app will be bigger that 1.2MB, so the default partition scheme will not
// work any more. You need to choose a partition scheme with 2MB (or bigger).
// For example "NO OTA (2MB APP, 2MB SPIFFS)" in the Arduino IDE.
// 3. There is no securuity (PIN) implemented. Everyone in radio range can pair
// 3. There is no security (PIN) implemented. Everyone in radio range can pair
// with your CS.
//
//#define SERIAL_BT_COMMANDS
@ -278,3 +278,15 @@ The configuration file for DCC-EX Command Station
//#define SABERTOOTH 1
/////////////////////////////////////////////////////////////////////////////////////
// don't change this, this defines the main aspect as RED -> red pin, AMBER -> amber
// pin, and GREEN -> green pin
// these are octal int16_t types defining aspect and pin map:
// -----------N/A----------- ---RED--- --AMBER-- --GREEN--
// r a g r a g r a g
// | f | e | d | c | b | a | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
//
#define SIGNAL_MAIN_ASPECT 0421
// this defines an alternate aspect (eg. here, the Deutsche Bahn RED -> red pin,
// AMBER -> amber pin and green pin, GREEN -> green pin)
// These can be selected with the SIGNALA and SIGNALAH automations in myAutomation.h
#define SIGNAL_ALT_ASPECT 0431