15 volatile RegisterList DCCppClass::mainRegs(MAX_MAIN_REGISTERS);
23 FunctionsState::FunctionsState()
28 void FunctionsState::clear()
31 this->activeFlags[0] = 0;
32 this->activeFlags[1] = 0;
33 this->activeFlags[2] = 0;
34 this->activeFlags[3] = 0;
37 void FunctionsState::activate(byte inFunctionNumber)
39 bitSet(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
42 void FunctionsState::inactivate(byte inFunctionNumber)
44 bitClear(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
47 bool FunctionsState::isActivated(byte inFunctionNumber)
49 return bitRead(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
52 #ifdef DCCPP_DEBUG_MODE 53 void FunctionsState::printActivated()
55 for (
int i = 0; i < 32; i++)
57 if (this->isActivated(i))
72 DCCppClass::DCCppClass()
74 this->programMode =
false;
75 this->panicStopped =
false;
77 DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
78 DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
80 DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
81 DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
83 DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
84 DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
86 mainMonitor.begin(UNDEFINED_PIN,
"");
87 progMonitor.begin(UNDEFINED_PIN,
"");
90 static bool first =
true;
96 void DCCppClass::loop()
98 #ifdef USE_TEXTCOMMAND 99 TextCommand::process();
105 #if defined(DCCPP_DEBUG_MODE) && defined(DCCPP_PRINT_DCCPP) 110 if (CurrentMonitor::checkTime())
112 this->mainMonitor.check();
113 this->progMonitor.check();
144 void DCCppClass::beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
146 DCCppConfig::DirectionMotorA = inOptionalDirectionMotor;
147 DCCppConfig::SignalEnablePinMain = inSignalEnable;
148 DCCppConfig::CurrentMonitorMain = inCurrentMonitor;
151 if (DCCppConfig::SignalEnablePinMain == UNDEFINED_PIN)
153 #ifdef DCCPP_DEBUG_MODE 154 Serial.println(
"No main line");
159 this->mainMonitor.begin(DCCppConfig::CurrentMonitorMain, (
char *)
"<p2>");
168 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER1 3199 169 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER1 1599 171 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER1 1855 172 #define DCC_ONE_BIT_PULSE_DURATION_TIMER1 927 173 if (DCCppConfig::DirectionMotorA != UNDEFINED_PIN)
175 pinMode(DCCppConfig::DirectionMotorA, INPUT);
176 digitalWrite(DCCppConfig::DirectionMotorA, LOW);
179 pinMode(inSignalPin,
OUTPUT);
181 bitSet(TCCR1A, WGM10);
182 bitSet(TCCR1A, WGM11);
183 bitSet(TCCR1B, WGM12);
184 bitSet(TCCR1B, WGM13);
186 bitSet(TCCR1A, COM1B1);
187 bitSet(TCCR1A, COM1B0);
189 bitClear(TCCR1B, CS12);
190 bitClear(TCCR1B, CS11);
191 bitSet(TCCR1B, CS10);
193 OCR1A = DCC_ONE_BIT_TOTAL_DURATION_TIMER1;
194 OCR1B = DCC_ONE_BIT_PULSE_DURATION_TIMER1;
196 pinMode(DCCppConfig::SignalEnablePinMain,
OUTPUT);
198 mainRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
200 bitSet(TIMSK1, OCIE1B);
201 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
203 #ifdef DCCPP_DEBUG_MODE 204 Serial.println(F(
"beginMain achivied"));
208 void DCCppClass::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
210 DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
211 DCCppConfig::SignalEnablePinProg = inSignalEnable;
212 DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
215 if (DCCppConfig::SignalEnablePinProg == UNDEFINED_PIN)
217 #ifdef DCCPP_DEBUG_MODE 218 Serial.println(
"No prog line");
223 this->progMonitor.begin(DCCppConfig::CurrentMonitorProg, (
char *)
"<p3>");
227 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 234 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER0 49 235 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER0 24 237 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER0 28 238 #define DCC_ONE_BIT_PULSE_DURATION_TIMER0 14 240 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
242 pinMode(DCCppConfig::DirectionMotorB, INPUT);
243 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
246 pinMode(inSignalPin,
OUTPUT);
248 bitSet(TCCR0A, WGM00);
249 bitSet(TCCR0A, WGM01);
250 bitSet(TCCR0B, WGM02);
252 bitSet(TCCR0A, COM0B1);
253 bitSet(TCCR0A, COM0B0);
255 bitClear(TCCR0B, CS02);
256 bitSet(TCCR0B, CS01);
257 bitSet(TCCR0B, CS00);
259 OCR0A = DCC_ONE_BIT_TOTAL_DURATION_TIMER0;
260 OCR0B = DCC_ONE_BIT_PULSE_DURATION_TIMER0;
262 pinMode(DCCppConfig::SignalEnablePinProg,
OUTPUT);
264 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
266 bitSet(TIMSK0, OCIE0B);
268 #else // Configuration for MEGA 275 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER3 3199 276 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER3 1599 278 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER3 1855 279 #define DCC_ONE_BIT_PULSE_DURATION_TIMER3 927 281 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
283 pinMode(DCCppConfig::DirectionMotorB, INPUT);
284 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
287 pinMode(DCC_SIGNAL_PIN_PROG,
OUTPUT);
289 bitSet(TCCR3A, WGM30);
290 bitSet(TCCR3A, WGM31);
291 bitSet(TCCR3B, WGM32);
292 bitSet(TCCR3B, WGM33);
294 bitSet(TCCR3A, COM3B1);
295 bitSet(TCCR3A, COM3B0);
297 bitClear(TCCR3B, CS32);
298 bitClear(TCCR3B, CS31);
299 bitSet(TCCR3B, CS30);
301 OCR3A = DCC_ONE_BIT_TOTAL_DURATION_TIMER3;
302 OCR3B = DCC_ONE_BIT_PULSE_DURATION_TIMER3;
304 pinMode(DCCppConfig::SignalEnablePinProg,
OUTPUT);
306 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
308 bitSet(TIMSK3, OCIE3B);
311 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
313 #ifdef DCCPP_DEBUG_MODE 314 Serial.println(F(
"beginProg achivied"));
318 void DCCppClass::begin()
321 pinMode(SDCARD_CS,
OUTPUT);
322 digitalWrite(SDCARD_CS, HIGH);
327 if (EEStore::needsRefreshing())
331 #ifdef DCCPP_DEBUG_MODE 333 Serial.println(F(
"begin achivied"));
339 void DCCppClass::beginEthernet(uint8_t *inMac, uint8_t *inIp, EthernetProtocol inProtocol)
341 for (
int i = 0; i < 4; i++)
342 DCCppConfig::EthernetIp[i] = inIp[i];
343 for (
int i = 0; i < 6; i++)
344 DCCppConfig::EthernetMac[i] = inMac[i];
346 DCCppConfig::Protocol = inProtocol;
349 Ethernet.begin(inMac);
351 Ethernet.begin(inMac, inIp);
354 #ifdef DCCPP_DEBUG_MODE 357 Serial.println(F(
"beginEthernet achivied"));
394 #define DCC_SIGNAL(R,N) 395 if(R.currentBit==R.currentReg->activePacket->nBits){ 397 if (R.nRepeat>0 && R.currentReg == R.reg) { 400 else if (R.nextReg != NULL) { 401 R.currentReg = R.nextReg; 403 R.tempPacket = R.currentReg->activePacket; 404 R.currentReg->activePacket = R.currentReg->updatePacket; 405 R.currentReg->updatePacket = R.tempPacket; 408 if (R.currentReg == R.maxLoadedReg) 409 R.currentReg = R.reg; 414 if (R.currentReg->activePacket->buf[R.currentBit / 8] & R.bitMask[R.currentBit % 8]) { 415 OCR ## N ## A = DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N; 416 OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N; 418 OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N; 419 OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N; 427 ISR(TIMER1_COMPB_vect) {
428 DCC_SIGNAL(DCCppClass::mainRegs, 1)
431 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 433 ISR(TIMER0_COMPB_vect) {
434 DCC_SIGNAL(DCCppClass::progRegs, 0)
437 #else // Configuration for MEGA 439 ISR(TIMER3_COMPB_vect) {
440 DCC_SIGNAL(DCCppClass::progRegs, 3)
445 #ifdef DCCPP_PRINT_DCCPP 450 void DCCppClass::showConfiguration()
452 Serial.println(F(
"*** DCCpp LIBRARY ***"));
454 Serial.print(F(
"VERSION DCC++: "));
455 Serial.println(VERSION);
456 Serial.println(F(
"VERSION DCCpp library: 0.7.0"));
457 Serial.print(F(
"COMPILED: "));
458 Serial.print(__DATE__);
459 Serial.print(F(
" "));
460 Serial.println(__TIME__);
468 if (DCCppConfig::SignalEnablePinMain!= UNDEFINED_PIN)
470 Serial.print(F(
"nnDCC SIG MAIN(DIR): "));
471 Serial.println(DCC_SIGNAL_PIN_MAIN);
472 Serial.print(F(
" DIRECTION: "));
473 Serial.println(DCCppConfig::DirectionMotorA);
474 Serial.print(F(
" ENABLE(PWM): "));
475 Serial.println(DCCppConfig::SignalEnablePinMain);
476 Serial.print(F(
" CURRENT: "));
477 Serial.println(DCCppConfig::CurrentMonitorMain);
480 if (DCCppConfig::SignalEnablePinProg!= UNDEFINED_PIN)
482 Serial.print(F(
"nnDCC SIG PROG(DIR): "));
483 Serial.println(DCC_SIGNAL_PIN_PROG);
484 Serial.print(F(
" DIRECTION: "));
485 Serial.println(DCCppConfig::DirectionMotorB);
486 Serial.print(F(
" ENABLE(PWM): "));
487 Serial.println(DCCppConfig::SignalEnablePinProg);
488 Serial.print(F(
" CURRENT: "));
489 Serial.println(DCCppConfig::CurrentMonitorProg);
491 #if defined(USE_EEPROM) 492 #if defined(USE_TURNOUT) 493 Serial.print(F(
"nnNUM TURNOUTS: "));
494 Serial.println(EEStore::eeStore->data.nTurnouts);
496 #if defined(USE_SENSOR) 497 Serial.print(F(
" SENSORS: "));
498 Serial.println(EEStore::eeStore->data.nSensors);
500 #if defined(USE_OUTPUT) 501 Serial.print(F(
" OUTPUTS: "));
502 Serial.println(EEStore::eeStore->data.nOutputs);
506 #ifdef USE_TEXTCOMMAND 507 Serial.print(F(
"nnINTERFACE: "));
509 Serial.println(F(
"ETHERNET "));
510 Serial.print(F(
"MAC ADDRESS: "));
511 for (
int i = 0; i<5; i++) {
512 Serial.print(DCCppConfig::EthernetMac[i], HEX);
513 Serial.print(F(
":"));
515 Serial.println(DCCppConfig::EthernetMac[5], HEX);
518 Serial.print(F(
"IP ADDRESS: "));
519 Serial.println(Ethernet.localIP());
528 Serial.println(F(
"SERIAL"));
539 void DCCppClass::panicStop(
bool inStop)
541 this->panicStopped = inStop;
543 #ifdef DCCPP_DEBUG_MODE 544 Serial.print(F(
"DCCpp PanicStop "));
545 Serial.println(inStop ? F(
"pressed"):F(
"canceled"));
550 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
551 digitalWrite(DCCppConfig::SignalEnablePinMain, inStop ? LOW : HIGH);
552 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
553 digitalWrite(DCCppConfig::SignalEnablePinProg, inStop ? LOW : HIGH);
556 void DCCppClass::powerOn()
558 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
559 digitalWrite(DCCppConfig::SignalEnablePinProg, HIGH);
560 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
561 digitalWrite(DCCppConfig::SignalEnablePinMain, HIGH);
562 INTERFACE.print(
"<p1>");
563 #if !defined(USE_ETHERNET) 564 INTERFACE.println(
"");
568 void DCCppClass::powerOff()
570 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
571 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
572 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
573 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
574 INTERFACE.print(
"<p0>");
575 #if !defined(USE_ETHERNET) 576 INTERFACE.println(
"");
582 bool DCCppClass::setThrottle(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
int inStepsNumber,
int inNewSpeed,
bool inToLeft)
586 if (this->panicStopped)
590 val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
592 #ifdef DCCPP_DEBUG_MODE 593 Serial.print(F(
"DCCpp SetSpeed "));
594 Serial.print(inNewSpeed);
595 Serial.print(F(
"/"));
596 Serial.print(inStepsNumber);
597 Serial.print(F(
" (in Dcc "));
599 Serial.println(F(
" )"));
602 inpRegs->setThrottle(nReg, inLocoId, val, inToLeft);
613 byte threeByte1 = 160;
617 for (byte func = 0; func <= 28; func++)
629 if (inStates.isActivated(func))
634 oneByte1 += (1 << (func - 1));
647 if (inStates.isActivated(func))
648 twoByte1 += (1 << (func - 5));
660 if (inStates.isActivated(func))
661 threeByte1 += (1 << (func - 9));
673 if (inStates.isActivated(func))
674 fourByte2 += (1 << (func - 13));
686 if (inStates.isActivated(func))
687 fiveByte2 += (1 << (func - 21));
692 inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
694 inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
696 inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
698 inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
700 inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
702 #ifdef DCCPP_DEBUG_MODE 703 Serial.print(F(
"DCCpp SetFunctions for loco"));
704 Serial.print(inLocoId);
705 Serial.print(
" / Activated : ");
706 inStates.printActivated();
710 void DCCppClass::writeCv(
volatile RegisterList *inReg,
int inLocoId,
int inCv, byte inValue)
712 inReg->writeCVByte(inCv, inValue, 100, 101);
714 #ifdef DCCPP_DEBUG_MODE 715 Serial.print(F(
"DCCpp WriteCv "));
717 Serial.print(F(
" : "));
718 Serial.println(inValue);
722 int DCCppClass::readCv(
volatile RegisterList *inReg,
int inLocoId, byte inCv)
724 return inReg->readCVmain(1, 100+inCv, 100+inCv);
727 void DCCppClass::setAccessory(
int inAddress, byte inSubAddress, byte inActivate)
729 this->mainRegs.setAccessory(inAddress, inSubAddress, inActivate);
731 #ifdef DCCPP_DEBUG_MODE 732 Serial.print(F(
"DCCpp AccessoryOperation "));
733 Serial.print(inAddress);
734 Serial.print(F(
" / "));
735 Serial.print(inSubAddress);
736 Serial.print(F(
" : "));
737 Serial.println(inActivate);