mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 16:16:13 +01:00
Acks
This commit is contained in:
parent
c16358facc
commit
864d2936b1
3
Config.h
3
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_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
||||||
const byte MAIN_SENSE_PIN = A0;
|
const byte MAIN_SENSE_PIN = A0;
|
||||||
const byte MAIN_SENSE_FACTOR=1; // analgRead(MAIN_SENSE_PIN) * MAIN_SENSE_FACTOR = milliamps
|
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_POWER_PIN = 11;
|
||||||
const byte PROG_SIGNAL_PIN = 13;
|
const byte PROG_SIGNAL_PIN = 13;
|
||||||
const byte PROG_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
const byte PROG_SIGNAL_PIN_ALT = 0; // for hardware that flipflops signal pins
|
||||||
const byte PROG_SENSE_PIN = A1;
|
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
|
const float PROG_SENSE_FACTOR=1; // analgRead(PROG_SENSE_PIN) * PROG_SENSE_FACTOR = milliamps
|
||||||
|
|
13
DCC.cpp
13
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
|
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
|
DCCWaveform::progTrack.schedulePacket(message,sizeof(message),6); // NMRA recommends 6 write or reset packets for decoder recovery time
|
||||||
*/
|
*/
|
||||||
|
return true; // <<<< NOT ACCURATE... see comment above
|
||||||
return DCCWaveform::progTrack.getAck();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,8 +140,8 @@ int DCC::readCV(int cv) {
|
||||||
// get each bit individually
|
// get each bit individually
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
message[2] = 0xE8 + i;
|
message[2] = 0xE8 + i;
|
||||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 4); // NMRA recommends 5 read packets
|
bool one=DCCWaveform::progTrack.schedulePacketWithAck(message, sizeof(message), 4); // NMRA recommends 5 read packets
|
||||||
value += (DCCWaveform::progTrack.getAck() << i);
|
value += one << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
return verifyCV(cv, value) ? value : -1;
|
return verifyCV(cv, value) ? value : -1;
|
||||||
|
@ -183,10 +182,8 @@ byte DCC::cv2(int cv) {
|
||||||
bool DCC::verifyCV(int cv, byte value) {
|
bool DCC::verifyCV(int cv, byte value) {
|
||||||
byte message[] = { cv1(0x74, cv), cv2(cv), value};
|
byte message[] = { cv1(0x74, cv), cv2(cv), value};
|
||||||
DIAG(F("\n\nVerifying cv %d = %d"), cv, value);
|
DIAG(F("\n\nVerifying cv %d = %d"), cv, value);
|
||||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 5);
|
return DCCWaveform::progTrack.schedulePacketWithAck(message, sizeof(message), 5);
|
||||||
return DCCWaveform::progTrack.getAck();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DCC::updateLocoReminder(int loco, byte tSpeed, bool forward) {
|
void DCC::updateLocoReminder(int loco, byte tSpeed, bool forward) {
|
||||||
// determine speed reg for this loco
|
// determine speed reg for this loco
|
||||||
|
|
|
@ -207,37 +207,41 @@ void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repea
|
||||||
packetPending = true;
|
packetPending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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<ACK_BASELINE_SAMPLES;i++) {
|
||||||
|
baseline += Hardware::getCurrentMilliamps(isMainTrack);
|
||||||
|
}
|
||||||
|
baseline/=ACK_BASELINE_SAMPLES;
|
||||||
|
int upTrigger=baseline+ACK_MIN_PULSE;
|
||||||
|
|
||||||
|
|
||||||
bool DCCWaveform::getAck()
|
DIAG(F("\nACK baseline=%d upT=%d "),baseline, upTrigger);
|
||||||
{
|
|
||||||
|
|
||||||
if (isMainTrack) return false; // cant do this on main track
|
|
||||||
|
|
||||||
|
schedulePacket(buffer,byteCount,repeats);
|
||||||
while (packetPending); // wait until transmitter has started transmitting the message
|
while (packetPending); // wait until transmitter has started transmitting the message
|
||||||
|
|
||||||
unsigned long timeout = millis() + ACK_TIMEOUT;
|
unsigned long timeout = millis() + ACK_TIMEOUT;
|
||||||
int maxCurrent = 0;
|
int maxCurrent = 0;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
int upsamples = 0;
|
int upsamples = 0;
|
||||||
int downsamples = 0;
|
|
||||||
|
|
||||||
// Monitor looking for a reading high enough to be an ack
|
|
||||||
while (result == false && timeout > millis()) {
|
// Monitor looking for an ack signal rise of at least 60mA but keep going for the timeout
|
||||||
upsamples++;
|
while (timeout > millis()) {
|
||||||
int current = Hardware::getCurrentMilliamps(isMainTrack);
|
int current = Hardware::getCurrentMilliamps(isMainTrack);
|
||||||
maxCurrent = max(maxCurrent, current);
|
maxCurrent = max(maxCurrent, current);
|
||||||
result = current > ACK_MIN_PULSE;
|
if (current>upTrigger) {
|
||||||
}
|
result=true;
|
||||||
|
upsamples++;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The following DIAG is really useful as it can show how long and how far the
|
// The following DIAG is really useful as it can show how long and how far the
|
||||||
// current changes during an ACK from the decoder.
|
// 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@ const int POWER_SAMPLE_OVERLOAD_WAIT = 4000;
|
||||||
|
|
||||||
|
|
||||||
// ACK current analogRead values (vary depending on motor shield and cpu voltage)
|
// 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_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 = 60 ; // current above baseline which a pulse is recognised
|
||||||
const int ACK_MIN_PULSE = 50 ; // current above which a pulse is recognised
|
|
||||||
|
|
||||||
const int PREAMBLE_BITS_MAIN = 20;
|
const int PREAMBLE_BITS_MAIN = 20;
|
||||||
const int PREAMBLE_BITS_PROG = 22;
|
const int PREAMBLE_BITS_PROG = 22;
|
||||||
|
@ -18,8 +18,6 @@ const int PREAMBLE_BITS_PROG = 22;
|
||||||
// Railcom settings
|
// Railcom settings
|
||||||
const bool RAILCOM_CUTOUT = true;
|
const bool RAILCOM_CUTOUT = true;
|
||||||
const byte RAILCOM_PREAMBLES_BEFORE_CUTOUT = 1; // how far into the preamble do we cutout
|
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();
|
POWERMODE getPowerMode();
|
||||||
void checkPowerOverload();
|
void checkPowerOverload();
|
||||||
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
||||||
|
bool schedulePacketWithAck(const byte buffer[], byte byteCount, byte repeats);
|
||||||
volatile bool packetPending;
|
volatile bool packetPending;
|
||||||
bool startAckProcess();
|
|
||||||
bool getAck();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -20,6 +20,9 @@ void Hardware::init() {
|
||||||
void Hardware::setPower(bool isMainTrack, bool on) {
|
void Hardware::setPower(bool isMainTrack, bool on) {
|
||||||
digitalWrite(isMainTrack ? MAIN_POWER_PIN : PROG_POWER_PIN, on ? HIGH : LOW);
|
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) {
|
void Hardware::setSignal(bool isMainTrack, bool high) {
|
||||||
byte pin = isMainTrack ? MAIN_SIGNAL_PIN : PROG_SIGNAL_PIN;
|
byte pin = isMainTrack ? MAIN_SIGNAL_PIN : PROG_SIGNAL_PIN;
|
||||||
|
|
|
@ -5,7 +5,8 @@ class Hardware {
|
||||||
static void init();
|
static void init();
|
||||||
static void setPower(bool isMainTrack, bool on);
|
static void setPower(bool isMainTrack, bool on);
|
||||||
static void setSignal(bool isMainTrack, bool high);
|
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 setCallback(int duration, void (*isr)());
|
||||||
static void setSingleCallback(int duration, void (*isr)());
|
static void setSingleCallback(int duration, void (*isr)());
|
||||||
static void resetSingleCallback(int duration);
|
static void resetSingleCallback(int duration);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user