13 volatile RegisterList DCCpp::mainRegs(MAX_MAIN_REGISTERS);
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) 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 line");
132 mainMonitor.
begin(DCCppConfig::CurrentMonitorMain, (
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 pinMode(inSignalPin,
OUTPUT);
154 bitSet(TCCR1A, WGM10);
155 bitSet(TCCR1A, WGM11);
156 bitSet(TCCR1B, WGM12);
157 bitSet(TCCR1B, WGM13);
159 bitSet(TCCR1A, COM1B1);
160 bitSet(TCCR1A, COM1B0);
162 bitClear(TCCR1B, CS12);
163 bitClear(TCCR1B, CS11);
164 bitSet(TCCR1B, CS10);
166 OCR1A = DCC_ONE_BIT_TOTAL_DURATION_TIMER1;
167 OCR1B = DCC_ONE_BIT_PULSE_DURATION_TIMER1;
169 pinMode(DCCppConfig::SignalEnablePinMain,
OUTPUT);
171 mainRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
173 bitSet(TIMSK1, OCIE1B);
174 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
176 #ifdef DCCPP_DEBUG_MODE 177 Serial.println(F(
"beginMain achivied"));
181 void DCCpp::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
183 DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
184 DCCppConfig::SignalEnablePinProg = inSignalEnable;
185 DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
188 if (DCCppConfig::SignalEnablePinProg == UNDEFINED_PIN)
190 #ifdef DCCPP_DEBUG_MODE 191 Serial.println(
"No prog line");
196 progMonitor.
begin(DCCppConfig::CurrentMonitorProg, (
char *)
"<p3>");
200 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 207 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER0 49 208 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER0 24 210 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER0 28 211 #define DCC_ONE_BIT_PULSE_DURATION_TIMER0 14 213 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
215 pinMode(DCCppConfig::DirectionMotorB, INPUT);
216 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
219 pinMode(inSignalPin,
OUTPUT);
221 bitSet(TCCR0A, WGM00);
222 bitSet(TCCR0A, WGM01);
223 bitSet(TCCR0B, WGM02);
225 bitSet(TCCR0A, COM0B1);
226 bitSet(TCCR0A, COM0B0);
228 bitClear(TCCR0B, CS02);
229 bitSet(TCCR0B, CS01);
230 bitSet(TCCR0B, CS00);
232 OCR0A = DCC_ONE_BIT_TOTAL_DURATION_TIMER0;
233 OCR0B = DCC_ONE_BIT_PULSE_DURATION_TIMER0;
235 pinMode(DCCppConfig::SignalEnablePinProg,
OUTPUT);
237 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
239 bitSet(TIMSK0, OCIE0B);
241 #else // Configuration for MEGA 248 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER3 3199 249 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER3 1599 251 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER3 1855 252 #define DCC_ONE_BIT_PULSE_DURATION_TIMER3 927 254 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
256 pinMode(DCCppConfig::DirectionMotorB, INPUT);
257 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
260 pinMode(DCC_SIGNAL_PIN_PROG,
OUTPUT);
262 bitSet(TCCR3A, WGM30);
263 bitSet(TCCR3A, WGM31);
264 bitSet(TCCR3B, WGM32);
265 bitSet(TCCR3B, WGM33);
267 bitSet(TCCR3A, COM3B1);
268 bitSet(TCCR3A, COM3B0);
270 bitClear(TCCR3B, CS32);
271 bitClear(TCCR3B, CS31);
272 bitSet(TCCR3B, CS30);
274 OCR3A = DCC_ONE_BIT_TOTAL_DURATION_TIMER3;
275 OCR3B = DCC_ONE_BIT_PULSE_DURATION_TIMER3;
277 pinMode(DCCppConfig::SignalEnablePinProg,
OUTPUT);
279 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
281 bitSet(TIMSK3, OCIE3B);
284 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
286 #ifdef DCCPP_DEBUG_MODE 287 Serial.println(F(
"beginProg achivied"));
294 panicStopped =
false;
296 DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
297 DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
299 DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
300 DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
302 DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
303 DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
305 mainMonitor.
begin(UNDEFINED_PIN,
"");
306 progMonitor.
begin(UNDEFINED_PIN,
"");
309 pinMode(SDCARD_CS,
OUTPUT);
310 digitalWrite(SDCARD_CS, HIGH);
319 #ifdef DCCPP_DEBUG_MODE 321 Serial.println(F(
"begin achieved"));
330 for (
int i = 0; i < 4; i++)
331 DCCppConfig::EthernetIp[i] = inIp[i];
333 for (
int i = 0; i < 6; i++)
334 DCCppConfig::EthernetMac[i] = inMac[i];
336 DCCppConfig::Protocol = inProtocol;
339 Ethernet.begin(inMac);
341 Ethernet.begin(inMac, inIp);
344 #ifdef DCCPP_DEBUG_MODE 347 Serial.println(F(
"beginEthernet achieved"));
384 #define DCC_SIGNAL(R,N) 385 if(R.currentBit==R.currentReg->activePacket->nBits){ 387 if (R.nRepeat>0 && R.currentReg == R.reg) { 390 else if (R.nextReg != NULL) { 391 R.currentReg = R.nextReg; 393 R.tempPacket = R.currentReg->activePacket; 394 R.currentReg->activePacket = R.currentReg->updatePacket; 395 R.currentReg->updatePacket = R.tempPacket; 398 if (R.currentReg == R.maxLoadedReg) 399 R.currentReg = R.reg; 404 if (R.currentReg->activePacket->buf[R.currentBit / 8] & R.bitMask[R.currentBit % 8]) { 405 OCR ## N ## A = DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N; 406 OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N; 408 OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N; 409 OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N; 417 ISR(TIMER1_COMPB_vect) {
418 DCC_SIGNAL(DCCpp::mainRegs, 1)
421 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 423 ISR(TIMER0_COMPB_vect) {
424 DCC_SIGNAL(DCCpp::progRegs, 0)
427 #else // Configuration for MEGA 429 ISR(TIMER3_COMPB_vect) {
430 DCC_SIGNAL(DCCpp::progRegs, 3)
435 #ifdef DCCPP_PRINT_DCCPP 440 void DCCpp::showConfiguration()
442 Serial.println(F(
"*** DCCpp LIBRARY ***"));
444 Serial.print(F(
"VERSION DCC++: "));
445 Serial.println(VERSION);
446 Serial.println(F(
"VERSION DCCpp library: 0.8.0"));
447 Serial.print(F(
"COMPILED: "));
448 Serial.print(__DATE__);
449 Serial.print(F(
" "));
450 Serial.println(__TIME__);
458 if (DCCppConfig::SignalEnablePinMain!= UNDEFINED_PIN)
460 Serial.print(F(
"nnDCC SIG MAIN(DIR): "));
461 Serial.println(DCC_SIGNAL_PIN_MAIN);
462 Serial.print(F(
" DIRECTION: "));
463 Serial.println(DCCppConfig::DirectionMotorA);
464 Serial.print(F(
" ENABLE(PWM): "));
465 Serial.println(DCCppConfig::SignalEnablePinMain);
466 Serial.print(F(
" CURRENT: "));
467 Serial.println(DCCppConfig::CurrentMonitorMain);
470 if (DCCppConfig::SignalEnablePinProg!= UNDEFINED_PIN)
472 Serial.print(F(
"nnDCC SIG PROG(DIR): "));
473 Serial.println(DCC_SIGNAL_PIN_PROG);
474 Serial.print(F(
" DIRECTION: "));
475 Serial.println(DCCppConfig::DirectionMotorB);
476 Serial.print(F(
" ENABLE(PWM): "));
477 Serial.println(DCCppConfig::SignalEnablePinProg);
478 Serial.print(F(
" CURRENT: "));
479 Serial.println(DCCppConfig::CurrentMonitorProg);
481 #if defined(USE_EEPROM) 482 #if defined(USE_TURNOUT) 483 Serial.print(F(
"nnNUM TURNOUTS: "));
486 #if defined(USE_SENSOR) 487 Serial.print(F(
" SENSORS: "));
490 #if defined(USE_OUTPUT) 491 Serial.print(F(
" OUTPUTS: "));
496 #ifdef USE_TEXTCOMMAND 497 Serial.print(F(
"nnINTERFACE: "));
499 Serial.println(F(
"ETHERNET "));
500 Serial.print(F(
"MAC ADDRESS: "));
501 for (
int i = 0; i<5; i++) {
502 Serial.print(DCCppConfig::EthernetMac[i], HEX);
503 Serial.print(F(
":"));
505 Serial.println(DCCppConfig::EthernetMac[5], HEX);
508 Serial.print(F(
"IP ADDRESS: "));
509 Serial.println(Ethernet.localIP());
518 Serial.println(F(
"SERIAL"));
531 panicStopped = inStop;
533 #ifdef DCCPP_DEBUG_MODE 534 Serial.print(F(
"DCCpp PanicStop "));
535 Serial.println(inStop ? F(
"pressed"):F(
"canceled"));
548 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
549 digitalWrite(DCCppConfig::SignalEnablePinProg, HIGH);
550 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
551 digitalWrite(DCCppConfig::SignalEnablePinMain, HIGH);
552 INTERFACE.print(
"<p1>");
553 #if !defined(USE_ETHERNET) 554 INTERFACE.println(
"");
560 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
561 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
562 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
563 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
564 INTERFACE.print(
"<p0>");
565 #if !defined(USE_ETHERNET) 566 INTERFACE.println(
"");
572 bool DCCpp::setThrottle(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
int inStepsNumber,
int inNewSpeed,
bool inForward)
580 val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
582 #ifdef DCCPP_DEBUG_MODE 583 Serial.print(F(
"DCCpp SetSpeed "));
584 Serial.print(inForward?inNewSpeed:-inNewSpeed);
585 Serial.print(F(
"/"));
586 Serial.print(inStepsNumber);
587 Serial.print(F(
" (in Dcc "));
589 Serial.println(F(
" )"));
592 inpRegs->setThrottle(nReg, inLocoId, val, inForward);
599 #ifdef DCCPP_DEBUG_MODE 600 if (inpRegs == &mainRegs)
602 if (nReg > MAX_MAIN_REGISTERS)
603 Serial.println(F(
"Invalid register number on main track."));
607 if (nReg > MAX_PROG_REGISTERS)
608 Serial.println(F(
"Invalid register number on programming track."));
615 byte threeByte1 = 160;
619 for (byte func = 0; func <= 28; func++)
637 oneByte1 += (1 << (func - 1));
652 twoByte1 += (1 << (func - 5));
666 threeByte1 += (1 << (func - 9));
680 fourByte2 += (1 << (func - 13));
694 fiveByte2 += (1 << (func - 21));
699 inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
701 inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
703 inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
705 inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
707 inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
711 #ifdef DCCPP_DEBUG_MODE 712 Serial.print(F(
"DCCpp SetFunctions for loco"));
713 Serial.print(inLocoId);
714 Serial.print(
" / Activated : ");
715 inStates.printActivated();
719 void DCCpp::writeCv(
volatile RegisterList *inReg,
int inLocoId,
int inCv, byte inValue)
721 inReg->writeCVByte(inCv, inValue, 100, 101);
723 #ifdef DCCPP_DEBUG_MODE 724 Serial.print(F(
"DCCpp WriteCv "));
726 Serial.print(F(
" : "));
727 Serial.println(inValue);
731 int DCCpp::readCv(
volatile RegisterList *inReg,
int inLocoId, byte inCv)
733 return inReg->readCVmain(1, 100+inCv, 100+inCv);
738 mainRegs.setAccessory(inAddress, inSubAddress, inActivate);
740 #ifdef DCCPP_DEBUG_MODE 741 Serial.print(F(
"DCCpp AccessoryOperation "));
742 Serial.print(inAddress);
743 Serial.print(F(
" / "));
744 Serial.print(inSubAddress);
745 Serial.print(F(
" : "));
746 Serial.println(inActivate);
static void setAccessory(int inAddress, byte inSubAddress, byte inActivate)
static void panicStop(bool inStop)
void inactivate(byte inFunctionNumber)
bool isActivationChanged(byte inFunctionNumber)
static boolean checkTime()
static bool needsRefreshing()
void activate(byte inFunctionNumber)
static void beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
void begin(int pin, const char *msg, float inSampleMax = 300)
bool isActivated(byte inFunctionNumber)
static void beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
static void beginEthernet(uint8_t *inMac, uint8_t *inIp, EthernetProtocol inProtocol = EthernetProtocol::TCP)