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 #include "Arduino.h"
11 
12 // See TextCommand::parse() below for defined text commands.
13 
14 #include "TextCommand.h"
15 #ifdef USE_TEXTCOMMAND
16 
17 #ifdef VISUALSTUDIO
18 #include "string.h"
19 #include "iostream"
20 #else
21 extern unsigned int __heap_start;
22 extern void *__brkval;
23 #endif
24 
26 
27 char TextCommand::commandString[MAX_COMMAND_LENGTH+1];
28 
30 
31 void TextCommand::init(volatile RegisterList *_mRegs, volatile RegisterList *_pRegs, CurrentMonitor *_mMonitor){
32  commandString[0] = 0;
33 } // TextCommand:TextCommand
34 
36 
38  char c;
39 
40  #if defined(USE_ETHERNET)
41 
42  EthernetClient client= DCCPP_INTERFACE.available();
43 
44  if (client) {
45 
46  if (DCCppConfig::Protocol == EthernetProtocol::HTTP) {
47  DCCPP_INTERFACE.println("HTTP/1.1 200 OK");
48  DCCPP_INTERFACE.println("Content-Type: text/html");
49  DCCPP_INTERFACE.println("Access-Control-Allow-Origin: *");
50  DCCPP_INTERFACE.println("Connection: close");
51  DCCPP_INTERFACE.println("");
52  }
53 
54  while (client.connected() && client.available()) { // while there is data on the network
55  c = client.read();
56  if (c == '<') // start of new command
57  commandString[0] = 0;
58  else if (c == '>') // end of new command
59  {
60  if (parse(commandString) == false)
61  {
62 #if defined(DCCPP_DEBUG_MODE)
63  Serial.println("invalid command !");
64 #endif
65  }
66  }
67  else if (strlen(commandString) < MAX_COMMAND_LENGTH) // if comandString still has space, append character just read from network
68  sprintf(commandString, "%s%c", commandString, c); // otherwise, character is ignored (but continue to look for '<' or '>')
69  } // while
70 
71  if (DCCppConfig::Protocol == EthernetProtocol::HTTP)
72  client.stop();
73  }
74 
75  #else // SERIAL case
76 
77  while (DCCPP_INTERFACE.available()>0) { // while there is data on the serial line
78  c = DCCPP_INTERFACE.read();
79  if (c == '<') // start of new command
80  commandString[0] = 0;
81  else if (c == '>') // end of new command
82  parse(commandString);
83  else if (strlen(commandString) < MAX_COMMAND_LENGTH) // if commandString still has space, append character just read from serial line
84  sprintf(commandString, "%s%c", commandString, c); // otherwise, character is ignored (but continue to look for '<' or '>')
85  } // while
86 
87  #endif
88 } // TextCommand:process
89 
91 
92 bool TextCommand::parse(char *com){
93 
94 
95 #ifdef DCCPP_DEBUG_MODE
96  Serial.print(com[0]);
97  Serial.println(F(" command"));
98 #ifdef VISUALSTUDIO
99  std::cout << com << " command received" << std::endl;
100 #endif
101 #endif
102 
103  switch(com[0]){
104 
105  case 't':
126  DCCpp::mainRegs.setThrottle(com+1);
127  return true;
128 
129  case 'f':
177  DCCpp::mainRegs.setFunction(com+1);
178  return true;
179 
180  case 'a':
216  DCCpp::mainRegs.setAccessory(com+1);
217  return true;
218 
219 #ifdef USE_TURNOUT
220  case 'T':
221 /*
222 * *** SEE TURNOUT.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "T" COMMAND
223 * USED TO CREATE/EDIT/REMOVE/SHOW TURNOUT DEFINITIONS
224 */
225 
226  return Turnout::parse(com+1);
227 #endif
228 
229 #ifdef USE_OUTPUT
230 
231  case 'Z':
232 /**** SEE OUTPUT.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "Z" COMMAND
233 * USED TO CREATE / EDIT / REMOVE / SHOW OUTPUT DEFINITIONS
234 */
235 
236  return Output::parse(com+1);
237 #endif
238 
239 #ifdef USE_SENSOR
240 
241  case 'S':
242 /*
243  * *** SEE SENSOR.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "S" COMMAND
244  * USED TO CREATE/EDIT/REMOVE/SHOW SENSOR DEFINITIONS
245  */
246  return Sensor::parse(com+1);
247 
248 #ifdef DCCPP_PRINT_DCCPP
249  case 'Q':
263  Sensor::status();
264  return true;
265 #endif
266 #endif
267 
268  case 'w':
269 
289  DCCpp::mainRegs.writeCVByteMain(com+1);
290  return true;
291 
292 
293  case 'b':
314  DCCpp::mainRegs.writeCVBitMain(com+1);
315  return true;
316 
317  case 'W':
339  DCCpp::progRegs.writeCVByte(com+1);
340  return true;
341 
342  case 'B':
365  DCCpp::progRegs.writeCVBit(com+1);
366  return true;
367 
368  case 'R':
389  DCCpp::progRegs.readCV(com+1);
390  return true;
391 
392  case 'r':
413  DCCpp::mainRegs.readCV(com + 1);
414  break;
415 
416  case '1':
432  DCCpp::powerOn();
433  return true;
434 
435  case '0':
451  DCCpp::powerOff();
452  return true;
453 
454  case 'c':
471  DCCPP_INTERFACE.print("<a");
472  DCCPP_INTERFACE.print(int(DCCpp::getCurrentMain()));
473  DCCPP_INTERFACE.print(">");
474 #if !defined(USE_ETHERNET)
475  DCCPP_INTERFACE.println("");
476 #endif
477  return true;
478 
479  case 's':
496  if (DCCppConfig::SignalEnablePinMain == UNDEFINED_PIN || digitalRead(DCCppConfig::SignalEnablePinMain) == HIGH)
497  DCCPP_INTERFACE.print("<p0>");
498  if (DCCppConfig::SignalEnablePinProg == UNDEFINED_PIN || digitalRead(DCCppConfig::SignalEnablePinProg) == HIGH)
499  DCCPP_INTERFACE.print("<p1>");
500 #if !defined(USE_ETHERNET)
501  DCCPP_INTERFACE.println("");
502 #endif
503 
504  for(int i=1;i<=MAX_MAIN_REGISTERS;i++){
505  if(DCCpp::mainRegs.speedTable[i]==0)
506  continue;
507  DCCPP_INTERFACE.print("<T");
508  DCCPP_INTERFACE.print(i); DCCPP_INTERFACE.print(" ");
509  if(DCCpp::mainRegs.speedTable[i]>0){
510  DCCPP_INTERFACE.print(DCCpp::mainRegs.speedTable[i]);
511  DCCPP_INTERFACE.print(" 1>");
512  } else{
513  DCCPP_INTERFACE.print(- DCCpp::mainRegs.speedTable[i]);
514  DCCPP_INTERFACE.print(" 0>");
515  }
516 #if !defined(USE_ETHERNET)
517  DCCPP_INTERFACE.println("");
518 #endif
519  }
520  DCCPP_INTERFACE.print("<iDCCpp LIBRARY BASE STATION FOR ARDUINO ");
521  //DCCPP_INTERFACE.print(ARDUINO_TYPE);
522  //DCCPP_INTERFACE.print(" / ");
523  //DCCPP_INTERFACE.print(MOTOR_SHIELD_NAME);
524  DCCPP_INTERFACE.print(": V-");
525  DCCPP_INTERFACE.print(VERSION);
526  DCCPP_INTERFACE.print(" / ");
527  DCCPP_INTERFACE.print(__DATE__);
528  DCCPP_INTERFACE.print(" ");
529  DCCPP_INTERFACE.print(__TIME__);
530  DCCPP_INTERFACE.print(">");
531 #if !defined(USE_ETHERNET)
532  DCCPP_INTERFACE.println("");
533 #endif
534 
535  DCCPP_INTERFACE.print("<N ");
536 #if defined(USE_ETHERNET)
537  DCCPP_INTERFACE.print("ETHERNET :");
538  DCCPP_INTERFACE.print(Ethernet.localIP());
539  DCCPP_INTERFACE.print(">");
540 #if !defined(USE_ETHERNET)
541  DCCPP_INTERFACE.println("");
542 #endif
543 #else
544  DCCPP_INTERFACE.println("SERIAL>");
545 #endif
546 
547 #ifdef DCCPP_PRINT_DCCPP
548 #ifdef USE_TURNOUT
549  Turnout::show();
550 #endif
551 #ifdef USE_OUTPUT
552  Output::show();
553 #endif
554 #ifdef USE_SENSOR
555  Sensor::show();
556 #endif
557 #endif
558  return true;
559 
560 #ifdef USE_EEPROM
561  case 'E':
577  EEStore::store();
578  DCCPP_INTERFACE.print("<e ");
579  DCCPP_INTERFACE.print(EEStore::data.nTurnouts);
580  DCCPP_INTERFACE.print(" ");
581  DCCPP_INTERFACE.print(EEStore::data.nSensors);
582  DCCPP_INTERFACE.print(" ");
583  DCCPP_INTERFACE.print(EEStore::data.nOutputs);
584  DCCPP_INTERFACE.print(">");
585 #if !defined(USE_ETHERNET)
586  DCCPP_INTERFACE.println("");
587 #endif
588  return true;
589 
590  case 'e':
606  EEStore::clear();
607  DCCPP_INTERFACE.print("<O>");
608 #if !defined(USE_ETHERNET)
609  DCCPP_INTERFACE.println("");
610 #endif
611  return true;
612 #endif
613 
614  case ' ':
630  DCCPP_INTERFACE.println("");
631  return true;
632 
637 
638  case 'D':
653  Serial.println("\nEntering Diagnostic Mode...");
654  delay(1000);
655 
657 
658  return true;
659 
660  case 'M':
684  DCCpp::mainRegs.writeTextPacket(com+1);
685  return true;
686 
687  case 'P':
711  DCCpp::progRegs.writeTextPacket(com+1);
712  return true;
713 
714 #ifndef VISUALSTUDIO
715  case 'F':
734  int v;
735  DCCPP_INTERFACE.print("<f");
736 #ifdef ARDUINO_ARCH_AVR
737  DCCPP_INTERFACE.print((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
738 #endif
739  DCCPP_INTERFACE.print(">");
740 #if !defined(USE_ETHERNET)
741  DCCPP_INTERFACE.println("");
742 #endif
743  v++; // not used. This line is just here to avoid a warning by the compiler !
744  return true;
745 #endif
746 
747  case 'L':
762  DCCPP_INTERFACE.println("");
763  for(Register *p = DCCpp::mainRegs.reg; p <= DCCpp::mainRegs.maxLoadedReg;p++){
764  DCCPP_INTERFACE.print("M"); DCCPP_INTERFACE.print((int)(p - DCCpp::mainRegs.reg)); DCCPP_INTERFACE.print(":\t");
765  DCCPP_INTERFACE.print((int)p); DCCPP_INTERFACE.print("\t");
766  DCCPP_INTERFACE.print((int)(p->activePacket)); DCCPP_INTERFACE.print("\t");
767  DCCPP_INTERFACE.print(p->activePacket->nBits); DCCPP_INTERFACE.print("\t");
768  for(int i=0;i<10;i++){
769  DCCPP_INTERFACE.print(p->activePacket->buf[i],HEX); DCCPP_INTERFACE.print("\t");
770  }
771  DCCPP_INTERFACE.println("");
772  }
773  for(Register *p = DCCpp::progRegs.reg; p <= DCCpp::progRegs.maxLoadedReg;p++){
774  DCCPP_INTERFACE.print("P"); DCCPP_INTERFACE.print((int)(p - DCCpp::progRegs.reg)); DCCPP_INTERFACE.print(":\t");
775  DCCPP_INTERFACE.print((int)p); DCCPP_INTERFACE.print("\t");
776  DCCPP_INTERFACE.print((int)p->activePacket); DCCPP_INTERFACE.print("\t");
777  DCCPP_INTERFACE.print(p->activePacket->nBits); DCCPP_INTERFACE.print("\t");
778  for(int i=0;i<10;i++){
779  DCCPP_INTERFACE.print(p->activePacket->buf[i],HEX); DCCPP_INTERFACE.print("\t");
780  }
781  DCCPP_INTERFACE.println("");
782  }
783  DCCPP_INTERFACE.println("");
784  return true;
785  } // switch
786 
787  return false;
788 }; // SerialCommand::parse
789 
791 
792 #endif
static void setDebugDccMode()
static void clear()
Definition: EEStore.cpp:70
static EEStoreData data
Definition: EEStore.h:45
static void store()
Definition: EEStore.cpp:92
static void show()
Definition: Sensor.cpp:153
static void show()
Definition: Turnout.cpp:284
static void powerOff(bool inMain=true, bool inProg=true)
Definition: DCCpp.cpp:417
static void powerOn(bool inMain=true, bool inProg=true)
Definition: DCCpp.cpp:391
static void status()
Definition: Sensor.cpp:180
static bool parse(char *c)
Definition: Sensor.cpp:255
static bool parse(char *c)
Definition: Turnout.cpp:206
static bool parse(char *com)
static float getCurrentMain()
Definition: DCCpp.hpp:240
static void process()
Definition: TextCommand.cpp:37