From adb8b56c92eafd4a925cf5d21cd58c1d8315a27c Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 30 Dec 2023 21:23:44 +0100 Subject: [PATCH 01/18] variable frequency step #1 --- DCCTimer.h | 1 + DCCTimerAVR.cpp | 71 ++++++++++++++++++++++++++++++++++++ DCCTimerESP.cpp | 16 +++++++- DCCTimerSTM32.cpp | 15 +++++++- MotorDriver.cpp | 93 ++++++++--------------------------------------- 5 files changed, 115 insertions(+), 81 deletions(-) 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..b27a906 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,76 @@ 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) + uint8_t abits; + uint8_t bbits; + if (pin == 9 || pin == 10) { // timer 2 is different + + if (fbits >= 3) + abits = B11; + else + abits = B01; + + if (fbits >= 3) + bbits = B0001; + else if (fbits == 2) + bbits = B0010; + else if (fbits == 1) + bbits = B0100; + else + 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 >= 3) + 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..dbd4e9d 100644 --- a/DCCTimerESP.cpp +++ b/DCCTimerESP.cpp @@ -151,10 +151,22 @@ void DCCTimer::reset() { ESP.restart(); } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { + if (f >= 16) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); + else if (f >= 3) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500); + 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 +176,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/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index f24adc2..c220620 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -257,6 +257,19 @@ void DCCTimer::reset() { while(true) {}; } +void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { + if (f >= 16) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); + else if (f >= 3) + DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 62500); + 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 +280,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/MotorDriver.cpp b/MotorDriver.cpp index bd25be4..cdbd667 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -328,45 +328,19 @@ uint16_t taurustones[28] = { 165, 175, 196, 220, void MotorDriver::setDCSignal(byte speedcode) { 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; #ifdef VARIABLE_TONES if (tSpeed > 2) { @@ -376,18 +350,13 @@ void MotorDriver::setDCSignal(byte speedcode) { } #endif DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup + DCCTimer::DCCEXanalogWrite(brakePin,brake); +#else // all AVR here + DCCTimer::DCCEXanalogWriteFrequency(brakePin, 0); // 0 is lowest possible f, like 120Hz + 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(); @@ -455,39 +424,7 @@ void MotorDriver::throttleInrush(bool on) { } #else 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, 3); } analogWrite(brakePin,duty); #endif From 67387d2dc320f04bbd9887abf41057a59d4d867f Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 30 Dec 2023 22:09:01 +0100 Subject: [PATCH 02/18] function bits to freqency step #2 --- DCC.cpp | 12 ++++++++++-- DCC.h | 1 + MotorDriver.cpp | 6 +++--- MotorDriver.h | 2 +- TrackManager.cpp | 7 +++++-- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index 0c5148a..bd07b84 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -138,7 +138,7 @@ void DCC::setFunctionInternal(int cab, byte byte1, byte byte2, byte count) { // returns speed steps 0 to 127 (1 == emergency stop) // or -1 on "loco not found" -int8_t DCC::getThrottleSpeed(int cab) { +static int8_t DCC::getThrottleSpeed(int cab) { int reg=lookupSpeedTable(cab); if (reg<0) return -1; return speedTable[reg].speedCode & 0x7F; @@ -146,13 +146,21 @@ int8_t DCC::getThrottleSpeed(int cab) { // returns speed code byte // or 128 (speed 0, dir forward) on "loco not found". -uint8_t DCC::getThrottleSpeedByte(int cab) { +static uint8_t DCC::getThrottleSpeedByte(int cab) { int reg=lookupSpeedTable(cab); if (reg<0) return 128; return speedTable[reg].speedCode; } +// returns -1 for fault, 0 to 3 for frequency +static int8_t DCC::getThrottleFrequency(int cab) { + int reg=lookupSpeedTable(cab); + if (reg<0) + return -1; + return (int8_t)(speedTable[reg].functions >>29); // shift out first 29 bits so we have the "frequency bits" left +} + // returns direction on loco // or true/forward on "loco not found" bool DCC::getThrottleDirection(int cab) { diff --git a/DCC.h b/DCC.h index 3bf0cf5..cbc5372 100644 --- a/DCC.h +++ b/DCC.h @@ -61,6 +61,7 @@ public: static void setThrottle(uint16_t cab, uint8_t tSpeed, bool tDirection); static int8_t getThrottleSpeed(int cab); static uint8_t getThrottleSpeedByte(int cab); + static int8_t getThrottleFrequency(int cab); static bool getThrottleDirection(int cab); static void writeCVByteMain(int cab, int cv, byte bValue); static void writeCVBitMain(int cab, int cv, byte bNum, bool bValue); diff --git a/MotorDriver.cpp b/MotorDriver.cpp index cdbd667..c1c9492 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -325,7 +325,7 @@ 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; // spedcoode is a dcc speed & direction @@ -341,7 +341,7 @@ void MotorDriver::setDCSignal(byte speedcode) { { // 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) { @@ -352,7 +352,7 @@ void MotorDriver::setDCSignal(byte speedcode) { DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup DCCTimer::DCCEXanalogWrite(brakePin,brake); #else // all AVR here - DCCTimer::DCCEXanalogWriteFrequency(brakePin, 0); // 0 is lowest possible f, like 120Hz + DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps 0 to 3 analogWrite(brakePin,brake); #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 4a501a1..f7be01a 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -348,8 +348,11 @@ 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); + int8_t frequency = DCC::getThrottleFrequency(trackDCAddr[t]); + if (frequency <0) // loco was not found + frequency = 0; // default + uint8_t speedByte = DCC::getThrottleSpeedByte(trackDCAddr[t]); + track[t]->setDCSignal(speedByte, (uint8_t)frequency); } bool TrackManager::parseEqualSign(Print *stream, int16_t params, int16_t p[]) From bf17f2018b83ae8227b273333b337ec53b0fee76 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 30 Dec 2023 22:20:41 +0100 Subject: [PATCH 03/18] fix type and static warning step #3 --- DCC.cpp | 10 +++++----- DCC.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index bd07b84..c3cd66f 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -138,7 +138,7 @@ void DCC::setFunctionInternal(int cab, byte byte1, byte byte2, byte count) { // returns speed steps 0 to 127 (1 == emergency stop) // or -1 on "loco not found" -static int8_t DCC::getThrottleSpeed(int cab) { +int8_t DCC::getThrottleSpeed(int cab) { int reg=lookupSpeedTable(cab); if (reg<0) return -1; return speedTable[reg].speedCode & 0x7F; @@ -146,7 +146,7 @@ static int8_t DCC::getThrottleSpeed(int cab) { // returns speed code byte // or 128 (speed 0, dir forward) on "loco not found". -static uint8_t DCC::getThrottleSpeedByte(int cab) { +uint8_t DCC::getThrottleSpeedByte(int cab) { int reg=lookupSpeedTable(cab); if (reg<0) return 128; @@ -154,7 +154,7 @@ static uint8_t DCC::getThrottleSpeedByte(int cab) { } // returns -1 for fault, 0 to 3 for frequency -static int8_t DCC::getThrottleFrequency(int cab) { +int8_t DCC::getThrottleFrequency(int cab) { int reg=lookupSpeedTable(cab); if (reg<0) return -1; @@ -199,8 +199,8 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) { // Take care of functions: // Set state of function - unsigned long previous=speedTable[reg].functions; - unsigned long funcmask = (1UL< Date: Sun, 31 Dec 2023 10:48:48 +0100 Subject: [PATCH 04/18] DC frequency fix bit shifting (debug code) step #4 --- DCC.cpp | 19 ++++++++++++------- DCC.h | 2 +- DCCTimerAVR.cpp | 4 ++-- GITHUB_SHA.h | 2 +- MotorDriver.cpp | 1 + TrackManager.cpp | 9 +++------ 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index c3cd66f..d857cb8 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -153,12 +153,14 @@ uint8_t DCC::getThrottleSpeedByte(int cab) { return speedTable[reg].speedCode; } -// returns -1 for fault, 0 to 3 for frequency -int8_t DCC::getThrottleFrequency(int cab) { +// returns 0 to 3 for frequency +uint8_t DCC::getThrottleFrequency(int cab) { int reg=lookupSpeedTable(cab); if (reg<0) - return -1; - return (int8_t)(speedTable[reg].functions >>29); // shift out first 29 bits so we have the "frequency bits" left + return 0; // use default frequency + uint8_t res = (uint8_t)(speedTable[reg].functions >>30); + DIAG(F("Speed table %d functions %l shifted %d"), reg, speedTable[reg].functions, res); + return res; // shift out first 29 bits so we have the "frequency bits" left } // returns direction on loco @@ -191,9 +193,12 @@ 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. + if (functionNumber > 31) + return true; + int reg = lookupSpeedTable(cab); if (reg<0) return false; @@ -206,7 +211,7 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) { } else { speedTable[reg].functions &= ~funcmask; } - if (speedTable[reg].functions != previous) { + if (speedTable[reg].functions != previous && functionNumber > 28) { updateGroupflags(speedTable[reg].groupFlags, functionNumber); CommandDistributor::broadcastLoco(reg); } diff --git a/DCC.h b/DCC.h index bccdd24..b5cb0e9 100644 --- a/DCC.h +++ b/DCC.h @@ -61,7 +61,7 @@ public: static void setThrottle(uint16_t cab, uint8_t tSpeed, bool tDirection); static int8_t getThrottleSpeed(int cab); static uint8_t getThrottleSpeedByte(int cab); - static int8_t getThrottleFrequency(int cab); + static uint8_t getThrottleFrequency(int cab); static bool getThrottleDirection(int cab); static void writeCVByteMain(int cab, int cv, byte bValue); static void writeCVBitMain(int cab, int cv, byte bNum, bool bValue); diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index b27a906..90d43a7 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -142,9 +142,9 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { if (pin == 9 || pin == 10) { // timer 2 is different if (fbits >= 3) - abits = B11; + abits = B00000011; else - abits = B01; + abits = B00000001; if (fbits >= 3) bbits = B0001; diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index 42646fe..1ccc6e5 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202312251647Z" +#define GITHUB_SHA "devel-202312310824Z" diff --git a/MotorDriver.cpp b/MotorDriver.cpp index c1c9492..265c8ed 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -349,6 +349,7 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/) } } #endif + DIAG(F("Brake %d freqencybits %x"), brakePin, f); DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup DCCTimer::DCCEXanalogWrite(brakePin,brake); #else // all AVR here diff --git a/TrackManager.cpp b/TrackManager.cpp index f7be01a..e2d4d27 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -202,7 +202,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])); } } @@ -348,11 +348,8 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr } void TrackManager::applyDCSpeed(byte t) { - int8_t frequency = DCC::getThrottleFrequency(trackDCAddr[t]); - if (frequency <0) // loco was not found - frequency = 0; // default - uint8_t speedByte = DCC::getThrottleSpeedByte(trackDCAddr[t]); - track[t]->setDCSignal(speedByte, (uint8_t)frequency); + track[t]->setDCSignal(DCC::getThrottleSpeedByte(trackDCAddr[t]), + DCC::getThrottleFrequency(trackDCAddr[t])); } bool TrackManager::parseEqualSign(Print *stream, int16_t params, int16_t p[]) From d4f0a7c8f35da240412a671514e45cd40866836a Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 31 Dec 2023 13:18:28 +0100 Subject: [PATCH 05/18] DC frequency uno does not have timers anyway step #5 --- DCC.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DCC.cpp b/DCC.cpp index d857cb8..ea6e910 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -155,12 +155,17 @@ uint8_t DCC::getThrottleSpeedByte(int cab) { // returns 0 to 3 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 uint8_t res = (uint8_t)(speedTable[reg].functions >>30); DIAG(F("Speed table %d functions %l shifted %d"), reg, speedTable[reg].functions, res); return res; // shift out first 29 bits so we have the "frequency bits" left +#endif } // returns direction on loco From ab58c38e7bbc4f132caf8d2459fa4475e337db37 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 31 Dec 2023 13:22:34 +0100 Subject: [PATCH 06/18] motordriver frequency diag --- MotorDriver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 265c8ed..b304204 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -349,7 +349,7 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/) } } #endif - DIAG(F("Brake %d freqencybits %x"), brakePin, f); + DIAG(F("Brake %d freqency %d"), brakePin, f); DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency to 100Hz XXX May move to setup DCCTimer::DCCEXanalogWrite(brakePin,brake); #else // all AVR here @@ -423,7 +423,7 @@ void MotorDriver::throttleInrush(bool on) { } else { pinMode(brakePin, OUTPUT); } -#else +#else // all AVR here if(on){ DCCTimer::DCCEXanalogWriteFrequency(brakePin, 3); } From bba74a08f6710dc59457f3fafcdd19ce127c1d0e Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 31 Dec 2023 13:22:42 +0100 Subject: [PATCH 07/18] Do not support obsolete on memory tight arch --- DCCEXParser.cpp | 3 ++- TrackManager.cpp | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index aefed4c..0c4a4d8 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -625,12 +625,13 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1. return; +#ifdef HAVE_ENOUGH_MEMORY case 'c': // SEND METER RESPONSES // 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/TrackManager.cpp b/TrackManager.cpp index e2d4d27..1e2f88d 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -574,14 +574,15 @@ 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 HAVE_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); +#endif } void TrackManager::reportCurrent(Print* stream) { From 36cc46e88ded2e9653088348e7839c2ba6e0bc24 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 31 Dec 2023 13:52:37 +0100 Subject: [PATCH 08/18] DC frequency dummy functions for odd architectures step #6 --- DCCTimerMEGAAVR.cpp | 5 +++++ DCCTimerSAMD.cpp | 5 +++++ DCCTimerTEENSY.cpp | 5 +++++ 3 files changed, 15 insertions(+) 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/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; } From 19efa749b8c5e7b00e63ee9fe6ca7daa32c5f36f Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 31 Dec 2023 17:57:30 +0100 Subject: [PATCH 09/18] Typo fix HAS vs HAVE --- DCCEXParser.cpp | 2 +- TrackManager.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 0c4a4d8..23b80ab 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -625,7 +625,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) DCC::setThrottle(0,1,1); // this broadcasts speed 1(estop) and sets all reminders to speed 1. return; -#ifdef HAVE_ENOUGH_MEMORY +#ifdef HAS_ENOUGH_MEMORY case 'c': // SEND METER RESPONSES // No longer useful because of multiple tracks See and if (params>0) break; diff --git a/TrackManager.cpp b/TrackManager.cpp index 1e2f88d..b76bb8b 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" @@ -578,10 +579,12 @@ 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 HAVE_ENOUGH_MEMORY +#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); +#else + (void)stream; #endif } From 9ebb1c5fb1b3abd3b2fc23d5411615c80937a922 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Mon, 1 Jan 2024 21:25:43 +0100 Subject: [PATCH 10/18] less debug diag --- DCC.cpp | 4 ++-- DCCTimerAVR.cpp | 6 +++--- MotorDriver.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index ea6e910..59e08c9 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -163,8 +163,8 @@ uint8_t DCC::getThrottleFrequency(int cab) { if (reg<0) return 0; // use default frequency uint8_t res = (uint8_t)(speedTable[reg].functions >>30); - DIAG(F("Speed table %d functions %l shifted %d"), reg, speedTable[reg].functions, res); - return res; // shift out first 29 bits so we have the "frequency bits" left + //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 #endif } diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index 90d43a7..e0fe941 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -157,7 +157,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { 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); + //DIAG(F("Timer 2 A=%x B=%x"), TCCR2A, TCCR2B); } else { // not timer 9 or 10 abits = B01; @@ -179,7 +179,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { // 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); + //DIAG(F("Timer 4 A=%x B=%x"), TCCR4A, TCCR4B); break; case 46: case 45: @@ -187,7 +187,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { // 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); + //DIAG(F("Timer 5 A=%x B=%x"), TCCR5A, TCCR5B); break; default: break; diff --git a/MotorDriver.cpp b/MotorDriver.cpp index b304204..3c207f2 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -349,7 +349,7 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/) } } #endif - DIAG(F("Brake %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::DCCEXanalogWrite(brakePin,brake); #else // all AVR here From 3ce9d2ec8876953a000e15fe18756010ecb6bfd8 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Mon, 1 Jan 2024 22:08:04 +0100 Subject: [PATCH 11/18] DC frequency fix broadcast messages step #7 --- CommandDistributor.cpp | 4 +++- DCC.cpp | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) 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 59e08c9..76e1509 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -216,28 +216,34 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) { } else { speedTable[reg].functions &= ~funcmask; } - if (speedTable[reg].functions != previous && functionNumber > 28) { + if (speedTable[reg].functions != previous && functionNumber <= 28) { updateGroupflags(speedTable[reg].groupFlags, functionNumber); CommandDistributor::broadcastLoco(reg); } return true; } -// Flip function state +// Flip function state (used from withrottle protocol) void DCC::changeFn( int cab, int16_t functionNumber) { - if (cab<=0 || functionNumber>28) return; + if (cab<=0 || functionNumber>31) return; int reg = lookupSpeedTable(cab); if (reg<0) return; unsigned long funcmask = (1UL<28) return -1; // unknown + 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< Date: Mon, 1 Jan 2024 22:08:59 +0100 Subject: [PATCH 12/18] Make return type of DCC::getFn int8_t --- DCC.cpp | 2 +- DCC.h | 2 +- WiThrottle.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index 76e1509..dbc72e3 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -238,7 +238,7 @@ void DCC::changeFn( int cab, int16_t functionNumber) { // Report function state (used from withrottle protocol) // returns 0 false, 1 true or -1 for do not know -int DCC::getFn( int cab, int16_t functionNumber) { +int8_t DCC::getFn( int cab, int16_t functionNumber) { if (cab<=0 || functionNumber>28) return -1; // unknown int reg = lookupSpeedTable(cab); diff --git a/DCC.h b/DCC.h index b5cb0e9..1deaf71 100644 --- a/DCC.h +++ b/DCC.h @@ -68,7 +68,7 @@ public: static void setFunction(int cab, byte fByte, byte eByte); static bool setFn(int cab, int16_t functionNumber, bool on); static void changeFn(int cab, int16_t functionNumber); - static int getFn(int cab, int16_t functionNumber); + static int8_t getFn(int cab, int16_t functionNumber); static uint32_t getFunctionMap(int cab); static void updateGroupflags(byte &flags, int16_t functionNumber); static void setAccessory(int address, byte port, bool gate, byte onoff = 2); 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); } } From 6f076720f74acbe9d26c8939959a2c21574eb593 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Mon, 1 Jan 2024 22:17:47 +0100 Subject: [PATCH 13/18] temp version tag --- GITHUB_SHA.h | 2 +- version.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index 1ccc6e5..c09f13c 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202312310824Z" +#define GITHUB_SHA "devel-202401012116Z" diff --git a/version.h b/version.h index bc79b3e..80711eb 100644 --- a/version.h +++ b/version.h @@ -3,7 +3,8 @@ #include "StringFormatter.h" -#define VERSION "5.2.17" +#define VERSION "5.2.XX" +// 5.2.XX - Variable frequency for DC mode // 5.2.17 - ESP32 simplify network logic // 5.2.16 - Bugfix to allow for devices using the EX-IOExpander protocol to have no analogue or no digital pins // 5.2.15 - move call to CommandDistributor::broadcastPower() into the TrackManager::setTrackPower(*) functions From 8036ba1c4857e71746830dbf54ab76a1ffd77070 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Wed, 3 Jan 2024 02:44:15 +0100 Subject: [PATCH 14/18] temp version tag --- GITHUB_SHA.h | 2 +- WifiESP32.cpp | 2 +- version.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index c09f13c..affe86c 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202401012116Z" +#define GITHUB_SHA "devel-202401030142Z" diff --git a/WifiESP32.cpp b/WifiESP32.cpp index c990495..2aef5d1 100644 --- a/WifiESP32.cpp +++ b/WifiESP32.cpp @@ -179,7 +179,7 @@ bool WifiESP::setup(const char *SSid, if (WiFi.status() == WL_CONNECTED) { // DIAG(F("Wifi STA IP %s"),WiFi.localIP().toString().c_str()); DIAG(F("Wifi in STA mode")); - LCD(7, F("IP: %s"), WiFi.softAPIP().toString().c_str()); + LCD(7, F("IP: %s"), WiFi.localIP().toString().c_str()); wifiUp = true; } else { DIAG(F("Could not connect to Wifi SSID %s"),SSid); diff --git a/version.h b/version.h index 80711eb..1677a49 100644 --- a/version.h +++ b/version.h @@ -5,6 +5,7 @@ #define VERSION "5.2.XX" // 5.2.XX - Variable frequency for DC mode +// 5.2.18 - Display network IP fix // 5.2.17 - ESP32 simplify network logic // 5.2.16 - Bugfix to allow for devices using the EX-IOExpander protocol to have no analogue or no digital pins // 5.2.15 - move call to CommandDistributor::broadcastPower() into the TrackManager::setTrackPower(*) functions From a5b73c823a0d79e786ebc530ebc7c238b5d60373 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Sat, 20 Jan 2024 18:09:03 +0000 Subject: [PATCH 15/18] Added SETFREQ command Added SETFREQ command to EXRAIL --- DCCTimerAVR.cpp | 2 +- EXRAIL2.cpp | 37 +++++++++++++++++++++++++++++++++++++ EXRAIL2.h | 2 +- EXRAIL2MacroReset.h | 2 ++ EXRAILMacros.h | 1 + 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index e0fe941..5c361a0 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -157,7 +157,7 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { 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); + DIAG(F("Timer 2 A=%x B=%x"), TCCR2A, TCCR2B); } else { // not timer 9 or 10 abits = B01; diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index cc3269b..de254a6 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -667,6 +667,43 @@ 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); + if (loco) { + DCC::setFn(loco,30,true); + DCC::setFn(loco,31,false); + } + break; + case 2: + //if (loco) DCC::setFn(loco,30,true); + if (loco) { + DCC::setFn(loco,30,false); + DCC::setFn(loco,31,true); + } + break; + case 3: + //if (loco) DCC::setFn(loco,31,true); + if (loco) { + DCC::setFn(loco,30,true); + DCC::setFn(loco,31,true); + } + 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 7811a0d..8ab854d 100644 --- a/EXRAIL2MacroReset.h +++ b/EXRAIL2MacroReset.h @@ -151,6 +151,7 @@ #undef SET_TRACK #undef SET_POWER #undef SETLOCO +#undef SETFREQ #undef SIGNAL #undef SIGNALH #undef SPEED @@ -302,6 +303,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 f79693d..93ea911 100644 --- a/EXRAILMacros.h +++ b/EXRAILMacros.h @@ -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_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), From 99a09c713fa702d1a73688f17e8340d9efc9f3e7 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 20 Jan 2024 23:34:17 +0100 Subject: [PATCH 16/18] To make usage easier, use F29 to F31 for frequencies --- DCC.cpp | 13 ++++++++----- DCCTimerAVR.cpp | 17 +++++++++++------ DCCTimerESP.cpp | 8 ++++++-- DCCTimerSTM32.cpp | 8 ++++++-- EXRAIL2.cpp | 24 +++++++++++++----------- MotorDriver.cpp | 12 ++++++------ 6 files changed, 50 insertions(+), 32 deletions(-) diff --git a/DCC.cpp b/DCC.cpp index dbc72e3..95464af 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -153,7 +153,7 @@ uint8_t DCC::getThrottleSpeedByte(int cab) { return speedTable[reg].speedCode; } -// returns 0 to 3 for frequency +// returns 0 to 7 for frequency uint8_t DCC::getThrottleFrequency(int cab) { #if defined(ARDUINO_AVR_UNO) (void)cab; @@ -161,10 +161,11 @@ uint8_t DCC::getThrottleFrequency(int cab) { #else int reg=lookupSpeedTable(cab); if (reg<0) - return 0; // use default frequency - uint8_t res = (uint8_t)(speedTable[reg].functions >>30); + 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; // shift out first 30 bits so we have the "frequency bits" left + return res; #endif } @@ -200,7 +201,9 @@ bool DCC::setFn( int cab, int16_t functionNumber, bool on) { DCCWaveform::mainTrack.schedulePacket(b, nB, 4); } // 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) return true; diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index 5c361a0..3bb2b9f 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -137,22 +137,27 @@ 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. #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 >= 3) + if (fbits >= 4) abits = B00000011; else abits = B00000001; - if (fbits >= 3) + if (fbits >= 4) bbits = B0001; - else if (fbits == 2) + else if (fbits >= 2) bbits = B0010; else if (fbits == 1) bbits = B0100; - else + else // fbits == 0 bbits = B0110; TCCR2A = (TCCR2A & B11111100) | abits; // set WGM0 and WGM1 @@ -162,9 +167,9 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t fbits) { } else { // not timer 9 or 10 abits = B01; - if (fbits >= 3) + if (fbits >= 4) bbits = B1001; - else if (fbits == 2) + else if (fbits >= 2) bbits = B0010; else if (fbits == 1) bbits = B0011; diff --git a/DCCTimerESP.cpp b/DCCTimerESP.cpp index dbd4e9d..ae81c74 100644 --- a/DCCTimerESP.cpp +++ b/DCCTimerESP.cpp @@ -154,9 +154,13 @@ void DCCTimer::reset() { void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { if (f >= 16) DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); - else if (f >= 3) + else if (f == 7) 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); else if (f == 1) DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480); diff --git a/DCCTimerSTM32.cpp b/DCCTimerSTM32.cpp index c220620..19f97b9 100644 --- a/DCCTimerSTM32.cpp +++ b/DCCTimerSTM32.cpp @@ -260,9 +260,13 @@ void DCCTimer::reset() { void DCCTimer::DCCEXanalogWriteFrequency(uint8_t pin, uint32_t f) { if (f >= 16) DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, f); - else if (f >= 3) + else if (f == 7) 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); else if (f == 1) DCCTimer::DCCEXanalogWriteFrequencyInternal(pin, 480); diff --git a/EXRAIL2.cpp b/EXRAIL2.cpp index de254a6..d4537d2 100644 --- a/EXRAIL2.cpp +++ b/EXRAIL2.cpp @@ -679,27 +679,29 @@ void RMFT2::loop2() { } break; case 1: - //if (loco) DCC::setFn(loco,29,true); if (loco) { - DCC::setFn(loco,30,true); + DCC::setFn(loco,29,true); + DCC::setFn(loco,30,false); DCC::setFn(loco,31,false); } break; case 2: - //if (loco) DCC::setFn(loco,30,true); 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; - case 3: - //if (loco) DCC::setFn(loco,31,true); - if (loco) { - DCC::setFn(loco,30,true); - DCC::setFn(loco,31,true); - } - break; - + default: + ; // do nothing + break; } break; diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 3c207f2..09e2c58 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -350,10 +350,10 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/) } #endif //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); #else // all AVR here - DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps 0 to 3 + DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps analogWrite(brakePin,brake); #endif } @@ -406,26 +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 // all AVR here if(on){ - DCCTimer::DCCEXanalogWriteFrequency(brakePin, 3); + DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max } analogWrite(brakePin,duty); #endif From 9728d19b19dcdb4010818ad4e3f730ed89128af2 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 20 Jan 2024 23:35:30 +0100 Subject: [PATCH 17/18] eliminate warning --- I2CManager_STM32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/I2CManager_STM32.h b/I2CManager_STM32.h index 7e0f547..821add6 100644 --- a/I2CManager_STM32.h +++ b/I2CManager_STM32.h @@ -110,7 +110,7 @@ void I2CManagerClass::I2C_setClock(uint32_t i2cClockSpeed) { // Calculate a rise time appropriate to the requested bus speed // Use 10x the rise time spec to enable integer divide of 50ns clock period uint16_t t_rise; - uint32_t ccr_freq; + //uint32_t ccr_freq; while (s->CR1 & I2C_CR1_STOP); // Prevents lockup by guarding further // writes to CR1 while STOP is being executed! From daa2ffc459337af98ce595f8319d7bc4e1071eb3 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 20 Jan 2024 23:36:11 +0100 Subject: [PATCH 18/18] tag --- GITHUB_SHA.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GITHUB_SHA.h b/GITHUB_SHA.h index affe86c..26195f4 100644 --- a/GITHUB_SHA.h +++ b/GITHUB_SHA.h @@ -1 +1 @@ -#define GITHUB_SHA "devel-202401030142Z" +#define GITHUB_SHA "devel-202401202235Z"