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 
37 void TextCommand::process(){
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 '1':
408  DCCpp::powerOn();
409  return true;
410 
411  case '0':
427  DCCpp::powerOff();
428  return true;
429 
430  case 'c':
447  DCCPP_INTERFACE.print("<a");
448  DCCPP_INTERFACE.print(int(DCCpp::getCurrentMain()));
449  DCCPP_INTERFACE.print(">");
450 #if !defined(USE_ETHERNET)
451  DCCPP_INTERFACE.println("");
452 #endif
453  return true;
454 
455  case 's':
472  if (DCCppConfig::SignalEnablePinMain == UNDEFINED_PIN || digitalRead(DCCppConfig::SignalEnablePinMain) == HIGH)
473  DCCPP_INTERFACE.print("<p0>");
474  if (DCCppConfig::SignalEnablePinProg == UNDEFINED_PIN || digitalRead(DCCppConfig::SignalEnablePinProg) == HIGH)
475  DCCPP_INTERFACE.print("<p1>");
476 #if !defined(USE_ETHERNET)
477  DCCPP_INTERFACE.println("");
478 #endif
479 
480  for(int i=1;i<=MAX_MAIN_REGISTERS;i++){
481  if(DCCpp::mainRegs.speedTable[i]==0)
482  continue;
483  DCCPP_INTERFACE.print("<T");
484  DCCPP_INTERFACE.print(i); DCCPP_INTERFACE.print(" ");
485  if(DCCpp::mainRegs.speedTable[i]>0){
486  DCCPP_INTERFACE.print(DCCpp::mainRegs.speedTable[i]);
487  DCCPP_INTERFACE.print(" 1>");
488  } else{
489  DCCPP_INTERFACE.print(- DCCpp::mainRegs.speedTable[i]);
490  DCCPP_INTERFACE.print(" 0>");
491  }
492 #if !defined(USE_ETHERNET)
493  DCCPP_INTERFACE.println("");
494 #endif
495  }
496  DCCPP_INTERFACE.print("<iDCCpp LIBRARY BASE STATION FOR ARDUINO ");
497  //DCCPP_INTERFACE.print(ARDUINO_TYPE);
498  //DCCPP_INTERFACE.print(" / ");
499  //DCCPP_INTERFACE.print(MOTOR_SHIELD_NAME);
500  DCCPP_INTERFACE.print(": V-");
501  DCCPP_INTERFACE.print(VERSION);
502  DCCPP_INTERFACE.print(" / ");
503  DCCPP_INTERFACE.print(__DATE__);
504  DCCPP_INTERFACE.print(" ");
505  DCCPP_INTERFACE.print(__TIME__);
506  DCCPP_INTERFACE.print(">");
507 #if !defined(USE_ETHERNET)
508  DCCPP_INTERFACE.println("");
509 #endif
510 
511  DCCPP_INTERFACE.print("<N ");
512 #if defined(USE_ETHERNET)
513  DCCPP_INTERFACE.print("ETHERNET :");
514  DCCPP_INTERFACE.print(Ethernet.localIP());
515  DCCPP_INTERFACE.print(">");
516 #if !defined(USE_ETHERNET)
517  DCCPP_INTERFACE.println("");
518 #endif
519 #else
520  DCCPP_INTERFACE.println("SERIAL>");
521 #endif
522 
523 #ifdef DCCPP_PRINT_DCCPP
524 #ifdef USE_TURNOUT
525  Turnout::show();
526 #endif
527 #ifdef USE_OUTPUT
528  Output::show();
529 #endif
530 #ifdef USE_SENSOR
531  Sensor::show();
532 #endif
533 #endif
534  return true;
535 
536 #ifdef USE_EEPROM
537  case 'E':
553  EEStore::store();
554  DCCPP_INTERFACE.print("<e ");
555  DCCPP_INTERFACE.print(EEStore::data.nTurnouts);
556  DCCPP_INTERFACE.print(" ");
557  DCCPP_INTERFACE.print(EEStore::data.nSensors);
558  DCCPP_INTERFACE.print(" ");
559  DCCPP_INTERFACE.print(EEStore::data.nOutputs);
560  DCCPP_INTERFACE.print(">");
561 #if !defined(USE_ETHERNET)
562  DCCPP_INTERFACE.println("");
563 #endif
564  return true;
565 
566  case 'e':
582  EEStore::clear();
583  DCCPP_INTERFACE.print("<O>");
584 #if !defined(USE_ETHERNET)
585  DCCPP_INTERFACE.println("");
586 #endif
587  return true;
588 #endif
589 
590  case ' ':
606  DCCPP_INTERFACE.println("");
607  return true;
608 
613 
614  case 'D':
629  Serial.println("\nEntering Diagnostic Mode...");
630  delay(1000);
631 
633 
634  return true;
635 
636  case 'M':
660  DCCpp::mainRegs.writeTextPacket(com+1);
661  return true;
662 
663  case 'P':
687  DCCpp::progRegs.writeTextPacket(com+1);
688  return true;
689 
690 #ifndef VISUALSTUDIO
691  case 'F':
710  int v;
711  DCCPP_INTERFACE.print("<f");
712 #ifdef ARDUINO_ARCH_AVR
713  DCCPP_INTERFACE.print((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
714 #endif
715  DCCPP_INTERFACE.print(">");
716 #if !defined(USE_ETHERNET)
717  DCCPP_INTERFACE.println("");
718 #endif
719  return true;
720 #endif
721 
722  case 'L':
737  DCCPP_INTERFACE.println("");
738  for(Register *p = DCCpp::mainRegs.reg; p <= DCCpp::mainRegs.maxLoadedReg;p++){
739  DCCPP_INTERFACE.print("M"); DCCPP_INTERFACE.print((int)(p - DCCpp::mainRegs.reg)); DCCPP_INTERFACE.print(":\t");
740  DCCPP_INTERFACE.print((int)p); DCCPP_INTERFACE.print("\t");
741  DCCPP_INTERFACE.print((int)(p->activePacket)); DCCPP_INTERFACE.print("\t");
742  DCCPP_INTERFACE.print(p->activePacket->nBits); DCCPP_INTERFACE.print("\t");
743  for(int i=0;i<10;i++){
744  DCCPP_INTERFACE.print(p->activePacket->buf[i],HEX); DCCPP_INTERFACE.print("\t");
745  }
746  DCCPP_INTERFACE.println("");
747  }
748  for(Register *p = DCCpp::progRegs.reg; p <= DCCpp::progRegs.maxLoadedReg;p++){
749  DCCPP_INTERFACE.print("P"); DCCPP_INTERFACE.print((int)(p - DCCpp::progRegs.reg)); DCCPP_INTERFACE.print(":\t");
750  DCCPP_INTERFACE.print((int)p); DCCPP_INTERFACE.print("\t");
751  DCCPP_INTERFACE.print((int)p->activePacket); DCCPP_INTERFACE.print("\t");
752  DCCPP_INTERFACE.print(p->activePacket->nBits); DCCPP_INTERFACE.print("\t");
753  for(int i=0;i<10;i++){
754  DCCPP_INTERFACE.print(p->activePacket->buf[i],HEX); DCCPP_INTERFACE.print("\t");
755  }
756  DCCPP_INTERFACE.println("");
757  }
758  DCCPP_INTERFACE.println("");
759  return true;
760  } // switch
761 
762  return false;
763 }; // SerialCommand::parse
764 
766 
767 #endif
static void setDebugDccMode()
static float getCurrentMain()
Definition: DCCpp.hpp:228
static void powerOff(bool inMain=true, bool inProg=true)
Definition: DCCpp.cpp:413
static void powerOn(bool inMain=true, bool inProg=true)
Definition: DCCpp.cpp:389