Skip to content

Commit 5d17f5e

Browse files
committed
Merge branch 'devel' into devel-mcpwm
2 parents 41543a2 + 8d356ba commit 5d17f5e

27 files changed

+426
-241
lines changed

CommandStation-EX.ino

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,11 @@ void setup()
154154

155155
void loop()
156156
{
157+
#ifdef ENABLE_SERIAL_LOG
158+
SerialLog.loop();
159+
#endif
160+
157161
#ifdef ARDUINO_ARCH_ESP32
158-
USB_SERIAL_WEB // optional web server loop polling
159162

160163
#ifdef BOOSTER_INPUT
161164
static bool oldactive = false;

DCC.cpp

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,47 +1239,3 @@ void DCC::displayCabList(Print * stream) {
12391239
StringFormatter::send(stream,F("<* Default momentum=%d/%d *>\n"),
12401240
DCC::defaultMomentumA,DCC::defaultMomentumD);
12411241
}
1242-
1243-
void DCC::setLocoInBlock(uint16_t loco, uint16_t blockid, bool exclusive) {
1244-
// avoid unused warnings when EXRAIL not active
1245-
(void)loco; (void)blockid; (void)exclusive;
1246-
1247-
// update block loco is in, tell exrail leaving old block, and entering new.
1248-
1249-
// NOTE: The loco table scanning is really inefficient and needs rewriting
1250-
// This was done once in the momentum poc.
1251-
#ifdef EXRAIL_ACTIVE
1252-
auto slot=LocoSlot::getSlot(loco,true);
1253-
if (!slot) return; // loco not known, nothing to do
1254-
1255-
auto oldBlock=slot->getBlockOccupied();
1256-
if (oldBlock==blockid) return;
1257-
if (oldBlock) RMFT2::blockEvent(oldBlock,loco,false);
1258-
slot->setBlockOccupied(blockid);
1259-
if (blockid) RMFT2::blockEvent(blockid,loco,true);
1260-
1261-
if (exclusive) {
1262-
SLOTLOOP {
1263-
if (slot->getLoco()!=loco && slot->getBlockOccupied()==blockid) {
1264-
RMFT2::blockEvent(blockid,slot->getLoco(),false);
1265-
slot->setBlockOccupied(0);
1266-
}
1267-
}
1268-
}
1269-
1270-
#endif
1271-
}
1272-
1273-
void DCC::clearBlock(uint16_t blockid) {
1274-
(void)blockid; // avoid unused warning when EXRAIL not active
1275-
// clear block occupied by loco, tell exrail about all leavers
1276-
#ifdef EXRAIL_ACTIVE
1277-
SLOTLOOP {
1278-
1279-
if (slot->getBlockOccupied()==blockid) {
1280-
RMFT2::blockEvent(blockid,slot->getLoco(),false);
1281-
slot->setBlockOccupied(0);
1282-
}
1283-
}
1284-
#endif
1285-
}

DCC.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ class DCC
8383
static void verifyCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback);
8484
static void verifyCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback);
8585
static bool setTime(uint16_t minutes,uint8_t speed, bool suddenChange);
86-
static void setLocoInBlock(uint16_t loco, uint16_t blockid, bool exclusive);
87-
static void clearBlock(uint16_t blockid);
8886
static void getDriveawayLocoId(ACK_CALLBACK callback);
8987
static void getLocoId(ACK_CALLBACK callback);
9088
static void getConsistId(ACK_CALLBACK callback);

DCCTimerAVR.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -72,44 +72,44 @@ void DCCTimer::startRailcomTimer(byte brakePin) {
7272
- Sets the Railcom pin high at first tick and subsequent ticks
7373
until its reset to setting pin 9 low at next tick.
7474
75-
- Cycles at 436uS so the second tick is the
75+
- Cycles at cutoutDuration so the second tick is the
7676
correct distance from the cutout.
7777
7878
- Waveform code is responsible for resetting
7979
any time between the first and second tick.
8080
(there will be 7 DCC timer1 ticks in which to do this.)
8181
8282
*/
83-
const int cutoutDuration = 430; // Desired interval in microseconds
84-
const int cycle=cutoutDuration/2;
83+
const int Tcs=(26+32)/2; // half way spec Desired time from idealised setup call (at previous DCC timer interrupt) to the cutout.
84+
const int Tce=(454+488)/2; // half way spec (460..480uS) Time from start of cutout to end of cutout.
85+
const int cutoutDuration = Tce-Tcs; // Desired interval in microseconds
86+
const int cycle=(cutoutDuration+1)/2; //
8587

86-
const byte RailcomFudge0=58+58+29;
88+
const byte delayBeforeCutout=58+58+Tcs; // Expected time from idealised setup call (at previous DCC timer interrupt) to the cutout. This is the time we need to wait before we can set pin 9 high. We will then set pin 9 low at the next tick which is cutoutDuration later. This value should be reduced to reflect the Timer1 value measuring the time since the previous hardware interrupt.
8789

8890
// Set Timer2 to CTC mode with set on compare match
8991
TCCR2A = (1 << WGM21) | (1 << COM2B0) | (1 << COM2B1);
9092
// Prescaler of 32
9193
TCCR2B = (1 << CS21) | (1 << CS20);
92-
OCR2A = cycle-1; // Compare match value for 430 uS
94+
OCR2A = cycle; // Compare match value for cutout duration
9395
// Enable Timer2 output on pin 9 (OC2B)
9496
DDRB |= (1 << DDB1);
9597

96-
// RailcomFudge2 is the expected time from idealised
98+
// timeSlip is the expected time from idealised
9799
// setup call (at previous DCC timer interrupt) to the cutout.
98100
// This value should be reduced to reflect the Timer1 value
99101
// measuring the time since the previous hardware interrupt
100-
byte tcfudge=TCNT1/16;
101-
TCNT2=cycle-RailcomFudge0/2+tcfudge/2;
102102

103-
104-
// Previous TIMER1 Tick was at rising end-of-packet bit
105-
// Cutout starts half way through first preamble
106-
// that is 2.5 * 58uS later.
107-
}
103+
// tcnt1 = prescaler 64, tcnt2 prescaler=32
104+
noInterrupts();
105+
uint16_t timeSlip=(TCNT1/64)*32;
106+
TCNT2=cycle-timeSlip/2-delayBeforeCutout/2;
107+
interrupts();
108+
}
108109

109110
void DCCTimer::ackRailcomTimer() {
110111
// Change Timer2 to CTC mode with RESET pin 9 on next compare match
111112
TCCR2A = (1 << WGM21) | (1 << COM2B1);
112-
// diagnostic digitalWrite(4,LOW);
113113
}
114114

115115

EXRAIL2.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,4 +1761,24 @@ void RMFT2::manageRouteCaption(int16_t id,const FSH* caption) {
17611761
CommandDistributor::broadcastRouteCaption(id,caption);
17621762
}
17631763
}
1764+
1765+
void RMFT2::ifAnyFunc(const int16_t * vpinList, int16_t count) {
1766+
// Sets skipIf if none found
1767+
skipIf=false;
1768+
for (int v=0;v<count;v++) {
1769+
int16_t vpin=vpinList[v];
1770+
if (vpin<0 && IODevice::read(-vpin)==0) return;
1771+
if (IODevice::read(vpin)>0) return;
1772+
}
1773+
skipIf=true; // none found
1774+
}
17641775

1776+
void RMFT2::ifAllFunc(const int16_t * vpinList, int16_t count) {
1777+
skipIf=true; // return skipping if any are wrong
1778+
for (int v=0;v<count;v++) {
1779+
int16_t vpin=vpinList[v];
1780+
if (vpin<0 && IODevice::read(-vpin)>0) return;
1781+
if (IODevice::read(vpin)==0) return;
1782+
}
1783+
skipIf=false; // no failures found
1784+
}

EXRAIL2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ class LookList {
245245
OPCODE op2=OPCODE_ENDEXRAIL,OPCODE op3=OPCODE_ENDEXRAIL);
246246
static uint16_t getOperand(int progCounter,byte n);
247247
static void killBlinkOnVpin(VPIN pin,uint16_t count=1);
248+
static void ifAllFunc(const int16_t * vpinList, int16_t count);
249+
static void ifAnyFunc(const int16_t * vpinList, int16_t count);
248250
static RMFT2 * loopTask;
249251
static RMFT2 * pausingTask;
250252
void delayMe(long millisecs);

EXRAIL2MacroBase.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,14 @@
272272
///brief Checks sensor state, If false jumps to matching nested ELSE or ENDIF
273273
///param vpin VPIN of sensor. Negative VPIN will invert sensor state.
274274

275+
#define IF_ALL(vpinList...)
276+
///brief Checks sensor state, If any are false, it jumps to matching nested ELSE or ENDIF
277+
///param vpinlist comma separated list of VPINs of sensors. Negative VPIN will invert sensor state.
278+
279+
#define IF_ANY(vpinList...)
280+
///brief Checks sensor state, If all are false jumps to matching nested ELSE or ENDIF
281+
///param vpinlist comma separated list of VPINs of sensors. Negative VPIN will invert sensor state.
282+
275283
#define IFAMBER(signal_id)
276284
///brief Checks if signal is in AMBER state.
277285
///see IF

EXRAIL2MacroReset.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
#undef HAL
8383
#undef HAL_IGNORE_DEFAULTS
8484
#undef IF
85+
#undef IF_ALL
86+
#undef IF_ANY
8587
#undef IFAMBER
8688
#undef IFCLOSED
8789
#undef IFGREEN

EXRAILMacros.h

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,30 @@ case (__COUNTER__ - StringMacroTracker1) : {\
305305
#define IFLOCO(locolist...) \
306306
case (__COUNTER__ - StringMacroTracker1) : \
307307
{ \
308-
const int16_t loco_id_list[]={locolist}; \
308+
const int16_t temp[]={locolist}; \
309309
skipIf=true; \
310-
for (size_t i=0; i<sizeof(loco_id_list)/sizeof(loco_id_list[0]); i++) { \
311-
if (loco==(uint16_t)loco_id_list[i]) { skipIf=false; break;} \
310+
for (size_t i=0; i<sizeof(temp)/sizeof(temp[0]); i++) { \
311+
if (loco==(uint16_t)temp[i]) { skipIf=false; break;} \
312312
} \
313-
break;\
313+
return;\
314+
}
315+
316+
#undef IF_ALL
317+
#define IF_ALL(vpinList...) \
318+
case (__COUNTER__ - StringMacroTracker1) : \
319+
{ \
320+
const int16_t temp[]={vpinList}; \
321+
ifAllFunc(temp,sizeof(temp)/sizeof(temp[0])); \
322+
return;\
323+
}
324+
325+
#undef IF_ANY
326+
#define IF_ANY(vpinList...) \
327+
case (__COUNTER__ - StringMacroTracker1) : \
328+
{ \
329+
const int16_t temp[]={vpinList}; \
330+
ifAnyFunc(temp,sizeof(temp)/sizeof(temp[0])); \
331+
return;\
314332
}
315333

316334
#undef LCD
@@ -563,6 +581,8 @@ int RMFT2::onLCCLookup[RMFT2::countLCCLookup];
563581
#define IFGREEN(signal_id) OPCODE_IFGREEN,V(signal_id),
564582
#define IFGTE(sensor_id,value) OPCODE_IFGTE,V(sensor_id),OPCODE_PAD,V(value),
565583
#define IFLOCO(loco_list...) OPCODE_IFLOCO,V(__COUNTER__ - StringMacroTracker2),
584+
#define IF_ALL(vpinlist...) OPCODE_IFLOCO,V(__COUNTER__ - StringMacroTracker2),
585+
#define IF_ANY(vpinlist...) OPCODE_IFLOCO,V(__COUNTER__ - StringMacroTracker2),
566586
#define IFLT(sensor_id,value) OPCODE_IFLT,V(sensor_id),OPCODE_PAD,V(value),
567587
#define IFNOT(sensor_id) OPCODE_IFNOT,V(sensor_id),
568588
#define IFRANDOM(percent) OPCODE_IFRANDOM,V(percent),

EXRAILTest.h

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,5 +201,81 @@ ROUTE(1771,"1771 Test IFLOCO with multiple loco ids")
201201
PRINT("IFLOCO 1,2,4 test failed")
202202
ELSE
203203
PRINT("IFLOCO 1,2,4 test passed")
204-
DONE
205-
204+
ENDIF
205+
206+
HAL(Bitmap,1700,10)
207+
SET(1702) SET(1703) SET(1704)
208+
209+
IF_ANY(1700,1701,1702)
210+
PRINT("IF_ANY 0,1,2 test OK")
211+
ELSE
212+
PRINT("IF_ANY 0,1,2 test failed")
213+
ENDIF
214+
215+
IF_ANY(1700,1701,1706)
216+
PRINT("IF_ANY 0,1,6 test failed")
217+
ELSE
218+
PRINT("IF_ANY 0,1,6 test passed")
219+
ENDIF
220+
221+
IF_ALL(1702,1703,1704)
222+
PRINT("IF_ALL 2,3,4 test OK")
223+
ELSE
224+
PRINT("IF_ALL 2,3,4 test failed")
225+
ENDIF
226+
227+
IF_ALL(1702,1703,1706)
228+
PRINT("IF_ALL 2,3,6 test failed")
229+
ELSE
230+
PRINT("IF_ALL 2,3,6 test passed")
231+
ENDIF
232+
233+
IF_ANY(1701,-1706)
234+
PRINT("IF_ANY 1,-1706 test passed")
235+
ELSE
236+
PRINT("IF_ANY 1,-1706 test failed")
237+
ENDIF
238+
239+
IF_ALL(1701,-1706)
240+
PRINT("IF_ALL 1,-1706 test failed")
241+
ELSE
242+
PRINT("IF_ALL 1,-1706 test passed")
243+
ENDIF
244+
245+
DONE
246+
247+
248+
249+
// Speedometer example
250+
// Track is =TS1===TS2===TS3= timing between S2 and S3.
251+
252+
ALIAS(TS1,181) ALIAS(TS2,182) ALIAS(TS3,183)
253+
STEALTH_GLOBAL(
254+
byte testStartSpeed=2;
255+
byte testEndSpeed=100;
256+
byte testStep=10;
257+
byte testSpeed;
258+
unsigned long testStartTime;
259+
)
260+
261+
AUTOMATION(9000,"Run Speed Test") // speed test setup
262+
STEALTH(testSpeed=testStartSpeed;)
263+
PRINT("Starting speed test")
264+
REV(20) // reverse loco to start point
265+
266+
SEQUENCE(9001)
267+
// make sure loco is at start point
268+
AT(TS1) ESTOP
269+
// drive loco fwd at testSpeed
270+
STEALTH(DCC::setThrottle(loco,testSpeed,true);)
271+
// At timing-start sensor(s2) record time
272+
AT(TS2) STEALTH(testStartTime=millis();)
273+
// at timing-end sensor(s3) stop and calculate and print speed
274+
AT(TS3) ESTOP STEALTH(
275+
StringFormatter::send(&USB_SERIAL,
276+
F("Speed %d Time %l\n"), testSpeed, millis()-testStartTime);
277+
testSpeed+=testStep;
278+
if (testSpeed>testEndSpeed) kill(); // test complete =DONE
279+
)
280+
// Reverse back to start, and test again
281+
REV(127) FOLLOW(9001)

0 commit comments

Comments
 (0)