mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-26 17:46:14 +01:00
dual momentum
This commit is contained in:
parent
3ac2fff70d
commit
2d58d06b19
56
DCC.cpp
56
DCC.cpp
|
@ -74,20 +74,28 @@ void DCC::begin() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t DCC::defaultMomentum=0;
|
byte DCC::defaultMomentumA=0;
|
||||||
|
byte DCC::defaultMomentumD=0;
|
||||||
|
|
||||||
|
byte DCC::getMomentum(LOCO * slot) {
|
||||||
|
if ((slot->targetSpeed & 0x7f) > (slot->speedCode & 0x7f)) // accelerate
|
||||||
|
return slot->momentumA==MOMENTUM_USE_DEFAULT ? defaultMomentumA : slot->momentumA;
|
||||||
|
return slot->momentumD==MOMENTUM_USE_DEFAULT ? defaultMomentumD : slot->momentumD;
|
||||||
|
}
|
||||||
|
|
||||||
void DCC::setThrottle( uint16_t cab, uint8_t tSpeed, bool tDirection) {
|
void DCC::setThrottle( uint16_t cab, uint8_t tSpeed, bool tDirection) {
|
||||||
|
if (tSpeed==1) {
|
||||||
if (cab==0) {
|
if (cab==0) {
|
||||||
if (tSpeed==1) estopAll(); // ESTOP broadcast fix
|
estopAll(); // ESTOP broadcast fix
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
byte speedCode = (tSpeed & 0x7F) + tDirection * 128;
|
byte speedCode = (tSpeed & 0x7F) + tDirection * 128;
|
||||||
LOCO * slot=lookupSpeedTable(cab);
|
LOCO * slot=lookupSpeedTable(cab);
|
||||||
if (slot->targetSpeed==speedCode) return;
|
if (slot->targetSpeed==speedCode) return;
|
||||||
slot->targetSpeed=speedCode;
|
slot->targetSpeed=speedCode;
|
||||||
auto momentum=slot->millis_per_notch;
|
byte momentum=getMomentum(slot);;
|
||||||
if (momentum<0) momentum=defaultMomentum;
|
if (momentum && tSpeed!=1) { // not ESTOP
|
||||||
if (momentum>0 && tSpeed!=1) { // not ESTOP
|
|
||||||
// we dont throttle speed, we just let the reminders take it to target
|
// we dont throttle speed, we just let the reminders take it to target
|
||||||
slot->momentum_base=millis();
|
slot->momentum_base=millis();
|
||||||
}
|
}
|
||||||
|
@ -813,8 +821,7 @@ bool DCC::issueReminder(LOCO * slot) {
|
||||||
// calculate new speed code
|
// calculate new speed code
|
||||||
auto now=millis();
|
auto now=millis();
|
||||||
int16_t delay=now-slot->momentum_base;
|
int16_t delay=now-slot->momentum_base;
|
||||||
auto millisPerNotch=slot->millis_per_notch;
|
auto millisPerNotch=MOMENTUM_FACTOR * (int16_t)getMomentum(slot);
|
||||||
if (millisPerNotch<0) millisPerNotch=defaultMomentum;
|
|
||||||
// allow for momentum change to 0 while accelerating/slowing
|
// allow for momentum change to 0 while accelerating/slowing
|
||||||
auto ticks=(millisPerNotch>0)?(delay/millisPerNotch):500;
|
auto ticks=(millisPerNotch>0)?(delay/millisPerNotch):500;
|
||||||
if (ticks>0) {
|
if (ticks>0) {
|
||||||
|
@ -920,20 +927,29 @@ DCC::LOCO * DCC::lookupSpeedTable(int locoId, bool autoCreate) {
|
||||||
firstEmpty->targetSpeed=128; // default direction forward
|
firstEmpty->targetSpeed=128; // default direction forward
|
||||||
firstEmpty->groupFlags=0;
|
firstEmpty->groupFlags=0;
|
||||||
firstEmpty->functions=0;
|
firstEmpty->functions=0;
|
||||||
firstEmpty->millis_per_notch=-1; // use default
|
firstEmpty->momentumA=MOMENTUM_USE_DEFAULT;
|
||||||
|
firstEmpty->momentumD=MOMENTUM_USE_DEFAULT;
|
||||||
return firstEmpty;
|
return firstEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DCC::setMomentum(int locoId,int16_t millis_per_notch) {
|
bool DCC::setMomentum(int locoId,int16_t accelerating, int16_t decelerating) {
|
||||||
if (locoId==0 && millis_per_notch>=0) {
|
if (locoId<=0 ) return false;
|
||||||
defaultMomentum=millis_per_notch;
|
if (locoId==0) {
|
||||||
|
if (accelerating<0 || decelerating<0) return false;
|
||||||
|
defaultMomentumA=accelerating/MOMENTUM_FACTOR;
|
||||||
|
defaultMomentumD=decelerating/MOMENTUM_FACTOR;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// millis=-1 is ok and means this loco should use the default.
|
// -1 is ok and means this loco should use the default.
|
||||||
// We dont copy the default here because it can be changed
|
if (accelerating<-1 || decelerating<-1) return false;
|
||||||
// while running and have immediate effect on all locos using -1.
|
if (accelerating>2000 || decelerating>2000) return false;
|
||||||
if (locoId<=0 || millis_per_notch<-1) return false;
|
|
||||||
lookupSpeedTable(locoId,true)->millis_per_notch=millis_per_notch;
|
// Values stored are 255=MOMENTUM_USE_DEFAULT, or millis/MOMENTUM_FACTOR.
|
||||||
|
// This is to keep the values in a byte rather than int16
|
||||||
|
// thus saving 2 bytes RAM per loco slot.
|
||||||
|
LOCO* slot=lookupSpeedTable(locoId,true);
|
||||||
|
slot->momentumA=(accelerating<0)? MOMENTUM_USE_DEFAULT: (accelerating/MOMENTUM_FACTOR);
|
||||||
|
slot->momentumD=(decelerating<0)? MOMENTUM_USE_DEFAULT: (decelerating/MOMENTUM_FACTOR);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,11 +980,11 @@ void DCC::displayCabList(Print * stream) {
|
||||||
if (slot->loco==0) break; // no more locos
|
if (slot->loco==0) break; // no more locos
|
||||||
if (slot->loco>0) {
|
if (slot->loco>0) {
|
||||||
used ++;
|
used ++;
|
||||||
StringFormatter::send(stream,F("cab=%d, speed=%d, target=%d momentum=%d\n"),
|
StringFormatter::send(stream,F("cab=%d, speed=%d, target=%d momentum=%d/%d\n"),
|
||||||
slot->loco, slot->speedCode, slot->targetSpeed,
|
slot->loco, slot->speedCode, slot->targetSpeed,
|
||||||
slot->millis_per_notch);
|
slot->momentumA, slot->momentumD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StringFormatter::send(stream,F("Used=%d, max=%d, momentum=%d *>\n"),
|
StringFormatter::send(stream,F("Used=%d, max=%d, momentum=%d/%d *>\n"),
|
||||||
used,MAX_LOCOS, DCC::defaultMomentum);
|
used,MAX_LOCOS, DCC::defaultMomentumA,DCC::defaultMomentumD);
|
||||||
}
|
}
|
||||||
|
|
11
DCC.h
11
DCC.h
|
@ -106,18 +106,23 @@ public:
|
||||||
uint32_t functions;
|
uint32_t functions;
|
||||||
// Momentum management variables
|
// Momentum management variables
|
||||||
uint32_t momentum_base; // millis() when speed modified under momentum
|
uint32_t momentum_base; // millis() when speed modified under momentum
|
||||||
int16_t millis_per_notch; // 0=no momentum, -1=defaultMomentum
|
byte momentumA, momentumD;
|
||||||
byte targetSpeed; // speed set by throttle
|
byte targetSpeed; // speed set by throttle
|
||||||
};
|
};
|
||||||
|
static const int16_t MOMENTUM_FACTOR=8;
|
||||||
|
static const byte MOMENTUM_USE_DEFAULT=255;
|
||||||
|
static byte getMomentum(LOCO * slot);
|
||||||
|
|
||||||
static LOCO speedTable[MAX_LOCOS];
|
static LOCO speedTable[MAX_LOCOS];
|
||||||
static LOCO * lookupSpeedTable(int locoId, bool autoCreate=true);
|
static LOCO * lookupSpeedTable(int locoId, bool autoCreate=true);
|
||||||
static byte cv1(byte opcode, int cv);
|
static byte cv1(byte opcode, int cv);
|
||||||
static byte cv2(int cv);
|
static byte cv2(int cv);
|
||||||
static bool setMomentum(int locoId,int16_t millis_per_notch);
|
static bool setMomentum(int locoId,int16_t accelerating, int16_t decelerating);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static byte loopStatus;
|
static byte loopStatus;
|
||||||
static int16_t defaultMomentum; // Millis per speed step
|
static byte defaultMomentumA; // Accelerating
|
||||||
|
static byte defaultMomentumD; // Accelerating
|
||||||
static void setThrottle2(uint16_t cab, uint8_t speedCode);
|
static void setThrottle2(uint16_t cab, uint8_t speedCode);
|
||||||
static void setFunctionInternal(int cab, byte fByte, byte eByte, byte count);
|
static void setFunctionInternal(int cab, byte fByte, byte eByte, byte count);
|
||||||
static bool issueReminder(LOCO * slot);
|
static bool issueReminder(LOCO * slot);
|
||||||
|
|
|
@ -430,9 +430,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 'm': // <m cabid momentum>
|
case 'm': // <m cabid momentum [braking]>
|
||||||
if (params!=2) break;
|
if (params<2 || params>3) break;
|
||||||
if (DCC::setMomentum(p[0],p[1])) return;
|
if (params==2) p[2]=p[1];
|
||||||
|
if (DCC::setMomentum(p[0],p[1],p[2])) return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M': // WRITE TRANSPARENT DCC PACKET MAIN <M REG X1 ... X9>
|
case 'M': // WRITE TRANSPARENT DCC PACKET MAIN <M REG X1 ... X9>
|
||||||
|
|
|
@ -568,7 +568,7 @@ void RMFT2::loop2() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPCODE_MOMENTUM:
|
case OPCODE_MOMENTUM:
|
||||||
DCC::setMomentum(loco,operand);
|
DCC::setMomentum(loco,operand,getOperand(1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPCODE_FORGET:
|
case OPCODE_FORGET:
|
||||||
|
|
|
@ -266,7 +266,7 @@
|
||||||
#define LCC(eventid)
|
#define LCC(eventid)
|
||||||
#define LCCX(senderid,eventid)
|
#define LCCX(senderid,eventid)
|
||||||
#define LCD(row,msg)
|
#define LCD(row,msg)
|
||||||
#define MOMENTUM(mspertick)
|
#define MOMENTUM(accel,decel...)
|
||||||
#define SCREEN(display,row,msg)
|
#define SCREEN(display,row,msg)
|
||||||
#define LCN(msg)
|
#define LCN(msg)
|
||||||
#define MESSAGE(msg)
|
#define MESSAGE(msg)
|
||||||
|
|
|
@ -551,7 +551,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
||||||
#define STEALTH_GLOBAL(code...)
|
#define STEALTH_GLOBAL(code...)
|
||||||
#define LCN(msg) PRINT(msg)
|
#define LCN(msg) PRINT(msg)
|
||||||
#define MESSAGE(msg) PRINT(msg)
|
#define MESSAGE(msg) PRINT(msg)
|
||||||
#define MOMENTUM(mspertick) OPCODE_MOMENTUM,V(mspertick),
|
#define MOMENTUM(accel,decel...) OPCODE_MOMENTUM,V(accel),OPCODE_PAD,V(#decel[0]?decel+0:accel),
|
||||||
#define MOVETT(id,steps,activity) OPCODE_SERVO,V(id),OPCODE_PAD,V(steps),OPCODE_PAD,V(EXTurntable::activity),OPCODE_PAD,V(0),
|
#define MOVETT(id,steps,activity) OPCODE_SERVO,V(id),OPCODE_PAD,V(steps),OPCODE_PAD,V(EXTurntable::activity),OPCODE_PAD,V(0),
|
||||||
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
#define ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
||||||
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
|
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.2.71"
|
#define VERSION "5.2.72"
|
||||||
|
// 5.2.72 - Momentum.
|
||||||
// 5.2.71 - Broadcasts of loco forgets.
|
// 5.2.71 - Broadcasts of loco forgets.
|
||||||
// 5.2.70 - IO_RocoDriver renamed to IO_EncoderThrottle.
|
// 5.2.70 - IO_RocoDriver renamed to IO_EncoderThrottle.
|
||||||
// - and included in IODEvice.h (circular dependency removed)
|
// - and included in IODEvice.h (circular dependency removed)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user