11 #ifdef ARDUINO_ARCH_AVR 13 static byte ackThreshold = 30;
21 uint8_t DCCppConfig::EthernetIp[4];
22 uint8_t DCCppConfig::EthernetMac[6];
23 int DCCppConfig::EthernetPort = 0;
25 EthernetProtocol DCCppConfig::Protocol = EthernetProtocol::TCP;
28 byte DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
29 byte DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
31 byte DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
32 byte DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
34 byte DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
35 byte DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
39 void Register::initPackets(){
41 updatePacket=packet+1;
46 RegisterList::RegisterList(
int maxNumRegs){
47 this->maxNumRegs=maxNumRegs;
48 reg=(Register *)calloc((maxNumRegs+1),
sizeof(Register));
49 for(
int i=0;i<=maxNumRegs;i++)
51 regMap=(Register **)calloc((maxNumRegs+1),
sizeof(Register *));
52 speedTable=(
int *)calloc((maxNumRegs+1),
sizeof(
int *));
67 void RegisterList::loadPacket(
int nReg, byte *b,
int nBytes,
int nRepeat,
int printFlag)
volatile 72 nReg=nReg%((maxNumRegs+1));
76 if(regMap[nReg]==NULL)
77 regMap[nReg]=maxLoadedReg+1;
79 Register *r=regMap[nReg];
80 Packet *p=r->updatePacket;
84 for(
int i=1;i<nBytes;i++)
90 buf[2]=0xFC + bitRead(b[0],7);
117 this->nRepeat=nRepeat;
118 maxLoadedReg=max(maxLoadedReg,nextReg);
120 #ifdef DCCPP_DEBUG_MODE 122 printPacket(nReg,b,nBytes,nRepeat);
129 void RegisterList::setThrottle(
int nReg,
int cab,
int tSpeed,
int tDirection)
volatile 135 b[nB++] = highByte(cab) | 0xC0;
137 b[nB++] = lowByte(cab);
140 b[nB++] = tSpeed + (tSpeed>0) + tDirection * 128;
146 loadPacket(nReg, b, nB, 0, 1);
148 #if defined(USE_TEXTCOMMAND) 149 DCCPP_INTERFACE.print(
"<T");
150 DCCPP_INTERFACE.print(nReg); DCCPP_INTERFACE.print(
" ");
151 DCCPP_INTERFACE.print(cab); DCCPP_INTERFACE.print(
" ");
152 DCCPP_INTERFACE.print(tSpeed); DCCPP_INTERFACE.print(
" ");
153 DCCPP_INTERFACE.print(tDirection);
154 DCCPP_INTERFACE.print(
">");
155 #if !defined(USE_ETHERNET) 156 DCCPP_INTERFACE.println(
"");
159 speedTable[nReg] = tDirection == 1 ? tSpeed : -tSpeed;
163 #ifdef USE_TEXTCOMMAND 164 void RegisterList::setThrottle(
char *s)
volatile 171 if (sscanf(s,
"%d %d %d %d", &nReg, &cab, &tSpeed, &tDirection) != 4)
173 #ifdef DCCPP_DEBUG_MODE 174 Serial.println(F(
"t Syntax error"));
179 this->setThrottle(nReg, cab, tSpeed, tDirection);
185 void RegisterList::setFunction(
int nReg,
int cab,
int fByte,
int eByte)
volatile 191 b[nB++] = highByte(cab) | 0xC0;
193 b[nB++] = lowByte(cab);
196 b[nB++] = (fByte | 0x80) & 0xBF;
199 b[nB++] = (fByte | 0xDE) & 0xDF;
203 #if defined(USE_TEXTCOMMAND) 204 DCCPP_INTERFACE.print(
"<F");
205 DCCPP_INTERFACE.print(nReg); DCCPP_INTERFACE.print(
" ");
206 DCCPP_INTERFACE.print(cab); DCCPP_INTERFACE.print(
" ");
207 DCCPP_INTERFACE.print(fByte); DCCPP_INTERFACE.print(
" ");
208 DCCPP_INTERFACE.print(eByte);
209 DCCPP_INTERFACE.print(
">");
210 #if !defined(USE_ETHERNET) 211 DCCPP_INTERFACE.println(
"");
219 loadPacket(nReg, b, nB, 4, 1);
222 #ifdef USE_TEXTCOMMAND 223 void RegisterList::setFunction(
char *s)
volatile 229 nParams = sscanf(s,
"%d %d %d", &cab, &fByte, &eByte);
232 #ifdef DCCPP_DEBUG_MODE 233 Serial.println(F(
"f Syntax error"));
241 this->setFunction(0, cab, fByte, eByte);
248 void RegisterList::setAccessory(
int aAdd,
int aNum,
int activate)
volatile 252 b[0] = aAdd % 64 + 128;
253 b[1] = ((((aAdd / 64) % 8) << 4) + (aNum % 4 << 1) + activate % 2) ^ 0xF8;
255 loadPacket(0, b, 2, 4, 1);
259 #ifdef USE_TEXTCOMMAND 260 void RegisterList::setAccessory(
char *s)
volatile 266 if (sscanf(s,
"%d %d %d", &aAdd, &aNum, &activate) != 3)
268 #ifdef DCCPP_DEBUG_MODE 269 Serial.println(F(
"a Syntax error"));
274 this->setAccessory(aAdd, aNum, activate);
281 void RegisterList::writeTextPacket(
int nReg, byte *b,
int nBytes)
volatile 284 if (nBytes<2 || nBytes>5) {
285 DCCPP_INTERFACE.print(
"<mInvalid Packet>");
286 #if !defined(USE_ETHERNET) 287 DCCPP_INTERFACE.println(
"");
292 loadPacket(nReg, b, nBytes, 0, 1);
296 #ifdef USE_TEXTCOMMAND 297 void RegisterList::writeTextPacket(
char *s)
volatile 303 nBytes = sscanf(s,
"%d %hhx %hhx %hhx %hhx %hhx", &nReg, b, b + 1, b + 2, b + 3, b + 4) - 1;
305 this->writeTextPacket(nReg, b, nBytes);
312 int RegisterList::buildBaseAcknowlegde(
int inMonitorPin)
volatile 315 for (
int j = 0; j < ACK_BASE_COUNT; j++)
317 int val = (int)analogRead(inMonitorPin);
321 return base / ACK_BASE_COUNT;
324 int RegisterList::checkAcknowlegde(
int inMonitorPin,
int inBase)
volatile 327 #ifdef DCCPP_DEBUG_MODE 331 for (
int j = 0; j < ACK_SAMPLE_COUNT; j++)
333 int val = (int)analogRead(inMonitorPin);
334 c = (int)((val - inBase) * ACK_SAMPLE_SMOOTHING + c * (1.0 - ACK_SAMPLE_SMOOTHING));
335 #ifdef DCCPP_DEBUG_MODE 339 if (c > ACK_SAMPLE_THRESHOLD)
343 #ifdef DCCPP_DEBUG_MODE 344 if (max > ACK_SAMPLE_THRESHOLD / 2)
347 Serial.print(F(
"Max acknowledge value : "));
354 int RegisterList::readCVraw(
int cv,
int callBack,
int callBackSub)
volatile 362 byte MonitorPin = DCCppConfig::CurrentMonitorProg;
364 MonitorPin = DCCppConfig::CurrentMonitorMain;
367 if (MonitorPin == UNDEFINED_PIN)
370 #ifdef DCCPP_DEBUG_MODE 371 Serial.print(F(
"readCVraw : start reading cv "));
375 bRead[0] = 0x78 + (highByte(cv) & 0x03);
376 bRead[1] = lowByte(cv);
380 for (
int i = 0; i<8; i++) {
382 base = RegisterList::buildBaseAcknowlegde(MonitorPin);
386 loadPacket(0, resetPacket, 2, 3);
387 loadPacket(0, bRead, 3, 5);
388 loadPacket(0, resetPacket, 2, 1);
390 ret = RegisterList::checkAcknowlegde(MonitorPin, base);
392 bitWrite(bValue, i, ret);
395 base = RegisterList::buildBaseAcknowlegde(MonitorPin);
397 bRead[0] = 0x74 + (highByte(cv) & 0x03);
400 loadPacket(0, resetPacket, 2, 3);
401 loadPacket(0, bRead, 3, 5);
402 loadPacket(0, resetPacket, 2, 1);
404 ret = RegisterList::checkAcknowlegde(MonitorPin, base);
409 #if defined(USE_TEXTCOMMAND) 410 DCCPP_INTERFACE.print(
"<r");
411 DCCPP_INTERFACE.print(callBack);
412 DCCPP_INTERFACE.print(
"|");
413 DCCPP_INTERFACE.print(callBackSub);
414 DCCPP_INTERFACE.print(
"|");
415 DCCPP_INTERFACE.print(cv + 1);
416 DCCPP_INTERFACE.print(
" ");
417 DCCPP_INTERFACE.print(bValue);
418 DCCPP_INTERFACE.print(
">");
419 #if !defined(USE_ETHERNET) 420 DCCPP_INTERFACE.println(
"");
424 #ifdef DCCPP_DEBUG_MODE 425 Serial.println(F(
"end reading"));
430 int RegisterList::readCV(
int cv,
int callBack,
int callBackSub)
volatile 432 return RegisterList::readCVraw(cv, callBack, callBackSub);
435 #ifdef USE_TEXTCOMMAND 436 int RegisterList::readCV(
char *s)
volatile 438 int cv, callBack, callBackSub;
440 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
442 #ifdef DCCPP_DEBUG_MODE 443 Serial.println(F(
"R Syntax error"));
448 return this->readCV(cv, callBack, callBackSub);
452 int RegisterList::readCVmain(
int cv,
int callBack,
int callBackSub)
volatile 454 return RegisterList::readCVraw(cv, callBack, callBackSub);
458 #ifdef USE_TEXTCOMMAND 459 int RegisterList::readCVmain(
char *s)
volatile 461 int cv, callBack, callBackSub;
463 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
465 #ifdef DCCPP_DEBUG_MODE 466 Serial.println(F(
"r Syntax error"));
471 return this->readCVmain(cv, callBack, callBackSub);
477 void RegisterList::writeCVByte(
int cv,
int bValue,
int callBack,
int callBackSub)
volatile 484 bWrite[0] = 0x7C + (highByte(cv) & 0x03);
485 bWrite[1] = lowByte(cv);
488 loadPacket(0, resetPacket, 2, 1);
489 loadPacket(0, bWrite, 3, 4);
490 loadPacket(0, resetPacket, 2, 1);
491 loadPacket(0, idlePacket, 2, 10);
494 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
496 base = RegisterList::buildBaseAcknowlegde(DCCppConfig::CurrentMonitorProg);
498 bWrite[0] = 0x74 + (highByte(cv) & 0x03);
500 loadPacket(0, resetPacket, 2, 3);
501 loadPacket(0, bWrite, 3, 5);
502 loadPacket(0, resetPacket, 2, 1);
504 ret = RegisterList::checkAcknowlegde(DCCppConfig::CurrentMonitorProg, base);
510 #if defined(USE_TEXTCOMMAND) 511 DCCPP_INTERFACE.print(
"<r");
512 DCCPP_INTERFACE.print(callBack);
513 DCCPP_INTERFACE.print(
"|");
514 DCCPP_INTERFACE.print(callBackSub);
515 DCCPP_INTERFACE.print(
"|");
516 DCCPP_INTERFACE.print(cv + 1);
517 DCCPP_INTERFACE.print(
" ");
518 DCCPP_INTERFACE.print(bValue);
519 DCCPP_INTERFACE.print(
">");
520 #if !defined(USE_ETHERNET) 521 DCCPP_INTERFACE.println(
"");
526 #ifdef USE_TEXTCOMMAND 527 void RegisterList::writeCVByte(
char *s)
volatile 529 int bValue, cv, callBack, callBackSub;
531 if (sscanf(s,
"%d %d %d %d", &cv, &bValue, &callBack, &callBackSub) != 4)
533 #ifdef DCCPP_DEBUG_MODE 534 Serial.println(F(
"W Syntax error"));
539 this->writeCVByte(cv, bValue, callBack, callBackSub);
545 void RegisterList::writeCVBit(
int cv,
int bNum,
int bValue,
int callBack,
int callBackSub)
volatile 554 bWrite[0] = 0x78 + (highByte(cv) & 0x03);
555 bWrite[1] = lowByte(cv);
556 bWrite[2] = 0xF0 + bValue * 8 + bNum;
558 loadPacket(0, resetPacket, 2, 1);
559 loadPacket(0, bWrite, 3, 4);
560 loadPacket(0, resetPacket, 2, 1);
561 loadPacket(0, idlePacket, 2, 10);
564 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
566 base = RegisterList::buildBaseAcknowlegde(DCCppConfig::CurrentMonitorProg);
568 bitClear(bWrite[2], 4);
570 loadPacket(0, resetPacket, 2, 3);
571 loadPacket(0, bWrite, 3, 5);
572 loadPacket(0, resetPacket, 2, 1);
574 ret = RegisterList::checkAcknowlegde(DCCppConfig::CurrentMonitorProg, base);
580 #if defined(USE_TEXTCOMMAND) 581 DCCPP_INTERFACE.print(
"<r");
582 DCCPP_INTERFACE.print(callBack);
583 DCCPP_INTERFACE.print(
"|");
584 DCCPP_INTERFACE.print(callBackSub);
585 DCCPP_INTERFACE.print(
"|");
586 DCCPP_INTERFACE.print(cv + 1);
587 DCCPP_INTERFACE.print(
" ");
588 DCCPP_INTERFACE.print(bNum);
589 DCCPP_INTERFACE.print(
" ");
590 DCCPP_INTERFACE.print(bValue);
591 DCCPP_INTERFACE.print(
">");
592 #if !defined(USE_ETHERNET) 593 DCCPP_INTERFACE.println(
"");
598 #ifdef USE_TEXTCOMMAND 599 void RegisterList::writeCVBit(
char *s)
volatile 601 int bNum, bValue, cv, callBack, callBackSub;
603 if(sscanf(s,
"%d %d %d %d %d",&cv,&bNum,&bValue,&callBack,&callBackSub) != 5)
605 #ifdef DCCPP_DEBUG_MODE 606 Serial.println(F(
"W Syntax error"));
611 this->writeCVBit(cv, bNum, bValue, callBack, callBackSub);
617 void RegisterList::writeCVByteMain(
int cab,
int cv,
int bValue)
volatile 625 b[nB++] = highByte(cab) | 0xC0;
627 b[nB++] = lowByte(cab);
628 b[nB++] = 0xEC + (highByte(cv) & 0x03);
629 b[nB++] = lowByte(cv);
632 loadPacket(0, b, nB, 4);
636 #ifdef USE_TEXTCOMMAND 637 void RegisterList::writeCVByteMain(
char *s)
volatile 643 if (sscanf(s,
"%d %d %d", &cab, &cv, &bValue) != 3)
645 #ifdef DCCPP_DEBUG_MODE 646 Serial.println(F(
"w Syntax error"));
651 this->writeCVByteMain(cab, cv, bValue);
657 void RegisterList::writeCVBitMain(
int cab,
int cv,
int bNum,
int bValue)
volatile 668 b[nB++] = highByte(cab) | 0xC0;
670 b[nB++] = lowByte(cab);
671 b[nB++] = 0xE8 + (highByte(cv) & 0x03);
672 b[nB++] = lowByte(cv);
673 b[nB++] = 0xF0 + bValue * 8 + bNum;
675 loadPacket(0, b, nB, 4);
679 #ifdef USE_TEXTCOMMAND 680 void RegisterList::writeCVBitMain(
char *s)
volatile 687 if (sscanf(s,
"%d %d %d %d", &cab, &cv, &bNum, &bValue) != 4)
689 #ifdef DCCPP_DEBUG_MODE 690 Serial.println(F(
"w Syntax error"));
695 this->writeCVBitMain(cab, cv, bNum, bValue);
701 #ifdef DCCPP_DEBUG_MODE 702 void RegisterList::printPacket(
int nReg, byte *b,
int nBytes,
int nRepeat)
volatile 704 DCCPP_INTERFACE.print(
"<*");
705 DCCPP_INTERFACE.print(nReg);
706 DCCPP_INTERFACE.print(
":");
707 for(
int i=0;i<nBytes;i++){
708 DCCPP_INTERFACE.print(
" ");
709 DCCPP_INTERFACE.print(b[i],HEX);
711 DCCPP_INTERFACE.print(
" / ");
712 DCCPP_INTERFACE.print(nRepeat);
713 DCCPP_INTERFACE.print(
">");
714 #if !defined(USE_ETHERNET) 715 DCCPP_INTERFACE.println(
"");
722 byte RegisterList::idlePacket[3]={0xFF,0x00,0};
723 byte RegisterList::resetPacket[3]={0x00,0x00,0};
725 byte RegisterList::bitMask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
static bool IsMainTrack(volatile RegisterList *apRegs)