diff --git a/getopt.c b/getopt.c new file mode 100755 index 0000000..1200447 --- /dev/null +++ b/getopt.c @@ -0,0 +1,138 @@ +/* +Newsgroups: mod.std.unix +Subject: public domain AT&T getopt source +Date: 3 Nov 85 19:34:15 GMT + +Here's something you've all been waiting for: the AT&T public domain +source for getopt(3). It is the code which was given out at the 1985 +UNIFORUM conference in Dallas. I obtained it by electronic mail +directly from AT&T. The people there assure me that it is indeed +in the public domain. + +25/1/2005 Henry Thomas + +Ported this original AT&T version of 'getopt' to windows. + +Added 'getargv' to parse the 'WinMain' 'lpCmdLine' argument and convert it +into an argc/argv pair. This should improve portability between windows and +unix/linux platforms. + +*/ + +#include "321/getopt.h" +#ifndef HAS_GETOPT_H + +#include +#if defined(_MSC_VER) +# include +#endif +#include +#include + +#ifdef HAS_WIN_GUI + +/* The windows gui version reports command line errors using MessageBox */ + +#define WIN32_LEAN_AND_MEAN +#include +#define ERR(s, c) if(opterr) {\ + char buffer[64];\ + _snprintf(buffer, 64, "%s%s%c", argv[0], s, c);\ + MessageBox(NULL, buffer, "Command Line Error", MB_OK | MB_ICONERROR);\ +} + +#else + +#define ERR(s, c) if(opterr) {\ + char errbuf[2];\ + errbuf[0] = c; errbuf[1] = '\n';\ + (void) write(2, argv[0], (unsigned)strlen(argv[0]));\ + (void) write(2, s, (unsigned)strlen(s));\ + (void) write(2, errbuf, 2);\ +} + +#endif + +int opterr = 1; +int optind = 1; +int optopt; +char *optarg; + +int getopt(int argc, char **argv, char *opts) +{ + static int sp = 1; + register int c; + register char *cp; + + if(sp == 1) { + if(optind >= argc || + argv[optind][0] != '-' || argv[optind][1] == '\0') { + return(-1); + } + else if(strcmp(argv[optind], "--") == 0) { + optind++; + return(-1); + } + } + optopt = c = argv[optind][sp]; + if(c == ':' || (cp = strchr(opts, c)) == NULL) { + ERR(": illegal option -- ", c); + if(argv[optind][++sp] == '\0') { + optind++; + sp = 1; + } + return('?'); + } + if(*++cp == ':') { + if(argv[optind][sp+1] != '\0') { + optarg = &argv[optind++][sp+1]; + } + else if(++optind >= argc) { + ERR(": option requires an argument -- ", c); + sp = 1; + return('?'); + } + else { + optarg = argv[optind++]; + } + sp = 1; + } + else { + if(argv[optind][++sp] == '\0') { + sp = 1; + optind++; + } + optarg = NULL; + } + return(c); +} + +#ifdef HAS_WIN_GUI + +char **getargv(char *cl, int *argc) +{ + static char *argv[MAX_ARGC]; + int i; + for(i = 0; i < MAX_ARGC; i++) { + argv[i] = cl; +LOOP: + cl++; + if(cl[0] == ' ') { + while(cl[1] == ' ') cl++; + *cl = 0; + cl++; + } + else { + if(cl[0]) { + goto LOOP; + } + i++; + break; + } + } + *argc = i; + return argv; +} + +#endif +#endif /* HAS_GETOPT_H */ diff --git a/getopt.h b/getopt.h new file mode 100755 index 0000000..16803c9 --- /dev/null +++ b/getopt.h @@ -0,0 +1,93 @@ +/* +Newsgroups: mod.std.unix +Subject: public domain AT&T getopt source +Date: 3 Nov 85 19:34:15 GMT + +Here's something you've all been waiting for: the AT&T public domain +source for getopt(3). It is the code which was given out at the 1985 +UNIFORUM conference in Dallas. I obtained it by electronic mail +directly from AT&T. The people there assure me that it is indeed +in the public domain. + +25/1/2005 Henry Thomas + +Ported this original AT&T version of 'getopt' to windows. + +Added documentation to this header, so know what everything does. + +*/ + +#ifndef GETOPT_H_ +#define GETOPT_H_ + +#ifdef HAS_GETOPT_H +# include +#else + +#ifdef __cplusplus +extern "C" { +#endif + +extern int opterr; + +/* If the value of the 'opterr' variable is nonzero, then getopt prints an +error message to the standard error stream if it encounters an unknown option +character or an option with a missing required argument. The windows version +reports the error using a message box. This is the default behavior. If you +set this variable to zero, getopt does not print any messages, but it still +returns the character ? to indicate an error. */ + +extern int optopt; + +/* When getopt encounters an unknown option character or an option with a +missing required argument, it stores that option character the 'optopt' +variable. You can use this for providing your own diagnostic messages. */ + +extern int optind; + +/* The 'optind' variable is set by getopt to the index of the next element of +the argv array to be processed. Once getopt has found all of the option +arguments, you can use this variable to determine where the remaining +non-option arguments begin. The initial value of this variable is 1. */ + +extern char *optarg; + +/* The 'optarg' variable is set by getopt to point at the value of the +option argument, for those options that accept arguments. */ + +int getopt(int argc, char **argv, char *opts); + +/* The getopt function gets the next option argument from the argument list +specified by the argv and argc arguments. Normally these values come directly +from the arguments received by main. + +The options argument is a string that specifies the option characters that are +valid for this program. An option character in this string can be followed +by a colon (':') to indicate that it takes a required argument. */ + +#ifdef WIN32 + +#ifndef HAS_WIN_CLI +#define HAS_WIN_GUI 1 +#endif + +/* Define 'HAS_WIN_CLI' if you plan to use this version of getopt in a +windows console application */ + +#define MAX_ARGC 32 + +/* This is the maximum argument count that 'getargv' will return. */ + +char **getargv(char *cl, int *argc); + +/* Parse a single command line sting and convert it into an argc/argv pair +compatible with getopt */ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HAS_GETOPT_H */ +#endif /* GETOPT_H_ */ diff --git a/gpx.c b/gpx.c index 2f30fe3..788cbbe 100644 --- a/gpx.c +++ b/gpx.c @@ -32,7 +32,12 @@ #include #include #include + +#ifdef _WIN32 +#include "getopt.h" +#else #include +#endif #include "gpx.h" @@ -47,6 +52,7 @@ static Machine replicator_1 = { {1170, 1100, 400, ENDSTOP_IS_MIN}, // z axis {1600, 96.275201870333662468889989185642, 3200, 1}, // a extruder {1600, 96.275201870333662468889989185642, 3200, 0}, // b extruder + 1.75, // nominal filament diameter 1, // extruder count 20, // timeout }; @@ -57,6 +63,7 @@ static Machine replicator_1D = { {1170, 1100, 400, ENDSTOP_IS_MIN}, // z axis {1600, 96.275201870333662468889989185642, 3200, 1}, // a extruder {1600, 96.275201870333662468889989185642, 3200, 0}, // b extruder + 1.75, // nominal filament diameter 2, // extruder count 20, // timeout }; @@ -67,6 +74,7 @@ static Machine replicator_2 = { {1170, 1100, 400, ENDSTOP_IS_MIN}, // z axis {1600, 96.275201870333662468889989185642, 3200, 0}, // a extruder {1600, 96.275201870333662468889989185642, 3200, 0}, // b extruder + 1.75, // nominal filament diameter 1, // extruder count 20, // timeout }; @@ -77,6 +85,7 @@ static Machine replicator_2X = { {1170, 1100, 400, ENDSTOP_IS_MIN}, // z axis {1600, 96.275201870333662468889989185642, 3200, 1}, // a extruder {1600, 96.275201870333662468889989185642, 3200, 0}, // b extruder + 1.75, // nominal filament diameter 2, // extruder count 20, // timeout }; @@ -89,6 +98,7 @@ Machine machine = { {1170, 400, ENDSTOP_IS_MIN}, // z axis {1600, 96.275201870333662468889989185642, 3200, 0}, // a extruder {1600, 96.275201870333662468889989185642, 3200, 0}, // b extruder + 1.75, // nominal filament diameter 1, // extruder count 20, // timeout }; @@ -100,9 +110,8 @@ static double get_home_feedrate(int flag); // GLOBAL VARIABLES Command command; // the gcode command line -Point5d currentPosition; // the extruders current position in 5D space -Point5d machineTarget; // machine target point -Point5d workTarget; // work target point (including G10 offsets) +Point5d currentPosition; // the current position of the extruder in 5D space +Point5d targetPosition; // the target poaition the extruder will move to (including G10 offsets) Point2d excess; // the accumulated rounding error in mm to step conversion int currentExtruder; // the currently selectd extruder using Tn double currentFeedrate; // the current feed rate @@ -114,6 +123,7 @@ int positionKnown; // is the current extruder position known int programState; // gcode program state used to trigger start and end code sequences unsigned line_number; // the current line number in the gcode file static char buffer[256]; // the statically allocated parse-in-place buffer +double scale[2]; // A & B scaling for n x 0.01 mm change in nominal diameter FILE *in; // the gcode input file stream FILE *out; // the x3g output file stream @@ -195,6 +205,9 @@ static void initialize_globals(void) programState = 0; line_number = 1; + + scale[0] = 0; + scale[1] = 0; } // STATE @@ -388,7 +401,9 @@ double get_safe_feedrate(int flag, Ptr5d delta) { return feedrate; } -// convert mm to steps using the current machine definition and accumulate the rounding error +// convert mm to steps using the current machine definition + +// IMPORTANT: this command changes the global excess value which accunulates the rounding remainder static Point5d mm_to_steps(Ptr5d mm, Ptr2d excess) { @@ -398,12 +413,15 @@ static Point5d mm_to_steps(Ptr5d mm, Ptr2d excess) result.y = round(mm->y * machine.y.steps_per_mm); result.z = round(mm->z * machine.z.steps_per_mm); if(excess) { + // accumulate rounding remainder value = (mm->a * machine.a.steps_per_mm) + excess->a; result.a = round(value); + // changes to excess excess->a = value - result.a; value = (mm->b * machine.b.steps_per_mm) + excess->b; result.b = round(value); + // changes to excess excess->b = value - result.b; } else { @@ -449,7 +467,6 @@ static void home_axes(unsigned direction) if(direction != machine.y.endstop) { fprintf(stderr, "(line %u) Semantic Warning: Y axis homing to %s endstop" EOL, line_number, direction ? "maximum" : "minimum"); } - } if(xyz_flag & Z_IS_SET) { if(machine.z.home_feedrate < feedrate) { @@ -522,6 +539,8 @@ static void wait_for_extruder(unsigned extruder_id, unsigned timeout) // 136 - extruder action command +// Action 03 - Set toolhead target temperature + static void set_extruder_temperature(unsigned extruder_id, unsigned temperature) { assert(extruder_id < machine.extruder_count); @@ -540,6 +559,8 @@ static void set_extruder_temperature(unsigned extruder_id, unsigned temperature) if(write_16(temperature) == EOF) exit(1); } +// Action 12 - Enable / Disable fan + static void set_fan(unsigned extruder_id, unsigned state) { assert(extruder_id < machine.extruder_count); @@ -558,6 +579,8 @@ static void set_fan(unsigned extruder_id, unsigned state) if(write_8(state) == EOF) exit(1); } +// Action 13 - Enable / Disable extra output (blower fan) + static void set_valve(unsigned extruder_id, unsigned state) { assert(extruder_id < machine.extruder_count); @@ -576,6 +599,8 @@ static void set_valve(unsigned extruder_id, unsigned state) if(write_8(state) == EOF) exit(1); } +// Action 31 - Set build platform target temperature + static void set_build_platform_temperature(unsigned extruder_id, unsigned temperature) { assert(extruder_id < machine.extruder_count); @@ -594,7 +619,7 @@ static void set_build_platform_temperature(unsigned extruder_id, unsigned temper if(write_16(temperature) == EOF) exit(1); } -// 137 - Enable/disable axes steppers +// 137 - Enable / Disable axes steppers static void set_steppers(unsigned axes, unsigned state) { @@ -613,7 +638,7 @@ static void set_steppers(unsigned axes, unsigned state) static void queue_absolute_point() { long longestDDA = get_longest_dda(); - Point5d steps = mm_to_steps(&workTarget, &excess); + Point5d steps = mm_to_steps(&targetPosition, &excess); if(write_8(139) == EOF) exit(1); @@ -634,16 +659,13 @@ static void queue_absolute_point() // uint32: Feedrate, in microseconds between steps on the max delta. (DDA) if(write_32((int)longestDDA) == EOF) exit(1); - - currentPosition = machineTarget; - positionKnown = 1; } // 140 - Set extended position static void set_position() { - Point5d steps = mm_to_steps(&workTarget, &excess); + Point5d steps = mm_to_steps(¤tPosition, NULL); if(write_8(140) == EOF) exit(1); // int32: X position, in steps @@ -719,9 +741,43 @@ static void set_pot_value(unsigned axis, unsigned value) } // 146 - Set RGB LED value + +static void set_LED(unsigned red, unsigned green, unsigned blue, unsigned blink) +{ + if(write_8(146) == EOF) exit(1); + + // uint8: red value (all pix are 0-255) + if(write_8(red) == EOF) exit(1); + + // uint8: green + if(write_8(green) == EOF) exit(1); + + // uint8: blue + if(write_8(blue) == EOF) exit(1); + + // uint8: blink rate (0-255 valid) + if(write_8(blink) == EOF) exit(1); + + // uint8: 0 (reserved for future use) + if(write_8(0) == EOF) exit(1); +} // 147 - Set Beep - + +static void set_beep(unsigned frequency, unsigned milliseconds) +{ + if(write_8(147) == EOF) exit(1); + + // uint16: frequency + if(write_16(frequency) == EOF) exit(1); + + // uint16: buzz length in ms + if(write_16(milliseconds) == EOF) exit(1); + + // uint8: 0 (reserved for future use) + if(write_8(0) == EOF) exit(1); +} + // 148 - Pause for button // 149 - Display message to LCD @@ -836,10 +892,13 @@ static void end_build() // 155 - Queue extended point x3g +// IMPORTANT: this command updates the parser state + static void queue_point(double feedrate) { Point5d deltaMM; Point5d deltaSteps; + Point5d target = targetPosition; // Because we don't know our previous position, we can't calculate the feedrate or // distance correctly, so we use an unaccelerated command with a fixed DDA @@ -850,7 +909,7 @@ static void queue_point(double feedrate) // compute the relative distance traveled along each axis and convert to steps if(command.flag & X_IS_SET) { - deltaMM.x = machineTarget.x - currentPosition.x; + deltaMM.x = targetPosition.x - currentPosition.x; deltaSteps.x = round(fabs(deltaMM.x) * machine.x.steps_per_mm); } else { @@ -859,7 +918,7 @@ static void queue_point(double feedrate) } if(command.flag & Y_IS_SET) { - deltaMM.y = machineTarget.y - currentPosition.y; + deltaMM.y = targetPosition.y - currentPosition.y; deltaSteps.y = round(fabs(deltaMM.y) * machine.y.steps_per_mm); } else { @@ -868,7 +927,7 @@ static void queue_point(double feedrate) } if(command.flag & Z_IS_SET) { - deltaMM.z = machineTarget.z - currentPosition.z; + deltaMM.z = targetPosition.z - currentPosition.z; deltaSteps.z = round(fabs(deltaMM.z) * machine.z.steps_per_mm); } else { @@ -877,7 +936,7 @@ static void queue_point(double feedrate) } if(command.flag & A_IS_SET) { - deltaMM.a = workTarget.a - currentPosition.a; + deltaMM.a = targetPosition.a - currentPosition.a; deltaSteps.a = round(fabs(deltaMM.a) * machine.a.steps_per_mm); } else { @@ -886,7 +945,7 @@ static void queue_point(double feedrate) } if(command.flag & B_IS_SET) { - deltaMM.b = workTarget.b - currentPosition.b; + deltaMM.b = targetPosition.b - currentPosition.b; deltaSteps.b = round(fabs(deltaMM.b) * machine.b.steps_per_mm); } else { @@ -898,8 +957,8 @@ static void queue_point(double feedrate) if(magnitude(command.flag, &deltaSteps) > 0) { double distance = magnitude(command.flag & XYZ_BIT_MASK, &deltaMM); - workTarget.a = -deltaMM.a; - workTarget.b = -deltaMM.b; + target.a = -deltaMM.a; + target.b = -deltaMM.b; deltaMM.x = fabs(deltaMM.x); deltaMM.y = fabs(deltaMM.y); @@ -933,8 +992,8 @@ static void queue_point(double feedrate) double mmPerRevolution = machine.a.motor_steps * (1 / machine.a.steps_per_mm); // set distance deltaMM.a = numRevolutions * mmPerRevolution; - deltaSteps.a = round(fabs(workTarget.a - currentPosition.a) * machine.a.steps_per_mm); - workTarget.a = -deltaMM.a; + deltaSteps.a = round(fabs(targetPosition.a - currentPosition.a) * machine.a.steps_per_mm); + target.a = -deltaMM.a; } } if(deltaMM.b == 0.0) { @@ -945,12 +1004,12 @@ static void queue_point(double feedrate) double mmPerRevolution = machine.b.motor_steps * (1 / machine.b.steps_per_mm); // set distance deltaMM.b = numRevolutions * mmPerRevolution; - deltaSteps.b = round(fabs(workTarget.b - currentPosition.b) * machine.b.steps_per_mm); - workTarget.b = -deltaMM.b; + deltaSteps.b = round(fabs(targetPosition.b - currentPosition.b) * machine.b.steps_per_mm); + target.b = -deltaMM.b; } } - Point5d steps = mm_to_steps(&workTarget, &excess); + Point5d steps = mm_to_steps(&target, &excess); double usec = (60 * 1000 * 1000 * minutes); @@ -987,8 +1046,6 @@ static void queue_point(double feedrate) // uint16: feedrate in mm/s, multiplied by 64 to assist fixed point calculation on the bot if(write_16((unsigned)(feedrate * 64.0)) == EOF) exit(1); - - currentPosition = machineTarget; } } @@ -1358,30 +1415,30 @@ int main(int argc, char * argv[]) } } - // CALCULATE TARGET POINT + // CALCULATE TARGET POSITION // x if(command.flag & X_IS_SET) { - machineTarget.x = isRelative ? (currentPosition.x + command.x) : command.x; + targetPosition.x = isRelative ? (currentPosition.x + command.x) : command.x; } else { - machineTarget.x = currentPosition.x; + targetPosition.x = currentPosition.x; } // y if(command.flag & Y_IS_SET) { - machineTarget.y = isRelative ? (currentPosition.y + command.y) : command.y; + targetPosition.y = isRelative ? (currentPosition.y + command.y) : command.y; } else { - machineTarget.y = currentPosition.y; + targetPosition.y = currentPosition.y; } // z if(command.flag & Z_IS_SET) { - machineTarget.z = isRelative ? (currentPosition.z + command.z) : command.z; + targetPosition.z = isRelative ? (currentPosition.z + command.z) : command.z; } else { - machineTarget.z = currentPosition.z; + targetPosition.z = currentPosition.z; } // we treat e as short hand for a or b being set @@ -1389,29 +1446,29 @@ int main(int argc, char * argv[]) if(command.flag & E_IS_SET) { if(currentExtruder == 0) { // a = e - machineTarget.a = isRelative ? (currentPosition.a + command.e) : command.e; + targetPosition.a = isRelative ? (currentPosition.a + command.e) : command.e; command.flag |= A_IS_SET; command.a = command.e; // b if(command.flag & B_IS_SET) { - machineTarget.b = isRelative ? (currentPosition.b + command.b) : command.b; + targetPosition.b = isRelative ? (currentPosition.b + command.b) : command.b; } else { - machineTarget.b = currentPosition.b; + targetPosition.b = currentPosition.b; } } else { // a if(command.flag & A_IS_SET) { - machineTarget.a = isRelative ? (currentPosition.a + command.a) : command.a; + targetPosition.a = isRelative ? (currentPosition.a + command.a) : command.a; } else { - machineTarget.a = currentPosition.a; + targetPosition.a = currentPosition.a; } // b = e - machineTarget.b = isRelative ? (currentPosition.b + command.e) : command.e; + targetPosition.b = isRelative ? (currentPosition.b + command.e) : command.e; command.flag |= B_IS_SET; command.b = command.e; } @@ -1419,17 +1476,17 @@ int main(int argc, char * argv[]) else { // a if(command.flag & A_IS_SET) { - machineTarget.a = isRelative ? (currentPosition.a + command.a) : command.a; + targetPosition.a = isRelative ? (currentPosition.a + command.a) : command.a; } else { - machineTarget.a = currentPosition.a; + targetPosition.a = currentPosition.a; } // b if(command.flag & B_IS_SET) { - machineTarget.b = isRelative ? (currentPosition.b + command.b) : command.b; + targetPosition.b = isRelative ? (currentPosition.b + command.b) : command.b; } else { - machineTarget.b = currentPosition.b; + targetPosition.b = currentPosition.b; } } @@ -1438,13 +1495,11 @@ int main(int argc, char * argv[]) currentFeedrate = command.f; } - // CALCULATE WORK OFFSET + // CALCULATE OFFSET - workTarget.x = machineTarget.x + offset[currentOffset].x; - workTarget.y = machineTarget.y + offset[currentOffset].y; - workTarget.z = machineTarget.z + offset[currentOffset].z; - workTarget.a = machineTarget.a; - workTarget.b = machineTarget.b; + if(command.flag & X_IS_SET) targetPosition.x += offset[currentOffset].x; + if(command.flag & Y_IS_SET) targetPosition.y += offset[currentOffset].y; + if(command.flag & Z_IS_SET) targetPosition.z += offset[currentOffset].z; // INTERPRET COMMAND @@ -1455,12 +1510,14 @@ int main(int argc, char * argv[]) case 0: if(command.flag & F_IS_SET) { queue_point(currentFeedrate); + currentPosition = targetPosition; + positionKnown = 1; } else { Point3d delta; - if(command.flag & X_IS_SET) delta.x = fabs(workTarget.x - currentPosition.x); - if(command.flag & Y_IS_SET) delta.y = fabs(workTarget.y - currentPosition.y); - if(command.flag & Z_IS_SET) delta.z = fabs(workTarget.z - currentPosition.z); + if(command.flag & X_IS_SET) delta.x = fabs(targetPosition.x - currentPosition.x); + if(command.flag & Y_IS_SET) delta.y = fabs(targetPosition.y - currentPosition.y); + if(command.flag & Z_IS_SET) delta.z = fabs(targetPosition.z - currentPosition.z); double length = magnitude(command.flag & XYZ_BIT_MASK, (Ptr5d)&delta); double candidate, feedrate = DBL_MAX; if(command.flag & X_IS_SET && delta.x != 0.0) { @@ -1482,12 +1539,16 @@ int main(int argc, char * argv[]) feedrate = machine.x.max_feedrate; } queue_point(feedrate); + currentPosition = targetPosition; + positionKnown = 1; } break; // G1 - Coordinated Motion case 1: queue_point(currentFeedrate); + currentPosition = targetPosition; + positionKnown = 1; break; // G2 - Clockwise Arc @@ -1508,15 +1569,21 @@ int main(int argc, char * argv[]) case 10: if(command.flag & P_IS_SET && command.p >= 1.0 && command.p <= 6.0) { i = (int)command.p; - if(command.flag & X_IS_SET) offset[i].x = machineTarget.x; - if(command.flag & Y_IS_SET) offset[i].y = machineTarget.y; - if(command.flag & Z_IS_SET) offset[i].z = machineTarget.z; + if(command.flag & X_IS_SET) offset[i].x = command.x; + if(command.flag & Y_IS_SET) offset[i].y = command.y; + if(command.flag & Z_IS_SET) offset[i].z = command.z; } else { fprintf(stderr, "(line %u) Syntax Error: G10 is missing coordiante system, use Pn where n is 1-6" EOL, line_number); exit(1); } break; + + // G21 - Use Milimeters as Units (IGNORED) + // G71 - Use Milimeters as Units (IGNORED) + case 21: + case 71: + break; // G53 - Set absolute coordinate system case 53: @@ -1570,14 +1637,18 @@ int main(int argc, char * argv[]) break; // G92 - Define current position on axes - case 92: + case 92: { + if(command.flag & X_IS_SET) currentPosition.x = command.x; + if(command.flag & Y_IS_SET) currentPosition.y = command.y; + if(command.flag & Z_IS_SET) currentPosition.z = command.z; + if(command.flag & A_IS_SET) currentPosition.a = command.a; + if(command.flag & B_IS_SET) currentPosition.b = command.b; + // check if we know where we are + int mask = machine.extruder_count == 1 ? (XYZ_BIT_MASK | A_IS_SET) : AXES_BIT_MASK; + if((command.flag & mask) == mask) positionKnown = 1; set_position(); - if(command.flag & X_IS_SET) currentPosition.x = machineTarget.x; - if(command.flag & Y_IS_SET) currentPosition.y = machineTarget.y; - if(command.flag & Z_IS_SET) currentPosition.z = machineTarget.z; - if(command.flag & A_IS_SET) currentPosition.a = machineTarget.a; - if(command.flag & B_IS_SET) currentPosition.b = machineTarget.b; break; + } // G130 - Set given axes potentiometer Value case 130: @@ -1630,6 +1701,10 @@ int main(int argc, char * argv[]) } if(extruder_id < machine.extruder_count) { if(currentExtruder != extruder_id) { + // check for active G10 offset + if(currentOffset == currentExtruder + 1) { + currentOffset = extruder_id + 1; + } currentExtruder = extruder_id; change_extruder(extruder_id); } @@ -1670,18 +1745,18 @@ int main(int argc, char * argv[]) case 71: if(command.flag & COMMENT_IS_SET) { if(command.flag & P_IS_SET) { - display_message(command.comment, command.p, 0); + display_message(command.comment, command.p, 1); } else { - display_message(command.comment, 0, 0); + display_message(command.comment, 0, 1); } } else { if(command.flag & P_IS_SET) { - display_message("Press M to continue", command.p, 0); + display_message("Press M to continue", command.p, 1); } else { - display_message("Press M to continue", 0, 0); + display_message("Press M to continue", 0, 1); } } break; @@ -1732,6 +1807,9 @@ int main(int argc, char * argv[]) unsigned extruder_id = (unsigned)command.t; if(extruder_id < machine.extruder_count) { set_steppers(extruder_id == 0 ? A_IS_SET : B_IS_SET, 1); + tool[extruder_id].motor_enabled = 1; + // update the direction + tool[extruder_id].rpm = command.m == 101 ? fabs(tool[extruder_id].rpm) : -fabs(tool[extruder_id].rpm); } else { fprintf(stderr, "(line %u) Semantic Warning: M%u cannot select non-existant extruder T%u" EOL, line_number, command.m, extruder_id); @@ -1740,6 +1818,9 @@ int main(int argc, char * argv[]) } else { set_steppers(currentExtruder == 0 ? A_IS_SET : B_IS_SET, 1); + tool[currentExtruder].motor_enabled = 1; + // update the direction + tool[currentExtruder].rpm = command.m == 101 ? fabs(tool[currentExtruder].rpm) : -fabs(tool[currentExtruder].rpm); } break; @@ -1749,6 +1830,7 @@ int main(int argc, char * argv[]) unsigned extruder_id = (unsigned)command.t; if(extruder_id < machine.extruder_count) { set_steppers(extruder_id == 0 ? A_IS_SET : B_IS_SET, 0); + tool[extruder_id].motor_enabled = 0; } else { fprintf(stderr, "(line %u) Semantic Warning: M103 cannot select non-existant extruder T%u" EOL, line_number, extruder_id); @@ -1757,6 +1839,7 @@ int main(int argc, char * argv[]) } else { set_steppers(currentExtruder == 0 ? A_IS_SET : B_IS_SET, 0); + tool[currentExtruder].motor_enabled = 0; } break; @@ -1818,6 +1901,28 @@ int main(int argc, char * argv[]) } break; + // M108 - set extruder motor 5D 'simulated' RPM + case 108: + if(command.flag & R_IS_SET) { + if(command.flag & T_IS_SET) { + unsigned extruder_id = (unsigned)command.t; + if(extruder_id < machine.extruder_count) { + tool[extruder_id].rpm = command.r; + } + else { + fprintf(stderr, "(line %u) Semantic Warning: M108 cannot select non-existant extruder T%u" EOL, line_number, extruder_id); + } + } + else { + tool[currentExtruder].rpm = command.r; + } + } + else { + fprintf(stderr, "(line %u) Syntax Error: M108 is missing motor RPM, use Rn where n is 0-5" EOL, line_number); + exit(1); + } + break; + // M109 - Set Build Platform Temperature // M140 - Set Build Platform Temperature (skeinforge) case 109: @@ -1879,22 +1984,6 @@ int main(int argc, char * argv[]) set_valve(currentExtruder, 0); } break; - - // M137 - Enable axes steppers - case 137: - break; - - // M138 - Disable axes steppers - case 138: - break; - - // M146 - Set RGB LED value - case 146: - break; - - // M147 - Set Beep - case 147: - break; // M131 - Store Current Position to EEPROM case 131: @@ -1921,6 +2010,56 @@ int main(int argc, char * argv[]) } break; + // M137 - Enable axes steppers + case 137: + if(command.flag & AXES_BIT_MASK) { + set_steppers(command.flag & AXES_BIT_MASK, 1); + if(command.flag & A_IS_SET) tool[0].motor_enabled = 1; + if(command.flag & B_IS_SET) tool[1].motor_enabled = 1; + } + else { + fprintf(stderr, "(line %u) Syntax Error: M137 is missing axes, use X Y Z A B" EOL, line_number); + exit(1); + } + break; + + // M138 - Disable axes steppers + case 138: + if(command.flag & AXES_BIT_MASK) { + set_steppers(command.flag & AXES_BIT_MASK, 0); + if(command.flag & A_IS_SET) tool[0].motor_enabled = 0; + if(command.flag & B_IS_SET) tool[1].motor_enabled = 0; + } + else { + fprintf(stderr, "(line %u) Syntax Error: M138 is missing axes, use X Y Z A B" EOL, line_number); + exit(1); + } + break; + + // M146 - Set RGB LED value (RLS - P) + case 146: { + unsigned red = 0; + if(command.flag & R_IS_SET) red = (unsigned)command.r & 0xFF; + unsigned green = 0; + if(command.flag & L_IS_SET) green = (unsigned)command.l & 0xFF; + unsigned blue = 0; + if(command.flag & S_IS_SET) blue = (unsigned)command.s & 0xFF; + unsigned blink = 0; + if(command.flag & P_IS_SET) blink = (unsigned)command.p & 0xFF; + set_LED(red, green, blue, blink); + break; + } + + // M147 - Set Beep (SP) + case 147: { + unsigned frequency = 6000; + if(command.flag & S_IS_SET) frequency = (unsigned)command.s & 0xFFFF; + unsigned milliseconds = 100; + if(command.flag & P_IS_SET) milliseconds = (unsigned)command.p & 0xFFFF; + set_beep(frequency, milliseconds); + break; + } + // M320 - Acceleration on for subsequent instructions case 320: set_acceleration(1); @@ -1934,23 +2073,31 @@ int main(int argc, char * argv[]) fprintf(stderr, "(line %u) Syntax Warning: unsupported mcode command 'M%u'" EOL, line_number, command.m); } } - else if(command.flag & T_IS_SET) { - unsigned extruder_id = (unsigned)command.t; - if(extruder_id < machine.extruder_count) { - if(currentExtruder != extruder_id) { - currentExtruder = extruder_id; - change_extruder(extruder_id); - command_line++; + else { + if(command.flag & T_IS_SET) { + unsigned extruder_id = (unsigned)command.t; + if(extruder_id < machine.extruder_count) { + if(currentExtruder != extruder_id) { + command_line++; + // check for active G10 offset + if(currentOffset == currentExtruder + 1) { + currentOffset = extruder_id + 1; + } + currentExtruder = extruder_id; + change_extruder(extruder_id); + } + } + else { + fprintf(stderr, "(line %u) Semantic Warning: T%u cannot select non-existant extruder" EOL, line_number, extruder_id); } } - else { - fprintf(stderr, "(line %u) Semantic Warning: T%u cannot select non-existant extruder" EOL, line_number, extruder_id); + if(command.flag & AXES_BIT_MASK) { + command_line++; + queue_point(currentFeedrate); + currentPosition = targetPosition; + positionKnown = 1; } } - else if(command.flag & AXES_BIT_MASK) { - command_line++; - queue_point(currentFeedrate); - } // update progress if(filesize && build_percent && command_line) { unsigned percent = (unsigned)round(100.0 * (double)ftell(in) / (double)filesize); diff --git a/gpx.h b/gpx.h index 43a5904..748a8d0 100644 --- a/gpx.h +++ b/gpx.h @@ -142,6 +142,7 @@ typedef struct tMachine { Axis z; Extruder a; Extruder b; + double filament_diameter; unsigned extruder_count; unsigned timeout; } Machine; diff --git a/lint.gcode b/lint.gcode index 52f597e..f5525ca 100644 --- a/lint.gcode +++ b/lint.gcode @@ -19,6 +19,7 @@ ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software Foundation, ; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ; PREFIX M70 (M103 - extruder off) @@ -58,16 +59,11 @@ G10 P4 X40 Y40 Z40 G10 P5 X50 Y50 Z50 G10 P6 X60 Y60 Z60 -; G20 - Use Inches as Units -; G70 - Use Inches as Units -;M70 (G20 - imperial units) -;G20 -;G1 X1 Y1 Z1 E0.197 - ; G21 - Use Milimeters as Units ; G71 - Use Milimeters as Units -;M70 (G21 - metric units) -;G21 +M70 (G21 - metric units) +G21 +G71 ; G28 - Home given axes to maximum M70 (G28 - home to max) @@ -147,18 +143,6 @@ M70 (M104 - set temp) M104 S230 T0 M104 S230 T1 -; M3 - Spindle On - Clockwise -;M70 (M3 - spindle on) -;M3 - -; M4 - Spindle On - Counter Clockwise -;M70 (M4 - spindle on) -;M4 - -; M5 - Spindle Off -;M70 (M5 - spindle off) -;M5 - ; M6 - Wait for toolhead to come up to reach (or exceed) temperature M70 (M6 - wait for tool) M6 T0 @@ -188,32 +172,6 @@ M6 M70 (T1 - tool change) T1 -; M13 - Spindle CW and Coolant A On -;M70 (M13 - spindle +cool) -;M13 - -; M14 - Spindle CCW and Coolant A On -;M70 (M14 - spindle +cool) -;M14 - -; M17 - Enable Motor(s) -;M70 (M17 - enable motor) -;M17 - -; M18 - Disable Motor(s) -;M70 (M18 - disable motor) -;M18 - -; M21 - Open Collet -;M70 (M21 - open collet) -;M21 - -; M22 - Close Collet -;M70 (M22 - close collet) -;M22 - -; M30 - Program Rewind - ; M70 - Display Message On Machine M70 P20 (This is a really large message that will take up quite a few rows to display on the makerbot LCD screen) @@ -232,34 +190,85 @@ M70 (M73 - progress) M73 P10 (build progress) ; M101 - Turn Extruder On, Forward +M70 (M101 - extruder on-f) +M101 T1 +M101 T0 + ; M102 - Turn Extruder On, Reverse +M70 (M102 - extruder on-r) +M102 T1 +M102 T0 + ; M103 - Turn Extruder Off +M70 (M103 - extruder off) +M103 T1 +M103 T0 + ; M104 - Set Temperature -; M105 - Get Temperature -; M106 - Turn Automated Build Platform (or the Fan, on older models) On -; M107 - Turn Automated Build Platform (or the Fan, on older models) Off -; M108 - Set Extruder's Max Speed (R = RPM, P = PWM) +M70 (M104 - set temp) +M104 T1 S240 +M104 T0 S230 + +; M108 - Set Extruder's Max Speed (R = RPM) +M70 (M108 - set rpm) +M108 T1 R5.0 +M108 T0 R3.0 + ; M109 - Set Build Platform Temperature -; M110 - Set Build Chamber Temperature +M70 (M109 - hbp temp) +M109 S110 + ; M126 - Valve Open +M70 (M126 - blower on) +M126 + ; M127 - Valve Close -; M128 - "Get Position +M70 (M127 - blower off) +M127 + ; M131 - Store Current Position to EEPROM +M70 (M131 - store EEPROM) +M131 X Y Z A B + ; M132 - Load Current Position from EEPROM +M70 (M132 - load EEPROM) +M132 X Y Z A B + +; M137 - Enable axes steppers +M70 (M137 - steppers on) +M132 X Y Z A B + +; M138 - Disable axes steppers +M70 (M138 - steppers on) +M138 X Y Z A B + +; M146 - Set RGB LED value +M70 (M146 - set LED) +M146 R255 L0 S0 P0 + +; M147 - Set Beep +M70 (M147 - set beep) +M147 S4000 P100 + ; M140 - Set Build Platform Temperature -; M141 - Set Chamber Temperature (Ignored) -; M142 - Set Chamber Holding Pressure (Ignored) -; M200 - Reset driver -; M300 - Set Servo 1 Position -; M301 - Set Servo 2 Position -; M310 - Start data capture -; M311 - Stop data capture -; M312 - Log a note to the data capture store +M70 (M140 - hbp temp) +M140 T0 S100 + ; M320 - Acceleration on for subsequent instructions +M70 (M320 - acc on) +M320 + ; M321 - Acceleration off for subsequent instructions +M70 (M21 - acc off) +M321 + +; T1 - Set Current Tool 1 +M70 (T1 - set tool) +T1 ; T0 - Set Current Tool 0 -; T1 - Set Current Tool 1 +M70 (T0 - set tool) +T0 ;POSTFIX M70 (M73 - end build) diff --git a/s3g-decompiler.py b/s3g-decompiler.py new file mode 100644 index 0000000..598d4c2 --- /dev/null +++ b/s3g-decompiler.py @@ -0,0 +1,179 @@ +#!/usr/bin/python +# +# s3g-decompiler.py +# +# Created by Adam Mayer on Jan 25 2011. +# +# Originally from ReplicatorG sources /src/replicatorg/scripts +# which are part of the ReplicatorG project - http://www.replicat.org +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import struct +import sys + +toolCommandTable = { + 1: ("", "[1] init: Initialize firmware to boot state"), + 3: ("