DCCpp
This is the library version of a program for Arduino to control railroading DCC devices.
TextCommand.cpp
1 /**********************************************************************
2 
3 TextCommand.cpp
4 COPYRIGHT (c) 2013-2016 Gregg E. Berman
5 
6 Part of DCC++ BASE STATION for the Arduino
7 
8 **********************************************************************/
9 
10 // See TextCommand::parse() below for defined text commands.
11 
12 #include "TextCommand.h"
13 #ifdef USE_TEXTCOMMAND
14 
15 #ifdef VISUALSTUDIO
16 #include "string.h"
17 #else
18 extern unsigned int __heap_start;
19 extern void *__brkval;
20 #endif
21 
23 
24 char TextCommand::commandString[MAX_COMMAND_LENGTH+1];
25 
27 
28 void TextCommand::init(volatile RegisterList *_mRegs, volatile RegisterList *_pRegs, CurrentMonitor *_mMonitor){
29  commandString[0] = 0;
30 } // TextCommand:TextCommand
31 
33 
34 void TextCommand::process(){
35  char c;
36 
37  #if defined(USE_ETHERNET)
38 
39  EthernetClient client=INTERFACE.available();
40 
41  if (client) {
42 
43  if (DCCppConfig::Protocol == EthernetProtocol::HTTP) {
44  INTERFACE.println("HTTP/1.1 200 OK");
45  INTERFACE.println("Content-Type: text/html");
46  INTERFACE.println("Access-Control-Allow-Origin: *");
47  INTERFACE.println("Connection: close");
48  INTERFACE.println("");
49  }
50 
51  while (client.connected() && client.available()) { // while there is data on the network
52  c = client.read();
53  if (c == '<') // start of new command
54  commandString[0] = 0;
55  else if (c == '>') // end of new command
56  parse(commandString);
57  else if (strlen(commandString) < MAX_COMMAND_LENGTH) // if comandString still has space, append character just read from network
58  sprintf(commandString, "%s%c", commandString, c); // otherwise, character is ignored (but continue to look for '<' or '>')
59  } // while
60 
61  if (DCCppConfig::Protocol == EthernetProtocol::HTTP)
62  client.stop();
63  }
64 
65  #else // SERIAL case
66 
67  while (INTERFACE.available()>0) { // while there is data on the serial line
68  c = INTERFACE.read();
69  if (c == '<') // start of new command
70  commandString[0] = 0;
71  else if (c == '>') // end of new command
72  parse(commandString);
73  else if (strlen(commandString) < MAX_COMMAND_LENGTH) // if commandString still has space, append character just read from serial line
74  sprintf(commandString, "%s%c", commandString, c); // otherwise, character is ignored (but continue to look for '<' or '>')
75  } // while
76 
77  #endif
78 
79 } // TextCommand:process
80 
82 
83 void TextCommand::parse(char *com){
84 
85 
86 #ifdef DCCPP_DEBUG_MODE
87  Serial.print(com[0]);
88  Serial.println(F(" command"));
89 #endif
90 
91  switch(com[0]){
92 
93  case 't':
114  DCCpp::mainRegs.setThrottle(com+1);
115  break;
116 
117  case 'f':
162  DCCpp::mainRegs.setFunction(com+1);
163  break;
164 
165  case 'a':
201  DCCpp::mainRegs.setAccessory(com+1);
202  break;
203 
204 #ifdef USE_TURNOUT
205  case 'T':
206 /*
207 * *** SEE TURNOUT.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "T" COMMAND
208 * USED TO CREATE/EDIT/REMOVE/SHOW TURNOUT DEFINITIONS
209 */
210 
211  Turnout::parse(com+1);
212  break;
213 #endif
214 
215 #ifdef USE_OUTPUT
216 
217  case 'Z':
218 /**** SEE OUTPUT.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "Z" COMMAND
219 * USED TO CREATE / EDIT / REMOVE / SHOW OUTPUT DEFINITIONS
220 */
221 
222  Output::parse(com+1);
223  break;
224 #endif
225 
226 #ifdef USE_SENSOR
227 
228  case 'S':
229 /*
230  * *** SEE SENSOR.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "S" COMMAND
231  * USED TO CREATE/EDIT/REMOVE/SHOW SENSOR DEFINITIONS
232  */
233  Sensor::parse(com+1);
234  break;
235 
236 #ifdef DCCPP_PRINT_DCCPP
237  case 'Q':
251  Sensor::status();
252  break;
253 #endif
254 #endif
255 
256  case 'w':
257 
277  DCCpp::mainRegs.writeCVByteMain(com+1);
278  break;
279 
280 
281  case 'b':
302  DCCpp::mainRegs.writeCVBitMain(com+1);
303  break;
304 
305  case 'W':
327  DCCpp::progRegs.writeCVByte(com+1);
328  break;
329 
330  case 'B':
353  DCCpp::progRegs.writeCVBit(com+1);
354  break;
355 
356  case 'R':
377  DCCpp::progRegs.readCV(com+1);
378  break;
379 
380  case '1':
396  DCCpp::powerOn();
397  break;
398 
399  case '0':
415  DCCpp::powerOff();
416  break;
417 
418  case 'c':
435  INTERFACE.print("<a");
436  INTERFACE.print(int(DCCpp::getCurrentMain()));
437  INTERFACE.print(">");
438 #if !defined(USE_ETHERNET)
439  INTERFACE.println("");
440 #endif
441  break;
442 
443  case 's':
460  if(digitalRead(DCCppConfig::SignalEnablePinProg)==LOW) // could check either PROG or MAIN
461  INTERFACE.print("<p0>");
462  else
463  INTERFACE.print("<p1>");
464 #if !defined(USE_ETHERNET)
465  INTERFACE.println("");
466 #endif
467 
468  for(int i=1;i<=MAX_MAIN_REGISTERS;i++){
469  if(DCCpp::mainRegs.speedTable[i]==0)
470  continue;
471  INTERFACE.print("<T");
472  INTERFACE.print(i); INTERFACE.print(" ");
473  if(DCCpp::mainRegs.speedTable[i]>0){
474  INTERFACE.print(DCCpp::mainRegs.speedTable[i]);
475  INTERFACE.print(" 1>");
476  } else{
477  INTERFACE.print(- DCCpp::mainRegs.speedTable[i]);
478  INTERFACE.print(" 0>");
479  }
480 #if !defined(USE_ETHERNET)
481  INTERFACE.println("");
482 #endif
483  }
484  INTERFACE.print("<iDCCpp LIBRARY BASE STATION FOR ARDUINO ");
485  //INTERFACE.print(ARDUINO_TYPE);
486  //INTERFACE.print(" / ");
487  //INTERFACE.print(MOTOR_SHIELD_NAME);
488  INTERFACE.print(": V-");
489  INTERFACE.print(VERSION);
490  INTERFACE.print(" / ");
491  INTERFACE.print(__DATE__);
492  INTERFACE.print(" ");
493  INTERFACE.print(__TIME__);
494  INTERFACE.print(">");
495 #if !defined(USE_ETHERNET)
496  INTERFACE.println("");
497 #endif
498 
499  INTERFACE.print("<N ");
500 #if defined(USE_ETHERNET)
501  INTERFACE.print("ETHERNET :");
502  INTERFACE.print(Ethernet.localIP());
503  INTERFACE.print(">");
504 #if !defined(USE_ETHERNET)
505  INTERFACE.println("");
506 #endif
507 #else
508  INTERFACE.println("SERIAL>");
509 #endif
510 
511 #ifdef DCCPP_PRINT_DCCPP
512 #ifdef USE_TURNOUT
513  Turnout::show();
514 #endif
515 #ifdef USE_OUTPUT
516  Output::show();
517 #endif
518 #ifdef USE_SENSOR
519  Sensor::show();
520 #endif
521 #endif
522  break;
523 
524 #ifdef USE_EEPROM
525  case 'E':
541  EEStore::store();
542  INTERFACE.print("<e ");
543  INTERFACE.print(EEStore::data.nTurnouts);
544  INTERFACE.print(" ");
545  INTERFACE.print(EEStore::data.nSensors);
546  INTERFACE.print(" ");
547  INTERFACE.print(EEStore::data.nOutputs);
548  INTERFACE.print(">");
549 #if !defined(USE_ETHERNET)
550  INTERFACE.println("");
551 #endif
552  break;
553 
554  case 'e':
570  EEStore::clear();
571  INTERFACE.print("<O>");
572 #if !defined(USE_ETHERNET)
573  INTERFACE.println("");
574 #endif
575  break;
576 #endif
577 
578  case ' ':
594  INTERFACE.println("");
595  break;
596 
601 
602  case 'D':
617  Serial.println("nEntering Diagnostic Mode...");
618  delay(1000);
619 
620  bitClear(TCCR1B,CS12); // set Timer 1 prescale=8 - SLOWS NORMAL SPEED BY FACTOR OF 8
621  bitSet(TCCR1B,CS11);
622  bitClear(TCCR1B,CS10);
623 
624  #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO
625 
626  bitSet(TCCR0B,CS02); // set Timer 0 prescale=256 - SLOWS NORMAL SPEED BY A FACTOR OF 4
627  bitClear(TCCR0B,CS01);
628  bitClear(TCCR0B,CS00);
629 
630  #else // Configuration for MEGA
631 
632  bitClear(TCCR3B,CS32); // set Timer 3 prescale=8 - SLOWS NORMAL SPEED BY A FACTOR OF 8
633  bitSet(TCCR3B,CS31);
634  bitClear(TCCR3B,CS30);
635 
636  #endif
637 
638  CLKPR=0x80; // THIS SLOWS DOWN SYSYEM CLOCK BY FACTOR OF 256
639  CLKPR=0x08; // BOARD MUST BE RESET TO RESUME NORMAL OPERATIONS
640 
641  break;
642 
643  case 'M':
667  DCCpp::mainRegs.writeTextPacket(com+1);
668  break;
669 
670  case 'P':
694  DCCpp::progRegs.writeTextPacket(com+1);
695  break;
696 
697 #ifndef VISUALSTUDIO
698  case 'F':
717  int v;
718  INTERFACE.print("<f");
719  INTERFACE.print((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
720  INTERFACE.print(">");
721 #if !defined(USE_ETHERNET)
722  INTERFACE.println("");
723 #endif
724  break;
725 #endif
726 
727  case 'L':
742  INTERFACE.println("");
743  for(Register *p = DCCpp::mainRegs.reg; p <= DCCpp::mainRegs.maxLoadedReg;p++){
744  INTERFACE.print("M"); INTERFACE.print((int)(p - DCCpp::mainRegs.reg)); INTERFACE.print(":t");
745  INTERFACE.print((int)p); INTERFACE.print("t");
746  INTERFACE.print((int)(p->activePacket)); INTERFACE.print("t");
747  INTERFACE.print(p->activePacket->nBits); INTERFACE.print("t");
748  for(int i=0;i<10;i++){
749  INTERFACE.print(p->activePacket->buf[i],HEX); INTERFACE.print("t");
750  }
751  INTERFACE.println("");
752  }
753  for(Register *p = DCCpp::progRegs.reg; p <= DCCpp::progRegs.maxLoadedReg;p++){
754  INTERFACE.print("P"); INTERFACE.print((int)(p - DCCpp::progRegs.reg)); INTERFACE.print(":t");
755  INTERFACE.print((int)p); INTERFACE.print("t");
756  INTERFACE.print((int)p->activePacket); INTERFACE.print("t");
757  INTERFACE.print(p->activePacket->nBits); INTERFACE.print("t");
758  for(int i=0;i<10;i++){
759  INTERFACE.print(p->activePacket->buf[i],HEX); INTERFACE.print("t");
760  }
761  INTERFACE.println("");
762  }
763  INTERFACE.println("");
764  break;
765 
766  } // switch
767 }; // SerialCommand::parse
768 
770 
771 #endif
static float getCurrentMain()
Definition: DCCpp.hpp:154
static void powerOff()
Definition: DCCpp.cpp:560
static void powerOn()
Definition: DCCpp.cpp:548