22 volatile RegisterList DCCppClass::mainRegs(MAX_MAIN_REGISTERS);
30 FunctionsState::FunctionsState()
35 void FunctionsState::Clear()
38 this->activeFlags[0] = 0;
39 this->activeFlags[1] = 0;
40 this->activeFlags[2] = 0;
41 this->activeFlags[3] = 0;
44 void FunctionsState::Activate(byte inFunctionNumber)
46 bitSet(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
49 void FunctionsState::Inactivate(byte inFunctionNumber)
51 bitClear(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
54 bool FunctionsState::IsActivated(byte inFunctionNumber)
56 return bitRead(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
59 #ifdef DCCPP_DEBUG_MODE 60 void FunctionsState::printActivated()
62 for (
int i = 0; i < 32; i++)
64 if (this->IsActivated(i))
81 this->programMode =
false;
82 this->panicStopped =
false;
84 DCCppConfig::SignalEnablePinMain = 255;
85 DCCppConfig::CurrentMonitorMain = 255;
87 DCCppConfig::SignalEnablePinProg = 255;
88 DCCppConfig::CurrentMonitorProg = 255;
90 DCCppConfig::DirectionMotorA = 255;
91 DCCppConfig::DirectionMotorB = 255;
93 MainMonitor.begin(255,
"");
94 ProgMonitor.begin(255,
"");
97 static bool first =
true;
103 void DCCppClass::loop()
105 #ifdef USE_TEXTCOMMAND 106 TextCommand::process();
112 #if defined(DCCPP_DEBUG_MODE) && defined(DCCPP_PRINT_DCCPP) 117 if (CurrentMonitor::checkTime())
151 void DCCppClass::beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
153 DCCppConfig::DirectionMotorA = inOptionalDirectionMotor;
154 DCCppConfig::SignalEnablePinMain = inSignalEnable;
155 DCCppConfig::CurrentMonitorMain = inCurrentMonitor;
158 if (DCCppConfig::SignalEnablePinMain == 255)
160 #ifdef DCCPP_DEBUG_MODE 161 Serial.println(
"No main line");
166 MainMonitor.begin(DCCppConfig::CurrentMonitorMain, (
char *)
"<p2>");
175 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER1 3199 176 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER1 1599 178 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER1 1855 179 #define DCC_ONE_BIT_PULSE_DURATION_TIMER1 927 180 if (DCCppConfig::DirectionMotorA != 255)
182 pinMode(DCCppConfig::DirectionMotorA, INPUT);
183 digitalWrite(DCCppConfig::DirectionMotorA, LOW);
186 pinMode(inSignalPin, OUTPUT);
188 bitSet(TCCR1A, WGM10);
189 bitSet(TCCR1A, WGM11);
190 bitSet(TCCR1B, WGM12);
191 bitSet(TCCR1B, WGM13);
193 bitSet(TCCR1A, COM1B1);
194 bitSet(TCCR1A, COM1B0);
196 bitClear(TCCR1B, CS12);
197 bitClear(TCCR1B, CS11);
198 bitSet(TCCR1B, CS10);
200 OCR1A = DCC_ONE_BIT_TOTAL_DURATION_TIMER1;
201 OCR1B = DCC_ONE_BIT_PULSE_DURATION_TIMER1;
203 pinMode(DCCppConfig::SignalEnablePinMain, OUTPUT);
205 mainRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
207 bitSet(TIMSK1, OCIE1B);
208 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
210 #ifdef DCCPP_DEBUG_MODE 211 Serial.println(F(
"beginMain achivied"));
215 void DCCppClass::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
217 DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
218 DCCppConfig::SignalEnablePinProg = inSignalEnable;
219 DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
222 if (DCCppConfig::SignalEnablePinProg == 255)
224 #ifdef DCCPP_DEBUG_MODE 225 Serial.println(
"No prog line");
230 ProgMonitor.begin(DCCppConfig::CurrentMonitorProg, (
char *)
"<p3>");
234 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 241 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER0 49 242 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER0 24 244 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER0 28 245 #define DCC_ONE_BIT_PULSE_DURATION_TIMER0 14 247 if (DCCppConfig::DirectionMotorB != 255)
249 pinMode(DCCppConfig::DirectionMotorB, INPUT);
250 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
253 pinMode(inSignalPin, OUTPUT);
255 bitSet(TCCR0A, WGM00);
256 bitSet(TCCR0A, WGM01);
257 bitSet(TCCR0B, WGM02);
259 bitSet(TCCR0A, COM0B1);
260 bitSet(TCCR0A, COM0B0);
262 bitClear(TCCR0B, CS02);
263 bitSet(TCCR0B, CS01);
264 bitSet(TCCR0B, CS00);
266 OCR0A = DCC_ONE_BIT_TOTAL_DURATION_TIMER0;
267 OCR0B = DCC_ONE_BIT_PULSE_DURATION_TIMER0;
269 pinMode(DCCppConfig::SignalEnablePinProg, OUTPUT);
271 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
273 bitSet(TIMSK0, OCIE0B);
275 #else // Configuration for MEGA 282 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER3 3199 283 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER3 1599 285 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER3 1855 286 #define DCC_ONE_BIT_PULSE_DURATION_TIMER3 927 288 if (DCCppConfig::DirectionMotorB != 255)
290 pinMode(DCCppConfig::DirectionMotorB, INPUT);
291 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
294 pinMode(DCC_SIGNAL_PIN_PROG, OUTPUT);
296 bitSet(TCCR3A, WGM30);
297 bitSet(TCCR3A, WGM31);
298 bitSet(TCCR3B, WGM32);
299 bitSet(TCCR3B, WGM33);
301 bitSet(TCCR3A, COM3B1);
302 bitSet(TCCR3A, COM3B0);
304 bitClear(TCCR3B, CS32);
305 bitClear(TCCR3B, CS31);
306 bitSet(TCCR3B, CS30);
308 OCR3A = DCC_ONE_BIT_TOTAL_DURATION_TIMER3;
309 OCR3B = DCC_ONE_BIT_PULSE_DURATION_TIMER3;
311 pinMode(DCCppConfig::SignalEnablePinProg, OUTPUT);
313 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
315 bitSet(TIMSK3, OCIE3B);
318 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
320 #ifdef DCCPP_DEBUG_MODE 321 Serial.println(F(
"beginProg achivied"));
325 void DCCppClass::begin()
328 pinMode(SDCARD_CS, OUTPUT);
329 digitalWrite(SDCARD_CS, HIGH);
334 if (EEStore::needsRefreshing())
338 #ifdef DCCPP_DEBUG_MODE 340 Serial.println(F(
"begin achivied"));
346 void DCCppClass::beginEthernet(uint8_t *inMac, uint8_t *inIp)
348 for (
int i = 0; i < 4; i++)
349 DCCppConfig::EthernetIp[i] = inIp[i];
350 for (
int i = 0; i < 6; i++)
351 DCCppConfig::EthernetMac[i] = inMac[i];
354 Ethernet.begin(inMac);
356 Ethernet.begin(inMac, inIp);
359 #ifdef DCCPP_DEBUG_MODE 362 Serial.println(F(
"beginEthernet achivied"));
399 #define DCC_SIGNAL(R,N) 400 if(R.currentBit==R.currentReg->activePacket->nBits){ 402 if (R.nRepeat>0 && R.currentReg == R.reg) { 405 else if (R.nextReg != NULL) { 406 R.currentReg = R.nextReg; 408 R.tempPacket = R.currentReg->activePacket; 409 R.currentReg->activePacket = R.currentReg->updatePacket; 410 R.currentReg->updatePacket = R.tempPacket; 413 if (R.currentReg == R.maxLoadedReg) 414 R.currentReg = R.reg; 419 if (R.currentReg->activePacket->buf[R.currentBit / 8] & R.bitMask[R.currentBit % 8]) { 420 OCR ## N ## A = DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N; 421 OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N; 423 OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N; 424 OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N; 432 ISR(TIMER1_COMPB_vect) {
433 DCC_SIGNAL(DCCppClass::mainRegs, 1)
436 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 438 ISR(TIMER0_COMPB_vect) {
439 DCC_SIGNAL(DCCppClass::progRegs, 0)
442 #else // Configuration for MEGA 444 ISR(TIMER3_COMPB_vect) {
445 DCC_SIGNAL(DCCppClass::progRegs, 3)
450 #ifdef DCCPP_PRINT_DCCPP 455 void DCCppClass::showConfiguration()
457 Serial.println(F(
"n*** DCCpp LIBRARY CONFIGURATION ***n"));
459 Serial.print(F(
"nVERSION: "));
460 Serial.println(VERSION);
461 Serial.print(F(
"nCOMPILED: "));
462 Serial.print(__DATE__);
463 Serial.print(F(
" "));
464 Serial.println(__TIME__);
472 if (DCCppConfig::SignalEnablePinMain!= 255)
474 Serial.print(F(
"nnDCC SIG MAIN(DIR): "));
475 Serial.print(DCC_SIGNAL_PIN_MAIN);
476 Serial.print(F(
"n DIRECTION: "));
477 Serial.print(DCCppConfig::DirectionMotorA);
478 Serial.print(F(
"n ENABLE(PWM): "));
479 Serial.print(DCCppConfig::SignalEnablePinMain);
480 Serial.print(F(
"n CURRENT: "));
481 Serial.println(DCCppConfig::CurrentMonitorMain);
484 if (DCCppConfig::SignalEnablePinProg!= 255)
486 Serial.print(F(
"nnDCC SIG PROG(DIR): "));
487 Serial.print(DCC_SIGNAL_PIN_PROG);
488 Serial.print(F(
"n DIRECTION: "));
489 Serial.print(DCCppConfig::DirectionMotorB);
490 Serial.print(F(
"n ENABLE(PWM): "));
491 Serial.print(DCCppConfig::SignalEnablePinProg);
492 Serial.print(F(
"n CURRENT: "));
493 Serial.println(DCCppConfig::CurrentMonitorProg);
495 #if defined(USE_TURNOUT) && defined(USE_EEPROM) 496 Serial.print(F(
"nnNUM TURNOUTS: "));
497 Serial.print(EEStore::eeStore->data.nTurnouts);
498 Serial.print(F(
"n SENSORS: "));
499 Serial.print(EEStore::eeStore->data.nSensors);
500 Serial.print(F(
"n OUTPUTS: "));
501 Serial.println(EEStore::eeStore->data.nOutputs);
504 #ifdef USE_TEXTCOMMAND 505 Serial.print(F(
"nnINTERFACE: "));
507 Serial.println(F(
"ETHERNET "));
508 Serial.print(F(
"MAC ADDRESS: "));
509 for (
int i = 0; i<5; i++) {
510 Serial.print(DCCppConfig::EthernetMac[i], HEX);
511 Serial.print(F(
":"));
513 Serial.println(DCCppConfig::EthernetMac[5], HEX);
516 Serial.print(F(
"nIP ADDRESS: "));
518 Serial.println(Ethernet.localIP());
527 Serial.println(F(
"SERIAL"));
538 void DCCppClass::PanicStop(
bool inStop)
540 this->panicStopped = inStop;
542 #ifdef DCCPP_DEBUG_MODE 543 Serial.print(F(
"DCCpp PanicStop "));
544 Serial.println(inStop ? F(
"pressed"):F(
"canceled"));
549 if (DCCppConfig::SignalEnablePinMain != 255)
550 digitalWrite(DCCppConfig::SignalEnablePinMain, inStop ? LOW : HIGH);
551 if (DCCppConfig::SignalEnablePinProg != 255)
552 digitalWrite(DCCppConfig::SignalEnablePinProg, inStop ? LOW : HIGH);
555 void DCCppClass::StartProgramMode()
557 this->programMode =
true;
560 void DCCppClass::EndProgramMode()
562 this->programMode =
false;
567 bool DCCppClass::SetThrottle(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
int inStepsNumber,
int inNewSpeed,
bool inToLeft)
571 if (this->panicStopped)
575 val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
577 #ifdef DCCPP_DEBUG_MODE 578 Serial.print(F(
"DCCpp SetSpeed "));
579 Serial.print(inNewSpeed);
580 Serial.print(F(
"/"));
581 Serial.print(inStepsNumber);
582 Serial.print(F(
" (in Dcc "));
584 Serial.println(F(
" )"));
587 inpRegs->setThrottle(nReg, inLocoId, val, inToLeft);
598 byte threeByte1 = 160;
602 for (byte func = 0; func <= 28; func++)
614 if (inStates.IsActivated(func))
619 oneByte1 += (1 << (func - 1));
632 if (inStates.IsActivated(func))
633 twoByte1 += (1 << (func - 5));
645 if (inStates.IsActivated(func))
646 threeByte1 += (1 << (func - 9));
658 if (inStates.IsActivated(func))
659 fourByte2 += (1 << (func - 13));
671 if (inStates.IsActivated(func))
672 fiveByte2 += (1 << (func - 21));
677 inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
679 inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
681 inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
683 inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
685 inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
687 #ifdef DCCPP_DEBUG_MODE 688 Serial.print(F(
"DCCpp SetFunctions for loco"));
689 Serial.print(inLocoId);
690 Serial.print(
" / Activated : ");
691 inStates.printActivated();
695 void DCCppClass::WriteCv(
volatile RegisterList *inReg,
int inLocoId,
int inCv, byte inValue)
697 inReg->writeCVByte(inCv, inValue, 100, 101);
699 #ifdef DCCPP_DEBUG_MODE 700 Serial.print(F(
"DCCpp WriteCv "));
702 Serial.print(F(
" : "));
703 Serial.println(inValue);
707 int DCCppClass::ReadCv(
volatile RegisterList *inReg,
int inLocoId, byte inCv)
709 return inReg->readCVmain(1, 100+inCv, 100+inCv);