From 864d2936b1d38bb53490598e808907e1e46d1841 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Tue, 26 May 2020 18:34:54 +0100 Subject: [PATCH] Acks --- Config.h | 3 +++ DCC.cpp | 13 +++++-------- DCCWaveform.cpp | 46 +++++++++++++++++++++++++--------------------- DCCWaveform.h | 9 +++------ Hardware.cpp | 3 +++ Hardware.h | 3 ++- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Config.h b/Config.h index c472e18..7426ef3 100644 --- a/Config.h +++ b/Config.h @@ -5,9 +5,12 @@ const byte MAIN_SIGNAL_PIN = 12; const byte MAIN_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins const byte MAIN_SENSE_PIN = A0; const byte MAIN_SENSE_FACTOR=1; // analgRead(MAIN_SENSE_PIN) * MAIN_SENSE_FACTOR = milliamps +const byte MAIN_BRAKE_PIN = 9; const byte PROG_POWER_PIN = 11; const byte PROG_SIGNAL_PIN = 13; const byte PROG_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins const byte PROG_SENSE_PIN = A1; +const byte PROG_BRAKE_PIN = 10; + const float PROG_SENSE_FACTOR=1; // analgRead(PROG_SENSE_PIN) * PROG_SENSE_FACTOR = milliamps diff --git a/DCC.cpp b/DCC.cpp index ed25e1f..96fa0cb 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -125,8 +125,7 @@ bool DCC::writeCVBit(int cv, byte bNum, bool bValue) { bitWrite(message[2],4,1); // change instruction code from Write Bit to Verify Bit DCCWaveform::progTrack.schedulePacket(message,sizeof(message),6); // NMRA recommends 6 write or reset packets for decoder recovery time */ - - return DCCWaveform::progTrack.getAck(); + return true; // <<<< NOT ACCURATE... see comment above } @@ -141,8 +140,8 @@ int DCC::readCV(int cv) { // get each bit individually for (int i = 0; i < 8; i++) { message[2] = 0xE8 + i; - DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 4); // NMRA recommends 5 read packets - value += (DCCWaveform::progTrack.getAck() << i); + bool one=DCCWaveform::progTrack.schedulePacketWithAck(message, sizeof(message), 4); // NMRA recommends 5 read packets + value += one << i; } return verifyCV(cv, value) ? value : -1; @@ -183,10 +182,8 @@ byte DCC::cv2(int cv) { bool DCC::verifyCV(int cv, byte value) { byte message[] = { cv1(0x74, cv), cv2(cv), value}; DIAG(F("\n\nVerifying cv %d = %d"), cv, value); - DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 5); - return DCCWaveform::progTrack.getAck(); -} - + return DCCWaveform::progTrack.schedulePacketWithAck(message, sizeof(message), 5); + } void DCC::updateLocoReminder(int loco, byte tSpeed, bool forward) { // determine speed reg for this loco diff --git a/DCCWaveform.cpp b/DCCWaveform.cpp index a395e77..789af0c 100644 --- a/DCCWaveform.cpp +++ b/DCCWaveform.cpp @@ -207,37 +207,41 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea packetPending = true; } - - -bool DCCWaveform::getAck() -{ - - if (isMainTrack) return false; // cant do this on main track - +// Wait until there is no packet pending, then make this pending +bool DCCWaveform::schedulePacketWithAck(const byte buffer[], byte byteCount, byte repeats) { + + if (isMainTrack) return false; + int baseline=0; + for (int i=0;i millis()) { - upsamples++; + // Monitor looking for an ack signal rise of at least 60mA but keep going for the timeout + while (timeout > millis()) { int current = Hardware::getCurrentMilliamps(isMainTrack); maxCurrent = max(maxCurrent, current); - result = current > ACK_MIN_PULSE; - } - - // Monitor current until ack signal dies back - if (result) while ( true) { - downsamples++; - int current = Hardware::getCurrentMilliamps(isMainTrack); - maxCurrent = max(maxCurrent, current); - if (current <= ACK_MAX_NOT_PULSE) break; + if (current>upTrigger) { + result=true; + upsamples++; } + } + // The following DIAG is really useful as it can show how long and how far the // current changes during an ACK from the decoder. - DIAG(F("\nack=%d max=%d, up=%d, down=%d "), result, maxCurrent, upsamples, downsamples); + DIAG(F("ack=%d max=%d, up=%d"), result, maxCurrent, upsamples); return result; } diff --git a/DCCWaveform.h b/DCCWaveform.h index d7a8a5e..6a83741 100644 --- a/DCCWaveform.h +++ b/DCCWaveform.h @@ -8,9 +8,9 @@ const int POWER_SAMPLE_OVERLOAD_WAIT = 4000; // ACK current analogRead values (vary depending on motor shield and cpu voltage) +const int ACK_BASELINE_SAMPLES = 250 ; // current samples before sending ACKable request const int ACK_TIMEOUT = 25 ; // millis getAck is prepared to wait for a signal -const int ACK_MAX_NOT_PULSE = 40 ; // 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 ACK_MIN_PULSE = 60 ; // current above baseline which a pulse is recognised const int PREAMBLE_BITS_MAIN = 20; const int PREAMBLE_BITS_PROG = 22; @@ -18,8 +18,6 @@ const int PREAMBLE_BITS_PROG = 22; // 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; @@ -46,9 +44,8 @@ class DCCWaveform { POWERMODE getPowerMode(); void checkPowerOverload(); void schedulePacket(const byte buffer[], byte byteCount, byte repeats); + bool schedulePacketWithAck(const byte buffer[], byte byteCount, byte repeats); volatile bool packetPending; - bool startAckProcess(); - bool getAck(); private: diff --git a/Hardware.cpp b/Hardware.cpp index 81dd021..d5a6f51 100644 --- a/Hardware.cpp +++ b/Hardware.cpp @@ -20,6 +20,9 @@ void Hardware::init() { void Hardware::setPower(bool isMainTrack, bool on) { digitalWrite(isMainTrack ? MAIN_POWER_PIN : PROG_POWER_PIN, on ? HIGH : LOW); } +void Hardware::setBrake(bool isMainTrack, bool on) { + digitalWrite(isMainTrack ? MAIN_BRAKE_PIN : PROG_BRAKE_PIN, on ? LOW:HIGH); +} void Hardware::setSignal(bool isMainTrack, bool high) { byte pin = isMainTrack ? MAIN_SIGNAL_PIN : PROG_SIGNAL_PIN; diff --git a/Hardware.h b/Hardware.h index f66b2df..8709f4e 100644 --- a/Hardware.h +++ b/Hardware.h @@ -5,7 +5,8 @@ class Hardware { static void init(); static void setPower(bool isMainTrack, bool on); static void setSignal(bool isMainTrack, bool high); - static int getCurrentMilliamps(bool isMainTrack); + static int getCurrentMilliamps(bool isMainTrack); + static void setBrake(bool isMainTrack, bool on); static void setCallback(int duration, void (*isr)()); static void setSingleCallback(int duration, void (*isr)()); static void resetSingleCallback(int duration);