1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-12-23 21:01:25 +01:00

MotorDriverContainer (multi-motordriver) start

This commit is contained in:
Harald Barth 2021-11-21 22:53:17 +01:00
parent 2632d44ec9
commit f7e90e7b73
6 changed files with 63 additions and 13 deletions

View File

@ -85,11 +85,7 @@ void setup()
#endif // ETHERNET_ON
// Responsibility 3: Start the DCC engine.
// Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s)
// Standard supported devices have pre-configured macros but custome hardware installations require
// detailed pin mappings and may also require modified subclasses of the MotorDriver to implement specialist logic.
// STANDARD_MOTOR_SHIELD, POLOLU_MOTOR_SHIELD, FIREBOX_MK1, FIREBOX_MK1S are pre defined in MotorShields.h
DCC::begin(MOTOR_SHIELD_TYPE);
DCC::begin();
// Start RMFT (ignored if no automnation)
RMFT::begin();

10
DCC.cpp
View File

@ -26,6 +26,9 @@
#include "FSH.h"
#include "IODevice.h"
#include "MotorDriver.h"
extern MotorDriverContainer mDC;
// This module is responsible for converting API calls into
// messages to be sent to the waveform generator.
// It has no visibility of the hardware, timers, interrupts
@ -49,9 +52,8 @@ FSH* DCC::shieldName=NULL;
byte DCC::joinRelay=UNUSED_PIN;
byte DCC::globalSpeedsteps=128;
void DCC::begin(const FSH * motorShieldName, MotorDriver * mainDriver, MotorDriver* progDriver) {
shieldName=(FSH *)motorShieldName;
StringFormatter::send(Serial,F("<iDCC-EX V-%S / %S / %S G-%S>\n"), F(VERSION), F(ARDUINO_TYPE), shieldName, F(GITHUB_SHA));
void DCC::begin() {
StringFormatter::send(Serial,F("<iDCC-EX V-%S / %S / %S G-%S>\n"), F(VERSION), F(ARDUINO_TYPE), mDC.getMotorShieldName(), F(GITHUB_SHA));
// Initialise HAL layer before reading EEprom.
IODevice::begin();
@ -60,7 +62,7 @@ void DCC::begin(const FSH * motorShieldName, MotorDriver * mainDriver, MotorDriv
(void)EEPROM; // tell compiler not to warn this is unused
EEStore::init();
DCCWaveform::begin(mainDriver,progDriver);
DCCWaveform::begin(mDC.mainTrack(),mDC.progTrack());
}
void DCC::setJoinRelayPin(byte joinRelayPin) {

2
DCC.h
View File

@ -77,7 +77,7 @@ const byte MAX_LOCOS = 50;
class DCC
{
public:
static void begin(const FSH * motorShieldName, MotorDriver *mainDriver, MotorDriver *progDriver);
static void begin();
static void setJoinRelayPin(byte joinRelayPin);
static void loop();

View File

@ -92,8 +92,10 @@ void IRAM_ATTR DCCWaveform::interruptHandler() {
byte sigMain=signalTransform[mainTrack.state];
byte sigProg=progTrackSyncMain? sigMain : signalTransform[progTrack.state];
// Set the signal state for both tracks
mainTrack.motorDriver->setSignal(sigMain);
progTrack.motorDriver->setSignal(sigProg);
if (mainTrack.motorDriver)
mainTrack.motorDriver->setSignal(sigMain);
if (progTrack.motorDriver)
progTrack.motorDriver->setSignal(sigProg);
// Move on in the state engine
mainTrack.state=stateTransform[mainTrack.state];
progTrack.state=stateTransform[progTrack.state];
@ -148,12 +150,14 @@ POWERMODE DCCWaveform::getPowerMode() {
void DCCWaveform::setPowerMode(POWERMODE mode) {
powerMode = mode;
bool ison = (mode == POWERMODE::ON);
motorDriver->setPower( ison);
if (motorDriver)
motorDriver->setPower( ison);
sentResetsSincePacket=0;
}
void DCCWaveform::checkPowerOverload(bool ackManagerActive) {
if (!motorDriver) return;
if (millis() - lastSampleTaken < sampleDelay) return;
lastSampleTaken = millis();
int tripValue= motorDriver->getRawCurrentTripValue();
@ -323,6 +327,7 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
// (yes I know I could have subclassed the main track but...)
void DCCWaveform::setAckBaseline() {
if (!motorDriver) return;
if (isMainTrack) return;
int baseline=motorDriver->getCurrentRaw();
ackThreshold= baseline + motorDriver->mA2raw(ackLimitmA);
@ -345,6 +350,7 @@ void DCCWaveform::setAckPending() {
}
byte DCCWaveform::getAck() {
if (!motorDriver) return 0;
if (ackPending) return (2); // still waiting
if (Diag::ACK) DIAG(F("%S after %dmS max=%d/%dmA pulse=%duS samples=%d gaps=%d"),ackDetected?F("ACK"):F("NO-ACK"), ackCheckDuration,
ackMaxCurrent,motorDriver->raw2mA(ackMaxCurrent), ackPulseDuration, numAckSamples, numAckGaps);
@ -355,6 +361,7 @@ byte DCCWaveform::getAck() {
#pragma GCC push_options
#pragma GCC optimize ("-O3")
void IRAM_ATTR DCCWaveform::checkAck() {
if (!motorDriver) return;
// This function operates in interrupt() time so must be fast and can't DIAG
if (sentResetsSincePacket > 6) { //ACK timeout
ackCheckDuration=millis()-ackCheckStart;

View File

@ -17,6 +17,8 @@
* along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
*/
#include <Arduino.h>
#include "config.h"
#include "defines.h"
#include "MotorDriver.h"
#include "DCCTimer.h"
#include "DIAG.h"
@ -194,3 +196,25 @@ void MotorDriver::getFastPin(const FSH* type,int pin, bool input, FASTPIN & res
result.maskLOW = ~result.maskHIGH;
// DIAG(F(" port=0x%x, inoutpin=0x%x, isinput=%d, mask=0x%x"),port, result.inout,input,result.maskHIGH);
}
MotorDriverContainer::MotorDriverContainer(const FSH * motorShieldName,
MotorDriver *m0,
MotorDriver *m1,
MotorDriver *m2,
MotorDriver *m3,
MotorDriver *m4,
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;
shieldName = (FSH *)motorShieldName;
}
MotorDriverContainer mDC(MOTOR_SHIELD_TYPE);

View File

@ -106,4 +106,25 @@ class MotorDriver {
}
#endif
};
class MotorDriverContainer {
public:
MotorDriverContainer(const FSH * motorShieldName,
MotorDriver *m0=NULL,
MotorDriver *m1=NULL,
MotorDriver *m2=NULL,
MotorDriver *m3=NULL,
MotorDriver *m4=NULL,
MotorDriver *m5=NULL,
MotorDriver *m6=NULL,
MotorDriver *m7=NULL);
// 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]; };
private:
MotorDriver *mD[8];
FSH *shieldName;
};
#endif