2013-04-11 05:32:34 +04:00
//
// gpx.c
//
2013-04-17 16:24:05 +04:00
// Created by WHPThomas <me(at)henri(dot)net> on 1/04/13.
2013-04-11 05:32:34 +04:00
//
2013-04-16 20:01:26 +04:00
// Copyright (c) 2013 WHPThomas, All rights reserved.
2013-04-11 05:32:34 +04:00
//
2013-04-12 17:47:40 +04:00
// gpx references ReplicatorG sources from /src/replicatorg/drivers
2013-04-11 05:32:34 +04:00
// which are part of the ReplicatorG project - http://www.replicat.org
// Copyright (c) 2008 Zach Smith
// and Makerbot4GSailfish.java Copyright (C) 2012 Jetty / Dan Newman
//
// 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
# include <assert.h>
# include <ctype.h>
2014-01-08 22:20:51 +04:00
# include <errno.h>
2013-04-11 05:32:34 +04:00
# include <float.h>
# include <math.h>
# include <stdlib.h>
# include <strings.h>
2014-01-08 22:20:51 +04:00
# include <sys/types.h>
# include <sys/uio.h>
2013-11-24 17:04:49 +04:00
# include <unistd.h>
2013-04-11 05:32:34 +04:00
# include "gpx.h"
2013-04-20 20:40:13 +04:00
# define A 0
# define B 1
2014-01-08 22:20:51 +04:00
# define SHOW(FN) if(gpx->flag.logMessages) {FN;}
# define VERBOSE(FN) if(gpx->flag.verboseMode && gpx->flag.logMessages) {FN;}
# define CALL(FN) if((rval = FN) != SUCCESS) return rval
2013-11-24 17:04:49 +04:00
2013-04-11 05:32:34 +04:00
// Machine definitions
2013-04-18 19:01:37 +04:00
// Axis - max_feedrate, home_feedrate, steps_per_mm, endstop;
// Extruder - max_feedrate, steps_per_mm, motor_steps, has_heated_build_platform;
2013-04-11 05:32:34 +04:00
2013-04-28 19:08:43 +04:00
static Machine cupcake_G3 = {
{ 9600 , 500 , 11.767463 , ENDSTOP_IS_MIN } , // x axis
{ 9600 , 500 , 11.767463 , ENDSTOP_IS_MIN } , // y axis
{ 450 , 450 , 320 , ENDSTOP_IS_MIN } , // z axis
{ 7200 , 50.235478806907409 , 400 , 1 } , // a extruder
{ 7200 , 50.235478806907409 , 400 , 0 } , // b extruder
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-28 19:08:43 +04:00
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
1 ,
2013-04-28 19:08:43 +04:00
} ;
static Machine cupcake_G4 = {
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // x axis
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // y axis
{ 450 , 450 , 1280 , ENDSTOP_IS_MIN } , // z axis
{ 7200 , 50.235478806907409 , 400 , 1 } , // a extruder
{ 7200 , 50.235478806907409 , 400 , 0 } , // b extruder
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-28 19:08:43 +04:00
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
2 ,
2013-04-28 19:08:43 +04:00
} ;
static Machine cupcake_P4 = {
{ 9600 , 500 , 94.13970462 , ENDSTOP_IS_MIN } , // x axis
{ 9600 , 500 , 94.13970462 , ENDSTOP_IS_MIN } , // y axis
{ 450 , 450 , 2560 , ENDSTOP_IS_MIN } , // z axis
{ 7200 , 50.235478806907409 , 400 , 1 } , // a extruder
{ 7200 , 50.235478806907409 , 400 , 0 } , // b extruder
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-28 19:08:43 +04:00
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
3 ,
2013-04-28 19:08:43 +04:00
} ;
static Machine cupcake_PP = {
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // x axis
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // y axis
{ 450 , 450 , 1280 , ENDSTOP_IS_MIN } , // z axis
{ 7200 , 100.470957613814818 , 400 , 1 } , // a extruder
{ 7200 , 100.470957613814818 , 400 , 0 } , // b extruder
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-28 19:08:43 +04:00
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
4 ,
2013-04-28 19:08:43 +04:00
} ;
2013-04-29 22:26:36 +04:00
// Axis - max_feedrate, home_feedrate, steps_per_mm, endstop;
// Extruder - max_feedrate, steps_per_mm, motor_steps, has_heated_build_platform;
2013-04-28 19:08:43 +04:00
static Machine thing_o_matic_7 = {
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // x axis
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // y axis
{ 1000 , 500 , 200 , ENDSTOP_IS_MAX } , // z axis
{ 1600 , 50.235478806907409 , 1600 , 1 } , // a extruder
{ 1600 , 50.235478806907409 , 1600 , 0 } , // b extruder
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-28 19:08:43 +04:00
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
5 ,
2013-04-28 19:08:43 +04:00
} ;
static Machine thing_o_matic_7D = {
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // x axis
{ 9600 , 500 , 47.069852 , ENDSTOP_IS_MIN } , // y axis
{ 1000 , 500 , 200 , ENDSTOP_IS_MAX } , // z axis
{ 1600 , 50.235478806907409 , 1600 , 0 } , // a extruder
{ 1600 , 50.235478806907409 , 1600 , 1 } , // b extruder
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-28 19:08:43 +04:00
2 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
6 ,
2013-04-28 19:08:43 +04:00
} ;
2013-04-29 22:26:36 +04:00
// Axis - max_feedrate, home_feedrate, steps_per_mm, endstop;
// Extruder - max_feedrate, steps_per_mm, motor_steps, has_heated_build_platform;
2013-04-11 05:32:34 +04:00
static Machine replicator_1 = {
{ 18000 , 2500 , 94.139704 , ENDSTOP_IS_MAX } , // x axis
{ 18000 , 2500 , 94.139704 , ENDSTOP_IS_MAX } , // y axis
{ 1170 , 1100 , 400 , ENDSTOP_IS_MIN } , // z axis
{ 1600 , 96.275201870333662468889989185642 , 3200 , 1 } , // a extruder
{ 1600 , 96.275201870333662468889989185642 , 3200 , 0 } , // b extruder
2013-04-17 15:54:52 +04:00
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-13 03:30:11 +04:00
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
7 ,
2013-04-13 03:30:11 +04:00
} ;
static Machine replicator_1D = {
{ 18000 , 2500 , 94.139704 , ENDSTOP_IS_MAX } , // x axis
{ 18000 , 2500 , 94.139704 , ENDSTOP_IS_MAX } , // y axis
{ 1170 , 1100 , 400 , ENDSTOP_IS_MIN } , // z axis
{ 1600 , 96.275201870333662468889989185642 , 3200 , 1 } , // a extruder
{ 1600 , 96.275201870333662468889989185642 , 3200 , 0 } , // b extruder
2013-04-17 15:54:52 +04:00
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-13 03:30:11 +04:00
2 , // extruder count
2013-04-11 05:32:34 +04:00
20 , // timeout
2013-11-15 21:17:33 +04:00
8 ,
2013-04-11 05:32:34 +04:00
} ;
2013-04-29 22:26:36 +04:00
// Axis - max_feedrate, home_feedrate, steps_per_mm, endstop;
// Extruder - max_feedrate, steps_per_mm, motor_steps, has_heated_build_platform;
2013-04-11 05:32:34 +04:00
static Machine replicator_2 = {
{ 18000 , 2500 , 88.573186 , ENDSTOP_IS_MAX } , // x axis
{ 18000 , 2500 , 88.573186 , ENDSTOP_IS_MAX } , // y axis
{ 1170 , 1100 , 400 , ENDSTOP_IS_MIN } , // z axis
{ 1600 , 96.275201870333662468889989185642 , 3200 , 0 } , // a extruder
{ 1600 , 96.275201870333662468889989185642 , 3200 , 0 } , // b extruder
2013-04-17 15:54:52 +04:00
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.97 , // nominal packing density
0.4 , // nozzle diameter
2013-04-13 03:30:11 +04:00
1 , // extruder count
2013-04-11 05:32:34 +04:00
20 , // timeout
2013-11-15 21:17:33 +04:00
9 ,
2013-04-11 05:32:34 +04:00
} ;
2013-08-22 15:48:32 +04:00
static Machine replicator_2H = {
{ 18000 , 2500 , 88.573186 , ENDSTOP_IS_MAX } , // x axis
{ 18000 , 2500 , 88.573186 , ENDSTOP_IS_MAX } , // y axis
{ 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
0.97 , // nominal packing density
0.4 , // nozzle diameter
1 , // extruder count
20 , // timeout
2013-11-15 21:17:33 +04:00
10 ,
2013-08-22 15:48:32 +04:00
} ;
2013-04-11 05:32:34 +04:00
static Machine replicator_2X = {
{ 18000 , 2500 , 88.573186 , ENDSTOP_IS_MAX } , // x axis
{ 18000 , 2500 , 88.573186 , ENDSTOP_IS_MAX } , // y axis
{ 1170 , 1100 , 400 , ENDSTOP_IS_MIN } , // z axis
{ 1600 , 96.275201870333662468889989185642 , 3200 , 1 } , // a extruder
2013-04-28 19:08:43 +04:00
{ 1600 , 96.275201870333662468889989185642 , 3200 , 1 } , // b extruder
2013-04-17 15:54:52 +04:00
1.75 , // nominal filament diameter
2013-06-05 17:35:06 +04:00
0.85 , // nominal packing density
0.4 , // nozzle diameter
2013-04-13 03:30:11 +04:00
2 , // extruder count
2013-04-11 05:32:34 +04:00
20 , // timeout
2013-11-15 21:17:33 +04:00
11 ,
2013-04-11 05:32:34 +04:00
} ;
2013-11-24 17:04:49 +04:00
# define MACHINE_IS(m) strcasecmp(machine, m) == 0
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
int gpx_set_machine ( Gpx * gpx , char * machine )
{
// only load/clobber the on-board machine definition if the one specified is different
if ( MACHINE_IS ( " c3 " ) ) {
if ( gpx - > machine . type ! = 1 ) {
gpx - > machine = cupcake_G3 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Cupcake Gen3 XYZ, Mk5/6 + Gen4 Extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m c3 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " c4 " ) ) {
if ( gpx - > machine . type ! = 2 ) {
gpx - > machine = cupcake_G4 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Cupcake Gen4 XYZ, Mk5/6 + Gen4 Extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m c4 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " cp4 " ) ) {
if ( gpx - > machine . type ! = 3 ) {
gpx - > machine = cupcake_P4 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Cupcake Pololu XYZ, Mk5/6 + Gen4 Extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m cp4 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " cpp " ) ) {
if ( gpx - > machine . type ! = 4 ) {
gpx - > machine = cupcake_PP ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Cupcake Pololu XYZ, Mk5/6 + Pololu Extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m cpp " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " t6 " ) ) {
if ( gpx - > machine . type ! = 5 ) {
gpx - > machine = thing_o_matic_7 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: TOM Mk6 - single extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m t6 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " t7 " ) ) {
if ( gpx - > machine . type ! = 5 ) {
gpx - > machine = thing_o_matic_7 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: TOM Mk7 - single extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m t7 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " t7d " ) ) {
if ( gpx - > machine . type ! = 6 ) {
gpx - > machine = thing_o_matic_7D ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: TOM Mk7 - dual extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m t7d " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " r1 " ) ) {
if ( gpx - > machine . type ! = 7 ) {
gpx - > machine = replicator_1 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Replicator 1 - single extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m r1 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " r1d " ) ) {
if ( gpx - > machine . type ! = 8 ) {
gpx - > machine = replicator_1D ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Replicator 1 - dual extruder " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m r1d " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " r2 " ) ) {
if ( gpx - > machine . type ! = 9 ) {
gpx - > machine = replicator_2 ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Replicator 2 " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m r2 " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( MACHINE_IS ( " r2h " ) ) {
if ( gpx - > machine . type ! = 10 ) {
gpx - > machine = replicator_2H ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Replicator 2 with HBP " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m r2h " EOL , gpx - > log ) ) ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
}
else if ( MACHINE_IS ( " r2x " ) ) {
if ( gpx - > machine . type ! = 11 ) {
gpx - > machine = replicator_2X ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( " Loading machine definition: Replicator 2X " EOL , gpx - > log ) ) ;
}
else {
VERBOSE ( fputs ( " Ignoring duplicate machine definition: -m r2x " EOL , gpx - > log ) ) ;
2013-04-25 15:46:44 +04:00
}
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
return ERROR ;
2013-11-24 17:04:49 +04:00
}
2014-01-08 22:20:51 +04:00
// update known position mask
gpx - > axis . mask = gpx - > machine . extruder_count = = 1 ? ( XYZ_BIT_MASK | A_IS_SET ) : AXES_BIT_MASK ; ;
return SUCCESS ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
// PRIVATE FUNCTION PROTOTYPES
static double get_home_feedrate ( Gpx * gpx , int flag ) ;
static int pause_at_zpos ( Gpx * gpx , float z_positon ) ;
2013-04-16 20:01:26 +04:00
// initialization of global variables
2013-11-24 17:04:49 +04:00
void gpx_initialize ( Gpx * gpx , int firstTime )
2013-04-12 17:47:40 +04:00
{
int i ;
2013-11-24 17:04:49 +04:00
gpx - > buffer . ptr = gpx - > buffer . out ;
2013-04-12 17:47:40 +04:00
// we default to using pipes
2013-11-24 17:04:49 +04:00
// initialise machine
if ( firstTime ) gpx - > machine = replicator_2 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
// initialise command
gpx - > command . x = 0.0 ;
gpx - > command . y = 0.0 ;
gpx - > command . z = 0.0 ;
gpx - > command . a = 0.0 ;
gpx - > command . b = 0.0 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
gpx - > command . e = 0.0 ;
gpx - > command . f = 0.0 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
gpx - > command . p = 0.0 ;
gpx - > command . r = 0.0 ;
gpx - > command . s = 0.0 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
gpx - > command . g = 0.0 ;
gpx - > command . m = 0.0 ;
gpx - > command . t = 0.0 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
gpx - > command . comment = " " ;
gpx - > command . flag = 0 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
// initialize target position
gpx - > target . position . x = 0.0 ;
gpx - > target . position . y = 0.0 ;
gpx - > target . position . z = 0.0 ;
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
gpx - > target . position . a = 0.0 ;
gpx - > target . position . b = 0.0 ;
gpx - > target . extruder = 0 ;
// initialize current position
gpx - > current . position . x = 0.0 ;
gpx - > current . position . y = 0.0 ;
gpx - > current . position . z = 0.0 ;
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
gpx - > current . position . a = 0.0 ;
gpx - > current . position . b = 0.0 ;
gpx - > current . feedrate = get_home_feedrate ( gpx , XYZ_BIT_MASK ) ;
gpx - > current . extruder = 0 ;
gpx - > current . offset = 0 ;
gpx - > current . percent = 0 ;
2014-01-08 22:20:51 +04:00
gpx - > axis . positionKnown = 0 ;
gpx - > axis . mask = gpx - > machine . extruder_count = = 1 ? ( XYZ_BIT_MASK | A_IS_SET ) : AXES_BIT_MASK ; ;
2013-11-24 17:04:49 +04:00
// initialize the accumulated rounding error
gpx - > excess . a = 0.0 ;
gpx - > excess . b = 0.0 ;
// initialize the G10 offsets
2013-04-12 17:47:40 +04:00
for ( i = 0 ; i < 7 ; i + + ) {
2013-11-24 17:04:49 +04:00
gpx - > offset [ i ] . x = 0.0 ;
gpx - > offset [ i ] . y = 0.0 ;
gpx - > offset [ i ] . z = 0.0 ;
2013-04-12 17:47:40 +04:00
}
2013-05-08 13:37:30 +04:00
2013-11-24 17:04:49 +04:00
// initialize the command line offset
if ( firstTime ) {
2014-01-08 22:20:51 +04:00
gpx - > user . offset . x = 0.0 ;
gpx - > user . offset . y = 0.0 ;
gpx - > user . offset . z = 0.0 ;
gpx - > user . scale = 1.0 ;
2013-11-24 17:04:49 +04:00
}
2013-04-12 17:47:40 +04:00
2013-04-16 20:01:26 +04:00
for ( i = 0 ; i < 2 ; i + + ) {
2013-11-24 17:04:49 +04:00
gpx - > tool [ i ] . motor_enabled = 0 ;
2013-05-03 17:57:14 +04:00
# if ENABLE_SIMULATED_RPM
2013-11-24 17:04:49 +04:00
gpx - > tool [ i ] . rpm = 0 ;
2013-04-21 21:37:12 +04:00
# endif
2013-11-24 17:04:49 +04:00
gpx - > tool [ i ] . nozzle_temperature = 0 ;
gpx - > tool [ i ] . build_platform_temperature = 0 ;
2013-04-18 19:01:37 +04:00
2013-11-24 17:04:49 +04:00
gpx - > override [ i ] . actual_filament_diameter = 0 ;
gpx - > override [ i ] . filament_scale = 1.0 ;
gpx - > override [ i ] . packing_density = 1.0 ;
gpx - > override [ i ] . standby_temperature = 0 ;
gpx - > override [ i ] . active_temperature = 0 ;
gpx - > override [ i ] . build_platform_temperature = 0 ;
}
if ( firstTime ) {
gpx - > filament [ 0 ] . colour = " _null_ " ;
gpx - > filament [ 0 ] . diameter = 0.0 ;
gpx - > filament [ 0 ] . temperature = 0 ;
gpx - > filament [ 0 ] . LED = 0 ;
gpx - > filamentLength = 1 ;
}
2014-01-08 22:20:51 +04:00
if ( firstTime ) {
gpx - > commandAtIndex = 0 ;
gpx - > commandAtLength = 0 ;
}
2013-11-24 17:04:49 +04:00
gpx - > commandAtZ = 0.0 ;
// SETTINGS
if ( firstTime ) {
gpx - > sdCardPath = NULL ;
gpx - > buildName = " GPX " GPX_VERSION ;
2013-04-12 17:47:40 +04:00
}
2013-04-18 19:01:37 +04:00
2013-11-24 17:04:49 +04:00
gpx - > flag . relativeCoordinates = 0 ;
gpx - > flag . extruderIsRelative = 0 ;
2013-04-18 19:01:37 +04:00
2013-11-24 17:04:49 +04:00
if ( firstTime ) {
2014-01-08 22:20:51 +04:00
gpx - > flag . reprapFlavor = 1 ; // reprap flavor is enabled by default
2013-11-24 17:04:49 +04:00
gpx - > flag . dittoPrinting = 0 ;
gpx - > flag . buildProgress = 0 ;
gpx - > flag . verboseMode = 0 ;
2014-01-08 22:20:51 +04:00
gpx - > flag . logMessages = 1 ; // logging is enabled by default
2013-11-24 17:04:49 +04:00
gpx - > flag . rewrite5D = 0 ;
}
2014-01-08 22:20:51 +04:00
2013-11-24 17:04:49 +04:00
// STATE
2013-04-17 15:54:52 +04:00
2013-11-24 17:04:49 +04:00
gpx - > flag . programState = 0 ;
gpx - > flag . doPauseAtZPos = 0 ;
gpx - > flag . pausePending = 0 ;
gpx - > flag . macrosEnabled = 0 ;
2014-01-08 22:20:51 +04:00
if ( firstTime ) {
gpx - > flag . loadMacros = 1 ;
gpx - > flag . runMacros = 1 ;
}
2013-11-24 17:04:49 +04:00
gpx - > flag . framingEnabled = 0 ;
2013-04-21 21:37:12 +04:00
2013-11-24 17:04:49 +04:00
gpx - > longestDDA = 0 ;
gpx - > layerHeight = 0.34 ;
gpx - > lineNumber = 1 ;
// STATISTICS
2013-06-05 17:35:06 +04:00
2013-11-24 17:04:49 +04:00
gpx - > accumulated . a = 0.0 ;
gpx - > accumulated . b = 0.0 ;
gpx - > accumulated . time = 0.0 ;
gpx - > accumulated . bytes = 0 ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
if ( firstTime ) {
gpx - > total . length = 0.0 ;
gpx - > total . time = 0.0 ;
gpx - > total . bytes = 0 ;
}
// CALLBACK
gpx - > callbackHandler = NULL ;
gpx - > callbackData = NULL ;
2014-01-08 22:20:51 +04:00
// LOGGING
if ( firstTime ) gpx - > log = stderr ;
2013-04-12 17:47:40 +04:00
}
2014-01-08 22:20:51 +04:00
// PRINT STATE
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
# define start_program() gpx->flag.programState = RUNNING_STATE
# define end_program() gpx->flag.programState = ENDED_STATE
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
# define program_is_ready() gpx->flag.programState < RUNNING_STATE
# define program_is_running() gpx->flag.programState < ENDED_STATE
2013-04-12 17:47:40 +04:00
2013-04-16 20:01:26 +04:00
// IO FUNCTIONS
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static void write_8 ( Gpx * gpx , unsigned char value )
2013-04-25 15:46:44 +04:00
{
2013-11-24 17:04:49 +04:00
* gpx - > buffer . ptr + + = value ;
2013-04-25 15:46:44 +04:00
}
2013-04-12 17:47:40 +04:00
2014-01-08 22:20:51 +04:00
static unsigned char read_8 ( Gpx * gpx )
{
return * gpx - > buffer . ptr + + ;
}
2013-11-24 17:04:49 +04:00
static void write_16 ( Gpx * gpx , unsigned short value )
2013-04-12 17:47:40 +04:00
{
union {
unsigned short s ;
unsigned char b [ 2 ] ;
} u ;
u . s = value ;
2013-11-24 17:04:49 +04:00
* gpx - > buffer . ptr + + = u . b [ 0 ] ;
* gpx - > buffer . ptr + + = u . b [ 1 ] ;
2013-04-11 05:32:34 +04:00
}
2014-01-08 22:20:51 +04:00
static unsigned short read_16 ( Gpx * gpx )
{
union {
unsigned short s ;
unsigned char b [ 2 ] ;
} u ;
u . b [ 0 ] = * gpx - > buffer . ptr + + ;
u . b [ 1 ] = * gpx - > buffer . ptr + + ;
return u . s ;
}
2013-11-24 17:04:49 +04:00
static void write_32 ( Gpx * gpx , unsigned int value )
2013-04-11 05:32:34 +04:00
{
2013-04-12 17:47:40 +04:00
union {
unsigned int i ;
unsigned char b [ 4 ] ;
} u ;
u . i = value ;
2013-11-24 17:04:49 +04:00
* gpx - > buffer . ptr + + = u . b [ 0 ] ;
* gpx - > buffer . ptr + + = u . b [ 1 ] ;
* gpx - > buffer . ptr + + = u . b [ 2 ] ;
* gpx - > buffer . ptr + + = u . b [ 3 ] ;
2013-04-11 05:32:34 +04:00
}
2014-01-08 22:20:51 +04:00
static unsigned int read_32 ( Gpx * gpx )
{
union {
unsigned int i ;
unsigned char b [ 4 ] ;
} u ;
u . b [ 0 ] = * gpx - > buffer . ptr + + ;
u . b [ 1 ] = * gpx - > buffer . ptr + + ;
u . b [ 2 ] = * gpx - > buffer . ptr + + ;
u . b [ 3 ] = * gpx - > buffer . ptr + + ;
return u . i ;
}
2013-11-24 17:04:49 +04:00
static void write_float ( Gpx * gpx , float value )
2013-04-25 15:46:44 +04:00
{
2013-04-12 17:47:40 +04:00
union {
float f ;
unsigned char b [ 4 ] ;
} u ;
u . f = value ;
2013-11-24 17:04:49 +04:00
* gpx - > buffer . ptr + + = u . b [ 0 ] ;
* gpx - > buffer . ptr + + = u . b [ 1 ] ;
* gpx - > buffer . ptr + + = u . b [ 2 ] ;
* gpx - > buffer . ptr + + = u . b [ 3 ] ;
}
2014-01-08 22:20:51 +04:00
static float read_float ( Gpx * gpx )
{
union {
float f ;
unsigned char b [ 4 ] ;
} u ;
u . b [ 0 ] = * gpx - > buffer . ptr + + ;
u . b [ 1 ] = * gpx - > buffer . ptr + + ;
u . b [ 2 ] = * gpx - > buffer . ptr + + ;
u . b [ 3 ] = * gpx - > buffer . ptr + + ;
return u . f ;
}
static long write_bytes ( Gpx * gpx , char * data , long length )
{
long l = length ;
while ( l - - ) {
* gpx - > buffer . ptr + + = * data + + ;
}
return length ;
}
static long read_bytes ( Gpx * gpx , char * data , long length )
{
long l = length ;
while ( l - - ) {
* data + + = * gpx - > buffer . ptr + + ;
}
return length ;
}
2013-11-24 17:04:49 +04:00
static long write_string ( Gpx * gpx , char * string , long length )
{
long l = length ;
while ( l - - ) {
* gpx - > buffer . ptr + + = * string + + ;
2013-04-25 15:46:44 +04:00
}
2013-11-24 17:04:49 +04:00
* gpx - > buffer . ptr + + = ' \0 ' ;
return length ;
2013-04-25 15:46:44 +04:00
}
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
// FRAMING
static unsigned char calculate_crc ( unsigned char * addr , long len )
2013-04-25 15:46:44 +04:00
{
2013-11-24 17:04:49 +04:00
unsigned char data , crc = 0 ;
while ( len - - ) {
data = * addr + + ;
// 8-bit iButton/Maxim/Dallas CRC loop unrolled
crc = crc ^ data ;
// 1
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 2
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 3
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 4
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 5
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 6
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 7
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
// 8
if ( crc & 0x01 ) crc = ( crc > > 1 ) ^ 0x8C ;
else crc > > = 1 ;
}
return crc ;
}
static void begin_frame ( Gpx * gpx )
{
gpx - > buffer . ptr = gpx - > buffer . out ;
if ( gpx - > flag . framingEnabled ) {
gpx - > buffer . out [ 0 ] = 0xD5 ; // synchronization byte
gpx - > buffer . ptr + = 2 ;
}
}
static int end_frame ( Gpx * gpx )
{
if ( gpx - > flag . framingEnabled ) {
unsigned char * start = ( unsigned char * ) gpx - > buffer . out + 2 ;
unsigned char * end = ( unsigned char * ) gpx - > buffer . ptr ;
2014-01-08 22:20:51 +04:00
size_t payload_length = end - start ;
gpx - > buffer . out [ 1 ] = ( unsigned char ) payload_length ;
* gpx - > buffer . ptr + + = calculate_crc ( start , payload_length ) ;
}
size_t length = gpx - > buffer . ptr - gpx - > buffer . out ;
gpx - > accumulated . bytes + = length ;
if ( gpx - > callbackHandler ) return gpx - > callbackHandler ( gpx , gpx - > callbackData , gpx - > buffer . out , length ) ;
return SUCCESS ;
2013-04-12 17:47:40 +04:00
}
2013-04-17 20:47:52 +04:00
// 5D VECTOR FUNCTIONS
2013-04-18 19:01:37 +04:00
// compute the filament scaling factor
2013-11-24 17:04:49 +04:00
static void set_filament_scale ( Gpx * gpx , unsigned extruder_id , double filament_diameter )
2013-04-29 22:26:36 +04:00
{
2013-04-21 21:37:12 +04:00
double actual_radius = filament_diameter / 2 ;
2013-11-24 17:04:49 +04:00
double nominal_radius = gpx - > machine . nominal_filament_diameter / 2 ;
gpx - > override [ extruder_id ] . filament_scale = ( nominal_radius * nominal_radius ) / ( actual_radius * actual_radius ) ;
2013-04-18 19:01:37 +04:00
}
2013-04-16 20:01:26 +04:00
// return the magnitude (length) of the 5D vector
2013-04-12 17:47:40 +04:00
static double magnitude ( int flag , Ptr5d vector )
2013-04-11 05:32:34 +04:00
{
double acc = 0.0 ;
if ( flag & X_IS_SET ) {
acc = vector - > x * vector - > x ;
}
if ( flag & Y_IS_SET ) {
acc + = vector - > y * vector - > y ;
}
if ( flag & Z_IS_SET ) {
acc + = vector - > z * vector - > z ;
}
if ( flag & A_IS_SET ) {
acc + = vector - > a * vector - > a ;
}
if ( flag & B_IS_SET ) {
acc + = vector - > b * vector - > b ;
}
return sqrt ( acc ) ;
}
2013-04-16 20:01:26 +04:00
// return the largest axis in the vector
static double largest_axis ( int flag , Ptr5d vector )
2013-04-11 05:32:34 +04:00
{
2014-01-08 22:20:51 +04:00
double length , result = 0.0 ;
2013-04-16 20:01:26 +04:00
if ( flag & X_IS_SET ) {
2014-01-08 22:20:51 +04:00
result = fabs ( vector - > x ) ;
2013-04-11 05:32:34 +04:00
}
2013-04-16 20:01:26 +04:00
if ( flag & Y_IS_SET ) {
length = fabs ( vector - > y ) ;
2014-01-08 22:20:51 +04:00
if ( result < length ) result = length ;
2013-04-16 20:01:26 +04:00
}
if ( flag & Z_IS_SET ) {
length = fabs ( vector - > z ) ;
2014-01-08 22:20:51 +04:00
if ( result < length ) result = length ;
2013-04-16 20:01:26 +04:00
}
if ( flag & A_IS_SET ) {
length = fabs ( vector - > a ) ;
2014-01-08 22:20:51 +04:00
if ( result < length ) result = length ;
2013-04-16 20:01:26 +04:00
}
if ( flag & B_IS_SET ) {
length = fabs ( vector - > b ) ;
2014-01-08 22:20:51 +04:00
if ( result < length ) result = length ;
2013-04-16 20:01:26 +04:00
}
2014-01-08 22:20:51 +04:00
return result ;
2013-04-16 20:01:26 +04:00
}
// calculate the dda for the longest axis for the current machine definition
2013-11-24 17:04:49 +04:00
static int get_longest_dda ( Gpx * gpx )
2013-04-16 20:01:26 +04:00
{
// calculate once
2013-11-24 17:04:49 +04:00
int longestDDA = gpx - > longestDDA ;
2013-04-16 20:01:26 +04:00
if ( longestDDA = = 0 ) {
2013-11-24 17:04:49 +04:00
longestDDA = ( int ) ( 60 * 1000000.0 / ( gpx - > machine . x . max_feedrate * gpx - > machine . x . steps_per_mm ) ) ;
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
int axisDDA = ( int ) ( 60 * 1000000.0 / ( gpx - > machine . y . max_feedrate * gpx - > machine . y . steps_per_mm ) ) ;
2013-04-16 20:01:26 +04:00
if ( longestDDA < axisDDA ) longestDDA = axisDDA ;
2013-11-24 17:04:49 +04:00
axisDDA = ( int ) ( 60 * 1000000.0 / ( gpx - > machine . z . max_feedrate * gpx - > machine . z . steps_per_mm ) ) ;
2013-04-16 20:01:26 +04:00
if ( longestDDA < axisDDA ) longestDDA = axisDDA ;
2013-11-24 17:04:49 +04:00
gpx - > longestDDA = longestDDA ;
2013-04-16 20:01:26 +04:00
}
return longestDDA ;
}
// return the maximum home feedrate
2013-11-24 17:04:49 +04:00
static double get_home_feedrate ( Gpx * gpx , int flag ) {
2013-04-16 20:01:26 +04:00
double feedrate = 0.0 ;
if ( flag & X_IS_SET ) {
2013-11-24 17:04:49 +04:00
feedrate = gpx - > machine . x . home_feedrate ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( flag & Y_IS_SET & & feedrate < gpx - > machine . y . home_feedrate ) {
feedrate = gpx - > machine . y . home_feedrate ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( flag & Z_IS_SET & & feedrate < gpx - > machine . z . home_feedrate ) {
feedrate = gpx - > machine . z . home_feedrate ;
2013-04-16 20:01:26 +04:00
}
return feedrate ;
}
// return the maximum safe feedrate
2013-11-24 17:04:49 +04:00
static double get_safe_feedrate ( Gpx * gpx , int flag , Ptr5d delta ) {
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
double feedrate = gpx - > current . feedrate ;
2013-04-16 20:01:26 +04:00
if ( feedrate = = 0.0 ) {
2013-11-24 17:04:49 +04:00
feedrate = gpx - > machine . x . max_feedrate ;
if ( feedrate < gpx - > machine . y . max_feedrate ) {
feedrate = gpx - > machine . y . max_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
if ( feedrate < gpx - > machine . z . max_feedrate ) {
feedrate = gpx - > machine . z . max_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
if ( feedrate < gpx - > machine . a . max_feedrate ) {
feedrate = gpx - > machine . a . max_feedrate ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( feedrate < gpx - > machine . b . max_feedrate ) {
feedrate = gpx - > machine . b . max_feedrate ;
2013-04-11 05:32:34 +04:00
}
}
2013-04-16 20:01:26 +04:00
double distance = magnitude ( flag & XYZ_BIT_MASK , delta ) ;
2013-11-24 17:04:49 +04:00
if ( flag & X_IS_SET & & ( feedrate * delta - > x / distance ) > gpx - > machine . x . max_feedrate ) {
feedrate = gpx - > machine . x . max_feedrate * distance / delta - > x ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
if ( flag & Y_IS_SET & & ( feedrate * delta - > y / distance ) > gpx - > machine . y . max_feedrate ) {
feedrate = gpx - > machine . y . max_feedrate * distance / delta - > y ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( flag & Z_IS_SET & & ( feedrate * delta - > z / distance ) > gpx - > machine . z . max_feedrate ) {
feedrate = gpx - > machine . z . max_feedrate * distance / delta - > z ;
2013-04-16 20:01:26 +04:00
}
if ( distance = = 0 ) {
2013-11-24 17:04:49 +04:00
if ( flag & A_IS_SET & & feedrate > gpx - > machine . a . max_feedrate ) {
feedrate = gpx - > machine . a . max_feedrate ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( flag & B_IS_SET & & feedrate > gpx - > machine . b . max_feedrate ) {
feedrate = gpx - > machine . b . max_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-04-16 20:01:26 +04:00
}
else {
2013-11-24 17:04:49 +04:00
if ( flag & A_IS_SET & & ( feedrate * delta - > a / distance ) > gpx - > machine . a . max_feedrate ) {
feedrate = gpx - > machine . a . max_feedrate * distance / delta - > a ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
if ( flag & B_IS_SET & & ( feedrate * delta - > b / distance ) > gpx - > machine . b . max_feedrate ) {
feedrate = gpx - > machine . b . max_feedrate * distance / delta - > b ;
2013-04-11 05:32:34 +04:00
}
}
return feedrate ;
}
2013-04-17 15:54:52 +04:00
// convert mm to steps using the current machine definition
2013-04-21 21:37:12 +04:00
// IMPORTANT: this command changes the global excess value which accumulates the rounding remainder
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
static Point5d mm_to_steps ( Gpx * gpx , Ptr5d mm , Ptr2d excess )
2013-04-12 17:47:40 +04:00
{
2013-04-16 20:01:26 +04:00
double value ;
2013-04-12 17:47:40 +04:00
Point5d result ;
2013-11-24 17:04:49 +04:00
result . x = round ( mm - > x * gpx - > machine . x . steps_per_mm ) ;
result . y = round ( mm - > y * gpx - > machine . y . steps_per_mm ) ;
result . z = round ( mm - > z * gpx - > machine . z . steps_per_mm ) ;
2013-04-12 17:47:40 +04:00
if ( excess ) {
2013-04-17 15:54:52 +04:00
// accumulate rounding remainder
2013-11-24 17:04:49 +04:00
value = ( mm - > a * gpx - > machine . a . steps_per_mm ) + excess - > a ;
2013-04-16 20:01:26 +04:00
result . a = round ( value ) ;
2013-04-17 15:54:52 +04:00
// changes to excess
2013-04-16 20:01:26 +04:00
excess - > a = value - result . a ;
2013-11-24 17:04:49 +04:00
value = ( mm - > b * gpx - > machine . b . steps_per_mm ) + excess - > b ;
2013-04-16 20:01:26 +04:00
result . b = round ( value ) ;
2013-04-17 15:54:52 +04:00
// changes to excess
2013-04-16 20:01:26 +04:00
excess - > b = value - result . b ;
2013-04-12 17:47:40 +04:00
}
else {
2013-11-24 17:04:49 +04:00
result . a = round ( mm - > a * gpx - > machine . a . steps_per_mm ) ;
result . b = round ( mm - > b * gpx - > machine . b . steps_per_mm ) ;
2013-04-12 17:47:40 +04:00
}
return result ;
}
2013-11-24 17:04:49 +04:00
static Point5d delta_mm ( Gpx * gpx )
2013-11-15 21:17:33 +04:00
{
Point5d deltaMM ;
// compute the relative distance traveled along each axis and convert to steps
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & X_IS_SET ) deltaMM . x = gpx - > target . position . x - gpx - > current . position . x ; else deltaMM . x = 0 ;
if ( gpx - > command . flag & Y_IS_SET ) deltaMM . y = gpx - > target . position . y - gpx - > current . position . y ; else deltaMM . y = 0 ;
if ( gpx - > command . flag & Z_IS_SET ) deltaMM . z = gpx - > target . position . z - gpx - > current . position . z ; else deltaMM . z = 0 ;
if ( gpx - > command . flag & A_IS_SET ) deltaMM . a = gpx - > target . position . a - gpx - > current . position . a ; else deltaMM . a = 0 ;
if ( gpx - > command . flag & B_IS_SET ) deltaMM . b = gpx - > target . position . b - gpx - > current . position . b ; else deltaMM . b = 0 ;
2013-11-15 21:17:33 +04:00
return deltaMM ;
}
2013-11-24 17:04:49 +04:00
static Point5d delta_steps ( Gpx * gpx , Point5d deltaMM )
2013-11-15 21:17:33 +04:00
{
Point5d deltaSteps ;
// compute the relative distance traveled along each axis and convert to steps
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & X_IS_SET ) deltaSteps . x = round ( fabs ( deltaMM . x ) * gpx - > machine . x . steps_per_mm ) ; else deltaSteps . x = 0 ;
if ( gpx - > command . flag & Y_IS_SET ) deltaSteps . y = round ( fabs ( deltaMM . y ) * gpx - > machine . y . steps_per_mm ) ; else deltaSteps . y = 0 ;
if ( gpx - > command . flag & Z_IS_SET ) deltaSteps . z = round ( fabs ( deltaMM . z ) * gpx - > machine . z . steps_per_mm ) ; else deltaSteps . z = 0 ;
if ( gpx - > command . flag & A_IS_SET ) deltaSteps . a = round ( fabs ( deltaMM . a ) * gpx - > machine . a . steps_per_mm ) ; else deltaSteps . a = 0 ;
if ( gpx - > command . flag & B_IS_SET ) deltaSteps . b = round ( fabs ( deltaMM . b ) * gpx - > machine . b . steps_per_mm ) ; else deltaSteps . b = 0 ;
2013-11-15 21:17:33 +04:00
return deltaSteps ;
}
2013-11-24 17:04:49 +04:00
// X3G QUERIES
2014-01-08 22:20:51 +04:00
# define COMMAND_OFFSET 2
# define EXTRUDER_ID_OFFSET 3
# define QUERY_COMMAND_OFFSET 4
# define EEPROM_LENGTH_OFFSET 8
2013-11-24 17:04:49 +04:00
// 00 - Get version
2014-01-08 22:20:51 +04:00
static int get_version ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 0 ) ;
// uint16: host version
write_16 ( gpx , HOST_VERSION ) ;
return end_frame ( gpx ) ;
}
/* 01 - Initialize firmware to boot state
This is treated as a NOOP in the Sailfish firmware . */
static int initialize_firmware ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 1 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 02 - Get available buffer size
2014-01-08 22:20:51 +04:00
static int get_buffer_size ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 2 ) ;
return end_frame ( gpx ) ;
}
// 03 - Clear buffer (same as 07 and 17)
static int clear_buffer ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 3 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 07 - Abort immediately
2014-01-08 22:20:51 +04:00
static int abort_immediately ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 7 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 08 - Pause/Resume
2014-01-08 22:20:51 +04:00
static int pause_resume ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 8 ) ;
return end_frame ( gpx ) ;
}
// 10 - Extruder Query Commands
// Query 00 - Query firmware version information
static int get_extruder_version ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 0 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 2 ) ;
// uint16: host version
write_16 ( gpx , HOST_VERSION ) ;
return end_frame ( gpx ) ;
}
// Query 02 - Get extruder temperature
static int get_extruder_temperature ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 2 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// Query 22 - Is extruder ready
static int is_extruder_ready ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 22 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// Query 30 - Get build platform temperature
static int get_build_platform_temperature ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 30 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// Query 32 - Get extruder target temperature
static int get_extruder_target_temperature ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 32 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// Query 33 - Get build platform target temperature
static int get_build_platform_target_temperature ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 33 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// Query 35 - Is build platform ready?
static int is_build_platform_ready ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 35 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// Query 36 - Get extruder status
static int get_extruder_status ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 36 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
2014-01-08 22:20:51 +04:00
// Query 37 - Get PID state
static int get_PID_state ( Gpx * gpx , unsigned extruder_id )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 10 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Query command to send to the extruder
write_8 ( gpx , 37 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
// 11 - Is ready
static int is_ready ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 11 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 12 - Read from EEPROM
2014-01-08 22:20:51 +04:00
static int read_eeprom ( Gpx * gpx , unsigned address , unsigned length )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 12 ) ;
// uint16: EEPROM memory offset to begin reading from
write_16 ( gpx , address ) ;
// uint8: Number of bytes to read, N.
write_8 ( gpx , length ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 13 - Write to EEPROM
2014-01-08 22:20:51 +04:00
static int write_eeprom ( Gpx * gpx , unsigned address , char * data , unsigned length )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 13 ) ;
// uint16: EEPROM memory offset to begin writing to
write_16 ( gpx , address ) ;
// uint8: Number of bytes to write
write_8 ( gpx , length ) ;
// N bytes: Data to write to EEPROM
write_bytes ( gpx , data , length ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 14 - Capture to file
2014-01-08 22:20:51 +04:00
static int capture_to_file ( Gpx * gpx , char * filename )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 14 ) ;
/* 1+N bytes: Filename to write to, in ASCII, terminated with a null character.
N can be 1 - 12 bytes long , not including the null character . */
write_string ( gpx , filename , strlen ( filename ) ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 15 - End capture to file
2014-01-08 22:20:51 +04:00
static int end_capture_to_file ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 15 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 16 - Play back capture
2014-01-08 22:20:51 +04:00
static int play_back_capture ( Gpx * gpx , char * filename )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 16 ) ;
/* 1+N bytes: Filename to write to, in ASCII, terminated with a null character.
N can be 1 - 12 bytes long , not including the null character . */
write_string ( gpx , filename , strlen ( filename ) ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 17 - Reset
2014-01-08 22:20:51 +04:00
static int reset ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 17 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 18 - Get next filename
2014-01-08 22:20:51 +04:00
static int get_next_filename ( Gpx * gpx , unsigned restart )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 18 ) ;
// uint8: 0 if file listing should continue, 1 to restart listing.
write_8 ( gpx , restart ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 20 - Get build name
2014-01-08 22:20:51 +04:00
static int get_build_name ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 20 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 21 - Get extended position
2014-01-08 22:20:51 +04:00
static int get_extended_position ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 21 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 22 - Extended stop
2014-01-08 22:20:51 +04:00
static int extended_stop ( Gpx * gpx , unsigned halt_steppers , unsigned clear_queue )
{
unsigned flag = 0 ;
if ( halt_steppers ) flag | = 0x1 ;
if ( clear_queue ) flag | = 0x2 ;
begin_frame ( gpx ) ;
write_8 ( gpx , 22 ) ;
/* uint8: Bitfield indicating which subsystems to shut down.
If bit 0 is set , halt all stepper motion .
If bit 1 is set , clear the command queue . */
write_8 ( gpx , flag ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 23 - Get motherboard status
2014-01-08 22:20:51 +04:00
static int get_motherboard_status ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 23 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 24 - Get build statistics
2014-01-08 22:20:51 +04:00
static int get_build_statistics ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 24 ) ;
return end_frame ( gpx ) ;
}
2013-11-24 17:04:49 +04:00
// 27 - Get advanced version number
2014-01-08 22:20:51 +04:00
static int get_advanced_version_number ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 27 ) ;
// uint16: Host version
write_16 ( gpx , HOST_VERSION ) ;
return end_frame ( gpx ) ;
}
2013-04-11 05:32:34 +04:00
// X3G COMMANDS
// 131 - Find axes minimums
// 132 - Find axes maximums
2014-01-08 22:20:51 +04:00
static int home_axes ( Gpx * gpx , unsigned axes , unsigned direction )
2013-04-11 05:32:34 +04:00
{
2013-04-16 20:01:26 +04:00
Point5d unitVector ;
2013-11-24 17:04:49 +04:00
double feedrate = gpx - > command . flag & F_IS_SET ? gpx - > current . feedrate : get_home_feedrate ( gpx , gpx - > command . flag ) ;
2013-04-16 20:01:26 +04:00
double longestAxis = 0.0 ;
2013-04-12 17:47:40 +04:00
assert ( direction < = 1 ) ;
2013-04-16 20:01:26 +04:00
2013-04-11 05:32:34 +04:00
// compute the slowest feedrate
2014-01-08 22:20:51 +04:00
if ( axes & X_IS_SET ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . x . home_feedrate < feedrate ) {
feedrate = gpx - > machine . x . home_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-04-16 20:01:26 +04:00
unitVector . x = 1 ;
2013-11-24 17:04:49 +04:00
longestAxis = gpx - > machine . x . steps_per_mm ;
2013-04-11 05:32:34 +04:00
// confirm machine compatibility
2013-11-24 17:04:49 +04:00
if ( direction ! = gpx - > machine . x . endstop ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: X axis homing to %s endstop " EOL , gpx - > lineNumber , direction ? " maximum " : " minimum " ) ) ;
2013-04-11 05:32:34 +04:00
}
}
2014-01-08 22:20:51 +04:00
if ( axes & Y_IS_SET ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . y . home_feedrate < feedrate ) {
feedrate = gpx - > machine . y . home_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-04-16 20:01:26 +04:00
unitVector . y = 1 ;
2013-11-24 17:04:49 +04:00
if ( longestAxis < gpx - > machine . y . steps_per_mm ) {
longestAxis = gpx - > machine . y . steps_per_mm ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( direction ! = gpx - > machine . y . endstop ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: Y axis homing to %s endstop " EOL , gpx - > lineNumber , direction ? " maximum " : " minimum " ) ) ;
2013-04-11 05:32:34 +04:00
}
}
2014-01-08 22:20:51 +04:00
if ( axes & Z_IS_SET ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . z . home_feedrate < feedrate ) {
feedrate = gpx - > machine . z . home_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-04-16 20:01:26 +04:00
unitVector . z = 1 ;
2013-11-24 17:04:49 +04:00
if ( longestAxis < gpx - > machine . z . steps_per_mm ) {
longestAxis = gpx - > machine . z . steps_per_mm ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( direction ! = gpx - > machine . z . endstop ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: Z axis homing to %s endstop " EOL , gpx - > lineNumber , direction ? " maximum " : " minimum " ) ) ;
2013-04-11 05:32:34 +04:00
}
}
2013-04-16 20:01:26 +04:00
// unit vector distance in mm
2014-01-08 22:20:51 +04:00
double distance = magnitude ( axes , & unitVector ) ;
2013-04-16 20:01:26 +04:00
// move duration in microseconds = distance / feedrate * 60,000,000
double microseconds = distance / feedrate * 60000000.0 ;
// time between steps for longest axis = microseconds / longestStep
unsigned step_delay = ( unsigned ) round ( microseconds / longestAxis ) ;
2013-04-12 17:47:40 +04:00
2014-06-03 23:24:55 +04:00
//gpx->accumulated.time += distance / feedrate * 60;
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , direction = = ENDSTOP_IS_MIN ? 131 : 132 ) ;
2013-04-12 17:47:40 +04:00
2013-04-11 05:32:34 +04:00
// uint8: Axes bitfield. Axes whose bits are set will be moved.
2014-01-08 22:20:51 +04:00
write_8 ( gpx , axes ) ;
2013-04-12 17:47:40 +04:00
2013-04-11 05:32:34 +04:00
// uint32: Feedrate, in microseconds between steps on the max delta. (DDA)
2013-11-24 17:04:49 +04:00
write_32 ( gpx , step_delay ) ;
2013-04-12 17:47:40 +04:00
2013-04-11 05:32:34 +04:00
// uint16: Timeout, in seconds.
2013-11-24 17:04:49 +04:00
write_16 ( gpx , gpx - > machine . timeout ) ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
return end_frame ( gpx ) ;
2013-04-11 05:32:34 +04:00
}
// 133 - delay
2013-11-24 17:04:49 +04:00
static int delay ( Gpx * gpx , unsigned milliseconds )
2013-04-11 05:32:34 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 133 ) ;
2013-04-12 17:47:40 +04:00
2013-04-11 05:32:34 +04:00
// uint32: delay, in milliseconds
2013-11-24 17:04:49 +04:00
write_32 ( gpx , milliseconds ) ;
return end_frame ( gpx ) ;
2013-04-11 05:32:34 +04:00
}
2013-04-22 18:22:44 +04:00
// 134 - Change extruder offset
// This is important to use on dual-head Replicators, because the machine needs to know
// the current toolhead in order to apply a calibration offset.
2013-11-24 17:04:49 +04:00
static int change_extruder_offset ( Gpx * gpx , unsigned extruder_id )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
begin_frame ( gpx ) ;
write_8 ( gpx , 134 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: ID of the extruder to switch to
2013-11-24 17:04:49 +04:00
write_8 ( gpx , extruder_id ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-13 03:30:11 +04:00
// 135 - Wait for extruder ready
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
static int wait_for_extruder ( Gpx * gpx , unsigned extruder_id , unsigned timeout )
2013-04-11 05:32:34 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
begin_frame ( gpx ) ;
write_8 ( gpx , 135 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: ID of the extruder to wait for
2013-11-24 17:04:49 +04:00
write_8 ( gpx , extruder_id ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint16: delay between query packets sent to the extruder, in ms (nominally 100 ms)
2013-11-24 17:04:49 +04:00
write_16 ( gpx , 100 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint16: Timeout before continuing without extruder ready, in seconds (nominally 1 minute)
2013-11-24 17:04:49 +04:00
write_16 ( gpx , timeout ) ;
return end_frame ( gpx ) ;
2013-04-11 05:32:34 +04:00
}
2013-04-13 03:30:11 +04:00
// 136 - extruder action command
2013-04-12 17:47:40 +04:00
2013-04-22 18:22:44 +04:00
// Action 03 - Set extruder target temperature
2013-04-17 15:54:52 +04:00
2013-11-24 17:04:49 +04:00
static int set_nozzle_temperature ( Gpx * gpx , unsigned extruder_id , unsigned temperature )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
2014-01-08 22:20:51 +04:00
double tDelta = ( double ) temperature - ( double ) gpx - > tool [ extruder_id ] . nozzle_temperature - AMBIENT_TEMP ;
if ( tDelta > 0.0 ) {
2014-06-03 23:24:55 +04:00
//gpx->accumulated.time += tDelta * NOZZLE_TIME;
2014-01-08 22:20:51 +04:00
}
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 136 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: ID of the extruder to query
2013-11-24 17:04:49 +04:00
write_8 ( gpx , extruder_id ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: Action command to send to the extruder
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 3 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: Length of the extruder command payload (N)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 2 ) ;
2013-04-12 17:47:40 +04:00
// int16: Desired target temperature, in Celsius
2013-11-24 17:04:49 +04:00
write_16 ( gpx , temperature ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-17 15:54:52 +04:00
// Action 12 - Enable / Disable fan
2013-11-24 17:04:49 +04:00
static int set_fan ( Gpx * gpx , unsigned extruder_id , unsigned state )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
begin_frame ( gpx ) ;
write_8 ( gpx , 136 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: ID of the extruder to query
2013-11-24 17:04:49 +04:00
write_8 ( gpx , extruder_id ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: Action command to send to the extruder
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 12 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: Length of the extruder command payload (N)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 1 ) ;
2013-04-12 17:47:40 +04:00
// uint8: 1 to enable, 0 to disable
2013-11-24 17:04:49 +04:00
write_8 ( gpx , state ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-17 15:54:52 +04:00
// Action 13 - Enable / Disable extra output (blower fan)
2013-11-24 17:04:49 +04:00
/*
WARNING : If you are using Gen 4 electronics ( e . g . a Thing - o - Matic or a
heavily modified Cupcake ) , THEN DO NOT USE M126 / M127 . It can trigger
a bug in the Gen 4 Extruder Controller firmware that will cause the
HBP temperature to go wild . Note that the Extruder Controller is a
separate uprocessor on a separate board . It has it ' s own firmware .
It ' s not clear if the bug is firmware - only or if there is a problem
with electronics as well ( e . g . the HBP FET sees some residual current
from the EXTRA FET and its Vgs / Igs threshold is met and it activates ) .
But , there ' s no fix for the bug since no one has invested the time in
diagnosing this Extruder Controller issue .
- dnewman 22 / 11 / 2013
*/
static int set_valve ( Gpx * gpx , unsigned extruder_id , unsigned state )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
if ( gpx - > machine . type > = MACHINE_TYPE_REPLICATOR_1 ) {
begin_frame ( gpx ) ;
write_8 ( gpx , 136 ) ;
// uint8: ID of the extruder to query
write_8 ( gpx , extruder_id ) ;
// uint8: Action command to send to the extruder
write_8 ( gpx , 13 ) ;
// uint8: Length of the extruder command payload (N)
write_8 ( gpx , 1 ) ;
// uint8: 1 to enable, 0 to disable
write_8 ( gpx , state ) ;
return end_frame ( gpx ) ;
}
2014-01-08 22:20:51 +04:00
else if ( gpx - > flag . logMessages ) {
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: ignoring M126/M127 with Gen 4 extruder electronics " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-12 17:47:40 +04:00
}
2013-04-17 15:54:52 +04:00
// Action 31 - Set build platform target temperature
2013-11-24 17:04:49 +04:00
static int set_build_platform_temperature ( Gpx * gpx , unsigned extruder_id , unsigned temperature )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
2014-01-08 22:20:51 +04:00
double tDelta = ( double ) temperature - ( double ) gpx - > tool [ extruder_id ] . build_platform_temperature - AMBIENT_TEMP ;
if ( tDelta > 0.0 ) {
2014-06-03 23:24:55 +04:00
//gpx->accumulated.time += tDelta * HBP_TIME;
2014-01-08 22:20:51 +04:00
}
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 136 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: ID of the extruder to query
2013-11-24 17:04:49 +04:00
write_8 ( gpx , extruder_id ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: Action command to send to the extruder
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 31 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: Length of the extruder command payload (N)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 2 ) ;
2013-04-12 17:47:40 +04:00
// int16: Desired target temperature, in Celsius
2013-11-24 17:04:49 +04:00
write_16 ( gpx , temperature ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-17 15:54:52 +04:00
// 137 - Enable / Disable axes steppers
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int set_steppers ( Gpx * gpx , unsigned axes , unsigned state )
2013-04-12 17:47:40 +04:00
{
unsigned bitfield = axes & AXES_BIT_MASK ;
if ( state ) {
bitfield | = 0x80 ;
}
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 137 ) ;
2013-04-12 17:47:40 +04:00
// uint8: Bitfield codifying the command (see below)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , bitfield ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
2013-04-21 21:37:12 +04:00
// 139 - Queue absolute point
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
static int queue_absolute_point ( Gpx * gpx )
2013-04-16 20:01:26 +04:00
{
2013-11-24 17:04:49 +04:00
long longestDDA = gpx - > longestDDA ? gpx - > longestDDA : get_longest_dda ( gpx ) ;
Point5d steps = mm_to_steps ( gpx , & gpx - > target . position , & gpx - > excess ) ;
begin_frame ( gpx ) ;
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 139 ) ;
2013-04-16 20:01:26 +04:00
// int32: X coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . x ) ;
2013-04-16 20:01:26 +04:00
// int32: Y coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . y ) ;
2013-04-16 20:01:26 +04:00
// int32: Z coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . z ) ;
2013-04-16 20:01:26 +04:00
// int32: A coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , - ( int ) steps . a ) ;
2013-04-16 20:01:26 +04:00
// int32: B coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , - ( int ) steps . b ) ;
2013-04-16 20:01:26 +04:00
// uint32: Feedrate, in microseconds between steps on the max delta. (DDA)
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) longestDDA ) ;
2014-01-08 22:20:51 +04:00
// reset current position
gpx - > axis . positionKnown = gpx - > axis . mask ;
2013-11-24 17:04:49 +04:00
return end_frame ( gpx ) ;
2013-04-16 20:01:26 +04:00
}
2013-04-11 05:32:34 +04:00
// 140 - Set extended position
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int set_position ( Gpx * gpx )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
Point5d steps = mm_to_steps ( gpx , & gpx - > current . position , NULL ) ;
begin_frame ( gpx ) ;
write_8 ( gpx , 140 ) ;
2013-04-12 17:47:40 +04:00
// int32: X position, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . x ) ;
2013-04-12 17:47:40 +04:00
// int32: Y position, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . y ) ;
2013-04-12 17:47:40 +04:00
// int32: Z position, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . z ) ;
2013-04-12 17:47:40 +04:00
// int32: A position, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . a ) ;
2013-04-12 17:47:40 +04:00
// int32: B position, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . b ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-13 03:30:11 +04:00
// 141 - Wait for build platform ready
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
static int wait_for_build_platform ( Gpx * gpx , unsigned extruder_id , int timeout )
2013-04-11 05:32:34 +04:00
{
2013-11-24 17:04:49 +04:00
assert ( extruder_id < gpx - > machine . extruder_count ) ;
begin_frame ( gpx ) ;
write_8 ( gpx , 141 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint8: ID of the extruder platform to wait for
2013-11-24 17:04:49 +04:00
write_8 ( gpx , extruder_id ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint16: delay between query packets sent to the extruder, in ms (nominally 100 ms)
2013-11-24 17:04:49 +04:00
write_16 ( gpx , 100 ) ;
2013-04-12 17:47:40 +04:00
2013-04-13 03:30:11 +04:00
// uint16: Timeout before continuing without extruder ready, in seconds (nominally 1 minute)
2013-11-24 17:04:49 +04:00
write_16 ( gpx , timeout ) ;
return end_frame ( gpx ) ;
2013-04-11 05:32:34 +04:00
}
// 142 - Queue extended point, new style
2013-04-20 20:40:13 +04:00
2013-05-03 17:57:14 +04:00
# if ENABLE_SIMULATED_RPM
2013-11-24 17:04:49 +04:00
static int queue_new_point ( Gpx * gpx , unsigned milliseconds )
2013-04-20 20:40:13 +04:00
{
2013-04-21 21:37:12 +04:00
Point5d target ;
// the function is only called by dwell, which is by definition stationary,
// so set zero relitive position change
target . x = 0 ;
target . y = 0 ;
target . z = 0 ;
target . a = 0 ;
target . b = 0 ;
2013-04-20 20:40:13 +04:00
// if we have a G4 dwell and either the a or b motor is on, 'simulate' a 5D extrusion distance
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ A ] . motor_enabled & & gpx - > tool [ A ] . rpm ) {
double maxrpm = gpx - > machine . a . max_feedrate * gpx - > machine . a . steps_per_mm / gpx - > machine . a . motor_steps ;
double rpm = gpx - > tool [ A ] . rpm > maxrpm ? maxrpm : gpx - > tool [ A ] . rpm ;
2013-04-20 20:40:13 +04:00
double minutes = milliseconds / 60000.0 ;
// minute * revolution/minute
2013-11-24 17:04:49 +04:00
double numRevolutions = minutes * ( gpx - > tool [ A ] . motor_enabled > 0 ? rpm : - rpm ) ;
2013-04-20 20:40:13 +04:00
// steps/revolution * mm/steps
2013-11-24 17:04:49 +04:00
double mmPerRevolution = gpx - > machine . a . motor_steps * ( 1 / gpx - > machine . a . steps_per_mm ) ;
2013-04-20 20:40:13 +04:00
target . a = - ( numRevolutions * mmPerRevolution ) ;
2013-11-24 17:04:49 +04:00
gpx - > command . flag | = A_IS_SET ;
gpx - > accumulated . a + = fabs ( target . a ) ;
2013-04-20 20:40:13 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ B ] . motor_enabled & & gpx - > tool [ B ] . rpm ) {
double maxrpm = gpx - > machine . b . max_feedrate * gpx - > machine . b . steps_per_mm / gpx - > machine . b . motor_steps ;
double rpm = gpx - > tool [ B ] . rpm > maxrpm ? maxrpm : gpx - > tool [ B ] . rpm ;
2013-04-20 20:40:13 +04:00
double minutes = milliseconds / 60000.0 ;
// minute * revolution/minute
2013-11-24 17:04:49 +04:00
double numRevolutions = minutes * ( gpx - > tool [ B ] . motor_enabled > 0 ? rpm : - rpm ) ;
2013-04-20 20:40:13 +04:00
// steps/revolution * mm/steps
2013-11-24 17:04:49 +04:00
double mmPerRevolution = gpx - > machine . b . motor_steps * ( 1 / gpx - > machine . b . steps_per_mm ) ;
2013-04-20 20:40:13 +04:00
target . b = - ( numRevolutions * mmPerRevolution ) ;
2013-11-24 17:04:49 +04:00
gpx - > command . flag | = B_IS_SET ;
gpx - > accumulated . b + = fabs ( target . a ) ;
2013-04-20 20:40:13 +04:00
}
2013-11-24 17:04:49 +04:00
Point5d steps = mm_to_steps ( gpx , & target , & gpx - > excess ) ;
2014-01-08 22:20:51 +04:00
gpx - > accumulated . time + = ( milliseconds / 1000.0 ) * ACCELERATION_TIME ;
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
2013-04-20 20:40:13 +04:00
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 142 ) ;
2013-04-20 20:40:13 +04:00
// int32: X coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . x ) ;
2013-04-20 20:40:13 +04:00
// int32: Y coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . y ) ;
2013-04-20 20:40:13 +04:00
// int32: Z coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . z ) ;
2013-04-20 20:40:13 +04:00
// int32: A coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . a ) ;
2013-04-20 20:40:13 +04:00
// int32: B coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . b ) ;
2013-04-20 20:40:13 +04:00
// uint32: Duration of the movement, in microseconds
2013-11-24 17:04:49 +04:00
write_32 ( gpx , milliseconds * 1000.0 ) ;
2013-04-20 20:40:13 +04:00
// uint8: Axes bitfield to specify which axes are relative. Any axis with a bit set should make a relative movement.
2013-11-24 17:04:49 +04:00
write_8 ( gpx , AXES_BIT_MASK ) ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
return end_frame ( gpx ) ;
2013-04-20 20:40:13 +04:00
}
2013-04-21 21:37:12 +04:00
# endif
2013-04-20 20:40:13 +04:00
2013-04-11 05:32:34 +04:00
// 143 - Store home positions
2013-11-24 17:04:49 +04:00
static int store_home_positions ( Gpx * gpx )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 143 ) ;
2013-04-12 17:47:40 +04:00
// uint8: Axes bitfield to specify which axes' positions to store.
// Any axis with a bit set should have its position stored.
2013-11-24 17:04:49 +04:00
write_8 ( gpx , gpx - > command . flag & AXES_BIT_MASK ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
// 144 - Recall home positions
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
static int recall_home_positions ( Gpx * gpx )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 144 ) ;
2013-04-12 17:47:40 +04:00
// uint8: Axes bitfield to specify which axes' positions to recall.
// Any axis with a bit set should have its position recalled.
2013-11-24 17:04:49 +04:00
write_8 ( gpx , gpx - > command . flag & AXES_BIT_MASK ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 145 - Set digital potentiometer value
2013-11-24 17:04:49 +04:00
static int set_pot_value ( Gpx * gpx , unsigned axis , unsigned value )
2013-04-11 05:32:34 +04:00
{
2013-04-12 17:47:40 +04:00
assert ( axis < = 4 ) ;
assert ( value < = 127 ) ;
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 145 ) ;
2013-04-12 17:47:40 +04:00
2013-04-11 05:32:34 +04:00
// uint8: axis value (valid range 0-4) which axis pot to set
2013-11-24 17:04:49 +04:00
write_8 ( gpx , axis ) ;
2013-04-12 17:47:40 +04:00
2013-04-11 05:32:34 +04:00
// uint8: value (valid range 0-127), values over max will be capped at max
2013-11-24 17:04:49 +04:00
write_8 ( gpx , value ) ;
return end_frame ( gpx ) ;
2013-04-11 05:32:34 +04:00
}
// 146 - Set RGB LED value
2013-04-17 15:54:52 +04:00
2013-11-24 17:04:49 +04:00
static int set_LED ( Gpx * gpx , unsigned red , unsigned green , unsigned blue , unsigned blink )
2013-04-17 15:54:52 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 146 ) ;
2013-04-17 15:54:52 +04:00
// uint8: red value (all pix are 0-255)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , red ) ;
2013-04-17 15:54:52 +04:00
// uint8: green
2013-11-24 17:04:49 +04:00
write_8 ( gpx , green ) ;
2013-04-17 15:54:52 +04:00
// uint8: blue
2013-11-24 17:04:49 +04:00
write_8 ( gpx , blue ) ;
2013-04-17 15:54:52 +04:00
// uint8: blink rate (0-255 valid)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , blink ) ;
2013-04-17 15:54:52 +04:00
// uint8: 0 (reserved for future use)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
2013-04-17 15:54:52 +04:00
}
2013-04-21 21:37:12 +04:00
2013-11-24 17:04:49 +04:00
static int set_LED_RGB ( Gpx * gpx , unsigned rgb , unsigned blink )
2013-04-21 21:37:12 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 146 ) ;
2013-04-21 21:37:12 +04:00
// uint8: red value (all pix are 0-255)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , ( rgb > > 16 ) & 0xFF ) ;
2013-04-21 21:37:12 +04:00
// uint8: green
2013-11-24 17:04:49 +04:00
write_8 ( gpx , ( rgb > > 8 ) & 0xFF ) ;
2013-04-21 21:37:12 +04:00
// uint8: blue
2013-11-24 17:04:49 +04:00
write_8 ( gpx , rgb & 0xFF ) ;
2013-04-21 21:37:12 +04:00
// uint8: blink rate (0-255 valid)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , blink ) ;
2013-04-21 21:37:12 +04:00
// uint8: 0 (reserved for future use)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 0 ) ;
2013-04-21 21:37:12 +04:00
2013-11-24 17:04:49 +04:00
return end_frame ( gpx ) ;
2013-04-21 21:37:12 +04:00
}
2013-04-11 05:32:34 +04:00
// 147 - Set Beep
2013-04-17 15:54:52 +04:00
2013-11-24 17:04:49 +04:00
static int set_beep ( Gpx * gpx , unsigned frequency , unsigned milliseconds )
2013-04-17 15:54:52 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 147 ) ;
2013-04-17 15:54:52 +04:00
// uint16: frequency
2013-11-24 17:04:49 +04:00
write_16 ( gpx , frequency ) ;
2013-04-17 15:54:52 +04:00
// uint16: buzz length in ms
2013-11-24 17:04:49 +04:00
write_16 ( gpx , milliseconds ) ;
2013-04-17 15:54:52 +04:00
// uint8: 0 (reserved for future use)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
2013-04-17 15:54:52 +04:00
}
2013-04-12 17:47:40 +04:00
// 148 - Pause for button
2013-11-24 17:04:49 +04:00
# define BUTTON_CENTER 0x01
# define BUTTON_RIGHT 0x02
# define BUTTON_LEFT 0x04
# define BUTTON_DOWN 0x08
# define BUTTON_UP 0x10
# define BUTTON_RESET 0x20
// Button options
# define READY_ON_TIMEOUT 0x01 // change to ready state on timeout
# define RESET_ON_TIMEOUT 0x02 // reset on timeout
# define CLEAR_ON_PRESS 0x04 // clear screen on button press
static int wait_for_button ( Gpx * gpx , int button , unsigned timeout , int button_options )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 148 ) ;
// uint8: Bit field of buttons to wait for
write_8 ( gpx , button ) ;
// uint16: Timeout, in seconds. A value of 0 indicates that the command should not time out.
write_16 ( gpx , timeout ) ;
// uint8: Options bitfield
write_8 ( gpx , button_options ) ;
return end_frame ( gpx ) ;
}
2013-04-11 05:32:34 +04:00
// 149 - Display message to LCD
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int display_message ( Gpx * gpx , char * message , unsigned vPos , unsigned hPos , unsigned timeout , int wait_for_button )
2013-04-12 17:47:40 +04:00
{
2013-04-21 21:37:12 +04:00
assert ( vPos < 4 ) ;
assert ( hPos < 20 ) ;
2014-01-08 22:20:51 +04:00
int rval ;
2013-04-12 17:47:40 +04:00
long bytesSent = 0 ;
unsigned bitfield = 0 ;
unsigned seconds = 0 ;
2013-04-13 03:30:11 +04:00
unsigned maxLength = hPos ? 20 - hPos : 20 ;
// clip string so it fits in 4 x 20 lcd display buffer
long length = strlen ( message ) ;
if ( vPos | | hPos ) {
if ( length > maxLength ) length = maxLength ;
2013-11-24 17:04:49 +04:00
bitfield | = 0x01 ; //do not clear flag
2013-04-13 03:30:11 +04:00
}
else {
if ( length > 80 ) length = 80 ;
}
2013-04-12 17:47:40 +04:00
while ( bytesSent < length ) {
2013-04-13 03:30:11 +04:00
if ( bytesSent + maxLength > = length ) {
2013-04-12 17:47:40 +04:00
seconds = timeout ;
bitfield | = 0x02 ; // last message in group
if ( wait_for_button ) {
bitfield | = 0x04 ;
}
}
2013-04-22 18:22:44 +04:00
if ( bytesSent > 0 ) {
2013-04-12 17:47:40 +04:00
bitfield | = 0x01 ; //do not clear flag
}
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 149 ) ;
2013-04-12 17:47:40 +04:00
// uint8: Options bitfield (see below)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , bitfield ) ;
2013-04-12 17:47:40 +04:00
// uint8: Horizontal position to display the message at (commonly 0-19)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , hPos ) ;
2013-04-12 17:47:40 +04:00
// uint8: Vertical position to display the message at (commonly 0-3)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , vPos ) ;
2013-04-12 17:47:40 +04:00
// uint8: Timeout, in seconds. If 0, this message will left on the screen
2013-11-24 17:04:49 +04:00
write_8 ( gpx , seconds ) ;
2013-04-12 17:47:40 +04:00
// 1+N bytes: Message to write to the screen, in ASCII, terminated with a null character.
2013-04-17 20:47:52 +04:00
long rowLength = length - bytesSent ;
2013-11-24 17:04:49 +04:00
bytesSent + = write_string ( gpx , message + bytesSent , rowLength < maxLength ? rowLength : maxLength ) ;
2014-01-08 22:20:51 +04:00
CALL ( end_frame ( gpx ) ) ;
2013-04-12 17:47:40 +04:00
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 150 - Set Build Percentage
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int set_build_progress ( Gpx * gpx , unsigned percent )
2013-04-12 17:47:40 +04:00
{
if ( percent > 100 ) percent = 100 ;
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 150 ) ;
2013-04-12 17:47:40 +04:00
// uint8: percent (0-100)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , percent ) ;
2013-04-12 17:47:40 +04:00
2014-01-08 22:20:51 +04:00
// uint8: 0 (reserved for future use)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 151 - Queue Song
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int queue_song ( Gpx * gpx , unsigned song_id )
2013-04-12 17:47:40 +04:00
{
2013-04-16 20:01:26 +04:00
// song ID 0: error tone with 4 cycles
// song ID 1: done tone
// song ID 2: error tone with 2 cycles
2013-04-12 17:47:40 +04:00
assert ( song_id < = 2 ) ;
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 151 ) ;
2013-04-12 17:47:40 +04:00
// uint8: songID: select from a predefined list of songs
2013-11-24 17:04:49 +04:00
write_8 ( gpx , song_id ) ;
return end_frame ( gpx ) ;
}
// 152 - Reset to factory defaults
static int factory_defaults ( Gpx * gpx )
{
begin_frame ( gpx ) ;
write_8 ( gpx , 152 ) ;
// uint8: 0 (reserved for future use)
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 153 - Build start notification
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int start_build ( Gpx * gpx , char * filename )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 153 ) ;
2013-04-12 17:47:40 +04:00
// uint32: 0 (reserved for future use)
2013-11-24 17:04:49 +04:00
write_32 ( gpx , 0 ) ;
2013-04-12 17:47:40 +04:00
// 1+N bytes: Name of the build, in ASCII, null terminated
2013-11-24 17:04:49 +04:00
write_string ( gpx , filename , strlen ( filename ) ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 154 - Build end notification
2013-04-12 17:47:40 +04:00
2013-11-24 17:04:49 +04:00
static int end_build ( Gpx * gpx )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 154 ) ;
2013-04-12 17:47:40 +04:00
// uint8: 0 (reserved for future use)
2013-11-24 17:04:49 +04:00
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 155 - Queue extended point x3g
2013-04-17 15:54:52 +04:00
// IMPORTANT: this command updates the parser state
2013-11-24 17:04:49 +04:00
static int queue_ext_point ( Gpx * gpx , double feedrate )
2013-04-11 05:32:34 +04:00
{
2014-01-08 22:20:51 +04:00
/* If we don't know our previous position on a command axis, we can't calculate the feedrate
or distance correctly , so we use an unaccelerated command with a fixed DDA . */
unsigned mask = gpx - > command . flag & gpx - > axis . mask ;
if ( ( gpx - > axis . positionKnown & mask ) ! = mask ) {
2013-11-24 17:04:49 +04:00
return queue_absolute_point ( gpx ) ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
Point5d deltaMM = delta_mm ( gpx ) ;
Point5d deltaSteps = delta_steps ( gpx , deltaMM ) ;
2013-04-16 20:01:26 +04:00
2013-04-28 19:08:43 +04:00
// check that we have actually moved on at least one axis when the move is
// rounded down to the nearest step
2013-11-24 17:04:49 +04:00
if ( magnitude ( gpx - > command . flag , & deltaSteps ) > 0 ) {
double distance = magnitude ( gpx - > command . flag & XYZ_BIT_MASK , & deltaMM ) ;
2013-06-05 17:35:06 +04:00
// are we moving and extruding?
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . rewrite5D & & ( gpx - > command . flag & ( A_IS_SET | B_IS_SET ) ) & & distance > 0.0001 ) {
2013-06-05 17:35:06 +04:00
double filament_radius , packing_area , packing_scale ;
if ( A_IS_SET & & deltaMM . a > 0.0001 ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > override [ A ] . actual_filament_diameter > 0.0001 ) {
filament_radius = gpx - > override [ A ] . actual_filament_diameter / 2 ;
packing_area = M_PI * filament_radius * filament_radius * gpx - > override [ A ] . packing_density ;
2013-06-05 17:35:06 +04:00
}
else {
2013-11-24 17:04:49 +04:00
filament_radius = gpx - > machine . nominal_filament_diameter / 2 ;
packing_area = M_PI * filament_radius * filament_radius * gpx - > machine . nominal_packing_density ;
2013-06-05 17:35:06 +04:00
}
2013-11-24 17:04:49 +04:00
packing_scale = gpx - > machine . nozzle_diameter * gpx - > layerHeight / packing_area ;
2013-06-05 17:35:06 +04:00
if ( deltaMM . a > 0 ) {
deltaMM . a = distance * packing_scale ;
}
else {
deltaMM . a = - ( distance * packing_scale ) ;
}
2013-11-24 17:04:49 +04:00
gpx - > target . position . a = gpx - > current . position . a + deltaMM . a ;
deltaSteps . a = round ( fabs ( deltaMM . a ) * gpx - > machine . a . steps_per_mm ) ;
2013-06-05 17:35:06 +04:00
}
if ( B_IS_SET & & deltaMM . b > 0.0001 ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > override [ B ] . actual_filament_diameter > 0.0001 ) {
filament_radius = gpx - > override [ B ] . actual_filament_diameter / 2 ;
packing_area = M_PI * filament_radius * filament_radius * gpx - > override [ A ] . packing_density ;
2013-06-05 17:35:06 +04:00
}
else {
2013-11-24 17:04:49 +04:00
filament_radius = gpx - > machine . nominal_filament_diameter / 2 ;
packing_area = M_PI * filament_radius * filament_radius * gpx - > machine . nominal_packing_density ;
2013-06-05 17:35:06 +04:00
}
2013-11-24 17:04:49 +04:00
packing_scale = gpx - > machine . nozzle_diameter * gpx - > layerHeight / packing_area ;
2013-06-05 17:35:06 +04:00
if ( deltaMM . b > 0 ) {
deltaMM . b = distance * packing_scale ;
}
else {
deltaMM . b = - ( distance * packing_scale ) ;
}
2013-11-24 17:04:49 +04:00
gpx - > target . position . b = gpx - > current . position . b + deltaMM . b ;
deltaSteps . b = round ( fabs ( deltaMM . b ) * gpx - > machine . b . steps_per_mm ) ;
2013-06-05 17:35:06 +04:00
}
}
2013-11-24 17:04:49 +04:00
Point5d target = gpx - > target . position ;
2013-04-16 20:01:26 +04:00
2013-04-17 15:54:52 +04:00
target . a = - deltaMM . a ;
target . b = - deltaMM . b ;
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
gpx - > accumulated . a + = deltaMM . a ;
gpx - > accumulated . b + = deltaMM . b ;
2013-11-15 21:17:33 +04:00
2013-04-16 20:01:26 +04:00
deltaMM . x = fabs ( deltaMM . x ) ;
deltaMM . y = fabs ( deltaMM . y ) ;
deltaMM . z = fabs ( deltaMM . z ) ;
deltaMM . a = fabs ( deltaMM . a ) ;
deltaMM . b = fabs ( deltaMM . b ) ;
2013-11-24 17:04:49 +04:00
feedrate = get_safe_feedrate ( gpx , gpx - > command . flag , & deltaMM ) ;
2013-04-16 20:01:26 +04:00
double minutes = distance / feedrate ;
if ( minutes = = 0 ) {
distance = 0 ;
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & A_IS_SET ) {
2013-04-16 20:01:26 +04:00
distance = deltaMM . a ;
}
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & B_IS_SET & & distance < deltaMM . b ) {
2013-04-16 20:01:26 +04:00
distance = deltaMM . b ;
}
minutes = distance / feedrate ;
}
//convert feedrate to mm/sec
feedrate / = 60.0 ;
2013-04-21 21:37:12 +04:00
2013-05-03 17:57:14 +04:00
# if ENABLE_SIMULATED_RPM
// if either a or b is 0, but their motor is on and turning, 'simulate' a 5D extrusion distance
2013-11-24 17:04:49 +04:00
if ( deltaMM . a = = 0.0 & & gpx - > tool [ A ] . motor_enabled & & gpx - > tool [ A ] . rpm ) {
double maxrpm = gpx - > machine . a . max_feedrate * gpx - > machine . a . steps_per_mm / gpx - > machine . a . motor_steps ;
double rpm = gpx - > tool [ A ] . rpm > maxrpm ? maxrpm : gpx - > tool [ A ] . rpm ;
2013-04-20 20:40:13 +04:00
// minute * revolution/minute
2013-11-24 17:04:49 +04:00
double numRevolutions = minutes * ( gpx - > tool [ A ] . motor_enabled > 0 ? rpm : - rpm ) ;
2013-04-20 20:40:13 +04:00
// steps/revolution * mm/steps
2013-11-24 17:04:49 +04:00
double mmPerRevolution = gpx - > machine . a . motor_steps * ( 1 / gpx - > machine . a . steps_per_mm ) ;
2013-04-20 20:40:13 +04:00
// set distance
deltaMM . a = numRevolutions * mmPerRevolution ;
2013-11-24 17:04:49 +04:00
deltaSteps . a = round ( fabs ( deltaMM . a ) * gpx - > machine . a . steps_per_mm ) ;
2013-04-20 20:40:13 +04:00
target . a = - deltaMM . a ;
2013-04-16 20:01:26 +04:00
}
2013-04-19 18:57:33 +04:00
else {
// disable RPM as soon as we begin 5D printing
2013-11-24 17:04:49 +04:00
gpx - > tool [ A ] . rpm = 0 ;
2013-04-19 18:57:33 +04:00
}
2013-11-24 17:04:49 +04:00
if ( deltaMM . b = = 0.0 & & gpx - > tool [ B ] . motor_enabled & & gpx - > tool [ B ] . rpm ) {
double maxrpm = gpx - > machine . b . max_feedrate * gpx - > machine . b . steps_per_mm / gpx - > machine . b . motor_steps ;
double rpm = gpx - > tool [ B ] . rpm > maxrpm ? maxrpm : gpx - > tool [ B ] . rpm ;
2013-04-20 20:40:13 +04:00
// minute * revolution/minute
2013-11-24 17:04:49 +04:00
double numRevolutions = minutes * ( gpx - > tool [ B ] . motor_enabled > 0 ? rpm : - rpm ) ;
2013-04-20 20:40:13 +04:00
// steps/revolution * mm/steps
2013-11-24 17:04:49 +04:00
double mmPerRevolution = gpx - > machine . b . motor_steps * ( 1 / gpx - > machine . b . steps_per_mm ) ;
2013-04-20 20:40:13 +04:00
// set distance
deltaMM . b = numRevolutions * mmPerRevolution ;
2013-11-24 17:04:49 +04:00
deltaSteps . b = round ( fabs ( deltaMM . b ) * gpx - > machine . b . steps_per_mm ) ;
2013-04-20 20:40:13 +04:00
target . b = - deltaMM . b ;
2013-04-16 20:01:26 +04:00
}
2013-04-19 18:57:33 +04:00
else {
// disable RPM as soon as we begin 5D printing
2013-11-24 17:04:49 +04:00
gpx - > tool [ B ] . rpm = 0 ;
2013-04-19 18:57:33 +04:00
}
2013-04-21 21:37:12 +04:00
# endif
2013-11-24 17:04:49 +04:00
Point5d steps = mm_to_steps ( gpx , & target , & gpx - > excess ) ;
2013-04-16 20:01:26 +04:00
2013-04-20 20:40:13 +04:00
double usec = ( 60000000.0 * minutes ) ;
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
double dda_interval = usec / largest_axis ( gpx - > command . flag , & deltaSteps ) ;
2013-04-16 20:01:26 +04:00
// Convert dda_interval into dda_rate (dda steps per second on the longest axis)
2013-04-20 20:40:13 +04:00
double dda_rate = 1000000.0 / dda_interval ;
2013-11-24 17:04:49 +04:00
2014-01-08 22:20:51 +04:00
gpx - > accumulated . time + = ( minutes * 60 ) * ACCELERATION_TIME ;
2013-04-16 20:01:26 +04:00
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 155 ) ;
2013-04-16 20:01:26 +04:00
// int32: X coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . x ) ;
2013-04-16 20:01:26 +04:00
// int32: Y coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . y ) ;
2013-04-16 20:01:26 +04:00
// int32: Z coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . z ) ;
2013-04-16 20:01:26 +04:00
// int32: A coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . a ) ;
2013-04-16 20:01:26 +04:00
// int32: B coordinate, in steps
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( int ) steps . b ) ;
2013-04-16 20:01:26 +04:00
// uint32: DDA Feedrate, in steps/s
2013-11-24 17:04:49 +04:00
write_32 ( gpx , ( unsigned ) dda_rate ) ;
2013-04-16 20:01:26 +04:00
// uint8: Axes bitfield to specify which axes are relative. Any axis with a bit set should make a relative movement.
2013-11-24 17:04:49 +04:00
write_8 ( gpx , A_IS_SET | B_IS_SET ) ;
2013-04-16 20:01:26 +04:00
// float (single precision, 32 bit): mm distance for this move. normal of XYZ if any of these axes are active, and AB for extruder only moves
2013-11-24 17:04:49 +04:00
write_float ( gpx , ( float ) distance ) ;
2013-04-16 20:01:26 +04:00
// uint16: feedrate in mm/s, multiplied by 64 to assist fixed point calculation on the bot
2013-11-24 17:04:49 +04:00
write_16 ( gpx , ( unsigned ) ( feedrate * 64.0 ) ) ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
return end_frame ( gpx ) ;
2013-04-16 20:01:26 +04:00
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-11 05:32:34 +04:00
}
2013-04-12 17:47:40 +04:00
// 156 - Set segment acceleration
2013-11-24 17:04:49 +04:00
static int set_acceleration ( Gpx * gpx , int state )
2013-04-12 17:47:40 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 156 ) ;
2013-04-12 17:47:40 +04:00
// uint8: 1 to enable, 0 to disable
2013-11-24 17:04:49 +04:00
write_8 ( gpx , state ) ;
return end_frame ( gpx ) ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
// 157 - Stream Version
2013-11-24 17:04:49 +04:00
static int stream_version ( Gpx * gpx )
{
if ( gpx - > machine . type > = MACHINE_TYPE_REPLICATOR_1 ) {
begin_frame ( gpx ) ;
write_8 ( gpx , 157 ) ;
// uint8: x3g version high byte
write_8 ( gpx , STREAM_VERSION_HIGH ) ;
// uint8: x3g version low byte
write_8 ( gpx , STREAM_VERSION_LOW ) ;
// uint8: not implemented
write_8 ( gpx , 0 ) ;
// uint32: not implemented
write_32 ( gpx , 0 ) ;
// uint16: bot type: PID for the intended bot is sent
// Repliator 2/2X (Might Two)
if ( gpx - > machine . type > = MACHINE_TYPE_REPLICATOR_2 ) {
write_16 ( gpx , 0xB015 ) ;
}
// Replicator (Might One)
else {
write_16 ( gpx , 0xD314 ) ;
}
// uint16: not implemented
write_16 ( gpx , 0 ) ;
// uint32: not implemented
write_32 ( gpx , 0 ) ;
// uint32: not implemented
write_32 ( gpx , 0 ) ;
// uint8: not implemented
write_8 ( gpx , 0 ) ;
return end_frame ( gpx ) ;
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-11-24 17:04:49 +04:00
}
2013-04-19 08:53:34 +04:00
// 158 - Pause @ zPos
2013-11-24 17:04:49 +04:00
static int pause_at_zpos ( Gpx * gpx , float z_positon )
2013-04-19 08:53:34 +04:00
{
2013-11-24 17:04:49 +04:00
begin_frame ( gpx ) ;
write_8 ( gpx , 158 ) ;
2013-04-19 08:53:34 +04:00
// uint8: pause at Z coordinate or 0.0 to disable
2013-11-24 17:04:49 +04:00
write_float ( gpx , z_positon ) ;
return end_frame ( gpx ) ;
2013-04-19 08:53:34 +04:00
}
2013-11-17 18:37:06 +04:00
// COMMAND @ ZPOS FUNCTIONS
// find an existing filament definition
2013-11-24 17:04:49 +04:00
static int find_filament ( Gpx * gpx , char * filament_id )
2013-11-17 18:37:06 +04:00
{
int i , index = - 1 ;
2013-11-24 17:04:49 +04:00
int l = gpx - > filamentLength ;
2013-11-17 18:37:06 +04:00
// a brute force search is generally fastest for low n
2013-11-24 17:04:49 +04:00
for ( i = 0 ; i < l ; i + + ) {
if ( strcmp ( filament_id , gpx - > filament [ i ] . colour ) = = 0 ) {
2013-11-17 18:37:06 +04:00
index = i ;
break ;
}
}
return index ;
}
// add a new filament definition
2013-11-24 17:04:49 +04:00
static int add_filament ( Gpx * gpx , char * filament_id , double diameter , unsigned temperature , unsigned LED )
2013-11-17 18:37:06 +04:00
{
2013-11-24 17:04:49 +04:00
int index = find_filament ( gpx , filament_id ) ;
2013-11-17 18:37:06 +04:00
if ( index < 0 ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > filamentLength < FILAMENT_MAX ) {
index = gpx - > filamentLength + + ;
gpx - > filament [ index ] . colour = strdup ( filament_id ) ;
gpx - > filament [ index ] . diameter = diameter ;
gpx - > filament [ index ] . temperature = temperature ;
gpx - > filament [ index ] . LED = LED ;
2013-11-17 18:37:06 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Buffer overflow: too many @filament definitions (maximum = %i) " EOL , gpx - > lineNumber , FILAMENT_MAX - 1 ) ) ;
2013-11-17 18:37:06 +04:00
index = 0 ;
}
}
return index ;
}
// append a new command at z function
2013-11-24 17:04:49 +04:00
static int add_command_at ( Gpx * gpx , double z , char * filament_id , unsigned nozzle_temperature , unsigned build_platform_temperature )
2013-11-17 18:37:06 +04:00
{
2013-11-24 17:04:49 +04:00
int rval ;
int index = filament_id ? find_filament ( gpx , filament_id ) : 0 ;
2013-11-17 18:37:06 +04:00
if ( index < 0 ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @pause macro with undefined filament name '%s', use a @filament macro to define it " EOL , gpx - > lineNumber , filament_id ) ) ;
2013-11-17 18:37:06 +04:00
index = 0 ;
}
// insert command
2013-11-24 17:04:49 +04:00
if ( gpx - > commandAtLength < COMMAND_AT_MAX ) {
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . loadMacros ) {
int i = gpx - > commandAtLength ;
if ( z < = gpx - > commandAtZ ) {
// make a space
while ( i > 0 & & z < = gpx - > commandAt [ i - 1 ] . z ) {
gpx - > commandAt [ i ] = gpx - > commandAt [ i - 1 ] ;
i - - ;
}
gpx - > commandAt [ i ] . z = z ;
gpx - > commandAt [ i ] . filament_index = index ;
gpx - > commandAt [ i ] . nozzle_temperature = nozzle_temperature ;
gpx - > commandAt [ i ] . build_platform_temperature = build_platform_temperature ;
gpx - > commandAtZ = gpx - > commandAt [ gpx - > commandAtLength ] . z ;
2013-11-17 18:37:06 +04:00
}
2014-01-08 22:20:51 +04:00
// append command
2013-11-17 18:37:06 +04:00
else {
2014-01-08 22:20:51 +04:00
gpx - > commandAt [ i ] . z = z ;
gpx - > commandAt [ i ] . filament_index = index ;
gpx - > commandAt [ i ] . nozzle_temperature = nozzle_temperature ;
gpx - > commandAt [ i ] . build_platform_temperature = build_platform_temperature ;
gpx - > commandAtZ = z ;
2013-11-17 18:37:06 +04:00
}
2014-01-08 22:20:51 +04:00
// nonzero temperature signals a temperature change, not a pause @ zPos
// so if its the first pause @ zPos que it up
if ( nozzle_temperature = = 0 & & build_platform_temperature = = 0 & & gpx - > commandAtLength = = 0 ) {
if ( gpx - > flag . macrosEnabled ) {
CALL ( pause_at_zpos ( gpx , z ) ) ;
}
else {
gpx - > flag . pausePending = 1 ;
}
}
gpx - > commandAtLength + + ;
2013-11-17 18:37:06 +04:00
}
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Buffer overflow: too many @pause definitions (maximum = %i) " EOL , gpx - > lineNumber , COMMAND_AT_MAX ) ) ;
2013-11-17 18:37:06 +04:00
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
}
static int display_tag ( Gpx * gpx ) {
int rval ;
CALL ( display_message ( gpx , " GPX " GPX_VERSION , 0 , 0 , 2 , 0 ) ) ;
return SUCCESS ;
2013-11-17 18:37:06 +04:00
}
2013-04-29 22:26:36 +04:00
// TARGET POSITION
// calculate target position
2013-11-24 17:04:49 +04:00
static int calculate_target_position ( Gpx * gpx )
2013-04-29 22:26:36 +04:00
{
2014-01-08 22:20:51 +04:00
int rval ;
2013-11-24 17:04:49 +04:00
// G10 ofset
Point3d userOffset = gpx - > offset [ gpx - > current . offset ] ;
2014-01-08 22:20:51 +04:00
double userScale = 1.0 ;
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . macrosEnabled ) {
// plus command line offset
2014-01-08 22:20:51 +04:00
userOffset . x + = gpx - > user . offset . x ;
userOffset . y + = gpx - > user . offset . y ;
userOffset . z + = gpx - > user . offset . z ;
// multiply by command line scale
userScale = gpx - > user . scale ;
2013-05-14 06:44:55 +04:00
}
2013-04-29 22:26:36 +04:00
// CALCULATE TARGET POSITION
// x
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & X_IS_SET ) {
2014-01-08 22:20:51 +04:00
gpx - > target . position . x = gpx - > flag . relativeCoordinates ? ( gpx - > current . position . x + ( gpx - > command . x * userScale ) ) : ( ( gpx - > command . x + userOffset . x ) * userScale ) ;
2013-04-29 22:26:36 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > target . position . x = gpx - > current . position . x ;
2013-04-29 22:26:36 +04:00
}
// y
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & Y_IS_SET ) {
2014-01-08 22:20:51 +04:00
gpx - > target . position . y = gpx - > flag . relativeCoordinates ? ( gpx - > current . position . y + ( gpx - > command . y * userScale ) ) : ( ( gpx - > command . y + userOffset . y ) * userScale ) ;
2013-04-29 22:26:36 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > target . position . y = gpx - > current . position . y ;
2013-04-29 22:26:36 +04:00
}
// z
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & Z_IS_SET ) {
2014-01-08 22:20:51 +04:00
gpx - > target . position . z = gpx - > flag . relativeCoordinates ? ( gpx - > current . position . z + ( gpx - > command . z * userScale ) ) : ( ( gpx - > command . z + userOffset . z ) * userScale ) ;
2013-04-29 22:26:36 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > target . position . z = gpx - > current . position . z ;
2013-04-29 22:26:36 +04:00
}
2013-05-17 04:59:01 +04:00
2013-04-29 22:26:36 +04:00
// a
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & A_IS_SET ) {
double a = ( gpx - > override [ A ] . filament_scale = = 1.0 ) ? gpx - > command . a : ( gpx - > command . a * gpx - > override [ A ] . filament_scale ) ;
gpx - > target . position . a = ( gpx - > flag . relativeCoordinates | | gpx - > flag . extruderIsRelative ) ? ( gpx - > current . position . a + a ) : a ;
2013-04-29 22:26:36 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > target . position . a = gpx - > current . position . a ;
2013-04-29 22:26:36 +04:00
}
2013-05-17 04:59:01 +04:00
2013-04-29 22:26:36 +04:00
// b
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & B_IS_SET ) {
double b = ( gpx - > override [ B ] . filament_scale = = 1.0 ) ? gpx - > command . b : ( gpx - > command . b * gpx - > override [ B ] . filament_scale ) ;
gpx - > target . position . b = ( gpx - > flag . relativeCoordinates | | gpx - > flag . extruderIsRelative ) ? ( gpx - > current . position . b + b ) : b ;
2013-04-29 22:26:36 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > target . position . b = gpx - > current . position . b ;
2013-04-29 22:26:36 +04:00
}
// update current feedrate
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & F_IS_SET ) {
gpx - > current . feedrate = gpx - > command . f ;
2013-04-29 22:26:36 +04:00
}
// DITTO PRINTING
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . dittoPrinting ) {
if ( gpx - > command . flag & A_IS_SET ) {
gpx - > target . position . b = gpx - > target . position . a ;
gpx - > command . flag | = B_IS_SET ;
2013-04-29 22:26:36 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( gpx - > command . flag & B_IS_SET ) {
gpx - > target . position . a = gpx - > target . position . b ;
gpx - > command . flag | = A_IS_SET ;
2013-04-29 22:26:36 +04:00
}
}
// CHECK FOR COMMAND @ Z POS
// check if there are more commands on the stack
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . macrosEnabled & & gpx - > flag . runMacros & & gpx - > commandAtIndex < gpx - > commandAtLength ) {
2013-04-29 22:26:36 +04:00
// check if the next command will cross the z threshold
2013-11-24 17:04:49 +04:00
if ( gpx - > commandAt [ gpx - > commandAtIndex ] . z < = gpx - > target . position . z ) {
2013-04-29 22:26:36 +04:00
// is this a temperature change macro?
2013-11-24 17:04:49 +04:00
if ( gpx - > commandAt [ gpx - > commandAtIndex ] . nozzle_temperature | | gpx - > commandAt [ gpx - > commandAtIndex ] . build_platform_temperature ) {
unsigned nozzle_temperature = gpx - > commandAt [ gpx - > commandAtIndex ] . nozzle_temperature ;
unsigned build_platform_temperature = gpx - > commandAt [ gpx - > commandAtIndex ] . build_platform_temperature ;
2013-04-29 22:26:36 +04:00
// make sure the temperature has changed
2013-11-17 18:37:06 +04:00
if ( nozzle_temperature ) {
2013-11-24 17:04:49 +04:00
if ( ( gpx - > current . extruder = = A | | gpx - > tool [ A ] . nozzle_temperature ) & & gpx - > tool [ A ] . nozzle_temperature ! = nozzle_temperature ) {
CALL ( set_nozzle_temperature ( gpx , A , nozzle_temperature ) ) ;
gpx - > tool [ A ] . nozzle_temperature = gpx - > override [ A ] . active_temperature = nozzle_temperature ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@zPos %0.2f) Nozzle[A] temperature %uc " EOL ,
gpx - > commandAt [ gpx - > commandAtIndex ] . z ,
nozzle_temperature ) ) ;
2013-04-29 22:26:36 +04:00
}
2013-11-24 17:04:49 +04:00
if ( ( gpx - > current . extruder = = B | | gpx - > tool [ B ] . nozzle_temperature ) & & gpx - > tool [ B ] . nozzle_temperature ! = nozzle_temperature ) {
CALL ( set_nozzle_temperature ( gpx , B , nozzle_temperature ) ) ;
gpx - > tool [ B ] . nozzle_temperature = gpx - > override [ B ] . active_temperature = nozzle_temperature ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@zPos %0.2f) Nozzle[B] temperature %uc " EOL ,
gpx - > commandAt [ gpx - > commandAtIndex ] . z ,
nozzle_temperature ) ) ;
2013-11-17 18:37:06 +04:00
}
}
if ( build_platform_temperature ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . a . has_heated_build_platform & & gpx - > tool [ A ] . build_platform_temperature & & gpx - > tool [ A ] . build_platform_temperature ! = build_platform_temperature ) {
CALL ( set_build_platform_temperature ( gpx , A , build_platform_temperature ) ) ;
gpx - > tool [ A ] . build_platform_temperature = gpx - > override [ A ] . build_platform_temperature = build_platform_temperature ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@zPos %0.2f) Build platform[A] temperature %uc " EOL ,
gpx - > commandAt [ gpx - > commandAtIndex ] . z ,
build_platform_temperature ) ) ;
2013-11-17 18:37:06 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( gpx - > machine . b . has_heated_build_platform & & gpx - > tool [ B ] . build_platform_temperature & & gpx - > tool [ B ] . build_platform_temperature ! = build_platform_temperature ) {
CALL ( set_build_platform_temperature ( gpx , B , build_platform_temperature ) ) ;
gpx - > tool [ B ] . build_platform_temperature = gpx - > override [ B ] . build_platform_temperature = build_platform_temperature ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@zPos %0.2f) Build platform[B] temperature %uc " EOL ,
gpx - > commandAt [ gpx - > commandAtIndex ] . z ,
build_platform_temperature ) ) ;
2013-04-29 22:26:36 +04:00
}
}
2013-11-24 17:04:49 +04:00
gpx - > commandAtIndex + + ;
2013-04-29 22:26:36 +04:00
}
// no its a pause macro
2013-11-24 17:04:49 +04:00
else if ( gpx - > commandAt [ gpx - > commandAtIndex ] . z < = gpx - > target . position . z ) {
int index = gpx - > commandAt [ gpx - > commandAtIndex ] . filament_index ;
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@zPos %0.2f) %s " ,
gpx - > commandAt [ gpx - > commandAtIndex ] . z ,
gpx - > filament [ index ] . colour ) ) ;
2013-04-29 22:26:36 +04:00
// override filament diameter
2014-01-08 22:20:51 +04:00
double filament_diameter = gpx - > filament [ index ] . diameter ;
if ( filament_diameter > 0.0001 ) {
VERBOSE ( fprintf ( gpx - > log , " , %0.2fmm " , filament_diameter ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . dittoPrinting ) {
2014-01-08 22:20:51 +04:00
set_filament_scale ( gpx , B , filament_diameter ) ;
set_filament_scale ( gpx , A , filament_diameter ) ;
2013-04-29 22:26:36 +04:00
}
else {
2014-01-08 22:20:51 +04:00
set_filament_scale ( gpx , gpx - > current . extruder , filament_diameter ) ;
2013-04-29 22:26:36 +04:00
}
}
2014-01-08 22:20:51 +04:00
unsigned temperature = gpx - > filament [ index ] . temperature ;
2013-04-29 22:26:36 +04:00
// override nozzle temperature
2014-01-08 22:20:51 +04:00
if ( temperature ) {
VERBOSE ( fprintf ( gpx - > log , " , %uc " , temperature ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ gpx - > current . extruder ] . nozzle_temperature ! = temperature ) {
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_nozzle_temperature ( gpx , B , temperature ) ) ;
CALL ( set_nozzle_temperature ( gpx , A , temperature ) ) ;
gpx - > tool [ A ] . nozzle_temperature = gpx - > tool [ B ] . nozzle_temperature = temperature ;
2013-04-29 22:26:36 +04:00
}
else {
2013-11-24 17:04:49 +04:00
CALL ( set_nozzle_temperature ( gpx , gpx - > current . extruder , temperature ) ) ;
gpx - > tool [ gpx - > current . extruder ] . nozzle_temperature = temperature ;
2013-04-29 22:26:36 +04:00
}
}
}
// override LED colour
2013-11-24 17:04:49 +04:00
if ( gpx - > filament [ index ] . LED ) {
CALL ( set_LED_RGB ( gpx , gpx - > filament [ index ] . LED , 0 ) ) ;
2013-04-29 22:26:36 +04:00
}
2013-11-24 17:04:49 +04:00
gpx - > commandAtIndex + + ;
if ( gpx - > commandAtIndex < gpx - > commandAtLength ) {
gpx - > flag . doPauseAtZPos = COMMAND_QUE_MAX ;
2013-04-29 22:26:36 +04:00
}
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( EOL , gpx - > log ) ) ;
2013-04-29 22:26:36 +04:00
}
}
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-29 22:26:36 +04:00
}
2013-11-24 17:04:49 +04:00
static void update_current_position ( Gpx * gpx )
2013-06-05 17:35:06 +04:00
{
2013-11-15 21:17:33 +04:00
// the current position to tracks where the print head currently is
2013-11-24 17:04:49 +04:00
if ( gpx - > target . position . z ! = gpx - > current . position . z ) {
2013-06-05 17:35:06 +04:00
// calculate layer height
2013-11-24 17:04:49 +04:00
gpx - > layerHeight = fabs ( gpx - > target . position . z - gpx - > current . position . z ) ;
2013-06-05 17:35:06 +04:00
// check upper bounds
2013-11-24 17:04:49 +04:00
if ( gpx - > layerHeight > ( gpx - > machine . nozzle_diameter * 0.85 ) ) {
gpx - > layerHeight = gpx - > machine . nozzle_diameter * 0.85 ;
2013-06-05 17:35:06 +04:00
}
}
2013-11-24 17:04:49 +04:00
gpx - > current . position = gpx - > target . position ;
2014-01-08 22:20:51 +04:00
if ( ! gpx - > flag . relativeCoordinates ) gpx - > axis . positionKnown | = gpx - > command . flag & gpx - > axis . mask ;
2013-06-05 17:35:06 +04:00
}
2013-04-29 22:26:36 +04:00
// TOOL CHANGE
2013-11-24 17:04:49 +04:00
static int do_tool_change ( Gpx * gpx , int timeout ) {
int rval ;
2013-04-29 22:26:36 +04:00
// set the temperature of current tool to standby (if standby is different to active)
2013-11-24 17:04:49 +04:00
if ( gpx - > override [ gpx - > current . extruder ] . standby_temperature
& & gpx - > override [ gpx - > current . extruder ] . standby_temperature ! = gpx - > tool [ gpx - > current . extruder ] . nozzle_temperature ) {
unsigned temperature = gpx - > override [ gpx - > current . extruder ] . standby_temperature ;
CALL ( set_nozzle_temperature ( gpx , gpx - > current . extruder , temperature ) ) ;
gpx - > tool [ gpx - > current . extruder ] . nozzle_temperature = temperature ;
2013-04-29 22:26:36 +04:00
}
// set the temperature of selected tool to active (if active is different to standby)
2013-11-24 17:04:49 +04:00
if ( gpx - > override [ gpx - > target . extruder ] . active_temperature
& & gpx - > override [ gpx - > target . extruder ] . active_temperature ! = gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature ) {
unsigned temperature = gpx - > override [ gpx - > target . extruder ] . active_temperature ;
CALL ( set_nozzle_temperature ( gpx , gpx - > target . extruder , temperature ) ) ;
gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature = temperature ;
2013-04-29 22:26:36 +04:00
// wait for nozzle to head up
2013-11-24 17:04:49 +04:00
// CALL( wait_for_extruder(gpx, gpx->target.extruder, timeout) );
2013-04-29 22:26:36 +04:00
}
// switch any active G10 offset (G54 or G55)
2013-11-24 17:04:49 +04:00
if ( gpx - > current . offset = = gpx - > current . extruder + 1 ) {
gpx - > current . offset = gpx - > target . extruder + 1 ;
2013-04-29 22:26:36 +04:00
}
// change current toolhead in order to apply the calibration offset
2013-11-24 17:04:49 +04:00
CALL ( change_extruder_offset ( gpx , gpx - > target . extruder ) ) ;
2013-04-29 22:26:36 +04:00
// set current extruder so changes in E are expressed as changes to A or B
2013-11-24 17:04:49 +04:00
gpx - > current . extruder = gpx - > target . extruder ;
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-29 22:26:36 +04:00
}
2013-04-21 21:37:12 +04:00
// PARSER PRE-PROCESSOR
2013-04-18 21:36:22 +04:00
2013-04-11 05:32:34 +04:00
// return the length of the given file in bytes
static long get_filesize ( FILE * file )
{
long filesize = - 1 ;
fseek ( file , 0L , SEEK_END ) ;
filesize = ftell ( file ) ;
fseek ( file , 0L , SEEK_SET ) ;
return filesize ;
}
2013-04-18 21:36:22 +04:00
// clean up the gcode command for processing
2013-04-11 05:32:34 +04:00
static char * normalize_word ( char * p )
{
// we expect a letter followed by a digit
// [ a-zA-Z] [ +-]? [ 0-9]+ ('.' [ 0-9]*)?
char * s = p + 1 ;
char * e = p ;
while ( isspace ( * s ) ) s + + ;
if ( * s = = ' + ' | | * s = = ' - ' ) {
* e + + = * s + + ;
}
while ( 1 ) {
// skip spaces
if ( isspace ( * s ) ) {
s + + ;
}
// append digits
else if ( isdigit ( * s ) ) {
* e + + = * s + + ;
}
else {
break ;
}
}
if ( * s = = ' . ' ) {
* e + + = * s + + ;
while ( 1 ) {
// skip spaces
if ( isspace ( * s ) ) {
s + + ;
}
// append digits
else if ( isdigit ( * s ) ) {
* e + + = * s + + ;
}
else {
break ;
}
}
}
* e = 0 ;
return s ;
}
2013-04-18 21:36:22 +04:00
// clean up the gcode comment for processing
2013-04-11 05:32:34 +04:00
static char * normalize_comment ( char * p ) {
// strip white space from the end of comment
char * e = p + strlen ( p ) ;
while ( e > p & & isspace ( ( unsigned char ) ( * - - e ) ) ) * e = ' \0 ' ;
// strip white space from the beginning of comment.
while ( isspace ( * p ) ) p + + ;
return p ;
}
2013-04-21 21:37:12 +04:00
// MACRO PARSER
/* format
2013-04-22 18:22:44 +04:00
; @ < STRING > < STRING > < FLOAT > < FLOAT > mm < INTEGER > c # < HEX > ( < STRING > )
MACRO : = ' ; ' ' @ ' COMMAND COMMENT EOL
COMMAND : = PRINTER | ENABLE | FILAMENT | EXTRUDER | SLICER | START | PAUSE
COMMENT : = S + ' ( ' [ ^ ) ] * ' ) ' S +
2013-06-05 17:35:06 +04:00
PRINTER : = ( ' printer ' | ' machine ' | ' slicer ' ) ( TYPE | PACKING_DENSITY | DIAMETER | TEMP | RGB ) +
2013-08-22 15:48:32 +04:00
TYPE : = S + ( ' c3 ' | ' c4 ' | ' cp4 ' | ' cpp ' | ' t6 ' | ' t7 ' | ' t7d ' | ' r1 ' | ' r1d ' | ' r2 ' | ' r2h ' | ' r2x ' )
2013-06-05 17:35:06 +04:00
PACKING_DENSITY : = S + DIGIT + ( ' . ' DIGIT + ) ?
2013-04-22 18:22:44 +04:00
DIAMETER : = S + DIGIT + ( ' . ' DIGIT + ) ? ' m ' ' m ' ?
TEMP : = S + DIGIT + ' c '
RGB : = S + ' # ' HEX HEX HEX HEX HEX HEX ; LED colour
ENABLE : = ' enable ' ( DITTO | PROGRESS )
DITTO : = S + ' ditto ' ; Simulated ditto printing
PROGRESS : = S + ' progress ' ; Override build progress
FILAMENT : = ' filament ' FILAMENT_ID ( DIAMETER | TEMP | RGB ) +
FILAMENT_ID : = S + ALPHA + ALPHA_NUMERIC *
EXTRUDER : = ( ' right ' | ' left ' ) ( FILAMENT_ID | DIAMETER | TEMP ) +
SLICER : = ' slicer ' DIAMETER ; Nominal filament diameter
2013-04-29 22:26:36 +04:00
START : = ' start ' ( FILAMENT_ID | TEMPERATURE )
PAUSE : = ' pause ' ( ZPOS | FILAMENT_ID | TEMPERATURE ) +
2013-04-22 18:22:44 +04:00
ZPOS : = S + DIGIT + ( ' . ' DIGIT + ) ?
2013-04-21 21:37:12 +04:00
*/
# define MACRO_IS(token) strcmp(token, macro) == 0
2013-04-29 22:26:36 +04:00
# define NAME_IS(n) strcasecmp(name, n) == 0
2013-04-21 21:37:12 +04:00
2013-11-24 17:04:49 +04:00
static int parse_macro ( Gpx * gpx , const char * macro , char * p )
2013-04-21 21:37:12 +04:00
{
2014-01-08 22:20:51 +04:00
int rval ;
2013-04-21 21:37:12 +04:00
char * name = NULL ;
double z = 0.0 ;
double diameter = 0.0 ;
2013-11-17 18:37:06 +04:00
unsigned nozzle_temperature = 0 ;
unsigned build_platform_temperature = 0 ;
2013-04-21 21:37:12 +04:00
unsigned LED = 0 ;
2013-04-29 22:26:36 +04:00
2013-04-21 21:37:12 +04:00
while ( * p ! = 0 ) {
// trim any leading white space
while ( isspace ( * p ) ) p + + ;
if ( isalpha ( * p ) ) {
name = p ;
2013-11-15 21:17:33 +04:00
while ( * p & & isalnum ( * p ) ) p + + ;
2013-04-21 21:37:12 +04:00
if ( * p ) * p + + = 0 ;
}
else if ( isdigit ( * p ) ) {
char * t = p ;
while ( * p & & ! isspace ( * p ) ) p + + ;
if ( * ( p - 1 ) = = ' m ' ) {
diameter = strtod ( t , NULL ) ;
}
else if ( * ( p - 1 ) = = ' c ' ) {
2013-11-17 18:37:06 +04:00
unsigned temperature = atoi ( t ) ;
if ( temperature > HBP_MAX ) {
nozzle_temperature = temperature ;
}
else {
build_platform_temperature = temperature ;
}
2013-04-21 21:37:12 +04:00
}
else {
z = strtod ( t , NULL ) ;
}
if ( * p ) * p + + = 0 ;
}
else if ( * p = = ' # ' ) {
char * t = + + p ;
while ( * p & & ! isspace ( * p ) ) p + + ;
if ( * p ) * p + + = 0 ;
LED = ( unsigned ) strtol ( t , NULL , 16 ) ;
}
else if ( * p = = ' ( ' ) {
2013-11-15 21:17:33 +04:00
char * t = strchr ( p + 1 , ' ) ' ) ;
2013-04-21 21:37:12 +04:00
if ( t ) {
* t = 0 ;
p = t + 1 ;
}
else {
* p = 0 ;
}
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: unrecognised macro parameter " EOL , gpx - > lineNumber ) ) ;
2013-04-21 21:37:12 +04:00
break ;
}
}
2013-06-05 17:35:06 +04:00
// ;@printer <TYPE> <PACKING_DENSITY> <DIAMETER>mm <HBP-TEMP>c #<LED-COLOUR>
2013-04-22 18:22:44 +04:00
if ( MACRO_IS ( " machine " ) | | MACRO_IS ( " printer " ) | | MACRO_IS ( " slicer " ) ) {
2013-04-21 21:37:12 +04:00
if ( name ) {
2013-11-24 17:04:49 +04:00
if ( gpx_set_machine ( gpx , name ) ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @%s macro with unrecognised type '%s' " EOL , gpx - > lineNumber , macro , name ) ) ;
2013-04-21 21:37:12 +04:00
}
2013-11-24 17:04:49 +04:00
gpx - > override [ A ] . packing_density = gpx - > machine . nominal_packing_density ;
gpx - > override [ B ] . packing_density = gpx - > machine . nominal_packing_density ;
2013-06-05 17:35:06 +04:00
}
if ( z > 0.0001 ) {
2013-11-24 17:04:49 +04:00
gpx - > machine . nominal_packing_density = z ;
2013-04-21 21:37:12 +04:00
}
2013-11-24 17:04:49 +04:00
if ( diameter > 0.0001 ) gpx - > machine . nominal_filament_diameter = diameter ;
2013-11-17 18:37:06 +04:00
if ( build_platform_temperature ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . a . has_heated_build_platform ) gpx - > override [ A ] . build_platform_temperature = build_platform_temperature ;
else if ( gpx - > machine . b . has_heated_build_platform ) gpx - > override [ B ] . build_platform_temperature = build_platform_temperature ;
2013-04-21 21:37:12 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: @%s macro cannot override non-existant heated build platform " EOL , gpx - > lineNumber , macro ) ) ;
2013-04-21 21:37:12 +04:00
}
}
2013-11-24 17:04:49 +04:00
if ( LED ) {
CALL ( set_LED_RGB ( gpx , LED , 0 ) ) ;
}
2013-04-21 21:37:12 +04:00
}
// ;@enable ditto
// ;@enable progress
else if ( MACRO_IS ( " enable " ) ) {
if ( name ) {
2013-04-22 18:22:44 +04:00
if ( NAME_IS ( " ditto " ) ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . extruder_count = = 1 ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: ditto printing cannot access non-existant second extruder " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
gpx - > flag . dittoPrinting = 0 ;
2013-04-22 18:22:44 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > flag . dittoPrinting = 1 ;
2013-04-22 18:22:44 +04:00
}
}
2013-11-24 17:04:49 +04:00
else if ( NAME_IS ( " progress " ) ) gpx - > flag . buildProgress = 1 ;
2013-04-22 18:22:44 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @enable macro with unrecognised parameter '%s' " EOL , gpx - > lineNumber , name ) ) ;
2013-04-22 18:22:44 +04:00
}
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: @enable macro with missing parameter " EOL , gpx - > lineNumber ) ) ;
2013-04-21 21:37:12 +04:00
}
}
2013-04-29 22:26:36 +04:00
// ;@filament <NAME> <DIAMETER>mm <TEMP>c #<LED-COLOUR>
2013-04-21 21:37:12 +04:00
else if ( MACRO_IS ( " filament " ) ) {
if ( name ) {
2013-11-24 17:04:49 +04:00
add_filament ( gpx , name , diameter , nozzle_temperature , LED ) ;
2013-04-21 21:37:12 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @filament macro with missing name " EOL , gpx - > lineNumber ) ) ;
2013-04-22 18:22:44 +04:00
}
}
2013-06-05 17:35:06 +04:00
// ;@right <NAME> <PACKING_DENSITY> <DIAMETER>mm <TEMP>c
2013-04-22 18:22:44 +04:00
else if ( MACRO_IS ( " right " ) ) {
if ( name ) {
2013-11-24 17:04:49 +04:00
int index = find_filament ( gpx , name ) ;
2013-04-22 18:22:44 +04:00
if ( index > 0 ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > filament [ index ] . diameter > 0.0001 ) set_filament_scale ( gpx , A , gpx - > filament [ index ] . diameter ) ;
if ( gpx - > filament [ index ] . temperature ) gpx - > override [ A ] . active_temperature = gpx - > filament [ index ] . temperature ;
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-22 18:22:44 +04:00
}
2013-04-21 21:37:12 +04:00
}
2013-11-24 17:04:49 +04:00
if ( z > 0.0001 ) gpx - > override [ A ] . packing_density = z ;
if ( diameter > 0.0001 ) set_filament_scale ( gpx , A , diameter ) ;
if ( nozzle_temperature ) gpx - > override [ A ] . active_temperature = nozzle_temperature ;
2013-04-21 21:37:12 +04:00
}
2013-06-05 17:35:06 +04:00
// ;@left <NAME> <PACKING_DENSITY> <DIAMETER>mm <TEMP>c
2013-04-22 18:22:44 +04:00
else if ( MACRO_IS ( " left " ) ) {
if ( name ) {
2013-11-24 17:04:49 +04:00
int index = find_filament ( gpx , name ) ;
2013-04-22 18:22:44 +04:00
if ( index > 0 ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > filament [ index ] . diameter > 0.0001 ) set_filament_scale ( gpx , B , gpx - > filament [ index ] . diameter ) ;
if ( gpx - > filament [ index ] . temperature ) gpx - > override [ B ] . active_temperature = gpx - > filament [ index ] . temperature ;
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-22 18:22:44 +04:00
}
}
2013-11-24 17:04:49 +04:00
if ( z > 0.0001 ) gpx - > override [ A ] . packing_density = z ;
if ( diameter > 0.0001 ) set_filament_scale ( gpx , B , diameter ) ;
if ( nozzle_temperature ) gpx - > override [ B ] . active_temperature = nozzle_temperature ;
2013-04-22 18:22:44 +04:00
}
// ;@pause <ZPOS> <NAME>
2013-04-21 21:37:12 +04:00
else if ( MACRO_IS ( " pause " ) ) {
2013-04-29 22:26:36 +04:00
if ( z > 0.0001 ) {
2013-11-24 17:04:49 +04:00
CALL ( add_command_at ( gpx , z , name , 0 , 0 ) ) ;
2013-11-17 18:37:06 +04:00
}
else if ( diameter > 0.0001 ) {
2013-11-24 17:04:49 +04:00
CALL ( add_command_at ( gpx , diameter , name , 0 , 0 ) ) ;
2013-04-29 22:26:36 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @pause macro with missing zPos " EOL , gpx - > lineNumber ) ) ;
2013-04-29 22:26:36 +04:00
}
}
// ;@temp <ZPOS> <TEMP>c
// ;@temperature <ZPOS> <TEMP>c
else if ( MACRO_IS ( " temp " ) | | MACRO_IS ( " temperature " ) ) {
2013-11-17 18:37:06 +04:00
if ( nozzle_temperature | | build_platform_temperature ) {
2013-04-29 22:26:36 +04:00
if ( z > 0.0001 ) {
2013-11-24 17:04:49 +04:00
CALL ( add_command_at ( gpx , z , NULL , nozzle_temperature , build_platform_temperature ) ) ;
2013-11-17 18:37:06 +04:00
}
else if ( diameter > 0.0001 ) {
2013-11-24 17:04:49 +04:00
CALL ( add_command_at ( gpx , diameter , NULL , nozzle_temperature , build_platform_temperature ) ) ;
2013-04-29 22:26:36 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @%s macro with missing zPos " EOL , gpx - > lineNumber , macro ) ) ;
2013-04-29 22:26:36 +04:00
}
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @%s macro with missing temperature " EOL , gpx - > lineNumber , macro ) ) ;
2013-04-29 22:26:36 +04:00
}
2013-04-21 21:37:12 +04:00
}
2013-04-29 22:26:36 +04:00
// ;@start <NAME> <TEMP>c
2013-04-21 21:37:12 +04:00
else if ( MACRO_IS ( " start " ) ) {
2013-11-17 18:37:06 +04:00
if ( nozzle_temperature | | build_platform_temperature ) {
if ( nozzle_temperature ) {
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@start) Nozzle temperature %uc " EOL , nozzle_temperature ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ A ] . nozzle_temperature & & gpx - > tool [ A ] . nozzle_temperature ! = nozzle_temperature ) {
if ( program_is_running ( ) ) {
CALL ( set_nozzle_temperature ( gpx , A , nozzle_temperature ) ) ;
}
gpx - > tool [ A ] . nozzle_temperature = gpx - > override [ A ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > override [ A ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ B ] . nozzle_temperature & & gpx - > tool [ B ] . nozzle_temperature ! = nozzle_temperature ) {
if ( program_is_running ( ) ) {
CALL ( set_nozzle_temperature ( gpx , B , nozzle_temperature ) ) ;
}
gpx - > tool [ B ] . nozzle_temperature = gpx - > override [ B ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > override [ B ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
2013-04-21 21:37:12 +04:00
}
2013-11-17 18:37:06 +04:00
if ( build_platform_temperature ) {
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@start) Build platform temperature %uc " EOL , build_platform_temperature ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > machine . a . has_heated_build_platform & & gpx - > tool [ A ] . build_platform_temperature & & gpx - > tool [ A ] . build_platform_temperature ! = build_platform_temperature ) {
if ( program_is_running ( ) ) {
CALL ( set_build_platform_temperature ( gpx , A , build_platform_temperature ) ) ;
}
gpx - > tool [ A ] . build_platform_temperature = gpx - > override [ A ] . build_platform_temperature = build_platform_temperature ;
2013-11-17 18:37:06 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( gpx - > machine . b . has_heated_build_platform & & gpx - > tool [ B ] . build_platform_temperature & & gpx - > tool [ B ] . build_platform_temperature ! = build_platform_temperature ) {
if ( program_is_running ( ) ) {
CALL ( set_build_platform_temperature ( gpx , B , build_platform_temperature ) ) ;
}
gpx - > tool [ B ] . build_platform_temperature = gpx - > override [ B ] . build_platform_temperature = build_platform_temperature ;
2013-11-17 18:37:06 +04:00
}
2013-04-21 21:37:12 +04:00
}
}
2013-11-15 21:17:33 +04:00
else if ( name ) {
2013-11-24 17:04:49 +04:00
int index = find_filament ( gpx , name ) ;
2013-04-29 22:26:36 +04:00
if ( index > 0 ) {
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " (@start) %s " , name ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > filament [ index ] . diameter > 0.0001 ) {
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " , %0.2fmm " , gpx - > filament [ index ] . diameter ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . dittoPrinting ) {
set_filament_scale ( gpx , B , gpx - > filament [ index ] . diameter ) ;
set_filament_scale ( gpx , A , gpx - > filament [ index ] . diameter ) ;
2013-04-29 22:26:36 +04:00
}
2013-11-17 18:37:06 +04:00
else {
2013-11-24 17:04:49 +04:00
set_filament_scale ( gpx , gpx - > current . extruder , gpx - > filament [ index ] . diameter ) ;
2013-04-29 22:26:36 +04:00
}
}
2013-11-24 17:04:49 +04:00
if ( gpx - > filament [ index ] . LED ) {
CALL ( set_LED_RGB ( gpx , gpx - > filament [ index ] . LED , 0 ) ) ;
}
nozzle_temperature = gpx - > filament [ index ] . temperature ;
2013-11-17 18:37:06 +04:00
if ( nozzle_temperature ) {
2014-01-08 22:20:51 +04:00
VERBOSE ( fprintf ( gpx - > log , " , %uc " , nozzle_temperature ) ) ;
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ A ] . nozzle_temperature & & gpx - > tool [ A ] . nozzle_temperature ! = nozzle_temperature ) {
if ( program_is_running ( ) ) {
CALL ( set_nozzle_temperature ( gpx , A , nozzle_temperature ) ) ;
}
gpx - > tool [ A ] . nozzle_temperature = gpx - > override [ A ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > override [ A ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ B ] . nozzle_temperature & & gpx - > tool [ B ] . nozzle_temperature ! = nozzle_temperature ) {
if ( program_is_running ( ) ) {
CALL ( set_nozzle_temperature ( gpx , B , nozzle_temperature ) ) ;
}
gpx - > tool [ B ] . nozzle_temperature = gpx - > override [ B ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
else {
2013-11-24 17:04:49 +04:00
gpx - > override [ B ] . active_temperature = nozzle_temperature ;
2013-11-17 18:37:06 +04:00
}
2013-04-29 22:26:36 +04:00
}
2014-01-08 22:20:51 +04:00
VERBOSE ( fputs ( EOL , gpx - > log ) ) ;
2013-04-29 22:26:36 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: @start with undefined filament name '%s', use a @filament macro to define it " EOL , gpx - > lineNumber , name ? name : " " ) ) ;
2013-04-29 22:26:36 +04:00
}
2013-04-22 18:22:44 +04:00
}
2013-04-21 21:37:12 +04:00
}
2013-05-03 17:57:14 +04:00
// ;@body
else if ( MACRO_IS ( " body " ) ) {
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . pausePending ) {
CALL ( pause_at_zpos ( gpx , gpx - > commandAt [ 0 ] . z ) ) ;
gpx - > flag . pausePending = 0 ;
2013-05-03 17:57:14 +04:00
}
2013-11-24 17:04:49 +04:00
gpx - > flag . macrosEnabled = 1 ;
2013-05-14 06:44:55 +04:00
}
// ;@header
// ;@footer
else if ( MACRO_IS ( " header " ) & & MACRO_IS ( " footer " ) ) {
2013-11-24 17:04:49 +04:00
gpx - > flag . macrosEnabled = 0 ;
2013-05-03 17:57:14 +04:00
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-04-21 21:37:12 +04:00
}
2013-11-24 17:04:49 +04:00
/*
SIMPLE . INI FILE PARSER
ini . c is released under the New BSD license ( see LICENSE . txt ) . Go to the project
home page for more info : http : //code.google.com/p/inih/
Parse given INI - style file . May have [ section ] s , name = value pairs
( whitespace stripped ) , and comments starting with ' ; ' ( semicolon ) . Section
is " " if name = value pair parsed before any section heading . name : value
pairs are also supported as a concession to Python ' s ConfigParser .
For each name = value pair parsed , call handler function with given user
pointer as well as section , name , and value ( data only valid for duration
of handler call ) . Handler should return 0 on success , nonzero on error .
Returns 0 on success , line number of first error on parse error ( doesn ' t
stop on first error ) , - 1 on file open error .
*/
# define INI_SECTION_MAX 64
# define INI_NAME_MAX 64
/* Nonzero to allow multi-line value parsing, in the style of Python's
ConfigParser . If allowed , ini_parse ( ) will call the handler with the same
name for each subsequent line parsed . */
# ifndef INI_ALLOW_MULTILINE
# define INI_ALLOW_MULTILINE 1
# endif
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file . See http : //code.google.com/p/inih/issues/detail?id=21 */
# ifndef INI_ALLOW_BOM
# define INI_ALLOW_BOM 1
# endif
/* Strip whitespace chars off end of given string, in place. Return s. */
static char * rstrip ( char * s )
2013-04-29 22:26:36 +04:00
{
2013-11-24 17:04:49 +04:00
char * p = s + strlen ( s ) ;
while ( p > s & & isspace ( ( unsigned char ) ( * - - p ) ) ) * p = ' \0 ' ;
return s ;
}
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
/* Return pointer to first non-whitespace char in given string. */
static char * lskip ( const char * s )
{
while ( * s & & isspace ( ( unsigned char ) ( * s ) ) ) s + + ;
return ( char * ) s ;
}
/* Return pointer to first char c or ';' comment in given string, or pointer to
null at end of string if neither found . ' ; ' must be prefixed by a whitespace
character to register as a comment . */
static char * find_char_or_comment ( const char * s , char c )
{
int was_whitespace = 0 ;
while ( * s & & * s ! = c & & ! ( was_whitespace & & * s = = ' ; ' ) ) {
was_whitespace = isspace ( ( unsigned char ) ( * s ) ) ;
s + + ;
}
return ( char * ) s ;
}
/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
static char * strncpy0 ( char * dest , const char * src , size_t size )
{
strncpy ( dest , src , size ) ;
dest [ size - 1 ] = ' \0 ' ;
return dest ;
}
/* See documentation in header file. */
static int ini_parse_file ( Gpx * gpx , FILE * file , int ( * handler ) ( Gpx * , const char * , const char * , char * ) )
{
/* Uses a fair bit of stack (use heap instead if you need to) */
char section [ INI_SECTION_MAX ] = " " ;
char prev_name [ INI_NAME_MAX ] = " " ;
char * start ;
char * end ;
char * name ;
char * value ;
int error = 0 ;
gpx - > lineNumber = 0 ;
/* Scan through file line by line */
while ( fgets ( gpx - > buffer . in , BUFFER_MAX , file ) ! = NULL ) {
gpx - > lineNumber + + ;
start = gpx - > buffer . in ;
# if INI_ALLOW_BOM
if ( gpx - > lineNumber = = 1 & & ( unsigned char ) start [ 0 ] = = 0xEF & &
( unsigned char ) start [ 1 ] = = 0xBB & &
( unsigned char ) start [ 2 ] = = 0xBF ) {
start + = 3 ;
2013-05-03 17:57:14 +04:00
}
2013-11-24 17:04:49 +04:00
# endif
start = lskip ( rstrip ( start ) ) ;
if ( * start = = ' ; ' | | * start = = ' # ' ) {
/* Per Python ConfigParser, allow '#' comments at start of line */
2013-06-05 17:35:06 +04:00
}
2013-11-24 17:04:49 +04:00
# if INI_ALLOW_MULTILINE
else if ( * prev_name & & * start & & start > gpx - > buffer . in ) {
/* Non-black line with leading whitespace, treat as continuation
of previous name ' s value ( as per Python ConfigParser ) . */
if ( handler ( gpx , section , prev_name , start ) & & ! error )
error = gpx - > lineNumber ;
2013-08-22 15:48:32 +04:00
}
2013-11-24 17:04:49 +04:00
# endif
else if ( * start = = ' [ ' ) {
/* A "[section]" line */
end = find_char_or_comment ( start + 1 , ' ] ' ) ;
if ( * end = = ' ] ' ) {
* end = ' \0 ' ;
strncpy0 ( section , start + 1 , sizeof ( section ) ) ;
* prev_name = ' \0 ' ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( ! error ) {
/* No ']' found on section line */
error = gpx - > lineNumber ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
}
else if ( * start & & * start ! = ' ; ' ) {
/* Not a comment, must be a name[=:]value pair */
end = find_char_or_comment ( start , ' = ' ) ;
if ( * end ! = ' = ' ) {
end = find_char_or_comment ( start , ' : ' ) ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
if ( * end = = ' = ' | | * end = = ' : ' ) {
* end = ' \0 ' ;
name = rstrip ( start ) ;
value = lskip ( end + 1 ) ;
end = find_char_or_comment ( value , ' \0 ' ) ;
if ( * end = = ' ; ' )
* end = ' \0 ' ;
rstrip ( value ) ;
/* Valid name[=:]value pair found, call handler */
strncpy0 ( prev_name , name , sizeof ( prev_name ) ) ;
if ( handler ( gpx , section , name , value ) & & ! error )
error = gpx - > lineNumber ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( ! error ) {
/* No '=' or ':' found on name[=:]value line */
error = gpx - > lineNumber ;
2013-04-16 20:01:26 +04:00
}
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
}
return error ;
}
/* See documentation in header file. */
static int ini_parse ( Gpx * gpx , const char * filename ,
int ( * handler ) ( Gpx * , const char * , const char * , char * ) )
{
FILE * file ;
int error ;
2014-01-08 22:20:51 +04:00
unsigned ln = gpx - > lineNumber ;
2013-11-24 17:04:49 +04:00
file = fopen ( filename , " r " ) ;
2014-01-08 22:20:51 +04:00
if ( ! file ) return ERROR ;
2013-11-24 17:04:49 +04:00
error = ini_parse_file ( gpx , file , handler ) ;
2014-01-08 22:20:51 +04:00
gpx - > lineNumber = ln ;
2013-11-24 17:04:49 +04:00
fclose ( file ) ;
return error ;
}
// Custom machine definition ini handler
# define SECTION_IS(s) strcasecmp(section, s) == 0
# define PROPERTY_IS(n) strcasecmp(property, n) == 0
# define VALUE_IS(v) strcasecmp(value, v) == 0
int gpx_set_property ( Gpx * gpx , const char * section , const char * property , char * value )
{
int rval ;
if ( SECTION_IS ( " " ) | | SECTION_IS ( " macro " ) ) {
if ( PROPERTY_IS ( " slicer " )
| | PROPERTY_IS ( " filament " )
| | PROPERTY_IS ( " pause " )
| | PROPERTY_IS ( " start " )
| | PROPERTY_IS ( " temp " )
| | PROPERTY_IS ( " temperature " ) ) {
CALL ( parse_macro ( gpx , property , value ) ) ;
2013-04-26 06:53:47 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( PROPERTY_IS ( " verbose " ) ) {
gpx - > flag . verboseMode = atoi ( value ) ;
}
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " printer " ) | | SECTION_IS ( " slicer " ) ) {
if ( PROPERTY_IS ( " ditto_printing " ) ) gpx - > flag . dittoPrinting = atoi ( value ) ;
else if ( PROPERTY_IS ( " build_progress " ) ) gpx - > flag . buildProgress = atoi ( value ) ;
else if ( PROPERTY_IS ( " packing_density " ) ) gpx - > machine . nominal_packing_density = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " recalculate_5d " ) ) gpx - > flag . rewrite5D = atoi ( value ) ;
else if ( PROPERTY_IS ( " nominal_filament_diameter " )
| | PROPERTY_IS ( " slicer_filament_diameter " )
| | PROPERTY_IS ( " filament_diameter " ) ) {
gpx - > machine . nominal_filament_diameter = strtod ( value , NULL ) ;
}
else if ( PROPERTY_IS ( " machine_type " ) ) {
// only load/clobber the on-board machine definition if the one specified is different
if ( gpx_set_machine ( gpx , value ) ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Configuration error: unrecognised machine type '%s' " EOL , gpx - > lineNumber , value ) ) ;
2013-11-24 17:04:49 +04:00
return gpx - > lineNumber ;
2013-04-22 19:16:40 +04:00
}
2013-11-24 17:04:49 +04:00
gpx - > override [ A ] . packing_density = gpx - > machine . nominal_packing_density ;
gpx - > override [ B ] . packing_density = gpx - > machine . nominal_packing_density ;
}
else if ( PROPERTY_IS ( " gcode_flavor " ) ) {
// use on-board machine definition
if ( VALUE_IS ( " reprap " ) ) gpx - > flag . reprapFlavor = 1 ;
else if ( VALUE_IS ( " makerbot " ) ) gpx - > flag . reprapFlavor = 0 ;
2013-04-22 19:16:40 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Configuration error: unrecognised GCODE flavor '%s' " EOL , gpx - > lineNumber , value ) ) ;
2013-11-24 17:04:49 +04:00
return gpx - > lineNumber ;
2013-04-22 19:16:40 +04:00
}
}
2013-11-24 17:04:49 +04:00
else if ( PROPERTY_IS ( " build_platform_temperature " ) ) {
if ( gpx - > machine . a . has_heated_build_platform ) gpx - > override [ A ] . build_platform_temperature = atoi ( value ) ;
else if ( gpx - > machine . b . has_heated_build_platform ) gpx - > override [ B ] . build_platform_temperature = atoi ( value ) ;
}
else if ( PROPERTY_IS ( " sd_card_path " ) ) {
gpx - > sdCardPath = strdup ( value ) ;
}
else if ( PROPERTY_IS ( " verbose " ) ) {
gpx - > flag . verboseMode = atoi ( value ) ;
}
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " x " ) ) {
if ( PROPERTY_IS ( " max_feedrate " ) ) gpx - > machine . x . max_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " home_feedrate " ) ) gpx - > machine . x . home_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " steps_per_mm " ) ) gpx - > machine . x . steps_per_mm = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " endstop " ) ) gpx - > machine . x . endstop = atoi ( value ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " y " ) ) {
if ( PROPERTY_IS ( " max_feedrate " ) ) gpx - > machine . y . max_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " home_feedrate " ) ) gpx - > machine . y . home_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " steps_per_mm " ) ) gpx - > machine . y . steps_per_mm = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " endstop " ) ) gpx - > machine . y . endstop = atoi ( value ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " z " ) ) {
if ( PROPERTY_IS ( " max_feedrate " ) ) gpx - > machine . z . max_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " home_feedrate " ) ) gpx - > machine . z . home_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " steps_per_mm " ) ) gpx - > machine . z . steps_per_mm = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " endstop " ) ) gpx - > machine . z . endstop = atoi ( value ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " a " ) ) {
if ( PROPERTY_IS ( " max_feedrate " ) ) gpx - > machine . a . max_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " steps_per_mm " ) ) gpx - > machine . a . steps_per_mm = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " motor_steps " ) ) gpx - > machine . a . motor_steps = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " has_heated_build_platform " ) ) gpx - > machine . a . has_heated_build_platform = atoi ( value ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " right " ) ) {
if ( PROPERTY_IS ( " active_temperature " )
| | PROPERTY_IS ( " nozzle_temperature " ) ) gpx - > override [ A ] . active_temperature = atoi ( value ) ;
else if ( PROPERTY_IS ( " standby_temperature " ) ) gpx - > override [ A ] . standby_temperature = atoi ( value ) ;
else if ( PROPERTY_IS ( " build_platform_temperature " ) ) gpx - > override [ A ] . build_platform_temperature = atoi ( value ) ;
else if ( PROPERTY_IS ( " actual_filament_diameter " ) ) gpx - > override [ A ] . actual_filament_diameter = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " packing_density " ) ) gpx - > override [ A ] . packing_density = strtod ( value , NULL ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " b " ) ) {
if ( PROPERTY_IS ( " max_feedrate " ) ) gpx - > machine . b . max_feedrate = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " steps_per_mm " ) ) gpx - > machine . b . steps_per_mm = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " motor_steps " ) ) gpx - > machine . b . motor_steps = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " has_heated_build_platform " ) ) gpx - > machine . b . has_heated_build_platform = atoi ( value ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " left " ) ) {
if ( PROPERTY_IS ( " active_temperature " )
| | PROPERTY_IS ( " nozzle_temperature " ) ) gpx - > override [ B ] . active_temperature = atoi ( value ) ;
else if ( PROPERTY_IS ( " standby_temperature " ) ) gpx - > override [ B ] . standby_temperature = atoi ( value ) ;
else if ( PROPERTY_IS ( " build_platform_temperature " ) ) gpx - > override [ B ] . build_platform_temperature = atoi ( value ) ;
else if ( PROPERTY_IS ( " actual_filament_diameter " ) ) gpx - > override [ B ] . actual_filament_diameter = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " packing_density " ) ) gpx - > override [ B ] . packing_density = strtod ( value , NULL ) ;
else goto SECTION_ERROR ;
}
else if ( SECTION_IS ( " machine " ) ) {
if ( PROPERTY_IS ( " nominal_filament_diameter " )
| | PROPERTY_IS ( " slicer_filament_diameter " ) ) gpx - > machine . nominal_filament_diameter = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " packing_density " ) ) gpx - > machine . nominal_packing_density = strtod ( value , NULL ) ;
else if ( PROPERTY_IS ( " nozzle_diameter " ) ) gpx - > machine . nozzle_diameter = strtod ( value , NULL ) ;
2014-01-08 22:20:51 +04:00
else if ( PROPERTY_IS ( " extruder_count " ) ) {
gpx - > machine . extruder_count = atoi ( value ) ;
gpx - > axis . mask = gpx - > machine . extruder_count = = 1 ? ( XYZ_BIT_MASK | A_IS_SET ) : AXES_BIT_MASK ; ;
}
2013-11-24 17:04:49 +04:00
else if ( PROPERTY_IS ( " timeout " ) ) gpx - > machine . timeout = atoi ( value ) ;
else goto SECTION_ERROR ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Configuration error: unrecognised section [%s] " EOL , gpx - > lineNumber , section ) ) ;
2013-11-24 17:04:49 +04:00
return gpx - > lineNumber ;
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-11-24 17:04:49 +04:00
SECTION_ERROR :
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Configuration error: [%s] section contains unrecognised property %s = %s " EOL , gpx - > lineNumber , section , property , value ) ) ;
2013-11-24 17:04:49 +04:00
return gpx - > lineNumber ;
}
2014-01-08 22:20:51 +04:00
int gpx_load_config ( Gpx * gpx , const char * filename )
2013-11-24 17:04:49 +04:00
{
return ini_parse ( gpx , filename , gpx_set_property ) ;
}
2014-01-08 22:20:51 +04:00
void gpx_register_callback ( Gpx * gpx , int ( * callbackHandler ) ( Gpx * , void * , char * , size_t ) , void * callbackData )
2013-11-24 17:04:49 +04:00
{
gpx - > callbackHandler = callbackHandler ;
gpx - > callbackData = callbackData ;
}
2014-01-08 22:20:51 +04:00
void gpx_start_convert ( Gpx * gpx , char * buildName )
2013-11-24 17:04:49 +04:00
{
if ( buildName ) gpx - > buildName = buildName ;
if ( gpx - > flag . dittoPrinting & & gpx - > machine . extruder_count = = 1 ) {
2014-01-08 22:20:51 +04:00
SHOW ( fputs ( " Configuration error: ditto printing cannot access non-existant second extruder " EOL , gpx - > log ) ) ;
2013-11-24 17:04:49 +04:00
gpx - > flag . dittoPrinting = 0 ;
}
// CALCULATE FILAMENT SCALING
if ( gpx - > override [ A ] . actual_filament_diameter > 0.0001
& & gpx - > override [ A ] . actual_filament_diameter ! = gpx - > machine . nominal_filament_diameter ) {
set_filament_scale ( gpx , A , gpx - > override [ A ] . actual_filament_diameter ) ;
}
if ( gpx - > override [ B ] . actual_filament_diameter > 0.0001
& & gpx - > override [ B ] . actual_filament_diameter ! = gpx - > machine . nominal_filament_diameter ) {
set_filament_scale ( gpx , B , gpx - > override [ B ] . actual_filament_diameter ) ;
}
}
int gpx_convert_line ( Gpx * gpx , char * gcode_line )
{
int i , rval ;
int next_line = 0 ;
int command_emitted = 0 ;
// reset flag state
gpx - > command . flag = 0 ;
char * digits ;
char * p = gcode_line ; // current parser location
while ( isspace ( * p ) ) p + + ;
// check for line number
if ( * p = = ' n ' | | * p = = ' N ' ) {
digits = p ;
p = normalize_word ( p ) ;
if ( * p = = 0 ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: line number command word 'N' is missing digits " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
next_line = gpx - > lineNumber + 1 ;
}
else {
next_line = gpx - > lineNumber = atoi ( digits ) ;
}
}
else {
next_line = gpx - > lineNumber + 1 ;
}
// parse command words in command line
while ( * p ! = 0 ) {
if ( isalpha ( * p ) ) {
int c = * p ;
digits = p ;
p = normalize_word ( p ) ;
switch ( c ) {
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
// PARAMETERS
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
// Xnnn X coordinate, usually to move to
case ' x ' :
case ' X ' :
gpx - > command . x = strtod ( digits , NULL ) ;
gpx - > command . flag | = X_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
// Ynnn Y coordinate, usually to move to
case ' y ' :
case ' Y ' :
gpx - > command . y = strtod ( digits , NULL ) ;
gpx - > command . flag | = Y_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
// Znnn Z coordinate, usually to move to
case ' z ' :
case ' Z ' :
gpx - > command . z = strtod ( digits , NULL ) ;
gpx - > command . flag | = Z_IS_SET ;
2013-04-17 15:54:52 +04:00
break ;
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
// Annn Length of extrudate in mm.
case ' a ' :
case ' A ' :
gpx - > command . a = strtod ( digits , NULL ) ;
gpx - > command . flag | = A_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
// Bnnn Length of extrudate in mm.
case ' b ' :
case ' B ' :
gpx - > command . b = strtod ( digits , NULL ) ;
gpx - > command . flag | = B_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
// Ennn Length of extrudate in mm.
case ' e ' :
case ' E ' :
gpx - > command . e = strtod ( digits , NULL ) ;
gpx - > command . flag | = E_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// Fnnn Feedrate in mm per minute.
case ' f ' :
case ' F ' :
gpx - > command . f = strtod ( digits , NULL ) ;
gpx - > command . flag | = F_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// Pnnn Command parameter, such as a time in milliseconds
case ' p ' :
case ' P ' :
gpx - > command . p = strtod ( digits , NULL ) ;
gpx - > command . flag | = P_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// Rnnn Command Parameter, such as RPM
case ' r ' :
case ' R ' :
gpx - > command . r = strtod ( digits , NULL ) ;
gpx - > command . flag | = R_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// Snnn Command parameter, such as temperature
case ' s ' :
case ' S ' :
gpx - > command . s = strtod ( digits , NULL ) ;
gpx - > command . flag | = S_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// COMMANDS
2013-11-15 21:17:33 +04:00
2013-11-24 17:04:49 +04:00
// Gnnn GCode command, such as move to a point
case ' g ' :
case ' G ' :
gpx - > command . g = atoi ( digits ) ;
gpx - > command . flag | = G_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// Mnnn RepRap-defined command
case ' m ' :
case ' M ' :
gpx - > command . m = atoi ( digits ) ;
gpx - > command . flag | = M_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
2013-11-24 17:04:49 +04:00
// Tnnn Select extruder nnn.
case ' t ' :
case ' T ' :
gpx - > command . t = atoi ( digits ) ;
gpx - > command . flag | = T_IS_SET ;
2013-04-11 05:32:34 +04:00
break ;
default :
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: unrecognised command word '%c' " EOL , gpx - > lineNumber , c ) ) ;
2013-04-11 05:32:34 +04:00
}
}
2013-11-24 17:04:49 +04:00
else if ( * p = = ' ; ' ) {
if ( * ( p + 1 ) = = ' @ ' ) {
char * s = p + 2 ;
if ( isalpha ( * s ) ) {
char * macro = s ;
// skip any no space characters
while ( * s & & ! isspace ( * s ) ) s + + ;
// null terminate
if ( * s ) * s + + = 0 ;
CALL ( parse_macro ( gpx , macro , normalize_comment ( s ) ) ) ;
* p = 0 ;
break ;
}
}
// Comment
gpx - > command . comment = normalize_comment ( p + 1 ) ;
gpx - > command . flag | = COMMENT_IS_SET ;
* p = 0 ;
break ;
}
else if ( * p = = ' ( ' ) {
if ( * ( p + 1 ) = = ' @ ' ) {
char * s = p + 2 ;
if ( isalpha ( * s ) ) {
char * macro = s ;
char * e = strrchr ( p + 1 , ' ) ' ) ;
// skip any no space characters
while ( * s & & ! isspace ( * s ) ) s + + ;
// null terminate
if ( * s ) * s + + = 0 ;
if ( e ) * e = 0 ;
CALL ( parse_macro ( gpx , macro , normalize_comment ( s ) ) ) ;
* p = 0 ;
break ;
}
}
// Comment
char * s = strchr ( p + 1 , ' ( ' ) ;
char * e = strchr ( p + 1 , ' ) ' ) ;
// check for nested comment
if ( s & & e & & s < e ) {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: nested comment detected " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
e = strrchr ( p + 1 , ' ) ' ) ;
}
if ( e ) {
* e = 0 ;
gpx - > command . comment = normalize_comment ( p + 1 ) ;
gpx - > command . flag | = COMMENT_IS_SET ;
p = e + 1 ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: comment is missing closing ')' " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
gpx - > command . comment = normalize_comment ( p + 1 ) ;
gpx - > command . flag | = COMMENT_IS_SET ;
* p = 0 ;
break ;
}
}
else if ( * p = = ' * ' ) {
// Checksum
* p = 0 ;
break ;
}
else if ( iscntrl ( * p ) ) {
break ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: unrecognised gcode '%s' " EOL , gpx - > lineNumber , p ) ) ;
2013-11-24 17:04:49 +04:00
break ;
}
}
// revert tool selection to current extruder (Makerbot Tn is not sticky)
if ( ! gpx - > flag . reprapFlavor ) gpx - > target . extruder = gpx - > current . extruder ;
// change the extruder selection (in the virtual tool carosel)
if ( gpx - > command . flag & T_IS_SET & & ! gpx - > flag . dittoPrinting ) {
unsigned tool_id = ( unsigned ) gpx - > command . t ;
if ( tool_id < gpx - > machine . extruder_count ) {
gpx - > target . extruder = tool_id ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: T%u cannot select non-existant extruder " EOL , gpx - > lineNumber , tool_id ) ) ;
2013-11-24 17:04:49 +04:00
}
}
// we treat E as short hand for A or B being set, depending on the state of the gpx->current.extruder
if ( gpx - > command . flag & E_IS_SET ) {
if ( gpx - > current . extruder = = 0 ) {
// a = e
gpx - > command . flag | = A_IS_SET ;
gpx - > command . a = gpx - > command . e ;
}
else {
// b = e
gpx - > command . flag | = B_IS_SET ;
gpx - > command . b = gpx - > command . e ;
}
}
// INTERPRET COMMAND
if ( gpx - > command . flag & G_IS_SET ) {
switch ( gpx - > command . g ) {
// G0 - Rapid Positioning
case 0 :
if ( gpx - > command . flag & F_IS_SET ) {
CALL ( calculate_target_position ( gpx ) ) ;
CALL ( queue_ext_point ( gpx , 0.0 ) ) ;
update_current_position ( gpx ) ;
command_emitted + + ;
}
else {
Point3d delta ;
CALL ( calculate_target_position ( gpx ) ) ;
if ( gpx - > command . flag & X_IS_SET ) delta . x = fabs ( gpx - > target . position . x - gpx - > current . position . x ) ;
if ( gpx - > command . flag & Y_IS_SET ) delta . y = fabs ( gpx - > target . position . y - gpx - > current . position . y ) ;
if ( gpx - > command . flag & Z_IS_SET ) delta . z = fabs ( gpx - > target . position . z - gpx - > current . position . z ) ;
double length = magnitude ( gpx - > command . flag & XYZ_BIT_MASK , ( Ptr5d ) & delta ) ;
double candidate , feedrate = DBL_MAX ;
if ( gpx - > command . flag & X_IS_SET & & delta . x ! = 0.0 ) {
feedrate = gpx - > machine . x . max_feedrate * length / delta . x ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & Y_IS_SET & & delta . y ! = 0.0 ) {
candidate = gpx - > machine . y . max_feedrate * length / delta . y ;
if ( feedrate > candidate ) {
feedrate = candidate ;
2013-04-12 17:47:40 +04:00
}
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & Z_IS_SET & & delta . z ! = 0.0 ) {
candidate = gpx - > machine . z . max_feedrate * length / delta . z ;
if ( feedrate > candidate ) {
feedrate = candidate ;
}
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
if ( feedrate = = DBL_MAX ) {
feedrate = gpx - > machine . x . max_feedrate ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
CALL ( queue_ext_point ( gpx , feedrate ) ) ;
update_current_position ( gpx ) ;
command_emitted + + ;
2013-04-16 20:01:26 +04:00
}
2013-11-24 17:04:49 +04:00
break ;
// G1 - Coordinated Motion
case 1 :
CALL ( calculate_target_position ( gpx ) ) ;
CALL ( queue_ext_point ( gpx , 0.0 ) ) ;
update_current_position ( gpx ) ;
command_emitted + + ;
break ;
// G2 - Clockwise Arc
// G3 - Counter Clockwise Arc
// G4 - Dwell
case 4 :
if ( gpx - > command . flag & P_IS_SET ) {
# if ENABLE_SIMULATED_RPM
if ( gpx - > tool [ gpx - > current . extruder ] . motor_enabled & & gpx - > tool [ gpx - > current . extruder ] . rpm ) {
CALL ( calculate_target_position ( gpx ) ) ;
CALL ( queue_new_point ( gpx , gpx - > command . p ) ) ;
2013-04-21 21:37:12 +04:00
command_emitted + + ;
2013-04-17 20:47:52 +04:00
}
2013-11-24 17:04:49 +04:00
else
# endif
{
CALL ( delay ( gpx , gpx - > command . p ) ) ;
2013-04-21 21:37:12 +04:00
command_emitted + + ;
2013-04-17 20:47:52 +04:00
}
2013-04-11 05:32:34 +04:00
2013-11-24 17:04:49 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: G4 is missing delay parameter, use Pn where n is milliseconds " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
break ;
// G10 - Create Coordinate System Offset from the Absolute one
case 10 :
if ( gpx - > command . flag & P_IS_SET & & gpx - > command . p > = 1.0 & & gpx - > command . p < = 6.0 ) {
i = ( int ) gpx - > command . p ;
if ( gpx - > command . flag & X_IS_SET ) gpx - > offset [ i ] . x = gpx - > command . x ;
if ( gpx - > command . flag & Y_IS_SET ) gpx - > offset [ i ] . y = gpx - > command . y ;
if ( gpx - > command . flag & Z_IS_SET ) gpx - > offset [ i ] . z = gpx - > command . z ;
// set standby temperature
if ( gpx - > command . flag & R_IS_SET ) {
unsigned temperature = ( unsigned ) gpx - > command . r ;
2014-01-08 22:20:51 +04:00
if ( temperature > NOZZLE_MAX ) temperature = NOZZLE_MAX ;
2013-11-24 17:04:49 +04:00
switch ( i ) {
case 1 :
gpx - > override [ A ] . standby_temperature = temperature ;
break ;
case 2 :
gpx - > override [ B ] . standby_temperature = temperature ;
break ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
}
// set tool temperature
if ( gpx - > command . flag & S_IS_SET ) {
unsigned temperature = ( unsigned ) gpx - > command . s ;
2014-01-08 22:20:51 +04:00
if ( temperature > NOZZLE_MAX ) temperature = NOZZLE_MAX ;
2013-11-24 17:04:49 +04:00
switch ( i ) {
case 1 :
gpx - > override [ A ] . active_temperature = temperature ;
break ;
case 2 :
gpx - > override [ B ] . active_temperature = temperature ;
break ;
2013-04-12 17:47:40 +04:00
}
}
2013-11-24 17:04:49 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: G10 is missing coordiante system, use Pn where n is 1-6 " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
break ;
// G21 - Use Milimeters as Units (IGNORED)
// G71 - Use Milimeters as Units (IGNORED)
case 21 :
case 71 :
break ;
2014-01-08 22:20:51 +04:00
// G28 - Home given axes to machine defined endstop
case 28 : {
unsigned endstop_max = 0 ;
unsigned endstop_min = 0 ;
if ( gpx - > command . flag & F_IS_SET ) gpx - > current . feedrate = gpx - > command . f ;
if ( gpx - > command . flag & X_IS_SET ) {
if ( gpx - > machine . x . endstop ) {
endstop_max | = X_IS_SET ;
}
else {
endstop_min | = X_IS_SET ;
}
}
if ( gpx - > command . flag & Y_IS_SET ) {
if ( gpx - > machine . y . endstop ) {
endstop_max | = Y_IS_SET ;
}
else {
endstop_min | = Y_IS_SET ;
}
}
if ( gpx - > command . flag & Z_IS_SET ) {
if ( gpx - > machine . z . endstop ) {
endstop_max | = Z_IS_SET ;
}
else {
endstop_min | = Z_IS_SET ;
}
}
// home xy before z
if ( gpx - > machine . x . endstop ) {
if ( endstop_max ) {
CALL ( home_axes ( gpx , endstop_max , ENDSTOP_IS_MAX ) ) ;
}
if ( endstop_min ) {
CALL ( home_axes ( gpx , endstop_min , ENDSTOP_IS_MIN ) ) ;
}
}
else {
if ( endstop_min ) {
CALL ( home_axes ( gpx , endstop_min , ENDSTOP_IS_MAX ) ) ;
}
if ( endstop_max ) {
CALL ( home_axes ( gpx , endstop_max , ENDSTOP_IS_MIN ) ) ;
}
}
command_emitted + + ;
gpx - > axis . positionKnown & = ~ ( gpx - > command . flag & gpx - > axis . mask ) ;
gpx - > excess . a = 0 ;
gpx - > excess . b = 0 ;
break ;
}
2013-11-24 17:04:49 +04:00
// G53 - Set absolute coordinate system
case 53 :
gpx - > current . offset = 0 ;
break ;
// G54 - Use coordinate system from G10 P1
case 54 :
gpx - > current . offset = 1 ;
break ;
// G55 - Use coordinate system from G10 P2
case 55 :
gpx - > current . offset = 2 ;
break ;
// G56 - Use coordinate system from G10 P3
case 56 :
gpx - > current . offset = 3 ;
break ;
// G57 - Use coordinate system from G10 P4
case 57 :
gpx - > current . offset = 4 ;
break ;
// G58 - Use coordinate system from G10 P5
case 58 :
gpx - > current . offset = 5 ;
break ;
// G59 - Use coordinate system from G10 P6
case 59 :
gpx - > current . offset = 6 ;
break ;
// G90 - Absolute Positioning
case 90 :
gpx - > flag . relativeCoordinates = 0 ;
break ;
// G91 - Relative Positioning
case 91 :
2014-01-08 22:20:51 +04:00
if ( ( gpx - > axis . positionKnown & XYZ_BIT_MASK ) = = XYZ_BIT_MASK ) {
2013-11-24 17:04:49 +04:00
gpx - > flag . relativeCoordinates = 1 ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic error: G91 switch to relitive positioning prior to first absolute move " EOL , gpx - > lineNumber ) ) ;
return ERROR ;
2013-11-24 17:04:49 +04:00
}
break ;
// G92 - Define current position on axes
case 92 : {
2014-01-08 22:20:51 +04:00
double userScale = gpx - > flag . macrosEnabled ? gpx - > user . scale : 1.0 ;
if ( gpx - > command . flag & X_IS_SET ) gpx - > current . position . x = gpx - > command . x * userScale ;
if ( gpx - > command . flag & Y_IS_SET ) gpx - > current . position . y = gpx - > command . y * userScale ;
if ( gpx - > command . flag & Z_IS_SET ) gpx - > current . position . z = gpx - > command . z * userScale ;
2013-11-24 17:04:49 +04:00
if ( gpx - > command . flag & A_IS_SET ) gpx - > current . position . a = gpx - > command . a ;
if ( gpx - > command . flag & B_IS_SET ) gpx - > current . position . b = gpx - > command . b ;
CALL ( set_position ( gpx ) ) ;
command_emitted + + ;
2014-01-08 22:20:51 +04:00
// flag axes that are known
gpx - > axis . positionKnown | = ( gpx - > command . flag & gpx - > axis . mask ) ;
2013-11-24 17:04:49 +04:00
break ;
}
// G130 - Set given axes potentiometer Value
case 130 :
if ( gpx - > command . flag & X_IS_SET ) {
CALL ( set_pot_value ( gpx , 0 , gpx - > command . x < 0 ? 0 : gpx - > command . x > 127 ? 127 : ( unsigned ) gpx - > command . x ) ) ;
}
if ( gpx - > command . flag & Y_IS_SET ) {
CALL ( set_pot_value ( gpx , 1 , gpx - > command . y < 0 ? 0 : gpx - > command . y > 127 ? 127 : ( unsigned ) gpx - > command . y ) ) ;
}
if ( gpx - > command . flag & Z_IS_SET ) {
CALL ( set_pot_value ( gpx , 2 , gpx - > command . z < 0 ? 0 : gpx - > command . z > 127 ? 127 : ( unsigned ) gpx - > command . z ) ) ;
}
if ( gpx - > command . flag & A_IS_SET ) {
CALL ( set_pot_value ( gpx , 3 , gpx - > command . a < 0 ? 0 : gpx - > command . a > 127 ? 127 : ( unsigned ) gpx - > command . a ) ) ;
}
if ( gpx - > command . flag & B_IS_SET ) {
CALL ( set_pot_value ( gpx , 4 , gpx - > command . b < 0 ? 0 : gpx - > command . b > 127 ? 127 : ( unsigned ) gpx - > command . b ) ) ;
}
break ;
// G161 - Home given axes to minimum
case 161 :
if ( gpx - > command . flag & F_IS_SET ) gpx - > current . feedrate = gpx - > command . f ;
2014-01-08 22:20:51 +04:00
CALL ( home_axes ( gpx , gpx - > command . flag & XYZ_BIT_MASK , ENDSTOP_IS_MIN ) ) ;
2013-11-24 17:04:49 +04:00
command_emitted + + ;
2014-01-08 22:20:51 +04:00
// clear homed axes
gpx - > axis . positionKnown & = ~ ( gpx - > command . flag & gpx - > axis . mask ) ;
2013-11-24 17:04:49 +04:00
gpx - > excess . a = 0 ;
gpx - > excess . b = 0 ;
break ;
// G162 - Home given axes to maximum
case 162 :
if ( gpx - > command . flag & F_IS_SET ) gpx - > current . feedrate = gpx - > command . f ;
2014-01-08 22:20:51 +04:00
CALL ( home_axes ( gpx , gpx - > command . flag & XYZ_BIT_MASK , ENDSTOP_IS_MAX ) ) ;
2013-11-24 17:04:49 +04:00
command_emitted + + ;
2014-01-08 22:20:51 +04:00
// clear homed axes
gpx - > axis . positionKnown & = ~ ( gpx - > command . flag & gpx - > axis . mask ) ;
2013-11-24 17:04:49 +04:00
gpx - > excess . a = 0 ;
gpx - > excess . b = 0 ;
break ;
default :
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: unsupported gcode command 'G%u' " EOL , gpx - > lineNumber , gpx - > command . g ) ) ;
2013-11-24 17:04:49 +04:00
}
}
else if ( gpx - > command . flag & M_IS_SET ) {
switch ( gpx - > command . m ) {
2014-01-08 22:20:51 +04:00
// M0 - Program stop
case 0 :
break ;
// M1 - Program pause
case 1 :
break ;
// M2 - Program end
2013-11-24 17:04:49 +04:00
case 2 :
if ( program_is_running ( ) ) {
end_program ( ) ;
CALL ( set_build_progress ( gpx , 100 ) ) ;
CALL ( end_build ( gpx ) ) ;
}
2014-01-08 22:20:51 +04:00
return END_OF_FILE ;
2013-11-24 17:04:49 +04:00
2014-01-08 22:20:51 +04:00
// M6 - Automatic tool change (AND)
2013-11-24 17:04:49 +04:00
// M116 - Wait for extruder AND build platfrom to reach (or exceed) temperature
case 6 :
case 116 : {
2014-01-08 22:20:51 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? ( int ) gpx - > command . p : MAX_TIMEOUT ;
2013-11-24 17:04:49 +04:00
if ( ! gpx - > flag . dittoPrinting & &
# if !ENABLE_TOOL_CHANGE_ON_WAIT
2014-01-08 22:20:51 +04:00
gpx - > command . m = = 6 & &
2013-11-24 17:04:49 +04:00
# endif
gpx - > target . extruder ! = gpx - > current . extruder ) {
CALL ( do_tool_change ( gpx , timeout ) ) ;
command_emitted + + ;
}
// wait for heated build platform
if ( gpx - > machine . a . has_heated_build_platform & & gpx - > tool [ A ] . build_platform_temperature > 0 ) {
CALL ( wait_for_build_platform ( gpx , A , timeout ) ) ;
command_emitted + + ;
}
else if ( gpx - > machine . b . has_heated_build_platform & & gpx - > tool [ B ] . build_platform_temperature > 0 ) {
CALL ( wait_for_build_platform ( gpx , B , timeout ) ) ;
command_emitted + + ;
}
// wait for extruder
if ( gpx - > flag . dittoPrinting ) {
if ( gpx - > tool [ B ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , B , timeout ) ) ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ A ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , A , timeout ) ) ;
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . verboseMode ) {
CALL ( display_tag ( gpx ) ) ;
}
2013-11-24 17:04:49 +04:00
}
command_emitted + + ;
}
else {
if ( gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , gpx - > target . extruder , timeout ) ) ;
command_emitted + + ;
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . verboseMode ) {
CALL ( display_tag ( gpx ) ) ;
}
2013-11-24 17:04:49 +04:00
}
}
break ;
}
// M17 - Enable axes steppers
case 17 :
if ( gpx - > command . flag & AXES_BIT_MASK ) {
CALL ( set_steppers ( gpx , gpx - > command . flag & AXES_BIT_MASK , 1 ) ) ;
command_emitted + + ;
if ( gpx - > command . flag & A_IS_SET ) gpx - > tool [ A ] . motor_enabled = 1 ;
if ( gpx - > command . flag & B_IS_SET ) gpx - > tool [ B ] . motor_enabled = 1 ;
}
else {
CALL ( set_steppers ( gpx , gpx - > machine . extruder_count = = 1 ? ( XYZ_BIT_MASK | A_IS_SET ) : AXES_BIT_MASK , 1 ) ) ;
command_emitted + + ;
gpx - > tool [ A ] . motor_enabled = 1 ;
if ( gpx - > machine . extruder_count = = 2 ) gpx - > tool [ B ] . motor_enabled = 1 ;
}
break ;
// M18 - Disable axes steppers
case 18 :
if ( gpx - > command . flag & AXES_BIT_MASK ) {
CALL ( set_steppers ( gpx , gpx - > command . flag & AXES_BIT_MASK , 0 ) ) ;
command_emitted + + ;
if ( gpx - > command . flag & A_IS_SET ) gpx - > tool [ A ] . motor_enabled = 0 ;
if ( gpx - > command . flag & B_IS_SET ) gpx - > tool [ B ] . motor_enabled = 0 ;
}
else {
CALL ( set_steppers ( gpx , gpx - > machine . extruder_count = = 1 ? ( XYZ_BIT_MASK | A_IS_SET ) : AXES_BIT_MASK , 0 ) ) ;
command_emitted + + ;
gpx - > tool [ A ] . motor_enabled = 0 ;
if ( gpx - > machine . extruder_count = = 2 ) gpx - > tool [ B ] . motor_enabled = 0 ;
}
break ;
2014-01-08 22:20:51 +04:00
// M20 - List SD card
case 20 :
break ;
// M21 - Init SD card
case 21 :
break ;
// M22 - Release SD card
case 22 :
break ;
// M23 - Select SD file
case 23 :
break ;
// M24 - Start/resume SD print
case 24 :
break ;
// M25 - Pause SD print
case 25 :
break ;
// M26 - Set SD position
case 26 :
break ;
// M27 - Report SD print status
case 27 :
break ;
// M28 - Begin write to SD card
case 28 :
break ;
// M29 - Stop writing to SD card
case 29 :
break ;
// M30 - Delete file from SD card
case 30 :
break ;
// M31 - Output time since last M109 or SD card start to serial
case 31 :
break ;
2013-11-24 17:04:49 +04:00
// M70 - Display message on LCD
case 70 :
if ( gpx - > command . flag & COMMENT_IS_SET ) {
unsigned vPos = gpx - > command . flag & Y_IS_SET ? ( unsigned ) gpx - > command . y : 0 ;
2013-04-21 21:37:12 +04:00
if ( vPos > 3 ) vPos = 3 ;
2013-11-24 17:04:49 +04:00
unsigned hPos = gpx - > command . flag & X_IS_SET ? ( unsigned ) gpx - > command . x : 0 ;
2013-04-21 21:37:12 +04:00
if ( hPos > 19 ) hPos = 19 ;
2013-11-24 17:04:49 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? gpx - > command . p : 0 ;
CALL ( display_message ( gpx , gpx - > command . comment , vPos , hPos , timeout , 0 ) ) ;
command_emitted + + ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M70 is missing message text, use (text) where text is message " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
break ;
// M71 - Display message and wait for button press
case 71 : {
char * message = gpx - > command . flag & COMMENT_IS_SET ? gpx - > command . comment : " Press M to continue " ;
unsigned vPos = gpx - > command . flag & Y_IS_SET ? ( unsigned ) gpx - > command . y : 0 ;
if ( vPos > 3 ) vPos = 3 ;
unsigned hPos = gpx - > command . flag & X_IS_SET ? ( unsigned ) gpx - > command . x : 0 ;
if ( hPos > 19 ) hPos = 19 ;
int timeout = gpx - > command . flag & P_IS_SET ? gpx - > command . p : 0 ;
CALL ( display_message ( gpx , message , vPos , hPos , timeout , 1 ) ) ;
command_emitted + + ;
break ;
}
// M72 - Queue a song or play a tone
case 72 :
if ( gpx - > command . flag & P_IS_SET ) {
unsigned song_id = ( unsigned ) gpx - > command . p ;
if ( song_id > 2 ) song_id = 2 ;
CALL ( queue_song ( gpx , song_id ) ) ;
command_emitted + + ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: M72 is missing song number, use Pn where n is 0-2 " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
break ;
// M73 - Manual set build percentage
case 73 :
if ( gpx - > command . flag & P_IS_SET ) {
unsigned percent = ( unsigned ) gpx - > command . p ;
if ( percent > 100 ) percent = 100 ;
if ( program_is_ready ( ) ) {
start_program ( ) ;
CALL ( start_build ( gpx , gpx - > buildName ) ) ;
CALL ( set_build_progress ( gpx , 0 ) ) ;
// start extruder in a known state
CALL ( change_extruder_offset ( gpx , gpx - > current . extruder ) ) ;
}
else if ( program_is_running ( ) ) {
if ( percent = = 100 ) {
// disable macros in footer
gpx - > flag . macrosEnabled = 0 ;
end_program ( ) ;
CALL ( set_build_progress ( gpx , 100 ) ) ;
CALL ( end_build ( gpx ) ) ;
gpx - > current . percent = 100 ;
2013-04-12 17:47:40 +04:00
}
else {
2013-11-24 17:04:49 +04:00
// enable macros in object body
if ( ! gpx - > flag . macrosEnabled & & percent > 0 ) {
if ( gpx - > flag . pausePending ) {
CALL ( pause_at_zpos ( gpx , gpx - > commandAt [ 0 ] . z ) ) ;
gpx - > flag . pausePending = 0 ;
}
gpx - > flag . macrosEnabled = 1 ;
}
2014-01-08 22:20:51 +04:00
if ( gpx - > current . percent < percent & & ( percent = = 1 | | gpx - > total . time = = 0.0 | | gpx - > flag . buildProgress = = 0 ) ) {
2013-11-24 17:04:49 +04:00
CALL ( set_build_progress ( gpx , percent ) ) ;
gpx - > current . percent = percent ;
}
2013-04-12 17:47:40 +04:00
}
}
2013-11-24 17:04:49 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: M73 is missing build percentage, use Pn where n is 0-100 " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
break ;
// M82 - set extruder to absolute mode
case 82 :
gpx - > flag . extruderIsRelative = 0 ;
break ;
// M83 - set extruder to relative mode
case 83 :
gpx - > flag . extruderIsRelative = 1 ;
break ;
2014-01-08 22:20:51 +04:00
// M84 - Disable steppers until next move
2013-11-24 17:04:49 +04:00
case 84 :
CALL ( set_steppers ( gpx , gpx - > machine . extruder_count = = 1 ? ( XYZ_BIT_MASK | A_IS_SET ) : AXES_BIT_MASK , 0 ) ) ;
command_emitted + + ;
gpx - > tool [ A ] . motor_enabled = 0 ;
if ( gpx - > machine . extruder_count = = 2 ) gpx - > tool [ B ] . motor_enabled = 0 ;
break ;
// M101 - Turn extruder on, forward
// M102 - Turn extruder on, reverse
case 101 :
case 102 :
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_steppers ( gpx , A_IS_SET | B_IS_SET , 1 ) ) ;
command_emitted + + ;
gpx - > tool [ A ] . motor_enabled = gpx - > tool [ B ] . motor_enabled = gpx - > command . m = = 101 ? 1 : - 1 ;
}
else {
CALL ( set_steppers ( gpx , gpx - > target . extruder = = 0 ? A_IS_SET : B_IS_SET , 1 ) ) ;
command_emitted + + ;
gpx - > tool [ gpx - > target . extruder ] . motor_enabled = gpx - > command . m = = 101 ? 1 : - 1 ;
}
break ;
// M103 - Turn extruder off
case 103 :
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_steppers ( gpx , A_IS_SET | B_IS_SET , 1 ) ) ;
command_emitted + + ;
gpx - > tool [ A ] . motor_enabled = gpx - > tool [ B ] . motor_enabled = 0 ;
}
else {
CALL ( set_steppers ( gpx , gpx - > target . extruder = = 0 ? A_IS_SET : B_IS_SET , 0 ) ) ;
command_emitted + + ;
gpx - > tool [ gpx - > target . extruder ] . motor_enabled = 0 ;
}
break ;
// M104 - Set extruder temperature
case 104 :
if ( gpx - > command . flag & S_IS_SET ) {
unsigned temperature = ( unsigned ) gpx - > command . s ;
2014-01-08 22:20:51 +04:00
if ( temperature > NOZZLE_MAX ) temperature = NOZZLE_MAX ;
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . dittoPrinting ) {
if ( temperature & & gpx - > override [ gpx - > current . extruder ] . active_temperature ) {
temperature = gpx - > override [ gpx - > current . extruder ] . active_temperature ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
CALL ( set_nozzle_temperature ( gpx , B , temperature ) ) ;
CALL ( set_nozzle_temperature ( gpx , A , temperature ) ) ;
command_emitted + + ;
gpx - > tool [ A ] . nozzle_temperature = gpx - > tool [ B ] . nozzle_temperature = temperature ;
}
else {
if ( temperature & & gpx - > override [ gpx - > target . extruder ] . active_temperature ) {
temperature = gpx - > override [ gpx - > target . extruder ] . active_temperature ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
CALL ( set_nozzle_temperature ( gpx , gpx - > target . extruder , temperature ) ) ;
command_emitted + + ;
gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature = temperature ;
2013-04-12 17:47:40 +04:00
}
2013-04-21 21:37:12 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M104 is missing temperature, use Sn where n is 0-280 " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
break ;
2014-01-08 22:20:51 +04:00
// M105 - Get extruder temperature
case 105 :
break ;
2013-11-24 17:04:49 +04:00
// M106 - Turn cooling fan on
case 106 : {
int state = ( gpx - > command . flag & S_IS_SET ) ? ( ( unsigned ) gpx - > command . s ? 1 : 0 ) : 1 ;
if ( gpx - > flag . reprapFlavor & & gpx - > machine . type > = MACHINE_TYPE_REPLICATOR_1 ) {
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_valve ( gpx , B , state ) ) ;
CALL ( set_valve ( gpx , A , state ) ) ;
2013-04-21 21:37:12 +04:00
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
else {
2013-11-24 17:04:49 +04:00
CALL ( set_valve ( gpx , gpx - > target . extruder , state ) ) ;
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
}
else {
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_fan ( gpx , B , state ) ) ;
CALL ( set_fan ( gpx , A , state ) ) ;
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
else {
2013-11-24 17:04:49 +04:00
CALL ( set_fan ( gpx , gpx - > target . extruder , state ) ) ;
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
}
break ;
}
// M107 - Turn cooling fan off
case 107 :
if ( gpx - > flag . reprapFlavor & & gpx - > machine . type > = MACHINE_TYPE_REPLICATOR_1 ) {
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_valve ( gpx , B , 0 ) ) ;
CALL ( set_valve ( gpx , A , 0 ) ) ;
2013-04-22 18:22:44 +04:00
command_emitted + + ;
}
2013-04-12 17:47:40 +04:00
else {
2013-11-24 17:04:49 +04:00
CALL ( set_valve ( gpx , gpx - > target . extruder , 0 ) ) ;
2013-04-21 21:37:12 +04:00
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
}
else {
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_fan ( gpx , B , 0 ) ) ;
CALL ( set_fan ( gpx , A , 0 ) ) ;
2013-04-22 18:22:44 +04:00
command_emitted + + ;
}
2013-04-12 17:47:40 +04:00
else {
2013-11-24 17:04:49 +04:00
CALL ( set_fan ( gpx , gpx - > target . extruder , 0 ) ) ;
2013-04-21 21:37:12 +04:00
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
}
break ;
2014-01-08 22:20:51 +04:00
// M108 - Set extruder motor 5D 'simulated' RPM
2013-11-24 17:04:49 +04:00
case 108 :
# if ENABLE_SIMULATED_RPM
if ( gpx - > command . flag & R_IS_SET ) {
if ( gpx - > flag . dittoPrinting ) {
gpx - > tool [ A ] . rpm = gpx - > tool [ B ] . rpm = gpx - > command . r ;
}
else {
gpx - > tool [ gpx - > target . extruder ] . rpm = gpx - > command . r ;
}
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M108 is missing motor RPM, use Rn where n is 0-5 " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
# endif
break ;
2014-01-08 22:20:51 +04:00
// M109 - Set extruder temperature and wait
2013-11-24 17:04:49 +04:00
case 109 :
if ( gpx - > flag . reprapFlavor ) {
if ( gpx - > command . flag & S_IS_SET ) {
2014-01-08 22:20:51 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? ( int ) gpx - > command . p : MAX_TIMEOUT ;
2013-11-24 17:04:49 +04:00
unsigned temperature = ( unsigned ) gpx - > command . s ;
2014-01-08 22:20:51 +04:00
if ( temperature > NOZZLE_MAX ) temperature = NOZZLE_MAX ;
2013-11-24 17:04:49 +04:00
if ( gpx - > flag . dittoPrinting ) {
unsigned tempB = temperature ;
// set extruder temperatures
if ( temperature ) {
if ( gpx - > override [ B ] . active_temperature ) {
tempB = gpx - > override [ B ] . active_temperature ;
}
if ( gpx - > override [ A ] . active_temperature ) {
temperature = gpx - > override [ A ] . active_temperature ;
}
}
CALL ( set_nozzle_temperature ( gpx , B , tempB ) ) ;
CALL ( set_nozzle_temperature ( gpx , A , temperature ) ) ;
gpx - > tool [ B ] . nozzle_temperature = tempB ;
gpx - > tool [ A ] . nozzle_temperature = temperature ;
// wait for extruders to reach (or exceed) temperature
if ( gpx - > tool [ B ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , B , timeout ) ) ;
}
if ( gpx - > tool [ A ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , A , timeout ) ) ;
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . verboseMode ) {
CALL ( display_tag ( gpx ) ) ;
}
2013-04-22 18:22:44 +04:00
}
command_emitted + + ;
}
2013-04-12 17:47:40 +04:00
else {
2013-11-24 17:04:49 +04:00
# if ENABLE_TOOL_CHANGE_ON_WAIT
// because there is a wait we do a tool change
if ( gpx - > target . extruder ! = gpx - > current . extruder ) {
CALL ( do_tool_change ( gpx , timeout ) ) ;
}
# endif
// set extruder temperature
if ( temperature & & gpx - > override [ gpx - > target . extruder ] . active_temperature ) {
temperature = gpx - > override [ gpx - > target . extruder ] . active_temperature ;
}
CALL ( set_nozzle_temperature ( gpx , gpx - > target . extruder , temperature ) ) ;
gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature = temperature ;
// wait for extruder to reach (or exceed) temperature
if ( gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , gpx - > target . extruder , timeout ) ) ;
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . verboseMode ) {
CALL ( display_tag ( gpx ) ) ;
}
2013-04-18 19:01:37 +04:00
}
2013-04-21 21:37:12 +04:00
command_emitted + + ;
2013-04-12 17:47:40 +04:00
}
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M109 is missing temperature, use Sn where n is 0-280 " EOL , gpx - > lineNumber ) ) ;
2013-04-12 17:47:40 +04:00
}
break ;
2013-11-24 17:04:49 +04:00
}
// fall through to M140 for Makerbot/ReplicatorG flavor
2014-01-08 22:20:51 +04:00
// M140 - Set build platform temperature
2013-11-24 17:04:49 +04:00
case 140 :
if ( gpx - > machine . a . has_heated_build_platform | | gpx - > machine . b . has_heated_build_platform ) {
if ( gpx - > command . flag & S_IS_SET ) {
unsigned temperature = ( unsigned ) gpx - > command . s ;
if ( temperature > HBP_MAX ) temperature = HBP_MAX ;
unsigned tool_id = gpx - > machine . a . has_heated_build_platform ? A : B ;
if ( gpx - > command . flag & T_IS_SET ) {
tool_id = gpx - > target . extruder ;
}
if ( tool_id ? gpx - > machine . b . has_heated_build_platform : gpx - > machine . a . has_heated_build_platform ) {
if ( temperature & & gpx - > override [ tool_id ] . build_platform_temperature ) {
temperature = gpx - > override [ tool_id ] . build_platform_temperature ;
}
CALL ( set_build_platform_temperature ( gpx , tool_id , temperature ) ) ;
2013-09-25 22:06:43 +04:00
command_emitted + + ;
2013-11-24 17:04:49 +04:00
gpx - > tool [ tool_id ] . build_platform_temperature = temperature ;
2013-09-25 22:06:43 +04:00
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: M%u cannot select non-existant heated build platform T%u " EOL , gpx - > lineNumber , gpx - > command . m , tool_id ) ) ;
2013-09-25 22:06:43 +04:00
}
2013-04-22 18:22:44 +04:00
}
2013-04-12 17:47:40 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M%u is missing temperature, use Sn where n is 0-120 " EOL , gpx - > lineNumber , gpx - > command . m ) ) ;
2013-04-12 17:47:40 +04:00
}
2013-05-03 17:57:14 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: M%u cannot select non-existant heated build platform " EOL , gpx - > lineNumber , gpx - > command . m ) ) ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
break ;
2014-01-08 22:20:51 +04:00
// M110 - Set current line number
case 110 :
break ;
// M111 - Set debug level
case 111 :
2013-11-24 17:04:49 +04:00
// M126 - Turn blower fan on (valve open)
case 126 : {
int state = ( gpx - > command . flag & S_IS_SET ) ? ( ( unsigned ) gpx - > command . s ? 1 : 0 ) : 1 ;
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_valve ( gpx , B , state ) ) ;
CALL ( set_valve ( gpx , A , state ) ) ;
2013-11-15 21:17:33 +04:00
command_emitted + + ;
}
2013-11-24 17:04:49 +04:00
else {
CALL ( set_valve ( gpx , gpx - > target . extruder , state ) ) ;
2013-11-15 21:17:33 +04:00
command_emitted + + ;
}
2013-11-24 17:04:49 +04:00
break ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
// M127 - Turn blower fan off (valve close)
case 127 :
if ( gpx - > flag . dittoPrinting ) {
CALL ( set_valve ( gpx , B , 0 ) ) ;
CALL ( set_valve ( gpx , A , 0 ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
else {
CALL ( set_valve ( gpx , gpx - > target . extruder , 0 ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
}
break ;
2013-11-24 17:04:49 +04:00
// M131 - Store Current Position to EEPROM
case 131 :
if ( gpx - > command . flag & AXES_BIT_MASK ) {
CALL ( store_home_positions ( gpx ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M131 is missing axes, use X Y Z A B " EOL , gpx - > lineNumber ) ) ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
break ;
// M132 - Load Current Position from EEPROM
case 132 :
if ( gpx - > command . flag & AXES_BIT_MASK ) {
CALL ( recall_home_positions ( gpx ) ) ;
command_emitted + + ;
2014-01-08 22:20:51 +04:00
// clear loaded axes
gpx - > axis . positionKnown & = ~ ( gpx - > command . flag & gpx - > axis . mask ) ; ;
2013-11-24 17:04:49 +04:00
gpx - > excess . a = 0 ;
gpx - > excess . b = 0 ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax error: M132 is missing axes, use X Y Z A B " EOL , gpx - > lineNumber ) ) ;
2013-08-22 15:48:32 +04:00
}
2013-11-24 17:04:49 +04:00
break ;
// M133 - Wait for extruder
case 133 : {
2014-01-08 22:20:51 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? ( int ) gpx - > command . p : MAX_TIMEOUT ;
2013-11-24 17:04:49 +04:00
// changing the
if ( gpx - > flag . dittoPrinting ) {
if ( gpx - > tool [ B ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , B , timeout ) ) ;
2013-05-03 17:57:14 +04:00
}
2013-11-24 17:04:49 +04:00
if ( gpx - > tool [ A ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , A , timeout ) ) ;
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . verboseMode ) {
CALL ( display_tag ( gpx ) ) ;
}
2013-05-03 17:57:14 +04:00
}
2013-11-24 17:04:49 +04:00
command_emitted + + ;
2013-05-03 17:57:14 +04:00
}
2013-11-24 17:04:49 +04:00
else {
# if ENABLE_TOOL_CHANGE_ON_WAIT
// because there is a wait we do a tool change
if ( gpx - > target . extruder ! = gpx - > current . extruder ) {
CALL ( do_tool_change ( gpx , timeout ) ) ;
2013-08-22 15:48:32 +04:00
}
2013-11-24 17:04:49 +04:00
# endif
// any tool changes have already occured
if ( gpx - > tool [ gpx - > target . extruder ] . nozzle_temperature > 0 ) {
CALL ( wait_for_extruder ( gpx , gpx - > target . extruder , timeout ) ) ;
2014-01-08 22:20:51 +04:00
if ( gpx - > flag . verboseMode ) {
CALL ( display_tag ( gpx ) ) ;
}
2013-08-22 15:48:32 +04:00
}
2013-11-24 17:04:49 +04:00
command_emitted + + ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
break ;
}
// M134
// M190 - Wait for build platform to reach (or exceed) temperature
case 134 :
case 190 : {
if ( gpx - > machine . a . has_heated_build_platform | | gpx - > machine . b . has_heated_build_platform ) {
2014-01-08 22:20:51 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? ( int ) gpx - > command . p : MAX_TIMEOUT ;
2013-11-24 17:04:49 +04:00
unsigned tool_id = gpx - > machine . a . has_heated_build_platform ? A : B ;
if ( gpx - > command . flag & T_IS_SET ) {
tool_id = gpx - > target . extruder ;
2013-08-22 15:48:32 +04:00
}
2013-11-24 17:04:49 +04:00
if ( tool_id ? gpx - > machine . b . has_heated_build_platform : gpx - > machine . a . has_heated_build_platform
& & gpx - > tool [ tool_id ] . build_platform_temperature > 0 ) {
CALL ( wait_for_build_platform ( gpx , tool_id , timeout ) ) ;
command_emitted + + ;
2013-04-19 08:53:34 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: M%u cannot select non-existant heated build platform T%u " EOL , gpx - > lineNumber , gpx - > command . m , tool_id ) ) ;
2013-04-19 08:53:34 +04:00
}
2013-04-22 18:22:44 +04:00
}
2013-11-24 17:04:49 +04:00
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Semantic warning: M%u cannot select non-existant heated build platform " EOL , gpx - > lineNumber , gpx - > command . m ) ) ;
2013-11-15 21:17:33 +04:00
}
break ;
2013-11-24 17:04:49 +04:00
}
// M135 - Change tool
case 135 :
if ( ! gpx - > flag . dittoPrinting & & gpx - > target . extruder ! = gpx - > current . extruder ) {
2014-01-08 22:20:51 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? ( int ) gpx - > command . p : MAX_TIMEOUT ;
2013-11-24 17:04:49 +04:00
CALL ( do_tool_change ( gpx , timeout ) ) ;
command_emitted + + ;
}
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
// M136 - Build start notification
case 136 :
if ( program_is_ready ( ) ) {
start_program ( ) ;
CALL ( start_build ( gpx , gpx - > buildName ) ) ;
CALL ( set_build_progress ( gpx , 0 ) ) ;
// start extruder in a known state
CALL ( change_extruder_offset ( gpx , gpx - > current . extruder ) ) ;
}
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
// M137 - Build end notification
case 137 :
if ( program_is_running ( ) ) {
2014-01-08 22:20:51 +04:00
// disable macros in footer
gpx - > flag . macrosEnabled = 0 ;
2013-11-24 17:04:49 +04:00
end_program ( ) ;
CALL ( set_build_progress ( gpx , 100 ) ) ;
CALL ( end_build ( gpx ) ) ;
gpx - > current . percent = 100 ;
}
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
// M300 - Set Beep (SP)
case 300 : {
unsigned frequency = 300 ;
if ( gpx - > command . flag & S_IS_SET ) frequency = ( unsigned ) gpx - > command . s & 0xFFFF ;
unsigned milliseconds = 1000 ;
if ( gpx - > command . flag & P_IS_SET ) milliseconds = ( unsigned ) gpx - > command . p & 0xFFFF ;
CALL ( set_beep ( gpx , frequency , milliseconds ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
}
// M320 - Acceleration on for subsequent instructions
case 320 :
CALL ( set_acceleration ( gpx , 1 ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
// M321 - Acceleration off for subsequent instructions
case 321 :
CALL ( set_acceleration ( gpx , 0 ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
// M322 - Pause @ zPos
case 322 :
if ( gpx - > command . flag & Z_IS_SET ) {
float conditional_z = gpx - > offset [ gpx - > current . offset ] . z ;
if ( gpx - > flag . macrosEnabled ) {
2014-01-08 22:20:51 +04:00
conditional_z + = gpx - > user . offset . z ;
2013-11-24 17:04:49 +04:00
}
double z = gpx - > flag . relativeCoordinates ? ( gpx - > current . position . z + gpx - > command . z ) : ( gpx - > command . z + conditional_z ) ;
CALL ( pause_at_zpos ( gpx , z ) ) ;
}
else {
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: M322 is missing Z axis " EOL , gpx - > lineNumber ) ) ;
2013-11-24 17:04:49 +04:00
}
command_emitted + + ;
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
// M420 - Set RGB LED value (REB - P)
case 420 : {
unsigned red = 0 ;
if ( gpx - > command . flag & R_IS_SET ) red = ( unsigned ) gpx - > command . r & 0xFF ;
unsigned green = 0 ;
if ( gpx - > command . flag & E_IS_SET ) green = ( unsigned ) gpx - > command . e & 0xFF ;
unsigned blue = 0 ;
if ( gpx - > command . flag & B_IS_SET ) blue = ( unsigned ) gpx - > command . b & 0xFF ;
unsigned blink = 0 ;
if ( gpx - > command . flag & P_IS_SET ) blink = ( unsigned ) gpx - > command . p & 0xFF ;
CALL ( set_LED ( gpx , red , green , blue , blink ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
break ;
2013-11-24 17:04:49 +04:00
}
2014-01-08 22:20:51 +04:00
// M500 - Write paramters to EEPROM
// M501 - Read parameters from EEPROM
// M502 - Revert to default "factory settings"
// M503 - Print/log current settings
2013-11-15 21:17:33 +04:00
default :
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Syntax warning: unsupported mcode command 'M%u' " EOL , gpx - > lineNumber , gpx - > command . m ) ) ;
2013-11-15 21:17:33 +04:00
}
}
2013-11-24 17:04:49 +04:00
else {
// X,Y,Z,A,B,E,F
if ( gpx - > command . flag & ( AXES_BIT_MASK | F_IS_SET ) ) {
CALL ( calculate_target_position ( gpx ) ) ;
CALL ( queue_ext_point ( gpx , 0.0 ) ) ;
update_current_position ( gpx ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
// Tn
else if ( ! gpx - > flag . dittoPrinting & & gpx - > target . extruder ! = gpx - > current . extruder ) {
2014-01-08 22:20:51 +04:00
int timeout = gpx - > command . flag & P_IS_SET ? ( int ) gpx - > command . p : MAX_TIMEOUT ;
2013-11-24 17:04:49 +04:00
CALL ( do_tool_change ( gpx , timeout ) ) ;
command_emitted + + ;
2013-11-15 21:17:33 +04:00
}
}
2013-11-24 17:04:49 +04:00
// check for pending pause @ zPos
if ( gpx - > flag . doPauseAtZPos ) {
gpx - > flag . doPauseAtZPos - - ;
// issue next pause @ zPos after command buffer is flushed
if ( gpx - > flag . doPauseAtZPos = = 0 ) {
CALL ( pause_at_zpos ( gpx , gpx - > commandAt [ gpx - > commandAtIndex ] . z ) ) ;
2013-04-11 05:32:34 +04:00
}
2013-11-24 17:04:49 +04:00
}
// update progress
if ( gpx - > total . time > 0.0001 & & gpx - > accumulated . time > 0.0001 & & gpx - > flag . buildProgress & & command_emitted ) {
unsigned percent = ( unsigned ) round ( 100.0 * gpx - > accumulated . time / gpx - > total . time ) ;
if ( percent > gpx - > current . percent ) {
if ( program_is_ready ( ) ) {
start_program ( ) ;
CALL ( start_build ( gpx , gpx - > buildName ) ) ;
CALL ( set_build_progress ( gpx , 0 ) ) ;
// start extruder in a known state
CALL ( change_extruder_offset ( gpx , gpx - > current . extruder ) ) ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
else if ( percent < 100 & & program_is_running ( ) ) {
2014-01-08 22:20:51 +04:00
if ( gpx - > current . percent ) {
CALL ( set_build_progress ( gpx , percent ) ) ;
gpx - > current . percent = percent ;
}
// force 1%
else {
CALL ( set_build_progress ( gpx , 1 ) ) ;
gpx - > current . percent = 1 ;
}
2013-04-12 17:47:40 +04:00
}
2013-11-24 17:04:49 +04:00
command_emitted = 0 ;
2013-04-11 05:32:34 +04:00
}
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
gpx - > lineNumber = next_line ;
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-11-24 17:04:49 +04:00
}
typedef struct tFile {
FILE * in ;
FILE * out ;
FILE * out2 ;
} File ;
2014-01-08 22:20:51 +04:00
static int file_handler ( Gpx * gpx , File * file , char * buffer , size_t length )
2013-11-24 17:04:49 +04:00
{
if ( length ) {
2014-01-08 22:20:51 +04:00
ssize_t bytes = fwrite ( buffer , 1 , length , file - > out ) ;
if ( bytes ! = length ) return ERROR ;
2013-11-24 17:04:49 +04:00
if ( file - > out2 ) {
2014-01-08 22:20:51 +04:00
bytes = fwrite ( buffer , 1 , length , file - > out2 ) ;
if ( bytes ! = length ) return ERROR ;
2013-11-24 17:04:49 +04:00
}
2013-04-12 17:47:40 +04:00
}
2014-01-08 22:20:51 +04:00
return SUCCESS ;
2013-11-24 17:04:49 +04:00
}
2014-01-08 22:20:51 +04:00
int gpx_convert ( Gpx * gpx , FILE * file_in , FILE * file_out , FILE * file_out2 )
2013-11-24 17:04:49 +04:00
{
int i , rval ;
File file ;
file . in = stdin ;
file . out = stdout ;
file . out2 = NULL ;
2014-01-08 22:20:51 +04:00
int logMessages = gpx - > flag . logMessages ;
2013-11-24 17:04:49 +04:00
if ( file_in & & file_in ! = stdin ) {
// Multi-pass
file . in = file_in ;
i = 0 ;
2014-01-08 22:20:51 +04:00
gpx - > flag . runMacros = 0 ;
2013-11-24 17:04:49 +04:00
gpx - > callbackHandler = NULL ;
gpx - > callbackData = NULL ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
else {
// Single-pass
i = 1 ;
2014-01-08 22:20:51 +04:00
gpx - > callbackHandler = ( int ( * ) ( Gpx * , void * , char * , size_t ) ) file_handler ; ;
2013-11-24 17:04:49 +04:00
gpx - > callbackData = & file ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
if ( file_out ) {
file . out = file_out ;
2013-11-15 21:17:33 +04:00
}
2013-11-24 17:04:49 +04:00
file . out2 = file_out2 ;
for ( ; ; ) {
int overflow = 0 ;
while ( fgets ( gpx - > buffer . in , BUFFER_MAX , file . in ) ! = NULL ) {
// detect input buffer overflow and ignore overflow input
if ( overflow ) {
if ( strlen ( gpx - > buffer . in ) ! = BUFFER_MAX - 1 ) {
overflow = 0 ;
}
continue ;
}
if ( strlen ( gpx - > buffer . in ) = = BUFFER_MAX - 1 ) {
overflow = 1 ;
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Buffer overflow: input exceeds %u character limit, remaining characters in line will be ignored " EOL , gpx - > lineNumber , BUFFER_MAX ) ) ;
2013-11-24 17:04:49 +04:00
}
rval = gpx_convert_line ( gpx , gpx - > buffer . in ) ;
// normal exit
2014-01-08 22:20:51 +04:00
if ( rval = = END_OF_FILE ) break ;
2013-11-24 17:04:49 +04:00
// error
if ( rval < 0 ) return rval ;
}
if ( program_is_running ( ) ) {
end_program ( ) ;
CALL ( set_build_progress ( gpx , 100 ) ) ;
CALL ( end_build ( gpx ) ) ;
}
CALL ( set_steppers ( gpx , AXES_BIT_MASK , 0 ) ) ;
gpx - > total . length = gpx - > accumulated . a + gpx - > accumulated . b ;
gpx - > total . time = gpx - > accumulated . time ;
gpx - > total . bytes = gpx - > accumulated . bytes ;
if ( + + i > 1 ) break ;
// rewind for second pass
fseek ( file . in , 0L , SEEK_SET ) ;
gpx_initialize ( gpx , 0 ) ;
2014-01-08 22:20:51 +04:00
gpx - > flag . loadMacros = 0 ;
gpx - > flag . runMacros = 1 ;
//gpx->flag.logMessages = 0;
gpx - > callbackHandler = ( int ( * ) ( Gpx * , void * , char * , size_t ) ) file_handler ;
2013-11-24 17:04:49 +04:00
gpx - > callbackData = & file ;
2013-11-15 21:17:33 +04:00
}
2014-01-08 22:20:51 +04:00
gpx - > flag . logMessages = logMessages ; ;
return SUCCESS ;
2013-11-24 17:04:49 +04:00
}
typedef struct tSio {
FILE * in ;
int port ;
2014-01-08 22:20:51 +04:00
unsigned bytes_out ;
unsigned bytes_in ;
union {
struct {
unsigned short version ;
unsigned char variant ;
} firmware ;
unsigned int bufferSize ;
unsigned short temperature ;
unsigned int isReady ;
union {
unsigned char bitfield ;
struct {
unsigned char ready : 1 ; // The extruder has reached target temperature
unsigned char notPluggedIn : 1 ; // The tool or platform is not plugged in.
unsigned char softwareCutoff : 1 ; // Temperature was recorded above maximum allowable.
unsigned char notHeating : 1 ; // Heater is not heating up as expected.
unsigned char temperatureDropping : 1 ; // Heater temperature dropped below target temp.
unsigned char reserved : 1 ;
unsigned char buildPlateError : 1 ; // An error was detected with the platform heater.
unsigned char extruderError : 1 ; // An error was detected with the extruder heater.
} flag ;
} extruder ;
struct {
char buffer [ 31 ] ;
unsigned char length ;
} eeprom ;
struct {
short extruderError ;
short extruderDelta ;
short extruderOutput ;
short buildPlateError ;
short buildPlateDelta ;
short buildPlateOutput ;
} pid ;
struct {
unsigned int length ;
char filename [ 65 ] ;
unsigned char status ;
} sd ;
struct {
int x ;
int y ;
int z ;
int a ;
int b ;
union {
unsigned short bitfield ;
struct {
unsigned short xMin : 1 ; // X min switch pressed
unsigned short xMax : 1 ; // X max switch pressed
unsigned short yMin : 1 ; // Y min switch pressed
unsigned short yMax : 1 ; // Y max switch pressed
unsigned short zMin : 1 ; // Z min switch pressed
unsigned short zMax : 1 ; // Z max switch pressed
unsigned short aMin : 1 ; // A min switch pressed
unsigned short aMax : 1 ; // A max switch pressed
unsigned short bMin : 1 ; // B min switch pressed
unsigned short bMax : 1 ; // B max switch pressed
} flag ;
} endstop ;
} position ;
union {
unsigned char bitfield ;
struct {
unsigned char preheat : 1 ; // Onboard preheat active
unsigned char manualMode : 1 ; // Manual move mode active
unsigned char onboardScript : 1 ; // Bot is running an onboard script
unsigned char onboardProcess : 1 ; // Bot is running an onboard process
unsigned char waitForButton : 1 ; // Bot is waiting for button press
unsigned char buildCancelling : 1 ; // Watchdog reset flag was set at restart
unsigned char heatShutdown : 1 ; // Heaters were shutdown after 30 minutes of inactivity
unsigned char powerError : 1 ; // An error was detected with the system power.
} flag ;
} motherboard ;
struct {
unsigned lineNumber ;
unsigned char status ;
unsigned char hours ;
unsigned char minutes ;
} build ;
} response ;
2013-11-24 17:04:49 +04:00
} Sio ;
2013-11-15 21:17:33 +04:00
2014-01-08 22:20:51 +04:00
char * sd_status [ ] = {
" operation successful " ,
" SD Card not present " ,
" SD Card initialization failed " ,
" partition table could not be read " ,
" filesystem could not be opened " ,
" root directory could not be opened " ,
" SD Card is locked " ,
" unknown status "
} ;
static char * get_sd_status ( unsigned int status )
{
return sd_status [ status < 7 ? status : 7 ] ;
}
char * build_status [ ] = {
" no build initialized (boot state) " ,
" build running " ,
" build finished normally " ,
" build paused " ,
" build cancelled " ,
" build sleeping " ,
" unknown status "
} ;
static char * get_build_status ( unsigned int status )
{
return sd_status [ status < 6 ? status : 6 ] ;
}
static void read_extruder_query_response ( Gpx * gpx , Sio * sio , unsigned command , char * buffer )
{
unsigned extruder_id = buffer [ EXTRUDER_ID_OFFSET ] ;
switch ( command ) {
// Query 00 - Query firmware version information
case 0 :
// uint16: Firmware Version
sio - > response . firmware . version = read_16 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Extruder T%u firmware v%u.%u " EOL ,
extruder_id ,
sio - > response . firmware . version / 100 ,
sio - > response . firmware . version % 100 ) ) ;
break ;
// Query 02 - Get extruder temperature
case 2 :
// int16: Current temperature, in Celsius
sio - > response . temperature = read_16 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Extruder T%u temperature: %uc " EOL ,
extruder_id ,
sio - > response . temperature ) ) ;
break ;
// Query 22 - Is extruder ready
case 22 :
// uint8: 1 if ready, 0 otherwise.
sio - > response . isReady = read_8 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Extruder T%u is%sready " EOL ,
extruder_id ,
sio - > response . isReady ? " " : " not " ) ) ;
break ;
// Query 30 - Get build platform temperature
case 30 :
// int16: Current temperature, in Celsius
sio - > response . temperature = read_16 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Build platform T%u temperature: %uc " EOL ,
extruder_id ,
sio - > response . temperature ) ) ;
break ;
// Query 32 - Get extruder target temperature
case 32 :
// int16: Current temperature, in Celsius
sio - > response . temperature = read_16 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Extruder T%u target temperature: %uc " EOL ,
extruder_id ,
sio - > response . temperature ) ) ;
break ;
// Query 33 - Get build platform target temperature
case 33 :
// int16: Current temperature, in Celsius
sio - > response . temperature = read_16 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Build platform T%u target temperature: %uc " EOL ,
extruder_id ,
sio - > response . temperature ) ) ;
break ;
// Query 35 - Is build platform ready?
case 35 :
// uint8: 1 if ready, 0 otherwise.
sio - > response . isReady = read_8 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Build platform T%u is%sready " EOL ,
extruder_id ,
sio - > response . isReady ? " " : " not " ) ) ;
break ;
// Query 36 - Get extruder status
case 36 :
// uint8: Bitfield containing status information
sio - > response . extruder . bitfield = read_8 ( gpx ) ;
if ( gpx - > flag . verboseMode & & gpx - > flag . logMessages ) {
fprintf ( gpx - > log , " Extruder T%u status " EOL , extruder_id ) ;
if ( sio - > response . extruder . flag . ready ) fputs ( " Target temperature reached " EOL , gpx - > log ) ;
if ( sio - > response . extruder . flag . notPluggedIn ) fputs ( " The extruder or build plate is not plugged in " EOL , gpx - > log ) ;
if ( sio - > response . extruder . flag . softwareCutoff ) fputs ( " Above maximum allowable temperature recorded: heater shutdown for safety " EOL , gpx - > log ) ;
if ( sio - > response . extruder . flag . temperatureDropping ) fputs ( " Heater temperature dropped below target temperature " EOL , gpx - > log ) ;
if ( sio - > response . extruder . flag . buildPlateError ) fputs ( " An error was detected with the build plate heater or sensor " EOL , gpx - > log ) ;
if ( sio - > response . extruder . flag . extruderError ) fputs ( " An error was detected with the extruder heater or sensor " EOL , gpx - > log ) ;
}
break ;
// Query 37 - Get PID state
case 37 :
// int16: Extruder heater error term
sio - > response . pid . extruderError = read_16 ( gpx ) ;
// int16: Extruder heater delta term
sio - > response . pid . extruderDelta = read_16 ( gpx ) ;
// int16: Extruder heater last output
sio - > response . pid . extruderOutput = read_16 ( gpx ) ;
// int16: Platform heater error term
sio - > response . pid . buildPlateError = read_16 ( gpx ) ;
// int16: Platform heater delta term
sio - > response . pid . buildPlateDelta = read_16 ( gpx ) ;
// int16: Platform heater last output
sio - > response . pid . buildPlateOutput = read_16 ( gpx ) ;
break ;
default :
abort ( ) ;
}
}
static void read_query_response ( Gpx * gpx , Sio * sio , unsigned command , char * buffer )
{
gpx - > buffer . ptr = gpx - > buffer . in + 2 ;
switch ( command ) {
// 00 - Query firmware version information
case 0 :
// uint16: Firmware Version
sio - > response . firmware . version = read_16 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Motherboard firmware v%u.%u " EOL ,
sio - > response . firmware . version / 100 , sio - > response . firmware . version % 100 ) ) ;
break ;
// 02 - Get available buffer size
case 2 :
// uint32: Number of bytes availabe in the command buffer
sio - > response . bufferSize = read_32 ( gpx ) ;
break ;
// 10 - Extruder query command
case 10 : {
unsigned query_command = buffer [ QUERY_COMMAND_OFFSET ] ;
read_extruder_query_response ( gpx , sio , query_command , buffer ) ;
break ;
}
// 11 - Is ready
case 11 :
// uint8: 1 if ready, 0 otherwise.
sio - > response . isReady = read_8 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Printer is%sready " EOL ,
sio - > response . isReady ? " " : " not " ) ) ;
break ;
// 12 - Read from EEPROM
case 12 :
// N bytes: Data read from the EEPROM
sio - > response . eeprom . length = buffer [ EEPROM_LENGTH_OFFSET ] ;
read_bytes ( gpx , sio - > response . eeprom . buffer , sio - > response . eeprom . length ) ;
break ;
// 13 - Write to EEPROM
case 13 :
// uint8: Number of bytes successfully written to the EEPROM
sio - > response . eeprom . length = read_8 ( gpx ) ;
break ;
// 14 - Capture to file
case 14 :
// uint8: SD response code
sio - > response . sd . status = read_8 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Capture to file: %s " EOL ,
get_sd_status ( sio - > response . sd . status ) ) ) ;
break ;
// 15 - End capture to file
case 15 :
// uint32: Number of bytes captured to file.
sio - > response . sd . length = read_32 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Capture to file ended: %u bytes written " EOL ,
sio - > response . sd . length ) ) ;
break ;
// 16 - Play back capture
case 16 :
// uint8: SD response code
sio - > response . sd . status = read_8 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " Play back captured file: %s " EOL ,
get_sd_status ( sio - > response . sd . status ) ) ) ;
break ;
// 18 - Get next filename
case 18 :
// uint8: SD Response code.
sio - > response . sd . status = read_8 ( gpx ) ;
/* 1+N bytes: Name of the next file, in ASCII, terminated with a null character.
If the operation was unsuccessful , this will be a null character */
strncpy0 ( sio - > response . sd . filename , gpx - > buffer . ptr , 65 ) ;
VERBOSE ( fprintf ( gpx - > log , " Get next filename: '%s' %s " EOL ,
sio - > response . sd . filename ,
get_sd_status ( sio - > response . sd . status ) ) ) ;
break ;
// 20 - Get build name
case 20 :
// 1+N bytes: A null terminated string representing the filename of the current build.
strncpy0 ( sio - > response . sd . filename , gpx - > buffer . ptr , 65 ) ;
VERBOSE ( fprintf ( gpx - > log , " Get build name: '%s' " EOL , sio - > response . sd . filename ) ) ;
break ;
// 21 - Get extended position
case 21 :
// int32: X position, in steps
sio - > response . position . x = read_32 ( gpx ) ;
// int32: Y position, in steps
sio - > response . position . y = read_32 ( gpx ) ;
// int32: Z position, in steps
sio - > response . position . z = read_32 ( gpx ) ;
// int32: A position, in steps
sio - > response . position . a = read_32 ( gpx ) ;
// int32: B position, in steps
sio - > response . position . b = read_32 ( gpx ) ;
// uint16: bitfield corresponding to the endstop status:
sio - > response . position . endstop . bitfield = read_16 ( gpx ) ;
if ( gpx - > flag . verboseMode & & gpx - > flag . logMessages ) {
fputs ( " Current position " EOL , gpx - > log ) ;
fprintf ( gpx - > log , " X = %0.2fmm%s%s " EOL ,
( double ) sio - > response . position . x / gpx - > machine . x . steps_per_mm ,
sio - > response . position . endstop . flag . xMax ? " , at max endstop " : " " ,
sio - > response . position . endstop . flag . xMin ? " , at min endstop " : " " ) ;
fprintf ( gpx - > log , " Y = %0.2fmm%s%s " EOL ,
( double ) sio - > response . position . y / gpx - > machine . y . steps_per_mm ,
sio - > response . position . endstop . flag . yMax ? " , at max endstop " : " " ,
sio - > response . position . endstop . flag . yMin ? " , at min endstop " : " " ) ;
fprintf ( gpx - > log , " Z = %0.2fmm%s%s " EOL ,
( double ) sio - > response . position . z / gpx - > machine . z . steps_per_mm ,
sio - > response . position . endstop . flag . zMax ? " , at max endstop " : " " ,
sio - > response . position . endstop . flag . zMin ? " , at min endstop " : " " ) ;
fprintf ( gpx - > log , " A = %0.2fmm%s%s " EOL ,
( double ) sio - > response . position . a / gpx - > machine . a . steps_per_mm ,
sio - > response . position . endstop . flag . aMax ? " , at max endstop " : " " ,
sio - > response . position . endstop . flag . aMin ? " , at min endstop " : " " ) ;
fprintf ( gpx - > log , " B = %0.2fmm%s%s " EOL ,
( double ) sio - > response . position . b / gpx - > machine . b . steps_per_mm ,
sio - > response . position . endstop . flag . bMax ? " , at max endstop " : " " ,
sio - > response . position . endstop . flag . bMin ? " , at min endstop " : " " ) ;
}
break ;
// 22 - Extended stop
case 22 :
// int8: 0 (reserved for future use)
read_8 ( gpx ) ;
VERBOSE ( fputs ( " Build stopped " EOL , gpx - > log ) ) ;
break ;
// 23 - Get motherboard status
case 23 :
// uint8: bitfield containing status information
sio - > response . motherboard . bitfield = read_8 ( gpx ) ;
if ( gpx - > flag . verboseMode & & gpx - > flag . logMessages ) {
fputs ( " Motherboard status " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . preheat ) fputs ( " Onboard preheat active " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . manualMode ) fputs ( " Manual move active " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . onboardScript ) fputs ( " Running onboard script " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . onboardProcess ) fputs ( " Running onboard process " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . waitForButton ) fputs ( " Waiting for buttons press " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . buildCancelling ) fputs ( " Build cancelling " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . heatShutdown ) fputs ( " Heaters were shutdown after 30 minutes of inactivity " EOL , gpx - > log ) ;
if ( sio - > response . motherboard . flag . powerError ) fputs ( " Error detected in system power " EOL , gpx - > log ) ;
}
break ;
// 24 - Get build statistics
case 24 :
// uint8 : Build status
sio - > response . build . status = read_8 ( gpx ) ;
// uint8 : Hours elapsed on print
sio - > response . build . hours = read_8 ( gpx ) ;
// uint8 : Minutes elapsed on print (add hours for total time)
sio - > response . build . minutes = read_8 ( gpx ) ;
// uint32: Line number (number of commands processed)
sio - > response . build . lineNumber = read_32 ( gpx ) ;
// uint32: Reserved for future use
read_32 ( gpx ) ;
VERBOSE ( fprintf ( gpx - > log , " (line %u) Build status: %s, %u hours, %u minutes " EOL ,
sio - > response . build . lineNumber ,
get_build_status ( sio - > response . build . status ) ,
sio - > response . build . hours ,
sio - > response . build . minutes ) ) ;
break ;
// 27 - Get advanced version number
case 27 :
// uint16_t Firmware version
sio - > response . firmware . version = read_16 ( gpx ) ;
// uint16_t Internal version
read_16 ( gpx ) ;
// uint8_t Software variant (0x01 MBI Official, 0x80 Sailfish)
sio - > response . firmware . variant = read_8 ( gpx ) ;
// uint8_t Reserved for future use
read_8 ( gpx ) ;
// uint16_t Reserved for future use
read_16 ( gpx ) ;
if ( gpx - > flag . verboseMode & & gpx - > flag . logMessages ) {
char * varient = " Unknown " ;
switch ( sio - > response . firmware . variant ) {
case 0x01 :
varient = " Makerbot " ;
break ;
case 0x80 :
varient = " Sailfish " ;
break ;
}
fprintf ( gpx - > log , " %s firmware v%u.%u " EOL , varient , sio - > response . firmware . version / 100 , sio - > response . firmware . version % 100 ) ;
}
break ;
}
}
// 02 - Get available buffer size
char buffer_size_query [ ] = {
0xD5 , // start byte
1 , // length
2 , // query command
0 // crc
} ;
static int port_handler ( Gpx * gpx , Sio * sio , char * buffer , size_t length )
2013-11-24 17:04:49 +04:00
{
2014-01-08 22:20:51 +04:00
int rval = SUCCESS ;
2013-11-24 17:04:49 +04:00
if ( length ) {
2014-01-08 22:20:51 +04:00
ssize_t bytes ;
int retry_count = 0 ;
do {
// send the packet
if ( ( bytes = write ( sio - > port , buffer , length ) ) = = - 1 ) {
return errno ;
}
else if ( bytes ! = length ) {
return ESIOWRITE ;
}
sio - > bytes_out + = length ;
if ( sio - > bytes_in ) {
// recieve the response
if ( ( bytes = read ( sio - > port , gpx - > buffer . in , 2 ) ) = = - 1 ) {
return errno ;
}
else if ( bytes ! = 2 ) {
return ESIOREAD ;
}
// invalid start byte
if ( gpx - > buffer . in [ 0 ] ! = 0xD5 ) {
return ESIOFRAME ;
}
}
else {
// first read
for ( ; ; ) {
// read start byte
if ( ( bytes = read ( sio - > port , gpx - > buffer . in , 1 ) ) = = - 1 ) {
return errno ;
}
else if ( bytes ! = 1 ) {
return ESIOREAD ;
}
// loop until we get a valid start byte
if ( gpx - > buffer . in [ 0 ] = = 0xD5 ) break ;
}
// read length
if ( ( bytes = read ( sio - > port , gpx - > buffer . in + 1 , 1 ) ) = = - 1 ) {
return errno ;
}
else if ( bytes ! = 1 ) {
return ESIOREAD ;
}
}
size_t payload_length = gpx - > buffer . in [ 1 ] ;
// recieve payload
if ( ( bytes = read ( sio - > port , gpx - > buffer . in + 2 , payload_length + 1 ) ) = = - 1 ) {
return errno ;
}
else if ( bytes ! = payload_length + 1 ) {
return ESIOREAD ;
}
// check CRC
unsigned crc = ( unsigned char ) gpx - > buffer . in [ 2 + payload_length ] ;
if ( crc ! = calculate_crc ( ( unsigned char * ) gpx - > buffer . in + 2 , payload_length ) ) {
fprintf ( gpx - > log , " (retry %u) Input CRC mismatch: packet discarded " EOL , retry_count ) ;
rval = ESIOCRC ;
goto L_RETRY ;
}
// check response code
rval = gpx - > buffer . in [ 2 ] ;
switch ( ( unsigned ) gpx - > buffer . in [ 2 ] ) {
// 0x80 - Generic Packet error, packet discarded (retry)
case 0x80 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Generic Packet error: packet discarded " EOL , retry_count ) ) ;
break ;
// 0x81 - Success
case 0x81 : {
unsigned command = ( unsigned ) buffer [ COMMAND_OFFSET ] ;
if ( ( command & 0x80 ) = = 0 ) {
read_query_response ( gpx , sio , command , buffer ) ;
}
return SUCCESS ;
}
// 0x82 - Action buffer overflow, entire packet discarded
case 0x82 :
do {
// wait for 1/10 seconds
usleep ( 100000 ) ;
// query buffer size
buffer_size_query [ 3 ] = calculate_crc ( ( unsigned char * ) buffer_size_query + 2 , 1 ) ;
CALL ( port_handler ( gpx , sio , buffer_size_query , 4 ) ) ;
// loop until buffer has space for the next command
} while ( sio - > response . bufferSize < length ) ;
break ;
// 0x83 - CRC mismatch, packet discarded. (retry)
case 0x83 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Output CRC mismatch: packet discarded " EOL , retry_count ) ) ;
break ;
// 0x84 - Query packet too big, packet discarded
case 0x84 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Query packet too big: packet discarded " EOL , retry_count ) ) ;
goto L_ABORT ;
// 0x85 - Command not supported/recognized
case 0x85 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Command not supported or recognized " EOL , retry_count ) ) ;
goto L_ABORT ;
// 0x87 - Downstream timeout
case 0x87 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Downstream timeout " EOL , retry_count ) ) ;
goto L_ABORT ;
// 0x88 - Tool lock timeout (retry)
case 0x88 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Tool lock timeout " EOL , retry_count ) ) ;
break ;
// 0x89 - Cancel build (retry)
case 0x89 :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Cancel build " EOL , retry_count ) ) ;
break ;
// 0x8A - Bot is building from SD
case 0x8A :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Bot is Building from SD card " EOL , retry_count ) ) ;
goto L_ABORT ;
// 0x8B - Bot is shutdown due to overheating
case 0x8B :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Bot is shutdown due to overheating " EOL , retry_count ) ) ;
goto L_ABORT ;
// 0x8C - Packet timeout error, packet discarded (retry)
case 0x8C :
VERBOSE ( fprintf ( gpx - > log , " (retry %u) Packet timeout error: packet discarded " EOL , retry_count ) ) ;
break ;
}
L_RETRY :
// wait for 2 seconds
sleep ( 2 ) ;
} while ( + + retry_count < 5 ) ;
2013-11-24 17:04:49 +04:00
}
2014-01-08 22:20:51 +04:00
L_ABORT :
return rval ;
2013-04-11 05:32:34 +04:00
}
2014-01-08 22:20:51 +04:00
int gpx_convert_and_send ( Gpx * gpx , FILE * file_in , int sio_port )
2013-11-24 17:04:49 +04:00
{
int i , rval ;
Sio sio ;
sio . in = stdin ;
sio . port = - 1 ;
2014-01-08 22:20:51 +04:00
sio . bytes_out = 0 ;
sio . bytes_in = 0 ;
int logMessages = gpx - > flag . logMessages ;
2013-11-24 17:04:49 +04:00
if ( file_in & & file_in ! = stdin ) {
// Multi-pass
sio . in = file_in ;
i = 0 ;
2014-01-08 22:20:51 +04:00
gpx - > flag . logMessages = 0 ;
2013-11-24 17:04:49 +04:00
gpx - > flag . framingEnabled = 0 ;
gpx - > callbackHandler = NULL ;
gpx - > callbackData = NULL ;
}
else {
// Single-pass
i = 1 ;
gpx - > flag . framingEnabled = 1 ;
2014-01-08 22:20:51 +04:00
gpx - > callbackHandler = ( int ( * ) ( Gpx * , void * , char * , size_t ) ) port_handler ; ;
2013-11-24 17:04:49 +04:00
gpx - > callbackData = & sio ;
}
if ( sio_port > 2 ) {
sio . port = sio_port ;
}
for ( ; ; ) {
int overflow = 0 ;
while ( fgets ( gpx - > buffer . in , BUFFER_MAX , sio . in ) ! = NULL ) {
// detect input buffer overflow and ignore overflow input
if ( overflow ) {
if ( strlen ( gpx - > buffer . in ) ! = BUFFER_MAX - 1 ) {
overflow = 0 ;
}
continue ;
}
if ( strlen ( gpx - > buffer . in ) = = BUFFER_MAX - 1 ) {
overflow = 1 ;
2014-01-08 22:20:51 +04:00
SHOW ( fprintf ( gpx - > log , " (line %u) Buffer overflow: input exceeds %u character limit, remaining characters in line will be ignored " EOL , gpx - > lineNumber , BUFFER_MAX ) ) ;
2013-11-24 17:04:49 +04:00
}
rval = gpx_convert_line ( gpx , gpx - > buffer . in ) ;
// normal exit
if ( rval > 0 ) break ;
// error
if ( rval < 0 ) return rval ;
}
if ( program_is_running ( ) ) {
end_program ( ) ;
CALL ( set_build_progress ( gpx , 100 ) ) ;
CALL ( end_build ( gpx ) ) ;
}
CALL ( set_steppers ( gpx , AXES_BIT_MASK , 0 ) ) ;
gpx - > total . length = gpx - > accumulated . a + gpx - > accumulated . b ;
gpx - > total . time = gpx - > accumulated . time ;
gpx - > total . bytes = gpx - > accumulated . bytes ;
if ( + + i > 1 ) break ;
// rewind for second pass
fseek ( sio . in , 0L , SEEK_SET ) ;
gpx_initialize ( gpx , 0 ) ;
2014-01-08 22:20:51 +04:00
gpx - > flag . logMessages = 1 ;
2013-11-24 17:04:49 +04:00
gpx - > flag . framingEnabled = 1 ;
2014-01-08 22:20:51 +04:00
gpx - > callbackHandler = ( int ( * ) ( Gpx * , void * , char * , size_t ) ) port_handler ; ;
2013-11-24 17:04:49 +04:00
gpx - > callbackData = & sio ;
}
2014-01-08 22:20:51 +04:00
gpx - > flag . logMessages = logMessages ; ;
return SUCCESS ;
}
void gpx_end_convert ( Gpx * gpx )
{
if ( gpx - > flag . verboseMode & & gpx - > flag . logMessages ) {
long seconds = round ( gpx - > accumulated . time ) ;
long minutes = seconds / 60 ;
long hours = minutes / 60 ;
minutes % = 60 ;
seconds % = 60 ;
fprintf ( gpx - > log , " Extrusion length: %#0.3f metres " EOL , round ( gpx - > accumulated . a + gpx - > accumulated . b ) / 1000 ) ;
fputs ( " Estimated print time: " , gpx - > log ) ;
if ( hours ) fprintf ( gpx - > log , " %lu hours " , hours ) ;
if ( minutes ) fprintf ( gpx - > log , " %lu minutes " , minutes ) ;
fprintf ( gpx - > log , " %lu seconds " EOL , seconds ) ;
fprintf ( gpx - > log , " X3G output filesize: %lu bytes " EOL , gpx - > accumulated . bytes ) ;
}
}
// EEPROM
static int write_eeprom_8 ( Gpx * gpx , Sio * sio , unsigned address , unsigned char value )
{
int rval ;
gpx - > buffer . ptr = sio - > response . eeprom . buffer ;
write_8 ( gpx , value ) ;
CALL ( write_eeprom ( gpx , address , sio - > response . eeprom . buffer , 1 ) ) ;
return SUCCESS ;
}
static int read_eeprom_8 ( Gpx * gpx , Sio * sio , unsigned address , unsigned char * value )
{
int rval ;
CALL ( read_eeprom ( gpx , address , 1 ) ) ;
gpx - > buffer . ptr = sio - > response . eeprom . buffer ;
* value = read_8 ( gpx ) ;
return SUCCESS ;
}
static int write_eeprom_32 ( Gpx * gpx , Sio * sio , unsigned address , unsigned value )
{
int rval ;
gpx - > buffer . ptr = sio - > response . eeprom . buffer ;
write_32 ( gpx , value ) ;
CALL ( write_eeprom ( gpx , address , sio - > response . eeprom . buffer , 4 ) ) ;
return SUCCESS ;
}
static int read_eeprom_32 ( Gpx * gpx , Sio * sio , unsigned address , unsigned * value )
{
int rval ;
CALL ( read_eeprom ( gpx , address , 4 ) ) ;
gpx - > buffer . ptr = sio - > response . eeprom . buffer ;
* value = read_32 ( gpx ) ;
return SUCCESS ;
}
static int write_eeprom_float ( Gpx * gpx , Sio * sio , unsigned address , float value )
{
int rval ;
gpx - > buffer . ptr = sio - > response . eeprom . buffer ;
write_float ( gpx , value ) ;
CALL ( write_eeprom ( gpx , address , sio - > response . eeprom . buffer , 4 ) ) ;
return SUCCESS ;
}
static int read_eeprom_float ( Gpx * gpx , Sio * sio , unsigned address , float * value )
{
int rval ;
CALL ( read_eeprom ( gpx , address , 4 ) ) ;
gpx - > buffer . ptr = sio - > response . eeprom . buffer ;
* value = read_float ( gpx ) ;
return SUCCESS ;
}
static int eeprom_set_property ( Gpx * gpx , const char * section , const char * property , char * value )
{
int rval ;
unsigned int address = ( unsigned int ) strtol ( property , NULL , 0 ) ;
if ( SECTION_IS ( " byte " ) ) {
unsigned char b = ( unsigned char ) strtol ( value , NULL , 0 ) ;
CALL ( write_eeprom_8 ( gpx , ( Sio * ) gpx - > callbackData , address , b ) ) ;
}
else if ( SECTION_IS ( " integer " ) ) {
unsigned int i = ( unsigned int ) strtol ( value , NULL , 0 ) ;
CALL ( write_eeprom_32 ( gpx , ( Sio * ) gpx - > callbackData , address , i ) ) ;
}
else if ( SECTION_IS ( " hex " ) | | SECTION_IS ( " hexadecimal " ) ) {
unsigned int h = ( unsigned int ) strtol ( value , NULL , 16 ) ;
unsigned length = ( unsigned ) strlen ( value ) / 2 ;
if ( length > 4 ) length = 4 ;
gpx - > buffer . ptr = ( ( Sio * ) gpx - > callbackData ) - > response . eeprom . buffer ;
write_32 ( gpx , h ) ;
CALL ( write_eeprom ( gpx , address , ( ( Sio * ) gpx - > callbackData ) - > response . eeprom . buffer , length ) ) ;
}
else if ( SECTION_IS ( " float " ) ) {
float f = strtof ( value , NULL ) ;
CALL ( write_eeprom_float ( gpx , ( Sio * ) gpx - > callbackData , address , f ) ) ;
}
else if ( SECTION_IS ( " string " ) ) {
unsigned length = ( unsigned ) strlen ( value ) ;
CALL ( write_eeprom ( gpx , address , value , length ) ) ;
}
else {
SHOW ( fprintf ( gpx - > log , " (line %u) Configuration error: unrecognised section [%s] " EOL , gpx - > lineNumber , section ) ) ;
return gpx - > lineNumber ;
}
return SUCCESS ;
}
int eeprom_load_config ( Gpx * gpx , const char * filename )
{
return ini_parse ( gpx , filename , eeprom_set_property ) ;
}