Skip to content

Instantly share code, notes, and snippets.

@epatel
Created January 2, 2023 17:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save epatel/69043e0be5b3caf550b9a8aa570f2093 to your computer and use it in GitHub Desktop.
Save epatel/69043e0be5b3caf550b9a8aa570f2093 to your computer and use it in GitHub Desktop.
/* Offset gcode tool (with speed change)
* -------------------------------------
*
* Compile: 'cc -o offset-gcode offset-gcode.c'
*
* Use: 'offset-gcode -x 12.0 -y 12.0 -f 1.2 file.gcode > newfile.gcode'
*
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static const char *program_name = "offset-gcode";
void print_usage() {
printf("Usage: %s [-x nn.nn] [-y nn.nn] [-f nn.nn] <filename>\n", program_name);
}
enum {
G1_X = 0x01,
G1_Y = 0x02,
G1_Z = 0x04,
G1_E = 0x08,
G1_F = 0x10
};
struct s_gmove {
int gcode;
int contains;
double x;
double y;
double z;
double e;
int f;
};
typedef struct s_gmove gmove;
void decode_gmove(gmove *data, char *line);
void output_gmove(gmove *data);
double offset_x = 0.0;
double offset_y = 0.0;
double factor_f = 1.0;
int main(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "hx:y:f:")) != -1) {
switch(opt) {
case 'x':
offset_x = atof(optarg);
break;
case 'y':
offset_y = atof(optarg);
break;
case 'f':
factor_f = atof(optarg);
break;
case 'h':
print_usage();
return 1;
}
}
if (optind >= argc) {
print_usage();
return 2;
}
FILE *fp = fopen(argv[optind], "rt");
if (fp == NULL) {
print_usage();
printf("Could not open: '%s'\n", argv[optind]);
return 2;
}
int active = 1;
char buffer[256];
while (fgets(buffer, 256, fp) == buffer) {
if (active &&
(!strncmp("G0 ", buffer, 3) ||
!strncmp("G1 ", buffer, 3))) {
gmove data;
decode_gmove(&data, buffer);
data.x += offset_x;
data.y += offset_y;
if (data.contains & (G1_X | G1_Y | G1_Z)) {
data.f *= factor_f;
}
output_gmove(&data);
} else if (!strncmp("G90", buffer, 3)) {
active = 1;
printf("%s", buffer);
} else if (!strncmp("G91", buffer, 3)) {
active = 0;
printf("%s", buffer);
} else {
printf("%s", buffer);
}
}
fclose(fp);
return 0;
}
void decode_gmove(gmove *data, char *line) {
data->contains = 0;
if (line[0] == 'G' &&
(line[1] == '0' || line[1] == '1')) {
char *x = strstr(line, "X");
char *y = strstr(line, "Y");
char *z = strstr(line, "Z");
char *e = strstr(line, "E");
char *f = strstr(line, "F");
data->gcode = line[1] - '0';
if (x) {
data->contains |= G1_X;
sscanf(x+1, "%lg", &data->x);
}
if (y) {
data->contains |= G1_Y;
sscanf(y+1, "%lg", &data->y);
}
if (z) {
data->contains |= G1_Z;
sscanf(z+1, "%lg", &data->z);
}
if (e) {
data->contains |= G1_E;
sscanf(e+1, "%lg", &data->e);
}
if (f) {
data->contains |= G1_F;
sscanf(f+1, "%d", &data->f);
}
}
}
void output_double(double value) {
char buffer[32];
sprintf(buffer, "%lg", value);
}
void output_gmove(gmove *data) {
printf("G%d", data->gcode);
if (data->contains & G1_X) {
printf(" X%lg", data->x);
}
if (data->contains & G1_Y) {
printf(" Y%lg", data->y);
}
if (data->contains & G1_Z) {
printf(" Z%lg", data->z);
}
if (data->contains & G1_E) {
printf(" E%lg", data->e);
}
if (data->contains & G1_F) {
printf(" F%d", data->f);
}
printf("\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment