13 volatile RegisterList DCCpp::mainRegs(MAX_MAIN_REGISTERS);
14 volatile RegisterList DCCpp::progRegs(3);
16 CurrentMonitor DCCpp::mainMonitor;
17 CurrentMonitor DCCpp::progMonitor;
19 bool DCCpp::programMode;
20 bool DCCpp::panicStopped;
32 this->activeFlags[0] = 0;
33 this->activeFlags[1] = 0;
34 this->activeFlags[2] = 0;
35 this->activeFlags[3] = 0;
42 bitSet(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
47 bitClear(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
52 return bitRead(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
57 return bitRead(this->activeFlagsSent[inFunctionNumber / 8], inFunctionNumber % 8) !=
isActivated(inFunctionNumber);
62 for (
int i = 0; i < 4; i++)
63 this->activeFlagsSent[i] = this->activeFlags[i];
66 #ifdef DCCPP_DEBUG_MODE 67 void FunctionsState::printActivated()
69 for (
int i = 0; i < 32; i++)
86 static bool first =
true;
94 #ifdef USE_TEXTCOMMAND 95 TextCommand::process();
101 #if defined(DCCPP_DEBUG_MODE) && defined(DCCPP_PRINT_DCCPP) 106 if (CurrentMonitor::checkTime())
117 void DCCpp::beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
119 DCCppConfig::DirectionMotorA = inOptionalDirectionMotor;
120 DCCppConfig::SignalEnablePinMain = inSignalEnable;
121 DCCppConfig::CurrentMonitorMain = inCurrentMonitor;
124 if (DCCppConfig::SignalEnablePinMain == UNDEFINED_PIN)
126 #ifdef DCCPP_DEBUG_MODE 127 Serial.println(
"No main track");
132 mainMonitor.begin(DCCppConfig::CurrentMonitorMain, DCCppConfig::SignalEnablePinMain, (
char *)
"<p2>");
141 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER1 3199 142 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER1 1599 144 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER1 1855 145 #define DCC_ONE_BIT_PULSE_DURATION_TIMER1 927 146 if (DCCppConfig::DirectionMotorA != UNDEFINED_PIN)
148 pinMode(DCCppConfig::DirectionMotorA, INPUT);
149 digitalWrite(DCCppConfig::DirectionMotorA, LOW);
152 if (inSignalPin != UNDEFINED_PIN)
153 pinMode(inSignalPin, OUTPUT);
155 bitSet(TCCR1A, WGM10);
156 bitSet(TCCR1A, WGM11);
157 bitSet(TCCR1B, WGM12);
158 bitSet(TCCR1B, WGM13);
160 bitSet(TCCR1A, COM1B1);
161 bitSet(TCCR1A, COM1B0);
163 bitClear(TCCR1B, CS12);
164 bitClear(TCCR1B, CS11);
165 bitSet(TCCR1B, CS10);
167 OCR1A = DCC_ONE_BIT_TOTAL_DURATION_TIMER1;
168 OCR1B = DCC_ONE_BIT_PULSE_DURATION_TIMER1;
170 pinMode(DCCppConfig::SignalEnablePinMain, OUTPUT);
172 mainRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
174 bitSet(TIMSK1, OCIE1B);
175 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
177 #ifdef DCCPP_DEBUG_MODE 178 Serial.println(F(
"beginMain achivied"));
182 void DCCpp::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
184 DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
185 DCCppConfig::SignalEnablePinProg = inSignalEnable;
186 DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
189 if (DCCppConfig::SignalEnablePinProg == UNDEFINED_PIN)
191 #ifdef DCCPP_DEBUG_MODE 192 Serial.println(
"No prog track");
197 progMonitor.begin(DCCppConfig::CurrentMonitorProg, DCCppConfig::SignalEnablePinProg, (
char *)
"<p3>");
201 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 208 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER0 49 209 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER0 24 211 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER0 28 212 #define DCC_ONE_BIT_PULSE_DURATION_TIMER0 14 214 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
216 pinMode(DCCppConfig::DirectionMotorB, INPUT);
217 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
220 if (inSignalPin != UNDEFINED_PIN)
221 pinMode(inSignalPin, OUTPUT);
223 bitSet(TCCR0A, WGM00);
224 bitSet(TCCR0A, WGM01);
225 bitSet(TCCR0B, WGM02);
227 bitSet(TCCR0A, COM0B1);
228 bitSet(TCCR0A, COM0B0);
230 bitClear(TCCR0B, CS02);
231 bitSet(TCCR0B, CS01);
232 bitSet(TCCR0B, CS00);
234 OCR0A = DCC_ONE_BIT_TOTAL_DURATION_TIMER0;
235 OCR0B = DCC_ONE_BIT_PULSE_DURATION_TIMER0;
237 pinMode(DCCppConfig::SignalEnablePinProg, OUTPUT);
239 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
241 bitSet(TIMSK0, OCIE0B);
243 #else // Configuration for MEGA 250 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER3 3199 251 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER3 1599 253 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER3 1855 254 #define DCC_ONE_BIT_PULSE_DURATION_TIMER3 927 256 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
258 pinMode(DCCppConfig::DirectionMotorB, INPUT);
259 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
262 pinMode(DCC_SIGNAL_PIN_PROG, OUTPUT);
264 bitSet(TCCR3A, WGM30);
265 bitSet(TCCR3A, WGM31);
266 bitSet(TCCR3B, WGM32);
267 bitSet(TCCR3B, WGM33);
269 bitSet(TCCR3A, COM3B1);
270 bitSet(TCCR3A, COM3B0);
272 bitClear(TCCR3B, CS32);
273 bitClear(TCCR3B, CS31);
274 bitSet(TCCR3B, CS30);
276 OCR3A = DCC_ONE_BIT_TOTAL_DURATION_TIMER3;
277 OCR3B = DCC_ONE_BIT_PULSE_DURATION_TIMER3;
279 pinMode(DCCppConfig::SignalEnablePinProg, OUTPUT);
281 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
283 bitSet(TIMSK3, OCIE3B);
286 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
288 #ifdef DCCPP_DEBUG_MODE 289 Serial.println(F(
"beginProg achivied"));
296 panicStopped =
false;
298 DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
299 DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
301 DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
302 DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
304 DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
305 DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
307 mainMonitor.begin(UNDEFINED_PIN, UNDEFINED_PIN,
"");
308 progMonitor.begin(UNDEFINED_PIN, UNDEFINED_PIN,
"");
311 pinMode(SDCARD_CS, OUTPUT);
312 digitalWrite(SDCARD_CS, HIGH);
317 if (EEStore::needsRefreshing())
321 #ifdef DCCPP_DEBUG_MODE 323 Serial.println(F(
"begin achieved"));
329 void DCCpp::beginEthernet(uint8_t *inMac, uint8_t *inIp, EthernetProtocol inProtocol)
332 for (
int i = 0; i < 4; i++)
333 DCCppConfig::EthernetIp[i] = inIp[i];
335 for (
int i = 0; i < 6; i++)
336 DCCppConfig::EthernetMac[i] = inMac[i];
338 DCCppConfig::Protocol = inProtocol;
341 Ethernet.begin(inMac);
343 Ethernet.begin(inMac, inIp);
345 DCCPP_INTERFACE.begin();
346 #ifdef DCCPP_DEBUG_MODE 349 Serial.println(F(
"beginEthernet achieved"));
386 #define DCC_SIGNAL(R,N) 387 if(R.currentBit==R.currentReg->activePacket->nBits){ 389 if (R.nRepeat>0 && R.currentReg == R.reg) { 392 else if (R.nextReg != NULL) { 393 R.currentReg = R.nextReg; 395 R.tempPacket = R.currentReg->activePacket; 396 R.currentReg->activePacket = R.currentReg->updatePacket; 397 R.currentReg->updatePacket = R.tempPacket; 400 if (R.currentReg == R.maxLoadedReg) 401 R.currentReg = R.reg; 406 if (R.currentReg->activePacket->buf[R.currentBit / 8] & R.bitMask[R.currentBit % 8]) { 407 OCR ## N ## A = DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N; 408 OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N; 410 OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N; 411 OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N; 419 ISR(TIMER1_COMPB_vect) {
420 DCC_SIGNAL(DCCpp::mainRegs, 1)
423 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 425 ISR(TIMER0_COMPB_vect) {
426 DCC_SIGNAL(DCCpp::progRegs, 0)
429 #else // Configuration for MEGA 431 ISR(TIMER3_COMPB_vect) {
432 DCC_SIGNAL(DCCpp::progRegs, 3)
437 #ifdef DCCPP_PRINT_DCCPP 442 void DCCpp::showConfiguration()
444 Serial.println(F(
"*** DCCpp LIBRARY ***"));
446 Serial.print(F(
"VERSION DCC++: "));
447 Serial.println(VERSION);
448 Serial.println(F(DCCPP_LIBRARY_VERSION));
449 Serial.print(F(
"COMPILED: "));
450 Serial.print(__DATE__);
451 Serial.print(F(
" "));
452 Serial.println(__TIME__);
460 if (DCCppConfig::SignalEnablePinMain!= UNDEFINED_PIN)
462 Serial.print(F(
"nnDCC SIG MAIN(DIR): "));
463 Serial.println(DCC_SIGNAL_PIN_MAIN);
464 Serial.print(F(
" DIRECTION: "));
465 Serial.println(DCCppConfig::DirectionMotorA);
466 Serial.print(F(
" ENABLE(PWM): "));
467 Serial.println(DCCppConfig::SignalEnablePinMain);
468 Serial.print(F(
" CURRENT: "));
469 Serial.println(DCCppConfig::CurrentMonitorMain);
472 if (DCCppConfig::SignalEnablePinProg!= UNDEFINED_PIN)
474 Serial.print(F(
"nnDCC SIG PROG(DIR): "));
475 Serial.println(DCC_SIGNAL_PIN_PROG);
476 Serial.print(F(
" DIRECTION: "));
477 Serial.println(DCCppConfig::DirectionMotorB);
478 Serial.print(F(
" ENABLE(PWM): "));
479 Serial.println(DCCppConfig::SignalEnablePinProg);
480 Serial.print(F(
" CURRENT: "));
481 Serial.println(DCCppConfig::CurrentMonitorProg);
483 #if defined(USE_EEPROM) 484 #if defined(USE_TURNOUT) 485 Serial.print(F(
"nnNUM TURNOUTS: "));
486 Serial.println(EEStore::data.nTurnouts);
488 #if defined(USE_SENSOR) 489 Serial.print(F(
" SENSORS: "));
490 Serial.println(EEStore::data.nSensors);
492 #if defined(USE_OUTPUT) 493 Serial.print(F(
" OUTPUTS: "));
494 Serial.println(EEStore::data.nOutputs);
498 #ifdef USE_TEXTCOMMAND 499 Serial.print(F(
"nnINTERFACE: "));
501 Serial.println(F(
"ETHERNET "));
502 Serial.print(F(
"MAC ADDRESS: "));
503 for (
int i = 0; i<5; i++) {
504 Serial.print(DCCppConfig::EthernetMac[i], HEX);
505 Serial.print(F(
":"));
507 Serial.println(DCCppConfig::EthernetMac[5], HEX);
510 Serial.print(F(
"IP ADDRESS: "));
511 Serial.println(Ethernet.localIP());
520 Serial.println(F(
"SERIAL"));
533 panicStopped = inStop;
535 #ifdef DCCPP_DEBUG_MODE 536 Serial.print(F(
"DCCpp PanicStop "));
537 Serial.println(inStop ? F(
"pressed"):F(
"canceled"));
550 if (inProg && DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
551 digitalWrite(DCCppConfig::SignalEnablePinProg, HIGH);
553 if (inMain && DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
554 digitalWrite(DCCppConfig::SignalEnablePinMain, HIGH);
555 DCCPP_INTERFACE.print(
"<p1>");
556 #if !defined(USE_ETHERNET) 557 DCCPP_INTERFACE.println(
"");
563 if (inProg && DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
564 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
565 if (inMain && DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
566 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
567 DCCPP_INTERFACE.print(
"<p0>");
568 #if !defined(USE_ETHERNET) 569 DCCPP_INTERFACE.println(
"");
575 bool DCCpp::setThrottle(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
int inStepsNumber,
int inNewSpeed,
bool inForward)
583 val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
585 #ifdef DCCPP_DEBUG_MODE 586 Serial.print(F(
"DCCpp SetSpeed "));
587 Serial.print(inForward?inNewSpeed:-inNewSpeed);
588 Serial.print(F(
"/"));
589 Serial.print(inStepsNumber);
590 Serial.print(F(
" (in Dcc "));
592 Serial.println(F(
" )"));
595 inpRegs->setThrottle(nReg, inLocoId, val, inForward);
600 void DCCpp::setFunctions(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
FunctionsState &inStates)
602 #ifdef DCCPP_DEBUG_MODE 603 if (inpRegs == &mainRegs)
605 if (nReg > MAX_MAIN_REGISTERS)
606 Serial.println(F(
"Invalid register number on main track."));
610 if (nReg > MAX_PROG_REGISTERS)
611 Serial.println(F(
"Invalid register number on programming track."));
618 byte threeByte1 = 160;
622 for (byte func = 0; func <= 28; func++)
640 oneByte1 += (1 << (func - 1));
655 twoByte1 += (1 << (func - 5));
669 threeByte1 += (1 << (func - 9));
683 fourByte2 += (1 << (func - 13));
697 fiveByte2 += (1 << (func - 21));
702 inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
704 inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
706 inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
708 inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
710 inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
714 #ifdef DCCPP_DEBUG_MODE 715 Serial.print(F(
"DCCpp SetFunctions for loco"));
716 Serial.print(inLocoId);
717 Serial.print(
" / Activated : ");
718 inStates.printActivated();
722 int DCCpp::identifyLocoId(
volatile RegisterList *inReg)
726 temp = inReg->readCV(29, 100, 200);
727 if ((temp != -1) && (bitRead(temp, 5))) {
729 id = inReg->readCV(18, 100, 200);
731 temp = inReg->readCV(17, 100, 200);
733 id =
id + ((temp - 192) << 8);
739 id = inReg->readCV(1, 100, 200);
744 void DCCpp::writeCv(
volatile RegisterList *inReg,
int inCv, byte inValue,
int callBack,
int callBackSub)
746 inReg->writeCVByte(inCv, inValue, callBack, callBackSub);
748 #ifdef DCCPP_DEBUG_MODE 749 Serial.print(F(
"DCCpp WriteCv "));
751 Serial.print(F(
" : "));
752 Serial.println(inValue);
758 mainRegs.setAccessory(inAddress, inSubAddress, inActivate);
760 #ifdef DCCPP_DEBUG_MODE 761 Serial.print(F(
"DCCpp AccessoryOperation "));
762 Serial.print(inAddress);
763 Serial.print(F(
" / "));
764 Serial.print(inSubAddress);
765 Serial.print(F(
" : "));
766 Serial.println(inActivate);
+
static void powerOn(bool inMain = true, bool inProg = true)
static void powerOff(bool inMain = true, bool inProg = true)
static void setAccessory(int inAddress, byte inSubAddress, byte inActivate)
static void panicStop(bool inStop)
static void beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
+
bool isActivationChanged(byte inFunctionNumber)
-
static void powerOn(bool inMain = true, bool inProg = true)
-
-
void inactivate(byte inFunctionNumber)
void activate(byte inFunctionNumber)
bool isActivated(byte inFunctionNumber)
+
void inactivate(byte inFunctionNumber)
static void beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)