diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index e8404de..f838fd2 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -209,7 +209,9 @@ int16_t CommandDistributor::retClockTime() { void CommandDistributor::broadcastLoco(byte slot) { DCC::LOCO * sp=&DCC::speedTable[slot]; - broadcastReply(COMMAND_TYPE, F("\n"), sp->loco,slot,sp->speedCode,sp->functions); + uint32_t func = sp->functions; + func = func & 0x1fffffff; // mask out bits 0-28 + broadcastReply(COMMAND_TYPE, F("\n"), sp->loco,slot,sp->speedCode,func); #ifdef SABERTOOTH if (Serial2 && sp->loco == SABERTOOTH) { static uint8_t rampingmode = 0; diff --git a/DCC.cpp b/DCC.cpp index 0c5148a..95464af 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -153,6 +153,22 @@ uint8_t DCC::getThrottleSpeedByte(int cab) { return speedTable[reg].speedCode; } +// returns 0 to 7 for frequency +uint8_t DCC::getThrottleFrequency(int cab) { +#if defined(ARDUINO_AVR_UNO) + (void)cab; + return 0; +#else + int reg=lookupSpeedTable(cab); + if (reg<0) + return 0; // use default frequency + // 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); + return res; +#endif +} + // returns direction on loco // or true/forward on "loco not found" bool DCC::getThrottleDirection(int cab) { @@ -183,43 +199,54 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) { b[nB++] = functionNumber >>7 ; // high order bits } DCCWaveform::mainTrack.schedulePacket(b, nB, 4); - return true; } - + // We use the reminder table up to 28 for normal functions. + // 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) + return true; + int reg = lookupSpeedTable(cab); if (reg<0) return false; // Take care of functions: // Set state of function - unsigned long previous=speedTable[reg].functions; - unsigned long funcmask = (1UL<28) return; + if (cab<=0 || functionNumber>31) return; int reg = lookupSpeedTable(cab); if (reg<0) return; unsigned long funcmask = (1UL<28) return -1; // unknown +// Report function state (used from withrottle protocol) +// returns 0 false, 1 true or -1 for do not know +int8_t DCC::getFn( int cab, int16_t functionNumber) { + if (cab<=0 || functionNumber>28) + return -1; // unknown int reg = lookupSpeedTable(cab); - if (reg<0) return -1; + if (reg<0) + return -1; unsigned long funcmask = (1UL< // No longer useful because of multiple tracks See and if (params>0) break; TrackManager::reportObsoleteCurrent(stream); return; - +#endif case 'Q': // SENSORS Sensor::printAll(stream); return; diff --git a/DCCTimer.h b/DCCTimer.h index 3b14fd6..5cc5ce8 100644 --- a/DCCTimer.h +++ b/DCCTimer.h @@ -85,6 +85,7 @@ class DCCTimer { static void reset(); private: + static void DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency); static int freeMemory(); static volatile int minimum_free_memory; static const int DCC_SIGNAL_TIME=58; // this is the 58uS DCC 1-bit waveform half-cycle diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index 3e6c436..3bb2b9f 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -29,6 +29,7 @@ #include #include #include "DCCTimer.h" +#include "DIAG.h" #ifdef DEBUG_ADC #include "TrackManager.h" #endif @@ -125,6 +126,81 @@ void DCCTimer::reset() { } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); +} +void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { +#if defined(ARDUINO_AVR_UNO) + // Not worth doin something here as: + // If we are on pin 9 or 10 we are on Timer1 and we can not touch Timer1 as that is our DCC source. + // If we are on pin 5 or 6 we are on Timer 0 ad we can not touch Timer0 as that is millis() etc. + // We are most likely not on pin 3 or 11 as no known motor shield has that as brake. +#endif +#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 bbits; + if (pin == 9 || pin == 10) { // timer 2 is different + + if (fbits >= 4) + abits = B00000011; + else + abits = B00000001; + + if (fbits >= 4) + bbits = B0001; + else if (fbits >= 2) + bbits = B0010; + else if (fbits == 1) + bbits = B0100; + else // fbits == 0 + bbits = B0110; + + TCCR2A = (TCCR2A & B11111100) | abits; // set WGM0 and WGM1 + TCCR2B = (TCCR2B & B11110000) | bbits; // set WGM2 and 3 bits of prescaler + DIAG(F("Timer 2 A=%x B=%x"), TCCR2A, TCCR2B); + + } else { // not timer 9 or 10 + abits = B01; + + if (fbits >= 4) + bbits = B1001; + else if (fbits >= 2) + bbits = B0010; + else if (fbits == 1) + bbits = B0011; + else + bbits = B0100; + + switch (pin) { + // case 9 and 10 taken care of above by if() + case 6: + case 7: + case 8: + // Timer4 + TCCR4A = (TCCR4A & B11111100) | abits; // set WGM0 and WGM1 + TCCR4B = (TCCR4B & B11100000) | bbits; // set WGM2 and WGM3 and divisor + //DIAG(F("Timer 4 A=%x B=%x"), TCCR4A, TCCR4B); + break; + case 46: + case 45: + case 44: + // Timer5 + TCCR5A = (TCCR5A & B11111100) | abits; // set WGM0 and WGM1 + TCCR5B = (TCCR5B & B11100000) | bbits; // set WGM2 and WGM3 and divisor + //DIAG(F("Timer 5 A=%x B=%x"), TCCR5A, TCCR5B); + break; + default: + break; + } + } +#endif +} + #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) #define NUM_ADC_INPUTS 16 #else diff --git a/DCCTimerESP.cpp b/DCCTimerESP.cpp index 7ed3f28..ae81c74 100644 --- a/DCCTimerESP.cpp +++ b/DCCTimerESP.cpp @@ -151,10 +151,26 @@ void DCCTimer::reset() { ESP.restart(); } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { + if (f >= 16) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); + else if (f == 7) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500); + else if (f >= 4) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 32000); + else if (f >= 3) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 16000); + else if (f >= 2) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400); + else if (f == 1) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480); + else + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 131); +} + #include "esp32-hal.h" #include "soc/soc_caps.h" - #ifdef SOC_LEDC_SUPPORT_HS_MODE #define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1) #else @@ -164,7 +180,7 @@ void DCCTimer::reset() { static int8_t pin_to_channel[SOC_GPIO_PIN_COUNT] = { 0 }; static int cnt_channel = LEDC_CHANNELS; -void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency) { +void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency) { if (pin < SOC_GPIO_PIN_COUNT) { if (pin_to_channel[pin] != 0) { ledcSetup(pin_to_channel[pin], frequency, 8); diff --git a/DCCTimerMEGAAVR.cpp b/DCCTimerMEGAAVR.cpp index 2b2bdab..f7badfd 100644 --- a/DCCTimerMEGAAVR.cpp +++ b/DCCTimerMEGAAVR.cpp @@ -125,6 +125,11 @@ void DCCTimer::reset() { while(true){} } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { +} +void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { +} + int16_t ADCee::ADCmax() { return 4095; } diff --git a/DCCTimerSAMD.cpp b/DCCTimerSAMD.cpp index f878ae5..4929ab8 100644 --- a/DCCTimerSAMD.cpp +++ b/DCCTimerSAMD.cpp @@ -156,6 +156,11 @@ void DCCTimer::reset() { while(true) {}; } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { +} +void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { +} + #define NUM_ADC_INPUTS NUM_ANALOG_INPUTS uint16_t ADCee::usedpins = 0; diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index ca02a41..eea231c 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -257,6 +257,23 @@ void DCCTimer::reset() { while(true) {}; } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { + if (f >= 16) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); + else if (f == 7) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500); + else if (f >= 4) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 32000); + else if (f >= 3) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 16000); + else if (f >= 2) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 3400); + else if (f == 1) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480); + else + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 131); +} + // TODO: rationalise the size of these... could really use sparse arrays etc. static HardwareTimer * pin_timer[100] = {0}; static uint32_t channel_frequency[100] = {0}; @@ -267,7 +284,7 @@ static uint32_t pin_channel[100] = {0}; // sophisticated about detecting any clash between the timer we'd like to use for PWM and the ones // currently used for HA so they don't interfere with one another. For now we'll just make PWM // work well... then work backwards to integrate with HA mode if we can. -void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency) +void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency) { if (pin_timer[pin] == NULL) { // Automatically retrieve TIM instance and channel associated to pin diff --git a/DCCTimerTEENSY.cpp b/DCCTimerTEENSY.cpp index 0619e21..fd512e9 100644 --- a/DCCTimerTEENSY.cpp +++ b/DCCTimerTEENSY.cpp @@ -141,6 +141,11 @@ void DCCTimer::reset() { SCB_AIRCR = 0x05FA0004; } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { +} +void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { +} + int16_t ADCee::ADCmax() { return 4095; } diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index 8a2eadf..490021b 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -669,6 +669,45 @@ void RMFT2::loop2() { } 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: pausingTask=NULL; driveLoco(speedo); diff --git a/EXRAIL2.h b/EXRAIL2.h index 30a2f45..63d20e7 100644 --- a/EXRAIL2.h +++ b/EXRAIL2.h @@ -51,7 +51,7 @@ enum OPCODE : byte {OPCODE_THROW,OPCODE_CLOSE, OPCODE_JOIN,OPCODE_UNJOIN,OPCODE_READ_LOCO1,OPCODE_READ_LOCO2, #endif 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_ONCLOSE, OPCODE_ONTHROW, OPCODE_SERVOTURNOUT, OPCODE_PINTURNOUT, OPCODE_PRINT,OPCODE_DCCACTIVATE, diff --git a/EXRAIL2MacroReset.h b/EXRAIL2MacroReset.h index 3554f6c..fefd6b8 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -152,6 +152,7 @@ #undef SET_TRACK #undef SET_POWER #undef SETLOCO +#undef SETFREQ #undef SIGNAL #undef SIGNALH #undef SPEED @@ -304,6 +305,7 @@ #define SET_TRACK(track,mode) #define SET_POWER(track,onoff) #define SETLOCO(loco) +#define SETFREQ(loco,freq) #define SIGNAL(redpin,amberpin,greenpin) #define SIGNALH(redpin,amberpin,greenpin) #define SPEED(speed) diff --git a/EXRAILMacros.h b/EXRAILMacros.h index 8ed2b82..ccf04c9 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -562,6 +562,7 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup]; #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 SETLOCO(loco) OPCODE_SETLOCO,V(loco), +#define SETFREQ(loco,freq) OPCODE_SETLOCO,V(loco), OPCODE_SETFREQ,V(freq), #define SIGNAL(redpin,amberpin,greenpin) #define SIGNALH(redpin,amberpin,greenpin) #define SPEED(speed) OPCODE_SPEED,V(speed), diff --git a/MotorDriver.cpp b/MotorDriver.cpp index bd25be4..09e2c58 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -325,49 +325,23 @@ uint16_t taurustones[28] = { 165, 175, 196, 220, 220, 196, 175, 165 }; #endif #endif -void MotorDriver::setDCSignal(byte speedcode) { +void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/) { if (brakePin == UNUSED_PIN) return; - switch(brakePin) { -#if defined(ARDUINO_AVR_UNO) - // Not worth doin something here as: - // If we are on pin 9 or 10 we are on Timer1 and we can not touch Timer1 as that is our DCC source. - // If we are on pin 5 or 6 we are on Timer 0 ad we can not touch Timer0 as that is millis() etc. - // We are most likely not on pin 3 or 11 as no known motor shield has that as brake. -#endif -#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) - case 9: - case 10: - // Timer2 (is differnet) - TCCR2A = (TCCR2A & B11111100) | B00000001; // set WGM1=0 and WGM0=1 phase correct PWM - TCCR2B = (TCCR2B & B11110000) | B00000110; // set WGM2=0 ; set divisor on timer 2 to 1/256 for 122.55Hz - //DIAG(F("2 A=%x B=%x"), TCCR2A, TCCR2B); - break; - case 6: - case 7: - case 8: - // Timer4 - TCCR4A = (TCCR4A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for normal PWM 8-bit - TCCR4B = (TCCR4B & B11100000) | B00000100; // set WGM2=0 and WGM3=0 for normal PWM 8 bit and div 1/256 for 122.55Hz - break; - case 46: - case 45: - case 44: - // Timer5 - TCCR5A = (TCCR5A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for normal PWM 8-bit - TCCR5B = (TCCR5B & B11100000) | B00000100; // set WGM2=0 and WGM3=0 for normal PWM 8 bit and div 1/256 for 122.55Hz - break; -#endif - default: - break; - } // spedcoode is a dcc speed & direction byte tSpeed=speedcode & 0x7F; // DCC Speed with 0,1 stop and speed steps 2 to 127 byte tDir=speedcode & 0x80; byte brake; + + if (tSpeed <= 1) brake = 255; + else if (tSpeed >= 127) brake = 0; + else brake = 2 * (128-tSpeed); + if (invertBrake) + brake=255-brake; + + { // new block because of variable f #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32) - { - int f = 131; + int f = frequency; #ifdef VARIABLE_TONES if (tSpeed > 2) { if (tSpeed <= 58) { @@ -375,19 +349,15 @@ void MotorDriver::setDCSignal(byte speedcode) { } } #endif - DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup + //DIAG(F("Brake pin %d freqency %d"), brakePin, f); + DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency + DCCTimer::DCCEXanalogWrite(brakePin,brake); +#else // all AVR here + DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps + analogWrite(brakePin,brake); +#endif } -#endif - if (tSpeed <= 1) brake = 255; - else if (tSpeed >= 127) brake = 0; - else brake = 2 * (128-tSpeed); - if (invertBrake) - brake=255-brake; -#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32) - DCCTimer::DCCEXanalogWrite(brakePin,brake); -#else - analogWrite(brakePin,brake); -#endif + //DIAG(F("DCSignal %d"), speedcode); if (HAVE_PORTA(fastSignalPin.shadowinout == &PORTA)) { noInterrupts(); @@ -436,58 +406,26 @@ void MotorDriver::throttleInrush(bool on) { return; if ( !(trackMode & (TRACK_MODE_MAIN | TRACK_MODE_PROG | TRACK_MODE_EXT))) return; - byte duty = on ? 208 : 0; + byte duty = on ? 207 : 0; // duty of 81% at 62500Hz this gives pauses of 3usec if (invertBrake) duty = 255-duty; #if defined(ARDUINO_ARCH_ESP32) if(on) { DCCTimer::DCCEXanalogWrite(brakePin,duty); - DCCTimer::DCCEXanalogWriteFrequency(brakePin, 62500); + DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max } else { ledcDetachPin(brakePin); } #elif defined(ARDUINO_ARCH_STM32) if(on) { - DCCTimer::DCCEXanalogWriteFrequency(brakePin, 62500); + DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max DCCTimer::DCCEXanalogWrite(brakePin,duty); } else { pinMode(brakePin, OUTPUT); } -#else +#else // all AVR here if(on){ - switch(brakePin) { -#if defined(ARDUINO_AVR_UNO) - // Not worth doin something here as: - // If we are on pin 9 or 10 we are on Timer1 and we can not touch Timer1 as that is our DCC source. - // If we are on pin 5 or 6 we are on Timer 0 ad we can not touch Timer0 as that is millis() etc. - // We are most likely not on pin 3 or 11 as no known motor shield has that as brake. -#endif -#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) - case 9: - case 10: - // Timer2 (is different) - TCCR2A = (TCCR2A & B11111100) | B00000011; // set WGM0=1 and WGM1=1 for fast PWM - TCCR2B = (TCCR2B & B11110000) | B00000001; // set WGM2=0 and prescaler div=1 (max) - DIAG(F("2 A=%x B=%x"), TCCR2A, TCCR2B); - break; - case 6: - case 7: - case 8: - // Timer4 - TCCR4A = (TCCR4A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for fast PWM 8-bit - TCCR4B = (TCCR4B & B11100000) | B00001001; // set WGM2=1 and WGM3=0 for fast PWM 8 bit and div=1 (max) - break; - case 46: - case 45: - case 44: - // Timer5 - TCCR5A = (TCCR5A & B11111100) | B00000001; // set WGM0=1 and WGM1=0 for fast PWM 8-bit - TCCR5B = (TCCR5B & B11100000) | B00001001; // set WGM2=1 and WGM3=0 for fast PWM 8 bit and div=1 (max) - break; -#endif - default: - break; - } + DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max } analogWrite(brakePin,duty); #endif diff --git a/MotorDriver.h b/MotorDriver.h index 07ff93f..b678a84 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -187,7 +187,7 @@ class MotorDriver { } }; inline pinpair getSignalPin() { return pinpair(signalPin,signalPin2); }; - void setDCSignal(byte speedByte); + void setDCSignal(byte speedByte, uint8_t frequency=0); void throttleInrush(bool on); inline void detachDCSignal() { #if defined(__arm__) diff --git a/TrackManager.cpp b/TrackManager.cpp index da96832..ace7dc3 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -19,6 +19,7 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . */ +#include "defines.h" #include "TrackManager.h" #include "FSH.h" #include "DCCWaveform.h" @@ -188,7 +189,7 @@ void TrackManager::setDCSignal(int16_t cab, byte speedbyte) { FOR_EACH_TRACK(t) { if (trackDCAddr[t]!=cab && cab != 0) continue; if (track[t]->getMode() & TRACK_MODE_DC) - track[t]->setDCSignal(speedbyte); + track[t]->setDCSignal(speedbyte, DCC::getThrottleFrequency(trackDCAddr[t])); } } @@ -334,8 +335,8 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr } void TrackManager::applyDCSpeed(byte t) { - uint8_t speedByte=DCC::getThrottleSpeedByte(trackDCAddr[t]); - track[t]->setDCSignal(speedByte); + track[t]->setDCSignal(DCC::getThrottleSpeedByte(trackDCAddr[t]), + DCC::getThrottleFrequency(trackDCAddr[t])); } bool TrackManager::parseEqualSign(Print *stream, int16_t params, int16_t p[]) @@ -560,14 +561,17 @@ bool TrackManager::getPower(byte t, char s[]) { return false; } - void TrackManager::reportObsoleteCurrent(Print* stream) { // This function is for backward JMRI compatibility only // It reports the first track only, as main, regardless of track settings. // +#ifdef HAS_ENOUGH_MEMORY int maxCurrent=track[0]->raw2mA(track[0]->getRawCurrentTripValue()); StringFormatter::send(stream, F("\n"), - track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent); + track[0]->raw2mA(track[0]->getCurrentRaw(false)), maxCurrent, maxCurrent); +#else + (void)stream; +#endif } void TrackManager::reportCurrent(Print* stream) { diff --git a/WiThrottle.cpp b/WiThrottle.cpp index 244dfd8..e71c1cd 100644 --- a/WiThrottle.cpp +++ b/WiThrottle.cpp @@ -618,7 +618,7 @@ void WiThrottle::sendFunctions(Print* stream, byte loco) { #endif for(int fKey=0; fKey=0) StringFormatter::send(stream,F("M%cA%c%d<;>F%d%d\n"),myLocos[loco].throttle,LorS(locoid),locoid,fstate,fKey); } } diff --git a/version.h b/version.h index e4ab5d0..276f2a9 100644 --- a/version.h +++ b/version.h @@ -3,7 +3,8 @@ #include "StringFormatter.h" -#define VERSION "5.2.27stm32EC" +#define VERSION "5.2.27stm32ECvf" +// 5.2.XX - Variable frequency for DC mode // 5.2.27 - Bugfix: IOExpander memory allocation // 5.2.26 - Silently ignore overridden HAL defaults // - include HAL_IGNORE_DEFAULTS macro in EXRAIL