Teacup_Firmware/mendel/gcode.c

192 lines
3.9 KiB
C

#include "gcode.h"
#include <string.h>
#include "machine.h"
#include "dda.h"
extern uint8_t option_bitfield;
#define PI 3.1415926535
/*
utility functions
*/
uint8_t indexof(uint8_t c, char *string) {
uint8_t i;
for (i = 0;string[i];i++) {
if (c == string[i])
return i;
}
return 255;
}
float manexp_to_float(uint32_t mantissa, uint8_t exp) {
float v = mantissa;
if (exp == 2)
v /= 10;
else if (exp == 3)
v /= 100;
else if (exp == 4)
v /= 1000;
else if (exp == 5)
v /= 10000;
else if (exp == 6)
v /= 100000;
return v;
}
/*
public functions
*/
void scan_char(uint8_t c) {
static uint8_t last_field = 0;
static uint32_t mantissa = 0;
static uint8_t exp = 0;
static GCODE_COMMAND next_target = { 0, 0, 0, 0, { 0, 0, 0, 0, 0 } };
// uppercase
if (c >= 'a' && c <= 'z')
c &= ~32;
// process field
if (indexof(c, "GMXYZEF\n") != 255) {
if (last_field) {
switch (last_field) {
case 'G':
next_target.G = mantissa;
break;
case 'M':
next_target.M = mantissa;
break;
case 'X':
next_target.target.X = manexp_to_float(mantissa, exp) * STEPS_PER_MM_X;
break;
case 'Y':
next_target.target.Y = manexp_to_float(mantissa, exp) * STEPS_PER_MM_Y;
break;
case 'Z':
next_target.target.Z = manexp_to_float(mantissa, exp) * STEPS_PER_MM_Z;
break;
case 'E':
next_target.target.E = manexp_to_float(mantissa, exp) * STEPS_PER_MM_E;
break;
case 'F':
// TODO: calculate end speed in microseconds per step from millimeters per minute
// MM = sqrt(X^2 + Y^2)
// STEPS = max(X * STEPS_PER_MM_X, Y * STEPS_PER_MM_Y)
// DURATION = MM / MM_PER_MIN * 60 SEC_PER_MIN * 1000000 US_PER_SEC
// US/STEP = DURATION / STEPS
// intF = sqrt(X^2 + Y^2) / max(X * STEPS_PER_MM_X, Y * STEPS_PER_MM_Y)
next_target.target.F = manexp_to_float(mantissa, exp) * STEPS_PER_MM_F;
break;
}
mantissa = 0;
exp = 0;
}
last_field = c;
switch (c) {
case 'G':
next_target.seen |= SEEN_G;
break;
case 'M':
next_target.seen |= SEEN_M;
break;
case 'X':
next_target.seen |= SEEN_X;
break;
case 'Y':
next_target.seen |= SEEN_Y;
break;
case 'Z':
next_target.seen |= SEEN_Z;
break;
case 'E':
next_target.seen |= SEEN_E;
break;
case 'F':
next_target.seen |= SEEN_F;
break;
case '\n':
// process
process_gcode_command(&next_target);
// save options
option_bitfield = next_target.option;
// reset variables
last_field = 0;
memset(&next_target, 0, sizeof(GCODE_COMMAND));
next_target.option = option_bitfield;
break;
}
}
// process digits
else if (c == '-')
exp |= 0x80;
else if ((c == '.') && ((exp & 0x7F) == 0))
exp |= 1;
else if (c >= '0' && c <= '9') {
mantissa = ((mantissa << 3) + (mantissa << 1)) + (c - '0');
if (exp & 0x7F)
exp++;
}
}
void process_gcode_command(GCODE_COMMAND *gcmd) {
uint8_t do_move;
if (gcmd->seen & SEEN_G) {
switch (gcmd->G) {
// G0 - rapid, unsynchronised motion
case 0:
gcmd->option &= ~OPTION_SYNCHRONISE;
do_move = 1;
break;
// G30 - go home via point
case 30:
gcmd->option |= OPTION_HOME_WHEN_COMPLETE;
// G1 - synchronised motion
case 1:
gcmd->option |= OPTION_SYNCHRONISE;
do_move = 1;
break;
// G2 - Arc Clockwise
// G3 - Arc Counter-clockwise
// G4 - Dwell
// G20 - inches as units
// G21 - mm as units
// G28 - go home
case 28:
gcmd->option &= ~OPTION_SYNCHRONISE;
do_move = 1;
break;
// G90 - absolute positioning
case 90:
gcmd->option &= ~OPTION_RELATIVE;
break;
// G91 - relative positioning
case 91:
gcmd->option |= OPTION_RELATIVE;
break;
// G92 - set home
case 92:
break;
// TODO: spit an error
}
}
if (gcmd->seen & SEEN_M) {
switch (gcmd->M) {
// TODO: spit an error
}
}
if (do_move) {
dda_create(&gcmd->target, movebuffer);
}
}