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
|
||||
}
|
||||
|
||||
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) {
|
||||
if (tSpeed==1) {
|
||||
if (cab==0) {
|
||||
if (tSpeed==1) estopAll(); // ESTOP broadcast fix
|
||||
estopAll(); // ESTOP broadcast fix
|
||||
return;
|
||||
}
|
||||
}
|
||||
byte speedCode = (tSpeed & 0x7F) + tDirection * 128;
|
||||
LOCO * slot=lookupSpeedTable(cab);
|
||||
if (slot->targetSpeed==speedCode) return;
|
||||
slot->targetSpeed=speedCode;
|
||||
auto momentum=slot->millis_per_notch;
|
||||
if (momentum<0) momentum=defaultMomentum;
|
||||
if (momentum>0 && tSpeed!=1) { // not ESTOP
|
||||
byte momentum=getMomentum(slot);;
|
||||
if (momentum && tSpeed!=1) { // not ESTOP
|
||||
// we dont throttle speed, we just let the reminders take it to target
|
||||
slot->momentum_base=millis();
|
||||
}
|
||||
|
@ -813,8 +821,7 @@ bool DCC::issueReminder(LOCO * slot) {
|
|||
// calculate new speed code
|
||||
auto now=millis();
|
||||
int16_t delay=now-slot->momentum_base;
|
||||
auto millisPerNotch=slot->millis_per_notch;
|
||||
if (millisPerNotch<0) millisPerNotch=defaultMomentum;
|
||||
auto millisPerNotch=MOMENTUM_FACTOR * (int16_t)getMomentum(slot);
|
||||
// allow for momentum change to 0 while accelerating/slowing
|
||||
auto ticks=(millisPerNotch>0)?(delay/millisPerNotch):500;
|
||||
if (ticks>0) {
|
||||
|
@ -920,20 +927,29 @@ DCC::LOCO * DCC::lookupSpeedTable(int locoId, bool autoCreate) {
|
|||
firstEmpty->targetSpeed=128; // default direction forward
|
||||
firstEmpty->groupFlags=0;
|
||||
firstEmpty->functions=0;
|
||||
firstEmpty->millis_per_notch=-1; // use default
|
||||
firstEmpty->momentumA=MOMENTUM_USE_DEFAULT;
|
||||
firstEmpty->momentumD=MOMENTUM_USE_DEFAULT;
|
||||
return firstEmpty;
|
||||
}
|
||||
|
||||
bool DCC::setMomentum(int locoId,int16_t millis_per_notch) {
|
||||
if (locoId==0 && millis_per_notch>=0) {
|
||||
defaultMomentum=millis_per_notch;
|
||||
bool DCC::setMomentum(int locoId,int16_t accelerating, int16_t decelerating) {
|
||||
if (locoId<=0 ) return false;
|
||||
if (locoId==0) {
|
||||
if (accelerating<0 || decelerating<0) return false;
|
||||
defaultMomentumA=accelerating/MOMENTUM_FACTOR;
|
||||
defaultMomentumD=decelerating/MOMENTUM_FACTOR;
|
||||
return true;
|
||||
}
|
||||
// millis=-1 is ok and means this loco should use the default.
|
||||
// We dont copy the default here because it can be changed
|
||||
// while running and have immediate effect on all locos using -1.
|
||||
if (locoId<=0 || millis_per_notch<-1) return false;
|
||||
lookupSpeedTable(locoId,true)->millis_per_notch=millis_per_notch;
|
||||
// -1 is ok and means this loco should use the default.
|
||||
if (accelerating<-1 || decelerating<-1) return false;
|
||||
if (accelerating>2000 || decelerating>2000) return false;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -964,11 +980,11 @@ void DCC::displayCabList(Print * stream) {
|
|||
if (slot->loco==0) break; // no more locos
|
||||
if (slot->loco>0) {
|
||||
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->millis_per_notch);
|
||||
slot->momentumA, slot->momentumD);
|
||||
}
|
||||
}
|
||||
StringFormatter::send(stream,F("Used=%d, max=%d, momentum=%d *>\n"),
|
||||
used,MAX_LOCOS, DCC::defaultMomentum);
|
||||
StringFormatter::send(stream,F("Used=%d, max=%d, momentum=%d/%d *>\n"),
|
||||
used,MAX_LOCOS, DCC::defaultMomentumA,DCC::defaultMomentumD);
|
||||
}
|
||||
|
|
11
DCC.h
11
DCC.h
|
@ -106,18 +106,23 @@ public:
|
|||
uint32_t functions;
|
||||
// Momentum management variables
|
||||
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
|
||||
};
|
||||
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 * lookupSpeedTable(int locoId, bool autoCreate=true);
|
||||
static byte cv1(byte opcode, 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:
|
||||
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 setFunctionInternal(int cab, byte fByte, byte eByte, byte count);
|
||||
static bool issueReminder(LOCO * slot);
|
||||
|
|
|
@ -430,9 +430,10 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream)
|
|||
return;
|
||||
#endif
|
||||
|
||||
case 'm': // <m cabid momentum>
|
||||
if (params!=2) break;
|
||||
if (DCC::setMomentum(p[0],p[1])) return;
|
||||
case 'm': // <m cabid momentum [braking]>
|
||||
if (params<2 || params>3) break;
|
||||
if (params==2) p[2]=p[1];
|
||||
if (DCC::setMomentum(p[0],p[1],p[2])) return;
|
||||
break;
|
||||
|
||||
case 'M': // WRITE TRANSPARENT DCC PACKET MAIN <M REG X1 ... X9>
|
||||
|
|
|
@ -568,7 +568,7 @@ void RMFT2::loop2() {
|
|||
break;
|
||||
|
||||
case OPCODE_MOMENTUM:
|
||||
DCC::setMomentum(loco,operand);
|
||||
DCC::setMomentum(loco,operand,getOperand(1));
|
||||
break;
|
||||
|
||||
case OPCODE_FORGET:
|
||||
|
|
|
@ -266,7 +266,7 @@
|
|||
#define LCC(eventid)
|
||||
#define LCCX(senderid,eventid)
|
||||
#define LCD(row,msg)
|
||||
#define MOMENTUM(mspertick)
|
||||
#define MOMENTUM(accel,decel...)
|
||||
#define SCREEN(display,row,msg)
|
||||
#define LCN(msg)
|
||||
#define MESSAGE(msg)
|
||||
|
|
|
@ -551,7 +551,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
|
|||
#define STEALTH_GLOBAL(code...)
|
||||
#define LCN(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 ONACTIVATE(addr,subaddr) OPCODE_ONACTIVATE,V(addr<<2|subaddr),
|
||||
#define ONACTIVATEL(linear) OPCODE_ONACTIVATE,V(linear+3),
|
||||
|
|
Loading…
Reference in New Issue
Block a user