mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-25 13:41:23 +01:00
Merge branch 'EX-RAIL' into EX-RAIL-neil-RCN213
This commit is contained in:
commit
77d4d7c400
@ -109,7 +109,7 @@ void setup()
|
|||||||
LCN::init(LCN_SERIAL);
|
LCN::init(LCN_SERIAL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LCD(1,F("Ready"));
|
LCD(3,F("Ready"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
@ -149,6 +149,6 @@ void loop()
|
|||||||
if (freeNow < ramLowWatermark)
|
if (freeNow < ramLowWatermark)
|
||||||
{
|
{
|
||||||
ramLowWatermark = freeNow;
|
ramLowWatermark = freeNow;
|
||||||
LCD(2,F("Free RAM=%5db"), ramLowWatermark);
|
LCD(3,F("Free RAM=%5db"), ramLowWatermark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
DCC.cpp
15
DCC.cpp
@ -683,9 +683,13 @@ int DCC::nextLoco = 0;
|
|||||||
|
|
||||||
//ACK MANAGER
|
//ACK MANAGER
|
||||||
ackOp const * DCC::ackManagerProg;
|
ackOp const * DCC::ackManagerProg;
|
||||||
|
ackOp const * DCC::ackManagerProgStart;
|
||||||
byte DCC::ackManagerByte;
|
byte DCC::ackManagerByte;
|
||||||
byte DCC::ackManagerStash;
|
byte DCC::ackManagerStash;
|
||||||
int DCC::ackManagerWord;
|
int DCC::ackManagerWord;
|
||||||
|
byte DCC::ackManagerRetry;
|
||||||
|
byte DCC::ackRetry = 2;
|
||||||
|
int16_t DCC::ackRetrySum;
|
||||||
int DCC::ackManagerCv;
|
int DCC::ackManagerCv;
|
||||||
byte DCC::ackManagerBitNum;
|
byte DCC::ackManagerBitNum;
|
||||||
bool DCC::ackReceived;
|
bool DCC::ackReceived;
|
||||||
@ -718,6 +722,8 @@ void DCC::ackManagerSetup(int cv, byte byteValueOrBitnum, ackOp const program[]
|
|||||||
|
|
||||||
ackManagerCv = cv;
|
ackManagerCv = cv;
|
||||||
ackManagerProg = program;
|
ackManagerProg = program;
|
||||||
|
ackManagerProgStart = program;
|
||||||
|
ackManagerRetry = ackRetry;
|
||||||
ackManagerByte = byteValueOrBitnum;
|
ackManagerByte = byteValueOrBitnum;
|
||||||
ackManagerBitNum=byteValueOrBitnum;
|
ackManagerBitNum=byteValueOrBitnum;
|
||||||
ackManagerCallback = callback;
|
ackManagerCallback = callback;
|
||||||
@ -901,6 +907,15 @@ void DCC::ackManagerLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DCC::callback(int value) {
|
void DCC::callback(int value) {
|
||||||
|
// check for automatic retry
|
||||||
|
if (value == -1 && ackManagerRetry > 0) {
|
||||||
|
ackRetrySum ++;
|
||||||
|
LCD(0, F("RETRY %d %d %d %d"), ackManagerCv, ackManagerRetry, ackRetry, ackRetrySum);
|
||||||
|
ackManagerRetry --;
|
||||||
|
ackManagerProg = ackManagerProgStart;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long callbackStart;
|
static unsigned long callbackStart;
|
||||||
// We are about to leave programming mode
|
// We are about to leave programming mode
|
||||||
// Rule 1: If we have written to a decoder we must maintain power for 100mS
|
// Rule 1: If we have written to a decoder we must maintain power for 100mS
|
||||||
|
12
DCC.h
12
DCC.h
@ -64,8 +64,10 @@ enum CALLBACK_STATE : byte {
|
|||||||
|
|
||||||
// Allocations with memory implications..!
|
// Allocations with memory implications..!
|
||||||
// Base system takes approx 900 bytes + 8 per loco. Turnouts, Sensors etc are dynamically created
|
// Base system takes approx 900 bytes + 8 per loco. Turnouts, Sensors etc are dynamically created
|
||||||
#ifdef ARDUINO_AVR_UNO
|
#if defined(ARDUINO_AVR_UNO)
|
||||||
const byte MAX_LOCOS = 20;
|
const byte MAX_LOCOS = 20;
|
||||||
|
#elif defined(ARDUINO_AVR_NANO)
|
||||||
|
const byte MAX_LOCOS = 30;
|
||||||
#else
|
#else
|
||||||
const byte MAX_LOCOS = 50;
|
const byte MAX_LOCOS = 50;
|
||||||
#endif
|
#endif
|
||||||
@ -113,6 +115,10 @@ public:
|
|||||||
static inline void setGlobalSpeedsteps(byte s) {
|
static inline void setGlobalSpeedsteps(byte s) {
|
||||||
globalSpeedsteps = s;
|
globalSpeedsteps = s;
|
||||||
};
|
};
|
||||||
|
static inline void setAckRetry(byte retry) {
|
||||||
|
ackRetry = retry;
|
||||||
|
ackRetrySum = 0; // reset running total
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct LOCO
|
struct LOCO
|
||||||
@ -141,9 +147,13 @@ private:
|
|||||||
|
|
||||||
// ACK MANAGER
|
// ACK MANAGER
|
||||||
static ackOp const *ackManagerProg;
|
static ackOp const *ackManagerProg;
|
||||||
|
static ackOp const *ackManagerProgStart;
|
||||||
static byte ackManagerByte;
|
static byte ackManagerByte;
|
||||||
static byte ackManagerBitNum;
|
static byte ackManagerBitNum;
|
||||||
static int ackManagerCv;
|
static int ackManagerCv;
|
||||||
|
static byte ackManagerRetry;
|
||||||
|
static byte ackRetry;
|
||||||
|
static int16_t ackRetrySum;
|
||||||
static int ackManagerWord;
|
static int ackManagerWord;
|
||||||
static byte ackManagerStash;
|
static byte ackManagerStash;
|
||||||
static bool ackReceived;
|
static bool ackReceived;
|
||||||
|
@ -32,6 +32,16 @@
|
|||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include <avr/wdt.h>
|
#include <avr/wdt.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Figure out if we have enough memory for advanced features
|
||||||
|
//
|
||||||
|
#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO)
|
||||||
|
// nope
|
||||||
|
#else
|
||||||
|
#define HAS_ENOUGH_MEMORY
|
||||||
|
#endif
|
||||||
|
|
||||||
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
|
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
|
||||||
// To discover new keyword numbers , use the <$ YOURKEYWORD> command
|
// To discover new keyword numbers , use the <$ YOURKEYWORD> command
|
||||||
const int16_t HASH_KEYWORD_PROG = -29718;
|
const int16_t HASH_KEYWORD_PROG = -29718;
|
||||||
@ -40,8 +50,6 @@ const int16_t HASH_KEYWORD_JOIN = -30750;
|
|||||||
const int16_t HASH_KEYWORD_CABS = -11981;
|
const int16_t HASH_KEYWORD_CABS = -11981;
|
||||||
const int16_t HASH_KEYWORD_RAM = 25982;
|
const int16_t HASH_KEYWORD_RAM = 25982;
|
||||||
const int16_t HASH_KEYWORD_CMD = 9962;
|
const int16_t HASH_KEYWORD_CMD = 9962;
|
||||||
const int16_t HASH_KEYWORD_WIT = 31594;
|
|
||||||
const int16_t HASH_KEYWORD_WIFI = -5583;
|
|
||||||
const int16_t HASH_KEYWORD_ACK = 3113;
|
const int16_t HASH_KEYWORD_ACK = 3113;
|
||||||
const int16_t HASH_KEYWORD_ON = 2657;
|
const int16_t HASH_KEYWORD_ON = 2657;
|
||||||
const int16_t HASH_KEYWORD_DCC = 6436;
|
const int16_t HASH_KEYWORD_DCC = 6436;
|
||||||
@ -49,17 +57,22 @@ const int16_t HASH_KEYWORD_SLOW = -17209;
|
|||||||
const int16_t HASH_KEYWORD_PROGBOOST = -6353;
|
const int16_t HASH_KEYWORD_PROGBOOST = -6353;
|
||||||
const int16_t HASH_KEYWORD_EEPROM = -7168;
|
const int16_t HASH_KEYWORD_EEPROM = -7168;
|
||||||
const int16_t HASH_KEYWORD_LIMIT = 27413;
|
const int16_t HASH_KEYWORD_LIMIT = 27413;
|
||||||
const int16_t HASH_KEYWORD_ETHERNET = -30767;
|
|
||||||
const int16_t HASH_KEYWORD_MAX = 16244;
|
const int16_t HASH_KEYWORD_MAX = 16244;
|
||||||
const int16_t HASH_KEYWORD_MIN = 15978;
|
const int16_t HASH_KEYWORD_MIN = 15978;
|
||||||
const int16_t HASH_KEYWORD_LCN = 15137;
|
|
||||||
const int16_t HASH_KEYWORD_RESET = 26133;
|
const int16_t HASH_KEYWORD_RESET = 26133;
|
||||||
|
const int16_t HASH_KEYWORD_RETRY = 25704;
|
||||||
const int16_t HASH_KEYWORD_SPEED28 = -17064;
|
const int16_t HASH_KEYWORD_SPEED28 = -17064;
|
||||||
const int16_t HASH_KEYWORD_SPEED128 = 25816;
|
const int16_t HASH_KEYWORD_SPEED128 = 25816;
|
||||||
const int16_t HASH_KEYWORD_SERVO=27709;
|
const int16_t HASH_KEYWORD_SERVO=27709;
|
||||||
const int16_t HASH_KEYWORD_VPIN=-415;
|
const int16_t HASH_KEYWORD_VPIN=-415;
|
||||||
const int16_t HASH_KEYWORD_C=67;
|
const int16_t HASH_KEYWORD_C=67;
|
||||||
const int16_t HASH_KEYWORD_T=84;
|
const int16_t HASH_KEYWORD_T=84;
|
||||||
|
const int16_t HASH_KEYWORD_LCN = 15137;
|
||||||
|
#ifdef HAS_ENOUGH_MEMORY
|
||||||
|
const int16_t HASH_KEYWORD_WIFI = -5583;
|
||||||
|
const int16_t HASH_KEYWORD_ETHERNET = -30767;
|
||||||
|
const int16_t HASH_KEYWORD_WIT = 31594;
|
||||||
|
#endif
|
||||||
|
|
||||||
int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS];
|
int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS];
|
||||||
bool DCCEXParser::stashBusy;
|
bool DCCEXParser::stashBusy;
|
||||||
@ -257,6 +270,7 @@ void DCCEXParser::parse(const FSH * cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See documentation on DCC class for info on this section
|
// See documentation on DCC class for info on this section
|
||||||
|
|
||||||
void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
||||||
{
|
{
|
||||||
(void)EEPROM; // tell compiler not to warn this is unused
|
(void)EEPROM; // tell compiler not to warn this is unused
|
||||||
@ -455,6 +469,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
if (mode == POWERMODE::OFF)
|
if (mode == POWERMODE::OFF)
|
||||||
DCC::setProgTrackBoost(false); // Prog track boost mode will not outlive prog track off
|
DCC::setProgTrackBoost(false); // Prog track boost mode will not outlive prog track off
|
||||||
StringFormatter::send(stream, F("<p%c>\n"), opcode);
|
StringFormatter::send(stream, F("<p%c>\n"), opcode);
|
||||||
|
LCD(2, F("p%c"), opcode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (p[0])
|
switch (p[0])
|
||||||
@ -462,6 +477,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
case HASH_KEYWORD_MAIN:
|
case HASH_KEYWORD_MAIN:
|
||||||
DCCWaveform::mainTrack.setPowerMode(mode);
|
DCCWaveform::mainTrack.setPowerMode(mode);
|
||||||
StringFormatter::send(stream, F("<p%c MAIN>\n"), opcode);
|
StringFormatter::send(stream, F("<p%c MAIN>\n"), opcode);
|
||||||
|
LCD(2, F("p%c MAIN"), opcode);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case HASH_KEYWORD_PROG:
|
case HASH_KEYWORD_PROG:
|
||||||
@ -469,6 +485,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
if (mode == POWERMODE::OFF)
|
if (mode == POWERMODE::OFF)
|
||||||
DCC::setProgTrackBoost(false); // Prog track boost mode will not outlive prog track off
|
DCC::setProgTrackBoost(false); // Prog track boost mode will not outlive prog track off
|
||||||
StringFormatter::send(stream, F("<p%c PROG>\n"), opcode);
|
StringFormatter::send(stream, F("<p%c PROG>\n"), opcode);
|
||||||
|
LCD(2, F("p%c PROG"), opcode);
|
||||||
return;
|
return;
|
||||||
case HASH_KEYWORD_JOIN:
|
case HASH_KEYWORD_JOIN:
|
||||||
DCCWaveform::mainTrack.setPowerMode(mode);
|
DCCWaveform::mainTrack.setPowerMode(mode);
|
||||||
@ -477,9 +494,13 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
{
|
{
|
||||||
DCC::setProgTrackSyncMain(true);
|
DCC::setProgTrackSyncMain(true);
|
||||||
StringFormatter::send(stream, F("<p1 JOIN>\n"), opcode);
|
StringFormatter::send(stream, F("<p1 JOIN>\n"), opcode);
|
||||||
|
LCD(2, F("p1 JOIN"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
StringFormatter::send(stream, F("<p0>\n"));
|
StringFormatter::send(stream, F("<p0>\n"));
|
||||||
|
LCD(2, F("p0"));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -779,17 +800,21 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
|||||||
StringFormatter::send(stream, F("Free memory=%d\n"), minimumFreeMemory());
|
StringFormatter::send(stream, F("Free memory=%d\n"), minimumFreeMemory());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HASH_KEYWORD_ACK: // <D ACK ON/OFF> <D ACK [LIMIT|MIN|MAX] Value>
|
case HASH_KEYWORD_ACK: // <D ACK ON/OFF> <D ACK [LIMIT|MIN|MAX|RETRY] Value>
|
||||||
if (params >= 3) {
|
if (params >= 3) {
|
||||||
if (p[1] == HASH_KEYWORD_LIMIT) {
|
if (p[1] == HASH_KEYWORD_LIMIT) {
|
||||||
DCCWaveform::progTrack.setAckLimit(p[2]);
|
DCCWaveform::progTrack.setAckLimit(p[2]);
|
||||||
StringFormatter::send(stream, F("Ack limit=%dmA\n"), p[2]);
|
LCD(1, F("Ack Limit=%dmA"), p[2]); // <D ACK LIMIT 42>
|
||||||
} else if (p[1] == HASH_KEYWORD_MIN) {
|
} else if (p[1] == HASH_KEYWORD_MIN) {
|
||||||
DCCWaveform::progTrack.setMinAckPulseDuration(p[2]);
|
DCCWaveform::progTrack.setMinAckPulseDuration(p[2]);
|
||||||
StringFormatter::send(stream, F("Ack min=%dus\n"), p[2]);
|
LCD(0, F("Ack Min=%dus"), p[2]); // <D ACK MIN 1500>
|
||||||
} else if (p[1] == HASH_KEYWORD_MAX) {
|
} else if (p[1] == HASH_KEYWORD_MAX) {
|
||||||
DCCWaveform::progTrack.setMaxAckPulseDuration(p[2]);
|
DCCWaveform::progTrack.setMaxAckPulseDuration(p[2]);
|
||||||
StringFormatter::send(stream, F("Ack max=%dus\n"), p[2]);
|
LCD(0, F("Ack Max=%dus"), p[2]); // <D ACK MAX 9000>
|
||||||
|
} else if (p[1] == HASH_KEYWORD_RETRY) {
|
||||||
|
if (p[2] >255) p[2]=3;
|
||||||
|
DCC::setAckRetry(p[2]);
|
||||||
|
LCD(0, F("Ack Retry=%d"), p[2]); // <D ACK RETRY 2>
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
StringFormatter::send(stream, F("Ack diag %S\n"), onOff ? F("on") : F("off"));
|
StringFormatter::send(stream, F("Ack diag %S\n"), onOff ? F("on") : F("off"));
|
||||||
@ -801,6 +826,7 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
|||||||
Diag::CMD = onOff;
|
Diag::CMD = onOff;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
#ifdef HAS_ENOUGH_MEMORY
|
||||||
case HASH_KEYWORD_WIFI: // <D WIFI ON/OFF>
|
case HASH_KEYWORD_WIFI: // <D WIFI ON/OFF>
|
||||||
Diag::WIFI = onOff;
|
Diag::WIFI = onOff;
|
||||||
return true;
|
return true;
|
||||||
@ -816,6 +842,7 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
|||||||
case HASH_KEYWORD_LCN: // <D LCN ON/OFF>
|
case HASH_KEYWORD_LCN: // <D LCN ON/OFF>
|
||||||
Diag::LCN = onOff;
|
Diag::LCN = onOff;
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
case HASH_KEYWORD_PROGBOOST:
|
case HASH_KEYWORD_PROGBOOST:
|
||||||
DCC::setProgTrackBoost(true);
|
DCC::setProgTrackBoost(true);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma GCC optimize ("-O3")
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "DCCWaveform.h"
|
#include "DCCWaveform.h"
|
||||||
@ -46,10 +46,8 @@ void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) {
|
|||||||
&& (mainDriver->getFaultPin() != UNUSED_PIN));
|
&& (mainDriver->getFaultPin() != UNUSED_PIN));
|
||||||
// Only use PWM if both pins are PWM capable. Otherwise JOIN does not work
|
// Only use PWM if both pins are PWM capable. Otherwise JOIN does not work
|
||||||
MotorDriver::usePWM= mainDriver->isPWMCapable() && progDriver->isPWMCapable();
|
MotorDriver::usePWM= mainDriver->isPWMCapable() && progDriver->isPWMCapable();
|
||||||
if (MotorDriver::usePWM)
|
DIAG(F("Signal pin config: %S accuracy waveform"),
|
||||||
DIAG(F("Signal pin config: high accuracy waveform"));
|
MotorDriver::usePWM ? F("high") : F("normal") );
|
||||||
else
|
|
||||||
DIAG(F("Signal pin config: normal accuracy waveform"));
|
|
||||||
DCCTimer::begin(DCCWaveform::interruptHandler);
|
DCCTimer::begin(DCCWaveform::interruptHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,6 +56,8 @@ void DCCWaveform::loop(bool ackManagerActive) {
|
|||||||
progTrack.checkPowerOverload(ackManagerActive);
|
progTrack.checkPowerOverload(ackManagerActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize ("-O3")
|
||||||
void DCCWaveform::interruptHandler() {
|
void DCCWaveform::interruptHandler() {
|
||||||
// call the timer edge sensitive actions for progtrack and maintrack
|
// call the timer edge sensitive actions for progtrack and maintrack
|
||||||
// member functions would be cleaner but have more overhead
|
// member functions would be cleaner but have more overhead
|
||||||
@ -79,7 +79,7 @@ void DCCWaveform::interruptHandler() {
|
|||||||
else if (progTrack.ackPending) progTrack.checkAck();
|
else if (progTrack.ackPending) progTrack.checkAck();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#pragma GCC push_options
|
||||||
|
|
||||||
// An instance of this class handles the DCC transmissions for one track. (main or prog)
|
// An instance of this class handles the DCC transmissions for one track. (main or prog)
|
||||||
// Interrupts are marshalled via the statics.
|
// Interrupts are marshalled via the statics.
|
||||||
@ -124,6 +124,8 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) {
|
|||||||
if (!isMainTrack && !ackManagerActive && !progTrackSyncMain && !progTrackBoosted)
|
if (!isMainTrack && !ackManagerActive && !progTrackSyncMain && !progTrackBoosted)
|
||||||
tripValue=progTripValue;
|
tripValue=progTripValue;
|
||||||
|
|
||||||
|
// Trackname for diag messages later
|
||||||
|
const FSH*trackname = isMainTrack ? F("MAIN") : F("PROG");
|
||||||
switch (powerMode) {
|
switch (powerMode) {
|
||||||
case POWERMODE::OFF:
|
case POWERMODE::OFF:
|
||||||
sampleDelay = POWER_SAMPLE_OFF_WAIT;
|
sampleDelay = POWER_SAMPLE_OFF_WAIT;
|
||||||
@ -141,9 +143,9 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) {
|
|||||||
}
|
}
|
||||||
// Write this after the fact as we want to turn on as fast as possible
|
// Write this after the fact as we want to turn on as fast as possible
|
||||||
// because we don't know which output actually triggered the fault pin
|
// because we don't know which output actually triggered the fault pin
|
||||||
DIAG(F("*** COMMON FAULT PIN ACTIVE - TOGGLED POWER on %S ***"), isMainTrack ? F("MAIN") : F("PROG"));
|
DIAG(F("COMMON FAULT PIN ACTIVE - TOGGLED POWER on %S"), trackname);
|
||||||
} else {
|
} else {
|
||||||
DIAG(F("*** %S FAULT PIN ACTIVE - OVERLOAD ***"), isMainTrack ? F("MAIN") : F("PROG"));
|
DIAG(F("%S FAULT PIN ACTIVE - OVERLOAD"), trackname);
|
||||||
if (lastCurrent < tripValue) {
|
if (lastCurrent < tripValue) {
|
||||||
lastCurrent = tripValue; // exaggerate
|
lastCurrent = tripValue; // exaggerate
|
||||||
}
|
}
|
||||||
@ -161,7 +163,7 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) {
|
|||||||
unsigned int maxmA=motorDriver->raw2mA(tripValue);
|
unsigned int maxmA=motorDriver->raw2mA(tripValue);
|
||||||
power_good_counter=0;
|
power_good_counter=0;
|
||||||
sampleDelay = power_sample_overload_wait;
|
sampleDelay = power_sample_overload_wait;
|
||||||
DIAG(F("*** %S TRACK POWER OVERLOAD current=%d max=%d offtime=%d ***"), isMainTrack ? F("MAIN") : F("PROG"), mA, maxmA, sampleDelay);
|
DIAG(F("%S TRACK POWER OVERLOAD current=%d max=%d offtime=%d"), trackname, mA, maxmA, sampleDelay);
|
||||||
if (power_sample_overload_wait >= 10000)
|
if (power_sample_overload_wait >= 10000)
|
||||||
power_sample_overload_wait = 10000;
|
power_sample_overload_wait = 10000;
|
||||||
else
|
else
|
||||||
@ -173,7 +175,7 @@ void DCCWaveform::checkPowerOverload(bool ackManagerActive) {
|
|||||||
setPowerMode(POWERMODE::ON);
|
setPowerMode(POWERMODE::ON);
|
||||||
sampleDelay = POWER_SAMPLE_ON_WAIT;
|
sampleDelay = POWER_SAMPLE_ON_WAIT;
|
||||||
// Debug code....
|
// Debug code....
|
||||||
DIAG(F("*** %S TRACK POWER RESET delay=%d ***"), isMainTrack ? F("MAIN") : F("PROG"), sampleDelay);
|
DIAG(F("%S TRACK POWER RESET delay=%d"), trackname, sampleDelay);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sampleDelay = 999; // cant get here..meaningless statement to avoid compiler warning.
|
sampleDelay = 999; // cant get here..meaningless statement to avoid compiler warning.
|
||||||
@ -197,6 +199,8 @@ const bool DCCWaveform::signalTransform[]={
|
|||||||
/* WAVE_LOW_0 -> */ LOW,
|
/* WAVE_LOW_0 -> */ LOW,
|
||||||
/* WAVE_PENDING (should not happen) -> */ LOW};
|
/* WAVE_PENDING (should not happen) -> */ LOW};
|
||||||
|
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize ("-O3")
|
||||||
void DCCWaveform::interrupt2() {
|
void DCCWaveform::interrupt2() {
|
||||||
// calculate the next bit to be sent:
|
// calculate the next bit to be sent:
|
||||||
// set state WAVE_MID_1 for a 1=bit
|
// set state WAVE_MID_1 for a 1=bit
|
||||||
@ -252,7 +256,7 @@ void DCCWaveform::interrupt2() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma GCC pop_options
|
||||||
|
|
||||||
|
|
||||||
// Wait until there is no packet pending, then make this pending
|
// Wait until there is no packet pending, then make this pending
|
||||||
@ -306,6 +310,8 @@ byte DCCWaveform::getAck() {
|
|||||||
return(0); // pending set off but not detected means no ACK.
|
return(0); // pending set off but not detected means no ACK.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma GCC push_options
|
||||||
|
#pragma GCC optimize ("-O3")
|
||||||
void DCCWaveform::checkAck() {
|
void DCCWaveform::checkAck() {
|
||||||
// This function operates in interrupt() time so must be fast and can't DIAG
|
// This function operates in interrupt() time so must be fast and can't DIAG
|
||||||
if (sentResetsSincePacket > 6) { //ACK timeout
|
if (sentResetsSincePacket > 6) { //ACK timeout
|
||||||
@ -355,3 +361,4 @@ void DCCWaveform::checkAck() {
|
|||||||
}
|
}
|
||||||
ackPulseStart=0; // We have detected a too-short or too-long pulse so ignore and wait for next leading edge
|
ackPulseStart=0; // We have detected a too-short or too-long pulse so ignore and wait for next leading edge
|
||||||
}
|
}
|
||||||
|
#pragma GCC pop_options
|
||||||
|
@ -17,12 +17,6 @@
|
|||||||
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#if __has_include ( "config.h")
|
|
||||||
#include "config.h"
|
|
||||||
#else
|
|
||||||
#warning config.h not found. Using defaults from config.example.h
|
|
||||||
#include "config.example.h"
|
|
||||||
#endif
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#if ETHERNET_ON == true
|
#if ETHERNET_ON == true
|
||||||
#include "EthernetInterface.h"
|
#include "EthernetInterface.h"
|
||||||
|
@ -22,12 +22,8 @@
|
|||||||
|
|
||||||
#ifndef EthernetInterface_h
|
#ifndef EthernetInterface_h
|
||||||
#define EthernetInterface_h
|
#define EthernetInterface_h
|
||||||
#if __has_include ( "config.h")
|
|
||||||
#include "config.h"
|
#include "defines.h")
|
||||||
#else
|
|
||||||
#warning config.h not found. Using defaults from config.example.h
|
|
||||||
#include "config.example.h"
|
|
||||||
#endif
|
|
||||||
#include "DCCEXParser.h"
|
#include "DCCEXParser.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
@ -19,10 +19,9 @@
|
|||||||
#ifndef LCDDisplay_h
|
#ifndef LCDDisplay_h
|
||||||
#define LCDDisplay_h
|
#define LCDDisplay_h
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include "defines.h"
|
||||||
#include "DisplayInterface.h"
|
#include "DisplayInterface.h"
|
||||||
|
|
||||||
#include "defines.h" // includes config.h as well
|
|
||||||
|
|
||||||
// Allow maximum message length to be overridden from config.h
|
// Allow maximum message length to be overridden from config.h
|
||||||
#if !defined(MAX_MSG_SIZE)
|
#if !defined(MAX_MSG_SIZE)
|
||||||
#define MAX_MSG_SIZE 20
|
#define MAX_MSG_SIZE 20
|
||||||
|
@ -36,6 +36,7 @@ const int16_t HASH_KEYWORD_UNLATCH=1353;
|
|||||||
const int16_t HASH_KEYWORD_PAUSE=-4142;
|
const int16_t HASH_KEYWORD_PAUSE=-4142;
|
||||||
const int16_t HASH_KEYWORD_RESUME=27609;
|
const int16_t HASH_KEYWORD_RESUME=27609;
|
||||||
const int16_t HASH_KEYWORD_KILL=5218;
|
const int16_t HASH_KEYWORD_KILL=5218;
|
||||||
|
const int16_t HASH_KEYWORD_ROUTES=-3702;
|
||||||
|
|
||||||
// One instance of RMFT clas is used for each "thread" in the automation.
|
// One instance of RMFT clas is used for each "thread" in the automation.
|
||||||
// Each thread manages a loco on a journey through the layout, and/or may manage a scenery automation.
|
// Each thread manages a loco on a journey through the layout, and/or may manage a scenery automation.
|
||||||
@ -193,6 +194,13 @@ bool RMFT2::parseSlash(Print * stream, byte & paramCount, int16_t p[]) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case HASH_KEYWORD_ROUTES: // </ ROUTES > JMRI withrottle support
|
||||||
|
if (paramCount>1) return false;
|
||||||
|
StringFormatter::send(stream,F("</ROUTES "));
|
||||||
|
emitWithrottleRouteList(stream);
|
||||||
|
StringFormatter::send(stream,F(">"));
|
||||||
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,8 @@ void Sensor::load(){
|
|||||||
struct SensorData data;
|
struct SensorData data;
|
||||||
Sensor *tt;
|
Sensor *tt;
|
||||||
|
|
||||||
for(uint16_t i=0;i<EEStore::eeStore->data.nSensors;i++){
|
uint16_t i=EEStore::eeStore->data.nSensors;
|
||||||
|
while(i--){
|
||||||
EEPROM.get(EEStore::pointer(),data);
|
EEPROM.get(EEStore::pointer(),data);
|
||||||
tt=create(data.snum, data.pin, data.pullUp);
|
tt=create(data.snum, data.pin, data.pullUp);
|
||||||
EEStore::advance(sizeof(tt->data));
|
EEStore::advance(sizeof(tt->data));
|
||||||
|
@ -22,10 +22,13 @@
|
|||||||
#define DEFINES_H
|
#define DEFINES_H
|
||||||
|
|
||||||
// defines.h relies on macros defined in config.h
|
// defines.h relies on macros defined in config.h
|
||||||
#if __has_include ( "config.h")
|
// but it may have already been included (for cosmetic convenence) by the .ino
|
||||||
|
#ifndef MOTOR_SHIELD_TYPE
|
||||||
|
#if __has_include ( "config.h")
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#else
|
#else
|
||||||
#include "config.example.h"
|
#include "config.example.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user