Skip to content

Commit bea58a7

Browse files
committed
Add Railcom cutout to STM32 platform
1 parent ec4c6b9 commit bea58a7

File tree

10 files changed

+72
-18
lines changed

10 files changed

+72
-18
lines changed

DCCTimer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class DCCTimer {
6262
static bool isPWMPin(byte pin);
6363
static void setPWM(byte pin, bool high);
6464
static void clearPWM();
65-
static void startRailcomTimer(byte brakePin);
65+
static void startRailcomTimer();
6666
static void ackRailcomTimer();
6767
static void DCCEXanalogWriteFrequency(uint8_t pin, uint32_t frequency);
6868
static void DCCEXanalogWrite(uint8_t pin, int value, bool invert);

DCCTimerAVR.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
6161
}
6262

6363

64-
void DCCTimer::startRailcomTimer(byte brakePin) {
65-
(void) brakePin; // Ignored... works on pin 9 only
64+
void DCCTimer::startRailcomTimer() {
6665
// diagnostic digitalWrite(4,HIGH);
6766

6867
/* The Railcom timer is started in such a way that it

DCCTimerMEGAAVR.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,8 @@ extern char *__malloc_heap_start;
8080
interruptHandler();
8181
}
8282

83-
void DCCTimer::startRailcomTimer(byte brakePin) {
83+
void DCCTimer::startRailcomTimer() {
8484
// TODO: for intended operation see DCCTimerAVR.cpp
85-
(void) brakePin;
8685
}
8786

8887
void DCCTimer::ackRailcomTimer() {

DCCTimerSAMD.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,8 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
7676
interrupts();
7777
}
7878

79-
void DCCTimer::startRailcomTimer(byte brakePin) {
79+
void DCCTimer::startRailcomTimer() {
8080
// TODO: for intended operation see DCCTimerAVR.cpp
81-
(void) brakePin;
8281
}
8382

8483
void DCCTimer::ackRailcomTimer() {

DCCTimerSTM32.cpp

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@
3030
#ifdef ARDUINO_ARCH_STM32
3131

3232
#include "DCCTimer.h"
33-
#ifdef DEBUG_ADC
3433
#include "TrackManager.h"
35-
#endif
3634
#include "DIAG.h"
3735
#include <wiring_private.h>
3836

@@ -215,13 +213,49 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
215213
interrupts();
216214
}
217215

218-
void DCCTimer::startRailcomTimer(byte brakePin) {
219-
// TODO: for intended operation see DCCTimerAVR.cpp
220-
(void) brakePin;
216+
static HardwareTimer *railcomTimer = nullptr;
217+
218+
void DCCTimer::startRailcomTimer() {
219+
// Initialize main timer if not already done
220+
if (!railcomTimer) {
221+
railcomTimer = new HardwareTimer(TIM3);
222+
railcomTimer->pause();
223+
}
224+
225+
// Start the timer to begin the cutout in ~29us
226+
railcomTimer->resume();
227+
}
228+
229+
void startRailcomCallback() {
230+
TrackManager::setMainBrake(true, true);
231+
if (railcomTimer) {
232+
railcomTimer->pause();
233+
}
221234
}
222235

223236
void DCCTimer::ackRailcomTimer() {
224-
// TODO: for intended operation see DCCTimerAVR.cpp
237+
uint32_t cutoutOffset;
238+
239+
// Un-set the track brake
240+
TrackManager::setMainBrake(false, true);
241+
242+
// Immediately end the Railcom cutout and set up the timer for the next
243+
// cutout. We're in the no-man's land between the end of the cutout window and
244+
// the start of the preamble so we can do time-consuming timer configuration
245+
// without disrupting the DCC signal.
246+
if (railcomTimer) {
247+
railcomTimer->setPrescaleFactor(1);
248+
249+
// Sync up with the primary DCC timer. It will continue to track while paused.
250+
cutoutOffset = dcctimer.getOverflow(MICROSEC_FORMAT) + 26;
251+
railcomTimer->setOverflow(cutoutOffset, MICROSEC_FORMAT);
252+
railcomTimer->setCount(dcctimer.getCount());
253+
254+
// Arm the timer for the next cutout
255+
railcomTimer->refresh();
256+
railcomTimer->attachInterrupt(startRailcomCallback);
257+
railcomTimer->pause();
258+
}
225259
}
226260

227261
bool DCCTimer::isPWMPin(byte pin) {

DCCTimerTEENSY.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
3939
myDCCTimer.begin(interruptHandler, DCC_SIGNAL_TIME);
4040
}
4141

42-
void DCCTimer::startRailcomTimer(byte brakePin) {
42+
void DCCTimer::startRailcomTimer() {
4343
// TODO: for intended operation see DCCTimerAVR.cpp
44-
(void) brakePin;
4544
}
4645

4746
void DCCTimer::ackRailcomTimer() {

DCCWaveform.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ void DCCWaveform::interruptHandler() {
7979
cutoutNextTime=false;
8080
railcomSampleWindow=false; // about to cutout, stop reading railcom data.
8181
railcomCutoutCounter++;
82-
DCCTimer::startRailcomTimer(9);
82+
DCCTimer::startRailcomTimer();
8383
}
8484
#endif
8585
byte sigMain=signalTransform[mainTrack.state];
@@ -177,7 +177,7 @@ void DCCWaveform::interrupt2() {
177177
railcomLastAddressHigh=transmitPacket[0];
178178
railcomLastAddressLow =transmitPacket[1];
179179
railcomSampleWindow=true;
180-
} else if (remainingPreambles==(requiredPreambles-3)) {
180+
} else if (remainingPreambles==(requiredPreambles-6)) {
181181
// cutout can be ended when read
182182
// see above for requiredPreambles
183183
DCCTimer::ackRailcomTimer();

DCCWaveform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131

3232
// Number of preamble bits.
33-
const byte PREAMBLE_BITS_MAIN = 16;
33+
const byte PREAMBLE_BITS_MAIN = 18;
3434
const byte PREAMBLE_BITS_PROG = 22;
3535
const byte MAX_PACKET_SIZE = 5; // NMRA standard extended packets, payload size WITHOUT checksum.
3636

TrackManager.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,12 @@ bool TrackManager::setTrackMode(byte trackToSet, TRACK_MODE mode, int16_t dcAddr
342342
}
343343
DCCTimer::clearPWM(); // has to be AFTER trackPWM changes because if trackPWM==true this is undone for that track
344344
}
345+
#ifdef ARDUINO_ARCH_STM32
346+
// High accuracy mode is not yet implemented or really needed to do Railcom on STM32
347+
DCCWaveform::setRailcomPossible(true);
348+
#else
345349
DCCWaveform::setRailcomPossible(canDo);
350+
#endif
346351
#else
347352
// For ESP32 we just reinitialize the DCC Waveform
348353
DCCWaveform::begin();
@@ -655,6 +660,21 @@ void TrackManager::reportGauges(Print* stream) {
655660
StringFormatter::send(stream,F(">\n"));
656661
}
657662

663+
void TrackManager::setMainBrake(bool on, bool interruptContext) {
664+
setTrackBrake(TRACK_MODE_MAIN, on, interruptContext);
665+
if (progTrackSyncMain) {
666+
setTrackBrake(TRACK_MODE_PROG, on, interruptContext);
667+
}
668+
}
669+
670+
void TrackManager::setTrackBrake(TRACK_MODE trackmode, bool on, bool interruptContext) {
671+
FOR_EACH_TRACK(t) {
672+
if (track[t]->getMode() & trackmode) {
673+
track[t]->setBrake(on, interruptContext);
674+
}
675+
}
676+
}
677+
658678
void TrackManager::setJoinRelayPin(byte joinRelayPin) {
659679
joinRelay=joinRelayPin;
660680
if (joinRelay!=UNUSED_PIN) {

TrackManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ class TrackManager {
7070
static void setMainPower(POWERMODE mode) {setTrackPower(TRACK_MODE_MAIN, mode);}
7171
static void setProgPower(POWERMODE mode) {setTrackPower(TRACK_MODE_PROG, mode);}
7272

73+
static void setTrackBrake(TRACK_MODE trackmode, bool on, bool interruptContext=false);
74+
static void setMainBrake(bool on, bool interruptContext=false);
75+
static void setProgBrake(bool on, bool interruptContext=false) {setTrackBrake(TRACK_MODE_PROG, on, interruptContext);}
76+
7377
static const int16_t MAX_TRACKS=8;
7478
static bool setTrackMode(byte track, TRACK_MODE mode, int16_t DCaddr=0);
7579
static bool parseEqualSign(Print * stream, int16_t params, int16_t p[]);

0 commit comments

Comments
 (0)