![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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
Diff: command_interpreter.cpp
- Revision:
- 1:66ee619f206b
- Parent:
- 0:5d0f270bfc87
- Child:
- 2:b3c668ec43ac
--- a/command_interpreter.cpp Fri Jan 31 11:16:21 2014 +0000 +++ b/command_interpreter.cpp Thu Feb 06 08:45:02 2014 +0000 @@ -1,11 +1,17 @@ #include "mbed.h" +#include "rtos.h" #include "cnc.h" using namespace std; extern Serial pc; -extern void pir_updater (struct axis_speeds_element * p) ; // Uses pointer as we may wish to rapid update from circular buffer +extern bool liss_active; +extern unsigned long pir_s; +extern int spindlefwdrev; +extern struct Gparams last_position; +extern int PutMoveOnList (struct pirbufgrain & s) ; +extern struct digital_readouts dro; // -double feed_rate = 1.0; // global scope, mm per minute +double feed_rate = 1.0; // global scope, mm per minute. DEFAULTS to 1.0mm per min, very slow. bool isdigit (int a) { @@ -27,9 +33,6 @@ return a; } -extern double find_distance (struct Gparams & from, struct Gparams & to, struct Gparams & distance); -extern long find_traverse_ticks(double dist, double feed_rate); -extern struct Gparams last_position; const int goodcodes[] = {0,'a','b','c','i','j','l','r','x','y','z'}; // possible G Code options const int const_numofcodes = sizeof(goodcodes) / sizeof(int); @@ -58,6 +61,9 @@ { //const int goodcodes[] = {0,'a','b','c','i','j','l','r','x','y','z'}; // possible G Code options //const int const_numofcodes = sizeof(goodcodes) / sizeof(int); +// source_array is the array filled by function 'void command_line_interpreter ()'. +// It contains any parameters read from the command line : +// source_array[i].c may contain 'x' or 'y' etc to tie this entry to one of the 'goodcodes' - or not int codecnt[const_numofcodes +1]; int codepos[const_numofcodes +1]; int j; @@ -74,8 +80,10 @@ dest.x.changed = dest.y.changed = dest.z.changed = dest.a.changed = false; dest.i.changed = dest.j.changed = dest.r.changed = false; dest.x.dbl = last_position.x.dbl; // copy previous coordinates in case not re-specified - dest.y.dbl = last_position.y.dbl; dest.z.dbl = last_position.z.dbl; - dest.a.dbl = last_position.a.dbl; dest.i.dbl = last_position.i.dbl; + dest.y.dbl = last_position.y.dbl; + dest.z.dbl = last_position.z.dbl; + dest.a.dbl = last_position.a.dbl; + dest.i.dbl = last_position.i.dbl; dest.j.dbl = last_position.j.dbl; dest.r.dbl = last_position.r.dbl; j = codepos[find_char_in_goodcodes('a')]; if (j) { @@ -114,31 +122,163 @@ } } +const double duration_multiplier = 60000000.0 / interrupt_period_us; + +void mover (struct pirbufgrain & ins) { + struct pirbufgrain outs; + double distx = ins.x - last_position.x.dbl, + disty = ins.y - last_position.y.dbl, + distz = ins.z - last_position.z.dbl, + distT = sqrt ((distx * distx) + (disty * disty) + (distz * distz)), // 3D Pythag ! + temp = n_for_onemmpermin / distT; + if (distT < 0.01) { + pc.printf("Very small move %.4f, Ignoring!\r\n", distT); + return; + } + last_position.x.dbl = ins.x; // Update global last_position record + last_position.y.dbl = ins.y; + last_position.z.dbl = ins.z; + outs.f_rate = ins.f_rate; + outs.c = duration_multiplier * distT; // Duration ticks subject to feed rate compo + outs.x = temp * distx; + outs.y = temp * disty; + outs.z = temp * distz; // Have assembled data ready to put onto queue of move instructions + PutMoveOnList (outs); +} + +void g2g3cmdcore (struct singleGparam * source_array, int twoorthree) { + struct Gparams tmp; + struct pirbufgrain start_point, end_point, centre_point, next_point; + int state = 0, arc_steps; + double rad_start, rad_end, start_angle, end_angle, next_angle, swept_angle, angle_step, arc_len, z_step; + if (twoorthree != 2 && twoorthree != 3) { + pc.printf("Err got %d when should be 2 or 3", twoorthree); + return; + } + if (twoorthree == 2) + pc.printf("g2 Clockwise Arc\r\n"); + else + pc.printf("g3 CounterClockwise Arc\r\n"); + get_codepositions (source_array, tmp); // will overwrite with new where entered + pc.printf("X %s\r\n", tmp.x.changed ? "T":"F"); + pc.printf("Y %s\r\n", tmp.y.changed ? "T":"F"); + pc.printf("Z %s\r\n", tmp.z.changed ? "T":"F"); + pc.printf("R %s\r\n", tmp.r.changed ? "T":"F"); + pc.printf("I %s\r\n", tmp.i.changed ? "T":"F"); + pc.printf("J %s\r\n", tmp.j.changed ? "T":"F"); + if (!tmp.x.changed || !tmp.y.changed) state |= 0x10000; // Error, X or Y missing + if (tmp.r.changed && !tmp.i.changed && !tmp.j.changed) state |= 1; // Validated R mode got R not I not J + if (!tmp.r.changed && tmp.i.changed && tmp.j.changed) state |= 2; // Validated IJ mode not R got I got J + start_point.x = last_position.x.dbl; + start_point.y = last_position.y.dbl; + start_point.z = last_position.z.dbl; + end_point.x = tmp.x.dbl; + end_point.y = tmp.y.dbl; + end_point.z = tmp.z.dbl; + switch (state) { + case 1: // Radius format arc + pc.printf("Valid Radius format arc TO DO - not yet implemeted\r\n"); + break; + case 2: // Centre format arc ** OFFSETS ARE RELATIVE ** Abs coordinates not catered for + pc.printf("Valid Centre format arc\r\n"); + centre_point.x = start_point.x + tmp.i.dbl; + centre_point.y = start_point.y + tmp.j.dbl; + rad_start = hypot(start_point.x - centre_point.x, start_point.y - centre_point.y); + rad_end = hypot(end_point.x - centre_point.x, end_point.y - centre_point.y); + pc.printf("Start point X %.3f, Y %.3f\r\n", start_point.x, start_point.y); + pc.printf("Centre point X %.3f, Y %.3f\r\n", centre_point.x, centre_point.y); + pc.printf("End point X %.3f, Y %.3f\r\n", end_point.x, end_point.y); + pc.printf("Rad start %.3f, Rad end %.3f\r\n", rad_start, rad_end); + if (fabs(rad_start - rad_end) > 0.001) { +// if ((rad_start - rad_end) > 0.001 || (rad_start - rad_end) < -0.001) { + state |= 0x20000; + pc.printf("Radii mismatch error in g2g3\r\n"); + } + start_angle = atan2(start_point.y - centre_point.y, start_point.x - centre_point.x); + end_angle = atan2(end_point.y - centre_point.y, end_point.x - centre_point.x); + swept_angle = end_angle - start_angle; + //swept_angle = 0.0; //=IF((B$8=2);IF((H$24>-0.0001);(H$24-2*PI());(H$24)) + // ;IF((H$24>0.0001);(H$24);(H$24+2*PI()))) + if (twoorthree == 2) { + if (swept_angle > -epsilon) + swept_angle -= TWO_PI; + } + else { // twoorthree is 3 + if (!(swept_angle > epsilon)) + swept_angle += TWO_PI; + } + arc_len = fabs(rad_start * swept_angle); + pc.printf("start_angle %.3f, end_angle %.3f, swept_angle %.3f, arc_len %.3f\r\n", start_angle, end_angle, swept_angle, arc_len); + arc_steps = (int)(4.0 + fabs(1.7 * rad_end * swept_angle)); // fiddle factors adjusted empirically ! + angle_step = swept_angle / arc_steps; + next_angle = start_angle; + z_step = (end_point.z - start_point.z) / arc_steps; + next_point.z = start_point.z; + pc.printf("Number of steps = %d, angle_step %.3f\r\n", arc_steps, angle_step); + for (int i = 0; i < arc_steps; i++) { // cut 'arc_steps' straight lines + next_angle += angle_step; + next_point.x = centre_point.x + (rad_start * cos(next_angle)); + next_point.y = centre_point.y + (rad_start * sin(next_angle)); + next_point.z += z_step; + pc.printf("X %.3f, Y %.3f\r\n", next_point.x, next_point.y); + Thread::wait(300); + } + break; // end of case 2: // Centre format arc ** OFFSETS ARE RELATIVE ** Abs coordinates not catered for + default: // Input error detected + pc.printf("Input error detected in g2g3, code %x\r\n", state); + break; + } // end of switch(state) +} void g0g1cmdcore (struct singleGparam * source_array, double f_rate) // Updates any / all of x, y, z NCOs -{ - struct Gparams pxyz, distance; - struct axis_speeds_element q; - get_codepositions (source_array, pxyz); // will overwrite with new where entered - pc.printf("g0"); - if (pxyz.x.changed) {pc.printf(" X %f", pxyz.x.dbl);} - if (pxyz.y.changed) {pc.printf(" Y %f", pxyz.y.dbl);} - if (pxyz.z.changed) {pc.printf(" Z %f", pxyz.z.dbl);} - pc.printf("\r\n"); -// for (int j = 1; j < const_numofcodes; j++) { -// pc.printf ("Count of %c is %d, last position %d, last value %f\r\n", goodcodes[j], codecnt[j], codepos[j], a[codepos[j]].d); -// } - double distT = find_distance (last_position, pxyz, distance); // also fills in distance x y z - double temp = n_for_onemmpermin * f_rate / distT; - q.duration_ticks = find_traverse_ticks(distT, f_rate); - last_position.x.dbl = pxyz.x.dbl; // Update global last_position record - last_position.y.dbl = pxyz.y.dbl; - last_position.z.dbl = pxyz.z.dbl; - q.x = (signed long)(temp * distance.x.dbl); - q.y = (signed long)(temp * distance.y.dbl); - q.z = (signed long)(temp * distance.z.dbl); - q.a = 0; - pir_updater (&q); // pir_updater (struct Gparams & p); // To arrive here with wanted 'mm per min' values in x, y and z +{ // Only get here when some G0 or G1 input has been read. G0 or G1 determined by f_rate + struct pirbufgrain ins, outs; + double distx, disty, distz;//, outx, outy, outz, outtimefactor; + struct Gparams tmp; + get_codepositions (source_array, tmp); // will overwrite with new where entered + if (!tmp.x.changed && !tmp.y.changed && !tmp.z.changed) { + pc.printf("No change in X, Y or Z in G0/G1. Ignoring\r\n"); + return; + } + ins.x = tmp.x.dbl; + ins.y = tmp.y.dbl; + ins.z = tmp.z.dbl; + ins.f_rate = f_rate; + distx = ins.x - last_position.x.dbl; // All doubles + disty = ins.y - last_position.y.dbl; + distz = ins.z - last_position.z.dbl; + double distT = sqrt ((distx * distx) + (disty * disty) + (distz * distz)); + if (distT < 0.01) { + pc.printf("Very small move %.4f, Ignoring!\r\n", distT); + return; + } + if (f_rate > feed_rate_max) { + pc.printf("WARNING Stupid feed rate in G0/G1 of %f, setting to %f\r\n", f_rate, feed_rate_max); + f_rate = feed_rate_max; + } + if (f_rate < 0.0) { + pc.printf("Bonkers neg feed rate %f, setting to 0"); + f_rate = 0.0; + } + double temp = n_for_onemmpermin / distT; +// pc.printf("\nG0--G1 Moving to X %4.4f, Y %4.4f, Z%4.4f, distT %f\r\n", px, py, pz, distT); +// pc.printf("Moving From pos'n X %4.4f, Y %4.4f, Z%4.4f\r\n", last_position.x.dbl, last_position.y.dbl, last_position.z.dbl); +// pc.printf("Distances to move X %4.4f, Y %4.4f, Z%4.4f\r\n", distx, disty, distz); +// pc.printf("mm per sec req'd X %4.4f, Y %4.4f, Z%4.4f\r\n", xmmps, ymmps, zmmps); + pc.printf("Total move distance %4.4f, at feed rate %.2f, run time SECs = %f\r\n", distT, f_rate, 60.0 * distT / f_rate); +// pc.printf("This time maps to %f interrupt ticks\r\n", run_secs * 1000000.0 / interrupt_period_us); + last_position.x.dbl = ins.x; // Update global last_position record + last_position.y.dbl = ins.y; + last_position.z.dbl = ins.z; + outs.f_rate = ins.f_rate; + outs.c = duration_multiplier * distT; // Duration ticks subject to feed rate compo + outs.x = temp * distx; + outs.y = temp * disty; + outs.z = temp * distz; +// pc.printf("Dists Scaled for angle, X%f, Y%f, Z%f\r\n", outs.x, outs.y, outs.z); +// pc.printf("Last position X%f, Y%f, Z%f\r\n", last_position.x.dbl, last_position.y.dbl, last_position.z.dbl); +// outs.a.dbl = 0.0; // not used axis + PutMoveOnList (outs); } void g0cmd (struct singleGparam * a) // Updates any / all of x, y, z NCOs @@ -151,25 +291,26 @@ g0g1cmdcore (a, feed_rate); // Settable feed_rate } -void fcmd (struct singleGparam * a) { - if (a[1].dbl < feed_rate_min || a[1].dbl > feed_rate_max) { - pc.printf ("Errror setting feed rate, can't set to %f, ignoring request\r\n", a[1].dbl); - return; +void fcmd (struct singleGparam * a) { // Set Feed Rate command + if (a[1].dbl < 0.0) { + pc.printf("feed rate %f ? Setting to 0\r\n", a[1].dbl); + a[1].dbl = 0.0; + } + if (a[1].dbl > feed_rate_max) { + pc.printf ("Error, can't set feed rate to %f, max is %f, ", a[1].dbl, feed_rate_max); + a[1].dbl = feed_rate_max; } pc.printf ("Setting feed_rate to %f\r\n", a[1].dbl); feed_rate = a[1].dbl; } -extern unsigned long pir_s; -extern int spindlefwdrev; - void sfcmd (struct singleGparam * a) {pc.printf("Spindle Fwd\r\n"); spindlefwdrev = 0;} void srcmd (struct singleGparam * a) {pc.printf("Spindle Rev\r\n"); spindlefwdrev = 4;} void stopcmd (struct singleGparam * a) {pc.printf("Stop ! er, not working yet\r\n");} void scmd (struct singleGparam * a) { pc.printf("pir_s=0x%x\r\n", pir_s); - if (a[1].dbl < spindle_min || a[1].dbl > spindle_max) { + if (a[1].dbl < 0.0 || a[1].dbl > spindle_max) { pc.printf ("Errror setting spindle RPM, can't set to %f, ignoring request\r\n", a[1].dbl); // return; } @@ -200,12 +341,42 @@ void g53cmd (struct singleGparam * a) {pc.printf("g53 Move in Absolute Coordinates\r\n");} void g90cmd (struct singleGparam * a) {pc.printf("g90 Absolute Distance Mode\r\n");} */ -void g2cmd (struct singleGparam * a) {pc.printf("g2 Clockwise Arc\r\n");} -void g3cmd (struct singleGparam * a) {pc.printf("g3 CounterClockwise Arc\r\n");} +void g2cmd (struct singleGparam * a) { // Clockwise arc + g2g3cmdcore (a, 2); + } +void g3cmd (struct singleGparam * a) { // Counter clockwise arc + g2g3cmdcore (a, 3); + } void g4cmd (struct singleGparam * a) {pc.printf("g4 Dwell\r\n");} void g91p1cmd (struct singleGparam * a) {pc.printf("g91.1 \r\n");} -extern struct digital_readouts dro; // +void tasktstone (void const * name) +{ + static int i = 0; + pc.printf("Arrived at tasktstone\r\n"); + while (true) { + pc.printf("%s %d\r\n", name, i++); + Thread::wait(9500); + osThreadYield(); + } +} + +/*void tasktestcmd (struct singleGparam * a) { + pc.printf("At tasktestcmd\r\n"); + Thread tasktest (tasktstone, (void *) "Bollocks"); + pc.printf("Leaving tasktestcmd\r\n"); +} +*/ +void lisscmd (struct singleGparam * a) { + if(liss_active) { + pc.printf("Can not add Lissajous, already running.\r\n"); + } + else { + pc.printf("Adding Lissajous task\r\n"); + liss_active = true; + } +} + void drooncmd (struct singleGparam * a) { dro.dro_output = true; // Enable continuous dro display update @@ -215,10 +386,6 @@ dro.dro_output = false; // Disable continuous dro display update } -//extern void craptest () ; -//void g1cmd (struct singleGparam * a) { -// craptest (); -//} void g90p1cmd (struct singleGparam * a) { @@ -232,19 +399,28 @@ } void menucmd (struct singleGparam * a); -struct kb_command { +struct kb_command { const char * cmd_word; // points to text e.g. "menu" const char * explan; void (*f)(struct singleGparam *); // points to function -} kbc[] = { - {(char const *)"menu", "Lists available commands, same as ls", menucmd}, - {(char const *)"ls", "Lists available commands, same as menu", menucmd}, +} ; + +struct kb_command const * command_list_ptr = NULL; // Pointer switched between 'input_syntax_check' and 'command_execute' + +struct kb_command const input_syntax_check [] = { + {"menu", "Lists available commands, same as ls", menucmd}, + {"ls", "Lists available commands, same as menu", menucmd} + } ; + +struct kb_command const command_execute[] = { + {"menu", "Lists available commands, same as ls", menucmd}, + {"ls", "Lists available commands, same as menu", menucmd}, {"stop", "To Stop the Machine !", stopcmd}, {"sf", "Spindle Clockwise", sfcmd}, {"sr", "Spindle Anticlockwise", srcmd}, {"f ", "To set Feed Rate mm/min, e.g. f 25", fcmd}, {"s ", "To set Spindle RPM, e.g. S 1250", scmd}, - {"g0", "Not Implemented", g0cmd}, + {"g0", "Rapid move", g0cmd}, /*{"m30", "Not Implemented", m30cmd}, {"m47", "Not Implemented", m47cmd}, {"m48", "Not Implemented", m48cmd}, @@ -265,20 +441,23 @@ {"g91.1", "Not Implemented", g91p1cmd}, {"g90", "Not Implemented", g90cmd}, */ - {"g1", "", g1cmd}, - {"g2", "", g2cmd}, - {"g3", "", g3cmd}, - {"g4", "", g4cmd}, + {"g1", "Linear Interpolation - move straight at current feed rate", g1cmd}, + {"g2", "Helical Interpolation CW (Arc, circle)", g2cmd}, + {"g3", "Helical Interpolation CCW (Arc, circle)", g3cmd}, + {"liss", "Add Lissajous pattern generator", lisscmd}, +// {"ttest", "Add a task to prove we can, or not", tasktestcmd}, {"dro on", "Turn dro readout on", drooncmd}, {"dro off", "Turn dro readout off", drooffcmd} }; -const int numof_menu_items = sizeof(kbc) / sizeof(kb_command); - +//const int numof_menu_items = sizeof(kbc2) / sizeof(kb_command); +//const int numof_menu_items_sc = sizeof(input_syntax_check) / sizeof(kb_command); +//const int numof_menu_items_ce = sizeof(command_execute) / sizeof(kb_command); +int numof_menu_items; void menucmd (struct singleGparam * a) { pc.printf("At menucmd function - listing commands:-\r\n"); for(int i = 0; i < numof_menu_items; i++) - pc.printf("[%s]\t\t%s\r\n", kbc[i].cmd_word, kbc[i].explan); + pc.printf("[%s]\t\t%s\r\n", command_list_ptr[i].cmd_word, command_list_ptr[i].explan); pc.printf("End of List of Commands\r\n"); } @@ -289,139 +468,131 @@ return false; } -char * readout (char * txt, int p) // p has running subtotal of all pulses issued to stepper driver -{ - txt[0] = '+'; // constructs string e.g. "+123.456" - txt[8] = 0; // null terminated - if (p < 0) { - txt[0] = '-'; - p = -p; - } - p *= 1000; - p /= pulses_per_mm; - for(int k = 7; k > 0; k--) { - if (k == 4) - txt[k] = '.'; - else { - txt[k] = '0' + (p % 10); - p /= 10; - } - } - return txt; // Returns pointer unaltered for subsequent use by e.g. cout -} - ////class CLI { -const int MAX_PARAMS = 20, MAX_CMD_LEN = 120; -char cmd_line[MAX_CMD_LEN + 4]; -struct singleGparam params[MAX_PARAMS + 1]; -int cl_index = 0, ch, lastalpha = 0; -double fracmul; /* void command_line_interpreter () Purpose: */ -void command_line_interpreter () +void command_line_interpreter (void const * name) { - while (pc.readable()) { - if (cl_index > MAX_CMD_LEN) { // trap out stupidly long command lines - pc.printf ("Keyboard Error!! Killing stupidly long command line"); - cl_index = 0; - } - ch = tolower(pc.getc()); - if(ch != '\r') // was this the 'Enter' key? - cmd_line[cl_index++] = ch; // added char to command being assembled - else { // key was CR, may or may not be command to lookup - cmd_line[cl_index] = 0; // null terminate command string - if(cl_index) { // If have got some chars to lookup - int i, wrdlen; - for (i = 0; i < numof_menu_items; i++) { // Look for input match in command list - wrdlen = strlen(kbc[i].cmd_word); - if(strncmp(kbc[i].cmd_word, cmd_line, wrdlen) == 0) { // If match found - bool negflag = false; - int state = 0, paramindex; -// pc.printf("Found match for word [%s]\r\n", kbc[i].wrd); - for(paramindex = 0; paramindex < MAX_PARAMS; paramindex++) { - // Clear out whole set of old parameters ready for anything new on this line - params[paramindex].i = 0; // for integer parameters - params[paramindex].c = 0; // for last alpha char, helps tie 'X' to '-23.5' etc - params[paramindex].dbl = 0.0; // for floating point parameters - params[paramindex].ul = 0; - params[paramindex].changed = false; - } - paramindex = 0; - // read any parameters from command line here - // Using parameters[0] as count of parameters to follow - while (wrdlen <= cl_index) { - ch = cmd_line[wrdlen++]; - if(isalpha(ch)) lastalpha = ch; - if(ch == '-') negflag = true; - if(ch == '+') negflag = false; - switch (state) { - case 0: // looking for start of a number string - if(isdigit(ch)) { // found first digit of a number string - paramindex++; - if(paramindex > MAX_PARAMS) { - wrdlen = cl_index; // exit condition - pc.printf("WARNING - too many parameters, ignoring extra\r\n"); - } else { - params[paramindex].i = ch - '0'; - params[paramindex].c = lastalpha; - state = 1; // Found first digit char of number string +const int MAX_PARAMS = 10, MAX_CMD_LEN = 120; +static char cmd_line[MAX_CMD_LEN + 4]; +static struct singleGparam params[MAX_PARAMS + 1]; +static int cl_index = 0, lastalpha = 0; + pc.printf("Got to cli, Starting cli\r\n"); + if (true) { + command_list_ptr = command_execute; + numof_menu_items = sizeof(command_execute) / sizeof(kb_command); + } + else { + command_list_ptr = input_syntax_check; + numof_menu_items = sizeof(input_syntax_check) / sizeof(kb_command); + } + while (true) { + while (pc.readable()) { + int ch; + if (cl_index > MAX_CMD_LEN) { // trap out stupidly long command lines + pc.printf ("Keyboard Error!! Killing stupidly long command line"); + cl_index = 0; + } + ch = tolower(pc.getc()); + if(ch != '\r') // was this the 'Enter' key? + cmd_line[cl_index++] = ch; // added char to command being assembled + else { // key was CR, may or may not be command to lookup + cmd_line[cl_index] = 0; // null terminate command string + if(cl_index) { // If have got some chars to lookup + int i, wrdlen; + for (i = 0; i < numof_menu_items; i++) { // Look for input match in command list + wrdlen = strlen(command_list_ptr[i].cmd_word); + if(strncmp(command_list_ptr[i].cmd_word, cmd_line, wrdlen) == 0) { // If match found + bool negflag = false; + int state = 0, paramindex; + double fracmul; + // pc.printf("Found match for word [%s]\r\n", kbc[i].wrd); + for(paramindex = 0; paramindex < MAX_PARAMS; paramindex++) { + // Clear out whole set of old parameters ready for anything new on this line + params[paramindex].i = 0; // for integer parameters + params[paramindex].c = 0; // for last alpha char, helps tie 'X' to '-23.5' etc + params[paramindex].dbl = 0.0; // for floating point parameters + params[paramindex].ul = 0; + params[paramindex].changed = false; + } + paramindex = 0; + // read any parameters from command line here + // Using parameters[0] as count of parameters to follow + while (wrdlen <= cl_index) { + ch = cmd_line[wrdlen++]; + if(isalpha(ch)) lastalpha = ch; + if(ch == '-') negflag = true; + if(ch == '+') negflag = false; + switch (state) { + case 0: // looking for start of a number string + if(isdigit(ch)) { // found first digit of a number string + paramindex++; + if(paramindex > MAX_PARAMS) { + wrdlen = cl_index; // exit condition + pc.printf("WARNING - too many parameters, ignoring extra\r\n"); + } else { + params[paramindex].i = ch - '0'; + params[paramindex].c = lastalpha; + state = 1; // Found first digit char of number string + } } - } - break; - case 1: // looking for end of a number string - if(isdigit(ch)) { // accumulating integer from string - params[paramindex].i *= 10; - params[paramindex].i += ch - '0'; - } else { // found non-digit terminating number - if (ch == '.') { - state = 2; - fracmul = 0.1; - params[paramindex].dbl = (double)params[paramindex].i; - } else { + break; + case 1: // looking for end of a number string + if(isdigit(ch)) { // accumulating integer from string + params[paramindex].i *= 10; + params[paramindex].i += ch - '0'; + } else { // found non-digit terminating number + if (ch == '.') { + state = 2; + fracmul = 0.1; + params[paramindex].dbl = (double)params[paramindex].i; + } else { + params[0].i++; // count of validated parameters + state = 0; // Have read past last digit of number string + if(negflag) { + params[paramindex].i = -params[paramindex].i; + negflag = false; + } + params[paramindex].dbl = (double)params[paramindex].i; + } + } + break; + case 2: // looking for fractional part of double + if(isdigit(ch)) { // accumulating fractional part from string + params[paramindex].dbl += (double)((ch - '0') * fracmul); + fracmul /= 10.0; + } else { // found non-digit terminating double precision number params[0].i++; // count of validated parameters state = 0; // Have read past last digit of number string if(negflag) { params[paramindex].i = -params[paramindex].i; + params[paramindex].dbl = -params[paramindex].dbl; negflag = false; } - params[paramindex].dbl = (double)params[paramindex].i; } - } - break; - case 2: // looking for fractional part of double - if(isdigit(ch)) { // accumulating fractional part from string - params[paramindex].dbl += (double)((ch - '0') * fracmul); - fracmul /= 10.0; - } else { // found non-digit terminating double precision number - params[0].i++; // count of validated parameters - state = 0; // Have read past last digit of number string - if(negflag) { - params[paramindex].i = -params[paramindex].i; - params[paramindex].dbl = -params[paramindex].dbl; - negflag = false; - } - } - break; - default: - break; - } // end of switch state - } // end of while wrdlen < cl_index -// pc.printf("Found match to [%s] with %d parameters\r\n", kbc[i].wrd, paramindex); - kbc[i].f(params); // execute command - i = numof_menu_items + 1; // to exit for loop - } - } // End of for numof_menu_items - if(i == numof_menu_items) - pc.printf("No Match Found for CMD [%s]\r\n", cmd_line); - } // End of If have got some chars to lookup - cl_index = lastalpha = 0; - } // End of else key was CR, may or may not be command to lookup - } // End of while (pc.readable()) -// osThreadYield(); // Not using RTOS on this project + break; + default: + break; + } // end of switch state + } // end of while wrdlen < cl_index + // pc.printf("Found match to [%s] with %d parameters\r\n", command_list_ptr[i].wrd, paramindex); + command_list_ptr[i].f(params); // execute command + i = numof_menu_items + 1; // to exit for loop + } + } // End of for numof_menu_items + if(i == numof_menu_items) + pc.printf("No Match Found for CMD [%s]\r\n", cmd_line); + } // End of If have got some chars to lookup + cl_index = lastalpha = 0; + } // End of else key was CR, may or may not be command to lookup + } // End of while (pc.readable()) + // pc.printf("cli yielding\r\n"); + osThreadYield(); // Using RTOS on this project + } } ////} cli;