11 #ifdef ARDUINO_ARCH_AVR 19 uint8_t DCCppConfig::EthernetIp[4];
20 uint8_t DCCppConfig::EthernetMac[6];
21 int DCCppConfig::EthernetPort = 0;
23 EthernetProtocol DCCppConfig::Protocol = EthernetProtocol::TCP;
26 byte DCCppConfig::SignalEnablePinMain = UNDEFINED_PIN;
27 byte DCCppConfig::CurrentMonitorMain = UNDEFINED_PIN;
29 byte DCCppConfig::SignalEnablePinProg = UNDEFINED_PIN;
30 byte DCCppConfig::CurrentMonitorProg = UNDEFINED_PIN;
32 byte DCCppConfig::DirectionMotorA = UNDEFINED_PIN;
33 byte DCCppConfig::DirectionMotorB = UNDEFINED_PIN;
37 void Register::initPackets(){
39 updatePacket=packet+1;
44 RegisterList::RegisterList(
int maxNumRegs){
45 this->maxNumRegs=maxNumRegs;
46 reg=(Register *)calloc((maxNumRegs+1),
sizeof(Register));
47 for(
int i=0;i<=maxNumRegs;i++)
49 regMap=(Register **)calloc((maxNumRegs+1),
sizeof(Register *));
50 speedTable=(
int *)calloc((maxNumRegs+1),
sizeof(
int *));
65 void RegisterList::loadPacket(
int nReg, byte *b,
int nBytes,
int nRepeat,
int printFlag)
volatile 70 nReg=nReg%((maxNumRegs+1));
74 if(regMap[nReg]==NULL)
75 regMap[nReg]=maxLoadedReg+1;
77 Register *r=regMap[nReg];
78 Packet *p=r->updatePacket;
82 for(
int i=1;i<nBytes;i++)
88 buf[2]=0xFC + bitRead(b[0],7);
115 this->nRepeat=nRepeat;
116 maxLoadedReg=max(maxLoadedReg,nextReg);
118 #ifdef DCCPP_DEBUG_MODE 120 printPacket(nReg,b,nBytes,nRepeat);
127 void RegisterList::setThrottle(
int nReg,
int cab,
int tSpeed,
int tDirection)
volatile 133 b[nB++] = highByte(cab) | 0xC0;
135 b[nB++] = lowByte(cab);
138 b[nB++] = tSpeed + (tSpeed>0) + tDirection * 128;
144 loadPacket(nReg, b, nB, 0, 1);
146 #if defined(USE_TEXTCOMMAND) 147 INTERFACE.print(
"<T");
148 INTERFACE.print(nReg); INTERFACE.print(
" ");
149 INTERFACE.print(cab); INTERFACE.print(
" ");
150 INTERFACE.print(tSpeed); INTERFACE.print(
" ");
151 INTERFACE.print(tDirection);
152 INTERFACE.print(
">");
153 #if !defined(USE_ETHERNET) 154 INTERFACE.println(
"");
157 speedTable[nReg] = tDirection == 1 ? tSpeed : -tSpeed;
161 #ifdef USE_TEXTCOMMAND 162 void RegisterList::setThrottle(
char *s)
volatile 169 if (sscanf(s,
"%d %d %d %d", &nReg, &cab, &tSpeed, &tDirection) != 4)
171 #ifdef DCCPP_DEBUG_MODE 172 Serial.println(F(
"t Syntax error"));
177 this->setThrottle(nReg, cab, tSpeed, tDirection);
183 void RegisterList::setFunction(
int nReg,
int cab,
int fByte,
int eByte)
volatile 189 b[nB++] = highByte(cab) | 0xC0;
191 b[nB++] = lowByte(cab);
194 b[nB++] = (fByte | 0x80) & 0xBF;
197 b[nB++] = (fByte | 0xDE) & 0xDF;
201 #if defined(USE_TEXTCOMMAND) 202 INTERFACE.print(
"<F");
203 INTERFACE.print(nReg); INTERFACE.print(
" ");
204 INTERFACE.print(cab); INTERFACE.print(
" ");
205 INTERFACE.print(fByte); INTERFACE.print(
" ");
206 INTERFACE.print(eByte);
207 INTERFACE.print(
">");
208 #if !defined(USE_ETHERNET) 209 INTERFACE.println(
"");
217 loadPacket(nReg, b, nB, 4, 1);
220 #ifdef USE_TEXTCOMMAND 221 void RegisterList::setFunction(
char *s)
volatile 227 nParams = sscanf(s,
"%d %d %d", &cab, &fByte, &eByte);
230 #ifdef DCCPP_DEBUG_MODE 231 Serial.println(F(
"f Syntax error"));
239 this->setFunction(0, cab, fByte, eByte);
246 void RegisterList::setAccessory(
int aAdd,
int aNum,
int activate)
volatile 250 b[0] = aAdd % 64 + 128;
251 b[1] = ((((aAdd / 64) % 8) << 4) + (aNum % 4 << 1) + activate % 2) ^ 0xF8;
253 loadPacket(0, b, 2, 4, 1);
257 #ifdef USE_TEXTCOMMAND 258 void RegisterList::setAccessory(
char *s)
volatile 264 if (sscanf(s,
"%d %d %d", &aAdd, &aNum, &activate) != 3)
266 #ifdef DCCPP_DEBUG_MODE 267 Serial.println(F(
"a Syntax error"));
272 this->setAccessory(aAdd, aNum, activate);
279 void RegisterList::writeTextPacket(
int nReg, byte *b,
int nBytes)
volatile 282 if (nBytes<2 || nBytes>5) {
283 INTERFACE.print(
"<mInvalid Packet>");
284 #if !defined(USE_ETHERNET) 285 INTERFACE.println(
"");
290 loadPacket(nReg, b, nBytes, 0, 1);
294 #ifdef USE_TEXTCOMMAND 295 void RegisterList::writeTextPacket(
char *s)
volatile 301 nBytes = sscanf(s,
"%d %hhx %hhx %hhx %hhx %hhx", &nReg, b, b + 1, b + 2, b + 3, b + 4) - 1;
303 this->writeTextPacket(nReg, b, nBytes);
310 int RegisterList::readCVraw(
int cv,
int callBack,
int callBackSub)
volatile 318 byte MonitorPin = DCCppConfig::CurrentMonitorProg;
320 MonitorPin = DCCppConfig::CurrentMonitorMain;
322 if (MonitorPin == UNDEFINED_PIN)
325 bRead[0] = 0x78 + (highByte(cv) & 0x03);
326 bRead[1] = lowByte(cv);
330 for (
int i = 0; i<8; i++) {
336 for (
int j = 0; j < ACK_BASE_COUNT; j++)
338 int val = (int)analogRead(MonitorPin);
341 base /= ACK_BASE_COUNT;
345 loadPacket(0, resetPacket, 2, 3);
346 loadPacket(0, bRead, 3, 5);
347 loadPacket(0, resetPacket, 2, 1);
349 for (
int j = 0; j<ACK_SAMPLE_COUNT; j++)
351 int val = (int)analogRead(MonitorPin);
352 c = (int)((val - base)*ACK_SAMPLE_SMOOTHING + c*(1.0 - ACK_SAMPLE_SMOOTHING));
353 if (c>ACK_SAMPLE_THRESHOLD)
357 bitWrite(bValue, i, d);
364 for (
int j = 0; j<ACK_BASE_COUNT; j++)
365 base += analogRead(MonitorPin);
366 base /= ACK_BASE_COUNT;
368 bRead[0] = 0x74 + (highByte(cv) & 0x03);
371 loadPacket(0, resetPacket, 2, 3);
372 loadPacket(0, bRead, 3, 5);
373 loadPacket(0, resetPacket, 2, 1);
375 for (
int j = 0; j<ACK_SAMPLE_COUNT; j++) {
376 c = (int)((analogRead(MonitorPin) - base)*ACK_SAMPLE_SMOOTHING + c*(1.0 - ACK_SAMPLE_SMOOTHING));
377 if (c>ACK_SAMPLE_THRESHOLD)
384 #if defined(USE_TEXTCOMMAND) 385 INTERFACE.print(
"<r");
386 INTERFACE.print(callBack);
387 INTERFACE.print(
"|");
388 INTERFACE.print(callBackSub);
389 INTERFACE.print(
"|");
390 INTERFACE.print(cv + 1);
391 INTERFACE.print(
" ");
392 INTERFACE.print(bValue);
393 INTERFACE.print(
">");
394 #if !defined(USE_ETHERNET) 395 INTERFACE.println(
"");
402 int RegisterList::readCV(
int cv,
int callBack,
int callBackSub)
volatile 404 return RegisterList::readCVraw(cv, callBack, callBackSub);
407 #ifdef USE_TEXTCOMMAND 408 int RegisterList::readCV(
char *s)
volatile 410 int cv, callBack, callBackSub;
412 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
414 #ifdef DCCPP_DEBUG_MODE 415 Serial.println(F(
"R Syntax error"));
420 return this->readCV(cv, callBack, callBackSub);
424 int RegisterList::readCVmain(
int cv,
int callBack,
int callBackSub)
volatile 426 return RegisterList::readCVraw(cv, callBack, callBackSub);
430 #ifdef USE_TEXTCOMMAND 431 int RegisterList::readCVmain(
char *s)
volatile 433 int cv, callBack, callBackSub;
435 if (sscanf(s,
"%d %d %d", &cv, &callBack, &callBackSub) != 3)
437 #ifdef DCCPP_DEBUG_MODE 438 Serial.println(F(
"r Syntax error"));
443 return this->readCVmain(cv, callBack, callBackSub);
449 void RegisterList::writeCVByte(
int cv,
int bValue,
int callBack,
int callBackSub)
volatile 456 bWrite[0] = 0x7C + (highByte(cv) & 0x03);
457 bWrite[1] = lowByte(cv);
460 loadPacket(0, resetPacket, 2, 1);
461 loadPacket(0, bWrite, 3, 4);
462 loadPacket(0, resetPacket, 2, 1);
463 loadPacket(0, idlePacket, 2, 10);
466 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
472 for (
int j = 0; j < ACK_BASE_COUNT; j++)
473 base += analogRead(DCCppConfig::CurrentMonitorProg);
474 base /= ACK_BASE_COUNT;
476 bWrite[0] = 0x74 + (highByte(cv) & 0x03);
478 loadPacket(0, resetPacket, 2, 3);
479 loadPacket(0, bWrite, 3, 5);
480 loadPacket(0, resetPacket, 2, 1);
482 for (
int j = 0; j < ACK_SAMPLE_COUNT; j++) {
483 c = (int)((analogRead(DCCppConfig::CurrentMonitorProg) - base)*ACK_SAMPLE_SMOOTHING + c*(1.0 - ACK_SAMPLE_SMOOTHING));
484 if (c > ACK_SAMPLE_THRESHOLD)
492 #if defined(USE_TEXTCOMMAND) 493 INTERFACE.print(
"<r");
494 INTERFACE.print(callBack);
495 INTERFACE.print(
"|");
496 INTERFACE.print(callBackSub);
497 INTERFACE.print(
"|");
498 INTERFACE.print(cv + 1);
499 INTERFACE.print(
" ");
500 INTERFACE.print(bValue);
501 INTERFACE.print(
">");
502 #if !defined(USE_ETHERNET) 503 INTERFACE.println(
"");
508 #ifdef USE_TEXTCOMMAND 509 void RegisterList::writeCVByte(
char *s)
volatile 511 int bValue, cv, callBack, callBackSub;
513 if (sscanf(s,
"%d %d %d %d", &cv, &bValue, &callBack, &callBackSub) != 4)
515 #ifdef DCCPP_DEBUG_MODE 516 Serial.println(F(
"W Syntax error"));
521 this->writeCVByte(cv, bValue, callBack, callBackSub);
527 void RegisterList::writeCVBit(
int cv,
int bNum,
int bValue,
int callBack,
int callBackSub)
volatile 536 bWrite[0] = 0x78 + (highByte(cv) & 0x03);
537 bWrite[1] = lowByte(cv);
538 bWrite[2] = 0xF0 + bValue * 8 + bNum;
540 loadPacket(0, resetPacket, 2, 1);
541 loadPacket(0, bWrite, 3, 4);
542 loadPacket(0, resetPacket, 2, 1);
543 loadPacket(0, idlePacket, 2, 10);
546 if (DCCppConfig::CurrentMonitorProg != UNDEFINED_PIN)
552 for (
int j = 0; j < ACK_BASE_COUNT; j++)
553 base += analogRead(DCCppConfig::CurrentMonitorProg);
554 base /= ACK_BASE_COUNT;
556 bitClear(bWrite[2], 4);
558 loadPacket(0, resetPacket, 2, 3);
559 loadPacket(0, bWrite, 3, 5);
560 loadPacket(0, resetPacket, 2, 1);
562 for (
int j = 0; j < ACK_SAMPLE_COUNT; j++) {
563 c = (int)((analogRead(DCCppConfig::CurrentMonitorProg) - base)*ACK_SAMPLE_SMOOTHING + c*(1.0 - ACK_SAMPLE_SMOOTHING));
564 if (c > ACK_SAMPLE_THRESHOLD)
572 #if defined(USE_TEXTCOMMAND) 573 INTERFACE.print(
"<r");
574 INTERFACE.print(callBack);
575 INTERFACE.print(
"|");
576 INTERFACE.print(callBackSub);
577 INTERFACE.print(
"|");
578 INTERFACE.print(cv + 1);
579 INTERFACE.print(
" ");
580 INTERFACE.print(bNum);
581 INTERFACE.print(
" ");
582 INTERFACE.print(bValue);
583 INTERFACE.print(
">");
584 #if !defined(USE_ETHERNET) 585 INTERFACE.println(
"");
590 #ifdef USE_TEXTCOMMAND 591 void RegisterList::writeCVBit(
char *s)
volatile 593 int bNum, bValue, cv, callBack, callBackSub;
595 if(sscanf(s,
"%d %d %d %d %d",&cv,&bNum,&bValue,&callBack,&callBackSub) != 5)
597 #ifdef DCCPP_DEBUG_MODE 598 Serial.println(F(
"W Syntax error"));
603 this->writeCVBit(cv, bNum, bValue, callBack, callBackSub);
609 void RegisterList::writeCVByteMain(
int cab,
int cv,
int bValue)
volatile 617 b[nB++] = highByte(cab) | 0xC0;
619 b[nB++] = lowByte(cab);
620 b[nB++] = 0xEC + (highByte(cv) & 0x03);
621 b[nB++] = lowByte(cv);
624 loadPacket(0, b, nB, 4);
628 #ifdef USE_TEXTCOMMAND 629 void RegisterList::writeCVByteMain(
char *s)
volatile 635 if (sscanf(s,
"%d %d %d", &cab, &cv, &bValue) != 3)
637 #ifdef DCCPP_DEBUG_MODE 638 Serial.println(F(
"w Syntax error"));
643 this->writeCVByteMain(cab, cv, bValue);
649 void RegisterList::writeCVBitMain(
int cab,
int cv,
int bNum,
int bValue)
volatile 660 b[nB++] = highByte(cab) | 0xC0;
662 b[nB++] = lowByte(cab);
663 b[nB++] = 0xE8 + (highByte(cv) & 0x03);
664 b[nB++] = lowByte(cv);
665 b[nB++] = 0xF0 + bValue * 8 + bNum;
667 loadPacket(0, b, nB, 4);
671 #ifdef USE_TEXTCOMMAND 672 void RegisterList::writeCVBitMain(
char *s)
volatile 679 if (sscanf(s,
"%d %d %d %d", &cab, &cv, &bNum, &bValue) != 4)
681 #ifdef DCCPP_DEBUG_MODE 682 Serial.println(F(
"w Syntax error"));
687 this->writeCVBitMain(cab, cv, bNum, bValue);
693 #ifdef DCCPP_DEBUG_MODE 694 void RegisterList::printPacket(
int nReg, byte *b,
int nBytes,
int nRepeat)
volatile 696 INTERFACE.print(
"<*");
697 INTERFACE.print(nReg);
698 INTERFACE.print(
":");
699 for(
int i=0;i<nBytes;i++){
700 INTERFACE.print(
" ");
701 INTERFACE.print(b[i],HEX);
703 INTERFACE.print(
" / ");
704 INTERFACE.print(nRepeat);
705 INTERFACE.print(
">");
706 #if !defined(USE_ETHERNET) 707 INTERFACE.println(
"");
714 byte RegisterList::idlePacket[3]={0xFF,0x00,0};
715 byte RegisterList::resetPacket[3]={0x00,0x00,0};
717 byte RegisterList::bitMask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
static bool IsMainTrack(volatile RegisterList *apRegs)