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;
40 bitSet(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
45 bitClear(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
50 return bitRead(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
53 #ifdef DCCPP_DEBUG_MODE 54 void FunctionsState::printActivated()
56 for (
int i = 0; i < 32; i++)
73 static bool first =
true;
81 #ifdef USE_TEXTCOMMAND 82 TextCommand::process();
88 #if defined(DCCPP_DEBUG_MODE) && defined(DCCPP_PRINT_DCCPP) 104 void DCCpp::beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
106 DCCppConfig::DirectionMotorA = inOptionalDirectionMotor;
107 DCCppConfig::SignalEnablePinMain = inSignalEnable;
108 DCCppConfig::CurrentMonitorMain = inCurrentMonitor;
111 if (DCCppConfig::SignalEnablePinMain == UNDEFINED_PIN)
113 #ifdef DCCPP_DEBUG_MODE 114 Serial.println(
"No main line");
119 mainMonitor.
begin(DCCppConfig::CurrentMonitorMain, (
char *)
"<p2>");
128 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER1 3199 129 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER1 1599 131 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER1 1855 132 #define DCC_ONE_BIT_PULSE_DURATION_TIMER1 927 133 if (DCCppConfig::DirectionMotorA != UNDEFINED_PIN)
135 pinMode(DCCppConfig::DirectionMotorA, INPUT);
136 digitalWrite(DCCppConfig::DirectionMotorA, LOW);
139 pinMode(inSignalPin,
OUTPUT);
141 bitSet(TCCR1A, WGM10);
142 bitSet(TCCR1A, WGM11);
143 bitSet(TCCR1B, WGM12);
144 bitSet(TCCR1B, WGM13);
146 bitSet(TCCR1A, COM1B1);
147 bitSet(TCCR1A, COM1B0);
149 bitClear(TCCR1B, CS12);
150 bitClear(TCCR1B, CS11);
151 bitSet(TCCR1B, CS10);
153 OCR1A = DCC_ONE_BIT_TOTAL_DURATION_TIMER1;
154 OCR1B = DCC_ONE_BIT_PULSE_DURATION_TIMER1;
156 pinMode(DCCppConfig::SignalEnablePinMain,
OUTPUT);
158 mainRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
160 bitSet(TIMSK1, OCIE1B);
161 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
163 #ifdef DCCPP_DEBUG_MODE 164 Serial.println(F(
"beginMain achivied"));
168 void DCCpp::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
170 DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
171 DCCppConfig::SignalEnablePinProg = inSignalEnable;
172 DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
175 if (DCCppConfig::SignalEnablePinProg == UNDEFINED_PIN)
177 #ifdef DCCPP_DEBUG_MODE 178 Serial.println(
"No prog line");
183 progMonitor.
begin(DCCppConfig::CurrentMonitorProg, (
char *)
"<p3>");
187 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 194 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER0 49 195 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER0 24 197 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER0 28 198 #define DCC_ONE_BIT_PULSE_DURATION_TIMER0 14 200 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
202 pinMode(DCCppConfig::DirectionMotorB, INPUT);
203 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
206 pinMode(inSignalPin,
OUTPUT);
208 bitSet(TCCR0A, WGM00);
209 bitSet(TCCR0A, WGM01);
210 bitSet(TCCR0B, WGM02);
212 bitSet(TCCR0A, COM0B1);
213 bitSet(TCCR0A, COM0B0);
215 bitClear(TCCR0B, CS02);
216 bitSet(TCCR0B, CS01);
217 bitSet(TCCR0B, CS00);
219 OCR0A = DCC_ONE_BIT_TOTAL_DURATION_TIMER0;
220 OCR0B = DCC_ONE_BIT_PULSE_DURATION_TIMER0;
222 pinMode(DCCppConfig::SignalEnablePinProg,
OUTPUT);
224 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
226 bitSet(TIMSK0, OCIE0B);
228 #else // Configuration for MEGA 235 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER3 3199 236 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER3 1599 238 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER3 1855 239 #define DCC_ONE_BIT_PULSE_DURATION_TIMER3 927 241 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
243 pinMode(DCCppConfig::DirectionMotorB, INPUT);
244 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
247 pinMode(DCC_SIGNAL_PIN_PROG,
OUTPUT);
249 bitSet(TCCR3A, WGM30);
250 bitSet(TCCR3A, WGM31);
251 bitSet(TCCR3B, WGM32);
252 bitSet(TCCR3B, WGM33);
254 bitSet(TCCR3A, COM3B1);
255 bitSet(TCCR3A, COM3B0);
257 bitClear(TCCR3B, CS32);
258 bitClear(TCCR3B, CS31);
259 bitSet(TCCR3B, CS30);
261 OCR3A = DCC_ONE_BIT_TOTAL_DURATION_TIMER3;
262 OCR3B = DCC_ONE_BIT_PULSE_DURATION_TIMER3;
264 pinMode(DCCppConfig::SignalEnablePinProg,
OUTPUT);
266 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
268 bitSet(TIMSK3, OCIE3B);
271 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
273 #ifdef DCCPP_DEBUG_MODE 274 Serial.println(F(
"beginProg achivied"));
281 panicStopped =
false;
283 DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
284 DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
286 DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
287 DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
289 DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
290 DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
292 mainMonitor.
begin(UNDEFINED_PIN,
"");
293 progMonitor.
begin(UNDEFINED_PIN,
"");
296 pinMode(SDCARD_CS,
OUTPUT);
297 digitalWrite(SDCARD_CS, HIGH);
306 #ifdef DCCPP_DEBUG_MODE 308 Serial.println(F(
"begin achieved"));
317 for (
int i = 0; i < 4; i++)
318 DCCppConfig::EthernetIp[i] = inIp[i];
320 for (
int i = 0; i < 6; i++)
321 DCCppConfig::EthernetMac[i] = inMac[i];
323 DCCppConfig::Protocol = inProtocol;
326 Ethernet.begin(inMac);
328 Ethernet.begin(inMac, inIp);
331 #ifdef DCCPP_DEBUG_MODE 334 Serial.println(F(
"beginEthernet achieved"));
371 #define DCC_SIGNAL(R,N) 372 if(R.currentBit==R.currentReg->activePacket->nBits){ 374 if (R.nRepeat>0 && R.currentReg == R.reg) { 377 else if (R.nextReg != NULL) { 378 R.currentReg = R.nextReg; 380 R.tempPacket = R.currentReg->activePacket; 381 R.currentReg->activePacket = R.currentReg->updatePacket; 382 R.currentReg->updatePacket = R.tempPacket; 385 if (R.currentReg == R.maxLoadedReg) 386 R.currentReg = R.reg; 391 if (R.currentReg->activePacket->buf[R.currentBit / 8] & R.bitMask[R.currentBit % 8]) { 392 OCR ## N ## A = DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N; 393 OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N; 395 OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N; 396 OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N; 404 ISR(TIMER1_COMPB_vect) {
405 DCC_SIGNAL(DCCpp::mainRegs, 1)
408 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 410 ISR(TIMER0_COMPB_vect) {
411 DCC_SIGNAL(DCCpp::progRegs, 0)
414 #else // Configuration for MEGA 416 ISR(TIMER3_COMPB_vect) {
417 DCC_SIGNAL(DCCpp::progRegs, 3)
422 #ifdef DCCPP_PRINT_DCCPP 427 void DCCpp::showConfiguration()
429 Serial.println(F(
"*** DCCpp LIBRARY ***"));
431 Serial.print(F(
"VERSION DCC++: "));
432 Serial.println(VERSION);
433 Serial.println(F(
"VERSION DCCpp library: 0.8.0"));
434 Serial.print(F(
"COMPILED: "));
435 Serial.print(__DATE__);
436 Serial.print(F(
" "));
437 Serial.println(__TIME__);
445 if (DCCppConfig::SignalEnablePinMain!= UNDEFINED_PIN)
447 Serial.print(F(
"nnDCC SIG MAIN(DIR): "));
448 Serial.println(DCC_SIGNAL_PIN_MAIN);
449 Serial.print(F(
" DIRECTION: "));
450 Serial.println(DCCppConfig::DirectionMotorA);
451 Serial.print(F(
" ENABLE(PWM): "));
452 Serial.println(DCCppConfig::SignalEnablePinMain);
453 Serial.print(F(
" CURRENT: "));
454 Serial.println(DCCppConfig::CurrentMonitorMain);
457 if (DCCppConfig::SignalEnablePinProg!= UNDEFINED_PIN)
459 Serial.print(F(
"nnDCC SIG PROG(DIR): "));
460 Serial.println(DCC_SIGNAL_PIN_PROG);
461 Serial.print(F(
" DIRECTION: "));
462 Serial.println(DCCppConfig::DirectionMotorB);
463 Serial.print(F(
" ENABLE(PWM): "));
464 Serial.println(DCCppConfig::SignalEnablePinProg);
465 Serial.print(F(
" CURRENT: "));
466 Serial.println(DCCppConfig::CurrentMonitorProg);
468 #if defined(USE_EEPROM) 469 #if defined(USE_TURNOUT) 470 Serial.print(F(
"nnNUM TURNOUTS: "));
473 #if defined(USE_SENSOR) 474 Serial.print(F(
" SENSORS: "));
477 #if defined(USE_OUTPUT) 478 Serial.print(F(
" OUTPUTS: "));
483 #ifdef USE_TEXTCOMMAND 484 Serial.print(F(
"nnINTERFACE: "));
486 Serial.println(F(
"ETHERNET "));
487 Serial.print(F(
"MAC ADDRESS: "));
488 for (
int i = 0; i<5; i++) {
489 Serial.print(DCCppConfig::EthernetMac[i], HEX);
490 Serial.print(F(
":"));
492 Serial.println(DCCppConfig::EthernetMac[5], HEX);
495 Serial.print(F(
"IP ADDRESS: "));
496 Serial.println(Ethernet.localIP());
505 Serial.println(F(
"SERIAL"));
518 panicStopped = inStop;
520 #ifdef DCCPP_DEBUG_MODE 521 Serial.print(F(
"DCCpp PanicStop "));
522 Serial.println(inStop ? F(
"pressed"):F(
"canceled"));
535 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
536 digitalWrite(DCCppConfig::SignalEnablePinProg, HIGH);
537 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
538 digitalWrite(DCCppConfig::SignalEnablePinMain, HIGH);
539 INTERFACE.print(
"<p1>");
540 #if !defined(USE_ETHERNET) 541 INTERFACE.println(
"");
547 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
548 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
549 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
550 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
551 INTERFACE.print(
"<p0>");
552 #if !defined(USE_ETHERNET) 553 INTERFACE.println(
"");
559 bool DCCpp::setThrottle(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
int inStepsNumber,
int inNewSpeed,
bool inForward)
567 val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
569 #ifdef DCCPP_DEBUG_MODE 570 Serial.print(F(
"DCCpp SetSpeed "));
571 Serial.print(inForward?inNewSpeed:-inNewSpeed);
572 Serial.print(F(
"/"));
573 Serial.print(inStepsNumber);
574 Serial.print(F(
" (in Dcc "));
576 Serial.println(F(
" )"));
579 inpRegs->setThrottle(nReg, inLocoId, val, inForward);
586 #ifdef DCCPP_DEBUG_MODE 587 if (inpRegs == &mainRegs)
589 if (nReg > MAX_MAIN_REGISTERS)
590 Serial.println(F(
"Invalid register number on main track."));
594 if (nReg > MAX_PROG_REGISTERS)
595 Serial.println(F(
"Invalid register number on programming track."));
602 byte threeByte1 = 160;
606 for (byte func = 0; func <= 28; func++)
623 oneByte1 += (1 << (func - 1));
637 twoByte1 += (1 << (func - 5));
650 threeByte1 += (1 << (func - 9));
663 fourByte2 += (1 << (func - 13));
676 fiveByte2 += (1 << (func - 21));
681 inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
683 inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
685 inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
687 inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
689 inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
691 #ifdef DCCPP_DEBUG_MODE 692 Serial.print(F(
"DCCpp SetFunctions for loco"));
693 Serial.print(inLocoId);
694 Serial.print(
" / Activated : ");
695 inStates.printActivated();
699 void DCCpp::writeCv(
volatile RegisterList *inReg,
int inLocoId,
int inCv, byte inValue)
701 inReg->writeCVByte(inCv, inValue, 100, 101);
703 #ifdef DCCPP_DEBUG_MODE 704 Serial.print(F(
"DCCpp WriteCv "));
706 Serial.print(F(
" : "));
707 Serial.println(inValue);
711 int DCCpp::readCv(
volatile RegisterList *inReg,
int inLocoId, byte inCv)
713 return inReg->readCVmain(1, 100+inCv, 100+inCv);
718 mainRegs.setAccessory(inAddress, inSubAddress, inActivate);
720 #ifdef DCCPP_DEBUG_MODE 721 Serial.print(F(
"DCCpp AccessoryOperation "));
722 Serial.print(inAddress);
723 Serial.print(F(
" / "));
724 Serial.print(inSubAddress);
725 Serial.print(F(
" : "));
726 Serial.println(inActivate);
static boolean checkTime()
void activate(byte inFunctionNumber)
static void panicStop(bool inStop)
static void setAccessory(int inAddress, byte inSubAddress, byte inActivate)
void inactivate(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 beginEthernet(uint8_t *inMac, uint8_t *inIp, EthernetProtocol inProtocol = EthernetProtocol::TCP)
static void beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
static bool needsRefreshing()