diff --git a/DCC.cpp b/DCC.cpp index 9f5d53e..6c640fb 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -56,24 +56,26 @@ void DCC::begin() { StringFormatter::send(Serial,F("\n"), F(VERSION), F(ARDUINO_TYPE), MotorDriverContainer::mDC.getMotorShieldName(), F(GITHUB_SHA)); + /* +NOT YES, PIN CONFLICTS // Initialise HAL layer before reading EEprom. IODevice::begin(); + */ + //MotorDriverContainer::mDC.add(new MotorDriver(16, 21, UNUSED_PIN, UNUSED_PIN, UNUSED_PIN, 2.00, 2000, UNUSED_PIN, RMT_MAIN)); // Load stuff from EEprom (void)EEPROM; // tell compiler not to warn this is unused EEStore::init(); + MotorDriverContainer::mDC.diag(); DCCWaveform::begin(MotorDriverContainer::mDC.mainTrack(),MotorDriverContainer::mDC.progTrack()); - DCCTrack::mainTrack.addDriver(MotorDriverContainer::mDC.mainTrack()); - DCCTrack::progTrack.addDriver(MotorDriverContainer::mDC.progTrack()); - MotorDriver *md; - MotorDriverContainer::mDC.add(2, md = new MotorDriver(16, 21, UNUSED_PIN, UNUSED_PIN, UNUSED_PIN, 2.00, 2000, UNUSED_PIN, RMT_MAIN)); - DCCTrack::mainTrack.addDriver(md); - /* - std::vector v = MotorDriverContainer::mDC.getDriverType(RMT_MAIN); + // Add main and prog drivers to the main and prog packet sources (dcc-tracks). + std::vector v; + v = MotorDriverContainer::mDC.getDriverType(RMT_MAIN|TIMER_MAIN); for (const auto& d: v) DCCTrack::mainTrack.addDriver(d); - */ + v = MotorDriverContainer::mDC.getDriverType(RMT_PROG|TIMER_PROG); + for (const auto& d: v) DCCTrack::progTrack.addDriver(d); } void DCC::setJoinRelayPin(byte joinRelayPin) { diff --git a/DCCTrack.cpp b/DCCTrack.cpp index e0896d0..f2f05a6 100644 --- a/DCCTrack.cpp +++ b/DCCTrack.cpp @@ -29,7 +29,7 @@ void DCCTrack::schedulePacket(dccPacket packet) { //DIAG(F("DCCTrack::schedulePacket RMT l=%d d=%x"),packet.length, packet.data[0]); driver->schedulePacket(packet); } - if (driver->type() == TIMERINTERRUPT && waveform && once) { + if (driver->type() & (TIMER_MAIN | TIMER_PROG) && waveform && once) { //DIAG(F("DCCTrack::schedulePacket WAVE l=%d d=%x"),packet.length, packet.data[0]); waveform->schedulePacket(packet); once=false; diff --git a/DCCTrack.h b/DCCTrack.h index 86ce98d..5a8d3de 100644 --- a/DCCTrack.h +++ b/DCCTrack.h @@ -3,13 +3,16 @@ #include #include "DCCPacket.h" #include "DCCWaveform.h" +#include "DIAG.h" class DCCTrack { public: DCCTrack(DCCWaveform *w); void schedulePacket(const byte buffer[], byte byteCount, byte repeats); void schedulePacket(dccPacket packet); - inline void addDriver(MotorDriver *m) { mD.push_back(m); }; + inline void addDriver(MotorDriver *m) { mD.push_back(m); + DIAG(F("Track: mDType=%d count=%d"),m->type(), mD.size()); + }; static DCCTrack mainTrack; static DCCTrack progTrack; private: diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 92b98eb..22bd42b 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -49,19 +49,27 @@ uint8_t DCCWaveform::trailingEdgeCounter=0; void DCCWaveform::begin(MotorDriver * mainDriver, MotorDriver * progDriver) { - mainTrack.motorDriver=mainDriver; - progTrack.motorDriver=progDriver; - progTripValue = progDriver->mA2raw(TRIP_CURRENT_PROG); // need only calculate once hence static - mainTrack.setPowerMode(POWERMODE::OFF); - progTrack.setPowerMode(POWERMODE::OFF); - // Fault pin config for odd motor boards (example pololu) - MotorDriver::commonFaultPin = ((mainDriver->getFaultPin() == progDriver->getFaultPin()) - && (mainDriver->getFaultPin() != UNUSED_PIN)); - // Only use PWM if both pins are PWM capable. Otherwise JOIN does not work - MotorDriver::usePWM= mainDriver->isPWMCapable() && progDriver->isPWMCapable(); - DIAG(F("Signal pin config: %S accuracy waveform"), + if(mainDriver) { + mainTrack.motorDriver=mainDriver; + mainTrack.setPowerMode(POWERMODE::OFF); + } + if(progDriver) { + progTrack.motorDriver=progDriver; + progTripValue = progDriver->mA2raw(TRIP_CURRENT_PROG); // need only calculate once hence static + progTrack.setPowerMode(POWERMODE::OFF); + } + if(mainDriver && progDriver) { + // Fault pin config for odd motor boards (example pololu) + MotorDriver::commonFaultPin = ((mainDriver->getFaultPin() == progDriver->getFaultPin()) + && (mainDriver->getFaultPin() != UNUSED_PIN)); + // Only use PWM if both pins are PWM capable. Otherwise JOIN does not work + MotorDriver::usePWM= mainDriver->isPWMCapable() && progDriver->isPWMCapable(); + } + if(mainDriver || progDriver) { + DIAG(F("Signal pin config: %S accuracy waveform"), MotorDriver::usePWM ? F("high") : F("normal") ); - DCCTimer::begin(DCCWaveform::interruptHandler); + } + DCCTimer::begin(DCCWaveform::interruptHandler); } #ifdef SLOW_ANALOG_READ diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 70643e5..ee878ec 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -44,7 +44,7 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8 rmtChannel = new RMTChannel(signalPin, 0, PREAMBLE_BITS_MAIN); #endif dualSignal=false; - } else if (dtype == TIMERINTERRUPT) { + } else if (dtype & (TIMER_MAIN | TIMER_PROG)) { signalPin=signal_pin; getFastPin(F("SIG"),signalPin,fastSignalPin); pinMode(signalPin, OUTPUT); @@ -212,8 +212,9 @@ bool MotorDriver::schedulePacket(dccPacket packet) { if(!rmtChannel) return true; // fake success if functionality is not there outQueue.push(packet); - if (outQueue.size() > 10) { - DIAG(F("Warning: outQueue > 10")); + uint16_t size = outQueue.size(); + if (size > 10) { + DIAG(F("Warning: outQueue %d > 10"),size); } return true; } @@ -232,33 +233,41 @@ MotorDriverContainer::MotorDriverContainer(const FSH * motorShieldName, MotorDriver *m5, MotorDriver *m6, MotorDriver *m7) { - mD[0]=m0; - mD[1]=m1; - mD[2]=m2; - mD[3]=m3; - mD[4]=m4; - mD[5]=m5; - mD[6]=m6; - mD[7]=m7; + // THIS AUTOMATIC DOES NOT WORK YET. TIMER_MAIN AND TIMER_PROG required in CONSTRUCTOR + // AND CAN NOT BE ADDED LATER + if (m0) { + if (m0->type() == TYPE_UNKNOWN) + m0->setType(TIMER_MAIN); + mD.push_back(m0); + } + if (m1) { + if (m1->type() == TYPE_UNKNOWN) + m1->setType(TIMER_PROG); + mD.push_back(m1); + } + if (m2) mD.push_back(m2); + if (m3) mD.push_back(m3); + if (m4) mD.push_back(m4); + if (m5) mD.push_back(m5); + if (m6) mD.push_back(m6); + if (m7) mD.push_back(m7); shieldName = (FSH *)motorShieldName; } void MotorDriverContainer::loop() { - static byte i = 0; - // loops over MotorDrivers which have loop tasks - if (mD[i]) - if (mD[i]->type() == RMT_MAIN || mD[i]->type() == RMT_PROG) - mD[i]->loop(); - i++; - if(i > 7) i=0; + if (mD.empty()) + return; + for(const auto& d: mD) + if (d->type() & (RMT_MAIN | RMT_PROG)) + d->loop(); } std::vector MotorDriverContainer::getDriverType(driverType t) { std::vector v; - for(byte i=0; i<8; i++) { - if (mD[i] && mD[i]->type() == t) - v.push_back(mD[i]); + for(const auto& d: mD){ + if (d->type() & t) + v.push_back(d); } return v; } diff --git a/MotorDriver.h b/MotorDriver.h index c84bdca..0121e99 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -22,6 +22,7 @@ #include #include "defines.h" #include "FSH.h" +#include "DIAG.h" #if defined(ARDUINO_ARCH_ESP32) #include @@ -57,13 +58,20 @@ struct FASTPIN { #define isHIGH(fastpin) (*fastpin.inout & fastpin.maskHIGH) #define isLOW(fastpin) (!isHIGH(fastpin)) -enum driverType { TIMERINTERRUPT, RMT_MAIN, RMT_PROG, DC_ENA, DC_BRAKE }; +typedef byte driverType; +const driverType TYPE_UNKNOWN=0; +const driverType TIMER_MAIN=1; +const driverType TIMER_PROG=2; +const driverType RMT_MAIN=4; +const driverType RMT_PROG=16; +const driverType DC_ENA=32; +const driverType DC_BRAKE=64; class MotorDriver { public: MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin, - driverType t=TIMERINTERRUPT); + driverType t=TYPE_UNKNOWN); void setPower( bool on); void setSignal( bool high); void setBrake( bool on); @@ -83,6 +91,7 @@ class MotorDriver { #if defined(ARDUINO_ARCH_ESP32) void loop(); inline driverType type() { return dtype; }; + inline void setType(driverType t) { dtype = t; }; bool schedulePacket(dccPacket packet); #endif @@ -129,19 +138,35 @@ public: MotorDriver *m6=NULL, MotorDriver *m7=NULL); static MotorDriverContainer mDC; - inline void add(byte n, MotorDriver *m) { - if (n>8) return; - mD[n] = m; + inline void add(MotorDriver *m) { + mD.push_back(m); + DIAG(F("Container: mDType=%d count=%d"),m->type(), mD.size()); }; // void SetCapability(byte n, byte cap, char [] name); inline FSH *getMotorShieldName() { return shieldName; }; - inline MotorDriver *mainTrack() { return mD[0]; }; //start fixed - inline MotorDriver *progTrack() { return mD[1]; }; + inline void diag() { + if (mD.empty()) { + DIAG(F("Container empty")); + return; + } + for(const auto& d: mD) + DIAG(F("Container: mDType=%d count=%d"),d->type(), mD.size()); + }; + inline MotorDriver *mainTrack() { + std::vector v = getDriverType(TIMER_MAIN); + if(v.empty()) return NULL; + return v.front(); + }; + inline MotorDriver *progTrack() { + std::vector v = getDriverType(TIMER_PROG); + if(v.empty()) return NULL; + return v.front(); + }; void loop(); std::vector getDriverType(driverType t); private: - MotorDriver *mD[8]; + std::vectormD; FSH *shieldName; }; #endif