mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 12:51:24 +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;
|
||||
}
|
||||
|
||||
bool DCCWaveform::railcomPossible=false; // High accuracy only
|
||||
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
|
||||
|
||||
bool DCCWaveform::setRailcom(bool on, bool debug) {
|
||||
if (on) {
|
||||
// TODO check possible
|
||||
if (on && railcomPossible) {
|
||||
railcomActive=true;
|
||||
railcomDebug=debug;
|
||||
}
|
||||
else {
|
||||
railcomActive=false;
|
||||
railcomDebug=false;
|
||||
railcomSampleWindow=false;
|
||||
}
|
||||
return railcomActive;
|
||||
}
|
||||
@ -147,7 +149,17 @@ void DCCWaveform::interrupt2() {
|
||||
// that the reminder doesn't block a more urgent packet.
|
||||
reminderWindowOpen=transmitRepeats==0 && remainingPreambles<4 && remainingPreambles>1;
|
||||
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.
|
||||
// Allow for checkAck and its called functions using 22 bytes more.
|
||||
else DCCTimer::updateMinimumFreeMemoryISR(22);
|
||||
@ -172,11 +184,14 @@ void DCCWaveform::interrupt2() {
|
||||
// preamble for next packet will start...
|
||||
remainingPreambles = requiredPreambles;
|
||||
|
||||
// set the railcom coundown to trigger half way
|
||||
// Set the railcom coundown to trigger half way
|
||||
// through the first preamble bit.
|
||||
// Note.. we are still sending the last packet bit
|
||||
// and we then have to allow for the packet end bit
|
||||
if (isMainTrack && railcomActive) DCCTimer::startRailcomTimer(9);
|
||||
// but the timer code allows for this
|
||||
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
|
||||
// Note: If railcomDebug is on, then we send resets to the main
|
||||
// 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.
|
||||
memcpy( transmitPacket, (isMainTrack && (!railcomDebug)) ? idlePacket : resetPacket, sizeof(idlePacket));
|
||||
transmitLength = sizeof(idlePacket);
|
||||
|
@ -85,8 +85,13 @@ class DCCWaveform {
|
||||
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
||||
bool isReminderWindowOpen();
|
||||
void promotePendingPacket();
|
||||
static void setRailcomPossible(bool yes) {
|
||||
railcomPossible=yes;
|
||||
if (!yes) setRailcom(false,false);
|
||||
}
|
||||
static bool setRailcom(bool on, bool debug);
|
||||
static bool isRailcom() {return railcomActive;}
|
||||
static bool isRailcomSampleWindow() {return railcomSampleWindow;}
|
||||
|
||||
private:
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
@ -112,9 +117,10 @@ class DCCWaveform {
|
||||
byte pendingPacket[MAX_PACKET_SIZE+1]; // +1 for checksum
|
||||
byte pendingLength;
|
||||
byte pendingRepeats;
|
||||
static volatile bool railcomActive; // switched on by user
|
||||
static volatile bool railcomDebug; // switched on by user
|
||||
|
||||
static bool railcomPossible; // High accuracy mode only
|
||||
static volatile bool railcomActive; // switched on by user
|
||||
static volatile bool railcomDebug; // switched on by user
|
||||
static volatile bool railcomSampleWindow; // when safe to sample
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
static RMTChannel *rmtMainChannel;
|
||||
static RMTChannel *rmtProgChannel;
|
||||
|
@ -47,11 +47,11 @@
|
||||
#include "IODevice.h"
|
||||
#include "I2CManager.h"
|
||||
#include "DIAG.h"
|
||||
#include "DCCWaveform.h"
|
||||
|
||||
// Debug and diagnostic defines, enable too many will result in slowing the driver
|
||||
#define DIAG_I2CRailcom
|
||||
#define DIAG_I2CRailcom_data
|
||||
#define DIAG_I2CRailcom_reg
|
||||
|
||||
class I2CRailcom : public IODevice {
|
||||
private:
|
||||
@ -62,7 +62,7 @@ private:
|
||||
const uint8_t STOP_BIT = 0x00; // Value LCR bit 2
|
||||
const uint8_t PARITY_ENA = 0x00; // Value LCR bit 3
|
||||
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 unsigned long SC16IS752_XTAL_FREQ_RAILCOM = 16000000; // Baud rate for Railcom signal
|
||||
byte _inbuf[65];
|
||||
@ -106,8 +106,9 @@ public:
|
||||
// Read responses from device
|
||||
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
|
||||
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
|
||||
// we must adjust the trackPWM capabilities
|
||||
DIAG(F("High Accuracy & Railcom disabled"));
|
||||
DCCWaveform::setRailcomPossible(false);
|
||||
FOR_EACH_TRACK(t) {
|
||||
track[t]->trackPWM=false;
|
||||
//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
|
||||
}
|
||||
else DIAG(F("High Accuracy Enabled"));
|
||||
else {
|
||||
DIAG(F("High Accuracy Enabled"));
|
||||
DCCWaveform::setRailcomPossible(true);
|
||||
}
|
||||
#else
|
||||
// For ESP32 we just reinitialize the DCC Waveform
|
||||
DCCWaveform::begin();
|
||||
|
Loading…
Reference in New Issue
Block a user