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;
21 byte DCCpp::ackThreshold;
33 this->activeFlags[0] = 0;
34 this->activeFlags[1] = 0;
35 this->activeFlags[2] = 0;
36 this->activeFlags[3] = 0;
43 bitSet(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
48 bitClear(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
53 return bitRead(this->activeFlags[inFunctionNumber / 8], inFunctionNumber % 8);
58 return bitRead(this->activeFlagsSent[inFunctionNumber / 8], inFunctionNumber % 8) !=
isActivated(inFunctionNumber);
63 for (
int i = 0; i < 4; i++)
64 this->activeFlagsSent[i] = this->activeFlags[i];
67 #ifdef DCCPP_DEBUG_MODE 70 for (
int i = 0; i < 32; i++)
87 static bool first =
true;
95 #ifdef USE_TEXTCOMMAND 96 TextCommand::process();
102 #if defined(DCCPP_DEBUG_MODE) && defined(DCCPP_PRINT_DCCPP) 107 if (CurrentMonitor::checkTime())
118 void DCCpp::beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
120 DCCppConfig::DirectionMotorA = inOptionalDirectionMotor;
121 DCCppConfig::SignalEnablePinMain = inSignalEnable;
122 DCCppConfig::CurrentMonitorMain = inCurrentMonitor;
125 if (inSignalPin == UNDEFINED_PIN)
127 #ifdef DCCPP_DEBUG_MODE 128 Serial.println(
"No main track");
133 mainMonitor.begin(DCCppConfig::CurrentMonitorMain, DCCppConfig::SignalEnablePinMain, (
char *)
"<p2>");
142 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER1 3199 143 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER1 1599 145 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER1 1855 146 #define DCC_ONE_BIT_PULSE_DURATION_TIMER1 927 147 if (DCCppConfig::DirectionMotorA != UNDEFINED_PIN)
149 pinMode(DCCppConfig::DirectionMotorA, INPUT);
150 digitalWrite(DCCppConfig::DirectionMotorA, LOW);
153 if (inSignalPin != UNDEFINED_PIN)
154 pinMode(inSignalPin, OUTPUT);
156 bitSet(TCCR1A, WGM10);
157 bitSet(TCCR1A, WGM11);
158 bitSet(TCCR1B, WGM12);
159 bitSet(TCCR1B, WGM13);
161 bitSet(TCCR1A, COM1B1);
162 bitSet(TCCR1A, COM1B0);
164 bitClear(TCCR1B, CS12);
165 bitClear(TCCR1B, CS11);
166 bitSet(TCCR1B, CS10);
168 OCR1A = DCC_ONE_BIT_TOTAL_DURATION_TIMER1;
169 OCR1B = DCC_ONE_BIT_PULSE_DURATION_TIMER1;
171 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
172 pinMode(DCCppConfig::SignalEnablePinMain, OUTPUT);
174 mainRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
176 bitSet(TIMSK1, OCIE1B);
177 if (DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
178 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
180 #ifdef DCCPP_DEBUG_MODE 181 Serial.println(F(
"beginMain achivied"));
185 void DCCpp::beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnable, uint8_t inCurrentMonitor)
187 DCCppConfig::DirectionMotorB = inOptionalDirectionMotor;
188 DCCppConfig::SignalEnablePinProg = inSignalEnable;
189 DCCppConfig::CurrentMonitorProg = inCurrentMonitor;
192 if (inSignalPin == UNDEFINED_PIN)
194 #ifdef DCCPP_DEBUG_MODE 195 Serial.println(
"No prog track");
200 progMonitor.begin(DCCppConfig::CurrentMonitorProg, DCCppConfig::SignalEnablePinProg, (
char *)
"<p3>");
204 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 211 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER0 49 212 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER0 24 214 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER0 28 215 #define DCC_ONE_BIT_PULSE_DURATION_TIMER0 14 217 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
219 pinMode(DCCppConfig::DirectionMotorB, INPUT);
220 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
223 if (inSignalPin != UNDEFINED_PIN)
224 pinMode(inSignalPin, OUTPUT);
226 bitSet(TCCR0A, WGM00);
227 bitSet(TCCR0A, WGM01);
228 bitSet(TCCR0B, WGM02);
230 bitSet(TCCR0A, COM0B1);
231 bitSet(TCCR0A, COM0B0);
233 bitClear(TCCR0B, CS02);
234 bitSet(TCCR0B, CS01);
235 bitSet(TCCR0B, CS00);
237 OCR0A = DCC_ONE_BIT_TOTAL_DURATION_TIMER0;
238 OCR0B = DCC_ONE_BIT_PULSE_DURATION_TIMER0;
240 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
241 pinMode(DCCppConfig::SignalEnablePinProg, OUTPUT);
243 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
245 bitSet(TIMSK0, OCIE0B);
247 #else // Configuration for MEGA 254 #define DCC_ZERO_BIT_TOTAL_DURATION_TIMER3 3199 255 #define DCC_ZERO_BIT_PULSE_DURATION_TIMER3 1599 257 #define DCC_ONE_BIT_TOTAL_DURATION_TIMER3 1855 258 #define DCC_ONE_BIT_PULSE_DURATION_TIMER3 927 260 if (DCCppConfig::DirectionMotorB != UNDEFINED_PIN)
262 pinMode(DCCppConfig::DirectionMotorB, INPUT);
263 digitalWrite(DCCppConfig::DirectionMotorB, LOW);
266 pinMode(DCC_SIGNAL_PIN_PROG, OUTPUT);
268 bitSet(TCCR3A, WGM30);
269 bitSet(TCCR3A, WGM31);
270 bitSet(TCCR3B, WGM32);
271 bitSet(TCCR3B, WGM33);
273 bitSet(TCCR3A, COM3B1);
274 bitSet(TCCR3A, COM3B0);
276 bitClear(TCCR3B, CS32);
277 bitClear(TCCR3B, CS31);
278 bitSet(TCCR3B, CS30);
280 OCR3A = DCC_ONE_BIT_TOTAL_DURATION_TIMER3;
281 OCR3B = DCC_ONE_BIT_PULSE_DURATION_TIMER3;
283 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
284 pinMode(DCCppConfig::SignalEnablePinProg, OUTPUT);
286 progRegs.loadPacket(1, RegisterList::idlePacket, 2, 0);
288 bitSet(TIMSK3, OCIE3B);
291 if (DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
292 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
294 #ifdef DCCPP_DEBUG_MODE 295 Serial.println(F(
"beginProg achivied"));
301 DCCpp::programMode =
false;
302 DCCpp::panicStopped =
false;
303 DCCpp::ackThreshold = 30;
305 DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
306 DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
308 DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
309 DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
311 DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
312 DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
314 mainMonitor.begin(UNDEFINED_PIN, UNDEFINED_PIN,
"");
315 progMonitor.begin(UNDEFINED_PIN, UNDEFINED_PIN,
"");
318 pinMode(SDCARD_CS, OUTPUT);
319 digitalWrite(SDCARD_CS, HIGH);
324 if (EEStore::needsRefreshing())
328 #ifdef DCCPP_DEBUG_MODE 330 Serial.println(F(
"begin achieved"));
336 void DCCpp::beginEthernet(uint8_t *inMac, uint8_t *inIp, EthernetProtocol inProtocol)
339 for (
int i = 0; i < 4; i++)
340 DCCppConfig::EthernetIp[i] = inIp[i];
342 for (
int i = 0; i < 6; i++)
343 DCCppConfig::EthernetMac[i] = inMac[i];
345 DCCppConfig::Protocol = inProtocol;
348 Ethernet.begin(inMac);
350 Ethernet.begin(inMac, inIp);
352 DCCPP_INTERFACE.begin();
353 #ifdef DCCPP_DEBUG_MODE 356 Serial.println(F(
"beginEthernet achieved"));
393 #define DCC_SIGNAL(R,N) 394 if(R.currentBit==R.currentReg->activePacket->nBits){ 396 if (R.nRepeat>0 && R.currentReg == R.reg) { 399 else if (R.nextReg != NULL) { 400 R.currentReg = R.nextReg; 402 R.tempPacket = R.currentReg->activePacket; 403 R.currentReg->activePacket = R.currentReg->updatePacket; 404 R.currentReg->updatePacket = R.tempPacket; 407 if (R.currentReg == R.maxLoadedReg) 408 R.currentReg = R.reg; 413 if (R.currentReg->activePacket->buf[R.currentBit / 8] & R.bitMask[R.currentBit % 8]) { 414 OCR ## N ## A = DCC_ONE_BIT_TOTAL_DURATION_TIMER ## N; 415 OCR ## N ## B=DCC_ONE_BIT_PULSE_DURATION_TIMER ## N; 417 OCR ## N ## A=DCC_ZERO_BIT_TOTAL_DURATION_TIMER ## N; 418 OCR ## N ## B=DCC_ZERO_BIT_PULSE_DURATION_TIMER ## N; 426 ISR(TIMER1_COMPB_vect) {
427 DCC_SIGNAL(DCCpp::mainRegs, 1)
430 #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO 432 ISR(TIMER0_COMPB_vect) {
433 DCC_SIGNAL(DCCpp::progRegs, 0)
436 #else // Configuration for MEGA 438 ISR(TIMER3_COMPB_vect) {
439 DCC_SIGNAL(DCCpp::progRegs, 3)
444 #ifdef DCCPP_PRINT_DCCPP 449 void DCCpp::showConfiguration()
451 Serial.println(F(
"*** DCCpp LIBRARY ***"));
453 Serial.print(F(
"VERSION DCC++: "));
454 Serial.println(VERSION);
455 Serial.println(F(DCCPP_LIBRARY_VERSION));
456 Serial.print(F(
"COMPILED: "));
457 Serial.print(__DATE__);
458 Serial.print(F(
" "));
459 Serial.println(__TIME__);
467 if (DCCppConfig::SignalEnablePinMain!= UNDEFINED_PIN)
469 Serial.print(F(
"nnDCC SIG MAIN(DIR): "));
470 Serial.println(DCC_SIGNAL_PIN_MAIN);
471 Serial.print(F(
" DIRECTION: "));
472 Serial.println(DCCppConfig::DirectionMotorA);
473 Serial.print(F(
" ENABLE(PWM): "));
474 Serial.println(DCCppConfig::SignalEnablePinMain);
475 Serial.print(F(
" CURRENT: "));
476 Serial.println(DCCppConfig::CurrentMonitorMain);
479 if (DCCppConfig::SignalEnablePinProg!= UNDEFINED_PIN)
481 Serial.print(F(
"nnDCC SIG PROG(DIR): "));
482 Serial.println(DCC_SIGNAL_PIN_PROG);
483 Serial.print(F(
" DIRECTION: "));
484 Serial.println(DCCppConfig::DirectionMotorB);
485 Serial.print(F(
" ENABLE(PWM): "));
486 Serial.println(DCCppConfig::SignalEnablePinProg);
487 Serial.print(F(
" CURRENT: "));
488 Serial.println(DCCppConfig::CurrentMonitorProg);
490 #if defined(USE_EEPROM) 491 #if defined(USE_TURNOUT) 492 Serial.print(F(
"nnNUM TURNOUTS: "));
493 Serial.println(EEStore::data.nTurnouts);
495 #if defined(USE_SENSOR) 496 Serial.print(F(
" SENSORS: "));
497 Serial.println(EEStore::data.nSensors);
499 #if defined(USE_OUTPUT) 500 Serial.print(F(
" OUTPUTS: "));
501 Serial.println(EEStore::data.nOutputs);
505 #ifdef USE_TEXTCOMMAND 506 Serial.print(F(
"nnINTERFACE: "));
508 Serial.println(F(
"ETHERNET "));
509 Serial.print(F(
"MAC ADDRESS: "));
510 for (
int i = 0; i<5; i++) {
511 Serial.print(DCCppConfig::EthernetMac[i], HEX);
512 Serial.print(F(
":"));
514 Serial.println(DCCppConfig::EthernetMac[5], HEX);
517 Serial.print(F(
"IP ADDRESS: "));
518 Serial.println(Ethernet.localIP());
527 Serial.println(F(
"SERIAL"));
540 panicStopped = inStop;
542 #ifdef DCCPP_DEBUG_MODE 543 Serial.print(F(
"DCCpp PanicStop "));
544 Serial.println(inStop ? F(
"pressed"):F(
"canceled"));
557 if (inProg && DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
558 digitalWrite(DCCppConfig::SignalEnablePinProg, HIGH);
560 if (inMain && DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
561 digitalWrite(DCCppConfig::SignalEnablePinMain, HIGH);
562 DCCPP_INTERFACE.print(
"<p1>");
563 #if !defined(USE_ETHERNET) 564 DCCPP_INTERFACE.println(
"");
570 if (inProg && DCCppConfig::SignalEnablePinProg != UNDEFINED_PIN)
571 digitalWrite(DCCppConfig::SignalEnablePinProg, LOW);
572 if (inMain && DCCppConfig::SignalEnablePinMain != UNDEFINED_PIN)
573 digitalWrite(DCCppConfig::SignalEnablePinMain, LOW);
574 DCCPP_INTERFACE.print(
"<p0>");
575 #if !defined(USE_ETHERNET) 576 DCCPP_INTERFACE.println(
"");
582 byte old = DCCpp::ackThreshold;
583 DCCpp::ackThreshold = inNewValue;
589 bool DCCpp::setThrottle(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
int inStepsNumber,
int inNewSpeed,
bool inForward)
597 val = map(inNewSpeed, 0, inStepsNumber, 2, 127);
599 #ifdef DCCPP_DEBUG_MODE 600 Serial.print(F(
"DCCpp SetSpeed "));
601 Serial.print(inForward?inNewSpeed:-inNewSpeed);
602 Serial.print(F(
"/"));
603 Serial.print(inStepsNumber);
604 Serial.print(F(
" (in Dcc "));
606 Serial.println(F(
" )"));
609 inpRegs->setThrottle(nReg, inLocoId, val, inForward);
614 void DCCpp::setFunctions(
volatile RegisterList *inpRegs,
int nReg,
int inLocoId,
FunctionsState &inStates)
616 #ifdef DCCPP_DEBUG_MODE 617 if (inpRegs == &mainRegs)
619 if (nReg > MAX_MAIN_REGISTERS)
620 Serial.println(F(
"Invalid register number on main track."));
624 if (nReg > MAX_PROG_REGISTERS)
625 Serial.println(F(
"Invalid register number on programming track."));
632 byte threeByte1 = 160;
636 for (byte func = 0; func <= 28; func++)
654 oneByte1 += (1 << (func - 1));
669 twoByte1 += (1 << (func - 5));
683 threeByte1 += (1 << (func - 9));
697 fourByte2 += (1 << (func - 13));
711 fiveByte2 += (1 << (func - 21));
716 inpRegs->setFunction(nReg, inLocoId, oneByte1, -1);
718 inpRegs->setFunction(nReg, inLocoId, twoByte1, -1);
720 inpRegs->setFunction(nReg, inLocoId, threeByte1, -1);
722 inpRegs->setFunction(nReg, inLocoId, 222, fourByte2);
724 inpRegs->setFunction(nReg, inLocoId, 223, fiveByte2);
728 #ifdef DCCPP_DEBUG_MODE 729 Serial.print(F(
"DCCpp SetFunctions for loco"));
730 Serial.print(inLocoId);
731 Serial.print(
" / Activated : ");
736 int DCCpp::identifyLocoId(
volatile RegisterList *inReg)
740 temp = inReg->readCV(29, 100, 200);
741 if ((temp != -1) && (bitRead(temp, 5))) {
743 id = inReg->readCV(18, 100, 200);
745 temp = inReg->readCV(17, 100, 200);
747 id =
id + ((temp - 192) << 8);
753 id = inReg->readCV(1, 100, 200);
758 void DCCpp::writeCv(
volatile RegisterList *inReg,
int inCv, byte inValue,
int callBack,
int callBackSub)
760 inReg->writeCVByte(inCv, inValue, callBack, callBackSub);
762 #ifdef DCCPP_DEBUG_MODE 763 Serial.print(F(
"DCCpp WriteCv "));
765 Serial.print(F(
" : "));
766 Serial.println(inValue);
772 mainRegs.setAccessory(inAddress, inSubAddress, inActivate);
774 #ifdef DCCPP_DEBUG_MODE 775 Serial.print(F(
"DCCpp AccessoryOperation "));
776 Serial.print(inAddress);
777 Serial.print(F(
" / "));
778 Serial.print(inSubAddress);
779 Serial.print(F(
" : "));
780 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 byte setAckThreshold(byte inNewValue)
static void panicStop(bool inStop)
static void beginProg(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
bool isActivated(byte inFunctionNumber)
bool isActivationChanged(byte inFunctionNumber)
void inactivate(byte inFunctionNumber)
static void beginMain(uint8_t inOptionalDirectionMotor, uint8_t inSignalPin, uint8_t inSignalEnablePin, uint8_t inCurrentMonitor)
void activate(byte inFunctionNumber)