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 #ifdef DCCPP_DEBUG_MODE
86  Serial.print(com[0]);
87  Serial.println(F(" command"));
88 #endif
89 
90  switch(com[0]){
91 
92 /***** SET ENGINE THROTTLES USING 128-STEP SPEED CONTROL ****/
93 
94  case 't': // <t REGISTER CAB SPEED DIRECTION>
95 /*
96  * sets the throttle for a given register/cab combination
97  *
98  * REGISTER: an internal register number, from 1 through MAX_MAIN_REGISTERS (inclusive), to store the DCC packet used to control this throttle setting
99  * CAB: the short (1-127) or long (128-10293) address of the engine decoder
100  * SPEED: throttle speed from 0-126, or -1 for emergency stop (resets SPEED to 0)
101  * DIRECTION: 1=forward, 0=reverse. Setting direction when speed=0 or speed=-1 only effects directionality of cab lighting for a stopped train
102  *
103  * returns: <T REGISTER SPEED DIRECTION>
104  *
105  */
106 
107  DCCppClass::mainRegs.setThrottle(com+1);
108  break;
109 
110 /***** OPERATE ENGINE DECODER FUNCTIONS F0-F28 ****/
111 
112  case 'f': // <f CAB BYTE1 [BYTE2]>
113 /*
114  * turns on and off engine decoder functions F0-F28 (F0 is sometimes called FL)
115  * NOTE: setting requests transmitted directly to mobile engine decoder --- current state of engine functions is not stored by this program
116  *
117  * CAB: the short (1-127) or long (128-10293) address of the engine decoder
118  *
119  * To set functions F0-F4 on (=1) or off (=0):
120  *
121  * BYTE1: 128 + F1*1 + F2*2 + F3*4 + F4*8 + F0*16
122  * BYTE2: omitted
123  *
124  * To set functions F5-F8 on (=1) or off (=0):
125  *
126  * BYTE1: 176 + F5*1 + F6*2 + F7*4 + F8*8
127  * BYTE2: omitted
128  *
129  * To set functions F9-F12 on (=1) or off (=0):
130  *
131  * BYTE1: 160 + F9*1 +F10*2 + F11*4 + F12*8
132  * BYTE2: omitted
133  *
134  * To set functions F13-F20 on (=1) or off (=0):
135  *
136  * BYTE1: 222
137  * BYTE2: F13*1 + F14*2 + F15*4 + F16*8 + F17*16 + F18*32 + F19*64 + F20*128
138  *
139  * To set functions F21-F28 on (=1) of off (=0):
140  *
141  * BYTE1: 223
142  * BYTE2: F21*1 + F22*2 + F23*4 + F24*8 + F25*16 + F26*32 + F27*64 + F28*128
143  *
144  * returns: NONE
145  *
146  */
147  DCCppClass::mainRegs.setFunction(com+1);
148  break;
149 
150 /***** OPERATE STATIONARY ACCESSORY DECODERS ****/
151 
152  case 'a': // <a ADDRESS SUBADDRESS ACTIVATE>
153 /*
154  * turns an accessory (stationary) decoder on or off
155  *
156  * ADDRESS: the primary address of the decoder (0-511)
157  * SUBADDRESS: the subaddress of the decoder (0-3)
158  * ACTIVATE: 1=on (set), 0=off (clear)
159  *
160  * Note that many decoders and controllers combine the ADDRESS and SUBADDRESS into a single number, N,
161  * from 1 through a max of 2044, where
162  *
163  * N = (ADDRESS - 1) * 4 + SUBADDRESS + 1, for all ADDRESS>0
164  *
165  * OR
166  *
167  * ADDRESS = INT((N - 1) / 4) + 1
168  * SUBADDRESS = (N - 1) % 4
169  *
170  * returns: NONE
171  */
172  DCCppClass::mainRegs.setAccessory(com+1);
173  break;
174 
175 #ifdef USE_TURNOUT
176  /***** CREATE/EDIT/REMOVE/SHOW & OPERATE A TURN-OUT ****/
177 
178  case 'T': // <T ID THROW>
179 /*
180  * <T ID THROW>: sets turnout ID to either the "thrown" or "unthrown" position
181  *
182  * ID: the numeric ID (0-32767) of the turnout to control
183  * THROW: 0 (unthrown) or 1 (thrown)
184  *
185  * returns: <H ID THROW> or <X> if turnout ID does not exist
186  *
187  * *** SEE TURNOUT.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "T" COMMAND
188  * USED TO CREATE/EDIT/REMOVE/SHOW TURNOUT DEFINITIONS
189  */
190  Turnout::parse(com+1);
191  break;
192 #endif
193 
194 #ifdef USE_OUTPUT
195 /***** CREATE/EDIT/REMOVE/SHOW & OPERATE AN OUTPUT PIN ****/
196 
197  case 'Z': // <Z ID ACTIVATE>
198 /*
199  * <Z ID ACTIVATE>: sets output ID to either the "active" or "inactive" state
200  *
201  * ID: the numeric ID (0-32767) of the output to control
202  * ACTIVATE: 0 (active) or 1 (inactive)
203  *
204  * returns: <Y ID ACTIVATE> or <X> if output ID does not exist
205  *
206  * *** SEE OUTPUTS.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "O" COMMAND
207  * USED TO CREATE/EDIT/REMOVE/SHOW TURNOUT DEFINITIONS
208  */
209  Output::parse(com+1);
210  break;
211 #endif
212 
213 #ifdef USE_SENSOR
214 /***** CREATE/EDIT/REMOVE/SHOW A SENSOR ****/
215 
216  case 'S':
217 /*
218  * *** SEE SENSOR.CPP FOR COMPLETE INFO ON THE DIFFERENT VARIATIONS OF THE "S" COMMAND
219  * USED TO CREATE/EDIT/REMOVE/SHOW SENSOR DEFINITIONS
220  */
221  Sensor::parse(com+1);
222  break;
223 
224 /***** SHOW STATUS OF ALL SENSORS ****/
225 
226 #ifdef DCCPP_PRINT_DCCPP
227  case 'Q': // <Q>
228 /*
229  * returns: the status of each sensor ID in the form <Q ID> (active) or <q ID> (not active)
230  */
231  Sensor::status();
232  break;
233 #endif
234 #endif
235 
236 /***** WRITE CONFIGURATION VARIABLE BYTE TO ENGINE DECODER ON MAIN OPERATIONS TRACK ****/
237 
238  case 'w': // <w CAB CV VALUE>
239 /*
240  * writes, without any verification, a Configuration Variable to the decoder of an engine on the main operations track
241  *
242  * CAB: the short (1-127) or long (128-10293) address of the engine decoder
243  * CV: the number of the Configuration Variable memory location in the decoder to write to (1-1024)
244  * VALUE: the value to be written to the Configuration Variable memory location (0-255)
245  *
246  * returns: NONE
247 */
248  DCCppClass::mainRegs.writeCVByteMain(com+1);
249  break;
250 
251 /***** WRITE CONFIGURATION VARIABLE BIT TO ENGINE DECODER ON MAIN OPERATIONS TRACK ****/
252 
253  case 'b': // <b CAB CV BIT VALUE>
254 /*
255  * writes, without any verification, a single bit within a Configuration Variable to the decoder of an engine on the main operations track
256  *
257  * CAB: the short (1-127) or long (128-10293) address of the engine decoder
258  * CV: the number of the Configuration Variable memory location in the decoder to write to (1-1024)
259  * BIT: the bit number of the Configurarion Variable regsiter to write (0-7)
260  * VALUE: the value of the bit to be written (0-1)
261  *
262  * returns: NONE
263 */
264  DCCppClass::mainRegs.writeCVBitMain(com+1);
265  break;
266 
267 /***** WRITE CONFIGURATION VARIABLE BYTE TO ENGINE DECODER ON PROGRAMMING TRACK ****/
268 
269  case 'W': // <W CV VALUE CALLBACKNUM CALLBACKSUB>
270 /*
271  * writes, and then verifies, a Configuration Variable to the decoder of an engine on the programming track
272  *
273  * CV: the number of the Configuration Variable memory location in the decoder to write to (1-1024)
274  * VALUE: the value to be written to the Configuration Variable memory location (0-255)
275  * CALLBACKNUM: an arbitrary integer (0-32767) that is ignored by the Base Station and is simply echoed back in the output - useful for external programs that call this function
276  * CALLBACKSUB: a second arbitrary integer (0-32767) that is ignored by the Base Station and is simply echoed back in the output - useful for external programs (e.g. DCC++ Interface) that call this function
277  *
278  * returns: <r CALLBACKNUM|CALLBACKSUB|CV Value)
279  * where VALUE is a number from 0-255 as read from the requested CV, or -1 if verificaiton read fails
280 */
281  DCCppClass::progRegs.writeCVByte(com+1);
282  break;
283 
284 /***** WRITE CONFIGURATION VARIABLE BIT TO ENGINE DECODER ON PROGRAMMING TRACK ****/
285 
286  case 'B': // <B CV BIT VALUE CALLBACKNUM CALLBACKSUB>
287 /*
288  * writes, and then verifies, a single bit within a Configuration Variable to the decoder of an engine on the programming track
289  *
290  * CV: the number of the Configuration Variable memory location in the decoder to write to (1-1024)
291  * BIT: the bit number of the Configurarion Variable memory location to write (0-7)
292  * VALUE: the value of the bit to be written (0-1)
293  * CALLBACKNUM: an arbitrary integer (0-32767) that is ignored by the Base Station and is simply echoed back in the output - useful for external programs that call this function
294  * CALLBACKSUB: a second arbitrary integer (0-32767) that is ignored by the Base Station and is simply echoed back in the output - useful for external programs (e.g. DCC++ Interface) that call this function
295  *
296  * returns: <r CALLBACKNUM|CALLBACKSUB|CV BIT VALUE)
297  * where VALUE is a number from 0-1 as read from the requested CV bit, or -1 if verificaiton read fails
298 */
299  DCCppClass::progRegs.writeCVBit(com+1);
300  break;
301 
302 /***** READ CONFIGURATION VARIABLE BYTE FROM ENGINE DECODER ON PROGRAMMING TRACK ****/
303 
304  case 'R': // <R CV CALLBACKNUM CALLBACKSUB>
305 /*
306  * reads a Configuration Variable from the decoder of an engine on the programming track
307  *
308  * CV: the number of the Configuration Variable memory location in the decoder to read from (1-1024)
309  * CALLBACKNUM: an arbitrary integer (0-32767) that is ignored by the Base Station and is simply echoed back in the output - useful for external programs that call this function
310  * CALLBACKSUB: a second arbitrary integer (0-32767) that is ignored by the Base Station and is simply echoed back in the output - useful for external programs (e.g. DCC++ Interface) that call this function
311  *
312  * returns: <r CALLBACKNUM|CALLBACKSUB|CV VALUE)
313  * where VALUE is a number from 0-255 as read from the requested CV, or -1 if read could not be verified
314 */
315  DCCppClass::progRegs.readCV(com+1);
316  break;
317 
318 /***** TURN ON POWER FROM MOTOR SHIELD TO TRACKS ****/
319 
320  case '1': // <1>
321 /*
322  * enables power from the motor shield to the main operations and programming tracks
323  *
324  * returns: <p1>
325  */
326  DCCpp.powerOn();
327  break;
328 
329 /***** TURN OFF POWER FROM MOTOR SHIELD TO TRACKS ****/
330 
331  case '0': // <0>
332 /*
333  * disables power from the motor shield to the main operations and programming tracks
334  *
335  * returns: <p0>
336  */
337  DCCpp.powerOff();
338  break;
339 
340 /***** READ MAIN OPERATIONS TRACK CURRENT ****/
341 
342  case 'c': // <c>
343 /*
344  * reads current being drawn on main operations track
345  *
346  * returns: <a CURRENT>
347  * where CURRENT = 0-1024, based on exponentially-smoothed weighting scheme
348  */
349  INTERFACE.print("<a");
350  INTERFACE.print(int(DCCpp.getCurrentMain()));
351  INTERFACE.print(">");
352 #if !defined(USE_ETHERNET)
353  INTERFACE.println("");
354 #endif
355  break;
356 
357 /***** READ STATUS OF DCC++ BASE STATION ****/
358 
359  case 's': // <s>
360 /*
361  * returns status messages containing track power status, throttle status, turn-out status, and a version number
362  * NOTE: this is very useful as a first command for an interface to send to this sketch in order to verify connectivity and update any GUI to reflect actual throttle and turn-out settings
363  *
364  * returns: series of status messages that can be read by an interface to determine status of DCC++ Base Station and important settings
365  */
366  if(digitalRead(DCCppConfig::SignalEnablePinProg)==LOW) // could check either PROG or MAIN
367  INTERFACE.print("<p0>");
368  else
369  INTERFACE.print("<p1>");
370 #if !defined(USE_ETHERNET)
371  INTERFACE.println("");
372 #endif
373 
374  for(int i=1;i<=MAX_MAIN_REGISTERS;i++){
375  if(DCCppClass::mainRegs.speedTable[i]==0)
376  continue;
377  INTERFACE.print("<T");
378  INTERFACE.print(i); INTERFACE.print(" ");
379  if(DCCppClass::mainRegs.speedTable[i]>0){
380  INTERFACE.print(DCCppClass::mainRegs.speedTable[i]);
381  INTERFACE.print(" 1>");
382  } else{
383  INTERFACE.print(- DCCppClass::mainRegs.speedTable[i]);
384  INTERFACE.print(" 0>");
385  }
386  }
387  INTERFACE.print("<iDCCpp LIBRARY BASE STATION FOR ARDUINO ");
388  //INTERFACE.print(ARDUINO_TYPE);
389  //INTERFACE.print(" / ");
390  //INTERFACE.print(MOTOR_SHIELD_NAME);
391  INTERFACE.print(": V-");
392  INTERFACE.print(VERSION);
393  INTERFACE.print(" / ");
394  INTERFACE.print(__DATE__);
395  INTERFACE.print(" ");
396  INTERFACE.print(__TIME__);
397  INTERFACE.print(">");
398 #if !defined(USE_ETHERNET)
399  INTERFACE.println("");
400 #endif
401 
402  INTERFACE.print("<N ");
403 #if defined(USE_ETHERNET)
404  INTERFACE.print("ETHERNET :");
405  INTERFACE.print(Ethernet.localIP());
406  INTERFACE.print(">");
407 #if !defined(USE_ETHERNET)
408  INTERFACE.println("");
409 #endif
410 #else
411  INTERFACE.println("SERIAL>");
412 #endif
413 
414 #ifdef DCCPP_PRINT_DCCPP
415 #ifdef USE_TURNOUT
416  Turnout::show();
417 #endif
418 #ifdef USE_OUTPUT
419  Output::show();
420 #endif
421 #ifdef USE_SENSOR
422  Sensor::show();
423 #endif
424 #endif
425  break;
426 
427 /***** STORE SETTINGS IN EEPROM ****/
428 
429 #ifdef USE_EEPROM
430  case 'E': // <E>
431 /*
432  * stores settings for turnouts and sensors EEPROM
433  *
434  * returns: <e nTurnouts nSensors>
435 */
436 
437  EEStore::store();
438  INTERFACE.print("<e ");
439  INTERFACE.print(EEStore::eeStore->data.nTurnouts);
440  INTERFACE.print(" ");
441  INTERFACE.print(EEStore::eeStore->data.nSensors);
442  INTERFACE.print(" ");
443  INTERFACE.print(EEStore::eeStore->data.nOutputs);
444  INTERFACE.print(">");
445 #if !defined(USE_ETHERNET)
446  INTERFACE.println("");
447 #endif
448  break;
449 
450 /***** CLEAR SETTINGS IN EEPROM ****/
451 
452  case 'e': // <e>
453 /*
454  * clears settings for Turnouts in EEPROM
455  *
456  * returns: <O>
457 */
458 
459  EEStore::clear();
460  INTERFACE.print("<O>");
461 #if !defined(USE_ETHERNET)
462  INTERFACE.println("");
463 #endif
464  break;
465 #endif
466 
467 /***** PRINT CARRIAGE RETURN IN SERIAL MONITOR WINDOW ****/
468 
469  case ' ': // < >
470 /*
471  * simply prints a carriage return - useful when interacting with Ardiuno through serial monitor window
472  *
473  * returns: a carriage return
474 */
475  INTERFACE.println("");
476  break;
477 
482 
483 /***** ENTER DIAGNOSTIC MODE ****/
484 
485  case 'D': // <D>
486 /*
487  * changes the clock speed of the chip and the pre-scaler for the timers so that you can visually see the DCC signals flickering with an LED
488  * SERIAL COMMUNICAITON WILL BE INTERUPTED ONCE THIS COMMAND IS ISSUED - MUST RESET BOARD OR RE-OPEN SERIAL WINDOW TO RE-ESTABLISH COMMS
489  */
490 
491  Serial.println("nEntering Diagnostic Mode...");
492  delay(1000);
493 
494  bitClear(TCCR1B,CS12); // set Timer 1 prescale=8 - SLOWS NORMAL SPEED BY FACTOR OF 8
495  bitSet(TCCR1B,CS11);
496  bitClear(TCCR1B,CS10);
497 
498  #if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO) // Configuration for UNO
499 
500  bitSet(TCCR0B,CS02); // set Timer 0 prescale=256 - SLOWS NORMAL SPEED BY A FACTOR OF 4
501  bitClear(TCCR0B,CS01);
502  bitClear(TCCR0B,CS00);
503 
504  #else // Configuration for MEGA
505 
506  bitClear(TCCR3B,CS32); // set Timer 3 prescale=8 - SLOWS NORMAL SPEED BY A FACTOR OF 8
507  bitSet(TCCR3B,CS31);
508  bitClear(TCCR3B,CS30);
509 
510  #endif
511 
512  CLKPR=0x80; // THIS SLOWS DOWN SYSYEM CLOCK BY FACTOR OF 256
513  CLKPR=0x08; // BOARD MUST BE RESET TO RESUME NORMAL OPERATIONS
514 
515  break;
516 
517 /***** WRITE A DCC PACKET TO ONE OF THE REGSITERS DRIVING THE MAIN OPERATIONS TRACK ****/
518 
519  case 'M': // <M REGISTER BYTE1 BYTE2 [BYTE3] [BYTE4] [BYTE5]>
520 /*
521  * writes a DCC packet of two, three, four, or five hexidecimal bytes to a register driving the main operations track
522  * FOR DEBUGGING AND TESTING PURPOSES ONLY. DO NOT USE UNLESS YOU KNOW HOW TO CONSTRUCT NMRA DCC PACKETS - YOU CAN INADVERTENTLY RE-PROGRAM YOUR ENGINE DECODER
523  *
524  * REGISTER: an internal register number, from 0 through MAX_MAIN_REGISTERS (inclusive), to write (if REGISTER=0) or write and store (if REGISTER>0) the packet
525  * BYTE1: first hexidecimal byte in the packet
526  * BYTE2: second hexidecimal byte in the packet
527  * BYTE3: optional third hexidecimal byte in the packet
528  * BYTE4: optional fourth hexidecimal byte in the packet
529  * BYTE5: optional fifth hexidecimal byte in the packet
530  *
531  * returns: NONE
532  */
533  DCCppClass::mainRegs.writeTextPacket(com+1);
534  break;
535 
536 /***** WRITE A DCC PACKET TO ONE OF THE REGSITERS DRIVING THE MAIN OPERATIONS TRACK ****/
537 
538  case 'P': // <P REGISTER BYTE1 BYTE2 [BYTE3] [BYTE4] [BYTE5]>
539 /*
540  * writes a DCC packet of two, three, four, or five hexidecimal bytes to a register driving the programming track
541  * FOR DEBUGGING AND TESTING PURPOSES ONLY. DO NOT USE UNLESS YOU KNOW HOW TO CONSTRUCT NMRA DCC PACKETS - YOU CAN INADVERTENTLY RE-PROGRAM YOUR ENGINE DECODER
542  *
543  * REGISTER: an internal register number, from 0 through MAX_MAIN_REGISTERS (inclusive), to write (if REGISTER=0) or write and store (if REGISTER>0) the packet
544  * BYTE1: first hexidecimal byte in the packet
545  * BYTE2: second hexidecimal byte in the packet
546  * BYTE3: optional third hexidecimal byte in the packet
547  * BYTE4: optional fourth hexidecimal byte in the packet
548  * BYTE5: optional fifth hexidecimal byte in the packet
549  *
550  * returns: NONE
551  */
552  DCCppClass::progRegs.writeTextPacket(com+1);
553  break;
554 
555 /***** ATTEMPTS TO DETERMINE HOW MUCH FREE SRAM IS AVAILABLE IN ARDUINO ****/
556 
557 #ifndef VISUALSTUDIO
558  case 'F': // <F>
559 /*
560  * measure amount of free SRAM memory left on the Arduino based on trick found on the internet.
561  * Useful when setting dynamic array sizes, considering the Uno only has 2048 bytes of dynamic SRAM.
562  * Unfortunately not very reliable --- would be great to find a better method
563  *
564  * returns: <f MEM>
565  * where MEM is the number of free bytes remaining in the Arduino's SRAM
566  */
567  int v;
568  INTERFACE.print("<f");
569  INTERFACE.print((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
570  INTERFACE.print(">");
571 #if !defined(USE_ETHERNET)
572  INTERFACE.println("");
573 #endif
574  break;
575 #endif
576 
577 /***** LISTS BIT CONTENTS OF ALL INTERNAL DCC PACKET REGISTERS ****/
578 
579  case 'L': // <L>
580 /*
581  * lists the packet contents of the main operations track registers and the programming track registers
582  * FOR DIAGNOSTIC AND TESTING USE ONLY
583  */
584  INTERFACE.println("");
585  for(Register *p = DCCppClass::mainRegs.reg; p <= DCCppClass::mainRegs.maxLoadedReg;p++){
586  INTERFACE.print("M"); INTERFACE.print((int)(p - DCCppClass::mainRegs.reg)); INTERFACE.print(":t");
587  INTERFACE.print((int)p); INTERFACE.print("t");
588  INTERFACE.print((int)(p->activePacket)); INTERFACE.print("t");
589  INTERFACE.print(p->activePacket->nBits); INTERFACE.print("t");
590  for(int i=0;i<10;i++){
591  INTERFACE.print(p->activePacket->buf[i],HEX); INTERFACE.print("t");
592  }
593  INTERFACE.println("");
594  }
595  for(Register *p = DCCppClass::progRegs.reg; p <= DCCppClass::progRegs.maxLoadedReg;p++){
596  INTERFACE.print("P"); INTERFACE.print((int)(p - DCCppClass::progRegs.reg)); INTERFACE.print(":t");
597  INTERFACE.print((int)p); INTERFACE.print("t");
598  INTERFACE.print((int)p->activePacket); INTERFACE.print("t");
599  INTERFACE.print(p->activePacket->nBits); INTERFACE.print("t");
600  for(int i=0;i<10;i++){
601  INTERFACE.print(p->activePacket->buf[i],HEX); INTERFACE.print("t");
602  }
603  INTERFACE.println("");
604  }
605  INTERFACE.println("");
606  break;
607 
608  } // switch
609 }; // SerialCommand::parse
610 
612 
613 #endif
static void parse(char *)
Definition: TextCommand.cpp:83