Skip to content

Commit

Permalink
dual momentum
Browse files Browse the repository at this point in the history
  • Loading branch information
Asbelos committed Jul 25, 2024
1 parent 3ac2fff commit 2d58d06
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 32 deletions.
60 changes: 38 additions & 22 deletions DCC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 (cab==0) {
if (tSpeed==1) estopAll(); // ESTOP broadcast fix
return;
if (tSpeed==1) {
if (cab==0) {
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();
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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 changes: 8 additions & 3 deletions DCC.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,23 @@ class DCC
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);
Expand Down
7 changes: 4 additions & 3 deletions DCCEXParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion EXRAIL2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion EXRAIL2MacroReset.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion EXRAILMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
3 changes: 2 additions & 1 deletion version.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

#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.70 - IO_RocoDriver renamed to IO_EncoderThrottle.
// - and included in IODEvice.h (circular dependency removed)
Expand Down

0 comments on commit 2d58d06

Please sign in to comment.