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
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
Generated on Sat Jul 16 2022 01:39:30 by 1.7.2