diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 61e229f..15b5607 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -605,6 +605,10 @@ void MotorDriver::checkPowerOverload(bool useProgLimit, byte trackno) { DIAG(F("TRACK %c ALERT FAULT"), trackno + 'A'); } setPower(POWERMODE::ALERT); + if (trackMode & (TRACK_MODE_MAIN|TRACK_MODE_EXT)){ // add (&& isAutoreverse) later + DIAG(F("TRACK %c INVERT"), trackno + 'A'); + invertOutput(); + } break; } // all well diff --git a/MotorDriver.h b/MotorDriver.h index 20a91d3..c6e06b8 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -148,7 +148,9 @@ class MotorDriver { // otherwise the call from interrupt context can undo whatever we do // from outside interrupt void setBrake( bool on, bool interruptContext=false); - __attribute__((always_inline)) inline void setSignal( bool high) { + __attribute__((always_inline)) inline void setSignal( bool high) { + if (invertPhase) + high = !high; if (trackPWM) { DCCTimer::setPWM(signalPin,high); } @@ -168,6 +170,12 @@ class MotorDriver { pinMode(signalPin, OUTPUT); else pinMode(signalPin, INPUT); + if (signalPin2 != UNUSED_PIN) { + if (on) + pinMode(signalPin2, OUTPUT); + else + pinMode(signalPin2, INPUT); + } }; inline pinpair getSignalPin() { return pinpair(signalPin,signalPin2); }; void setDCSignal(byte speedByte); @@ -232,6 +240,32 @@ class MotorDriver { #endif inline void setMode(TRACK_MODE m) { trackMode = m; + invertOutput(trackMode & TRACK_MODE_DCX);// change later to TRACK_MODE_INVERTED? + }; + inline void invertOutput() { // toggles output inversion + invertPhase = !invertPhase; + invertOutput(invertPhase); + }; + inline void invertOutput(bool b) { // sets output inverted or not + if (b) + invertPhase = 1; + else + invertPhase = 0; +#if defined(ARDUINO_ARCH_ESP32) + pinpair p = getSignalPin(); + uint32_t *outreg = (uint32_t *)(GPIO_FUNC0_OUT_SEL_CFG_REG + 4*p.pin); + if (invertPhase) // set or clear the invert bit in the gpio out register + *outreg |= ((uint32_t)0x1 << GPIO_FUNC0_OUT_INV_SEL_S); + else + *outreg &= ~((uint32_t)0x1 << GPIO_FUNC0_OUT_INV_SEL_S); + if (p.invpin != UNUSED_PIN) { + outreg = (uint32_t *)(GPIO_FUNC0_OUT_SEL_CFG_REG + 4*p.invpin); + if (invertPhase) // clear or set the invert bit in the gpio out register + *outreg &= ~((uint32_t)0x1 << GPIO_FUNC0_OUT_INV_SEL_S); + else + *outreg |= ((uint32_t)0x1 << GPIO_FUNC0_OUT_INV_SEL_S); + } +#endif }; inline TRACK_MODE getMode() { return trackMode; @@ -263,7 +297,7 @@ class MotorDriver { bool invertBrake; // brake pin passed as negative means pin is inverted bool invertPower; // power pin passed as negative means pin is inverted bool invertFault; // fault pin passed as negative means pin is inverted - + bool invertPhase = 0; // phase of out pin is inverted // Raw to milliamp conversion factors avoiding float data types. // Milliamps=rawADCreading * sensefactorInternal / senseScale // diff --git a/TrackManager.cpp b/TrackManager.cpp index dedf45e..772f64e 100644 --- a/TrackManager.cpp +++ b/TrackManager.cpp @@ -197,8 +197,8 @@ void TrackManager::setPROGSignal( bool on) { 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); - else if (track[t]->getMode()==TRACK_MODE_DCX) track[t]->setDCSignal(speedbyte ^ 128); + if (track[t]->getMode() & (TRACK_MODE_DC|TRACK_MODE_DCX)) + track[t]->setDCSignal(speedbyte); } } @@ -223,11 +223,18 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr pinpair p = track[trackToSet]->getSignalPin(); //DIAG(F("Track=%c remove pin %d"),trackToSet+'A', p.pin); gpio_reset_pin((gpio_num_t)p.pin); - pinMode(p.pin, OUTPUT); // gpio_reset_pin may reset to input if (p.invpin != UNUSED_PIN) { //DIAG(F("Track=%c remove ^pin %d"),trackToSet+'A', p.invpin); gpio_reset_pin((gpio_num_t)p.invpin); - pinMode(p.invpin, OUTPUT); // gpio_reset_pin may reset to input + } + + if (mode == TRACK_MODE_EXT) { + pinMode(26, INPUT); + gpio_matrix_in(26, SIG_IN_FUNC228_IDX, false); //pads 224 to 228 available as loopback + gpio_matrix_out(p.pin, SIG_IN_FUNC228_IDX, false, false); + if (p.invpin != UNUSED_PIN) { + gpio_matrix_out(p.invpin, SIG_IN_FUNC228_IDX, true /*inverted*/, false); + } } #endif #ifndef DISABLE_PROG @@ -261,10 +268,12 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr track[trackToSet]->setBrake(false); } +#ifndef ARDUINO_ARCH_ESP32 // EXT is a special case where the signal pin is // turned off. So unless that is set, the signal // pin should be turned on track[trackToSet]->enableSignal(mode != TRACK_MODE_EXT); +#endif #ifndef ARDUINO_ARCH_ESP32 // re-evaluate HighAccuracy mode @@ -320,8 +329,6 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr void TrackManager::applyDCSpeed(byte t) { uint8_t speedByte=DCC::getThrottleSpeedByte(trackDCAddr[t]); - if (track[t]->getMode()==TRACK_MODE_DCX) - speedByte = speedByte ^ 128; // reverse direction bit track[t]->setDCSignal(speedByte); }