DCCpp
This is the library version of a program for Arduino to control railroading DCC devices.
DCCpp.cpp
1 /*************************************************************
2 project: <DCCpp library>
3 author: <Thierry PARIS>
4 description: <DCCpp class>
5 *************************************************************/
6 
7 #include "Arduino.h"
8 #include "DCCpp.h"
9 
10 // NEXT DECLARE GLOBAL OBJECTS TO PROCESS AND STORE DCC PACKETS AND MONITOR TRACK CURRENTS.
11 // NOTE REGISTER LISTS MUST BE DECLARED WITH "VOLATILE" QUALIFIER TO ENSURE THEY ARE PROPERLY UPDATED BY INTERRUPT ROUTINES
12 
13 volatile RegisterList DCCpp::mainRegs(MAX_MAIN_REGISTERS); // create list of registers for MAX_MAIN_REGISTER Main Track Packets
14 volatile RegisterList DCCpp::progRegs(3); // create a shorter list of only two registers for Program Track Packets
15 
16 CurrentMonitor DCCpp::mainMonitor; // create monitor for current on Main Track
17 CurrentMonitor DCCpp::progMonitor; // create monitor for current on Program Track
18 
19 bool DCCpp::programMode;
20 bool DCCpp::panicStopped;
21 byte DCCpp::ackThreshold = 0;
22 
23 // *********************************************************** FunctionsState
24 
26 {
27  this->clear();
28 }
29 
31 {
32  // Clear all functions
33  this->activeFlags[0] = 0;
34  this->activeFlags[1] = 0;
35  this->activeFlags[2] = 0;
36  this->activeFlags[3] = 0;
37 
38  this->statesSent();
39 }
40 
41 void FunctionsState::activate(byte inFunctionNumber)
42 {
43  bitSet(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
44 }
45 
46 void FunctionsState::inactivate(byte inFunctionNumber)
47 {
48  bitClear(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
49 }
50 
51 bool FunctionsState::isActivated(byte inFunctionNumber)
52 {
53  return bitRead(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
54 }
55 
56 bool FunctionsState::isActivationChanged(byte inFunctionNumber)
57 {
58  return bitRead(this->activeFlagsSent[inFunctionNumber / 8], inFunctionNumber % 8) != isActivated(inFunctionNumber);
59 }
60 
62 {
63  for (int i = 0; i < 4; i++)
64  this->activeFlagsSent[i] = this->activeFlags[i];
65 }
66 
67 #ifdef DCCPP_DEBUG_MODE
68 void FunctionsState::printActivated()
69 {
70  for (int i = 0; i < 32; i++)
71  {
72  if (this->isActivated(i))
73  {
74  Serial.print(i);
75  Serial.print(" ");
76  }
77  }
78 
79  Serial.println("");
80 }
81 #endif
82 
83 // *********************************************************** end of FunctionsState
84 
85 // *********************************************************** DCCpp class
86 
87 static bool first = true;
88 
90 // MAIN ARDUINO LOOP
92 
94 {
95 #ifdef USE_TEXTCOMMAND
96  TextCommand::process(); // check for, and process, and new serial commands
97 #endif
98 
99  if (first)
100  {
101  first = false;
102 #if defined(DCCPP_DEBUG_MODE) && defined(DCCPP_PRINT_DCCPP)
103  showConfiguration();
104 #endif
105  }
106 
108  { // if sufficient time has elapsed since last update, check current draw on Main and Program Tracks
109  mainMonitor.check();
110  progMonitor.check();
111  }
112 
113 #ifdef USE_SENSOR
114  Sensor::check(); // check sensors for activated or not
115 #endif
116 }
117 
118 #ifndef USE_ONLY1_INTERRUPT
119 void DCCpp::beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
120 {
121  DCCppConfig::DirectionMotorA = inOptionalDirectionMotor;
122 #else
123 void DCCpp::beginMain(uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
124 {
125 #endif
126 
127 #ifdef DCCPP_DEBUG_MODE
128 // CheckPowerConnectionsWithLeds(inSignalPin, 1000);
129 #endif
130 
131  DCCppConfig::SignalEnablePinMain = inSignalEnable; // PWM
132  DCCppConfig::CurrentMonitorMain = inCurrentMonitor;
133 
134  // If no main line, exit.
135  if (inSignalPin == UNDEFINED_PIN)
136  {
137 #ifdef DCCPP_DEBUG_MODE
138  Serial.println("No main track");
139 #endif
140  return;
141  }
142 
143  mainMonitor.begin(DCCppConfig::CurrentMonitorMain, DCCppConfig::SignalEnablePinMain, (char *) "<p2>");
144 
145  DCCpp::beginMainDccSignal(inSignalPin);
146 
147  if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
148  digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
149 
150 #ifdef DCCPP_DEBUG_MODE
151  Serial.print(F("beginMain achivied with pin "));
152  Serial.println(inSignalPin);
153 #endif
154 }
155 
156 #ifndef USE_ONLY1_INTERRUPT
157 void DCCpp::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
158 {
159  DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
160 #else
161 void DCCpp::beginProg(uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
162 {
163 #endif
164  DCCppConfig::SignalEnablePinProg = inSignalEnable;
165  DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
166 
167  // If no programming line, exit.
168  if (inSignalPin == UNDEFINED_PIN)
169  {
170 #ifdef DCCPP_DEBUG_MODE
171  Serial.println("No prog track");
172 #endif
173  return;
174  }
175 
176  progMonitor.begin(DCCppConfig::CurrentMonitorProg, DCCppConfig::SignalEnablePinProg, (char *) "<p3>");
177 
178  DCCpp::beginProgDccSignal(inSignalPin);
179 
180 #ifdef DCCPP_DEBUG_MODE
181  Serial.print(F("beginProg achivied with pin "));
182  Serial.println(inSignalPin);
183 #endif
184 }
185 
187 {
188  DCCpp::programMode = false;
189  DCCpp::panicStopped = false;
190  DCCpp::ackThreshold = 30;
191 
192  DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
193  DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
194 
195  DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
196  DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
197 
198 #ifndef USE_ONLY1_INTERRUPT
199  DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
200  DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
201 #else
202  DCCppConfig::SignalPortMaskMain = 0;
203  DCCppConfig::SignalPortMaskProg = 0;
204 #endif
205 
206  mainMonitor.begin(UNDEFINED_PIN, UNDEFINED_PIN, "");
207  progMonitor.begin(UNDEFINED_PIN, UNDEFINED_PIN, "");
208 
209 #ifdef SDCARD_CS
210  pinMode(SDCARD_CS, OUTPUT);
211  digitalWrite(SDCARD_CS, HIGH); // De-select the SD card
212 #endif
213 
214 #ifdef USE_EEPROM
215  EEStore::init(); // initialize and load Turnout and Sensor definitions stored in EEPROM
216  if (EEStore::needsRefreshing())
217  EEStore::store();
218 #endif
219 
220 #ifdef DCCPP_DEBUG_MODE
221  //pinMode(LED_BUILTIN, OUTPUT);
222  Serial.println(F("begin achieved"));
223 #endif
224 
225 } // begin
226 
227 #ifdef USE_ETHERNET
228 void DCCpp::beginEthernet(uint8_t *inMac, uint8_t *inIp, EthernetProtocol inProtocol)
229 {
230  if (inIp != NULL)
231  for (int i = 0; i < 4; i++)
232  DCCppConfig::EthernetIp[i] = inIp[i];
233 
234  for (int i = 0; i < 6; i++)
235  DCCppConfig::EthernetMac[i] = inMac[i];
236 
237  DCCppConfig::Protocol = inProtocol;
238 
239  if (inIp == NULL)
240  Ethernet.begin(inMac); // Start networking using DHCP to get an IP Address
241  else
242  Ethernet.begin(inMac, inIp); // Start networking using STATIC IP Address
243 
244  DCCPP_INTERFACE.begin();
245 #ifdef DCCPP_DEBUG_MODE
246  //pinMode(LED_BUILTIN, OUTPUT);
247  showConfiguration();
248  Serial.println(F("beginEthernet achieved"));
249 #endif
250 } // beginEthernet
251 #endif
252 
253 #ifdef DCCPP_PRINT_DCCPP
254 // PRINT CONFIGURATION INFO TO SERIAL PORT REGARDLESS OF INTERFACE TYPE
256 // - ACTIVATED ON STARTUP IF SHOW_CONFIG_PIN IS TIED HIGH
257 
258 void DCCpp::showConfiguration()
259 {
260  Serial.println(F("*** DCCpp LIBRARY ***"));
261 
262  Serial.print(F("VERSION DCC++: "));
263  Serial.println(VERSION);
264  Serial.println(F(DCCPP_LIBRARY_VERSION));
265  Serial.print(F("COMPILED: "));
266  Serial.print(__DATE__);
267  Serial.print(F(" "));
268  Serial.println(__TIME__);
269 
270  //Serial.print(F("\nARDUINO: "));
271  //Serial.print(ARDUINO_TYPE);
272 
273  //Serial.print(F("\n\nMOTOR SHIELD: "));
274  //Serial.print(MOTOR_SHIELD_NAME);
275 
276 #ifdef ARDUINO_ARCH_AVR
277  Serial.print(F("\n\nDCC SIG MAIN(DIR): "));
278  Serial.println(DCC_SIGNAL_PIN_MAIN);
279 #endif
280 
281 #ifndef USE_ONLY1_INTERRUPT
282  if (DCCppConfig::DirectionMotorA != UNDEFINED_PIN)
283  {
284  Serial.print(F(" DIRECTION: "));
285  Serial.println(DCCppConfig::DirectionMotorA);
286  }
287 #endif
288 
289  if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
290  {
291  Serial.print(F(" ENABLE(PWM): "));
292  Serial.println(DCCppConfig::SignalEnablePinMain);
293  }
294 
295  if (DCCppConfig::CurrentMonitorMain != UNDEFINED_PIN)
296  {
297  Serial.print(F(" CURRENT: "));
298  Serial.println(DCCppConfig::CurrentMonitorMain);
299  }
300 
301 #ifdef ARDUINO_ARCH_AVR
302  Serial.print(F("\n\nDCC SIG PROG(DIR): "));
303  Serial.println(DCC_SIGNAL_PIN_PROG);
304 #endif
305 
306 #ifndef USE_ONLY1_INTERRUPT
307  if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
308  {
309  Serial.print(F(" DIRECTION: "));
310  Serial.println(DCCppConfig::DirectionMotorB);
311  }
312 #endif
313  if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
314  {
315  Serial.print(F(" ENABLE(PWM): "));
316  Serial.println(DCCppConfig::SignalEnablePinProg);
317  }
318  if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
319  {
320  Serial.print(F(" CURRENT: "));
321  Serial.println(DCCppConfig::CurrentMonitorProg);
322  }
323 
324 #if defined(USE_EEPROM)
325 #if defined(USE_TURNOUT)
326  Serial.print(F("\n\nNUM TURNOUTS: "));
327  Serial.println(EEStore::data.nTurnouts);
328 #endif
329 #if defined(USE_SENSOR)
330  Serial.print(F(" SENSORS: "));
331  Serial.println(EEStore::data.nSensors);
332 #endif
333 #if defined(USE_OUTPUT)
334  Serial.print(F(" OUTPUTS: "));
335  Serial.println(EEStore::data.nOutputs);
336 #endif
337 #endif
338 
339 #ifdef USE_TEXTCOMMAND
340  Serial.print(F("\n\nINTERFACE: "));
341 #ifdef USE_ETHERNET
342  Serial.println(F("ETHERNET "));
343  Serial.print(F("MAC ADDRESS: "));
344  for (int i = 0; i<5; i++) {
345  Serial.print(DCCppConfig::EthernetMac[i], HEX);
346  Serial.print(F(":"));
347  }
348  Serial.println(DCCppConfig::EthernetMac[5], HEX);
349 // Serial.print(F("PORT: "));
350 // Serial.println(DCCppConfig::EthernetPort);
351  Serial.print(F("IP ADDRESS: "));
352  Serial.println(Ethernet.localIP());
353 
354 /*#ifdef IP_ADDRESS
355  Serial.println(F(" (STATIC)"));
356 #else
357  Serial.println(F(" (DHCP)"));
358 #endif*/
359 
360 #else
361  Serial.println(F("SERIAL"));
362 #endif
363 
364 #endif
365 // Serial.print(F("\n\nPROGRAM HALTED - PLEASE RESTART ARDUINO"));
366 
367 // while (true);
368 // Serial.println("");
369 }
370 #endif
371 
372 void DCCpp::panicStop(bool inStop)
373 {
374  panicStopped = inStop;
375 
376 #ifdef DCCPP_DEBUG_MODE
377  Serial.print(F("DCCpp PanicStop "));
378  Serial.println(inStop ? F("pressed"):F("canceled"));
379 #endif
380 
381  /* activate or not the power on rails */
382 
383  if (inStop)
384  powerOff();
385  else
386  powerOn();
387 }
388 
389 void DCCpp::powerOn(bool inMain, bool inProg)
390 {
391  bool done = false;
392  if (inProg && DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
393  {
394  digitalWrite(DCCppConfig::SignalEnablePinProg, HIGH);
395  done = true;
396  }
397 
398  if (inMain && DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
399  {
400  digitalWrite(DCCppConfig::SignalEnablePinMain, HIGH);
401  done = true;
402  }
403 
404  if (done)
405  {
406  DCCPP_INTERFACE.print("<p1>");
407 #if !defined(USE_ETHERNET)
408  DCCPP_INTERFACE.println("");
409 #endif
410  }
411 }
412 
413 void DCCpp::powerOff(bool inMain, bool inProg)
414 {
415  bool done = false;
416  if (inProg && DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
417  {
418  digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
419  done = true;
420  }
421  if (inMain && DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
422  {
423  digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
424  done = true;
425  }
426 
427  if (done)
428  {
429  DCCPP_INTERFACE.print("<p0>");
430 #if !defined(USE_ETHERNET)
431  DCCPP_INTERFACE.println("");
432 #endif
433  }
434 }
435 
436 byte DCCpp::setAckThreshold(byte inNewValue)
437 {
438  byte old = DCCpp::ackThreshold;
439  DCCpp::ackThreshold = inNewValue;
440  return old;
441 }
442 
443 /***************************** Driving functions */
444 
445 bool DCCpp::setThrottle(volatile RegisterList *inpRegs, int nReg, int inLocoId, int inStepsNumber, int inNewSpeed, bool inForward)
446 {
447  int val = 0;
448 
449  if (panicStopped)
450  val = 1;
451  else
452  if (inNewSpeed > 0)
453  val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
454 
455 #ifdef DCCPP_DEBUG_MODE
456  Serial.print(F("DCCpp SetSpeed "));
457  Serial.print(inForward?inNewSpeed:-inNewSpeed);
458  Serial.print(F("/"));
459  Serial.print(inStepsNumber);
460  Serial.print(F(" (in Dcc "));
461  Serial.print(val);
462  Serial.println(F(" )"));
463 #endif
464 
465  inpRegs->setThrottle(nReg, inLocoId, val, inForward);
466 
467  return true;
468 }
469 
470 void DCCpp::setFunctions(volatile RegisterList *inpRegs, int nReg, int inLocoId, FunctionsState &inStates)
471 {
472 #ifdef DCCPP_DEBUG_MODE
473  if (inpRegs == &mainRegs)
474  {
475  if (nReg > MAX_MAIN_REGISTERS)
476  Serial.println(F("Invalid register number on main track."));
477  }
478  else
479  {
480  if (nReg > MAX_PROG_REGISTERS)
481  Serial.println(F("Invalid register number on programming track."));
482  }
483 #endif
484  byte flags = 0;
485 
486  byte oneByte1 = 128; // Group one functions F0-F4
487  byte twoByte1 = 176; // Group two F5-F8
488  byte threeByte1 = 160; // Group three F9-F12
489  byte fourByte2 = 0; // Group four F13-F20
490  byte fiveByte2 = 0; // Group five F21-F28
491 
492  for (byte func = 0; func <= 28; func++)
493  {
494  if (func <= 4)
495  {
496  /*
497  * To set functions F0 - F4 on(= 1) or off(= 0) :
498  *
499  * BYTE1 : 128 + F1 * 1 + F2 * 2 + F3 * 4 + F4 * 8 + F0 * 16
500  * BYTE2 : omitted
501  */
502 
503  if (inStates.isActivationChanged(func))
504  flags |= 1;
505  if (inStates.isActivated(func))
506  {
507  if (func == 0)
508  oneByte1 += 16;
509  else
510  oneByte1 += (1 << (func - 1));
511  }
512  }
513  else if (func <= 8)
514  {
515  /*
516  * To set functions F5 - F8 on(= 1) or off(= 0) :
517  *
518  * BYTE1 : 176 + F5 * 1 + F6 * 2 + F7 * 4 + F8 * 8
519  * BYTE2 : omitted
520  */
521 
522  if (inStates.isActivationChanged(func))
523  flags |= 2;
524  if (inStates.isActivated(func))
525  twoByte1 += (1 << (func - 5));
526  }
527  else if (func <= 12)
528  {
529  /*
530  * To set functions F9 - F12 on(= 1) or off(= 0) :
531  *
532  * BYTE1 : 160 + F9 * 1 + F10 * 2 + F11 * 4 + F12 * 8
533  * BYTE2 : omitted
534  */
535 
536  if (inStates.isActivationChanged(func))
537  flags |= 4;
538  if (inStates.isActivated(func))
539  threeByte1 += (1 << (func - 9));
540  }
541  else if (func <= 20)
542  {
543  /*
544  * To set functions F13 - F20 on(= 1) or off(= 0) :
545  *
546  * BYTE1 : 222
547  * BYTE2 : F13 * 1 + F14 * 2 + F15 * 4 + F16 * 8 + F17 * 16 + F18 * 32 + F19 * 64 + F20 * 128
548  */
549 
550  if (inStates.isActivationChanged(func))
551  flags |= 8;
552  if (inStates.isActivated(func))
553  fourByte2 += (1 << (func - 13));
554  }
555  else if (func <= 28)
556  {
557  /*
558  * To set functions F21 - F28 on(= 1) of off(= 0) :
559  *
560  * BYTE1 : 223
561  * BYTE2 : F21 * 1 + F22 * 2 + F23 * 4 + F24 * 8 + F25 * 16 + F26 * 32 + F27 * 64 + F28 * 128
562  */
563 
564  if (inStates.isActivationChanged(func))
565  flags |= 16;
566  if (inStates.isActivated(func))
567  fiveByte2 += (1 << (func - 21));
568  }
569  }
570 
571  if (flags & 1)
572  inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
573  if (flags & 2)
574  inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
575  if (flags & 4)
576  inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
577  if (flags & 8)
578  inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
579  if (flags & 16)
580  inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
581 
582  inStates.statesSent();
583 
584 #ifdef DCCPP_DEBUG_MODE
585  Serial.print(F("DCCpp SetFunctions for loco"));
586  Serial.print(inLocoId);
587  Serial.print(" / Activated : ");
588  inStates.printActivated();
589 #endif
590 }
591 
592 int DCCpp::identifyLocoId(volatile RegisterList *inReg)
593 {
594  int id = -1;
595  int temp;
596  temp = inReg->readCV(29, 100, 200);
597  if ((temp != -1) && (bitRead(temp, 5))) {
598  // long address : get CV#17 and CV#18
599  id = inReg->readCV(18, 100, 200);
600  if (id != -1) {
601  temp = inReg->readCV(17, 100, 200);
602  if (temp != -1) {
603  id = id + ((temp - 192) << 8);
604  }
605  }
606  }
607  else {
608  // short address: read only CV#1
609  id = inReg->readCV(1, 100, 200);
610  }
611  return(id);
612 }
613 
614 void DCCpp::writeCv(volatile RegisterList *inReg, int inCv, byte inValue, int callBack, int callBackSub)
615 {
616  inReg->writeCVByte(inCv, inValue, callBack, callBackSub);
617 
618 #ifdef DCCPP_DEBUG_MODE
619  Serial.print(F("DCCpp WriteCv "));
620  Serial.print(inCv);
621  Serial.print(F(" : "));
622  Serial.println(inValue);
623 #endif
624 }
625 
626 void DCCpp::setAccessory(int inAddress, byte inSubAddress, byte inActivate)
627 {
628  mainRegs.setAccessory(inAddress, inSubAddress, inActivate);
629 
630 #ifdef DCCPP_DEBUG_MODE
631  Serial.print(F("DCCpp AccessoryOperation "));
632  Serial.print(inAddress);
633  Serial.print(F(" / "));
634  Serial.print(inSubAddress);
635  Serial.print(F(" : "));
636  Serial.println(inActivate);
637 #endif
638 }
639 
640 #ifdef DCCPP_DEBUG_MODE
641 void DCCpp::CheckPowerConnectionsWithLeds(uint8_t aDirPin, unsigned int inDelay)
642 {
643  if (DCCppConfig::SignalEnablePinMain != 255 || DCCppConfig::SignalEnablePinProg != 255)
644  {
645  Serial.print(F("DCC signal is started, this function cannot operates."));
646  return;
647  }
648 
649  pinMode(aDirPin, OUTPUT);
650  digitalWrite(aDirPin, HIGH);
651  delay(inDelay);
652 
653  digitalWrite(aDirPin, LOW);
654  delay(inDelay);
655 }
656 #endif
657 
658 
static void setAccessory(int inAddress, byte inSubAddress, byte inActivate)
Definition: DCCpp.cpp:626
static void powerOn(bool inMain=true, bool inProg=true)
Definition: DCCpp.cpp:389
static void powerOff(bool inMain=true, bool inProg=true)
Definition: DCCpp.cpp:413
static void begin()
Definition: DCCpp.cpp:186
static void beginProgDccSignal(uint8_t inSignalPin)
static void beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
Definition: DCCpp.cpp:157
static void beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
Definition: DCCpp.cpp:119
static void panicStop(bool inStop)
Definition: DCCpp.cpp:372
void statesSent()
Definition: DCCpp.cpp:61
static byte setAckThreshold(byte inNewValue)
Definition: DCCpp.cpp:436
void inactivate(byte inFunctionNumber)
Definition: DCCpp.cpp:46
static void beginMainDccSignal(uint8_t inSignalPin)
bool isActivated(byte inFunctionNumber)
Definition: DCCpp.cpp:51
bool isActivationChanged(byte inFunctionNumber)
Definition: DCCpp.cpp:56
FunctionsState()
Definition: DCCpp.cpp:25
void clear()
Definition: DCCpp.cpp:30
static void loop()
Definition: DCCpp.cpp:93
static boolean checkTime()
void activate(byte inFunctionNumber)
Definition: DCCpp.cpp:41
void begin(int pin, int inSignalPin, const char *msg, float inSampleMax=300)