mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-11-23 08:06:13 +01:00
Railcom sample window
This commit is contained in:
parent
9f1cdfcda6
commit
45f4bf2041
|
@ -116,18 +116,20 @@ DCCWaveform::DCCWaveform( byte preambleBits, bool isMain) {
|
||||||
bits_sent = 0;
|
bits_sent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DCCWaveform::railcomPossible=false; // High accuracy only
|
||||||
volatile bool DCCWaveform::railcomActive=false; // switched on by user
|
volatile bool DCCWaveform::railcomActive=false; // switched on by user
|
||||||
|
volatile bool DCCWaveform::railcomSampleWindow=false; // true during packet transmit
|
||||||
volatile bool DCCWaveform::railcomDebug=false; // switched on by user
|
volatile bool DCCWaveform::railcomDebug=false; // switched on by user
|
||||||
|
|
||||||
bool DCCWaveform::setRailcom(bool on, bool debug) {
|
bool DCCWaveform::setRailcom(bool on, bool debug) {
|
||||||
if (on) {
|
if (on && railcomPossible) {
|
||||||
// TODO check possible
|
|
||||||
railcomActive=true;
|
railcomActive=true;
|
||||||
railcomDebug=debug;
|
railcomDebug=debug;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
railcomActive=false;
|
railcomActive=false;
|
||||||
railcomDebug=false;
|
railcomDebug=false;
|
||||||
|
railcomSampleWindow=false;
|
||||||
}
|
}
|
||||||
return railcomActive;
|
return railcomActive;
|
||||||
}
|
}
|
||||||
|
@ -147,7 +149,17 @@ void DCCWaveform::interrupt2() {
|
||||||
// that the reminder doesn't block a more urgent packet.
|
// that the reminder doesn't block a more urgent packet.
|
||||||
reminderWindowOpen=transmitRepeats==0 && remainingPreambles<4 && remainingPreambles>1;
|
reminderWindowOpen=transmitRepeats==0 && remainingPreambles<4 && remainingPreambles>1;
|
||||||
if (remainingPreambles==1) promotePendingPacket();
|
if (remainingPreambles==1) promotePendingPacket();
|
||||||
else if (remainingPreambles==10 && isMainTrack && railcomActive) DCCTimer::ackRailcomTimer();
|
else if (isMainTrack && railcomActive) {
|
||||||
|
if (remainingPreambles==10) {
|
||||||
|
// cutout has started so the railcom timer needs to end the cutout at next
|
||||||
|
// cutout timer tick.
|
||||||
|
DCCTimer::ackRailcomTimer();
|
||||||
|
}
|
||||||
|
else if (remainingPreambles==5) {
|
||||||
|
// cutout has ended so its now possible to poll the railcom detectors
|
||||||
|
railcomSampleWindow=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Update free memory diagnostic as we don't have anything else to do this time.
|
// Update free memory diagnostic as we don't have anything else to do this time.
|
||||||
// Allow for checkAck and its called functions using 22 bytes more.
|
// Allow for checkAck and its called functions using 22 bytes more.
|
||||||
else DCCTimer::updateMinimumFreeMemoryISR(22);
|
else DCCTimer::updateMinimumFreeMemoryISR(22);
|
||||||
|
@ -172,11 +184,14 @@ void DCCWaveform::interrupt2() {
|
||||||
// preamble for next packet will start...
|
// preamble for next packet will start...
|
||||||
remainingPreambles = requiredPreambles;
|
remainingPreambles = requiredPreambles;
|
||||||
|
|
||||||
// set the railcom coundown to trigger half way
|
// Set the railcom coundown to trigger half way
|
||||||
// through the first preamble bit.
|
// through the first preamble bit.
|
||||||
// Note.. we are still sending the last packet bit
|
// Note.. we are still sending the last packet bit
|
||||||
// and we then have to allow for the packet end bit
|
// but the timer code allows for this
|
||||||
if (isMainTrack && railcomActive) DCCTimer::startRailcomTimer(9);
|
if (isMainTrack && railcomActive) {
|
||||||
|
railcomSampleWindow=false; // about to cutout, stop reading railcom data.
|
||||||
|
DCCTimer::startRailcomTimer(9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +245,7 @@ void DCCWaveform::promotePendingPacket() {
|
||||||
// Fortunately reset and idle packets are the same length
|
// Fortunately reset and idle packets are the same length
|
||||||
// Note: If railcomDebug is on, then we send resets to the main
|
// Note: If railcomDebug is on, then we send resets to the main
|
||||||
// track instead of idles. This means that all data will be zeros
|
// track instead of idles. This means that all data will be zeros
|
||||||
// and only the porersets will be ones, making it much
|
// and only the presets will be ones, making it much
|
||||||
// easier to read on a logic analyser.
|
// easier to read on a logic analyser.
|
||||||
memcpy( transmitPacket, (isMainTrack && (!railcomDebug)) ? idlePacket : resetPacket, sizeof(idlePacket));
|
memcpy( transmitPacket, (isMainTrack && (!railcomDebug)) ? idlePacket : resetPacket, sizeof(idlePacket));
|
||||||
transmitLength = sizeof(idlePacket);
|
transmitLength = sizeof(idlePacket);
|
||||||
|
|
|
@ -85,8 +85,13 @@ class DCCWaveform {
|
||||||
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
||||||
bool isReminderWindowOpen();
|
bool isReminderWindowOpen();
|
||||||
void promotePendingPacket();
|
void promotePendingPacket();
|
||||||
|
static void setRailcomPossible(bool yes) {
|
||||||
|
railcomPossible=yes;
|
||||||
|
if (!yes) setRailcom(false,false);
|
||||||
|
}
|
||||||
static bool setRailcom(bool on, bool debug);
|
static bool setRailcom(bool on, bool debug);
|
||||||
static bool isRailcom() {return railcomActive;}
|
static bool isRailcom() {return railcomActive;}
|
||||||
|
static bool isRailcomSampleWindow() {return railcomSampleWindow;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef ARDUINO_ARCH_ESP32
|
#ifndef ARDUINO_ARCH_ESP32
|
||||||
|
@ -112,9 +117,10 @@ class DCCWaveform {
|
||||||
byte pendingPacket[MAX_PACKET_SIZE+1]; // +1 for checksum
|
byte pendingPacket[MAX_PACKET_SIZE+1]; // +1 for checksum
|
||||||
byte pendingLength;
|
byte pendingLength;
|
||||||
byte pendingRepeats;
|
byte pendingRepeats;
|
||||||
|
static bool railcomPossible; // High accuracy mode only
|
||||||
static volatile bool railcomActive; // switched on by user
|
static volatile bool railcomActive; // switched on by user
|
||||||
static volatile bool railcomDebug; // switched on by user
|
static volatile bool railcomDebug; // switched on by user
|
||||||
|
static volatile bool railcomSampleWindow; // when safe to sample
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
static RMTChannel *rmtMainChannel;
|
static RMTChannel *rmtMainChannel;
|
||||||
static RMTChannel *rmtProgChannel;
|
static RMTChannel *rmtProgChannel;
|
||||||
|
|
|
@ -47,11 +47,11 @@
|
||||||
#include "IODevice.h"
|
#include "IODevice.h"
|
||||||
#include "I2CManager.h"
|
#include "I2CManager.h"
|
||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
|
#include "DCCWaveform.h"
|
||||||
|
|
||||||
// Debug and diagnostic defines, enable too many will result in slowing the driver
|
// Debug and diagnostic defines, enable too many will result in slowing the driver
|
||||||
#define DIAG_I2CRailcom
|
#define DIAG_I2CRailcom
|
||||||
#define DIAG_I2CRailcom_data
|
#define DIAG_I2CRailcom_data
|
||||||
#define DIAG_I2CRailcom_reg
|
|
||||||
|
|
||||||
class I2CRailcom : public IODevice {
|
class I2CRailcom : public IODevice {
|
||||||
private:
|
private:
|
||||||
|
@ -62,7 +62,7 @@ private:
|
||||||
const uint8_t STOP_BIT = 0x00; // Value LCR bit 2
|
const uint8_t STOP_BIT = 0x00; // Value LCR bit 2
|
||||||
const uint8_t PARITY_ENA = 0x00; // Value LCR bit 3
|
const uint8_t PARITY_ENA = 0x00; // Value LCR bit 3
|
||||||
const uint8_t PARITY_TYPE = 0x00; // Value LCR bit 4
|
const uint8_t PARITY_TYPE = 0x00; // Value LCR bit 4
|
||||||
const uint32_t BAUD_RATE = 9600;
|
const uint32_t BAUD_RATE = 250000;
|
||||||
const uint8_t PRESCALER = 0x01; // Value MCR bit 7
|
const uint8_t PRESCALER = 0x01; // Value MCR bit 7
|
||||||
const unsigned long SC16IS752_XTAL_FREQ_RAILCOM = 16000000; // Baud rate for Railcom signal
|
const unsigned long SC16IS752_XTAL_FREQ_RAILCOM = 16000000; // Baud rate for Railcom signal
|
||||||
byte _inbuf[65];
|
byte _inbuf[65];
|
||||||
|
@ -106,7 +106,8 @@ public:
|
||||||
// Read responses from device
|
// Read responses from device
|
||||||
if (_deviceState!=DEVSTATE_NORMAL) return;
|
if (_deviceState!=DEVSTATE_NORMAL) return;
|
||||||
|
|
||||||
// TODO - return if in cutout or cutout very soon.
|
// return if in cutout or cutout very soon.
|
||||||
|
if (!DCCWaveform::isRailcomSampleWindow()) return;
|
||||||
|
|
||||||
// flip channels each loop
|
// flip channels each loop
|
||||||
if (_nPins>1) _UART_CH=_UART_CH?0:1;
|
if (_nPins>1) _UART_CH=_UART_CH?0:1;
|
||||||
|
|
|
@ -338,13 +338,17 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
|
||||||
// if we discover that HA mode was globally impossible
|
// if we discover that HA mode was globally impossible
|
||||||
// we must adjust the trackPWM capabilities
|
// we must adjust the trackPWM capabilities
|
||||||
DIAG(F("High Accuracy & Railcom disabled"));
|
DIAG(F("High Accuracy & Railcom disabled"));
|
||||||
|
DCCWaveform::setRailcomPossible(false);
|
||||||
FOR_EACH_TRACK(t) {
|
FOR_EACH_TRACK(t) {
|
||||||
track[t]->trackPWM=false;
|
track[t]->trackPWM=false;
|
||||||
//DIAG(F("Track %c trackPWM 0 (global override)"), t+'A');
|
//DIAG(F("Track %c trackPWM 0 (global override)"), t+'A');
|
||||||
}
|
}
|
||||||
DCCTimer::clearPWM(); // has to be AFTER trackPWM changes because if trackPWM==true this is undone for that track
|
DCCTimer::clearPWM(); // has to be AFTER trackPWM changes because if trackPWM==true this is undone for that track
|
||||||
}
|
}
|
||||||
else DIAG(F("High Accuracy Enabled"));
|
else {
|
||||||
|
DIAG(F("High Accuracy Enabled"));
|
||||||
|
DCCWaveform::setRailcomPossible(true);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
// For ESP32 we just reinitialize the DCC Waveform
|
// For ESP32 we just reinitialize the DCC Waveform
|
||||||
DCCWaveform::begin();
|
DCCWaveform::begin();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user