20 uint8_t DCCppConfig::EthernetIp[4];
21 uint8_t DCCppConfig::EthernetMac[6];
22 int DCCppConfig::EthernetPort = 0;
24 EthernetProtocol DCCppConfig::Protocol = EthernetProtocol::TCP;
27 byte DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
28 byte DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
30 byte DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
31 byte DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
33 #ifndef USE_ONLY1_INTERRUPT 34 byte DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
35 byte DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
37 uint8_t DCCppConfig::SignalPortMaskMain = 0;
38 uint8_t DCCppConfig::SignalPortMaskProg = 0;
40 volatile uint8_t *DCCppConfig::SignalPortInMain = 0;
41 volatile uint8_t *DCCppConfig::SignalPortInProg = 0;
46 void Register::initPackets(){
53 RegisterList::RegisterList(
int maxNumRegs){
54 this->maxNumRegs=maxNumRegs;
56 for(
int i=0;i<=maxNumRegs;i++)
59 speedTable=(
int *)calloc((maxNumRegs+1),
sizeof(
int *));
74 void RegisterList::loadPacket(
int nReg, byte *b,
int nBytes,
int nRepeat,
int printFlag)
volatile 79 nReg=nReg%((maxNumRegs+1));
83 if(regMap[nReg]==NULL)
84 regMap[nReg]=maxLoadedReg+1;
91 for(
int i=1;i<nBytes;i++)
97 buf[2]=0xFC + bitRead(b[0],7);
124 this->nRepeat=nRepeat;
125 maxLoadedReg=max(maxLoadedReg,nextReg);
127 #ifdef DCCPP_DEBUG_MODE 128 #ifdef DCCPP_DEBUG_VERBOSE_MODE 130 printPacket(nReg,b,nBytes,nRepeat);
138 void RegisterList::setThrottle(
int nReg,
int cab,
int tSpeed,
int tDirection)
volatile 144 b[nB++] = highByte(cab) | 0xC0;
146 b[nB++] = lowByte(cab);
149 b[nB++] = tSpeed + (tSpeed>0) + tDirection * 128;
155 loadPacket(nReg, b, nB, 0, 1);
157 #if defined(USE_TEXTCOMMAND) 158 DCCPP_INTERFACE.print(
"<T");
159 DCCPP_INTERFACE.print(nReg); DCCPP_INTERFACE.print(
" ");
160 DCCPP_INTERFACE.print(cab); DCCPP_INTERFACE.print(
" ");
161 DCCPP_INTERFACE.print(tSpeed); DCCPP_INTERFACE.print(
" ");
162 DCCPP_INTERFACE.print(tDirection);
163 DCCPP_INTERFACE.print(
">");
164 #if !defined(USE_ETHERNET) 165 DCCPP_INTERFACE.println(
"");
168 speedTable[nReg] = tDirection == 1 ? tSpeed : -tSpeed;
172 #ifdef USE_TEXTCOMMAND 173 void RegisterList::setThrottle(
const char *s)
volatile 180 if (sscanf(s,
"%d %d %d %d", &nReg, &cab, &tSpeed, &tDirection) != 4)
182 #ifdef DCCPP_DEBUG_MODE 183 Serial.println(F(
"t Syntax error"));
188 this->setThrottle(nReg, cab, tSpeed, tDirection);
194 void RegisterList::setFunction(
int nReg,
int cab,
int fByte,
int eByte)
volatile 200 b[nB++] = highByte(cab) | 0xC0;
202 b[nB++] = lowByte(cab);
205 b[nB++] = (fByte | 0x80) & 0xBF;
208 b[nB++] = (fByte | 0xDE) & 0xDF;
212 #if defined(USE_TEXTCOMMAND) 213 DCCPP_INTERFACE.print(
"<F");
214 DCCPP_INTERFACE.print(nReg); DCCPP_INTERFACE.print(
" ");
215 DCCPP_INTERFACE.print(cab); DCCPP_INTERFACE.print(
" ");
216 DCCPP_INTERFACE.print(fByte); DCCPP_INTERFACE.print(
" ");
217 DCCPP_INTERFACE.print(eByte);
218 DCCPP_INTERFACE.print(
">");
219 #if !defined(USE_ETHERNET) 220 DCCPP_INTERFACE.println(
"");
228 loadPacket(nReg, b, nB, 4, 1);
231 #ifdef USE_TEXTCOMMAND 232 void RegisterList::setFunction(
const char *s)
volatile 239 switch (sscanf(s,
"%d %d %d %d %d", &a, &b, &c, &d, &e))
268 #ifdef DCCPP_DEBUG_MODE 269 Serial.println(F(
"f Syntax error"));
274 this->setFunction(reg, cab, fByte, eByte);
281 void RegisterList::setAccessory(
int aAdd,
int aNum,
int activate)
volatile 285 b[0] = aAdd % 64 + 128;
286 b[1] = ((((aAdd / 64) % 8) << 4) + (aNum % 4 << 1) + activate % 2) ^ 0xF8;
288 loadPacket(0, b, 2, 4, 1);
292 #ifdef USE_TEXTCOMMAND 293 void RegisterList::setAccessory(
const char *s)
volatile 299 if (sscanf(s,
"%d %d %d", &aAdd, &aNum, &activate) != 3)
301 #ifdef DCCPP_DEBUG_MODE 302 Serial.println(F(
"a Syntax error"));
307 this->setAccessory(aAdd, aNum, activate);
314 void RegisterList::writeTextPacket(
int nReg, byte *b,
int nBytes)
volatile 317 if (nBytes<2 || nBytes>5) {
318 DCCPP_INTERFACE.print(
"<mInvalid Packet>");
319 #if !defined(USE_ETHERNET) 320 DCCPP_INTERFACE.println(
"");
325 loadPacket(nReg, b, nBytes, 0, 1);
329 #ifdef USE_TEXTCOMMAND 330 void RegisterList::writeTextPacket(
const char *s)
volatile 336 nBytes = sscanf(s,
"%d %hhx %hhx %hhx %hhx %hhx", &nReg, b, b + 1, b + 2, b + 3, b + 4) - 1;
338 this->writeTextPacket(nReg, b, nBytes);
345 int RegisterList::buildBaseAcknowlegde(
int inMonitorPin)
volatile 348 for (
int j = 0; j < ACK_BASE_COUNT; j++)
350 int val = (int)analogRead(inMonitorPin);
354 return base / ACK_BASE_COUNT;
357 bool RegisterList::checkAcknowlegde(
int inMonitorPin,
int inBase)
volatile 362 #if defined(ARDUINO_ARCH_ESP32) 368 #ifdef DCCPP_DEBUG_MODE 371 for (
int a = 0; a < loopMax; a++)
374 for (
int j = 0; j < ACK_SAMPLE_COUNT; j++)
376 int val = (int)analogRead(inMonitorPin);
377 c = (int)((val - inBase) * ACK_SAMPLE_SMOOTHING + c * (1.0 - ACK_SAMPLE_SMOOTHING));
381 #ifdef DCCPP_DEBUG_MODE 388 #ifdef DCCPP_DEBUG_MODE 389 Serial.print(F(
" iter : "));
391 Serial.print(
", max : ");
395 return (max > ACK_SAMPLE_THRESHOLD);
398 int RegisterList::readCVraw(
int cv,
int callBack,
int callBackSub)
volatile 406 byte MonitorPin = DCCppConfig::CurrentMonitorProg;
408 MonitorPin = DCCppConfig::CurrentMonitorMain;
411 if (MonitorPin == UNDEFINED_PIN)
414 #ifdef DCCPP_DEBUG_MODE 415 Serial.print(F(
"readCVraw : start reading cv "));
416 Serial.println(cv+1);
419 bRead[0] = 0x78 + (highByte(cv) & 0x03);
420 bRead[1] = lowByte(cv);
424 for (
int i = 0; i<8; i++) {
426 base = RegisterList::buildBaseAcknowlegde(MonitorPin);
428 #if defined(ARDUINO_ARCH_ESP32) 434 loadPacket(0, resetPacket, 2, 3);
435 loadPacket(0, bRead, 3, 5);
437 loadPacket(0, idlePacket, 2, 6);
439 #if defined(ARDUINO_ARCH_ESP32) 443 ret = RegisterList::checkAcknowlegde(MonitorPin, base);
445 bitWrite(bValue, i, ret);
448 #if defined(ARDUINO_ARCH_ESP32) 452 base = RegisterList::buildBaseAcknowlegde(MonitorPin);
454 #if defined(ARDUINO_ARCH_ESP32) 458 bRead[0] = 0x74 + (highByte(cv) & 0x03);
461 loadPacket(0, resetPacket, 2, 3);
462 loadPacket(0, bRead, 3, 5);
464 loadPacket(0, idlePacket, 2, 6);
466 #if defined(ARDUINO_ARCH_ESP32) 470 ret = RegisterList::checkAcknowlegde(MonitorPin, base);
475 #if defined(USE_TEXTCOMMAND) 476 DCCPP_INTERFACE.print(
"<r");
477 DCCPP_INTERFACE.print(callBack);
478 DCCPP_INTERFACE.print(
"|");
479 DCCPP_INTERFACE.print(callBackSub);
480 DCCPP_INTERFACE.print(
"|");
481 DCCPP_INTERFACE.print(cv + 1);
482 DCCPP_INTERFACE.print(
" ");
483 DCCPP_INTERFACE.print(bValue);
484 DCCPP_INTERFACE.print(
">");
485 #if !defined(USE_ETHERNET) 486 DCCPP_INTERFACE.println(
"");
490 #ifdef DCCPP_DEBUG_MODE 491 Serial.println(F(
"end reading"));
496 int RegisterList::readCV(
int cv,
int callBack,
int callBackSub)
volatile 498 return RegisterList::readCVraw(cv, callBack, callBackSub);
501 #ifdef USE_TEXTCOMMAND 502 int RegisterList::readCV(
const char *s)
volatile 504 int cv, callBack, callBackSub;
506 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
508 #ifdef DCCPP_DEBUG_MODE 509 Serial.println(F(
"R Syntax error"));
514 return this->readCV(cv, callBack, callBackSub);
518 int RegisterList::readCVmain(
int cv,
int callBack,
int callBackSub)
volatile 520 return RegisterList::readCVraw(cv, callBack, callBackSub);
524 #ifdef USE_TEXTCOMMAND 525 int RegisterList::readCVmain(
const char *s)
volatile 527 int cv, callBack, callBackSub;
529 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
531 #ifdef DCCPP_DEBUG_MODE 532 Serial.println(F(
"r Syntax error"));
537 return this->readCVmain(cv, callBack, callBackSub);
543 bool RegisterList::writeCVByte(
int cv,
int bValue,
int callBack,
int callBackSub)
volatile 551 bWrite[0] = 0x7C + (highByte(cv) & 0x03);
552 bWrite[1] = lowByte(cv);
555 loadPacket(0, resetPacket, 2, 3);
556 loadPacket(0, bWrite, 3, 5);
557 loadPacket(0, bWrite, 3, 6);
565 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
567 base = RegisterList::buildBaseAcknowlegde(DCCppConfig::CurrentMonitorProg);
569 bWrite[0] = 0x74 + (highByte(cv) & 0x03);
571 loadPacket(0, resetPacket, 2, 3);
572 loadPacket(0, bWrite, 3, 5);
574 loadPacket(0, bWrite, 3, 6);
576 ret = RegisterList::checkAcknowlegde(DCCppConfig::CurrentMonitorProg, base);
578 loadPacket(0, resetPacket, 2, 1);
584 #if defined(USE_TEXTCOMMAND) 585 DCCPP_INTERFACE.print(
"<r");
586 DCCPP_INTERFACE.print(callBack);
587 DCCPP_INTERFACE.print(
"|");
588 DCCPP_INTERFACE.print(callBackSub);
589 DCCPP_INTERFACE.print(
"|");
590 DCCPP_INTERFACE.print(cv + 1);
591 DCCPP_INTERFACE.print(
" ");
592 DCCPP_INTERFACE.print(bValue);
593 DCCPP_INTERFACE.print(
">");
594 #if !defined(USE_ETHERNET) 595 DCCPP_INTERFACE.println(
"");
601 #ifdef USE_TEXTCOMMAND 602 bool RegisterList::writeCVByte(
const char *s)
volatile 604 int bValue, cv, callBack, callBackSub;
606 if (sscanf(s,
"%d %d %d %d", &cv, &bValue, &callBack, &callBackSub) != 4)
608 #ifdef DCCPP_DEBUG_MODE 609 Serial.println(F(
"W Syntax error"));
614 return this->writeCVByte(cv, bValue, callBack, callBackSub);
620 bool RegisterList::writeCVBit(
int cv,
int bNum,
int bValue,
int callBack,
int callBackSub)
volatile 630 bWrite[0] = 0x78 + (highByte(cv) & 0x03);
631 bWrite[1] = lowByte(cv);
632 bWrite[2] = 0xF0 + bValue * 8 + bNum;
639 loadPacket(0, resetPacket, 2, 3);
640 loadPacket(0, bWrite, 3, 5);
641 loadPacket(0, bWrite, 3, 6);
644 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
646 base = RegisterList::buildBaseAcknowlegde(DCCppConfig::CurrentMonitorProg);
648 bitClear(bWrite[2], 4);
650 loadPacket(0, resetPacket, 2, 3);
651 loadPacket(0, bWrite, 3, 5);
653 loadPacket(0, bWrite, 3, 6);
655 ret = RegisterList::checkAcknowlegde(DCCppConfig::CurrentMonitorProg, base);
657 loadPacket(0, resetPacket, 2, 1);
663 #if defined(USE_TEXTCOMMAND) 664 DCCPP_INTERFACE.print(
"<r");
665 DCCPP_INTERFACE.print(callBack);
666 DCCPP_INTERFACE.print(
"|");
667 DCCPP_INTERFACE.print(callBackSub);
668 DCCPP_INTERFACE.print(
"|");
669 DCCPP_INTERFACE.print(cv + 1);
670 DCCPP_INTERFACE.print(
" ");
671 DCCPP_INTERFACE.print(bNum);
672 DCCPP_INTERFACE.print(
" ");
673 DCCPP_INTERFACE.print(bValue);
674 DCCPP_INTERFACE.print(
">");
675 #if !defined(USE_ETHERNET) 676 DCCPP_INTERFACE.println(
"");
682 #ifdef USE_TEXTCOMMAND 683 bool RegisterList::writeCVBit(
const char *s)
volatile 685 int bNum, bValue, cv, callBack, callBackSub;
687 if(sscanf(s,
"%d %d %d %d %d",&cv,&bNum,&bValue,&callBack,&callBackSub) != 5)
689 #ifdef DCCPP_DEBUG_MODE 690 Serial.println(F(
"W Syntax error"));
695 return this->writeCVBit(cv, bNum, bValue, callBack, callBackSub);
701 void RegisterList::writeCVByteMain(
int cab,
int cv,
int bValue)
volatile 709 b[nB++] = highByte(cab) | 0xC0;
711 b[nB++] = lowByte(cab);
712 b[nB++] = 0xEC + (highByte(cv) & 0x03);
713 b[nB++] = lowByte(cv);
716 loadPacket(0, b, nB, 4);
720 #ifdef USE_TEXTCOMMAND 721 void RegisterList::writeCVByteMain(
const char *s)
volatile 727 if (sscanf(s,
"%d %d %d", &cab, &cv, &bValue) != 3)
729 #ifdef DCCPP_DEBUG_MODE 730 Serial.println(F(
"w Syntax error"));
735 this->writeCVByteMain(cab, cv, bValue);
741 void RegisterList::writeCVBitMain(
int cab,
int cv,
int bNum,
int bValue)
volatile 752 b[nB++] = highByte(cab) | 0xC0;
754 b[nB++] = lowByte(cab);
755 b[nB++] = 0xE8 + (highByte(cv) & 0x03);
756 b[nB++] = lowByte(cv);
757 b[nB++] = 0xF0 + bValue * 8 + bNum;
759 loadPacket(0, b, nB, 4);
763 #ifdef USE_TEXTCOMMAND 764 void RegisterList::writeCVBitMain(
const char *s)
volatile 771 if (sscanf(s,
"%d %d %d %d", &cab, &cv, &bNum, &bValue) != 4)
773 #ifdef DCCPP_DEBUG_MODE 774 Serial.println(F(
"w Syntax error"));
779 this->writeCVBitMain(cab, cv, bNum, bValue);
785 #ifdef DCCPP_DEBUG_MODE 786 void RegisterList::printPacket(
int nReg, byte *b,
int nBytes,
int nRepeat)
volatile 788 DCCPP_INTERFACE.print(
"<*");
789 DCCPP_INTERFACE.print(nReg);
790 DCCPP_INTERFACE.print(
":");
791 for(
int i=0;i<nBytes;i++){
792 DCCPP_INTERFACE.print(
" ");
793 DCCPP_INTERFACE.print(b[i],HEX);
795 DCCPP_INTERFACE.print(
" / ");
796 DCCPP_INTERFACE.print(nRepeat);
797 DCCPP_INTERFACE.print(
">");
798 #if !defined(USE_ETHERNET) 799 DCCPP_INTERFACE.println(
"");
806 byte RegisterList::idlePacket[3]={0xFF,0x00,0};
807 byte RegisterList::resetPacket[3]={0x00,0x00,0};
809 byte RegisterList::bitMask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
static bool IsMainTrack(volatile RegisterList *apRegs)