Code to drive a CNC machine via a PC LPT port lookalike 25 pin 'D', experiment in 'PC/Mach3' replacement. Designed to compile and run on mbed LPC1768, Freescale KL25Z and Freescale KL46Z. Proved on LPC1768 and KL25Z, problem with serial port on KL46Z. Reads subset of 'G Codes' through usb/serial port and drives 3 stepper/servo drives for X, Y and Z, also similar Step/Dir outputs for spindle motor control. Emulates PC LPT, outputs 'charge pump', proved driving Seig KX3 CNC mill

Dependencies:   MODSERIAL mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers command_interpreter.cpp Source File

command_interpreter.cpp

00001 #include "mbed.h"
00002 #include "rtos.h"
00003 #include "MODSERIAL.h"
00004 #include "cnc.h"
00005 #include <cctype>
00006 
00007 extern  MODSERIAL pc;
00008 extern  struct  Gparams    last_position;
00009 extern  void    move_to_XYZ   (struct pirbufgrain & ins)   ;
00010 extern  void    flags_report_cmd (struct singleGparam * a)   ;
00011 extern  void    report_inputs   ()  ;
00012 
00013 fl_typ  feed_rate = 1.0;  //  global scope, mm per minute. DEFAULTS to 1.0mm per min, very slow.
00014 signed long    spindle_rpm = 0;  //  global scope
00015 
00016 
00017 
00018 
00019 #if defined I2C_Enable
00020 extern    I2CSlave slave;//(PTE0, PTE1); on KL25
00021 
00022 int i2c_checksumchecker (char * buf, int len)    {
00023     int k, i = 0x01;
00024     for (k = 0; k < len; k++)
00025         i += buf[k];
00026     i &= 0x0ff;
00027     return  i;
00028 }
00029 
00030 int i2c_checksumchecker (char * buf)    {
00031     return  i2c_checksumchecker (buf, strlen(buf));
00032 }
00033 
00034 char * add_csum (char * buf, int len)    {           //  Adds checksum to end of binary string of known length
00035     int j;
00036     char    cs = 0;
00037     for (j = 0; j < len; j++) {
00038         cs += buf[j];
00039     }
00040     buf[len] = 0xff - cs;
00041     buf[len + 1] = 0;
00042     return  buf;
00043 }
00044 
00045 char * add_csum (char * buf)    {           //  Adds checksum to end of null terminated string
00046     return  add_csum    (buf, strlen(buf));
00047 }
00048 
00049 void    i2c_handler    (void const * name)
00050 {
00051     const int i2buflen = 16;
00052     int err = 0;
00053     char    buf[i2buflen];
00054     char msg[20] = "Message 2snd\0";
00055     add_csum(msg);
00056     slave.address(0xc0);
00057     err = slave.write(msg, strlen(msg) + 1); // Includes null char    //  returns 0 on success, nz otherwise
00058     while   (true)  {
00059         int i = slave.receive();
00060         switch (i) {
00061             case I2CSlave::NoData:  //  Happens most of the time    NoData - the slave has not been addressed
00062                 osThreadYield();  //  Using RTOS on this project
00063                 break;
00064             case I2CSlave::ReadAddressed:   //   - the master has requested a read from this slave
00065                 err = slave.write(msg, strlen(msg) + 1); // Includes null char    //  returns 0 on success, nz otherwise
00066                 pc.printf("RdAddr'd ");
00067                 break;
00068             case I2CSlave::WriteGeneral:    //   - the master is writing to all slave
00069                 err = slave.read(buf, i2buflen);    //  returns 0 on success, nz otherwise
00070                 pc.printf("i=%d, - the master is writing to all slave %s\r\n", i, buf);
00071                 break;
00072             case I2CSlave::WriteAddressed:  //   - the master is writing to this slave
00073                 err = slave.read(buf, i2buflen);    //  returns 0 on success, nz otherwise
00074                 pc.printf("M wr-> [%s]", buf);
00075                 for (int z = 0; z < strlen(buf); z++)
00076                     pc.printf("%2x, ", buf[z]);
00077                 pc.printf("cs %2x\r\n", i2c_checksumchecker(buf));
00078                 break;
00079             default:
00080                 pc.printf("Unknown I2C code %d\r\n");
00081                 break;
00082         }   //  end of switch (i) upon result of slave.receive()
00083         if  (err)   {
00084             pc.printf("Err %d with i = %d\r\n", err, i);
00085             err = 0;
00086         }
00087         memset  (buf, 0, i2buflen);    // Clear buffer
00088     }   //  end of while (true)
00089 }       //  end of void    i2c_handler    (void const * name)
00090 
00091 #endif
00092 
00093 
00094 const int   goodcodes[] = {0,'a','b','c','i','j','l','r','x','y','z'};    //  possible G Code options
00095 const int   const_numofcodes = sizeof(goodcodes) / sizeof(int);
00096 
00097 int find_char_in_goodcodes  (int target)        //  Returns position of char in goodcodes[], 0 if not found.
00098 {
00099     for (int i = 1; i < const_numofcodes; i++)
00100         if  (goodcodes[i] == target)
00101             return  i;
00102     return  0;
00103 }
00104 
00105 /*
00106 void    get_codepositions   (struct singleGparam * a, struct Gparams & p)
00107     Only call from "void    g0g1cmdcore (struct singleGparam * a, double f_rate)"
00108 Purpose:
00109     G code line may have any number of valid axes or parameters entered in any order or position.
00110     This function detects any X,Y,Z,A,I,J,R entries in 'p' if present and copies values into their
00111     respective positions within singleGparam 'a', setting the 'changed' flag for each to true if found,
00112     false if not found
00113 struct  Gparams {  //  Where possibly messy G code line gets ordered and sorted into
00114     struct  singleGparam   x, y, z, i, j, r, a, b, c, d;   //  After sorting, know where to find any X, Y etc values !
00115 }   ;
00116 */
00117 void    get_codepositions   (struct singleGparam * source_array, struct Gparams & dest)
00118 {
00119 //const int   goodcodes[] = {0,'a','b','c','i','j','l','r','x','y','z'};    //  possible G Code options
00120 //const int   const_numofcodes = sizeof(goodcodes) / sizeof(int);
00121 //  source_array is the array filled by function 'void    command_line_interpreter    ()'.
00122 //  It contains any parameters read from the command line :
00123 //  source_array[i].c may contain 'x' or 'y' etc to tie this entry to one of the 'goodcodes' - or not
00124     int         codecnt[const_numofcodes +1];
00125     int         codepos[const_numofcodes +1];
00126     int j;
00127     for (j = 0; j < const_numofcodes; j++)
00128         codecnt[j] = codepos[j] = 0;        //  Zero all results
00129     for (int i = 1; i <= source_array[0].i; i++)  {       //  for number of parameters passed to us here
00130         for(j = 0; j < const_numofcodes; j++)  {  //  for a, for b, ... for x, then y, then z
00131             if  (source_array[i].c == goodcodes[j])   {
00132                 codecnt[j]++;   //  Count of number of 'a's, 'b's ... 'x's, 'y's, 'z's.  All should be 0 or 1 but could be more
00133                 codepos[j] = i; //  Identifies the a[?] containing last incidence of goodcodes[j]
00134             }
00135         }
00136     }
00137     dest.x.changed = dest.y.changed = dest.z.changed = dest.a.changed = false;
00138     dest.i.changed = dest.j.changed = dest.r.changed = false;
00139     dest.x.flt = last_position.x.flt;   //  copy previous coordinates in case not re-specified
00140     dest.y.flt = last_position.y.flt;
00141     dest.z.flt = last_position.z.flt;
00142     dest.a.flt = last_position.a.flt;
00143     dest.i.flt = last_position.i.flt;
00144     dest.j.flt = last_position.j.flt;
00145     dest.r.flt = last_position.r.flt;
00146     j = codepos[find_char_in_goodcodes('a')];
00147     if  (j)  {
00148         dest.a.changed = true;
00149         dest.a.flt = source_array[j].flt;
00150     }
00151     j = codepos[find_char_in_goodcodes('x')];
00152     if  (j)  {
00153         dest.x.changed = true;
00154         dest.x.flt = source_array[j].flt;
00155     }
00156     j = codepos[find_char_in_goodcodes('y')];
00157     if  (j)  {
00158         dest.y.changed = true;
00159         dest.y.flt = source_array[j].flt;
00160     }
00161     j = codepos[find_char_in_goodcodes('z')];
00162     if  (j)  {
00163         dest.z.changed = true;
00164         dest.z.flt = source_array[j].flt;
00165     }
00166     j = codepos[find_char_in_goodcodes('i')];
00167     if  (j)  {
00168         dest.i.changed = true;
00169         dest.i.flt = source_array[j].flt;
00170     }
00171     j = codepos[find_char_in_goodcodes('j')];
00172     if  (j)  {
00173         dest.j.changed = true;
00174         dest.j.flt = source_array[j].flt;
00175     }
00176     j = codepos[find_char_in_goodcodes('r')];
00177     if  (j)  {
00178         dest.r.changed = true;
00179         dest.r.flt = source_array[j].flt;
00180     }
00181 }
00182 
00183 
00184 void    g2g3cmdcore (struct singleGparam * source_array, int twoorthree) {
00185     struct  Gparams tmp;
00186     struct  pirbufgrain start_point, end_point, centre_point, next_point;
00187     int state = 0, arc_steps;
00188     fl_typ  rad_start, rad_end, start_angle, end_angle, next_angle, swept_angle, angle_step, arc_len, z_step;
00189     if  (twoorthree != 2 && twoorthree != 3)    {
00190         pc.printf("Err got %d when should be 2 or 3", twoorthree);
00191         return;
00192     }
00193     if  (twoorthree == 2)
00194         pc.printf("g2 Clockwise Arc\r\n");
00195     else
00196         pc.printf("g3 CounterClockwise Arc\r\n");
00197     get_codepositions   (source_array, tmp);  //  will overwrite with new where entered
00198     pc.printf("X %s\r\n", tmp.x.changed ? "T":"F");
00199     pc.printf("Y %s\r\n", tmp.y.changed ? "T":"F");
00200     pc.printf("Z %s\r\n", tmp.z.changed ? "T":"F");
00201     pc.printf("R %s\r\n", tmp.r.changed ? "T":"F");
00202     pc.printf("I %s\r\n", tmp.i.changed ? "T":"F");
00203     pc.printf("J %s\r\n", tmp.j.changed ? "T":"F");
00204     if  (!tmp.x.changed || !tmp.y.changed)                  state |= 0x10000;    //  Error, X or Y missing
00205     if  (tmp.r.changed && !tmp.i.changed && !tmp.j.changed) state |= 1;  //  Validated R mode got R not I not J
00206     if  (!tmp.r.changed && tmp.i.changed && tmp.j.changed)  state |= 2;  //  Validated IJ mode not R got I got J
00207     start_point.x   = last_position.x.flt;
00208     start_point.y   = last_position.y.flt;
00209     start_point.z   = last_position.z.flt;
00210     end_point.x     = tmp.x.flt;
00211     end_point.y     = tmp.y.flt;
00212     end_point.z     = tmp.z.flt;
00213     switch  (state) {
00214         case    1:  //  Radius format arc
00215             pc.printf("Valid Radius format arc TO DO - not yet implemeted\r\n");
00216         break;
00217         case    2:  //  Centre format arc ** OFFSETS ARE RELATIVE ** Abs coordinates not catered for
00218             pc.printf("Valid Centre format arc\r\n");
00219             centre_point.x = start_point.x + tmp.i.flt;
00220             centre_point.y = start_point.y + tmp.j.flt;
00221             rad_start   = hypot(start_point.x - centre_point.x, start_point.y - centre_point.y);
00222             rad_end     = hypot(end_point.x - centre_point.x, end_point.y - centre_point.y);
00223             pc.printf("Start  point X %.3f, Y %.3f\r\n", start_point.x, start_point.y);
00224             pc.printf("Centre point X %.3f, Y %.3f\r\n", centre_point.x, centre_point.y);
00225             pc.printf("End    point X %.3f, Y %.3f\r\n", end_point.x, end_point.y);
00226             pc.printf("Rad start %.3f, Rad end %.3f\r\n", rad_start, rad_end);
00227             if  (fabs(rad_start - rad_end) > 0.001)  {
00228 //            if  ((rad_start - rad_end) > 0.001 || (rad_start - rad_end) < -0.001)  {
00229                 state |= 0x20000;
00230                 pc.printf("Radii mismatch error in g2g3\r\n");
00231             }
00232             start_angle =   atan2(start_point.y - centre_point.y, start_point.x - centre_point.x);
00233             end_angle   =   atan2(end_point.y - centre_point.y, end_point.x - centre_point.x);
00234             swept_angle = end_angle - start_angle;
00235             //swept_angle = 0.0;  //=IF((B$8=2);IF((H$24>-0.0001);(H$24-2*PI());(H$24))
00236                                 //           ;IF((H$24>0.0001);(H$24);(H$24+2*PI())))
00237             if  (twoorthree == 2)   {
00238                 if  (swept_angle > -epsilon)
00239                     swept_angle -= TWO_PI;
00240             }
00241             else    {   //  twoorthree is 3
00242                 if  (!(swept_angle > epsilon))
00243                     swept_angle += TWO_PI;
00244             }
00245             arc_len  = fabs(rad_start * swept_angle);
00246             pc.printf("start_angle %.3f, end_angle %.3f, swept_angle %.3f, arc_len %.3f\r\n", start_angle, end_angle, swept_angle, arc_len);
00247             arc_steps = (int)(4.0 + fabs(1.7 * rad_end * swept_angle)); //  fiddle factors adjusted empirically !
00248             angle_step = swept_angle / arc_steps;
00249             next_angle = start_angle;
00250             z_step = (end_point.z - start_point.z) / arc_steps;
00251             next_point.z = start_point.z;
00252             pc.printf("Number of steps = %d, angle_step %.3f\r\n", arc_steps, angle_step);
00253             for (int i = 0; i < arc_steps; i++) {   //  cut 'arc_steps' straight lines
00254                 next_angle += angle_step;
00255                 next_point.x = centre_point.x + (rad_start * cos(next_angle));
00256                 next_point.y = centre_point.y + (rad_start * sin(next_angle));
00257                 next_point.z += z_step; 
00258                 pc.printf("X %.3f, Y %.3f\r\n", next_point.x, next_point.y);
00259                 Thread::wait(300);
00260                 next_point.f_rate = feed_rate;
00261                 move_to_XYZ (next_point);
00262             }
00263         break;  //  end of case    2:  //  Centre format arc ** OFFSETS ARE RELATIVE ** Abs coordinates not catered for
00264         default:    //  Input error detected
00265             pc.printf("Input error detected in g2g3, code %x\r\n", state);
00266         break;
00267     }   //  end of switch(state)
00268 }
00269 
00270 void    g0g1cmdcore (struct singleGparam * source_array, fl_typ f_rate)    //  Updates any / all of x, y, z NCOs
00271 {   //  Only get here when some G0 or G1 input has been read.  G0 or G1 determined by f_rate
00272     struct  pirbufgrain ins;//, outs;
00273     struct  Gparams tmp;
00274     get_codepositions   (source_array, tmp);  //  will overwrite with new where entered
00275     if  (!tmp.x.changed && !tmp.y.changed && !tmp.z.changed)    {
00276         pc.printf("No change in X, Y or Z in G0/G1. Ignoring\r\n");
00277         return;
00278     }
00279     ins.x  = tmp.x.flt;
00280     ins.y  = tmp.y.flt;
00281     ins.z  = tmp.z.flt;
00282     ins.f_rate = f_rate;
00283     move_to_XYZ (ins);
00284 }
00285 
00286 void    g0cmd (struct singleGparam * a)    //  Updates any / all of x, y, z NCOs
00287 {
00288     g0g1cmdcore (a, feed_rate_max);     //  Defined parameter in code
00289 }
00290 
00291 void    g1cmd (struct singleGparam * a)    //  Updates any / all of x, y, z NCOs
00292 {
00293     g0g1cmdcore (a, feed_rate);     //  Settable feed_rate
00294 }
00295 
00296 void    g2cmd (struct singleGparam * a)   { //  Clockwise arc
00297     g2g3cmdcore (a, 2);
00298 }
00299 
00300 void    g3cmd (struct singleGparam * a)   { //  Counter clockwise arc
00301     g2g3cmdcore (a, 3);
00302 }
00303 
00304 void    fcmd (struct singleGparam * a)   {  //  Set Feed Rate command
00305     if  (a[1].flt < 0.0)    {
00306         pc.printf("feed rate %.1f ? Setting to 0\r\n", a[1].flt);
00307         a[1].flt = 0.0;
00308     }
00309     if  (a[1].flt > feed_rate_max)    {
00310         pc.printf   ("Error, can't set feed rate to %.1f, max is %.1f, ", a[1].flt, feed_rate_max);
00311         a[1].flt = feed_rate_max;
00312     }
00313     pc.printf   ("Setting feed_rate to %.1f\r\n", a[1].flt);
00314     feed_rate = a[1].flt;
00315 }
00316 extern  void    spindle_control (signed long ss)  ;
00317 extern  bool    spindle_running ()  ;
00318 
00319 void    M3cmd (struct singleGparam * a)   { spindle_control (spindle_rpm);  }
00320 void    M5cmd (struct singleGparam * a)   { spindle_control (0);  }
00321 
00322 void    scmd (struct singleGparam * a)   {
00323     if  (fabs(a[1].flt) > spindle_max)    {
00324         pc.printf   ("Errror setting spindle RPM, can't set to %.0f, ignoring request\r\n", a[1].flt);
00325         return;
00326     }
00327     pc.printf   ("Setting spindle RPM to %.0f Can set Pos or Neg for fwd/rev\r\n", a[1].flt);
00328     spindle_rpm = (signed long) a[1].flt;
00329     if  (spindle_running())
00330         spindle_control (spindle_rpm);
00331     pc.printf("Readback ss %d\r\n", spindle_rpm);
00332 }
00333 
00334 extern  void    target_cmd (struct singleGparam * a)   ;
00335 
00336 void    stopcmd (struct singleGparam * a)   {pc.printf("Stop ! er, not working yet\r\n");}
00337 //void    m1cmd (struct singleGparam * a)   {pc.printf("m1 Optional Programme Stop\r\n");}
00338 //void    m3cmd (struct singleGparam * a)   {pc.printf("m3 Rotate Spindle Clockwise\r\n");}
00339 //void    m4cmd (struct singleGparam * a)   {pc.printf("m4 Rotate Spindle Counter Clockwise\r\n");}
00340 //void    m5cmd (struct singleGparam * a)   {pc.printf("m5 Stop Spindle\r\n");}
00341 /*void    m30cmd (struct singleGparam * a)   {pc.printf("m30 Programme End and Rewind\r\n");}
00342 void    m47cmd (struct singleGparam * a)   {pc.printf("m47 Repeat Prog from First Line\r\n");}
00343 void    m48cmd (struct singleGparam * a)   {pc.printf("m48 Enable Speed and Feed Override\r\n");}
00344 void    m49cmd (struct singleGparam * a)   {pc.printf("m49 Disable Speed and Feed Override\r\n");}
00345 void    m98cmd (struct singleGparam * a)   {pc.printf("m98 Call Subroutine\r\n");}
00346 void    m99cmd (struct singleGparam * a)   {pc.printf("m99 Return from Subroutine\r\n");}
00347 void    g10cmd (struct singleGparam * a)   {pc.printf("g10 Coord System Origin Set\r\n");}
00348 void    g17cmd (struct singleGparam * a)   {pc.printf("g17 XY Plane Select\r\n");}
00349 void    g20cmd (struct singleGparam * a)   {pc.printf("g20 Inch\r\n");}
00350 void    g21cmd (struct singleGparam * a)   {pc.printf("g21 mm\r\n");}
00351 
00352 void    g40cmd (struct singleGparam * a)   {pc.printf("g40 Cutter Compensation Off\r\n");}
00353 void    g50cmd (struct singleGparam * a)   {pc.printf("g50 Reset Scale Factors\r\n");}
00354 void    g53cmd (struct singleGparam * a)   {pc.printf("g53 Move in Absolute Coordinates\r\n");}
00355 void    g90cmd (struct singleGparam * a)   {pc.printf("g90 Absolute Distance Mode\r\n");}
00356 */
00357 //void    g4cmd (struct singleGparam * a)   {pc.printf("g4 Dwell\r\n");}
00358 //void    g91p1cmd (struct singleGparam * a)   {pc.printf("g91.1 \r\n");}
00359 
00360 //void    report_inputs   ()  {
00361 void    report_ins_cmd  (struct singleGparam * a)  {
00362    report_inputs();
00363 }
00364 extern  void    lissajous   (fl_typ)  ;
00365 
00366 void    lisscmd (struct singleGparam * a)   {
00367     lissajous   (feed_rate);
00368 }
00369 
00370 void    menucmd (struct singleGparam * a);
00371 struct kb_command  {
00372     const char * cmd_word;         //  points to text e.g. "menu"
00373     const char * explan;
00374     void (*f)(struct singleGparam *);   //  points to function
00375 }  ;
00376 
00377 struct  kb_command const * command_list_ptr = NULL;   //  Pointer switched between 'input_syntax_check' and 'command_execute'
00378 
00379 struct  kb_command const  input_syntax_check  [] = {
00380     {"menu", "Lists available commands, same as ls", menucmd},
00381     {"ls", "Lists available commands, same as menu", menucmd}    
00382     }   ;
00383 
00384 struct  kb_command const command_execute[] = {
00385     {"menu", "Lists available commands, same as ls", menucmd},
00386     {"ls", "Lists available commands, same as menu", menucmd},
00387     {"stop", "To Stop the Machine !", stopcmd},
00388     {"f ", "To set Feed Rate mm/min, e.g. f 25", fcmd},
00389     {"s ", "To set Spindle RPM, e.g. S 1250", scmd},
00390     {"m3", "Start Spindle at last 'S'", M3cmd},
00391     {"m5", "Stop Spindle", M5cmd},
00392     {"g0", "Rapid move", g0cmd},
00393     {"g1", "Linear Interpolation - move straight at current feed rate", g1cmd},
00394     {"g2", "Helical Interpolation CW (Arc, circle)", g2cmd},
00395     {"g3", "Helical Interpolation CCW (Arc, circle)", g3cmd},
00396     {"liss", "Run Lissajous pattern generator", lisscmd},
00397     {"flags", "Report System Flags", flags_report_cmd},
00398     {"inputs", "Report State of Input bits", report_ins_cmd},
00399     {"target", "Identify computer device", target_cmd},
00400 };
00401 
00402 int numof_menu_items;
00403 void    menucmd (struct singleGparam * a)
00404 {
00405     pc.printf("At menucmd function - listing commands:-\r\n");
00406     for(int i = 0; i < numof_menu_items; i++)
00407         pc.printf("[%s]\t\t%s\r\n", command_list_ptr[i].cmd_word, command_list_ptr[i].explan);
00408     pc.printf("End of List of Commands\r\n");
00409 }
00410 
00411 
00412 void    nudger  (int code)  {   //  Allows <Ctrl> chars to nudge machine axes
00413     //  Using <Ctrl>+ 'F', 'B' for Y, 'L', 'R' for X, 'U', 'D' for Z
00414     //                 6    2          12   18         21   4
00415     struct  pirbufgrain dest;
00416     dest.x = last_position.x.flt;
00417     dest.y = last_position.y.flt;
00418     dest.z = last_position.z.flt;
00419     dest.f_rate = feed_rate;
00420     switch  (code)  {
00421         case    6:  //  'F' move -Y
00422         dest.y -= 0.1;
00423         break;
00424         case    2:  //  'B' move +Y
00425         dest.y += 0.1;
00426         break;
00427         case    12: //  'L' move +X
00428         dest.x += 0.1;
00429         break;
00430         case    18: //  'R' move -X
00431         dest.x -= 0.1;
00432         break;
00433         case    21: //  'U' move +Z
00434         dest.z += 0.1;
00435         break;
00436         case    4:  //  'D' move -Z
00437         dest.z -= 0.1;
00438         default:
00439         break;
00440     }   //  end of switch
00441     move_to_XYZ (dest);
00442 }
00443 
00444 ////class CLI {
00445 
00446 /*
00447 void    command_line_interpreter    ()
00448 Purpose:
00449 
00450 */
00451 
00452 void    command_line_interpreter    (void const * name)
00453 {
00454 const int MAX_PARAMS = 10, MAX_CMD_LEN = 120;
00455 static  char    cmd_line[MAX_CMD_LEN + 4];
00456 static  struct  singleGparam   params[MAX_PARAMS + 1];
00457 static  int     cl_index = 0, lastalpha = 0;
00458 static  fl_typ  fracmul;
00459     if  (true)  {
00460         command_list_ptr = command_execute;
00461         numof_menu_items = sizeof(command_execute) / sizeof(kb_command);
00462     }
00463     else    {
00464         command_list_ptr = input_syntax_check;
00465         numof_menu_items = sizeof(input_syntax_check) / sizeof(kb_command);
00466     }
00467     while   (true)  {
00468         while  (pc.readable()) {
00469             int     ch;
00470             if  (cl_index > MAX_CMD_LEN)  {   //  trap out stupidly long command lines
00471                 pc.printf   ("Keyboard Error!! Killing stupidly long command line");
00472                 cl_index = 0;
00473             }
00474             ch = tolower(pc.getc());
00475             if  (ch == '\r' || ch >= ' ' && ch <= 'z')
00476                 pc.printf("%c", ch);
00477             else    {                   //  Using <Ctrl>+ 'F', 'B' for Y, 'L', 'R' for X, 'U', 'D' for Z
00478                 cl_index = 0;           //                 6    2          12   18         21   4
00479                 pc.printf("[%d]", ch);
00480                 nudger  (ch);
00481             }
00482             if(ch != '\r')  //  was this the 'Enter' key?
00483                 cmd_line[cl_index++] = ch;  //  added char to command being assembled
00484             else    {   //  key was CR, may or may not be command to lookup
00485                 cmd_line[cl_index] = 0; //  null terminate command string
00486                 if(cl_index)    {   //  If have got some chars to lookup
00487                     int i, wrdlen;
00488                     for (i = 0; i < numof_menu_items; i++)   {   //  Look for input match in command list
00489                         wrdlen = strlen(command_list_ptr[i].cmd_word);
00490                         if(strncmp(command_list_ptr[i].cmd_word, cmd_line, wrdlen) == 0)  {   //  If match found
00491                             bool negflag = false;
00492                             int state = 0, paramindex;
00493     //                            pc.printf("Found match for word [%s]\r\n", kbc[i].wrd);
00494                             for(paramindex = 0; paramindex < MAX_PARAMS; paramindex++) {
00495                                 // Clear out whole set of old parameters ready for anything new on this line
00496                                 params[paramindex].i = 0;   //  for integer parameters
00497                                 params[paramindex].c = 0;   //  for last alpha char, helps tie 'X' to '-23.5' etc
00498                                 params[paramindex].flt = 0.0; //  for floating point parameters
00499                                 params[paramindex].ul = 0;
00500                                 params[paramindex].changed = false;
00501                             }
00502                             paramindex = 0;
00503                             //  read any parameters from command line here
00504                             //  Using parameters[0] as count of parameters to follow
00505                             while   (wrdlen <= cl_index)  {
00506                                 ch = cmd_line[wrdlen++];
00507                                 if(isalpha(ch)) lastalpha = ch;
00508                                 if(ch == '-')   negflag = true;
00509                                 if(ch == '+')   negflag = false;
00510                                 switch  (state) {
00511                                     case    0:  //  looking for start of a number string
00512                                         if(isdigit(ch)) {   //  found first digit of a number string
00513                                             paramindex++;
00514                                             if(paramindex > MAX_PARAMS)    {
00515                                                 wrdlen = cl_index;  //  exit condition
00516                                                 pc.printf("WARNING - too many parameters, ignoring extra\r\n");
00517                                             } else    {
00518                                                 params[paramindex].i = ch - '0';
00519                                                 params[paramindex].c = lastalpha;
00520                                                 state = 1;  //  Found first digit char of number string
00521                                             }
00522                                         }
00523                                         break;
00524                                     case    1:  //  looking for end of a number string
00525                                         if(isdigit(ch)) {   //  accumulating integer from string
00526                                             params[paramindex].i *= 10;
00527                                             params[paramindex].i += ch - '0';
00528                                         } else    { //  found non-digit terminating number
00529                                             if  (ch == '.')  {
00530                                                 state = 2;
00531                                                 fracmul = 0.1;
00532                                                 params[paramindex].flt = (fl_typ)params[paramindex].i;
00533                                             } else    {
00534                                                 params[0].i++;    //  count of validated parameters
00535                                                 state = 0;  //  Have read past last digit of number string
00536                                                 if(negflag) {
00537                                                     params[paramindex].i = -params[paramindex].i;
00538                                                     negflag = false;
00539                                                 }
00540                                                 params[paramindex].flt = (fl_typ)params[paramindex].i;
00541                                             }
00542                                         }
00543                                         break;
00544                                     case    2:  //  looking for fractional part of double
00545                                         if(isdigit(ch)) {   //  accumulating fractional part from string
00546                                             params[paramindex].flt += (fl_typ)((ch - '0') * fracmul);
00547                                             fracmul /= 10.0;
00548                                         } else    { //  found non-digit terminating double precision number
00549                                             params[0].i++;    //  count of validated parameters
00550                                             state = 0;  //  Have read past last digit of number string
00551                                             if(negflag) {
00552                                                 params[paramindex].i = -params[paramindex].i;
00553                                                 params[paramindex].flt = -params[paramindex].flt;
00554                                                 negflag = false;
00555                                             }
00556                                         }
00557                                         break;
00558                                     default:
00559                                         break;
00560                                 }   //  end of switch state
00561                             }       //  end of while wrdlen < cl_index
00562     //                            pc.printf("Found match to [%s] with %d parameters\r\n", command_list_ptr[i].wrd, paramindex);
00563                             command_list_ptr[i].f(params);   //  execute command
00564                             i = numof_menu_items + 1;    //  to exit for loop
00565                         }
00566                     }       // End of for numof_menu_items
00567                     if(i == numof_menu_items)
00568                         pc.printf("No Match Found for CMD [%s]\r\n", cmd_line);
00569                 }           //  End of If have got some chars to lookup
00570                 pc.printf("\r\n>");
00571                 cl_index = lastalpha = 0;
00572             }               // End of else key was CR, may or may not be command to lookup
00573         }                   //  End of while (pc.readable())
00574         osThreadYield();  //  Using RTOS on this project
00575     }
00576 }
00577 
00578 ////} cli;
00579