mirror of https://github.com/vitalif/GPX
Alpha 0.1
All suppoted G and M codes are now implemented, and the output from the lint.gcode unit test has been compared to that of ReplicatorG to confirm equivilance.master
parent
17d5cbd2c7
commit
cc5b5aa561
|
@ -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 <me(at)henri.net>
|
||||
|
||||
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 <string.h>
|
||||
#if defined(_MSC_VER)
|
||||
# include <io.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAS_WIN_GUI
|
||||
|
||||
/* The windows gui version reports command line errors using MessageBox */
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#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 */
|
|
@ -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 <me(at)henri.net>
|
||||
|
||||
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 <getopt.h>
|
||||
#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_ */
|
335
gpx.c
335
gpx.c
|
@ -32,7 +32,12 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "getopt.h"
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#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);
|
||||
|
|
1
gpx.h
1
gpx.h
|
@ -142,6 +142,7 @@ typedef struct tMachine {
|
|||
Axis z;
|
||||
Extruder a;
|
||||
Extruder b;
|
||||
double filament_diameter;
|
||||
unsigned extruder_count;
|
||||
unsigned timeout;
|
||||
} Machine;
|
||||
|
|
131
lint.gcode
131
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)
|
||||
|
|
|
@ -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: ("<H", "[3] Extruder: set temperature = %i"),
|
||||
4: ("<B", "[4] Motor 1: set speed (PWM) = %i"),
|
||||
5: ("<B", "[5] Motor 2: set speed (PWM) = %i"),
|
||||
6: ("<I", "[6] Motor 1: set speed (RPM) = %i"),
|
||||
7: ("<I", "[7] Motor 2: set speed (RPM) = %i"),
|
||||
8: ("<I", "[8] Motor 1: set direction = %i"),
|
||||
9: ("<I", "[9] Motor 2: set direction = %i"),
|
||||
10: ("B", "[10] Motor 1: toggle = %d"),
|
||||
11: ("B", "[11] Motor 2: toggle = %d"),
|
||||
12: ("B", "[12] Fan: toggle = %d"),
|
||||
13: ("B", "[13] Valve: toggle = %d"),
|
||||
13: ("B", "[14] Servo 1: angle = %d"),
|
||||
13: ("B", "[15] Serve 2: angle = %d"),
|
||||
27: ("B", "[27] Automated build platform: toggle = %d"),
|
||||
31: ("<H", "[31] Build Platform: set temperature = %i"),
|
||||
}
|
||||
|
||||
def parseToolAction():
|
||||
global s3gFile
|
||||
packetStr = s3gFile.read(3)
|
||||
if len(packetStr) != 3:
|
||||
raise "Incomplete s3g file during tool command parse"
|
||||
(index,command,payload) = struct.unpack("<BBB",packetStr)
|
||||
contents = s3gFile.read(payload)
|
||||
if len(contents) != payload:
|
||||
raise "Incomplete s3g file: tool packet truncated"
|
||||
return (index,command,contents)
|
||||
|
||||
def printToolAction(tuple):
|
||||
print "\t[136] Tool %i:" % (tuple[0]),
|
||||
# command - tuple[1]
|
||||
# data - tuple[2]
|
||||
(parse, disp) = toolCommandTable[tuple[1]]
|
||||
if type(parse) == type(""):
|
||||
packetLen = struct.calcsize(parse)
|
||||
if len(tuple[2]) != packetLen:
|
||||
raise "Packet incomplete"
|
||||
parsed = struct.unpack(parse,tuple[2])
|
||||
else:
|
||||
parsed = parse()
|
||||
if type(disp) == type(""):
|
||||
print disp % parsed
|
||||
|
||||
def parseDisplayMessageAction():
|
||||
global s3gFile
|
||||
packetStr = s3gFile.read(4)
|
||||
if len(packetStr) < 4:
|
||||
raise "Incomplete s3g file during tool command parse"
|
||||
(options,offsetX,offsetY,timeout) = struct.unpack("<BBBB",packetStr)
|
||||
message = "";
|
||||
while True:
|
||||
c = s3gFile.read(1);
|
||||
if c == '\0':
|
||||
break;
|
||||
else:
|
||||
message += c;
|
||||
|
||||
return (options,offsetX,offsetY,timeout,message)
|
||||
|
||||
def parseBuildStartNotificationAction():
|
||||
global s3gFile
|
||||
packetStr = s3gFile.read(4)
|
||||
if len(packetStr) < 4:
|
||||
raise "Incomplete s3g file during tool command parse"
|
||||
(steps) = struct.unpack("<i",packetStr)
|
||||
buildName = "";
|
||||
while True:
|
||||
c = s3gFile.read(1);
|
||||
if c == '\0':
|
||||
break;
|
||||
else:
|
||||
buildName += c;
|
||||
|
||||
return (steps[0],buildName)
|
||||
|
||||
# Command table entries consist of:
|
||||
# * The key: the integer command code
|
||||
# * A tuple:
|
||||
# * idx 0: the python struct description of the rest of the data,
|
||||
# of a function that unpacks the remaining data from the
|
||||
# stream
|
||||
# * idx 1: either a format string that will take the tuple of unpacked
|
||||
# data, or a function that takes the tuple as input and returns
|
||||
# a string
|
||||
# REMINDER: all values are little-endian. Struct strings with multibyte
|
||||
# types should begin with "<".
|
||||
# For a refresher on Python struct syntax, see here:
|
||||
# http://docs.python.org/library/struct.html
|
||||
|
||||
commandTable = {
|
||||
129: ("<iiiI","\t[129] Absolute move to (%i,%i,%i) at DDA %i"),
|
||||
130: ("<iii","\t[130] Machine position set as (%i,%i,%i)"),
|
||||
131: ("<BIH","\t[131] Home minimum on %X, feedrate %i, timeout %i s"),
|
||||
132: ("<BIH","\t[132] Home maximum on %X, feedrate %i, timeout %i s"),
|
||||
133: ("<I","\t[133] Delay of %i us"),
|
||||
134: ("<B","\t[134] Switch to tool %i"),
|
||||
135: ("<BHH","\t[135] Wait for tool %i (%i ms between polls, %i s timeout"),
|
||||
136: (parseToolAction, printToolAction),
|
||||
137: ("<B", "\t[137] Enable/disable axes %X"),
|
||||
138: ("<H", "\t[138] User block on ID %i"),
|
||||
139: ("<iiiiiI","\t[139] Absolute move to (%i,%i,%i,%i,%i) at DDA %i"),
|
||||
140: ("<iiiii","\t[140] Extended Machine position set as (%i,%i,%i,%i,%i)"),
|
||||
141: ("<BHH","\t[141] Wait for platform %i (%i ms between polls, %i s timeout)"),
|
||||
142: ("<iiiiiIB","\t[142] Move to (%i,%i,%i,%i,%i) in %i us (relative: %X)"),
|
||||
143: ("<b","\t[143] Store home position for axes %d"),
|
||||
144: ("<b","\t[144] Recall home position for axes %d"),
|
||||
145: ("<BB","\t[145] Set pot axis %i to %i"),
|
||||
146: ("<BBBBB","\t[146] Set RGB led red %i, green %i, blue %i, blink rate %i, effect %i"),
|
||||
147: ("<HHB","\t[147] Set beep, frequency %i, length %i, effect %i"),
|
||||
148: ("<BHB","\t[148] Pause for button 0x%X, timeout %i s, timeout_bevavior %i"),
|
||||
149: (parseDisplayMessageAction, "\t[149] Display message, options 0x%X at %i,%i timeout %i\n %s"),
|
||||
150: ("<BB","\t[150] Set build percent %i%%, ignore %i"),
|
||||
151: ("<B","\t[151] Queue song %i"),
|
||||
152: ("<B","\t[152] Reset to factory, options 0x%X"),
|
||||
153: (parseBuildStartNotificationAction, "\t[153] Start build, steps %i: %s"),
|
||||
154: ("<B","\t[154] End build, flags 0x%X"),
|
||||
155: ("<iiiiiIBfh","\t[155] Move to (%i,%i,%i,%i,%i) dda_rate: %i (relative: %X) distance: %f feedrateX64: %i"),
|
||||
156: ("<B","\t[156] Set acceleration to %i"),
|
||||
157: ("<BBBIHHIIB","\t[157] Stream version %i.%i (%i %i %i %i %i %i %i)"),
|
||||
}
|
||||
|
||||
def parseNextCommand():
|
||||
"""Parse and handle the next command. Returns
|
||||
True for success, False on EOF, and raises an
|
||||
exception on corrupt data."""
|
||||
global s3gFile
|
||||
commandStr = s3gFile.read(1)
|
||||
if len(commandStr) == 0:
|
||||
print "EOF"
|
||||
return False
|
||||
sys.stdout.write(str(lineNumber) + ': ')
|
||||
(command) = struct.unpack("B",commandStr)
|
||||
(parse, disp) = commandTable[command[0]]
|
||||
if type(parse) == type(""):
|
||||
packetLen = struct.calcsize(parse)
|
||||
packetData = s3gFile.read(packetLen)
|
||||
if len(packetData) != packetLen:
|
||||
raise "Packet incomplete"
|
||||
parsed = struct.unpack(parse,packetData)
|
||||
else:
|
||||
parsed = parse()
|
||||
if type(disp) == type(""):
|
||||
print disp % parsed
|
||||
else:
|
||||
disp(parsed)
|
||||
return True
|
||||
|
||||
s3gFile = open(sys.argv[1],'rb')
|
||||
lineNumber = 0
|
||||
while parseNextCommand():
|
||||
lineNumber = lineNumber + 1
|
Loading…
Reference in New Issue