1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-24 00:26:13 +01:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Harald Barth
daa2ffc459 tag 2024-01-20 23:36:11 +01:00
Harald Barth
9728d19b19 eliminate warning 2024-01-20 23:35:30 +01:00
Harald Barth
99a09c713f To make usage easier, use F29 to F31 for frequencies 2024-01-20 23:34:17 +01:00
Colin Murdoch
a5b73c823a Added SETFREQ command
Added SETFREQ command to EXRAIL
2024-01-20 18:09:03 +00:00
11 changed files with 83 additions and 25 deletions

13
DCC.cpp
View File

@ -153,7 +153,7 @@ uint8_t DCC::getThrottleSpeedByte(int cab) {
return speedTable[reg].speedCode; return speedTable[reg].speedCode;
} }
// returns 0 to 3 for frequency // returns 0 to 7 for frequency
uint8_t DCC::getThrottleFrequency(int cab) { uint8_t DCC::getThrottleFrequency(int cab) {
#if defined(ARDUINO_AVR_UNO) #if defined(ARDUINO_AVR_UNO)
(void)cab; (void)cab;
@ -161,10 +161,11 @@ uint8_t DCC::getThrottleFrequency(int cab) {
#else #else
int reg=lookupSpeedTable(cab); int reg=lookupSpeedTable(cab);
if (reg<0) if (reg<0)
return 0; // use default frequency return 0; // use default frequency
uint8_t res = (uint8_t)(speedTable[reg].functions >>30); // shift out first 29 bits so we have the 3 "frequency bits" left
uint8_t res = (uint8_t)(speedTable[reg].functions >>29);
//DIAG(F("Speed table %d functions %l shifted %d"), reg, speedTable[reg].functions, res); //DIAG(F("Speed table %d functions %l shifted %d"), reg, speedTable[reg].functions, res);
return res; // shift out first 30 bits so we have the "frequency bits" left return res;
#endif #endif
} }
@ -200,7 +201,9 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) {
DCCWaveform::mainTrack.schedulePacket(b, nB, 4); DCCWaveform::mainTrack.schedulePacket(b, nB, 4);
} }
// We use the reminder table up to 28 for normal functions. // We use the reminder table up to 28 for normal functions.
// We use 29 to 31 for DC frequency as well. // We use 29 to 31 for DC frequency as well so up to 28
// are "real" functions and 29 to 31 are frequency bits
// controlled by function buttons
if (functionNumber > 31) if (functionNumber > 31)
return true; return true;

View File

@ -137,34 +137,39 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) {
// We are most likely not on pin 3 or 11 as no known motor shield has that as brake. // We are most likely not on pin 3 or 11 as no known motor shield has that as brake.
#endif #endif
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
// Speed mapping is done like this:
// No functions buttons: 000 0 -> low 131Hz
// Only F29 pressed 001 1 -> mid 490Hz
// F30 with or w/o F29 01x 2-3 -> high 3400Hz
// F31 with or w/o F29/30 1xx 4-7 -> supersonic 62500Hz
uint8_t abits; uint8_t abits;
uint8_t bbits; uint8_t bbits;
if (pin == 9 || pin == 10) { // timer 2 is different if (pin == 9 || pin == 10) { // timer 2 is different
if (fbits >= 3) if (fbits >= 4)
abits = B00000011; abits = B00000011;
else else
abits = B00000001; abits = B00000001;
if (fbits >= 3) if (fbits >= 4)
bbits = B0001; bbits = B0001;
else if (fbits == 2) else if (fbits >= 2)
bbits = B0010; bbits = B0010;
else if (fbits == 1) else if (fbits == 1)
bbits = B0100; bbits = B0100;
else else // fbits == 0
bbits = B0110; bbits = B0110;
TCCR2A = (TCCR2A & B11111100) | abits; // set WGM0 and WGM1 TCCR2A = (TCCR2A & B11111100) | abits; // set WGM0 and WGM1
TCCR2B = (TCCR2B & B11110000) | bbits; // set WGM2 and 3 bits of prescaler TCCR2B = (TCCR2B & B11110000) | bbits; // set WGM2 and 3 bits of prescaler
//DIAG(F("Timer 2 A=%x B=%x"), TCCR2A, TCCR2B); DIAG(F("Timer 2 A=%x B=%x"), TCCR2A, TCCR2B);
} else { // not timer 9 or 10 } else { // not timer 9 or 10
abits = B01; abits = B01;
if (fbits >= 3) if (fbits >= 4)
bbits = B1001; bbits = B1001;
else if (fbits == 2) else if (fbits >= 2)
bbits = B0010; bbits = B0010;
else if (fbits == 1) else if (fbits == 1)
bbits = B0011; bbits = B0011;

View File

@ -154,9 +154,13 @@ void DCCTimer::reset() {
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
if (f >= 16) if (f >= 16)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f);
else if (f >= 3) else if (f == 7)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500);
else if (f == 2) else if (f >= 4)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 32000);
else if (f >= 3)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 16000);
else if (f >= 2)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400);
else if (f == 1) else if (f == 1)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480);

View File

@ -260,9 +260,13 @@ void DCCTimer::reset() {
void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) {
if (f >= 16) if (f >= 16)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f);
else if (f >= 3) else if (f == 7)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500);
else if (f == 2) else if (f >= 4)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 32000);
else if (f >= 3)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 16000);
else if (f >= 2)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400);
else if (f == 1) else if (f == 1)
DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480); DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480);

View File

@ -667,6 +667,45 @@ void RMFT2::loop2() {
} }
break; break;
case OPCODE_SETFREQ:
// Frequency is default 0, or 1, 2,3
//if (loco) DCC::setFn(loco,operand,true);
switch (operand) {
case 0: // default - all F-s off
if (loco) {
DCC::setFn(loco,29,false);
DCC::setFn(loco,30,false);
DCC::setFn(loco,31,false);
}
break;
case 1:
if (loco) {
DCC::setFn(loco,29,true);
DCC::setFn(loco,30,false);
DCC::setFn(loco,31,false);
}
break;
case 2:
if (loco) {
DCC::setFn(loco,29,false);
DCC::setFn(loco,30,true);
DCC::setFn(loco,31,false);
}
break;
case 3:
if (loco) {
DCC::setFn(loco,29,false);
DCC::setFn(loco,30,false);
DCC::setFn(loco,31,true);
}
break;
default:
; // do nothing
break;
}
break;
case OPCODE_RESUME: case OPCODE_RESUME:
pausingTask=NULL; pausingTask=NULL;
driveLoco(speedo); driveLoco(speedo);

View File

@ -51,7 +51,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE,
OPCODE_JOIN,OPCODE_UNJOIN,OPCODE_READ_LOCO1,OPCODE_READ_LOCO2, OPCODE_JOIN,OPCODE_UNJOIN,OPCODE_READ_LOCO1,OPCODE_READ_LOCO2,
#endif #endif
OPCODE_POM, OPCODE_POM,
OPCODE_START,OPCODE_SETLOCO,OPCODE_SENDLOCO,OPCODE_FORGET, OPCODE_START,OPCODE_SETLOCO,OPCODE_SETFREQ,OPCODE_SENDLOCO,OPCODE_FORGET,
OPCODE_PAUSE, OPCODE_RESUME,OPCODE_POWEROFF,OPCODE_POWERON, OPCODE_PAUSE, OPCODE_RESUME,OPCODE_POWEROFF,OPCODE_POWERON,
OPCODE_ONCLOSE, OPCODE_ONTHROW, OPCODE_SERVOTURNOUT, OPCODE_PINTURNOUT, OPCODE_ONCLOSE, OPCODE_ONTHROW, OPCODE_SERVOTURNOUT, OPCODE_PINTURNOUT,
OPCODE_PRINT,OPCODE_DCCACTIVATE, OPCODE_PRINT,OPCODE_DCCACTIVATE,

View File

@ -151,6 +151,7 @@
#undef SET_TRACK #undef SET_TRACK
#undef SET_POWER #undef SET_POWER
#undef SETLOCO #undef SETLOCO
#undef SETFREQ
#undef SIGNAL #undef SIGNAL
#undef SIGNALH #undef SIGNALH
#undef SPEED #undef SPEED
@ -302,6 +303,7 @@
#define SET_TRACK(track,mode) #define SET_TRACK(track,mode)
#define SET_POWER(track,onoff) #define SET_POWER(track,onoff)
#define SETLOCO(loco) #define SETLOCO(loco)
#define SETFREQ(loco,freq)
#define SIGNAL(redpin,amberpin,greenpin) #define SIGNAL(redpin,amberpin,greenpin)
#define SIGNALH(redpin,amberpin,greenpin) #define SIGNALH(redpin,amberpin,greenpin)
#define SPEED(speed) #define SPEED(speed)

View File

@ -493,6 +493,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
#define SET_TRACK(track,mode) OPCODE_SET_TRACK,V(TRACK_MODE_##mode <<8 | TRACK_NUMBER_##track), #define SET_TRACK(track,mode) OPCODE_SET_TRACK,V(TRACK_MODE_##mode <<8 | TRACK_NUMBER_##track),
#define SET_POWER(track,onoff) OPCODE_SET_POWER,V(TRACK_POWER_##onoff),OPCODE_PAD, V(TRACK_NUMBER_##track), #define SET_POWER(track,onoff) OPCODE_SET_POWER,V(TRACK_POWER_##onoff),OPCODE_PAD, V(TRACK_NUMBER_##track),
#define SETLOCO(loco) OPCODE_SETLOCO,V(loco), #define SETLOCO(loco) OPCODE_SETLOCO,V(loco),
#define SETFREQ(loco,freq) OPCODE_SETLOCO,V(loco), OPCODE_SETFREQ,V(freq),
#define SIGNAL(redpin,amberpin,greenpin) #define SIGNAL(redpin,amberpin,greenpin)
#define SIGNALH(redpin,amberpin,greenpin) #define SIGNALH(redpin,amberpin,greenpin)
#define SPEED(speed) OPCODE_SPEED,V(speed), #define SPEED(speed) OPCODE_SPEED,V(speed),

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-202401030142Z" #define GITHUB_SHA "devel-202401202235Z"

View File

@ -110,7 +110,7 @@ void I2CManagerClass::I2C_setClock(uint32_t i2cClockSpeed) {
// Calculate a rise time appropriate to the requested bus speed // Calculate a rise time appropriate to the requested bus speed
// Use 10x the rise time spec to enable integer divide of 50ns clock period // Use 10x the rise time spec to enable integer divide of 50ns clock period
uint16_t t_rise; uint16_t t_rise;
uint32_t ccr_freq; //uint32_t ccr_freq;
while (s->CR1 & I2C_CR1_STOP); // Prevents lockup by guarding further while (s->CR1 & I2C_CR1_STOP); // Prevents lockup by guarding further
// writes to CR1 while STOP is being executed! // writes to CR1 while STOP is being executed!

View File

@ -350,10 +350,10 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/)
} }
#endif #endif
//DIAG(F("Brake pin %d freqency %d"), brakePin, f); //DIAG(F("Brake pin %d freqency %d"), brakePin, f);
DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency
DCCTimer::DCCEXanalogWrite(brakePin,brake); DCCTimer::DCCEXanalogWrite(brakePin,brake);
#else // all AVR here #else // all AVR here
DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps 0 to 3 DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps
analogWrite(brakePin,brake); analogWrite(brakePin,brake);
#endif #endif
} }
@ -406,26 +406,26 @@ void MotorDriver::throttleInrush(bool on) {
return; return;
if ( !(trackMode & (TRACK_MODE_MAIN | TRACK_MODE_PROG | TRACK_MODE_EXT))) if ( !(trackMode & (TRACK_MODE_MAIN | TRACK_MODE_PROG | TRACK_MODE_EXT)))
return; return;
byte duty = on ? 208 : 0; byte duty = on ? 207 : 0; // duty of 81% at 62500Hz this gives pauses of 3usec
if (invertBrake) if (invertBrake)
duty = 255-duty; duty = 255-duty;
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
if(on) { if(on) {
DCCTimer::DCCEXanalogWrite(brakePin,duty); DCCTimer::DCCEXanalogWrite(brakePin,duty);
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 62500); DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
} else { } else {
ledcDetachPin(brakePin); ledcDetachPin(brakePin);
} }
#elif defined(ARDUINO_ARCH_STM32) #elif defined(ARDUINO_ARCH_STM32)
if(on) { if(on) {
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 62500); DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
DCCTimer::DCCEXanalogWrite(brakePin,duty); DCCTimer::DCCEXanalogWrite(brakePin,duty);
} else { } else {
pinMode(brakePin, OUTPUT); pinMode(brakePin, OUTPUT);
} }
#else // all AVR here #else // all AVR here
if(on){ if(on){
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 3); DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
} }
analogWrite(brakePin,duty); analogWrite(brakePin,duty);
#endif #endif