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