mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-27 01:56:14 +01:00
ESP32 fix PWM LEDC inverted pin mode
This commit is contained in:
parent
cff4075937
commit
dc5f5e05b9
|
@ -65,10 +65,12 @@ class DCCTimer {
|
||||||
static void startRailcomTimer(byte brakePin);
|
static void startRailcomTimer(byte brakePin);
|
||||||
static void ackRailcomTimer();
|
static void ackRailcomTimer();
|
||||||
static void DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency);
|
static void DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency);
|
||||||
static void DCCEXanalogWrite(uint8_t pin, int value);
|
static void DCCEXanalogWrite(uint8_t pin, int value, bool invert);
|
||||||
static void DCCEXledcDetachPin(uint8_t pin);
|
static void DCCEXledcDetachPin(uint8_t pin);
|
||||||
static void DCCEXanalogCopyChannel(uint8_t frompin, uint8_t topin);
|
static void DCCEXanalogCopyChannel(int8_t frompin, int8_t topin);
|
||||||
static void DCCEXInrushControlOn(uint8_t pin, int duty);
|
static void DCCEXInrushControlOn(uint8_t pin, int duty, bool invert);
|
||||||
|
static void DCCEXledcAttachPin(uint8_t pin, int8_t channel, bool inverted);
|
||||||
|
|
||||||
// Update low ram level. Allow for extra bytes to be specified
|
// Update low ram level. Allow for extra bytes to be specified
|
||||||
// by estimation or inspection, that may be used by other
|
// by estimation or inspection, that may be used by other
|
||||||
// called subroutines. Must be called with interrupts disabled.
|
// called subroutines. Must be called with interrupts disabled.
|
||||||
|
|
|
@ -197,13 +197,48 @@ void DCCTimer::DCCEXledcDetachPin(uint8_t pin) {
|
||||||
pinMatrixOutDetach(pin, false, false);
|
pinMatrixOutDetach(pin, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte LEDCToMux[] = {
|
||||||
|
LEDC_HS_SIG_OUT0_IDX,
|
||||||
|
LEDC_HS_SIG_OUT1_IDX,
|
||||||
|
LEDC_HS_SIG_OUT2_IDX,
|
||||||
|
LEDC_HS_SIG_OUT3_IDX,
|
||||||
|
LEDC_HS_SIG_OUT4_IDX,
|
||||||
|
LEDC_HS_SIG_OUT5_IDX,
|
||||||
|
LEDC_HS_SIG_OUT6_IDX,
|
||||||
|
LEDC_HS_SIG_OUT7_IDX,
|
||||||
|
LEDC_LS_SIG_OUT0_IDX,
|
||||||
|
LEDC_LS_SIG_OUT1_IDX,
|
||||||
|
LEDC_LS_SIG_OUT2_IDX,
|
||||||
|
LEDC_LS_SIG_OUT3_IDX,
|
||||||
|
LEDC_LS_SIG_OUT4_IDX,
|
||||||
|
LEDC_LS_SIG_OUT5_IDX,
|
||||||
|
LEDC_LS_SIG_OUT6_IDX,
|
||||||
|
LEDC_LS_SIG_OUT7_IDX,
|
||||||
|
};
|
||||||
|
|
||||||
void DCCTimer::DCCEXanalogCopyChannel(uint8_t frompin, uint8_t topin) {
|
void DCCTimer::DCCEXledcAttachPin(uint8_t pin, int8_t channel, bool inverted) {
|
||||||
DIAG(F("Pin %d copied to %d channel %d"), frompin, topin, pin_to_channel[frompin]);
|
DIAG(F("Attaching pin %d to channel %d %c"), pin, channel, inverted ? 'I' : ' ');
|
||||||
pin_to_channel[topin] = pin_to_channel[frompin];
|
ledcAttachPin(pin, channel);
|
||||||
ledcAttachPin(topin, pin_to_channel[topin]);
|
if (inverted) // we attach again but with inversion
|
||||||
|
gpio_matrix_out(pin, LEDCToMux[channel], inverted, 0);
|
||||||
}
|
}
|
||||||
void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value) {
|
|
||||||
|
void DCCTimer::DCCEXanalogCopyChannel(int8_t frompin, int8_t topin) {
|
||||||
|
// arguments are signed depending on inversion of pins
|
||||||
|
DIAG(F("Pin %d copied to %d"), frompin, topin);
|
||||||
|
bool inverted = false;
|
||||||
|
if (frompin<0)
|
||||||
|
frompin = -frompin;
|
||||||
|
if (topin<0) {
|
||||||
|
inverted = true;
|
||||||
|
topin = -topin;
|
||||||
|
}
|
||||||
|
int channel = pin_to_channel[frompin]; // after abs(frompin)
|
||||||
|
pin_to_channel[topin] = channel;
|
||||||
|
DCCTimer::DCCEXledcAttachPin(topin, channel, inverted);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value, bool invert) {
|
||||||
// This allocates channels 15, 13, 11, ....
|
// This allocates channels 15, 13, 11, ....
|
||||||
// so each channel gets its own timer.
|
// so each channel gets its own timer.
|
||||||
if (pin < SOC_GPIO_PIN_COUNT) {
|
if (pin < SOC_GPIO_PIN_COUNT) {
|
||||||
|
@ -237,17 +272,20 @@ void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value) {
|
||||||
--cnt_channel; // Now we are at 14, 12, ...
|
--cnt_channel; // Now we are at 14, 12, ...
|
||||||
}
|
}
|
||||||
ledcSetup(pin_to_channel[pin], 1000, 8);
|
ledcSetup(pin_to_channel[pin], 1000, 8);
|
||||||
ledcAttachPin(pin, pin_to_channel[pin]);
|
DCCEXledcAttachPin(pin, pin_to_channel[pin], invert);
|
||||||
} else {
|
} else {
|
||||||
//DIAG(F("Pin %d assigned to old channel %d"), pin, pin_to_channel[pin]);
|
// This else is only here so we can enable diag
|
||||||
ledcAttachPin(pin, pin_to_channel[pin]);
|
// Pin should be already attached to channel
|
||||||
|
// DIAG(F("Pin %d assigned to old channel %d"), pin, pin_to_channel[pin]);
|
||||||
}
|
}
|
||||||
ledcWrite(pin_to_channel[pin], value);
|
ledcWrite(pin_to_channel[pin], value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void DCCTimer::DCCEXInrushControlOn(uint8_t pin, int duty) {
|
|
||||||
|
void DCCTimer::DCCEXInrushControlOn(uint8_t pin, int duty, bool inverted) {
|
||||||
|
// this uses hardcoded channel 0
|
||||||
ledcSetup(0, 62500, 8);
|
ledcSetup(0, 62500, 8);
|
||||||
ledcAttachPin(pin, 0);
|
DCCEXledcAttachPin(pin, 0, inverted);
|
||||||
ledcWrite(0, duty);
|
ledcWrite(0, duty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,9 @@ void DCCTimer::DCCEXanalogWriteFrequencyInternal(uint8_t pin, uint32_t frequency
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value) {
|
void DCCTimer::DCCEXanalogWrite(uint8_t pin, int value, bool invert) {
|
||||||
|
if (invert)
|
||||||
|
value = 255-value;
|
||||||
// Calculate percentage duty cycle from value given
|
// Calculate percentage duty cycle from value given
|
||||||
uint32_t duty_cycle = (value * 100 / 256) + 1;
|
uint32_t duty_cycle = (value * 100 / 256) + 1;
|
||||||
if (pin_timer[pin] != NULL) {
|
if (pin_timer[pin] != NULL) {
|
||||||
|
|
|
@ -336,8 +336,6 @@ void MotorDriver::setDCSignal(byte speedcode, uint8_t frequency /*default =0*/)
|
||||||
if (tSpeed <= 1) brake = 255;
|
if (tSpeed <= 1) brake = 255;
|
||||||
else if (tSpeed >= 127) brake = 0;
|
else if (tSpeed >= 127) brake = 0;
|
||||||
else brake = 2 * (128-tSpeed);
|
else brake = 2 * (128-tSpeed);
|
||||||
if (invertBrake)
|
|
||||||
brake=255-brake;
|
|
||||||
|
|
||||||
{ // new block because of variable f
|
{ // new block because of variable f
|
||||||
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32)
|
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_STM32)
|
||||||
|
@ -351,10 +349,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
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, f); // set DC PWM frequency
|
||||||
DCCTimer::DCCEXanalogWrite(brakePin,brake);
|
DCCTimer::DCCEXanalogWrite(brakePin, brake, invertBrake);
|
||||||
#else // all AVR here
|
#else // all AVR here
|
||||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, frequency); // frequency steps
|
||||||
analogWrite(brakePin,brake);
|
analogWrite(brakePin, invertBrake ? 255-brake : brake);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,16 +405,16 @@ void MotorDriver::throttleInrush(bool on) {
|
||||||
if ( !(trackMode & (TRACK_MODE_MAIN | TRACK_MODE_PROG | TRACK_MODE_EXT | TRACK_MODE_BOOST)))
|
if ( !(trackMode & (TRACK_MODE_MAIN | TRACK_MODE_PROG | TRACK_MODE_EXT | TRACK_MODE_BOOST)))
|
||||||
return;
|
return;
|
||||||
byte duty = on ? 207 : 0; // duty of 81% at 62500Hz this gives pauses of 3usec
|
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 defined(ARDUINO_ARCH_ESP32)
|
||||||
if(on) {
|
if(on) {
|
||||||
DCCTimer::DCCEXInrushControlOn(brakePin, duty);
|
DCCTimer::DCCEXInrushControlOn(brakePin, duty, invertBrake);
|
||||||
} else {
|
} else {
|
||||||
ledcDetachPin(brakePin); // not DCCTimer::DCCEXledcDetachPin() as we have not
|
ledcDetachPin(brakePin); // not DCCTimer::DCCEXledcDetachPin() as we have not
|
||||||
// registered the pin in the pin to channel array
|
// registered the pin in the pin to channel array
|
||||||
}
|
}
|
||||||
#elif defined(ARDUINO_ARCH_STM32)
|
#elif defined(ARDUINO_ARCH_STM32)
|
||||||
|
if (invertBrake)
|
||||||
|
duty = 255-duty;
|
||||||
if(on) {
|
if(on) {
|
||||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
|
||||||
DCCTimer::DCCEXanalogWrite(brakePin,duty);
|
DCCTimer::DCCEXanalogWrite(brakePin,duty);
|
||||||
|
@ -424,6 +422,8 @@ void MotorDriver::throttleInrush(bool on) {
|
||||||
pinMode(brakePin, OUTPUT);
|
pinMode(brakePin, OUTPUT);
|
||||||
}
|
}
|
||||||
#else // all AVR here
|
#else // all AVR here
|
||||||
|
if (invertBrake)
|
||||||
|
duty = 255-duty;
|
||||||
if(on){
|
if(on){
|
||||||
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
|
DCCTimer::DCCEXanalogWriteFrequency(brakePin, 7); // 7 means max
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,7 @@ class MotorDriver {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
inline pinpair getSignalPin() { return pinpair(signalPin,signalPin2); };
|
inline pinpair getSignalPin() { return pinpair(signalPin,signalPin2); };
|
||||||
inline byte getBrakePin() { return brakePin; };
|
inline int8_t getBrakePinSigned() { return invertBrake ? -brakePin : brakePin; };
|
||||||
void setDCSignal(byte speedByte, uint8_t frequency=0);
|
void setDCSignal(byte speedByte, uint8_t frequency=0);
|
||||||
void throttleInrush(bool on);
|
void throttleInrush(bool on);
|
||||||
inline void detachDCSignal() {
|
inline void detachDCSignal() {
|
||||||
|
|
|
@ -264,14 +264,18 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
int trackfound = -1;
|
int trackfound = -1;
|
||||||
FOR_EACH_TRACK(t) {
|
FOR_EACH_TRACK(t) {
|
||||||
if ((track[t]->getMode() & TRACK_MODE_DC) && trackDCAddr[t] == dcAddr) {
|
//DIAG(F("Checking track %c mode %x dcAddr %d"), 'A'+t, track[t]->getMode(), trackDCAddr[t]);
|
||||||
|
if (t != trackToSet // not our track
|
||||||
|
&& (track[t]->getMode() & TRACK_MODE_DC) // right mode
|
||||||
|
&& trackDCAddr[t] == dcAddr) { // right addr
|
||||||
|
//DIAG(F("Found track %c"), 'A'+t);
|
||||||
trackfound = t;
|
trackfound = t;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trackfound > -1) {
|
if (trackfound > -1) {
|
||||||
DCCTimer::DCCEXanalogCopyChannel(track[trackfound]->getBrakePin(),
|
DCCTimer::DCCEXanalogCopyChannel(track[trackfound]->getBrakePinSigned(),
|
||||||
track[trackToSet]->getBrakePin());
|
track[trackToSet]->getBrakePinSigned());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user