12 static byte ackThreshold = 30;
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 129 printPacket(nReg,b,nBytes,nRepeat);
136 void RegisterList::setThrottle(
int nReg,
int cab,
int tSpeed,
int tDirection)
volatile 142 b[nB++] = highByte(cab) | 0xC0;
144 b[nB++] = lowByte(cab);
147 b[nB++] = tSpeed + (tSpeed>0) + tDirection * 128;
153 loadPacket(nReg, b, nB, 0, 1);
155 #if defined(USE_TEXTCOMMAND) 156 DCCPP_INTERFACE.print(
"<T");
157 DCCPP_INTERFACE.print(nReg); DCCPP_INTERFACE.print(
" ");
158 DCCPP_INTERFACE.print(cab); DCCPP_INTERFACE.print(
" ");
159 DCCPP_INTERFACE.print(tSpeed); DCCPP_INTERFACE.print(
" ");
160 DCCPP_INTERFACE.print(tDirection);
161 DCCPP_INTERFACE.print(
">");
162 #if !defined(USE_ETHERNET) 163 DCCPP_INTERFACE.println(
"");
166 speedTable[nReg] = tDirection == 1 ? tSpeed : -tSpeed;
170 #ifdef USE_TEXTCOMMAND 171 void RegisterList::setThrottle(
char *s)
volatile 178 if (sscanf(s,
"%d %d %d %d", &nReg, &cab, &tSpeed, &tDirection) != 4)
180 #ifdef DCCPP_DEBUG_MODE 181 Serial.println(F(
"t Syntax error"));
186 this->setThrottle(nReg, cab, tSpeed, tDirection);
192 void RegisterList::setFunction(
int nReg,
int cab,
int fByte,
int eByte)
volatile 198 b[nB++] = highByte(cab) | 0xC0;
200 b[nB++] = lowByte(cab);
203 b[nB++] = (fByte | 0x80) & 0xBF;
206 b[nB++] = (fByte | 0xDE) & 0xDF;
210 #if defined(USE_TEXTCOMMAND) 211 DCCPP_INTERFACE.print(
"<F");
212 DCCPP_INTERFACE.print(nReg); DCCPP_INTERFACE.print(
" ");
213 DCCPP_INTERFACE.print(cab); DCCPP_INTERFACE.print(
" ");
214 DCCPP_INTERFACE.print(fByte); DCCPP_INTERFACE.print(
" ");
215 DCCPP_INTERFACE.print(eByte);
216 DCCPP_INTERFACE.print(
">");
217 #if !defined(USE_ETHERNET) 218 DCCPP_INTERFACE.println(
"");
226 loadPacket(nReg, b, nB, 4, 1);
229 #ifdef USE_TEXTCOMMAND 230 void RegisterList::setFunction(
char *s)
volatile 237 switch (sscanf(s,
"%d %d %d %d %d", &a, &b, &c, &d, &e))
266 #ifdef DCCPP_DEBUG_MODE 267 Serial.println(F(
"f Syntax error"));
272 this->setFunction(reg, cab, fByte, eByte);
279 void RegisterList::setAccessory(
int aAdd,
int aNum,
int activate)
volatile 283 b[0] = aAdd % 64 + 128;
284 b[1] = ((((aAdd / 64) % 8) << 4) + (aNum % 4 << 1) + activate % 2) ^ 0xF8;
286 loadPacket(0, b, 2, 4, 1);
290 #ifdef USE_TEXTCOMMAND 291 void RegisterList::setAccessory(
char *s)
volatile 297 if (sscanf(s,
"%d %d %d", &aAdd, &aNum, &activate) != 3)
299 #ifdef DCCPP_DEBUG_MODE 300 Serial.println(F(
"a Syntax error"));
305 this->setAccessory(aAdd, aNum, activate);
312 void RegisterList::writeTextPacket(
int nReg, byte *b,
int nBytes)
volatile 315 if (nBytes<2 || nBytes>5) {
316 DCCPP_INTERFACE.print(
"<mInvalid Packet>");
317 #if !defined(USE_ETHERNET) 318 DCCPP_INTERFACE.println(
"");
323 loadPacket(nReg, b, nBytes, 0, 1);
327 #ifdef USE_TEXTCOMMAND 328 void RegisterList::writeTextPacket(
char *s)
volatile 334 nBytes = sscanf(s,
"%d %hhx %hhx %hhx %hhx %hhx", &nReg, b, b + 1, b + 2, b + 3, b + 4) - 1;
336 this->writeTextPacket(nReg, b, nBytes);
343 int RegisterList::buildBaseAcknowlegde(
int inMonitorPin)
volatile 346 for (
int j = 0; j < ACK_BASE_COUNT; j++)
348 int val = (int)analogRead(inMonitorPin);
352 return base / ACK_BASE_COUNT;
355 int RegisterList::checkAcknowlegde(
int inMonitorPin,
int inBase)
volatile 358 #ifdef DCCPP_DEBUG_MODE 362 for (
int j = 0; j < ACK_SAMPLE_COUNT; j++)
364 int val = (int)analogRead(inMonitorPin);
365 c = (int)((val - inBase) * ACK_SAMPLE_SMOOTHING + c * (1.0 - ACK_SAMPLE_SMOOTHING));
366 #ifdef DCCPP_DEBUG_MODE 370 if (c > ACK_SAMPLE_THRESHOLD)
374 #ifdef DCCPP_DEBUG_MODE 375 if (max > ACK_SAMPLE_THRESHOLD / 2)
378 Serial.print(F(
"Max acknowledge value : "));
385 int RegisterList::readCVraw(
int cv,
int callBack,
int callBackSub)
volatile 393 byte MonitorPin = DCCppConfig::CurrentMonitorProg;
395 MonitorPin = DCCppConfig::CurrentMonitorMain;
398 if (MonitorPin == UNDEFINED_PIN)
401 #ifdef DCCPP_DEBUG_MODE 402 Serial.print(F(
"readCVraw : start reading cv "));
406 bRead[0] = 0x78 + (highByte(cv) & 0x03);
407 bRead[1] = lowByte(cv);
411 for (
int i = 0; i<8; i++) {
413 base = RegisterList::buildBaseAcknowlegde(MonitorPin);
417 loadPacket(0, resetPacket, 2, 3);
418 loadPacket(0, bRead, 3, 5);
419 loadPacket(0, resetPacket, 2, 1);
421 ret = RegisterList::checkAcknowlegde(MonitorPin, base);
423 bitWrite(bValue, i, ret);
426 base = RegisterList::buildBaseAcknowlegde(MonitorPin);
428 bRead[0] = 0x74 + (highByte(cv) & 0x03);
431 loadPacket(0, resetPacket, 2, 3);
432 loadPacket(0, bRead, 3, 5);
433 loadPacket(0, resetPacket, 2, 1);
435 ret = RegisterList::checkAcknowlegde(MonitorPin, base);
440 #if defined(USE_TEXTCOMMAND) 441 DCCPP_INTERFACE.print(
"<r");
442 DCCPP_INTERFACE.print(callBack);
443 DCCPP_INTERFACE.print(
"|");
444 DCCPP_INTERFACE.print(callBackSub);
445 DCCPP_INTERFACE.print(
"|");
446 DCCPP_INTERFACE.print(cv + 1);
447 DCCPP_INTERFACE.print(
" ");
448 DCCPP_INTERFACE.print(bValue);
449 DCCPP_INTERFACE.print(
">");
450 #if !defined(USE_ETHERNET) 451 DCCPP_INTERFACE.println(
"");
455 #ifdef DCCPP_DEBUG_MODE 456 Serial.println(F(
"end reading"));
461 int RegisterList::readCV(
int cv,
int callBack,
int callBackSub)
volatile 463 return RegisterList::readCVraw(cv, callBack, callBackSub);
466 #ifdef USE_TEXTCOMMAND 467 int RegisterList::readCV(
char *s)
volatile 469 int cv, callBack, callBackSub;
471 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
473 #ifdef DCCPP_DEBUG_MODE 474 Serial.println(F(
"R Syntax error"));
479 return this->readCV(cv, callBack, callBackSub);
483 int RegisterList::readCVmain(
int cv,
int callBack,
int callBackSub)
volatile 485 return RegisterList::readCVraw(cv, callBack, callBackSub);
489 #ifdef USE_TEXTCOMMAND 490 int RegisterList::readCVmain(
char *s)
volatile 492 int cv, callBack, callBackSub;
494 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
496 #ifdef DCCPP_DEBUG_MODE 497 Serial.println(F(
"r Syntax error"));
502 return this->readCVmain(cv, callBack, callBackSub);
508 void RegisterList::writeCVByte(
int cv,
int bValue,
int callBack,
int callBackSub)
volatile 515 bWrite[0] = 0x7C + (highByte(cv) & 0x03);
516 bWrite[1] = lowByte(cv);
519 loadPacket(0, resetPacket, 2, 1);
520 loadPacket(0, bWrite, 3, 4);
521 loadPacket(0, resetPacket, 2, 1);
522 loadPacket(0, idlePacket, 2, 10);
525 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
527 base = RegisterList::buildBaseAcknowlegde(DCCppConfig::CurrentMonitorProg);
529 bWrite[0] = 0x74 + (highByte(cv) & 0x03);
531 loadPacket(0, resetPacket, 2, 3);
532 loadPacket(0, bWrite, 3, 5);
533 loadPacket(0, resetPacket, 2, 1);
535 ret = RegisterList::checkAcknowlegde(DCCppConfig::CurrentMonitorProg, base);
541 #if defined(USE_TEXTCOMMAND) 542 DCCPP_INTERFACE.print(
"<r");
543 DCCPP_INTERFACE.print(callBack);
544 DCCPP_INTERFACE.print(
"|");
545 DCCPP_INTERFACE.print(callBackSub);
546 DCCPP_INTERFACE.print(
"|");
547 DCCPP_INTERFACE.print(cv + 1);
548 DCCPP_INTERFACE.print(
" ");
549 DCCPP_INTERFACE.print(bValue);
550 DCCPP_INTERFACE.print(
">");
551 #if !defined(USE_ETHERNET) 552 DCCPP_INTERFACE.println(
"");
557 #ifdef USE_TEXTCOMMAND 558 void RegisterList::writeCVByte(
char *s)
volatile 560 int bValue, cv, callBack, callBackSub;
562 if (sscanf(s,
"%d %d %d %d", &cv, &bValue, &callBack, &callBackSub) != 4)
564 #ifdef DCCPP_DEBUG_MODE 565 Serial.println(F(
"W Syntax error"));
570 this->writeCVByte(cv, bValue, callBack, callBackSub);
576 void RegisterList::writeCVBit(
int cv,
int bNum,
int bValue,
int callBack,
int callBackSub)
volatile 585 bWrite[0] = 0x78 + (highByte(cv) & 0x03);
586 bWrite[1] = lowByte(cv);
587 bWrite[2] = 0xF0 + bValue * 8 + bNum;
589 loadPacket(0, resetPacket, 2, 1);
590 loadPacket(0, bWrite, 3, 4);
591 loadPacket(0, resetPacket, 2, 1);
592 loadPacket(0, idlePacket, 2, 10);
595 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
597 base = RegisterList::buildBaseAcknowlegde(DCCppConfig::CurrentMonitorProg);
599 bitClear(bWrite[2], 4);
601 loadPacket(0, resetPacket, 2, 3);
602 loadPacket(0, bWrite, 3, 5);
603 loadPacket(0, resetPacket, 2, 1);
605 ret = RegisterList::checkAcknowlegde(DCCppConfig::CurrentMonitorProg, base);
611 #if defined(USE_TEXTCOMMAND) 612 DCCPP_INTERFACE.print(
"<r");
613 DCCPP_INTERFACE.print(callBack);
614 DCCPP_INTERFACE.print(
"|");
615 DCCPP_INTERFACE.print(callBackSub);
616 DCCPP_INTERFACE.print(
"|");
617 DCCPP_INTERFACE.print(cv + 1);
618 DCCPP_INTERFACE.print(
" ");
619 DCCPP_INTERFACE.print(bNum);
620 DCCPP_INTERFACE.print(
" ");
621 DCCPP_INTERFACE.print(bValue);
622 DCCPP_INTERFACE.print(
">");
623 #if !defined(USE_ETHERNET) 624 DCCPP_INTERFACE.println(
"");
629 #ifdef USE_TEXTCOMMAND 630 void RegisterList::writeCVBit(
char *s)
volatile 632 int bNum, bValue, cv, callBack, callBackSub;
634 if(sscanf(s,
"%d %d %d %d %d",&cv,&bNum,&bValue,&callBack,&callBackSub) != 5)
636 #ifdef DCCPP_DEBUG_MODE 637 Serial.println(F(
"W Syntax error"));
642 this->writeCVBit(cv, bNum, bValue, callBack, callBackSub);
648 void RegisterList::writeCVByteMain(
int cab,
int cv,
int bValue)
volatile 656 b[nB++] = highByte(cab) | 0xC0;
658 b[nB++] = lowByte(cab);
659 b[nB++] = 0xEC + (highByte(cv) & 0x03);
660 b[nB++] = lowByte(cv);
663 loadPacket(0, b, nB, 4);
667 #ifdef USE_TEXTCOMMAND 668 void RegisterList::writeCVByteMain(
char *s)
volatile 674 if (sscanf(s,
"%d %d %d", &cab, &cv, &bValue) != 3)
676 #ifdef DCCPP_DEBUG_MODE 677 Serial.println(F(
"w Syntax error"));
682 this->writeCVByteMain(cab, cv, bValue);
688 void RegisterList::writeCVBitMain(
int cab,
int cv,
int bNum,
int bValue)
volatile 699 b[nB++] = highByte(cab) | 0xC0;
701 b[nB++] = lowByte(cab);
702 b[nB++] = 0xE8 + (highByte(cv) & 0x03);
703 b[nB++] = lowByte(cv);
704 b[nB++] = 0xF0 + bValue * 8 + bNum;
706 loadPacket(0, b, nB, 4);
710 #ifdef USE_TEXTCOMMAND 711 void RegisterList::writeCVBitMain(
char *s)
volatile 718 if (sscanf(s,
"%d %d %d %d", &cab, &cv, &bNum, &bValue) != 4)
720 #ifdef DCCPP_DEBUG_MODE 721 Serial.println(F(
"w Syntax error"));
726 this->writeCVBitMain(cab, cv, bNum, bValue);
732 #ifdef DCCPP_DEBUG_MODE 733 void RegisterList::printPacket(
int nReg, byte *b,
int nBytes,
int nRepeat)
volatile 735 DCCPP_INTERFACE.print(
"<*");
736 DCCPP_INTERFACE.print(nReg);
737 DCCPP_INTERFACE.print(
":");
738 for(
int i=0;i<nBytes;i++){
739 DCCPP_INTERFACE.print(
" ");
740 DCCPP_INTERFACE.print(b[i],HEX);
742 DCCPP_INTERFACE.print(
" / ");
743 DCCPP_INTERFACE.print(nRepeat);
744 DCCPP_INTERFACE.print(
">");
745 #if !defined(USE_ETHERNET) 746 DCCPP_INTERFACE.println(
"");
753 byte RegisterList::idlePacket[3]={0xFF,0x00,0};
754 byte RegisterList::resetPacket[3]={0x00,0x00,0};
756 byte RegisterList::bitMask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
static bool IsMainTrack(volatile RegisterList *apRegs)