From 0b9f4cf5740ea411beb8975dd7f7660b2ed050b8 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sun, 24 May 2020 10:27:33 +0100 Subject: [PATCH] Rauilcom cutout --- DCCWaveform.cpp | 32 ++++++++++-- DCCWaveform.h | 136 +++++++++++++++++++++++++----------------------- 2 files changed, 99 insertions(+), 69 deletions(-) diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index 92008fe..41a58b3 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -59,11 +59,19 @@ DCCWaveform::DCCWaveform(byte powerPinNo, byte directionPinNo, byte sensePinNo, bytes_sent=0; bits_sent=0; nextSampleDue=0; + } void DCCWaveform::beginTrack() { pinMode2f(powerPin,OUTPUT); pinMode2f(directionPin,OUTPUT); pinMode(sensePin,INPUT); + + if (isMainTrack && RAILCOM_CUTOUT) { + railcomBrakePin=Arduino_to_GPIO_pin(RAILCOM_BRAKE_PIN); + pinMode2f(railcomBrakePin, OUTPUT); + digitalWrite2f(railcomBrakePin, LOW); + } + setPowerMode(POWERMODE::ON); DIAG(F("\nTrack started sensePin=%d\n"),sensePin); } @@ -121,20 +129,23 @@ bool DCCWaveform::interrupt1() { switch (state) { case 0: // start of bit transmission digitalWrite2f(directionPin, HIGH); + checkRailcom(); state = 1; - return true; // must call interrupt2 + return true; // must call interrupt2 to set currentBit - case 1: // 58Ms after case 0 + case 1: // 58us after case 0 if (currentBit) { digitalWrite2f(directionPin, LOW); state = 0; } else state = 2; break; - case 2: digitalWrite2f(directionPin, LOW); + case 2: // 116us after case 0 + digitalWrite2f(directionPin, LOW); state = 3; break; - case 3: state = 0; + case 3: // finished sending zero bit + state = 0; break; } return false; @@ -186,7 +197,18 @@ void DCCWaveform::interrupt2() { } } } - + +void DCCWaveform::checkRailcom() { + if (isMainTrack && RAILCOM_CUTOUT) { + byte preamble=PREAMBLE_BITS_MAIN - remainingPreambles; + if (preamble == RAILCOM_PREAMBLES_BEFORE_CUTOUT) { + digitalWrite2f(railcomBrakePin,HIGH); + } + else if (preamble== RAILCOM_PREAMBLES_BEFORE_CUTOUT+RAILCOM_PREAMBLES_SKIPPED_IN_CUTOUT) { + digitalWrite2f(railcomBrakePin,LOW); + } + } +} // Wait until there is no packet pending, then make this pending void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repeats) { diff --git a/DCCWaveform.h b/DCCWaveform.h index ab47bb1..9435534 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -1,17 +1,17 @@ #include // This hardware configuration would normally be setup in a .h file elsewhere -const byte MAIN_POWER_PIN=3; -const byte MAIN_SIGNAL_PIN=12; -const byte MAIN_SENSE_PIN=A0; +const byte MAIN_POWER_PIN = 3; +const byte MAIN_SIGNAL_PIN = 12; +const byte MAIN_SENSE_PIN = A0; -const byte PROG_POWER_PIN=11; -const byte PROG_SIGNAL_PIN=13; -const byte PROG_SENSE_PIN=A1; +const byte PROG_POWER_PIN = 11; +const byte PROG_SIGNAL_PIN = 13; +const byte PROG_SENSE_PIN = A1; -const int POWER_SAMPLE_MAX=300; -const int POWER_SAMPLE_ON_WAIT=100; -const int POWER_SAMPLE_OFF_WAIT=1000; -const int POWER_SAMPLE_OVERLOAD_WAIT=4000; +const int POWER_SAMPLE_MAX = 300; +const int POWER_SAMPLE_ON_WAIT = 100; +const int POWER_SAMPLE_OFF_WAIT = 1000; +const int POWER_SAMPLE_OVERLOAD_WAIT = 4000; // ACK current analogRead values (vary depending on motor shield and cpu voltage) @@ -19,71 +19,79 @@ const int ACK_TIMEOUT = 25 ; // millis getAck is prepared to wait for a signa const int ACK_MAX_NOT_PULSE = 10 ; // current below which this is NOT a pulse any more const int ACK_MIN_PULSE = 50 ; // current above which a pulse is recognised -const int PREAMBLE_BITS_MAIN=16; -const int PREAMBLE_BITS_PROG=22; +const int PREAMBLE_BITS_MAIN = 20; +const int PREAMBLE_BITS_PROG = 22; -const byte MAX_PACKET_SIZE=12; -// NOTE: static functions are used for the overall controller, then +// Railcom settings +const bool RAILCOM_CUTOUT = true; +const byte RAILCOM_PREAMBLES_BEFORE_CUTOUT = 1; // how far into the preamble do we cutout +const byte RAILCOM_PREAMBLES_SKIPPED_IN_CUTOUT = 5; +const byte RAILCOM_BRAKE_PIN = 9; + + + +const byte MAX_PACKET_SIZE = 12; +// NOTE: static functions are used for the overall controller, then // one instance is created for each track. enum class POWERMODE { OFF, ON, OVERLOAD }; -const byte idleMessage[]={0xFF,0x00}; -const byte resetMessage[]={0x00,0x00}; -const byte idlePacket[]={0xFF,0x00,0xFF}; -const byte resetPacket[]={0x00,0x00,0x00}; +const byte idleMessage[] = {0xFF, 0x00}; +const byte resetMessage[] = {0x00, 0x00}; +const byte idlePacket[] = {0xFF, 0x00, 0xFF}; +const byte resetPacket[] = {0x00, 0x00, 0x00}; class DCCWaveform { public: - DCCWaveform(byte powerPinNo, byte directionPinNo, byte sensePinNo, byte preambleBits, bool isMain); - static void begin(); - static void loop(); - static DCCWaveform mainTrack; - static DCCWaveform progTrack; - - void beginTrack(); - void setPowerMode(POWERMODE); - POWERMODE getPowerMode(); - void checkPowerOverload(); - void schedulePacket(const byte buffer[], byte byteCount, byte repeats); - volatile bool packetPending; - bool startAckProcess(); - bool getAck(); + DCCWaveform(byte powerPinNo, byte directionPinNo, byte sensePinNo, byte preambleBits, bool isMain); + static void begin(); + static void loop(); + static DCCWaveform mainTrack; + static DCCWaveform progTrack; + + void beginTrack(); + void setPowerMode(POWERMODE); + POWERMODE getPowerMode(); + void checkPowerOverload(); + void schedulePacket(const byte buffer[], byte byteCount, byte repeats); + volatile bool packetPending; + bool startAckProcess(); + bool getAck(); + - private: - - static void interruptHandler(); - bool interrupt1(); - void interrupt2(); - - POWERMODE powerMode; -// Transmission controller - byte transmitPacket[MAX_PACKET_SIZE]; // packet being transmitted - byte transmitLength; - byte transmitRepeats; // remaining repeats of transmission - byte remainingPreambles; - byte requiredPreambles; - bool currentBit; // bit to be transmitted + static void interruptHandler(); + bool interrupt1(); + void interrupt2(); + + bool isMainTrack; + + // Transmission controller + byte transmitPacket[MAX_PACKET_SIZE]; // packet being transmitted + byte transmitLength; + byte transmitRepeats; // remaining repeats of transmission + byte remainingPreambles; + byte requiredPreambles; + bool currentBit; // bit to be transmitted + byte bits_sent; // 0-8 (yes 9 bits) sent for current byte + byte bytes_sent; // number of bytes sent from transmitPacket + byte state; // wave generator state machine + void checkRailcom(); + + byte pendingPacket[MAX_PACKET_SIZE]; + byte pendingLength; + byte pendingRepeats; + + // Hardware fast pins + GPIO_pin_t directionPin; + GPIO_pin_t powerPin; + GPIO_pin_t railcomBrakePin; + + // current sampling + POWERMODE powerMode; + byte sensePin; + unsigned long nextSampleDue; - byte bits_sent; // 0-8 (yes 9 bits) sent for current byte - byte bytes_sent; // number of bytes sent from transmitPacket - - byte state; // wave generator state machine - - byte pendingPacket[MAX_PACKET_SIZE]; - byte pendingLength; - byte pendingRepeats; - // Hardware pins - GPIO_pin_t directionPin; - GPIO_pin_t powerPin; - - // current sampling - bool isMainTrack; - byte sensePin; - unsigned long nextSampleDue; - int ackBaseCurrent; - };