summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradrian-bowyer <adrian-bowyer@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-11-20 14:50:19 +0000
committeradrian-bowyer <adrian-bowyer@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-11-20 14:50:19 +0000
commit77fc82ad8589ddeed0bd20b8bac5662233112013 (patch)
tree31ae588de09126046f96c4f2072b2fa34921a5d2
parent02038b9b3f406b109a54fe901148ce265b5b7752 (diff)
downloadreprap-backup-77fc82ad8589ddeed0bd20b8bac5662233112013.tar.gz
reprap-backup-77fc82ad8589ddeed0bd20b8bac5662233112013.zip
Arduino/Sanguino GCode firmware updated to allow multiple extruders in the Sanguino version.
Some code tidying too. git-svn-id: https://reprap.svn.sourceforge.net/svnroot/reprap@2247 cb376a5e-1013-0410-a455-b6b1f9ac8223
-rw-r--r--trunk/reprap/firmware/GCode_Interpreter/GCode_Interpreter.pde136
-rw-r--r--trunk/reprap/firmware/GCode_Interpreter/ThermistorTable.h8
-rw-r--r--trunk/reprap/firmware/GCode_Interpreter/extruder.h.dist56
-rw-r--r--trunk/reprap/firmware/GCode_Interpreter/extruder.pde229
-rw-r--r--trunk/reprap/firmware/GCode_Interpreter/process_string.pde96
-rw-r--r--trunk/reprap/firmware/GCode_Interpreter/stepper_control.pde21
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/GCode_Interpreter.pde (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/GCode_Interpreter.pde)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/ThermistorTable.h (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/ThermistorTable.h)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/_init.pde (renamed from trunk/reprap/firmware/GCode_Interpreter/_init.pde)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.cpp1528
-rwxr-xr-xtrunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.elfbin0 -> 73576 bytes
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.hex779
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.pde158
-rwxr-xr-xtrunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.rom780
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/ThermistorTable.h36
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/_init.pde (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/_init.pde)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/core.abin0 -> 71598 bytes
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/extruder.pde (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/extruder.pde)1
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/parameters.h27
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/pins.h77
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/process_string.pde (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/process_string.pde)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/stepper_control.pde (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/stepper_control.pde)13
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/extruder.pde267
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/parameters.h.dist (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/parameters.h.dist)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/pins.h.dist (renamed from trunk/reprap/firmware/Sanguino/GCode_Interpreter/pins.h.dist)0
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/process_string.pde579
-rw-r--r--trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/stepper_control.pde466
-rw-r--r--trunk/reprap/firmware/sketch_081010a/sketch_081010a.pde17
28 files changed, 5047 insertions, 227 deletions
diff --git a/trunk/reprap/firmware/GCode_Interpreter/GCode_Interpreter.pde b/trunk/reprap/firmware/GCode_Interpreter/GCode_Interpreter.pde
index 63438124..f243cd36 100644
--- a/trunk/reprap/firmware/GCode_Interpreter/GCode_Interpreter.pde
+++ b/trunk/reprap/firmware/GCode_Interpreter/GCode_Interpreter.pde
@@ -5,33 +5,32 @@
// v1.1 by Zach Hoeken - cleaned up and did lots of tweaks (hoeken@gmail.com)
// v1.2 by Chris Meighan - cleanup / G2&G3 support (cmeighan@gmail.com)
// v1.3 by Zach Hoeken - added thermocouple support and multi-sample temp readings. (hoeken@gmail.com)
-// Sanguino v1.4 by Adrian Bowyer - switch to the Sanguino; extensive mods... (a.bowyer@bath.ac.uk)
+// Sanguino v1.4 by Adrian Bowyer - added the Sanguino; extensive mods... (a.bowyer@bath.ac.uk)
#include <ctype.h>
#include <HardwareSerial.h>
+#include "parameters.h"
+#include "pins.h"
+#include "extruder.h"
-// Uncomment the next line to run stand-alone tests on the machine (also see the
-// ends of this, the process_string, the extruder, and the stepper_control tabs).
-//#define TEST_MACHINE
-//our command string
-#define COMMAND_SIZE 128
-char word[COMMAND_SIZE];
-char c = '?';
-byte serial_count = 0;
-boolean comment = false;
+byte extruder_in_use = 0;
+extruder ex0(EXTRUDER_0_MOTOR_DIR_PIN, EXTRUDER_0_MOTOR_SPEED_PIN , EXTRUDER_0_HEATER_PIN,
+ EXTRUDER_0_FAN_PIN, EXTRUDER_0_TEMPERATURE_PIN, EXTRUDER_0_VALVE_DIR_PIN,
+ EXTRUDER_0_VALVE_ENABLE_PIN);
+
+extruder* ex[EXTRUDER_COUNT];
void setup()
{
- //Do startup stuff here
+ ex[0] = &ex0;
Serial.begin(19200);
Serial.println("start");
//other initialization.
init_process_string();
init_steppers();
- init_extruder();
}
void loop()
@@ -40,54 +39,9 @@ void loop()
//keep it hot!
- extruder_manage_temperature();
-
- //read in characters if we got them.
- if (Serial.available())
- {
- c = Serial.read();
- if(c == '\r')
- c = '\n';
- // Throw away control chars except \n
- if(c >= ' ' || c == '\n')
- {
-
- //newlines are ends of commands.
- if (c != '\n')
- {
- // Start of comment - ignore any bytes received from now on
- if (c == ';')
- comment = true;
-
- // If we're not in comment mode, add it to our array.
- if (!comment)
- word[serial_count++] = c;
- }
-
- }
- }
-
- // Data runaway?
- if(serial_count >= COMMAND_SIZE)
- init_process_string();
-
- //if we've got a real command, do it
- if (serial_count && c == '\n')
- {
- // Terminate string
- word[serial_count] = 0;
-
- //process our command!
- process_string(word, serial_count);
-
- //clear command.
- init_process_string();
-
- // Say we're ready for the next one
-
- Serial.println("ok");
- }
-
+ manage_all_extruders();
+ get_and_do_command();
+
#else
// Run the parts of the machine as a test
@@ -96,9 +50,6 @@ void loop()
// what you type in a terminal window connected
// to the Sanguino.
-// If that works, comment out the next line to test the rest:
-#define COMMS_TEST
-
#ifdef COMMS_TEST
comms_test();
@@ -110,35 +61,38 @@ void loop()
c = Serial.read();
Serial.println(c);
}
-
- switch(c)
+ if(c >= '0' && c <= '9')
{
- case 0:
- break;
-
- case 'x':
- X_motor_test();
- break;
- case 'y':
- Y_motor_test();
- break;
- case 'z':
- Z_motor_test();
- break;
- case 'h':
- extruder_heater_test();
- break;
- case 'e':
- extruder_drive_test();
- break;
- case 'v':
- extruder_valve_test();
- break;
- case 'f':
- extruder_fan_test();
- break;
+ extruder_in_use = c - '0';
+ if(extruder_in_use >= EXTRUDER_COUNT)
+ extruder_in_use = EXTRUDER_COUNT - 1;
+ } else
+ {
+ switch(c)
+ {
+ case 'x':
+ X_motor_test();
+ break;
+ case 'y':
+ Y_motor_test();
+ break;
+ case 'z':
+ Z_motor_test();
+ break;
+ case 'h':
+ ex[extruder_in_use]->heater_test();
+ break;
+ case 'e':
+ ex[extruder_in_use]->drive_test();
+ break;
+ case 'v':
+ ex[extruder_in_use]->valve_test();
+ break;
+ case 'f':
+ ex[extruder_in_use]->fan_test();
+ break;
- default:
+ default:
Serial.println("Commands:\n");
Serial.println(" x - X motor test");
Serial.println(" y - Y motor test");
@@ -147,9 +101,11 @@ void loop()
Serial.println(" e - extruder drive test");
Serial.println(" v - extruder valve test");
Serial.println(" f - extruder fan test");
+ Serial.println(" 0..9 - select extruder");
Serial.println(" s - stop current test at the end of its cycle then print this list\n\n");
Serial.print("Command: ");
c = 0;
+ }
}
#endif
diff --git a/trunk/reprap/firmware/GCode_Interpreter/ThermistorTable.h b/trunk/reprap/firmware/GCode_Interpreter/ThermistorTable.h
index 07a35377..1fa53628 100644
--- a/trunk/reprap/firmware/GCode_Interpreter/ThermistorTable.h
+++ b/trunk/reprap/firmware/GCode_Interpreter/ThermistorTable.h
@@ -1,6 +1,12 @@
#ifndef THERMISTORTABLE_H_
#define THERMISTORTABLE_H_
+// Uncomment the next line if you are using a thermistor; leave it if you have a thermocouple
+//#define USE_THERMISTOR
+
+// How many temperature samples to take. each sample takes about 100 usecs.
+#define TEMPERATURE_SAMPLES 3
+
// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)
// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)
// ./createTemperatureLookup.py --r0=100000 --t0=25 --r1=0 --r2=4700 --beta=4066 --max-adc=1023
@@ -10,6 +16,7 @@
// r2: 4700
// beta: 4066
// max adc: 1023
+#ifdef USE_THERMISTOR
#define NUMTEMPS 20
short temptable[NUMTEMPS][2] = {
{1, 841},
@@ -34,3 +41,4 @@ short temptable[NUMTEMPS][2] = {
{1008, 3}
};
#endif
+#endif
diff --git a/trunk/reprap/firmware/GCode_Interpreter/extruder.h.dist b/trunk/reprap/firmware/GCode_Interpreter/extruder.h.dist
new file mode 100644
index 00000000..afb7ece0
--- /dev/null
+++ b/trunk/reprap/firmware/GCode_Interpreter/extruder.h.dist
@@ -0,0 +1,56 @@
+#ifndef EXTRUDER_H
+#define EXTRUDER_H
+
+#define EXTRUDER_FORWARD true
+#define EXTRUDER_REVERSE false
+
+#define EXTRUDER_COUNT 1
+
+void manage_all_extruders();
+
+class extruder
+{
+private:
+
+//these our the default values for the extruder.
+ int e_speed;
+ int target_celsius;
+ int max_celsius;
+ byte heater_low;
+ byte heater_high;
+ byte heater_current;
+
+//this is for doing encoder based extruder control
+ int rpm;
+ long e_delay;
+ int error;
+ int last_extruder_error;
+ int error_delta;
+ bool e_direction;
+ bool valve_open;
+
+// The pins we control
+ byte motor_dir_pin, motor_speed_pin, heater_pin, fan_pin, temp_pin, valve_dir_pin, valve_en_pin;
+
+public:
+
+ extruder(byte md_pin, byte ms_pin, byte h_pin, byte f_pin, byte t_pin, byte vd_pin, byte ve_pin);
+ void wait_for_heater();
+ void valve_set(bool open, int millis);
+ void set_direction(bool direction);
+ void set_speed(byte e_speed);
+ void set_cooler(byte e_speed);
+ void set_temperature(int temp);
+ int get_temperature();
+ int sample_temperature(byte pin);
+ void manage();
+
+#ifdef TEST_MACHINE
+ void heater_test();
+ void drive_test();
+ void valve_test();
+ void fan_test();
+#endif
+
+};
+#endif
diff --git a/trunk/reprap/firmware/GCode_Interpreter/extruder.pde b/trunk/reprap/firmware/GCode_Interpreter/extruder.pde
index 6cb0311d..3130e4a9 100644
--- a/trunk/reprap/firmware/GCode_Interpreter/extruder.pde
+++ b/trunk/reprap/firmware/GCode_Interpreter/extruder.pde
@@ -1,115 +1,137 @@
-// Yep, this is actually -*- c++ -*-
+#include "parameters.h"
+#include "pins.h"
#include "ThermistorTable.h"
+#include "extruder.h"
-#define EXTRUDER_0_FORWARD true
-#define EXTRUDER_0_REVERSE false
-
-//these our the default values for the extruder.
-int extruder_speed = 128;
-int extruder_target_celsius = 0;
-int extruder_max_celsius = 0;
-byte extruder_heater_low = 64;
-byte extruder_heater_high = 255;
-byte extruder_heater_current = 0;
-
-//this is for doing encoder based extruder control
-int extruder_rpm = 0;
-long extruder_delay = 0;
-int extruder_error = 0;
-int last_extruder_error = 0;
-int extruder_error_delta = 0;
-bool extruder_direction = EXTRUDER_0_FORWARD;
-bool valve_open = false;
-
-void init_extruder()
+void manage_all_extruders()
{
- //default to cool...
- extruder_set_temperature(-273);
-
+ for(byte i = 0; i < EXTRUDER_COUNT; i++)
+ ex[i]->manage();
+}
+
+extruder::extruder(byte md_pin, byte ms_pin, byte h_pin, byte f_pin, byte t_pin, byte vd_pin, byte ve_pin)
+{
+ motor_dir_pin = md_pin;
+ motor_speed_pin = ms_pin;
+ heater_pin = h_pin;
+ fan_pin = f_pin;
+ temp_pin = t_pin;
+ valve_dir_pin = vd_pin;
+ valve_en_pin = ve_pin;
+
//setup our pins
- pinMode(EXTRUDER_0_MOTOR_DIR_PIN, OUTPUT);
- pinMode(EXTRUDER_0_MOTOR_SPEED_PIN, OUTPUT);
- pinMode(EXTRUDER_0_HEATER_PIN, OUTPUT);
- pinMode(EXTRUDER_0_FAN_PIN, OUTPUT);
- pinMode(EXTRUDER_0_VALVE_DIR_PIN, OUTPUT);
- pinMode(EXTRUDER_0_VALVE_ENABLE_PIN, OUTPUT);
+ pinMode(motor_dir_pin, OUTPUT);
+ pinMode(motor_speed_pin, OUTPUT);
+ pinMode(heater_pin, OUTPUT);
+ pinMode(fan_pin, OUTPUT);
+ pinMode(temp_pin, INPUT);
+ pinMode(valve_dir_pin, OUTPUT);
+ pinMode(valve_en_pin, OUTPUT);
//initialize values
- digitalWrite(EXTRUDER_0_MOTOR_DIR_PIN, EXTRUDER_0_FORWARD);
- analogWrite(EXTRUDER_0_FAN_PIN, 0);
- analogWrite(EXTRUDER_0_HEATER_PIN, 0);
- analogWrite(EXTRUDER_0_MOTOR_SPEED_PIN, 0);
- digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, false);
- digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+ digitalWrite(motor_dir_pin, EXTRUDER_FORWARD);
+ analogWrite(fan_pin, 0);
+ analogWrite(heater_pin, 0);
+ analogWrite(motor_speed_pin, 0);
+ digitalWrite(valve_dir_pin, false);
+ digitalWrite(valve_en_pin, 0);
+
+ //these our the default values for the extruder.
+ e_speed = 128;
+ target_celsius = -273;
+ max_celsius = 0;
+ heater_low = 64;
+ heater_high = 255;
+ heater_current = 0;
+ valve_open = false;
+
+//this is for doing encoder based extruder control
+ rpm = 0;
+ e_delay = 0;
+ error = 0;
+ last_extruder_error = 0;
+ error_delta = 0;
+ e_direction = EXTRUDER_FORWARD;
+
+ //default to cool
+ set_temperature(target_celsius);
}
-void wait_for_heater()
+void extruder::wait_for_heater()
{
//warmup if we're too cold.
- while (extruder_get_temperature() < (extruder_target_celsius - 5))
+ byte count = 0;
+ int oldT, newT;
+ oldT = get_temperature();
+ while (get_temperature() < (target_celsius - 5))
{
- extruder_manage_temperature();
- //Serial.print("T: ");
- //Serial.println(extruder_get_temperature());
+ manage_all_extruders();
+ count++;
+ if(count > 20)
+ {
+ newT = get_temperature();
+ if(newT > oldT)
+ {
+ oldT = newT;
+ } else
+ {
+ // Temp's stuck - dud heater or temperature sensor
+ // Tell the host and return.
+ Serial.print("E: ");
+ Serial.println(newT);
+ return;
+ }
+ count = 0;
+ }
delay(1000);
}
}
-void valve_set(bool open, int millis)
+void extruder::valve_set(bool open, int millis)
{
wait_for_heater();
valve_open = open;
- digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, open);
- digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 1);
+ digitalWrite(valve_dir_pin, open);
+ digitalWrite(valve_en_pin, 1);
delay(millis);
- digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+ digitalWrite(valve_en_pin, 0);
}
-void extruder_set_direction(bool direction)
+void extruder::set_direction(bool dir)
{
- extruder_direction = direction;
- digitalWrite(EXTRUDER_0_MOTOR_DIR_PIN, direction);
+ e_direction = dir;
+ digitalWrite(motor_dir_pin, e_direction);
}
-void extruder_set_speed(byte speed)
+void extruder::set_speed(byte sp)
{
- if(speed > 0)
+ e_speed = sp;
+ if(e_speed > 0)
wait_for_heater();
- analogWrite(EXTRUDER_0_MOTOR_SPEED_PIN, speed);
+ analogWrite(motor_speed_pin, e_speed);
}
-void extruder_set_cooler(byte speed)
+void extruder::set_cooler(byte sp)
{
- analogWrite(EXTRUDER_0_FAN_PIN, speed);
+ analogWrite(fan_pin, sp);
}
-void extruder_set_temperature(int temp)
+void extruder::set_temperature(int temp)
{
- extruder_target_celsius = temp;
- extruder_max_celsius = (int)((float)temp * 1.1);
+ target_celsius = temp;
+ max_celsius = (temp*11)/10;
}
/**
* Samples the temperature and converts it to degrees celsius.
* Returns degrees celsius.
*/
-int extruder_get_temperature()
-{
- if (EXTRUDER_0_THERMISTOR_PIN > -1)
- return extruder_read_thermistor();
- else if (EXTRUDER_0_THERMOCOUPLE_PIN > -1)
- return extruder_read_thermocouple();
-}
-
-/*
-* This function gives us the temperature from the thermistor in Celsius
-*/
-
-int extruder_read_thermistor()
+int extruder::get_temperature()
{
- int raw = extruder_sample_temperature(EXTRUDER_0_THERMISTOR_PIN);
+#ifdef USE_THERMISTOR
+ int raw = sample_temperature(temp_pin);
int celsius = 0;
byte i;
@@ -134,20 +156,17 @@ int extruder_read_thermistor()
else if (celsius < 0) celsius = 0;
return celsius;
+#else
+ return ( 5.0 * sample_temperature(temp_pin) * 100.0) / 1024.0;
+#endif
}
-/*
-* This function gives us the temperature from the thermocouple in Celsius
-*/
-int extruder_read_thermocouple()
-{
- return ( 5.0 * extruder_sample_temperature(EXTRUDER_0_THERMOCOUPLE_PIN) * 100.0) / 1024.0;
-}
+
/*
* This function gives us an averaged sample of the analog temperature pin.
*/
-int extruder_sample_temperature(byte pin)
+int extruder::sample_temperature(byte pin)
{
int raw = 0;
@@ -163,27 +182,29 @@ int extruder_sample_temperature(byte pin)
}
/*!
- Manages motor and heater based on measured temperature:
+ Manages extruder functions to keep temps, speeds etc
+ at the set levels. Should be called only by manage_all_extruders(),
+ which should be called in all non-trivial loops.
o If temp is too low, don't start the motor
o Adjust the heater power to keep the temperature at the target
*/
-void extruder_manage_temperature()
+void extruder::manage()
{
//make sure we know what our temp is.
- int current_celsius = extruder_get_temperature();
+ int current_celsius = get_temperature();
byte newheat = 0;
//put the heater into high mode if we're not at our target.
- if (current_celsius < extruder_target_celsius)
- newheat = extruder_heater_high;
+ if (current_celsius < target_celsius)
+ newheat = heater_high;
//put the heater on low if we're at our target.
- else if (current_celsius < extruder_max_celsius)
- newheat = extruder_heater_low;
+ else if (current_celsius < max_celsius)
+ newheat = heater_low;
// Only update heat if it changed
- if (extruder_heater_current != newheat) {
- extruder_heater_current = newheat;
- analogWrite(EXTRUDER_0_HEATER_PIN, extruder_heater_current);
+ if (heater_current != newheat) {
+ heater_current = newheat;
+ analogWrite(heater_pin, heater_current);
}
}
@@ -191,21 +212,21 @@ void extruder_manage_temperature()
bool heat_on;
-void extruder_heater_test()
+void extruder::heater_test()
{
- int t = extruder_get_temperature();
+ int t = get_temperature();
if(t < 50 && !heat_on)
{
Serial.println("\n *** Turning heater on.\n");
heat_on = true;
- analogWrite(EXTRUDER_0_HEATER_PIN, extruder_heater_high);
+ analogWrite(heater_pin, heater_high);
}
if(t > 100 && heat_on)
{
Serial.println("\n *** Turning heater off.\n");
heat_on = false;
- analogWrite(EXTRUDER_0_HEATER_PIN, 0);
+ analogWrite(heater_pin, 0);
}
Serial.print("Temperature: ");
@@ -219,25 +240,25 @@ void extruder_heater_test()
delay(2000);
}
-void extruder_drive_test()
+void extruder::drive_test()
{
Serial.println("Turning the extruder motor on forwards for 5 seconds.");
- extruder_set_direction(true);
- extruder_set_speed(200);
+ set_direction(true);
+ set_speed(200);
delay(5000);
- extruder_set_speed(0);
+ set_speed(0);
Serial.println("Pausing for 2 seconds.");
delay(2000);
Serial.println("Turning the extruder motor on backwards for 5 seconds.");
- extruder_set_direction(false);
- extruder_set_speed(200);
+ set_direction(false);
+ set_speed(200);
delay(5000);
- extruder_set_speed(0);
+ set_speed(0);
Serial.println("Pausing for 2 seconds.");
delay(2000);
}
-void extruder_valve_test()
+void extruder::valve_test()
{
Serial.println("Opening the valve.");
valve_set(true, 500);
@@ -249,14 +270,14 @@ void extruder_valve_test()
delay(2000);
}
-void extruder_fan_test()
+void extruder::fan_test()
{
Serial.println("Fan on.");
- extruder_set_cooler(255);
+ set_cooler(255);
Serial.println("Pausing for 2 seconds.");
delay(2000);
Serial.println("Fan off.");
- extruder_set_cooler(0);
+ set_cooler(0);
Serial.println("Pausing for 2 seconds.");
delay(2000);
}
diff --git a/trunk/reprap/firmware/GCode_Interpreter/process_string.pde b/trunk/reprap/firmware/GCode_Interpreter/process_string.pde
index c22d83c8..61c2bfb3 100644
--- a/trunk/reprap/firmware/GCode_Interpreter/process_string.pde
+++ b/trunk/reprap/firmware/GCode_Interpreter/process_string.pde
@@ -1,4 +1,14 @@
-// Yep, this is actually -*- c++ -*-
+
+#include "parameters.h"
+#include "pins.h"
+#include "extruder.h"
+
+//our command string
+#define COMMAND_SIZE 128
+char word[COMMAND_SIZE];
+char c = '?';
+byte serial_count = 0;
+boolean comment = false;
// our point structure to make things nice.
struct LongPoint
@@ -54,19 +64,69 @@ byte x_direction = 1;
byte y_direction = 1;
byte z_direction = 1;
+int extruder_speed = 0;
+
int scan_int(char *str, int *valp);
int scan_float(char *str, float *valp);
//init our string processing
void init_process_string()
{
- //init our command
- //for (byte i=0; i<COMMAND_SIZE; i++)
- // word[i] = 0;
serial_count = 0;
comment = false;
}
+// Get a command and process it
+
+void get_and_do_command()
+{
+ //read in characters if we got them.
+ if (Serial.available())
+ {
+ c = Serial.read();
+ if(c == '\r')
+ c = '\n';
+ // Throw away control chars except \n
+ if(c >= ' ' || c == '\n')
+ {
+
+ //newlines are ends of commands.
+ if (c != '\n')
+ {
+ // Start of comment - ignore any bytes received from now on
+ if (c == ';')
+ comment = true;
+
+ // If we're not in comment mode, add it to our array.
+ if (!comment)
+ word[serial_count++] = c;
+ }
+
+ }
+ }
+
+ // Data runaway?
+ if(serial_count >= COMMAND_SIZE)
+ init_process_string();
+
+ //if we've got a real command, do it
+ if (serial_count && c == '\n')
+ {
+ // Terminate string
+ word[serial_count] = 0;
+
+ //process our command!
+ process_string(word, serial_count);
+
+ //clear command.
+ init_process_string();
+
+ // Say we're ready for the next one
+
+ Serial.println("ok");
+ }
+}
+
//our feedrate variables.
float feedrate = 0.0;
long feedrate_micros = 0;
@@ -450,33 +510,33 @@ void process_string(char instruction[], int size)
*/
//turn extruder on, forward
case 101:
- extruder_set_direction(1);
- extruder_set_speed(extruder_speed);
+ ex[extruder_in_use]->set_direction(1);
+ ex[extruder_in_use]->set_speed(extruder_speed);
break;
//turn extruder on, reverse
case 102:
- extruder_set_direction(0);
- extruder_set_speed(extruder_speed);
+ ex[extruder_in_use]->set_direction(0);
+ ex[extruder_in_use]->set_speed(extruder_speed);
break;
//turn extruder off
case 103:
- extruder_set_speed(0);
+ ex[extruder_in_use]->set_speed(0);
break;
//custom code for temperature control
case 104:
if (gc.seen & GCODE_S)
{
- extruder_set_temperature((int)gc.S);
+ ex[extruder_in_use]->set_temperature((int)gc.S);
// //warmup if we're too cold.
-// while (extruder_get_temperature() < extruder_target_celsius)
+// while (ex[extruder_in_use]->get_temperature() < extruder_target_celsius)
// {
-// extruder_manage_temperature();
+// manage_all_extruders();
// Serial.print("T: ");
-// Serial.println(extruder_get_temperature());
+// Serial.println(ex[extruder_in_use]->get_temperature());
// delay(1000);
// }
}
@@ -485,17 +545,17 @@ void process_string(char instruction[], int size)
//custom code for temperature reading
case 105:
Serial.print("T:");
- Serial.println(extruder_get_temperature());
+ Serial.println(ex[extruder_in_use]->get_temperature());
break;
//turn fan on
case 106:
- extruder_set_cooler(255);
+ ex[extruder_in_use]->set_cooler(255);
break;
//turn fan off
case 107:
- extruder_set_cooler(0);
+ ex[extruder_in_use]->set_cooler(0);
break;
//set max extruder speed, 0-255 PWM
@@ -506,12 +566,12 @@ void process_string(char instruction[], int size)
// Open the valve
case 126:
- valve_set(true, (int)(gc.P + 0.5));
+ ex[extruder_in_use]->valve_set(true, (int)(gc.P + 0.5));
break;
// Close the valve
case 127:
- valve_set(false, (int)(gc.P + 0.5));
+ ex[extruder_in_use]->valve_set(false, (int)(gc.P + 0.5));
break;
diff --git a/trunk/reprap/firmware/GCode_Interpreter/stepper_control.pde b/trunk/reprap/firmware/GCode_Interpreter/stepper_control.pde
index 5d59fa6c..b4860101 100644
--- a/trunk/reprap/firmware/GCode_Interpreter/stepper_control.pde
+++ b/trunk/reprap/firmware/GCode_Interpreter/stepper_control.pde
@@ -1,4 +1,6 @@
-// Yep, this is actually -*- c++ -*-
+#include "parameters.h"
+#include "pins.h"
+#include "extruder.h"
//init our variables
long max_delta;
@@ -33,13 +35,18 @@ void init_steppers()
pinMode(X_STEP_PIN, OUTPUT);
pinMode(X_DIR_PIN, OUTPUT);
- pinMode(X_ENABLE_PIN, OUTPUT);
+
pinMode(Y_STEP_PIN, OUTPUT);
pinMode(Y_DIR_PIN, OUTPUT);
- pinMode(Y_ENABLE_PIN, OUTPUT);
+
pinMode(Z_STEP_PIN, OUTPUT);
pinMode(Z_DIR_PIN, OUTPUT);
+
+#ifdef SANGUINO
+ pinMode(X_ENABLE_PIN, OUTPUT);
+ pinMode(Y_ENABLE_PIN, OUTPUT);
pinMode(Z_ENABLE_PIN, OUTPUT);
+#endif
#if ENDSTOPS_MIN_ENABLED == 1
pinMode(X_MIN_PIN, INPUT);
@@ -137,7 +144,7 @@ void dda_move(long micro_delay)
}
//keep it hot =)
- extruder_manage_temperature();
+ manage_all_extruders();
//wait for next step.
if (milli_delay > 0)
@@ -305,6 +312,9 @@ void enable_steppers()
// taking account of the fact that some or all axes
// may share an enable line (check using macros at
// compile time to avoid needless code)
+ // Not enough pins for enable on Arduino
+
+#ifdef SANGUINO
if ( target_units.x == current_units.x
#if X_ENABLE_PIN == Y_ENABLE_PIN
&& target_units.y == current_units.y
@@ -338,14 +348,17 @@ void enable_steppers()
digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
else
digitalWrite(Z_ENABLE_PIN, ENABLE_ON);
+#endif
}
void disable_steppers()
{
+ #ifdef SANGUINO
//disable our steppers
digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
+#endif
}
void delayMicrosecondsInterruptible(unsigned int us)
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/GCode_Interpreter.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/GCode_Interpreter.pde
index 63438124..63438124 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/GCode_Interpreter.pde
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/GCode_Interpreter.pde
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/ThermistorTable.h b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/ThermistorTable.h
index 07a35377..07a35377 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/ThermistorTable.h
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/ThermistorTable.h
diff --git a/trunk/reprap/firmware/GCode_Interpreter/_init.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/_init.pde
index 1db13f72..1db13f72 100644
--- a/trunk/reprap/firmware/GCode_Interpreter/_init.pde
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/_init.pde
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.cpp b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.cpp
new file mode 100644
index 00000000..d60d8b4d
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.cpp
@@ -0,0 +1,1528 @@
+#include "WProgram.h"
+void init_extruder();
+void wait_for_heater();
+void valve_set(bool open, int millis);
+void extruder_set_direction(bool direction);
+void extruder_set_speed(byte speed);
+void extruder_set_cooler(byte speed);
+void extruder_set_temperature(int temp);
+int extruder_get_temperature();
+int extruder_read_thermistor();
+int extruder_read_thermocouple();
+int extruder_sample_temperature(byte pin);
+void extruder_manage_temperature();
+void extruder_heater_test();
+void extruder_drive_test();
+void extruder_valve_test();
+void extruder_fan_test();
+void init_process_string();
+int parse_string(struct GcodeParser * gc, char instruction[], int size);
+void process_string(char instruction[], int size);
+int scan_float(char *str, float *valp, unsigned int *seen, unsigned int flag);
+int scan_int(char *str, int *valp, unsigned int *seen, unsigned int flag);
+void comms_test();
+void init_steppers();
+void dda_move(long micro_delay);
+bool can_step(byte min_pin, byte max_pin, long current, long target, byte direction);
+void do_step(byte step_pin);
+bool read_switch(byte pin);
+long to_steps(float steps_per_unit, float units);
+void set_target(float x, float y, float z);
+void set_position(float x, float y, float z);
+void calculate_deltas();
+long calculate_feedrate_delay(float feedrate);
+long getMaxSpeed();
+void enable_steppers();
+void disable_steppers();
+void delayMicrosecondsInterruptible(unsigned int us);
+void X_motor_test();
+void Y_motor_test();
+void Z_motor_test();
+#include "ctype.h"
+#include "HardwareSerial.h"
+#include "parameters.h"
+#include "pins.h"
+#include "ThermistorTable.h"
+// Yep, this is actually -*- c++ -*-
+
+// Sanguino G-code Interpreter
+// Arduino v1.0 by Mike Ellery - initial software (mellery@gmail.com)
+// v1.1 by Zach Hoeken - cleaned up and did lots of tweaks (hoeken@gmail.com)
+// v1.2 by Chris Meighan - cleanup / G2&G3 support (cmeighan@gmail.com)
+// v1.3 by Zach Hoeken - added thermocouple support and multi-sample temp readings. (hoeken@gmail.com)
+// Sanguino v1.4 by Adrian Bowyer - switch to the Sanguino; extensive mods... (a.bowyer@bath.ac.uk)
+
+// Uncomment the next line to run stand-alone tests on the machine (also see the
+// ends of this, the process_string, the extruder, and the stepper_control tabs).
+//#define TEST_MACHINE
+
+
+//our command string
+#define COMMAND_SIZE 128
+char word[COMMAND_SIZE];
+char c = '?';
+byte serial_count = 0;
+boolean comment = false;
+
+void setup()
+{
+ //Do startup stuff here
+ Serial.begin(19200);
+ Serial.println("start");
+
+ //other initialization.
+ init_process_string();
+ init_steppers();
+ init_extruder();
+}
+
+void loop()
+{
+#ifndef TEST_MACHINE
+
+
+ //keep it hot!
+ extruder_manage_temperature();
+
+ //read in characters if we got them.
+ if (Serial.available())
+ {
+ c = Serial.read();
+ if(c == '\r')
+ c = '\n';
+ // Throw away control chars except \n
+ if(c >= ' ' || c == '\n')
+ {
+
+ //newlines are ends of commands.
+ if (c != '\n')
+ {
+ // Start of comment - ignore any bytes received from now on
+ if (c == ';')
+ comment = true;
+
+ // If we're not in comment mode, add it to our array.
+ if (!comment)
+ word[serial_count++] = c;
+ }
+
+ }
+ }
+
+ // Data runaway?
+ if(serial_count >= COMMAND_SIZE)
+ init_process_string();
+
+ //if we've got a real command, do it
+ if (serial_count && c == '\n')
+ {
+ // Terminate string
+ word[serial_count] = 0;
+
+ //process our command!
+ process_string(word, serial_count);
+
+ //clear command.
+ init_process_string();
+
+ // Say we're ready for the next one
+
+ Serial.println("ok");
+ }
+
+#else
+
+// Run the parts of the machine as a test
+
+// Do the comms test first. It should echo
+// what you type in a terminal window connected
+// to the Sanguino.
+
+// If that works, comment out the next line to test the rest:
+#define COMMS_TEST
+
+#ifdef COMMS_TEST
+
+ comms_test();
+
+#else
+
+ if (Serial.available() > 0)
+ {
+ c = Serial.read();
+ Serial.println(c);
+ }
+
+ switch(c)
+ {
+ case 0:
+ break;
+
+ case 'x':
+ X_motor_test();
+ break;
+ case 'y':
+ Y_motor_test();
+ break;
+ case 'z':
+ Z_motor_test();
+ break;
+ case 'h':
+ extruder_heater_test();
+ break;
+ case 'e':
+ extruder_drive_test();
+ break;
+ case 'v':
+ extruder_valve_test();
+ break;
+ case 'f':
+ extruder_fan_test();
+ break;
+
+ default:
+ Serial.println("Commands:\n");
+ Serial.println(" x - X motor test");
+ Serial.println(" y - Y motor test");
+ Serial.println(" z - Z motor test");
+ Serial.println(" h - extruder heater test");
+ Serial.println(" e - extruder drive test");
+ Serial.println(" v - extruder valve test");
+ Serial.println(" f - extruder fan test");
+ Serial.println(" s - stop current test at the end of its cycle then print this list\n\n");
+ Serial.print("Command: ");
+ c = 0;
+ }
+
+#endif
+
+#endif
+}
+
+
+
+// Yep, this is actually -*- c++ -*-
+
+#define EXTRUDER_0_FORWARD true
+#define EXTRUDER_0_REVERSE false
+
+//these our the default values for the extruder.
+int extruder_speed = 128;
+int extruder_target_celsius = 0;
+int extruder_max_celsius = 0;
+byte extruder_heater_low = 64;
+byte extruder_heater_high = 255;
+byte extruder_heater_current = 0;
+
+//this is for doing encoder based extruder control
+int extruder_rpm = 0;
+long extruder_delay = 0;
+int extruder_error = 0;
+int last_extruder_error = 0;
+int extruder_error_delta = 0;
+bool extruder_direction = EXTRUDER_0_FORWARD;
+bool valve_open = false;
+
+void init_extruder()
+{
+ //default to cool...
+ extruder_set_temperature(-273);
+
+ //setup our pins
+ pinMode(EXTRUDER_0_MOTOR_DIR_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_MOTOR_SPEED_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_HEATER_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_FAN_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_VALVE_DIR_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_VALVE_ENABLE_PIN, OUTPUT);
+
+ //initialize values
+ digitalWrite(EXTRUDER_0_MOTOR_DIR_PIN, EXTRUDER_0_FORWARD);
+ analogWrite(EXTRUDER_0_FAN_PIN, 0);
+ analogWrite(EXTRUDER_0_HEATER_PIN, 0);
+ analogWrite(EXTRUDER_0_MOTOR_SPEED_PIN, 0);
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, false);
+ digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+}
+
+void wait_for_heater()
+{
+ //warmup if we're too cold.
+ while (extruder_get_temperature() < (extruder_target_celsius - 5))
+ {
+ extruder_manage_temperature();
+ //Serial.print("T: ");
+ //Serial.println(extruder_get_temperature());
+ delay(1000);
+ }
+}
+
+void valve_set(bool open, int millis)
+{
+ wait_for_heater();
+ valve_open = open;
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, open);
+ digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 1);
+ delay(millis);
+ digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, 0);
+}
+
+
+void extruder_set_direction(bool direction)
+{
+ extruder_direction = direction;
+ digitalWrite(EXTRUDER_0_MOTOR_DIR_PIN, direction);
+}
+
+void extruder_set_speed(byte speed)
+{
+ if(speed > 0)
+ wait_for_heater();
+ analogWrite(EXTRUDER_0_MOTOR_SPEED_PIN, speed);
+}
+
+void extruder_set_cooler(byte speed)
+{
+ analogWrite(EXTRUDER_0_FAN_PIN, speed);
+}
+
+void extruder_set_temperature(int temp)
+{
+ extruder_target_celsius = temp;
+ extruder_max_celsius = (int)((float)temp * 1.1);
+}
+
+/**
+* Samples the temperature and converts it to degrees celsius.
+* Returns degrees celsius.
+*/
+int extruder_get_temperature()
+{
+ if (EXTRUDER_0_THERMISTOR_PIN > -1)
+ return extruder_read_thermistor();
+ else if (EXTRUDER_0_THERMOCOUPLE_PIN > -1)
+ return extruder_read_thermocouple();
+}
+
+/*
+* This function gives us the temperature from the thermistor in Celsius
+*/
+
+int extruder_read_thermistor()
+{
+ int raw = extruder_sample_temperature(EXTRUDER_0_THERMISTOR_PIN);
+
+ int celsius = 0;
+ byte i;
+
+ for (i=1; i<NUMTEMPS; i++)
+ {
+ if (temptable[i][0] > raw)
+ {
+ celsius = temptable[i-1][1] +
+ (raw - temptable[i-1][0]) *
+ (temptable[i][1] - temptable[i-1][1]) /
+ (temptable[i][0] - temptable[i-1][0]);
+
+ break;
+ }
+ }
+
+ // Overflow: Set to last value in the table
+ if (i == NUMTEMPS) celsius = temptable[i-1][1];
+ // Clamp to byte
+ if (celsius > 255) celsius = 255;
+ else if (celsius < 0) celsius = 0;
+
+ return celsius;
+}
+
+/*
+* This function gives us the temperature from the thermocouple in Celsius
+*/
+int extruder_read_thermocouple()
+{
+ return ( 5.0 * extruder_sample_temperature(EXTRUDER_0_THERMOCOUPLE_PIN) * 100.0) / 1024.0;
+}
+
+/*
+* This function gives us an averaged sample of the analog temperature pin.
+*/
+int extruder_sample_temperature(byte pin)
+{
+ int raw = 0;
+
+ //read in a certain number of samples
+ for (byte i=0; i<TEMPERATURE_SAMPLES; i++)
+ raw += analogRead(pin);
+
+ //average the samples
+ raw = raw/TEMPERATURE_SAMPLES;
+
+ //send it back.
+ return raw;
+}
+
+/*!
+ Manages motor and heater based on measured temperature:
+ o If temp is too low, don't start the motor
+ o Adjust the heater power to keep the temperature at the target
+ */
+void extruder_manage_temperature()
+{
+ //make sure we know what our temp is.
+ int current_celsius = extruder_get_temperature();
+ byte newheat = 0;
+
+ //put the heater into high mode if we're not at our target.
+ if (current_celsius < extruder_target_celsius)
+ newheat = extruder_heater_high;
+ //put the heater on low if we're at our target.
+ else if (current_celsius < extruder_max_celsius)
+ newheat = extruder_heater_low;
+
+ // Only update heat if it changed
+ if (extruder_heater_current != newheat) {
+ extruder_heater_current = newheat;
+ analogWrite(EXTRUDER_0_HEATER_PIN, extruder_heater_current);
+ }
+}
+
+#ifdef TEST_MACHINE
+
+bool heat_on;
+
+void extruder_heater_test()
+{
+ int t = extruder_get_temperature();
+ if(t < 50 && !heat_on)
+ {
+ Serial.println("\n *** Turning heater on.\n");
+ heat_on = true;
+ analogWrite(EXTRUDER_0_HEATER_PIN, extruder_heater_high);
+ }
+
+ if(t > 100 && heat_on)
+ {
+ Serial.println("\n *** Turning heater off.\n");
+ heat_on = false;
+ analogWrite(EXTRUDER_0_HEATER_PIN, 0);
+ }
+
+ Serial.print("Temperature: ");
+ Serial.print(t);
+ Serial.print(" deg C. The heater is ");
+ if(heat_on)
+ Serial.println("on.");
+ else
+ Serial.println("off.");
+
+ delay(2000);
+}
+
+void extruder_drive_test()
+{
+ Serial.println("Turning the extruder motor on forwards for 5 seconds.");
+ extruder_set_direction(true);
+ extruder_set_speed(200);
+ delay(5000);
+ extruder_set_speed(0);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+ Serial.println("Turning the extruder motor on backwards for 5 seconds.");
+ extruder_set_direction(false);
+ extruder_set_speed(200);
+ delay(5000);
+ extruder_set_speed(0);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+}
+
+void extruder_valve_test()
+{
+ Serial.println("Opening the valve.");
+ valve_set(true, 500);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+ Serial.println("Closing the valve.");
+ valve_set(false, 500);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+}
+
+void extruder_fan_test()
+{
+ Serial.println("Fan on.");
+ extruder_set_cooler(255);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+ Serial.println("Fan off.");
+ extruder_set_cooler(0);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+}
+
+
+
+#endif
+
+// Yep, this is actually -*- c++ -*-
+
+// our point structure to make things nice.
+struct LongPoint
+{
+ long x;
+ long y;
+ long z;
+};
+
+struct FloatPoint
+{
+ float x;
+ float y;
+ float z;
+};
+
+/* gcode line parse results */
+struct GcodeParser
+{
+ unsigned int seen;
+ int G;
+ int M;
+ float P;
+ float X;
+ float Y;
+ float Z;
+ float I;
+ float J;
+ float F;
+ float S;
+ float R;
+ float Q;
+};
+
+FloatPoint current_units;
+FloatPoint target_units;
+FloatPoint delta_units;
+
+FloatPoint current_steps;
+FloatPoint target_steps;
+FloatPoint delta_steps;
+
+boolean abs_mode = true; //0 = incremental; 1 = absolute
+
+//default to mm for units
+float x_units = X_STEPS_PER_MM;
+float y_units = Y_STEPS_PER_MM;
+float z_units = Z_STEPS_PER_MM;
+float curve_section = CURVE_SECTION_MM;
+
+//our direction vars
+byte x_direction = 1;
+byte y_direction = 1;
+byte z_direction = 1;
+
+int scan_int(char *str, int *valp);
+int scan_float(char *str, float *valp);
+
+//init our string processing
+void init_process_string()
+{
+ //init our command
+ //for (byte i=0; i<COMMAND_SIZE; i++)
+ // word[i] = 0;
+ serial_count = 0;
+ comment = false;
+}
+
+//our feedrate variables.
+float feedrate = 0.0;
+long feedrate_micros = 0;
+
+/* keep track of the last G code - this is the command mode to use
+ * if there is no command in the current string
+ */
+int last_gcode_g = -1;
+
+/* bit-flags for commands and parameters */
+#define GCODE_G (1<<0)
+#define GCODE_M (1<<1)
+#define GCODE_P (1<<2)
+#define GCODE_X (1<<3)
+#define GCODE_Y (1<<4)
+#define GCODE_Z (1<<5)
+#define GCODE_I (1<<6)
+#define GCODE_J (1<<7)
+#define GCODE_K (1<<8)
+#define GCODE_F (1<<9)
+#define GCODE_S (1<<10)
+#define GCODE_Q (1<<11)
+#define GCODE_R (1<<12)
+
+#define TYPE_INT 1
+#define TYPE_FLOAT 2
+
+
+#define PARSE_INT(ch, str, len, val, seen, flag) \
+ case ch: \
+ len = scan_int(str, &val, &seen, flag); \
+ break;
+
+#define PARSE_FLOAT(ch, str, len, val, seen, flag) \
+ case ch: \
+ len = scan_float(str, &val, &seen, flag); \
+ break;
+
+int parse_string(struct GcodeParser * gc, char instruction[], int size)
+{
+ int ind;
+ int len; /* length of parameter argument */
+
+ gc->seen = 0;
+
+ len=0;
+ /* scan the string for commands and parameters, recording the arguments for each,
+ * and setting the seen flag for each that is seen
+ */
+ for (ind=0; ind<size; ind += (1+len))
+ {
+ len = 0;
+ switch (instruction[ind])
+ {
+ PARSE_INT('G', &instruction[ind+1], len, gc->G, gc->seen, GCODE_G);
+ PARSE_INT('M', &instruction[ind+1], len, gc->M, gc->seen, GCODE_M);
+ PARSE_FLOAT('S', &instruction[ind+1], len, gc->S, gc->seen, GCODE_S);
+ PARSE_FLOAT('P', &instruction[ind+1], len, gc->P, gc->seen, GCODE_P);
+ PARSE_FLOAT('X', &instruction[ind+1], len, gc->X, gc->seen, GCODE_X);
+ PARSE_FLOAT('Y', &instruction[ind+1], len, gc->Y, gc->seen, GCODE_Y);
+ PARSE_FLOAT('Z', &instruction[ind+1], len, gc->Z, gc->seen, GCODE_Z);
+ PARSE_FLOAT('I', &instruction[ind+1], len, gc->I, gc->seen, GCODE_I);
+ PARSE_FLOAT('J', &instruction[ind+1], len, gc->J, gc->seen, GCODE_J);
+ PARSE_FLOAT('F', &instruction[ind+1], len, gc->F, gc->seen, GCODE_F);
+ PARSE_FLOAT('R', &instruction[ind+1], len, gc->R, gc->seen, GCODE_R);
+ PARSE_FLOAT('Q', &instruction[ind+1], len, gc->Q, gc->seen, GCODE_Q);
+ default:
+ break;
+ }
+ }
+}
+
+
+//Read the string and execute instructions
+void process_string(char instruction[], int size)
+{
+
+ GcodeParser gc; /* string parse result */
+
+ //the character / means delete block... used for comments and stuff.
+ if (instruction[0] == '/')
+ return;
+
+ //init baby!
+ FloatPoint fp;
+ fp.x = 0.0;
+ fp.y = 0.0;
+ fp.z = 0.0;
+
+ //get all our parameters!
+ parse_string(&gc, instruction, size);
+ /* if no command was seen, but parameters were, then use the last G code as
+ * the current command
+ */
+ if ((!(gc.seen & (GCODE_G | GCODE_M))) &&
+ ((gc.seen != 0) &&
+ (last_gcode_g >= 0))
+ )
+ {
+ /* yes - so use the previous command with the new parameters */
+ gc.G = last_gcode_g;
+ gc.seen |= GCODE_G;
+ }
+ //did we get a gcode?
+ if (gc.seen & GCODE_G)
+ {
+ last_gcode_g = gc.G; /* remember this for future instructions */
+ fp = current_units;
+ if (abs_mode)
+ {
+ if (gc.seen & GCODE_X)
+ fp.x = gc.X;
+ if (gc.seen & GCODE_Y)
+ fp.y = gc.Y;
+ if (gc.seen & GCODE_Z)
+ fp.z = gc.Z;
+ }
+ else
+ {
+ if (gc.seen & GCODE_X)
+ fp.x += gc.X;
+ if (gc.seen & GCODE_Y)
+ fp.y += gc.Y;
+ if (gc.seen & GCODE_Z)
+ fp.z += gc.Z;
+ }
+
+ // Get feedrate if supplied
+ if ( gc.seen & GCODE_F )
+ feedrate = gc.F;
+
+ //do something!
+ switch (gc.G)
+ {
+ //Rapid Positioning
+ //Linear Interpolation
+ //these are basically the same thing.
+ case 0:
+ case 1:
+ //set our target.
+ set_target(fp.x, fp.y, fp.z);
+
+ // Use currently set feedrate if doing a G1
+ if (gc.G == 1)
+ feedrate_micros = calculate_feedrate_delay(feedrate);
+ // Use our max for G0
+ else
+ feedrate_micros = getMaxSpeed();
+ //finally move.
+ dda_move(feedrate_micros);
+ break;
+#ifdef SANGUINO
+// No room for this in the Arduino
+ //Clockwise arc
+ case 2:
+ //Counterclockwise arc
+ case 3:
+ {
+ FloatPoint cent;
+
+ // Centre coordinates are always relative
+ if (gc.seen & GCODE_I) cent.x = current_units.x + gc.I;
+ else cent.x = current_units.x;
+ if (gc.seen & GCODE_J) cent.y = current_units.y + gc.J;
+
+ float angleA, angleB, angle, radius, length, aX, aY, bX, bY;
+
+ aX = (current_units.x - cent.x);
+ aY = (current_units.y - cent.y);
+ bX = (fp.x - cent.x);
+ bY = (fp.y - cent.y);
+
+ // Clockwise
+ if (gc.G == 2)
+ {
+ angleA = atan2(bY, bX);
+ angleB = atan2(aY, aX);
+ }
+ // Counterclockwise
+ else
+ {
+ angleA = atan2(aY, aX);
+ angleB = atan2(bY, bX);
+ }
+
+ // Make sure angleB is always greater than angleA
+ // and if not add 2PI so that it is (this also takes
+ // care of the special case of angleA == angleB,
+ // ie we want a complete circle)
+ if (angleB <= angleA)
+ angleB += 2 * M_PI;
+ angle = angleB - angleA;
+
+ radius = sqrt(aX * aX + aY * aY);
+ length = radius * angle;
+ int steps, s, step;
+
+ // Maximum of either 2.4 times the angle in radians or the length of the curve divided by the constant specified in _init.pde
+ steps = (int) ceil(max(angle * 2.4, length / curve_section));
+
+ FloatPoint newPoint;
+ float arc_start_z = current_units.z;
+ for (s = 1; s <= steps; s++)
+ {
+ step = (gc.G == 3) ? s : steps - s; // Work backwards for CW
+ newPoint.x = cent.x + radius * cos(angleA + angle
+ * ((float) step / steps));
+ newPoint.y = cent.y + radius * sin(angleA + angle
+ * ((float) step / steps));
+ set_target(newPoint.x, newPoint.y, arc_start_z + (fp.z
+ - arc_start_z) * s / steps);
+
+ // Need to calculate rate for each section of curve
+ if (feedrate > 0)
+ feedrate_micros = calculate_feedrate_delay(feedrate);
+ else
+ feedrate_micros = getMaxSpeed();
+
+ // Make step
+ dda_move(feedrate_micros);
+ }
+ }
+ break;
+#endif
+
+ case 4: //Dwell
+ delay((int)(gc.P + 0.5)); // Changed by AB from 1000*gc.P
+ break;
+
+ //Inches for Units
+ case 20:
+ x_units = X_STEPS_PER_INCH;
+ y_units = Y_STEPS_PER_INCH;
+ z_units = Z_STEPS_PER_INCH;
+ curve_section = CURVE_SECTION_INCHES;
+
+ calculate_deltas();
+ break;
+
+ //mm for Units
+ case 21:
+ x_units = X_STEPS_PER_MM;
+ y_units = Y_STEPS_PER_MM;
+ z_units = Z_STEPS_PER_MM;
+ curve_section = CURVE_SECTION_MM;
+
+ calculate_deltas();
+ break;
+
+ //go home.
+ case 28:
+ set_target(0.0, 0.0, 0.0);
+ dda_move(getMaxSpeed());
+ break;
+
+ //go home via an intermediate point.
+ case 30:
+ //set our target.
+ set_target(fp.x, fp.y, fp.z);
+
+ //go there.
+ dda_move(getMaxSpeed());
+
+ //go home.
+ set_target(0.0, 0.0, 0.0);
+ dda_move(getMaxSpeed());
+ break;
+
+ // Drilling canned cycles
+ case 81: // Without dwell
+ case 82: // With dwell
+ case 83: // Peck drilling
+ {
+ float retract = gc.R;
+
+ if (!abs_mode)
+ retract += current_units.z;
+
+ // Retract to R position if Z is currently below this
+ if (current_units.z < retract)
+ {
+ set_target(current_units.x, current_units.y, retract);
+ dda_move(getMaxSpeed());
+ }
+
+ // Move to start XY
+ set_target(fp.x, fp.y, current_units.z);
+ dda_move(getMaxSpeed());
+
+ // Do the actual drilling
+ float target_z = retract;
+ float delta_z;
+
+ // For G83 move in increments specified by Q code, otherwise do in one pass
+ if (gc.G == 83)
+ delta_z = gc.Q;
+ else
+ delta_z = retract - fp.z;
+
+ do {
+ // Move rapidly to bottom of hole drilled so far (target Z if starting hole)
+ set_target(fp.x, fp.y, target_z);
+ dda_move(getMaxSpeed());
+
+ // Move with controlled feed rate by delta z (or to bottom of hole if less)
+ target_z -= delta_z;
+ if (target_z < fp.z)
+ target_z = fp.z;
+ set_target(fp.x, fp.y, target_z);
+ if (feedrate > 0)
+ feedrate_micros = calculate_feedrate_delay(feedrate);
+ else
+ feedrate_micros = getMaxSpeed();
+ dda_move(feedrate_micros);
+
+ // Dwell if doing a G82
+ if (gc.G == 82)
+ delay((int)(gc.P * 1000));
+
+ // Retract
+ set_target(fp.x, fp.y, retract);
+ dda_move(getMaxSpeed());
+ } while (target_z > fp.z);
+ }
+ break;
+
+
+ case 90: //Absolute Positioning
+ abs_mode = true;
+ break;
+
+
+ case 91: //Incremental Positioning
+ abs_mode = false;
+ break;
+
+
+ case 92: //Set position as fp
+ set_position(fp.x, fp.y, fp.z);
+ break;
+
+ /*
+ //Inverse Time Feed Mode
+ case 93:
+
+ break; //TODO: add this
+
+ //Feed per Minute Mode
+ case 94:
+
+ break; //TODO: add this
+ */
+
+ default:
+ Serial.print("huh? G");
+ Serial.println(gc.G, DEC);
+ }
+ }
+
+ //find us an m code.
+ if (gc.seen & GCODE_M)
+ {
+ switch (gc.M)
+ {
+ //TODO: this is a bug because search_string returns 0. gotta fix that.
+ case 0:
+ true;
+ break;
+ /*
+ case 0:
+ //todo: stop program
+ break;
+
+ case 1:
+ //todo: optional stop
+ break;
+
+ case 2:
+ //todo: program end
+ break;
+ */
+ //turn extruder on, forward
+ case 101:
+ extruder_set_direction(1);
+ extruder_set_speed(extruder_speed);
+ break;
+
+ //turn extruder on, reverse
+ case 102:
+ extruder_set_direction(0);
+ extruder_set_speed(extruder_speed);
+ break;
+
+ //turn extruder off
+ case 103:
+ extruder_set_speed(0);
+ break;
+
+ //custom code for temperature control
+ case 104:
+ if (gc.seen & GCODE_S)
+ {
+ extruder_set_temperature((int)gc.S);
+
+// //warmup if we're too cold.
+// while (extruder_get_temperature() < extruder_target_celsius)
+// {
+// extruder_manage_temperature();
+// Serial.print("T: ");
+// Serial.println(extruder_get_temperature());
+// delay(1000);
+// }
+ }
+ break;
+
+ //custom code for temperature reading
+ case 105:
+ Serial.print("T:");
+ Serial.println(extruder_get_temperature());
+ break;
+
+ //turn fan on
+ case 106:
+ extruder_set_cooler(255);
+ break;
+
+ //turn fan off
+ case 107:
+ extruder_set_cooler(0);
+ break;
+
+ //set max extruder speed, 0-255 PWM
+ case 108:
+ if (gc.seen & GCODE_S)
+ extruder_speed = (int)gc.S;
+ break;
+
+ // Open the valve
+ case 126:
+ valve_set(true, (int)(gc.P + 0.5));
+ break;
+
+ // Close the valve
+ case 127:
+ valve_set(false, (int)(gc.P + 0.5));
+ break;
+
+
+ default:
+ Serial.print("Huh? M");
+ Serial.println(gc.M, DEC);
+ }
+ }
+
+}
+
+int scan_float(char *str, float *valp, unsigned int *seen, unsigned int flag)
+{
+ float res;
+ int len;
+ char *end;
+
+ res = (float)strtod(str, &end);
+
+ len = end - str;
+
+ if (len > 0)
+ {
+ *valp = res;
+ *seen |= flag;
+ }
+ else
+ *valp = 0;
+
+ return len; /* length of number */
+}
+
+int scan_int(char *str, int *valp, unsigned int *seen, unsigned int flag)
+{
+ int res;
+ int len;
+ char *end;
+
+ res = (int)strtol(str, &end, 10);
+ len = end - str;
+
+ if (len > 0)
+ {
+ *valp = res;
+ *seen |= flag;
+ }
+ else
+ *valp = 0;
+
+ return len; /* length of number */
+}
+
+#ifdef TEST_MACHINE
+
+// Read and echo bytes.
+
+void comms_test()
+{
+ if (Serial.available() > 0)
+ Serial.print((char)Serial.read());
+}
+
+#endif
+
+
+
+// Yep, this is actually -*- c++ -*-
+
+//init our variables
+long max_delta;
+long x_counter;
+long y_counter;
+long z_counter;
+bool x_can_step;
+bool y_can_step;
+bool z_can_step;
+int milli_delay;
+
+#if INVERT_ENABLE_PINS == 1
+#define ENABLE_ON LOW
+#else
+#define ENABLE_ON HIGH
+#endif
+
+#define ENDSTOPS_MIN_ENABLED 1
+
+void init_steppers()
+{
+ //turn them off to start.
+#ifdef SANGUINO
+ disable_steppers();
+#endif
+
+ //init our points.
+ current_units.x = 0.0;
+ current_units.y = 0.0;
+ current_units.z = 0.0;
+ target_units.x = 0.0;
+ target_units.y = 0.0;
+ target_units.z = 0.0;
+
+ pinMode(X_STEP_PIN, OUTPUT);
+ pinMode(X_DIR_PIN, OUTPUT);
+ pinMode(Y_STEP_PIN, OUTPUT);
+ pinMode(Y_DIR_PIN, OUTPUT);
+ pinMode(Z_STEP_PIN, OUTPUT);
+ pinMode(Z_DIR_PIN, OUTPUT);
+
+#ifdef SANGUINO
+ pinMode(X_ENABLE_PIN, OUTPUT);
+ pinMode(Y_ENABLE_PIN, OUTPUT);
+ pinMode(Z_ENABLE_PIN, OUTPUT);
+#endif
+
+#if ENDSTOPS_MIN_ENABLED == 1
+ pinMode(X_MIN_PIN, INPUT);
+ pinMode(Y_MIN_PIN, INPUT);
+ pinMode(Z_MIN_PIN, INPUT);
+#endif
+#if ENDSTOPS_MAX_ENABLED == 1
+ pinMode(X_MAX_PIN, INPUT);
+ pinMode(Y_MAX_PIN, INPUT);
+ pinMode(Z_MAX_PIN, INPUT);
+#endif
+
+ //figure our stuff.
+ calculate_deltas();
+}
+
+void dda_move(long micro_delay)
+{
+ //turn on steppers to start moving =)
+#ifdef SANGUINO
+ enable_steppers();
+#endif
+
+ //figure out our deltas
+ max_delta = max(delta_steps.x, delta_steps.y);
+ max_delta = max(delta_steps.z, max_delta);
+
+ //init stuff.
+ long x_counter = -max_delta/2;
+ long y_counter = -max_delta/2;
+ long z_counter = -max_delta/2;
+
+ //our step flags
+ bool x_can_step = 0;
+ bool y_can_step = 0;
+ bool z_can_step = 0;
+
+ //how long do we delay for?
+ if (micro_delay >= 16383)
+ milli_delay = micro_delay / 1000;
+ else
+ milli_delay = 0;
+
+ //do our DDA line!
+ do
+ {
+ x_can_step = can_step(X_MIN_PIN, X_MAX_PIN, current_steps.x, target_steps.x, x_direction);
+ y_can_step = can_step(Y_MIN_PIN, Y_MAX_PIN, current_steps.y, target_steps.y, y_direction);
+ z_can_step = can_step(Z_MIN_PIN, Z_MAX_PIN, current_steps.z, target_steps.z, z_direction);
+
+ if (x_can_step)
+ {
+ x_counter += delta_steps.x;
+
+ if (x_counter > 0)
+ {
+ do_step(X_STEP_PIN);
+ x_counter -= max_delta;
+
+ if (x_direction)
+ current_steps.x++;
+ else
+ current_steps.x--;
+ }
+ }
+
+ if (y_can_step)
+ {
+ y_counter += delta_steps.y;
+
+ if (y_counter > 0)
+ {
+ do_step(Y_STEP_PIN);
+ y_counter -= max_delta;
+
+ if (y_direction)
+ current_steps.y++;
+ else
+ current_steps.y--;
+ }
+ }
+
+ if (z_can_step)
+ {
+ z_counter += delta_steps.z;
+
+ if (z_counter > 0)
+ {
+ do_step(Z_STEP_PIN);
+ z_counter -= max_delta;
+
+ if (z_direction)
+ current_steps.z++;
+ else
+ current_steps.z--;
+ }
+ }
+
+ //keep it hot =)
+ extruder_manage_temperature();
+
+ //wait for next step.
+ if (milli_delay > 0)
+ delay(milli_delay);
+ else
+ delayMicrosecondsInterruptible(micro_delay);
+ }
+ while (x_can_step || y_can_step || z_can_step);
+
+ //set our points to be the same
+ current_units.x = target_units.x;
+ current_units.y = target_units.y;
+ current_units.z = target_units.z;
+ calculate_deltas();
+}
+
+bool can_step(byte min_pin, byte max_pin, long current, long target, byte direction)
+{
+ //stop us if we're on target
+ if (target == current)
+ return false;
+#if ENDSTOPS_MIN_ENABLED == 1
+ //stop us if we're at home and still going
+ else if (read_switch(min_pin) && !direction)
+ return false;
+#endif
+#if ENDSTOPS_MAX_ENABLED == 1
+ //stop us if we're at max and still going
+ else if (read_switch(max_pin) && direction)
+ return false;
+#endif
+
+ //default to being able to step
+ return true;
+}
+
+void do_step(byte step_pin)
+{
+ digitalWrite(step_pin, HIGH);
+ delayMicroseconds(5);
+ digitalWrite(step_pin, LOW);
+}
+
+bool read_switch(byte pin)
+{
+ //dual read as crude debounce
+ #if ENDSTOPS_INVERTING == 1
+ return !digitalRead(pin) && !digitalRead(pin);
+ #else
+ return digitalRead(pin) && digitalRead(pin);
+ #endif
+}
+
+long to_steps(float steps_per_unit, float units)
+{
+ return steps_per_unit * units;
+}
+
+void set_target(float x, float y, float z)
+{
+ target_units.x = x;
+ target_units.y = y;
+ target_units.z = z;
+
+ calculate_deltas();
+}
+
+void set_position(float x, float y, float z)
+{
+ current_units.x = x;
+ current_units.y = y;
+ current_units.z = z;
+
+ calculate_deltas();
+}
+
+void calculate_deltas()
+{
+ //figure our deltas.
+ delta_units.x = abs(target_units.x - current_units.x);
+ delta_units.y = abs(target_units.y - current_units.y);
+ delta_units.z = abs(target_units.z - current_units.z);
+
+ //set our steps current, target, and delta
+ current_steps.x = to_steps(x_units, current_units.x);
+ current_steps.y = to_steps(y_units, current_units.y);
+ current_steps.z = to_steps(z_units, current_units.z);
+
+ target_steps.x = to_steps(x_units, target_units.x);
+ target_steps.y = to_steps(y_units, target_units.y);
+ target_steps.z = to_steps(z_units, target_units.z);
+
+ delta_steps.x = abs(target_steps.x - current_steps.x);
+ delta_steps.y = abs(target_steps.y - current_steps.y);
+ delta_steps.z = abs(target_steps.z - current_steps.z);
+
+ //what is our direction
+ x_direction = (target_units.x >= current_units.x);
+ y_direction = (target_units.y >= current_units.y);
+ z_direction = (target_units.z >= current_units.z);
+
+ //set our direction pins as well
+#if INVERT_X_DIR == 1
+ digitalWrite(X_DIR_PIN, !x_direction);
+#else
+ digitalWrite(X_DIR_PIN, x_direction);
+#endif
+#if INVERT_Y_DIR == 1
+ digitalWrite(Y_DIR_PIN, !y_direction);
+#else
+ digitalWrite(Y_DIR_PIN, y_direction);
+#endif
+#if INVERT_Z_DIR == 1
+ digitalWrite(Z_DIR_PIN, !z_direction);
+#else
+ digitalWrite(Z_DIR_PIN, z_direction);
+#endif
+}
+
+
+long calculate_feedrate_delay(float feedrate)
+{
+ //how long is our line length?
+ float distance = sqrt(delta_units.x*delta_units.x +
+ delta_units.y*delta_units.y +
+ delta_units.z*delta_units.z);
+ long master_steps = 0;
+
+ //find the dominant axis.
+ if (delta_steps.x > delta_steps.y)
+ {
+ if (delta_steps.z > delta_steps.x)
+ master_steps = delta_steps.z;
+ else
+ master_steps = delta_steps.x;
+ }
+ else
+ {
+ if (delta_steps.z > delta_steps.y)
+ master_steps = delta_steps.z;
+ else
+ master_steps = delta_steps.y;
+ }
+
+ //calculate delay between steps in microseconds. this is sort of tricky, but not too bad.
+ //the formula has been condensed to save space. here it is in english:
+ // (feedrate is in mm/minute)
+ // distance / feedrate * 60000000.0 = move duration in microseconds
+ // move duration / master_steps = time between steps for master axis.
+
+ return ((distance * 60000000.0) / feedrate) / master_steps;
+}
+
+long getMaxSpeed()
+{
+ if (delta_steps.z > 0)
+ return calculate_feedrate_delay(FAST_Z_FEEDRATE);
+ else
+ return calculate_feedrate_delay(FAST_XY_FEEDRATE);
+}
+
+#ifdef SANGUINO
+void enable_steppers()
+{
+ // Enable steppers only for axes which are moving
+ // taking account of the fact that some or all axes
+ // may share an enable line (check using macros at
+ // compile time to avoid needless code)
+ if ( target_units.x == current_units.x
+ #if X_ENABLE_PIN == Y_ENABLE_PIN
+ && target_units.y == current_units.y
+ #endif
+ #if X_ENABLE_PIN == Z_ENABLE_PIN
+ && target_units.z == current_units.z
+ #endif
+ )
+ digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
+ else
+ digitalWrite(X_ENABLE_PIN, ENABLE_ON);
+ if ( target_units.y == current_units.y
+ #if Y_ENABLE_PIN == X_ENABLE_PIN
+ && target_units.x == current_units.x
+ #endif
+ #if Y_ENABLE_PIN == Z_ENABLE_PIN
+ && target_units.z == current_units.z
+ #endif
+ )
+ digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
+ else
+ digitalWrite(Y_ENABLE_PIN, ENABLE_ON);
+ if ( target_units.z == current_units.z
+ #if Z_ENABLE_PIN == X_ENABLE_PIN
+ && target_units.x == current_units.x
+ #endif
+ #if Z_ENABLE_PIN == Y_ENABLE_PIN
+ && target_units.y == current_units.y
+ #endif
+ )
+ digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
+ else
+ digitalWrite(Z_ENABLE_PIN, ENABLE_ON);
+}
+
+void disable_steppers()
+{
+ //disable our steppers
+ digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
+ digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
+ digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
+}
+#endif
+
+void delayMicrosecondsInterruptible(unsigned int us)
+{
+
+#if F_CPU >= 16000000L
+ // for the 16 MHz clock on most Arduino boards
+
+ // for a one-microsecond delay, simply return. the overhead
+ // of the function call yields a delay of approximately 1 1/8 us.
+ if (--us == 0)
+ return;
+
+ // the following loop takes a quarter of a microsecond (4 cycles)
+ // per iteration, so execute it four times for each microsecond of
+ // delay requested.
+ us <<= 2;
+
+ // account for the time taken in the preceeding commands.
+ us -= 2;
+#else
+ // for the 8 MHz internal clock on the ATmega168
+
+ // for a one- or two-microsecond delay, simply return. the overhead of
+ // the function calls takes more than two microseconds. can't just
+ // subtract two, since us is unsigned; we'd overflow.
+ if (--us == 0)
+ return;
+ if (--us == 0)
+ return;
+
+ // the following loop takes half of a microsecond (4 cycles)
+ // per iteration, so execute it twice for each microsecond of
+ // delay requested.
+ us <<= 1;
+
+ // partially compensate for the time taken by the preceeding commands.
+ // we can't subtract any more than this or we'd overflow w/ small delays.
+ us--;
+#endif
+
+ // busy wait
+ __asm__ __volatile__ (
+ "1: sbiw %0,1" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+}
+
+#ifdef TEST_MACHINE
+
+void X_motor_test()
+{
+ Serial.println("Moving X forward by 100 mm at half maximum speed.");
+ set_target(100, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+
+ Serial.println("Moving X back to the start.");
+ set_target(0, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+}
+
+void Y_motor_test()
+{
+
+ Serial.println("Moving Y forward by 100 mm at half maximum speed.");
+ set_target(0, 100, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+
+ Serial.println("Moving Y back to the start.");
+ set_target(0, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+}
+
+void Z_motor_test()
+{
+ Serial.println("Moving Z down by 5 mm at half maximum speed.");
+ set_target(0, 0, 5);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_Z_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+
+ Serial.println("Moving Z back to the start.");
+ set_target(0, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_Z_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+}
+
+#endif
+
+int main(void)
+{
+ init();
+
+ setup();
+
+ for (;;)
+ loop();
+
+ return 0;
+}
+
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.elf b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.elf
new file mode 100755
index 00000000..07bfe1f9
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.elf
Binary files differ
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.hex b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.hex
new file mode 100644
index 00000000..87a43945
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.hex
@@ -0,0 +1,779 @@
+:100000000C9478000C94A0000C94A0000C94A00018
+:100010000C94A0000C94A0000C94A0000C94A000E0
+:100020000C94A0000C94A0000C94A0000C94A000D0
+:100030000C94A0000C94A0000C94A0000C94A000C0
+:100040000C94000E0C94A0000C941A110C94A000B7
+:100050000C94A0000C94A0000C94A0000C94A000A0
+:100060000C94A0000C94A000000024272A00002576
+:10007000282B000023262904040404040404040299
+:100080000202020202030303030303010204081035
+:100090002040800102040810200102040810200002
+:1000A0000000070002010000030406000000000039
+:1000B000000000494E46494E4954594E414ECDCC60
+:1000C000CC3D0AD7233C17B7D13877CC2B32959546
+:1000D000E6241FB14F0A000020410000C842004042
+:1000E0001C4620BCBE4CCA1B0E5AAEC59D749F1048
+:1000F00011241FBECFEFD4E0DEBFCDBF11E0A0E0E2
+:10010000B1E0E8E0F0E302C005900D92A638B10737
+:10011000D9F713E0A6E8B1E001C01D92AA30B107FB
+:10012000E1F710E0C0EFD0E004C02297FE010E948A
+:100130009E17CE3ED107C9F70E94F50D0C94031807
+:100140000C9400009093090280930802AA2797FD5F
+:10015000A095BA2FBC01CD010E94BC152DEC3CEC42
+:100160004CE85FE30E9470160E94891570930B02A1
+:1001700060930A02089510920602109207020895F1
+:100180000E9470160E9489150895019739F0880F12
+:10019000991F880F991F02970197F1F708952F92E1
+:1001A0003F924F925F926F927F928F929F92AF9207
+:1001B000BF92CF92DF92EF92FF920F931F93CF9354
+:1001C000DF93CDB7DEB72C970FB6F894DEBF0FBE26
+:1001D000CDBF69877A878B879C87209032023090C9
+:1001E0003302409034025090350280913602909153
+:1001F0003702A0913802B09139028D839E83AF837C
+:10020000B88780913A0290913B02A0913C02B09154
+:100210003D0289839A83AB83BC83609056027090C1
+:1002200057028090580290905902A0905A02B090C4
+:100230005B02C0905C02D0905D02A6019501C401F2
+:10024000B3010E946C16E0905E02F0905F02009194
+:1002500060021091610218165CF4A4019301C801B8
+:10026000B7010E946C1618165CF0C401B3010DC0F2
+:10027000A6019501C801B7010E946C1618161CF45E
+:10028000C801B70102C0C601B5010E9489155B0112
+:100290006C01A2019101C201B1010E9470167B01A3
+:1002A0008C012D813E814F815885CA01B9010E9480
+:1002B00070169B01AC01C801B7010E94B9147B0103
+:1002C0008C0129813A814B815C81CA01B9010E946C
+:1002D00070169B01AC01C801B7010E94B9140E94BD
+:1002E000D71620EC31EE44E65CE40E9470162985B6
+:1002F0003A854B855C850E9421157B018C01C601E6
+:10030000B5010E94BC159B01AC01C801B7010E9458
+:1003100021150E9489152C960FB6F894DEBF0FBEEA
+:10032000CDBFDF91CF911F910F91FF90EF90DF90A4
+:10033000CF90BF90AF909F908F907F906F905F9085
+:100340004F903F902F90089520E030E040E050E043
+:1003500060915E0270915F028091600290916102F3
+:100360000E946C1618163CF460E070E088E492E499
+:100370000E94CF00089560E070E088EC94E40E9451
+:10038000CF0008952F923F924F925F926F927F928B
+:100390008F929F92AF92BF92CF92DF92EF92FF9295
+:1003A0000F931F93CF93DF93CDB7DEB7A0970FB610
+:1003B000F894DEBF0FBECDBF809126029091270238
+:1003C000A0912802B09129028D8F9E8FAF8FB8A384
+:1003D00080911A0290911B02A0911C02B0911D0203
+:1003E000898F9A8FAB8FBC8F9C01AD016D8D7E8DF7
+:1003F0008F8D98A10E94B8147B018C0120E030E021
+:1004000040E050E00E946C16181624F017FB10957F
+:1004100017F91095E0923202F09233020093340201
+:100420001093350280912A0290912B02A0912C0208
+:10043000B0912D028D8B9E8BAF8BB88F80911E0259
+:1004400090911F02A0912002B0912102898B9A8B7A
+:10045000AB8BBC8B9C01AD016D897E898F89988D9A
+:100460000E94B8147B018C0120E030E040E050E0B5
+:100470000E946C16181624F017FB109517F91095AA
+:10048000E0923602F092370200933802109339025C
+:1004900080912E0290912F02A0913002B0913102F2
+:1004A0008D879E87AF87B88B80912202909123021F
+:1004B000A0912402B091250289879A87AB87BC87D7
+:1004C0009C01AD016D857E858F8598890E94B81449
+:1004D0007B018C0120E030E040E050E00E946C168F
+:1004E000181624F017FB109517F91095E0923A02B0
+:1004F000F0923B0200933C0210933D02E0907101A8
+:10050000F09072010091730110917401298D3A8D60
+:100510004B8D5C8DC801B7010E9470160E94891531
+:100520000E94BC151B012C0160933E0270933F0298
+:100530008093400290934102609075017090760123
+:10054000809077019090780129893A894B895C895C
+:10055000C401B3010E9470160E9489150E94BC1547
+:100560006D837E838F8398876093420270934302EA
+:100570008093440290934502A0907901B0907A0153
+:10058000C0907B01D0907C0129853A854B855C85A4
+:10059000C601B5010E9470160E9489150E94BC1503
+:1005A00069837A838B839C836093460270934702AE
+:1005B00080934802909349022D8D3E8D4F8D58A116
+:1005C000C801B7010E9470160E9489150E94BC15CF
+:1005D0007B018C0160934A0270934B0280934C0222
+:1005E00090934D022D893E894F89588DC401B301E6
+:1005F0000E9470160E9489150E94BC153B014C0197
+:1006000060934E0270934F02809350029093510278
+:100610002D853E854F855889C601B5010E9470160B
+:100620000E9489150E94BC155B016C016093520207
+:10063000709353028093540290935502A20191014A
+:10064000C801B7010E94B8147B018C0120E030E0A2
+:1006500040E050E00E946C16181624F017FB10952D
+:1006600017F91095E0925602F09257020093580243
+:10067000109359022D813E814F815885C401B301E9
+:100680000E94B8147B018C0120E030E040E050E093
+:100690000E946C16181624F017FB109517F9109588
+:1006A000E0925A02F0925B0200935C0210935D02AA
+:1006B00029813A814B815C81C601B5010E94B81441
+:1006C0007B018C0120E030E040E050E00E946C169D
+:1006D000181624F017FB109517F91095E0925E029A
+:1006E000F0925F02009360021093610210E0298D86
+:1006F0003A8D4B8D5C8D6D8D7E8D8F8D98A10E9476
+:100700006C1688230CF011E0109381011092820185
+:1007100029893A894B895C896D897E898F89988D71
+:100720000E946C1688231CF081E080938201109255
+:10073000830129853A854B855C856D857E858F850E
+:1007400098890E946C1688231CF081E080938301B5
+:10075000612F83E00E94200F6091820187E00E9458
+:10076000200F6091830182E10E94200FA0960FB6B6
+:10077000F894DEBF0FBECDBFDF91CF911F910F91D7
+:10078000FF90EF90DF90CF90BF90AF909F908F90B1
+:100790007F906F905F904F903F902F900895EF92D1
+:1007A000FF920F931F9360931A0270931B02809322
+:1007B0001C0290931D0220931E0230931F0240934F
+:1007C000200250932102E0922202F0922302009331
+:1007D0002402109325020E94C2011F910F91FF90E5
+:1007E000EF900895EF92FF920F931F93609326026C
+:1007F00070932702809328029093290220932A0263
+:1008000030932B0240932C0250932D02E0922E0243
+:10081000F0922F0200933002109331020E94C20125
+:100820001F910F91FF90EF90089580936F01682FB3
+:100830008CE00E94200F08951F93182F0E94D40E61
+:10084000892B11F420E007C0812F0E94D40E20E0F4
+:10085000892B09F021E0822F99271F910895CF92CB
+:10086000EF92FF920F931F93E216F306040715070A
+:1008700019F480E090E00AC00E941C04882321F053
+:1008800080E090E0CC2011F081E090E01F910F918A
+:10089000FF90EF90CF9008951F93182F61E00E9472
+:1008A000200F85E090E00E945F0E60E0812F0E94A3
+:1008B000200F1F91089580E090E0A0E0B0E08093C9
+:1008C0001A0290931B02A0931C02B0931D02809306
+:1008D0001E0290931F02A0932002B09321028093E6
+:1008E000220290932302A0932402B09325028093C6
+:1008F000260290932702A0932802B09329028093A6
+:100900002A0290932B02A0932C02B0932D02809385
+:100910002E0290932F02A0933002B093310261E037
+:1009200082E00E94B60E61E083E00E94B60E61E0B4
+:100930008AE00E94B60E61E087E00E94B60E61E098
+:1009400083E10E94B60E61E082E10E94B60E60E093
+:1009500084E00E94B60E60E088E00E94B60E60E07F
+:1009600081E10E94B60E0E94C2010895AF92BF922B
+:10097000CF92DF92EF92FF920F931F93CF93DF936B
+:10098000CDB7DEB722970FB6F894DEBF0FBECDBF4E
+:100990008C017B016A0159014AE050E0BE016F5FA2
+:1009A0007F4F0E948A1329813A81201B310B121636
+:1009B00013065CF4F70171836083F60180819181F5
+:1009C0008A299B299183808303C0F70111821082B9
+:1009D000C90122960FB6F894DEBF0FBECDBFDF91DE
+:1009E000CF911F910F91FF90EF90DF90CF90BF902C
+:1009F000AF900895AF92BF92CF92DF92EF92FF92A5
+:100A00000F931F93CF93DF93CDB7DEB722970FB627
+:100A1000F894DEBF0FBECDBF8C017B016A01590186
+:100A2000BE016F5F7F4F0E943D1229813A81201BDA
+:100A3000310B121613066CF4F70160837183828305
+:100A40009383F601808191818A299B2991838083F8
+:100A500009C080E090E0A0E0B0E0F70180839183DE
+:100A6000A283B383C90122960FB6F894DEBF0FBEEE
+:100A7000CDBFDF91CF911F910F91FF90EF90DF904D
+:100A8000CF90BF90AF9008952F923F924F925F9278
+:100A90006F927F928F929F92AF92BF92CF92DF928E
+:100AA000EF92FF920F931F93CF93DF93CDB7DEB7F3
+:100AB00062970FB6F894DEBF0FBECDBF9A8B898BBD
+:100AC0006B015A834983FC0111821082EE24FF24BA
+:100AD0003696FC83EB838B010F5F1F4F82969E83BC
+:100AE0008D83E989FA893E96F887EF8389899A8907
+:100AF00042969A878987E989FA893A96FC87EB8733
+:100B000089899A898A969E878D87E989FA89B69616
+:100B1000F88BEF8776E1272E312C89899A89280E68
+:100B2000391E6AE1462E512C480E591E54E0652E9E
+:100B3000712C680E791E4EE1842E912C880E991E20
+:100B400032E0A32EB12CA80EB91E89C0F601EE0D1D
+:100B5000FF1DE081E035F1F1E1358CF4E93409F471
+:100B600055C0EA3434F4E63409F45CC0E734B9F42F
+:100B700019C0EA3409F450C0ED3489F419C0E335E2
+:100B800011F1E43534F4E13509F459C0E23539F4B2
+:100B90004FC0E93569F1EA3591F1E83511F180E0AE
+:100BA00090E058C021E030E049895A89B50105C07C
+:100BB00022E030E049895A89B301C8018E0D9F1D9A
+:100BC0000E94B60447C020E034E049895A896D810B
+:100BD0007E813BC024E030E049895A896B817C8169
+:100BE00034C028E030E049895A896B857C852DC066
+:100BF00020E130E049895A896F81788526C020E25A
+:100C000030E049895A8969857A851FC020E430E03F
+:100C100049895A89B10119C020E830E049895A89C7
+:100C2000B20113C020E032E049895A89B4010DC0F5
+:100C300020E030E149895A896F85788906C020E033
+:100C400038E049895A896D857E85C8018E0D9F1DC2
+:100C50000E94FA040894E11CF11CE80EF91EE981D7
+:100C6000FA81EE16FF060CF471CF62960FB6F89477
+:100C7000DEBF0FBECDBFDF91CF911F910F91FF90CF
+:100C8000EF90DF90CF90BF90AF909F908F907F902C
+:100C90006F905F904F903F902F9008959927BC01DF
+:100CA00085E00E94860F08958FEE9EEF0E94A200BD
+:100CB00061E08CE00E94B60E61E08BE00E94B60E0F
+:100CC00061E086E00E94B60E61E085E00E94B60E0B
+:100CD00061E080E10E94B60E61E08FE00E94B60EF6
+:100CE00061E08CE00E94200F60E070E085E00E94EF
+:100CF000860F60E070E086E00E94860F60E070E0A2
+:100D00008BE00E94860F60E080E10E94200F60E08F
+:100D10008FE00E94200F08950F931F93CF93DF93CE
+:100D2000082FC0E0D0E010E0802F0E946B0FC80FAA
+:100D3000D91F1F5F1330C1F7CE0163E070E00E943E
+:100D40003817CB01DF91CF911F910F91089580E06B
+:100D50000E948C06AA2797FDA095BA2FBC01CD0151
+:100D60000E94BC1520E030E040EA50E40E9470167A
+:100D700020E030E048EC52E40E94701620E030E0C1
+:100D800040E85AE30E9470160E948915DC01CB01ED
+:100D900008950E94A70608950E94C9069C018091AB
+:100DA000080290910902281739071CF460916E011E
+:100DB0000BC080910A0290910B022817390714F09A
+:100DC00060E002C060916D0180910C02861731F0E5
+:100DD00060930C02772786E00E94860F08953F9269
+:100DE0004F925F926F927F928F929F92AF92BF923B
+:100DF000CF92DF92EF92FF920F931F93CF93DF93E7
+:100E0000CDB7DEB728970FB6F894DEBF0FBECDBFC3
+:100E10006D837E838F839887A0905602B09057028F
+:100E2000C0905802D0905902E0905A02F0905B02B4
+:100E300000915C0210915D02A8019701C601B50105
+:100E40000E946C1618161CF4C601B50102C0C80138
+:100E5000B7010E94891560936A0270936B028093B8
+:100E60006C0290936D02A0905E02B0905F02C09001
+:100E70006002D09061020E94BC157B018C019B0135
+:100E8000AC01C601B5010E946C1618161CF4C6010F
+:100E9000B50102C0C801B7010E94891560936A02BA
+:100EA00070936B0280936C0290936D0222E030E0AD
+:100EB00040E050E00E946D17442455243201421A4C
+:100EC000530A640A750A2D813E814F8158852F3F50
+:100ED0008FE3380780E0480780E058076CF0CA01CC
+:100EE000B90128EE33E040E050E00E946D173093E6
+:100EF0007E0220937D0204C010927E0210927D0239
+:100F00005301420149825A826B827C8260914A027B
+:100F100070914B0280914C0290914D020E94891574
+:100F20007B018C0160913E0270913F0280914002F2
+:100F3000909141020E9489159B01AC01C0908101F2
+:100F400069E084E00E942F04382E60914E02709177
+:100F50004F0280915002909151020E9489157B01AD
+:100F60008C01609142027091430280914402909101
+:100F700045020E9489159B01AC01C09082016DE081
+:100F800088E00E942F04D82E609152027091530283
+:100F900080915402909155020E9489157B018C0129
+:100FA00060914602709147028091480290914902F7
+:100FB0000E9489159B01AC01C090830160E181E131
+:100FC0000E942F04182F332009F44FC0C301B2012F
+:100FD0000E94BC1520915602309157024091580250
+:100FE000509159020E94B9140E9489152B013C01AD
+:100FF0001616170618061906C4F582E00E944C045E
+:1010000080916A0290916B02A0916C02B0916D0286
+:10101000481A590A6A0A7B0A80918101882379F06B
+:1010200020E030E040E85FE360913E0270913F02D3
+:1010300080914002909141020E94B9140EC020E0BC
+:1010400030E040E85FE360913E0270913F028091A2
+:101050004002909141020E94B81460933E02709346
+:101060003F028093400290934102DD2009F45CC06E
+:1010700069817A818B819C810E94BC1520915A02E2
+:1010800030915B0240915C0250915D020E94B91464
+:101090000E94891569837A838B839C8316161706B1
+:1010A000180619060CF040C08AE00E944C0480919A
+:1010B0006A0290916B02A0916C02B0916D0229813D
+:1010C0003A814B815C81281B390B4A0B5B0B2983CE
+:1010D0003A834B835C8380918201882379F020E0FE
+:1010E00030E040E85FE360914202709143028091FA
+:1010F0004402909145020E94B9140EC020E030E0F5
+:1011000040E85FE3609142027091430280914402A3
+:10111000909145020E94B81460934202709343027A
+:101120008093440290934502112309F44FC0C501F6
+:10113000B4010E94BC1520915E0230915F02409183
+:101140006002509161020E94B9140E9489154B01FE
+:101150005C011616170618061906C4F583E10E94ED
+:101160004C0480916A0290916B02A0916C02B09144
+:101170006D02881A990AAA0ABB0A80918301882302
+:1011800079F020E030E040E85FE360914602709142
+:10119000470280914802909149020E94B9140EC002
+:1011A00020E030E040E85FE3609146027091470242
+:1011B00080914802909149020E94B81460934602BF
+:1011C0007093470280934802909349020E94CC0694
+:1011D00060917D0270917E02161617063CF48827F6
+:1011E00077FD8095982F0E943D0E04C08D819E81D1
+:1011F0000E94C500332009F089CEDD2009F086CE9B
+:10120000112309F083CE8091260290912702A091AC
+:101210002802B091290280931A0290931B02A09396
+:101220001C02B0931D0280912A0290912B02A09182
+:101230002C02B0912D0280931E0290931F02A09366
+:101240002002B093210280912E0290912F02A09152
+:101250003002B09131028093220290932302A09336
+:101260002402B09325020E94C20128960FB6F8947A
+:10127000DEBF0FBECDBFDF91CF911F910F91FF90C9
+:10128000EF90DF90CF90BF90AF909F908F907F9026
+:101290006F905F904F903F90089508C00E94CC06D9
+:1012A00068EE73E080E090E00E943D0E0E94C90667
+:1012B000209108023091090225503040821793078F
+:1012C0006CF308951F93182F882311F00E944D0985
+:1012D000612F77278BE00E94860F1F910895DF9280
+:1012E000EF92FF920F931F93D82E7B010E944D091E
+:1012F000D09219026D2D80E10E94200F61E08FE0F5
+:101300000E94200F0027F7FC0095102FC801B7019D
+:101310000E943D0E60E08FE00E94200F60E080E1BF
+:101320000E94200F1F910F91FF90EF90DF90089582
+:101330002F923F924F925F926F927F928F929F92E5
+:10134000AF92BF92CF92DF92EF92FF920F931F93D3
+:10135000CF93DF93CDB7DEB7C354D0400FB6F89428
+:10136000DEBF0FBECDBFFC01AB0180818F3209F41F
+:1013700068C3BF01CE0101960E94440529813A81CC
+:10138000C90183709070892B71F42115310559F0D2
+:10139000809184019091850197FD05C09C838B838A
+:1013A00021603A832983E980FA80E0FEA5C20B819F
+:1013B0001C811093850100938401A0902202B090BB
+:1013C0002302C0902402D090250280911E029091A9
+:1013D0001F02A0912002B09121028FA798ABA9AB68
+:1013E000BAAB80911A0290911B02A0911C02B0919D
+:1013F0001D028BAB9CABADABBEAB90917001249644
+:101400009FAF2497C701887090702496AFAD249742
+:10141000AA2329F1892B29F48BA99CA9ADA9BEA9DE
+:1014200004C08B859C85AD85BE858FAB98AFA9AF79
+:10143000BAAFE4FC05C08FA598A9A9A9BAA904C0B0
+:101440008F859889A989BA898BAF9CAFADAFBEAFA4
+:10145000E5FE44C02B883C884D885E8841C0892BBE
+:1014600049F48BA99CA9ADA9BEA98FAB98AFA9AF30
+:10147000BAAF0EC02B853C854D855E856BA97CA9D6
+:101480008DA99EA90E94B9146FAB78AF89AF9AAFAE
+:10149000E4FC09C08FA598A9A9A9BAA98BAF9CAFF4
+:1014A000ADAFBEAF0EC02F85388949895A896FA567
+:1014B00078A989A99AA90E94B9146BAF7CAF8DAFA6
+:1014C0009EAFE5FE0BC02B893C894D895E89C60124
+:1014D000B5010E94B9141B012C0102C0150126019F
+:1014E000F1FE0CC08F8D98A1A9A1BAA180936202D0
+:1014F00090936302A0936402B09365020C311105CE
+:1015000009F4C6C00D311105ACF40430110509F41D
+:1015100058C0053011052CF40230110508F0DAC16D
+:1015200022C00431110509F45FC00531110509F02D
+:10153000D1C17FC0043511054CF4013511050CF003
+:10154000CDC00E31110509F0C5C1B7C00B3511056D
+:1015500009F4B0C10C35110509F4AFC10A35110504
+:1015600009F0B8C1A3C1820171012BAD3CAD4DADF5
+:101570005EAD6FA978AD89AD9AAD0E94F2038B8103
+:101580009C81019759F4609162027091630280918D
+:101590006402909165020E94CF0002C00E94A401E3
+:1015A0006093660270936702809368029093690269
+:1015B0006091660270916702809168029091690261
+:1015C00079C020E030E040E05FE36F817885898575
+:1015D0009A850E94B9140E948915882777FD809505
+:1015E000982F0E943D0E88C188EF91E2ABE4B3E4EE
+:1015F0008093710190937201A0937301B093740171
+:101600008093750190937601A0937701B093780150
+:1016100080E090E0AEEFB5E48093790190937A0199
+:10162000A0937B01B0937C0180E792E4A1EABCE344
+:1016300024C08BE49AEEAFEFB0E4809371019093F5
+:101640007201A0937301B09374018093750190931C
+:101650007601A0937701B093780180E090E0A0EA52
+:10166000B3E48093790190937A01A0937B01B093C6
+:101670007C0180E090E0A0E0BFE380937D01909347
+:101680007E01A0937F01B09380010E94C20134C10A
+:101690000F2EF0E0EF2EF0E0FF2EF0E00F2FF0E045
+:1016A0001F2FF02DA8019701C801B7010E94F20376
+:1016B0000E94A4010E94EF061FC1820171012BAD9F
+:1016C0003CAD4DAD5EAD6FA978AD89AD9AAD0E94D0
+:1016D000F2030E94A4010E94EF06DACF6FA078A463
+:1016E00089A49AA424969FAD2497992341F4A60136
+:1016F0009501C401B3010E94B9143B014C01A4013E
+:101700009301C601B5010E941D15882384F484014C
+:1017100073012FA538A949A95AA96BA97CA98DA93C
+:101720009EA90E94F2030E94A4010E94EF06E0908D
+:101730002202F090230200912402109125022BAD89
+:101740003CAD4DAD5EAD6FA978AD89AD9AAD0E944F
+:10175000F2030E94A4010E94EF068B819C818335D5
+:10176000910559F48BA59CA5ADA5BEA523968CAF7C
+:101770009DAFAEAFBFAF23970CC0A2019101C401D2
+:10178000B3010E94B81423966CAF7DAF8EAF9FAFAC
+:10179000239764015301860175012BAD3CAD4DAD1E
+:1017A0005EAD6FA978AD89AD9AAD0E94F2030E943B
+:1017B000A4010E94EF0623962CAD3DAD4EAD5FAD6A
+:1017C0002397C601B5010E94B8145B016C01A20108
+:1017D00091010E941D15882314F4620151018601B4
+:1017E00075012BAD3CAD4DAD5EAD6FA978AD89AD4A
+:1017F0009AAD0E94F203E0906202F09063020091C1
+:1018000064021091650220E030E040E050E0C80141
+:10181000B7010E946C1618162CF4C801B7010E947B
+:10182000CF0002C00E94A401609366027093670219
+:1018300080936802909369026091660270916702DA
+:1018400080916802909169020E94EF068B819C81D1
+:101850008235910591F420E030E04AE754E46F814D
+:10186000788589859A850E9470160E948915882737
+:1018700077FD8095982F0E943D0E840173012BAD5A
+:101880003CAD4DAD5EAD6FA978AD89AD9AAD0E940E
+:10189000F2030E94A4010E94EF06A2019101C60179
+:1018A000B5010E946C1618163CF575CF81E0809347
+:1018B000700122C0109270011FC0820171012BAD16
+:1018C0003CAD4DAD5EAD6FA978AD89AD9AAD0E94CE
+:1018D000CF0312C060E071E08FE792E00E948010B9
+:1018E0004B815C81662757FD6095762F2AE030E0BA
+:1018F0008FE792E00E94621029813A8121FFA1C006
+:101900008D819E818936910509F44AC08A369105F8
+:10191000B4F48636910569F18736910544F4009751
+:1019200009F48FC08536910509F079C020C087364B
+:10193000910539F18836910509F071C024C08C36C3
+:10194000910509F441C08D36910544F48A3691051C
+:10195000A9F18B36910509F062C032C08E3791052E
+:1019600009F43FC08F37910509F059C048C081E0A4
+:1019700001C080E00E94150480916B010E94620901
+:1019800060C080E0FBCF32FF5CC06BA17CA18DA169
+:101990009EA10E948915DC01CB010E94A20051C0CA
+:1019A00067E071E08FE792E00E9480100E94C90614
+:1019B000BC018FE792E00E94751043C08FEF01C019
+:1019C00080E00E944E063DC032FF3BC06BA17CA16F
+:1019D0008DA19EA10E94891570936C0160936B018B
+:1019E00030C020E030E040E05FE36F81788589859A
+:1019F0009A850E94B9140E94891581E00DC020E0EB
+:101A000030E040E05FE36F81788589859A850E94A8
+:101A1000B9140E94891580E00E946F0912C06AE023
+:101A200071E08FE792E00E9480104D815E81662711
+:101A300057FD6095762F2AE030E08FE792E00E9414
+:101A40006210CD5BDF4F0FB6F894DEBF0FBECDBF87
+:101A5000DF91CF911F910F91FF90EF90DF90CF908A
+:101A6000BF90AF909F908F907F906F905F904F90BE
+:101A70003F902F9008950F931F938FEF0E948C0635
+:101A8000AC01EEE1F1E0A1E0B0E0608171814617C8
+:101A900057071CF5AA0FBB1FAA0FBB1FFD01EA5E6B
+:101AA000FE4F0281138120813181421B530BA65EC0
+:101AB000BE4FFD0182819381801B910B621B730BD2
+:101AC0009C01429FC001439F900D529F900D112495
+:101AD0000E943817600F711F10C08A2F8F5F1196F8
+:101AE0003496A431B10589F6843119F060E070E0D4
+:101AF0000BC060916801709169016F3F710521F021
+:101B00001CF06FEF70E004C077FF02C060E070E08F
+:101B1000CB011F910F9108950E94CC068FE792E0B0
+:101B20000E949510882311F18FE792E00E94921095
+:101B300080936A018D3019F48AE080936A01909154
+:101B40006A0190329CF09B3319F481E08093070284
+:101B500080910702882351F480910602E82FFF2725
+:101B6000EA57FE4F90838F5F8093060280910602B2
+:101B700087FF04C0109206021092070260910602CD
+:101B80006623B9F080916A018A3099F47727FB01C6
+:101B9000EA57FE4F108286E891E00E949809109261
+:101BA00006021092070261E171E08FE792E00E9465
+:101BB000841008950F931F930FE712E040E05BE459
+:101BC00060E070E0C8010E94991064E171E0C80112
+:101BD0000E94841010920602109207020E945B0479
+:101BE0000E9454061F910F910895CFEFD4E0DEBFFD
+:101BF000CDBF0E946C0E0E94DA0D0E948C0DFDCFAD
+:101C00001F920F920FB60F9211248F939F93AF9351
+:101C1000BF938091840290918502A0918602B09139
+:101C200087020196A11DB11D8093840290938502C5
+:101C3000A0938602B0938702BF91AF919F918F913D
+:101C40000F900FBE0F901F901895609184027091B5
+:101C50008502809186029091870227E0660F771FA8
+:101C6000881F991F2A95D1F72DE730E040E050E01A
+:101C70000E944B17CA01B9010895AF92BF92CF924B
+:101C8000DF92EF92FF920F931F935B016C010E9412
+:101C9000250E7B018C010E94250E6E197F09800B99
+:101CA000910B6A157B058C059D05A8F31F910F917B
+:101CB000FF90EF90DF90CF90BF90AF900895019785
+:101CC00051F0880F991F880F991F02972FB7F8942A
+:101CD0000197F1F72FBF0895789410928402109223
+:101CE0008502109286021092870284B5826084BDBC
+:101CF00084B5816084BD85B5826085BD85B5816010
+:101D000085BDEEE6F0E0808181608083E1E8F0E06F
+:101D1000808182608083808181608083E0E8F0E060
+:101D2000808181608083E1EBF0E08081846080834A
+:101D3000E0EBF0E0808181608083ECE7F0E080817F
+:101D40008F778083808180648083EAE7F0E0808100
+:101D500084608083808182608083808181608083D1
+:101D60008081806880831092C1000895282F3327D6
+:101D7000C90185579F4FFC01949129583F4FF901A4
+:101D80008491882381F0E82FFF27E859FF4FE491E1
+:101D9000FF27662329F48081909589238083089505
+:101DA0008081892B80830895482F5527CA01815649
+:101DB0009F4FFC012491CA0185579F4FFC019491CC
+:101DC00049585F4FFA013491332319F480E090E0D1
+:101DD0000895222331F1233021F4809180008F7700
+:101DE00005C0243031F4809180008F7D8093800085
+:101DF00018C0213019F484B58F7704C0223021F443
+:101E000084B58F7D84BD0DC0263021F48091B00053
+:101E10008F7705C0273029F48091B0008F7D8093A3
+:101E2000B000E32FFF27EE58FF4FE491FF2780819A
+:101E300020E030E0892311F021E030E0C90108956D
+:101E4000482F5527CA0181569F4FFC012491CA0192
+:101E500085579F4FFC01949149585F4FFA01349187
+:101E60003323C1F1222331F1233021F4809180000A
+:101E70008F7705C0243031F4809180008F7D80936E
+:101E8000800018C0213019F484B58F7704C0223047
+:101E900021F484B58F7D84BD0DC0263021F480915E
+:101EA000B0008F7705C0273029F48091B0008F7D76
+:101EB0008093B000E32FFF27E359FF4FE491FF2702
+:101EC000662329F4808190958923808308958081F9
+:101ED000892B8083089590917C008F70907F892B4F
+:101EE00080937C0080917A00806480937A00809156
+:101EF0007A0086FDFCCF20917800809179009927A7
+:101F0000982F88273327822B932B08951F93CF93E5
+:101F1000DF93182FEB0161E00E94B60EE12FFF273F
+:101F2000E156FF4F8491833051F4809180008068A6
+:101F300080938000D0938900C093880037C084309C
+:101F400051F480918000806280938000D0938B0058
+:101F5000C0938A002BC0813029F484B5806884BD89
+:101F6000C7BD24C0823029F484B5806284BDC8BD59
+:101F70001DC0863041F48091B00080688093B0002D
+:101F8000C093B30013C0873041F48091B0008062E9
+:101F90008093B000C093B40009C0C038D10514F4D8
+:101FA00060E001C061E0812F0E94200FDF91CF919E
+:101FB0001F91089508950895CB01BA01332744274E
+:101FC00055270E94601108952AE00E94DC0F0895B1
+:101FD000AB01662777270E94E40F0895862F0E94A1
+:101FE00058110895862F0E94581108950F931F933A
+:101FF0008C016DE00E94F20F6AE0C8010E94F20FAE
+:102000001F910F9108950F931F938C010E94E40F6D
+:10201000C8010E94F60F1F910F9108950F931F930F
+:102020008C010E94EE0FC8010E94F60F1F910F91C4
+:1020300008950F931F938C010E94F20FC8010E9414
+:10204000F60F1F910F910895EF92FF920F931F9338
+:10205000CF93DF93EC017A018B0177FF0BC06DE228
+:102060000E94F20F10950095F094E094E11CF11C91
+:10207000011D111D2AE0B801A701CE010E94DC0F4D
+:10208000DF91CF911F910F91FF90EF9008950F93E3
+:102090001F938C010E942410C8010E94F60F1F910B
+:1020A0000F9108952115310521F4642F0E94F20F3C
+:1020B00008952A30310519F40E94241008950E94D1
+:1020C000DC0F08950F931F938C010E945210C801DA
+:1020D0000E94F60F1F910F910895AB01662757FDDF
+:1020E0006095762F0E94241008950F931F938C0102
+:1020F0000E946D10C8010E94F60F1F910F91089564
+:10210000CB010E94301208950F931F938C010E94FF
+:102110008010C8010E94F60F1F910F9108950E9430
+:10212000111108950E94F21008950E94E11099275C
+:102130000895CB01BA010E94A01008950895089552
+:10214000EF92FF920F931F937B018C0122E030E00E
+:1021500040E050E00E946D17205C3D4B404F5F4FC8
+:10216000CA01B901A80197010E946D1721503040A2
+:1021700040405040BB2757FDBA95A52F942F832F81
+:102180002F5F3F4F4F4F5F4F8093C50021502093EB
+:10219000C400E1ECF0E08081806180838081886010
+:1021A00080838081806880831F910F91FF90EF90E2
+:1021B0000895982F8091C00085FFFCCF9093C600B2
+:1021C0000895809180029091810280589F4F2091C4
+:1021D000820230918302821B930B60E870E00E94C0
+:1021E00038170895409182025091830280918002B5
+:1021F000909181028417950719F48FEF9FEF08954E
+:10220000FA01E857FD4F2081CA01019660E870E0AD
+:102210000E9438179093830280938202822F99271D
+:10222000089580918202909183029093810280931D
+:10223000800208951F920F920FB60F9211242F93D0
+:102240003F934F935F936F937F938F939F93AF933E
+:10225000BF93EF93FF934091C600E0918002F0910D
+:102260008102CF01019660E870E00E9438179C015E
+:1022700080918202909183022817390739F0E8573C
+:10228000FD4F40833093810220938002FF91EF91B4
+:10229000BF91AF919F918F917F916F915F914F917E
+:1022A0003F912F910F900FBE0F901F90189508959A
+:1022B000982F8091C00085FFFCCF9093C6000895B1
+:1022C0002F923F924F925F926F927F928F929F9246
+:1022D000AF92BF92CF92DF92EF92FF920F931F9334
+:1022E000CF93DF93CDB7DEB7A0970FB6F894DEBFDC
+:1022F0000FBECDBF6B017C0129013A01611571054B
+:102300008105910541F48091C00085FFFCCF80E3F9
+:102310008093C6004BC08824992454011E01089460
+:10232000211C311C8101080D191DC701B601A30133
+:1023300092010E944B17F80160830894811C911C44
+:10234000A11CB11CC701B601A30192010E944B1749
+:1023500069017A01211531054105510519F70894E4
+:1023600081089108A108B108F101E80DF91D089450
+:10237000811C911CA11CB11C14C0089481089108F7
+:10238000A108B10880818A3018F4982F905D02C0AE
+:10239000982F995C8091C00085FFFCCF9093C60078
+:1023A000319781149104A104B10439F7A0960FB6B6
+:1023B000F894DEBF0FBECDBFDF91CF911F910F917B
+:1023C000FF90EF90DF90CF90BF90AF909F908F9055
+:1023D0007F906F905F904F903F902F90089520E1F5
+:1023E00030E040E050E00E946011089528E030E0C5
+:1023F00040E050E00E946011089522E030E040E0AB
+:1024000050E00E94601108958091C00085FFFCCFCC
+:102410008AE08093C6000895EF92FF920F931F9376
+:102420007B018C0197FF0FC08091C00085FFFCCF1E
+:102430008DE28093C60010950095F094E094E11C25
+:10244000F11C011D111D2AE030E040E050E0C80100
+:10245000B7010E9460111F910F91FF90EF900895B6
+:10246000FC0107C08091C00085FFFCCF319690939E
+:10247000C60090819923B1F70895A0E0B0E0E3E4AD
+:10248000F2E10C94D017EC015B016115710519F0B4
+:10249000FB0191838083D9908D2D99270E94A217EB
+:1024A000892BC9F7FDE2DF1621F4D990CC24C3941F
+:1024B00005C08BE2D81609F4D990CC248E010150C6
+:1024C000104043E050E063EB70E0C8010E94A014AC
+:1024D000892B09F58E010E5F1F4F45E050E066EB3A
+:1024E00070E0C8010E94A014892B19F48E01095FC5
+:1024F0001F4FA114B10419F0F50111830083C0FE30
+:1025000005C060E070E080E89FEFFFC060E070E031
+:1025100080E89FE7FAC043E050E06BEB70E0C80151
+:102520000E94A014892B61F4A114B10421F0229619
+:10253000F501D183C08360E070E080EC9FE7E5C0E7
+:1025400088249924EE24FF2487014D2D40534A30DE
+:10255000A8F5F2E0CF2A8C2D99279C0128703070C5
+:1025600082FF06C0232B81F50894811C911C2CC08E
+:10257000232B19F0089481089108D801C701E2E0E3
+:10258000880F991FAA1FBB1FEA95D1F7E80EF91E05
+:102590000A1F1B1FEE0CFF1C001F111FE40EF11C75
+:1025A000011D111D88E9E81689E9F80689E908077F
+:1025B00089E1180748F0E4E0CE2A06C04E3F31F426
+:1025C000C3FC3AC0F8E0CF2AD990BFCF453311F011
+:1025D000453191F589918D3219F480E1C82A05C001
+:1025E0008B3219F021E030E003C0899122E030E025
+:1025F000482F40534A3018F420E030E007C0C21B97
+:10260000D30B1AC0ECE020383E075CF4C901880FF8
+:10261000991F880F991F280F391F220F331F240F6E
+:10262000311D499140534A3068F3C4FE03C03095D0
+:1026300021953F4F820E931EDD2492E0692E712C6E
+:102640006C207D20C1FE07C0A114B10421F02197A8
+:10265000F501D183C083C801B7010E94BA157B017F
+:102660008C01C0FE06C0672821F017FB109517F9F2
+:1026700010955701680120E030E040E050E0C801CB
+:10268000B7010E941D15882309F43DC097FE09C0BB
+:10269000C2EDD0E0909481949108939400E210E010
+:1026A00010C0CAEED0E0FACFFE01259135914591D8
+:1026B0005491C601B5010E9470165B016C01801A2D
+:1026C000910A8016910684F7159507950115110555
+:1026D00011F02497F6CF860175018C2D880F8D2D72
+:1026E000881F8F3F51F020E030E040E050E0C6010D
+:1026F000B5010E941D15882331F482E290E0909389
+:10270000090380930803C801B701EEE0CDB7DEB737
+:102710000C94EC17A0E0B0E0E0E9F3E10C94CD17E5
+:102720008C012B01EA016115710519F0FB01918300
+:102730008083209749F0CE010297839728F060E0CC
+:1027400070E080E090E0F7C0F801E1908F018E2DFD
+:1027500099270E94A217892BB9F7FDE2EF1631F4F1
+:10276000F801E1908F013324339407C0FBE2EF16A8
+:1027700019F4F801E1908F013324209719F0C0314A
+:10278000D105E1F4F0E3EF1679F4F80180818837A0
+:1027900011F0883549F4F801E1800E5F1F4FF2E037
+:1027A0003F2AC0E1D0E00AC0209741F480E3E81658
+:1027B00019F4C8E0D0E002C0CAE0D0E0C830D105CA
+:1027C00071F0C930D10524F4C230D10519F50DC01E
+:1027D000CA30D10581F0C031D105E1F415C0A12C7A
+:1027E000B12CC12CB0E1DB2E22C0A12CB12CC12C0C
+:1027F000A0E4DA2E1CC0FCECAF2EFCECBF2EFCECEF
+:10280000CF2EFCE0DF2E13C0A12CB12CC12CE8E0B0
+:10281000DE2E0DC09E01442737FD4095542F60E009
+:1028200070E080E090E80E944B1759016A0120E0B7
+:1028300030E040E050E060E03E01882477FC809486
+:10284000982C70EDF72EFE0CE9E0EF1570F48E2D4C
+:1028500081548A3118F499ECF92E06C08E2D8156D8
+:102860008A3150F589EAF82EFE0C8F2D99278C17A6
+:102870009D0714F567FD1CC0A216B306C406D50655
+:10288000B0F0CA01B901A40193010E94AD179B01E8
+:10289000AC012F0D311D411D511D2130F0E03F07CE
+:1028A000F0E04F07F0E85F0710F461E001C06FEF60
+:1028B000F801E1908F01C5CF4114510481F06623E6
+:1028C00031F001501040F2011183008308C031FE45
+:1028D0001AC002501040F2011183008314C067FF38
+:1028E00012C030FE05C020E030E040E050E804C0F7
+:1028F0002FEF3FEF4FEF5FE782E290E09093090305
+:102900008093080316C030FE08C05095409530955E
+:1029100021953F4F4F4F5F4F0CC057FF0AC082E2D7
+:1029200090E090930903809308032FEF3FEF4FEF60
+:102930005FE7CA01B901E1E1CDB7DEB70C94E91751
+:10294000FB01DC014150504088F08D9181341CF036
+:102950008B350CF4805E659161341CF06B350CF4A2
+:10296000605E861B611171F3990B0895881BFCCF83
+:102970005058BB27AA270ED075C166D130F06BD155
+:1029800020F031F49F3F11F41EF45BC10EF4E0958A
+:10299000E7FB51C1E92F77D180F3BA1762077307BC
+:1029A0008407950718F071F49EF58FC10EF4E09539
+:1029B0000B2EBA2FA02D0B01B90190010C01CA01F9
+:1029C000A0011124FF27591B99F0593F50F4503EA4
+:1029D00068F11A16F040A22F232F342F4427585F96
+:1029E000F3CF469537952795A795F0405395C9F7AE
+:1029F0007EF41F16BA0B620B730B840BBAF0915066
+:102A0000A1F0FF0FBB1F661F771F881FC2F70EC004
+:102A1000BA0F621F731F841F48F4879577956795D7
+:102A2000B795F7959E3F08F0B3CF9395880F08F0C0
+:102A30009927EE0F979587950895D9D008F481E0EE
+:102A400008950CD00FC107D140F0FED030F021F432
+:102A50005F3F19F0F0C0511139C1F3C014D198F3A0
+:102A60009923C9F35523B1F3951B550BBB27AA270F
+:102A700062177307840738F09F5F5F4F220F331F81
+:102A8000441FAA1FA9F333D00E2E3AF0E0E830D04D
+:102A900091505040E695001CCAF729D0FE2F27D050
+:102AA000660F771F881FBB1F261737074807AB071E
+:102AB000B0E809F0BB0B802DBF01FF2793585F4F93
+:102AC0002AF09E3F510568F0B6C000C15F3FECF3AD
+:102AD000983EDCF3869577956795B795F7959F5F58
+:102AE000C9F7880F911D9695879597F90895E1E0AC
+:102AF000660F771F881FBB1F621773078407BA070B
+:102B000020F0621B730B840BBA0BEE1F88F7E09565
+:102B1000089504D06894B111D9C00895BCD088F04C
+:102B20009F5790F0B92F9927B751A0F0D1F0660FB9
+:102B3000771F881F991F1AF0BA95C9F712C0B130D4
+:102B400081F0C3D0B1E00895C0C0672F782F8827E7
+:102B5000B85F39F0B93FCCF3869577956795B39513
+:102B6000D9F73EF490958095709561957F4F8F4F82
+:102B70009F4F0895E89409C097FB3EF49095809587
+:102B8000709561957F4F8F4F9F4F9923A9F0F92F33
+:102B900096E9BB279395F695879577956795B795B1
+:102BA000F111F8CFFAF4BB0F11F460FF1BC06F5F97
+:102BB0007F4F8F4F9F4F16C0882311F096E911C0A9
+:102BC000772321F09EE8872F762F05C0662371F0CA
+:102BD00096E8862F70E060E02AF09A95660F771FDE
+:102BE000881FDAF7880F9695879597F90895990FBA
+:102BF0000008550FAA0BE0E8FEEF16161706E807C7
+:102C0000F907C0F012161306E407F50798F0621BE7
+:102C1000730B840B950B39F40A2661F0232B242BBC
+:102C2000252B21F408950A2609F4A140A6958FEFDB
+:102C3000811D811D089597F99F6780E870E060E02D
+:102C400008959FEF80EC089500240A941616170645
+:102C500018060906089500240A941216130614068D
+:102C600005060895092E0394000C11F4882352F0F0
+:102C7000BB0F40F4BF2B11F460FF04C06F5F7F4FA8
+:102C80008F4F9F4F089557FD9058440F551F59F08F
+:102C90005F3F71F04795880F97FB991F61F09F3F49
+:102CA00079F087950895121613061406551FF2CF72
+:102CB0004695F1DF08C0161617061806991FF1CFC2
+:102CC00086957105610508940895E894BB276627E9
+:102CD0007727CB0197F908958ADF08F48FEF0895DD
+:102CE0000BD0C0CFB1DF28F0B6DF18F0952309F084
+:102CF000A2CFA7CF1124EACFC6DFA0F3959FD1F3CF
+:102D0000950F50E0551F629FF001729FBB27F00D99
+:102D1000B11D639FAA27F00DB11DAA1F649F6627EE
+:102D2000B00DA11D661F829F2227B00DA11D621F3D
+:102D3000739FB00DA11D621F839FA00D611D221FF7
+:102D4000749F3327A00D611D231F849F600D211DDB
+:102D5000822F762F6A2F11249F5750408AF0E1F07E
+:102D600088234AF0EE0FFF1FBB1F661F771F881FC7
+:102D700091505040A9F79E3F510570F05CCFA6CF0F
+:102D80005F3FECF3983EDCF3869577956795B795B2
+:102D9000F795E7959F5FC1F7FE2B880F911D9695DC
+:102DA000879597F9089511F40EF44BCF4AC073DF5D
+:102DB000D0F39923D9F3CEF39F57550B87FF51D00A
+:102DC00056959795B0E020F4660F771F881FBB1FBC
+:102DD0001F930F9300249001A0018001F001A0E84F
+:102DE0000E0F1F1F0A1E511D601B710B8009B50BB2
+:102DF00048F4600F711F801DB51F0E1B1F0B0A0AC0
+:102E0000510907C02E0F3F1F4A1F0E0F1F1F0A1E1A
+:102E1000511D660F771F881FBB1FA695F795E79575
+:102E2000F8F60617170708065B07211D311D411D1F
+:102E30000F911F91B901842F9158880F969587950E
+:102E400008959F3F49F0915028F4869577956795AE
+:102E5000B7959F5F80389F4F880F9695879597F914
+:102E6000089591505040660F771F881FD2F708953C
+:102E700097FB092E07260AD077FD04D049D006D04B
+:102E800000201AF4709561957F4F0895F6F790959C
+:102E900081959F4F0895A1E21A2EAA1BBB1BFD012D
+:102EA0000DC0AA1FBB1FEE1FFF1FA217B307E40729
+:102EB000F50720F0A21BB30BE40BF50B661F771F81
+:102EC000881F991F1A9469F7609570958095909561
+:102ED0009B01AC01BD01CF01089597FB092E05268A
+:102EE0000ED057FD04D0D7DF0AD0001C38F450951F
+:102EF0004095309521953F4F4F4F5F4F0895F6F71E
+:102F000090958095709561957F4F8F4F9F4F089555
+:102F1000AA1BBB1B51E107C0AA1FBB1FA617B707FF
+:102F200010F0A61BB70B881F991F5A95A9F780951B
+:102F30009095BC01CD010895EE0FFF1F0590F4910F
+:102F4000E02D0994911106C0803219F08950855006
+:102F5000D0F70895992788270895629FD001739F1D
+:102F6000F001829FE00DF11D649FE00DF11D929F25
+:102F7000F00D839FF00D749FF00D659FF00D992764
+:102F8000729FB00DE11DF91F639FB00DE11DF91F88
+:102F9000BD01CF01112408952F923F924F925F926D
+:102FA0006F927F928F929F92AF92BF92CF92DF9259
+:102FB000EF92FF920F931F93CF93DF93CDB7DEB7BE
+:102FC000CA1BDB0B0FB6F894DEBF0FBECDBF099452
+:102FD0002A88398848885F846E847D848C849B84A9
+:102FE000AA84B984C884DF80EE80FD800C811B81B7
+:102FF000AA81B981CE0FD11D0FB6F894DEBF0FBEE6
+:08300000CDBFED010895FFCFE3
+:103008006875683F204700543A004875683F204D6E
+:10301800006F6B007374617274000100490336001D
+:10302800FF006B00D100A000B800D500A6000A017F
+:1030380099003F018E0074018400A9017C00DE0123
+:10304800740013026C00480265007D025D00B20244
+:103058005600E7024E001C03460051033D0086035C
+:103068003200BB032200F00303003F800040FF0151
+:10307800014BEAFF404BEAFF400000A0430000007C
+:063088003F010101FFFF02
+:00000001FF
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.pde
new file mode 100644
index 00000000..63438124
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.pde
@@ -0,0 +1,158 @@
+// Yep, this is actually -*- c++ -*-
+
+// Sanguino G-code Interpreter
+// Arduino v1.0 by Mike Ellery - initial software (mellery@gmail.com)
+// v1.1 by Zach Hoeken - cleaned up and did lots of tweaks (hoeken@gmail.com)
+// v1.2 by Chris Meighan - cleanup / G2&G3 support (cmeighan@gmail.com)
+// v1.3 by Zach Hoeken - added thermocouple support and multi-sample temp readings. (hoeken@gmail.com)
+// Sanguino v1.4 by Adrian Bowyer - switch to the Sanguino; extensive mods... (a.bowyer@bath.ac.uk)
+
+#include <ctype.h>
+#include <HardwareSerial.h>
+
+// Uncomment the next line to run stand-alone tests on the machine (also see the
+// ends of this, the process_string, the extruder, and the stepper_control tabs).
+//#define TEST_MACHINE
+
+
+//our command string
+#define COMMAND_SIZE 128
+char word[COMMAND_SIZE];
+char c = '?';
+byte serial_count = 0;
+boolean comment = false;
+
+void setup()
+{
+ //Do startup stuff here
+ Serial.begin(19200);
+ Serial.println("start");
+
+ //other initialization.
+ init_process_string();
+ init_steppers();
+ init_extruder();
+}
+
+void loop()
+{
+#ifndef TEST_MACHINE
+
+
+ //keep it hot!
+ extruder_manage_temperature();
+
+ //read in characters if we got them.
+ if (Serial.available())
+ {
+ c = Serial.read();
+ if(c == '\r')
+ c = '\n';
+ // Throw away control chars except \n
+ if(c >= ' ' || c == '\n')
+ {
+
+ //newlines are ends of commands.
+ if (c != '\n')
+ {
+ // Start of comment - ignore any bytes received from now on
+ if (c == ';')
+ comment = true;
+
+ // If we're not in comment mode, add it to our array.
+ if (!comment)
+ word[serial_count++] = c;
+ }
+
+ }
+ }
+
+ // Data runaway?
+ if(serial_count >= COMMAND_SIZE)
+ init_process_string();
+
+ //if we've got a real command, do it
+ if (serial_count && c == '\n')
+ {
+ // Terminate string
+ word[serial_count] = 0;
+
+ //process our command!
+ process_string(word, serial_count);
+
+ //clear command.
+ init_process_string();
+
+ // Say we're ready for the next one
+
+ Serial.println("ok");
+ }
+
+#else
+
+// Run the parts of the machine as a test
+
+// Do the comms test first. It should echo
+// what you type in a terminal window connected
+// to the Sanguino.
+
+// If that works, comment out the next line to test the rest:
+#define COMMS_TEST
+
+#ifdef COMMS_TEST
+
+ comms_test();
+
+#else
+
+ if (Serial.available() > 0)
+ {
+ c = Serial.read();
+ Serial.println(c);
+ }
+
+ switch(c)
+ {
+ case 0:
+ break;
+
+ case 'x':
+ X_motor_test();
+ break;
+ case 'y':
+ Y_motor_test();
+ break;
+ case 'z':
+ Z_motor_test();
+ break;
+ case 'h':
+ extruder_heater_test();
+ break;
+ case 'e':
+ extruder_drive_test();
+ break;
+ case 'v':
+ extruder_valve_test();
+ break;
+ case 'f':
+ extruder_fan_test();
+ break;
+
+ default:
+ Serial.println("Commands:\n");
+ Serial.println(" x - X motor test");
+ Serial.println(" y - Y motor test");
+ Serial.println(" z - Z motor test");
+ Serial.println(" h - extruder heater test");
+ Serial.println(" e - extruder drive test");
+ Serial.println(" v - extruder valve test");
+ Serial.println(" f - extruder fan test");
+ Serial.println(" s - stop current test at the end of its cycle then print this list\n\n");
+ Serial.print("Command: ");
+ c = 0;
+ }
+
+#endif
+
+#endif
+}
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.rom b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.rom
new file mode 100755
index 00000000..f8867a2c
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/GCode_Interpreter.rom
@@ -0,0 +1,780 @@
+S02B00002F686F6D652F656E7361622F776F726B73706163652F6669726D776172652F53616E6775696E6F2F98
+S11300000C9478000C94A0000C94A0000C94A00014
+S11300100C94A0000C94A0000C94A0000C94A000DC
+S11300200C94A0000C94A0000C94A0000C94A000CC
+S11300300C94A0000C94A0000C94A0000C94A000BC
+S11300400C94000E0C94A0000C941A110C94A000B3
+S11300500C94A0000C94A0000C94A0000C94A0009C
+S11300600C94A0000C94A000000024272A00002572
+S1130070282B000023262904040404040404040295
+S11300800202020202030303030303010204081031
+S113009020408001020408102001020408102000FE
+S11300A00000070002010000030406000000000035
+S11300B0000000494E46494E4954594E414ECDCC5C
+S11300C0CC3D0AD7233C17B7D13877CC2B32959542
+S11300D0E6241FB14F0A000020410000C84200403E
+S11300E01C4620BCBE4CCA1B0E5AAEC59D749F1044
+S11300F011241FBECFEFD4E0DEBFCDBF11E0A0E0DE
+S1130100B1E0E8E0F0E302C005900D92A638B10733
+S1130110D9F713E0A6E8B1E001C01D92AA30B107F7
+S1130120E1F710E0C0EFD0E004C02297FE010E9486
+S11301309E17CE3ED107C9F70E94F50D0C94031803
+S11301400C9400009093090280930802AA2797FD5B
+S1130150A095BA2FBC01CD010E94BC152DEC3CEC3E
+S11301604CE85FE30E9470160E94891570930B029D
+S113017060930A02089510920602109207020895ED
+S11301800E9470160E9489150895019739F0880F0E
+S1130190991F880F991F02970197F1F708952F92DD
+S11301A03F924F925F926F927F928F929F92AF9203
+S11301B0BF92CF92DF92EF92FF920F931F93CF9350
+S11301C0DF93CDB7DEB72C970FB6F894DEBF0FBE22
+S11301D0CDBF69877A878B879C87209032023090C5
+S11301E0330240903402509035028091360290914F
+S11301F03702A0913802B09139028D839E83AF8378
+S1130200B88780913A0290913B02A0913C02B09150
+S11302103D0289839A83AB83BC83609056027090BD
+S113022057028090580290905902A0905A02B090C0
+S11302305B02C0905C02D0905D02A6019501C401EE
+S1130240B3010E946C16E0905E02F0905F02009190
+S113025060021091610218165CF4A4019301C801B4
+S1130260B7010E946C1618165CF0C401B3010DC0EE
+S1130270A6019501C801B7010E946C1618161CF45A
+S1130280C801B70102C0C601B5010E9489155B010E
+S11302906C01A2019101C201B1010E9470167B019F
+S11302A08C012D813E814F815885CA01B9010E947C
+S11302B070169B01AC01C801B7010E94B9147B01FF
+S11302C08C0129813A814B815C81CA01B9010E9468
+S11302D070169B01AC01C801B7010E94B9140E94B9
+S11302E0D71620EC31EE44E65CE40E9470162985B2
+S11302F03A854B855C850E9421157B018C01C601E2
+S1130300B5010E94BC159B01AC01C801B7010E9454
+S113031021150E9489152C960FB6F894DEBF0FBEE6
+S1130320CDBFDF91CF911F910F91FF90EF90DF90A0
+S1130330CF90BF90AF909F908F907F906F905F9081
+S11303404F903F902F90089520E030E040E050E03F
+S113035060915E0270915F028091600290916102EF
+S11303600E946C1618163CF460E070E088E492E495
+S11303700E94CF00089560E070E088EC94E40E944D
+S1130380CF0008952F923F924F925F926F927F9287
+S11303908F929F92AF92BF92CF92DF92EF92FF9291
+S11303A00F931F93CF93DF93CDB7DEB7A0970FB60C
+S11303B0F894DEBF0FBECDBF809126029091270234
+S11303C0A0912802B09129028D8F9E8FAF8FB8A380
+S11303D080911A0290911B02A0911C02B0911D02FF
+S11303E0898F9A8FAB8FBC8F9C01AD016D8D7E8DF3
+S11303F08F8D98A10E94B8147B018C0120E030E01D
+S113040040E050E00E946C16181624F017FB10957B
+S113041017F91095E0923202F092330200933402FD
+S11304201093350280912A0290912B02A0912C0204
+S1130430B0912D028D8B9E8BAF8BB88F80911E0255
+S113044090911F02A0912002B0912102898B9A8B76
+S1130450AB8BBC8B9C01AD016D897E898F89988D96
+S11304600E94B8147B018C0120E030E040E050E0B1
+S11304700E946C16181624F017FB109517F91095A6
+S1130480E0923602F0923702009338021093390258
+S113049080912E0290912F02A0913002B0913102EE
+S11304A08D879E87AF87B88B80912202909123021B
+S11304B0A0912402B091250289879A87AB87BC87D3
+S11304C09C01AD016D857E858F8598890E94B81445
+S11304D07B018C0120E030E040E050E00E946C168B
+S11304E0181624F017FB109517F91095E0923A02AC
+S11304F0F0923B0200933C0210933D02E0907101A4
+S1130500F09072010091730110917401298D3A8D5C
+S11305104B8D5C8DC801B7010E9470160E9489152D
+S11305200E94BC151B012C0160933E0270933F0294
+S1130530809340029093410260907501709076011F
+S1130540809077019090780129893A894B895C8958
+S1130550C401B3010E9470160E9489150E94BC1543
+S11305606D837E838F8398876093420270934302E6
+S11305708093440290934502A0907901B0907A014F
+S1130580C0907B01D0907C0129853A854B855C85A0
+S1130590C601B5010E9470160E9489150E94BC15FF
+S11305A069837A838B839C836093460270934702AA
+S11305B080934802909349022D8D3E8D4F8D58A112
+S11305C0C801B7010E9470160E9489150E94BC15CB
+S11305D07B018C0160934A0270934B0280934C021E
+S11305E090934D022D893E894F89588DC401B301E2
+S11305F00E9470160E9489150E94BC153B014C0193
+S113060060934E0270934F02809350029093510274
+S11306102D853E854F855889C601B5010E94701607
+S11306200E9489150E94BC155B016C016093520203
+S1130630709353028093540290935502A201910146
+S1130640C801B7010E94B8147B018C0120E030E09E
+S113065040E050E00E946C16181624F017FB109529
+S113066017F91095E0925602F0925702009358023F
+S1130670109359022D813E814F815885C401B301E5
+S11306800E94B8147B018C0120E030E040E050E08F
+S11306900E946C16181624F017FB109517F9109584
+S11306A0E0925A02F0925B0200935C0210935D02A6
+S11306B029813A814B815C81C601B5010E94B8143D
+S11306C07B018C0120E030E040E050E00E946C1699
+S11306D0181624F017FB109517F91095E0925E0296
+S11306E0F0925F02009360021093610210E0298D82
+S11306F03A8D4B8D5C8D6D8D7E8D8F8D98A10E9472
+S11307006C1688230CF011E0109381011092820181
+S113071029893A894B895C896D897E898F89988D6D
+S11307200E946C1688231CF081E080938201109251
+S1130730830129853A854B855C856D857E858F850A
+S113074098890E946C1688231CF081E080938301B1
+S1130750612F83E00E94200F6091820187E00E9454
+S1130760200F6091830182E10E94200FA0960FB6B2
+S1130770F894DEBF0FBECDBFDF91CF911F910F91D3
+S1130780FF90EF90DF90CF90BF90AF909F908F90AD
+S11307907F906F905F904F903F902F900895EF92CD
+S11307A0FF920F931F9360931A0270931B0280931E
+S11307B01C0290931D0220931E0230931F0240934B
+S11307C0200250932102E0922202F092230200932D
+S11307D02402109325020E94C2011F910F91FF90E1
+S11307E0EF900895EF92FF920F931F936093260268
+S11307F070932702809328029093290220932A025F
+S113080030932B0240932C0250932D02E0922E023F
+S1130810F0922F0200933002109331020E94C20121
+S11308201F910F91FF90EF90089580936F01682FAF
+S11308308CE00E94200F08951F93182F0E94D40E5D
+S1130840892B11F420E007C0812F0E94D40E20E0F0
+S1130850892B09F021E0822F99271F910895CF92C7
+S1130860EF92FF920F931F93E216F3060407150706
+S113087019F480E090E00AC00E941C04882321F04F
+S113088080E090E0CC2011F081E090E01F910F9186
+S1130890FF90EF90CF9008951F93182F61E00E946E
+S11308A0200F85E090E00E945F0E60E0812F0E949F
+S11308B0200F1F91089580E090E0A0E0B0E08093C5
+S11308C01A0290931B02A0931C02B0931D02809302
+S11308D01E0290931F02A0932002B09321028093E2
+S11308E0220290932302A0932402B09325028093C2
+S11308F0260290932702A0932802B09329028093A2
+S11309002A0290932B02A0932C02B0932D02809381
+S11309102E0290932F02A0933002B093310261E033
+S113092082E00E94B60E61E083E00E94B60E61E0B0
+S11309308AE00E94B60E61E087E00E94B60E61E094
+S113094083E10E94B60E61E082E10E94B60E60E08F
+S113095084E00E94B60E60E088E00E94B60E60E07B
+S113096081E10E94B60E0E94C2010895AF92BF9227
+S1130970CF92DF92EF92FF920F931F93CF93DF9367
+S1130980CDB7DEB722970FB6F894DEBF0FBECDBF4A
+S11309908C017B016A0159014AE050E0BE016F5F9E
+S11309A07F4F0E948A1329813A81201B310B121632
+S11309B013065CF4F70171836083F60180819181F1
+S11309C08A299B299183808303C0F70111821082B5
+S11309D0C90122960FB6F894DEBF0FBECDBFDF91DA
+S11309E0CF911F910F91FF90EF90DF90CF90BF9028
+S11309F0AF900895AF92BF92CF92DF92EF92FF92A1
+S1130A000F931F93CF93DF93CDB7DEB722970FB623
+S1130A10F894DEBF0FBECDBF8C017B016A01590182
+S1130A20BE016F5F7F4F0E943D1229813A81201BD6
+S1130A30310B121613066CF4F70160837183828301
+S1130A409383F601808191818A299B2991838083F4
+S1130A5009C080E090E0A0E0B0E0F70180839183DA
+S1130A60A283B383C90122960FB6F894DEBF0FBEEA
+S1130A70CDBFDF91CF911F910F91FF90EF90DF9049
+S1130A80CF90BF90AF9008952F923F924F925F9274
+S1130A906F927F928F929F92AF92BF92CF92DF928A
+S1130AA0EF92FF920F931F93CF93DF93CDB7DEB7EF
+S1130AB062970FB6F894DEBF0FBECDBF9A8B898BB9
+S1130AC06B015A834983FC0111821082EE24FF24B6
+S1130AD03696FC83EB838B010F5F1F4F82969E83B8
+S1130AE08D83E989FA893E96F887EF8389899A8903
+S1130AF042969A878987E989FA893A96FC87EB872F
+S1130B0089899A898A969E878D87E989FA89B69612
+S1130B10F88BEF8776E1272E312C89899A89280E64
+S1130B20391E6AE1462E512C480E591E54E0652E9A
+S1130B30712C680E791E4EE1842E912C880E991E1C
+S1130B4032E0A32EB12CA80EB91E89C0F601EE0D19
+S1130B50FF1DE081E035F1F1E1358CF4E93409F46D
+S1130B6055C0EA3434F4E63409F45CC0E734B9F42B
+S1130B7019C0EA3409F450C0ED3489F419C0E335DE
+S1130B8011F1E43534F4E13509F459C0E23539F4AE
+S1130B904FC0E93569F1EA3591F1E83511F180E0AA
+S1130BA090E058C021E030E049895A89B50105C078
+S1130BB022E030E049895A89B301C8018E0D9F1D96
+S1130BC00E94B60447C020E034E049895A896D8107
+S1130BD07E813BC024E030E049895A896B817C8165
+S1130BE034C028E030E049895A896B857C852DC062
+S1130BF020E130E049895A896F81788526C020E256
+S1130C0030E049895A8969857A851FC020E430E03B
+S1130C1049895A89B10119C020E830E049895A89C3
+S1130C20B20113C020E032E049895A89B4010DC0F1
+S1130C3020E030E149895A896F85788906C020E02F
+S1130C4038E049895A896D857E85C8018E0D9F1DBE
+S1130C500E94FA040894E11CF11CE80EF91EE981D3
+S1130C60FA81EE16FF060CF471CF62960FB6F89473
+S1130C70DEBF0FBECDBFDF91CF911F910F91FF90CB
+S1130C80EF90DF90CF90BF90AF909F908F907F9028
+S1130C906F905F904F903F902F9008959927BC01DB
+S1130CA085E00E94860F08958FEE9EEF0E94A200B9
+S1130CB061E08CE00E94B60E61E08BE00E94B60E0B
+S1130CC061E086E00E94B60E61E085E00E94B60E07
+S1130CD061E080E10E94B60E61E08FE00E94B60EF2
+S1130CE061E08CE00E94200F60E070E085E00E94EB
+S1130CF0860F60E070E086E00E94860F60E070E09E
+S1130D008BE00E94860F60E080E10E94200F60E08B
+S1130D108FE00E94200F08950F931F93CF93DF93CA
+S1130D20082FC0E0D0E010E0802F0E946B0FC80FA6
+S1130D30D91F1F5F1330C1F7CE0163E070E00E943A
+S1130D403817CB01DF91CF911F910F91089580E067
+S1130D500E948C06AA2797FDA095BA2FBC01CD014D
+S1130D600E94BC1520E030E040EA50E40E94701676
+S1130D7020E030E048EC52E40E94701620E030E0BD
+S1130D8040E85AE30E9470160E948915DC01CB01E9
+S1130D9008950E94A70608950E94C9069C018091A7
+S1130DA0080290910902281739071CF460916E011A
+S1130DB00BC080910A0290910B022817390714F096
+S1130DC060E002C060916D0180910C02861731F0E1
+S1130DD060930C02772786E00E94860F08953F9265
+S1130DE04F925F926F927F928F929F92AF92BF9237
+S1130DF0CF92DF92EF92FF920F931F93CF93DF93E3
+S1130E00CDB7DEB728970FB6F894DEBF0FBECDBFBF
+S1130E106D837E838F839887A0905602B09057028B
+S1130E20C0905802D0905902E0905A02F0905B02B0
+S1130E3000915C0210915D02A8019701C601B50101
+S1130E400E946C1618161CF4C601B50102C0C80134
+S1130E50B7010E94891560936A0270936B028093B4
+S1130E606C0290936D02A0905E02B0905F02C090FD
+S1130E706002D09061020E94BC157B018C019B0131
+S1130E80AC01C601B5010E946C1618161CF4C6010B
+S1130E90B50102C0C801B7010E94891560936A02B6
+S1130EA070936B0280936C0290936D0222E030E0A9
+S1130EB040E050E00E946D17442455243201421A48
+S1130EC0530A640A750A2D813E814F8158852F3F4C
+S1130ED08FE3380780E0480780E058076CF0CA01C8
+S1130EE0B90128EE33E040E050E00E946D173093E2
+S1130EF07E0220937D0204C010927E0210927D0235
+S1130F005301420149825A826B827C8260914A0277
+S1130F1070914B0280914C0290914D020E94891570
+S1130F207B018C0160913E0270913F0280914002EE
+S1130F30909141020E9489159B01AC01C0908101EE
+S1130F4069E084E00E942F04382E60914E02709173
+S1130F504F0280915002909151020E9489157B01A9
+S1130F608C016091420270914302809144029091FD
+S1130F7045020E9489159B01AC01C09082016DE07D
+S1130F8088E00E942F04D82E60915202709153027F
+S1130F9080915402909155020E9489157B018C0125
+S1130FA060914602709147028091480290914902F3
+S1130FB00E9489159B01AC01C090830160E181E12D
+S1130FC00E942F04182F332009F44FC0C301B2012B
+S1130FD00E94BC152091560230915702409158024C
+S1130FE0509159020E94B9140E9489152B013C01A9
+S1130FF01616170618061906C4F582E00E944C045A
+S113100080916A0290916B02A0916C02B0916D0282
+S1131010481A590A6A0A7B0A80918101882379F067
+S113102020E030E040E85FE360913E0270913F02CF
+S113103080914002909141020E94B9140EC020E0B8
+S113104030E040E85FE360913E0270913F0280919E
+S11310504002909141020E94B81460933E02709342
+S11310603F028093400290934102DD2009F45CC06A
+S113107069817A818B819C810E94BC1520915A02DE
+S113108030915B0240915C0250915D020E94B91460
+S11310900E94891569837A838B839C8316161706AD
+S11310A0180619060CF040C08AE00E944C04809196
+S11310B06A0290916B02A0916C02B0916D02298139
+S11310C03A814B815C81281B390B4A0B5B0B2983CA
+S11310D03A834B835C8380918201882379F020E0FA
+S11310E030E040E85FE360914202709143028091F6
+S11310F04402909145020E94B9140EC020E030E0F1
+S113110040E85FE36091420270914302809144029F
+S1131110909145020E94B814609342027093430276
+S11311208093440290934502112309F44FC0C501F2
+S1131130B4010E94BC1520915E0230915F0240917F
+S11311406002509161020E94B9140E9489154B01FA
+S11311505C011616170618061906C4F583E10E94E9
+S11311604C0480916A0290916B02A0916C02B09140
+S11311706D02881A990AAA0ABB0A809183018823FE
+S113118079F020E030E040E85FE36091460270913E
+S1131190470280914802909149020E94B9140EC0FE
+S11311A020E030E040E85FE360914602709147023E
+S11311B080914802909149020E94B81460934602BB
+S11311C07093470280934802909349020E94CC0690
+S11311D060917D0270917E02161617063CF48827F2
+S11311E077FD8095982F0E943D0E04C08D819E81CD
+S11311F00E94C500332009F089CEDD2009F086CE97
+S1131200112309F083CE8091260290912702A091A8
+S11312102802B091290280931A0290931B02A09392
+S11312201C02B0931D0280912A0290912B02A0917E
+S11312302C02B0912D0280931E0290931F02A09362
+S11312402002B093210280912E0290912F02A0914E
+S11312503002B09131028093220290932302A09332
+S11312602402B09325020E94C20128960FB6F89476
+S1131270DEBF0FBECDBFDF91CF911F910F91FF90C5
+S1131280EF90DF90CF90BF90AF909F908F907F9022
+S11312906F905F904F903F90089508C00E94CC06D5
+S11312A068EE73E080E090E00E943D0E0E94C90663
+S11312B0209108023091090225503040821793078B
+S11312C06CF308951F93182F882311F00E944D0981
+S11312D0612F77278BE00E94860F1F910895DF927C
+S11312E0EF92FF920F931F93D82E7B010E944D091A
+S11312F0D09219026D2D80E10E94200F61E08FE0F1
+S11313000E94200F0027F7FC0095102FC801B70199
+S11313100E943D0E60E08FE00E94200F60E080E1BB
+S11313200E94200F1F910F91FF90EF90DF9008957E
+S11313302F923F924F925F926F927F928F929F92E1
+S1131340AF92BF92CF92DF92EF92FF920F931F93CF
+S1131350CF93DF93CDB7DEB7C354D0400FB6F89424
+S1131360DEBF0FBECDBFFC01AB0180818F3209F41B
+S113137068C3BF01CE0101960E94440529813A81C8
+S1131380C90183709070892B71F42115310559F0CE
+S1131390809184019091850197FD05C09C838B8386
+S11313A021603A832983E980FA80E0FEA5C20B819B
+S11313B01C811093850100938401A0902202B090B7
+S11313C02302C0902402D090250280911E029091A5
+S11313D01F02A0912002B09121028FA798ABA9AB64
+S11313E0BAAB80911A0290911B02A0911C02B09199
+S11313F01D028BAB9CABADABBEAB90917001249640
+S11314009FAF2497C701887090702496AFAD24973E
+S1131410AA2329F1892B29F48BA99CA9ADA9BEA9DA
+S113142004C08B859C85AD85BE858FAB98AFA9AF75
+S1131430BAAFE4FC05C08FA598A9A9A9BAA904C0AC
+S11314408F859889A989BA898BAF9CAFADAFBEAFA0
+S1131450E5FE44C02B883C884D885E8841C0892BBA
+S113146049F48BA99CA9ADA9BEA98FAB98AFA9AF2C
+S1131470BAAF0EC02B853C854D855E856BA97CA9D2
+S11314808DA99EA90E94B9146FAB78AF89AF9AAFAA
+S1131490E4FC09C08FA598A9A9A9BAA98BAF9CAFF0
+S11314A0ADAFBEAF0EC02F85388949895A896FA563
+S11314B078A989A99AA90E94B9146BAF7CAF8DAFA2
+S11314C09EAFE5FE0BC02B893C894D895E89C60120
+S11314D0B5010E94B9141B012C0102C0150126019B
+S11314E0F1FE0CC08F8D98A1A9A1BAA180936202CC
+S11314F090936302A0936402B09365020C311105CA
+S113150009F4C6C00D311105ACF40430110509F419
+S113151058C0053011052CF40230110508F0DAC169
+S113152022C00431110509F45FC00531110509F029
+S1131530D1C17FC0043511054CF4013511050CF0FF
+S1131540CDC00E31110509F0C5C1B7C00B35110569
+S113155009F4B0C10C35110509F4AFC10A35110500
+S113156009F0B8C1A3C1820171012BAD3CAD4DADF1
+S11315705EAD6FA978AD89AD9AAD0E94F2038B81FF
+S11315809C81019759F46091620270916302809189
+S11315906402909165020E94CF0002C00E94A401DF
+S11315A06093660270936702809368029093690265
+S11315B0609166027091670280916802909169025D
+S11315C079C020E030E040E05FE36F817885898571
+S11315D09A850E94B9140E948915882777FD809501
+S11315E0982F0E943D0E88C188EF91E2ABE4B3E4EA
+S11315F08093710190937201A0937301B09374016D
+S11316008093750190937601A0937701B09378014C
+S113161080E090E0AEEFB5E48093790190937A0195
+S1131620A0937B01B0937C0180E792E4A1EABCE340
+S113163024C08BE49AEEAFEFB0E4809371019093F1
+S11316407201A0937301B093740180937501909318
+S11316507601A0937701B093780180E090E0A0EA4E
+S1131660B3E48093790190937A01A0937B01B093C2
+S11316707C0180E090E0A0E0BFE380937D01909343
+S11316807E01A0937F01B09380010E94C20134C106
+S11316900F2EF0E0EF2EF0E0FF2EF0E00F2FF0E041
+S11316A01F2FF02DA8019701C801B7010E94F20372
+S11316B00E94A4010E94EF061FC1820171012BAD9B
+S11316C03CAD4DAD5EAD6FA978AD89AD9AAD0E94CC
+S11316D0F2030E94A4010E94EF06DACF6FA078A45F
+S11316E089A49AA424969FAD2497992341F4A60132
+S11316F09501C401B3010E94B9143B014C01A4013A
+S11317009301C601B5010E941D15882384F4840148
+S113171073012FA538A949A95AA96BA97CA98DA938
+S11317209EA90E94F2030E94A4010E94EF06E09089
+S11317302202F090230200912402109125022BAD85
+S11317403CAD4DAD5EAD6FA978AD89AD9AAD0E944B
+S1131750F2030E94A4010E94EF068B819C818335D1
+S1131760910559F48BA59CA5ADA5BEA523968CAF78
+S11317709DAFAEAFBFAF23970CC0A2019101C401CE
+S1131780B3010E94B81423966CAF7DAF8EAF9FAFA8
+S1131790239764015301860175012BAD3CAD4DAD1A
+S11317A05EAD6FA978AD89AD9AAD0E94F2030E9437
+S11317B0A4010E94EF0623962CAD3DAD4EAD5FAD66
+S11317C02397C601B5010E94B8145B016C01A20104
+S11317D091010E941D15882314F4620151018601B0
+S11317E075012BAD3CAD4DAD5EAD6FA978AD89AD46
+S11317F09AAD0E94F203E0906202F09063020091BD
+S113180064021091650220E030E040E050E0C8013D
+S1131810B7010E946C1618162CF4C801B7010E9477
+S1131820CF0002C00E94A401609366027093670215
+S113183080936802909369026091660270916702D6
+S113184080916802909169020E94EF068B819C81CD
+S11318508235910591F420E030E04AE754E46F8149
+S1131860788589859A850E9470160E948915882733
+S113187077FD8095982F0E943D0E840173012BAD56
+S11318803CAD4DAD5EAD6FA978AD89AD9AAD0E940A
+S1131890F2030E94A4010E94EF06A2019101C60175
+S11318A0B5010E946C1618163CF575CF81E0809343
+S11318B0700122C0109270011FC0820171012BAD12
+S11318C03CAD4DAD5EAD6FA978AD89AD9AAD0E94CA
+S11318D0CF0312C060E071E08FE792E00E948010B5
+S11318E04B815C81662757FD6095762F2AE030E0B6
+S11318F08FE792E00E94621029813A8121FFA1C002
+S11319008D819E818936910509F44AC08A369105F4
+S1131910B4F48636910569F18736910544F400974D
+S113192009F48FC08536910509F079C020C0873647
+S1131930910539F18836910509F071C024C08C36BF
+S1131940910509F441C08D36910544F48A36910518
+S1131950A9F18B36910509F062C032C08E3791052A
+S113196009F43FC08F37910509F059C048C081E0A0
+S113197001C080E00E94150480916B010E946209FD
+S113198060C080E0FBCF32FF5CC06BA17CA18DA165
+S11319909EA10E948915DC01CB010E94A20051C0C6
+S11319A067E071E08FE792E00E9480100E94C90610
+S11319B0BC018FE792E00E94751043C08FEF01C015
+S11319C080E00E944E063DC032FF3BC06BA17CA16B
+S11319D08DA19EA10E94891570936C0160936B0187
+S11319E030C020E030E040E05FE36F817885898596
+S11319F09A850E94B9140E94891581E00DC020E0E7
+S1131A0030E040E05FE36F81788589859A850E94A4
+S1131A10B9140E94891580E00E946F0912C06AE01F
+S1131A2071E08FE792E00E9480104D815E8166270D
+S1131A3057FD6095762F2AE030E08FE792E00E9410
+S1131A406210CD5BDF4F0FB6F894DEBF0FBECDBF83
+S1131A50DF91CF911F910F91FF90EF90DF90CF9086
+S1131A60BF90AF909F908F907F906F905F904F90BA
+S1131A703F902F9008950F931F938FEF0E948C0631
+S1131A80AC01EEE1F1E0A1E0B0E0608171814617C4
+S1131A9057071CF5AA0FBB1FAA0FBB1FFD01EA5E67
+S1131AA0FE4F0281138120813181421B530BA65EBC
+S1131AB0BE4FFD0182819381801B910B621B730BCE
+S1131AC09C01429FC001439F900D529F900D112491
+S1131AD00E943817600F711F10C08A2F8F5F1196F4
+S1131AE03496A431B10589F6843119F060E070E0D0
+S1131AF00BC060916801709169016F3F710521F01D
+S1131B001CF06FEF70E004C077FF02C060E070E08B
+S1131B10CB011F910F9108950E94CC068FE792E0AC
+S1131B200E949510882311F18FE792E00E94921091
+S1131B3080936A018D3019F48AE080936A01909150
+S1131B406A0190329CF09B3319F481E08093070280
+S1131B5080910702882351F480910602E82FFF2721
+S1131B60EA57FE4F90838F5F8093060280910602AE
+S1131B7087FF04C0109206021092070260910602C9
+S1131B806623B9F080916A018A3099F47727FB01C2
+S1131B90EA57FE4F108286E891E00E94980910925D
+S1131BA006021092070261E171E08FE792E00E9461
+S1131BB0841008950F931F930FE712E040E05BE455
+S1131BC060E070E0C8010E94991064E171E0C8010E
+S1131BD00E94841010920602109207020E945B0475
+S1131BE00E9454061F910F910895CFEFD4E0DEBFF9
+S1131BF0CDBF0E946C0E0E94DA0D0E948C0DFDCFA9
+S1131C001F920F920FB60F9211248F939F93AF934D
+S1131C10BF938091840290918502A0918602B09135
+S1131C2087020196A11DB11D8093840290938502C1
+S1131C30A0938602B0938702BF91AF919F918F9139
+S1131C400F900FBE0F901F901895609184027091B1
+S1131C508502809186029091870227E0660F771FA4
+S1131C60881F991F2A95D1F72DE730E040E050E016
+S1131C700E944B17CA01B9010895AF92BF92CF9247
+S1131C80DF92EF92FF920F931F935B016C010E940E
+S1131C90250E7B018C010E94250E6E197F09800B95
+S1131CA0910B6A157B058C059D05A8F31F910F9177
+S1131CB0FF90EF90DF90CF90BF90AF900895019781
+S1131CC051F0880F991F880F991F02972FB7F89426
+S1131CD00197F1F72FBF089578941092840210921F
+S1131CE08502109286021092870284B5826084BDB8
+S1131CF084B5816084BD85B5826085BD85B581600C
+S1131D0085BDEEE6F0E0808181608083E1E8F0E06B
+S1131D10808182608083808181608083E0E8F0E05C
+S1131D20808181608083E1EBF0E080818460808346
+S1131D30E0EBF0E0808181608083ECE7F0E080817B
+S1131D408F778083808180648083EAE7F0E08081FC
+S1131D5084608083808182608083808181608083CD
+S1131D608081806880831092C1000895282F3327D2
+S1131D70C90185579F4FFC01949129583F4FF901A0
+S1131D808491882381F0E82FFF27E859FF4FE491DD
+S1131D90FF27662329F48081909589238083089501
+S1131DA08081892B80830895482F5527CA01815645
+S1131DB09F4FFC012491CA0185579F4FFC019491C8
+S1131DC049585F4FFA013491332319F480E090E0CD
+S1131DD00895222331F1233021F4809180008F77FC
+S1131DE005C0243031F4809180008F7D8093800081
+S1131DF018C0213019F484B58F7704C0223021F43F
+S1131E0084B58F7D84BD0DC0263021F48091B0004F
+S1131E108F7705C0273029F48091B0008F7D80939F
+S1131E20B000E32FFF27EE58FF4FE491FF27808196
+S1131E3020E030E0892311F021E030E0C901089569
+S1131E40482F5527CA0181569F4FFC012491CA018E
+S1131E5085579F4FFC01949149585F4FFA01349183
+S1131E603323C1F1222331F1233021F48091800006
+S1131E708F7705C0243031F4809180008F7D80936A
+S1131E80800018C0213019F484B58F7704C0223043
+S1131E9021F484B58F7D84BD0DC0263021F480915A
+S1131EA0B0008F7705C0273029F48091B0008F7D72
+S1131EB08093B000E32FFF27E359FF4FE491FF27FE
+S1131EC0662329F4808190958923808308958081F5
+S1131ED0892B8083089590917C008F70907F892B4B
+S1131EE080937C0080917A00806480937A00809152
+S1131EF07A0086FDFCCF20917800809179009927A3
+S1131F00982F88273327822B932B08951F93CF93E1
+S1131F10DF93182FEB0161E00E94B60EE12FFF273B
+S1131F20E156FF4F8491833051F4809180008068A2
+S1131F3080938000D0938900C093880037C0843098
+S1131F4051F480918000806280938000D0938B0054
+S1131F50C0938A002BC0813029F484B5806884BD85
+S1131F60C7BD24C0823029F484B5806284BDC8BD55
+S1131F701DC0863041F48091B00080688093B00029
+S1131F80C093B30013C0873041F48091B0008062E5
+S1131F908093B000C093B40009C0C038D10514F4D4
+S1131FA060E001C061E0812F0E94200FDF91CF919A
+S1131FB01F91089508950895CB01BA01332744274A
+S1131FC055270E94601108952AE00E94DC0F0895AD
+S1131FD0AB01662777270E94E40F0895862F0E949D
+S1131FE058110895862F0E94581108950F931F9336
+S1131FF08C016DE00E94F20F6AE0C8010E94F20FAA
+S11320001F910F9108950F931F938C010E94E40F69
+S1132010C8010E94F60F1F910F9108950F931F930B
+S11320208C010E94EE0FC8010E94F60F1F910F91C0
+S113203008950F931F938C010E94F20FC8010E9410
+S1132040F60F1F910F910895EF92FF920F931F9334
+S1132050CF93DF93EC017A018B0177FF0BC06DE224
+S11320600E94F20F10950095F094E094E11CF11C8D
+S1132070011D111D2AE0B801A701CE010E94DC0F49
+S1132080DF91CF911F910F91FF90EF9008950F93DF
+S11320901F938C010E942410C8010E94F60F1F9107
+S11320A00F9108952115310521F4642F0E94F20F38
+S11320B008952A30310519F40E94241008950E94CD
+S11320C0DC0F08950F931F938C010E945210C801D6
+S11320D00E94F60F1F910F910895AB01662757FDDB
+S11320E06095762F0E94241008950F931F938C01FE
+S11320F00E946D10C8010E94F60F1F910F91089560
+S1132100CB010E94301208950F931F938C010E94FB
+S11321108010C8010E94F60F1F910F9108950E942C
+S1132120111108950E94F21008950E94E110992758
+S11321300895CB01BA010E94A0100895089508954E
+S1132140EF92FF920F931F937B018C0122E030E00A
+S113215040E050E00E946D17205C3D4B404F5F4FC4
+S1132160CA01B901A80197010E946D17215030409E
+S113217040405040BB2757FDBA95A52F942F832F7D
+S11321802F5F3F4F4F4F5F4F8093C50021502093E7
+S1132190C400E1ECF0E0808180618083808188600C
+S11321A080838081806880831F910F91FF90EF90DE
+S11321B00895982F8091C00085FFFCCF9093C600AE
+S11321C00895809180029091810280589F4F2091C0
+S11321D0820230918302821B930B60E870E00E94BC
+S11321E038170895409182025091830280918002B1
+S11321F0909181028417950719F48FEF9FEF08954A
+S1132200FA01E857FD4F2081CA01019660E870E0A9
+S11322100E9438179093830280938202822F992719
+S11322200895809182029091830290938102809319
+S1132230800208951F920F920FB60F9211242F93CC
+S11322403F934F935F936F937F938F939F93AF933A
+S1132250BF93EF93FF934091C600E0918002F09109
+S11322608102CF01019660E870E00E9438179C015A
+S113227080918202909183022817390739F0E85738
+S1132280FD4F40833093810220938002FF91EF91B0
+S1132290BF91AF919F918F917F916F915F914F917A
+S11322A03F912F910F900FBE0F901F901895089596
+S11322B0982F8091C00085FFFCCF9093C6000895AD
+S11322C02F923F924F925F926F927F928F929F9242
+S11322D0AF92BF92CF92DF92EF92FF920F931F9330
+S11322E0CF93DF93CDB7DEB7A0970FB6F894DEBFD8
+S11322F00FBECDBF6B017C0129013A016115710547
+S11323008105910541F48091C00085FFFCCF80E3F5
+S11323108093C6004BC08824992454011E0108945C
+S1132320211C311C8101080D191DC701B601A3012F
+S113233092010E944B17F80160830894811C911C40
+S1132340A11CB11CC701B601A30192010E944B1745
+S113235069017A01211531054105510519F70894E0
+S113236081089108A108B108F101E80DF91D08944C
+S1132370811C911CA11CB11C14C0089481089108F3
+S1132380A108B10880818A3018F4982F905D02C0AA
+S1132390982F995C8091C00085FFFCCF9093C60074
+S11323A0319781149104A104B10439F7A0960FB6B2
+S11323B0F894DEBF0FBECDBFDF91CF911F910F9177
+S11323C0FF90EF90DF90CF90BF90AF909F908F9051
+S11323D07F906F905F904F903F902F90089520E1F1
+S11323E030E040E050E00E946011089528E030E0C1
+S11323F040E050E00E946011089522E030E040E0A7
+S113240050E00E94601108958091C00085FFFCCFC8
+S11324108AE08093C6000895EF92FF920F931F9372
+S11324207B018C0197FF0FC08091C00085FFFCCF1A
+S11324308DE28093C60010950095F094E094E11C21
+S1132440F11C011D111D2AE030E040E050E0C801FC
+S1132450B7010E9460111F910F91FF90EF900895B2
+S1132460FC0107C08091C00085FFFCCF319690939A
+S1132470C60090819923B1F70895A0E0B0E0E3E4A9
+S1132480F2E10C94D017EC015B016115710519F0B0
+S1132490FB0191838083D9908D2D99270E94A217E7
+S11324A0892BC9F7FDE2DF1621F4D990CC24C3941B
+S11324B005C08BE2D81609F4D990CC248E010150C2
+S11324C0104043E050E063EB70E0C8010E94A014A8
+S11324D0892B09F58E010E5F1F4F45E050E066EB36
+S11324E070E0C8010E94A014892B19F48E01095FC1
+S11324F01F4FA114B10419F0F50111830083C0FE2C
+S113250005C060E070E080E89FEFFFC060E070E02D
+S113251080E89FE7FAC043E050E06BEB70E0C8014D
+S11325200E94A014892B61F4A114B10421F0229615
+S1132530F501D183C08360E070E080EC9FE7E5C0E3
+S113254088249924EE24FF2487014D2D40534A30DA
+S1132550A8F5F2E0CF2A8C2D99279C0128703070C1
+S113256082FF06C0232B81F50894811C911C2CC08A
+S1132570232B19F0089481089108D801C701E2E0DF
+S1132580880F991FAA1FBB1FEA95D1F7E80EF91E01
+S11325900A1F1B1FEE0CFF1C001F111FE40EF11C71
+S11325A0011D111D88E9E81689E9F80689E908077B
+S11325B089E1180748F0E4E0CE2A06C04E3F31F422
+S11325C0C3FC3AC0F8E0CF2AD990BFCF453311F00D
+S11325D0453191F589918D3219F480E1C82A05C0FD
+S11325E08B3219F021E030E003C0899122E030E021
+S11325F0482F40534A3018F420E030E007C0C21B93
+S1132600D30B1AC0ECE020383E075CF4C901880FF4
+S1132610991F880F991F280F391F220F331F240F6A
+S1132620311D499140534A3068F3C4FE03C03095CC
+S113263021953F4F820E931EDD2492E0692E712C6A
+S11326406C207D20C1FE07C0A114B10421F02197A4
+S1132650F501D183C083C801B7010E94BA157B017B
+S11326608C01C0FE06C0672821F017FB109517F9EE
+S113267010955701680120E030E040E050E0C801C7
+S1132680B7010E941D15882309F43DC097FE09C0B7
+S1132690C2EDD0E0909481949108939400E210E00C
+S11326A010C0CAEED0E0FACFFE01259135914591D4
+S11326B05491C601B5010E9470165B016C01801A29
+S11326C0910A8016910684F7159507950115110551
+S11326D011F02497F6CF860175018C2D880F8D2D6E
+S11326E0881F8F3F51F020E030E040E050E0C60109
+S11326F0B5010E941D15882331F482E290E0909385
+S1132700090380930803C801B701EEE0CDB7DEB733
+S11327100C94EC17A0E0B0E0E0E9F3E10C94CD17E1
+S11327208C012B01EA016115710519F0FB019183FC
+S11327308083209749F0CE010297839728F060E0C8
+S113274070E080E090E0F7C0F801E1908F018E2DF9
+S113275099270E94A217892BB9F7FDE2EF1631F4ED
+S1132760F801E1908F013324339407C0FBE2EF16A4
+S113277019F4F801E1908F013324209719F0C03146
+S1132780D105E1F4F0E3EF1679F4F801808188379C
+S113279011F0883549F4F801E1800E5F1F4FF2E033
+S11327A03F2AC0E1D0E00AC0209741F480E3E81654
+S11327B019F4C8E0D0E002C0CAE0D0E0C830D105C6
+S11327C071F0C930D10524F4C230D10519F50DC01A
+S11327D0CA30D10581F0C031D105E1F415C0A12C76
+S11327E0B12CC12CB0E1DB2E22C0A12CB12CC12C08
+S11327F0A0E4DA2E1CC0FCECAF2EFCECBF2EFCECEB
+S1132800CF2EFCE0DF2E13C0A12CB12CC12CE8E0AC
+S1132810DE2E0DC09E01442737FD4095542F60E005
+S113282070E080E090E80E944B1759016A0120E0B3
+S113283030E040E050E060E03E01882477FC809482
+S1132840982C70EDF72EFE0CE9E0EF1570F48E2D48
+S113285081548A3118F499ECF92E06C08E2D8156D4
+S11328608A3150F589EAF82EFE0C8F2D99278C17A2
+S11328709D0714F567FD1CC0A216B306C406D50651
+S1132880B0F0CA01B901A40193010E94AD179B01E4
+S1132890AC012F0D311D411D511D2130F0E03F07CA
+S11328A0F0E04F07F0E85F0710F461E001C06FEF5C
+S11328B0F801E1908F01C5CF4114510481F06623E2
+S11328C031F001501040F2011183008308C031FE41
+S11328D01AC002501040F2011183008314C067FF34
+S11328E012C030FE05C020E030E040E050E804C0F3
+S11328F02FEF3FEF4FEF5FE782E290E09093090301
+S11329008093080316C030FE08C05095409530955A
+S113291021953F4F4F4F5F4F0CC057FF0AC082E2D3
+S113292090E090930903809308032FEF3FEF4FEF5C
+S11329305FE7CA01B901E1E1CDB7DEB70C94E9174D
+S1132940FB01DC014150504088F08D9181341CF032
+S11329508B350CF4805E659161341CF06B350CF49E
+S1132960605E861B611171F3990B0895881BFCCF7F
+S11329705058BB27AA270ED075C166D130F06BD151
+S113298020F031F49F3F11F41EF45BC10EF4E09586
+S1132990E7FB51C1E92F77D180F3BA1762077307B8
+S11329A08407950718F071F49EF58FC10EF4E09535
+S11329B00B2EBA2FA02D0B01B90190010C01CA01F5
+S11329C0A0011124FF27591B99F0593F50F4503EA0
+S11329D068F11A16F040A22F232F342F4427585F92
+S11329E0F3CF469537952795A795F0405395C9F7AA
+S11329F07EF41F16BA0B620B730B840BBAF0915062
+S1132A00A1F0FF0FBB1F661F771F881FC2F70EC000
+S1132A10BA0F621F731F841F48F4879577956795D3
+S1132A20B795F7959E3F08F0B3CF9395880F08F0BC
+S1132A309927EE0F979587950895D9D008F481E0EA
+S1132A4008950CD00FC107D140F0FED030F021F42E
+S1132A505F3F19F0F0C0511139C1F3C014D198F39C
+S1132A609923C9F35523B1F3951B550BBB27AA270B
+S1132A7062177307840738F09F5F5F4F220F331F7D
+S1132A80441FAA1FA9F333D00E2E3AF0E0E830D049
+S1132A9091505040E695001CCAF729D0FE2F27D04C
+S1132AA0660F771F881FBB1F261737074807AB071A
+S1132AB0B0E809F0BB0B802DBF01FF2793585F4F8F
+S1132AC02AF09E3F510568F0B6C000C15F3FECF3A9
+S1132AD0983EDCF3869577956795B795F7959F5F54
+S1132AE0C9F7880F911D9695879597F90895E1E0A8
+S1132AF0660F771F881FBB1F621773078407BA0707
+S1132B0020F0621B730B840BBA0BEE1F88F7E09561
+S1132B10089504D06894B111D9C00895BCD088F048
+S1132B209F5790F0B92F9927B751A0F0D1F0660FB5
+S1132B30771F881F991F1AF0BA95C9F712C0B130D0
+S1132B4081F0C3D0B1E00895C0C0672F782F8827E3
+S1132B50B85F39F0B93FCCF3869577956795B3950F
+S1132B60D9F73EF490958095709561957F4F8F4F7E
+S1132B709F4F0895E89409C097FB3EF49095809583
+S1132B80709561957F4F8F4F9F4F9923A9F0F92F2F
+S1132B9096E9BB279395F695879577956795B795AD
+S1132BA0F111F8CFFAF4BB0F11F460FF1BC06F5F93
+S1132BB07F4F8F4F9F4F16C0882311F096E911C0A5
+S1132BC0772321F09EE8872F762F05C0662371F0C6
+S1132BD096E8862F70E060E02AF09A95660F771FDA
+S1132BE0881FDAF7880F9695879597F90895990FB6
+S1132BF00008550FAA0BE0E8FEEF16161706E807C3
+S1132C00F907C0F012161306E407F50798F0621BE3
+S1132C10730B840B950B39F40A2661F0232B242BB8
+S1132C20252B21F408950A2609F4A140A6958FEFD7
+S1132C30811D811D089597F99F6780E870E060E029
+S1132C4008959FEF80EC089500240A941616170641
+S1132C5018060906089500240A9412161306140689
+S1132C6005060895092E0394000C11F4882352F0EC
+S1132C70BB0F40F4BF2B11F460FF04C06F5F7F4FA4
+S1132C808F4F9F4F089557FD9058440F551F59F08B
+S1132C905F3F71F04795880F97FB991F61F09F3F45
+S1132CA079F087950895121613061406551FF2CF6E
+S1132CB04695F1DF08C0161617061806991FF1CFBE
+S1132CC086957105610508940895E894BB276627E5
+S1132CD07727CB0197F908958ADF08F48FEF0895D9
+S1132CE00BD0C0CFB1DF28F0B6DF18F0952309F080
+S1132CF0A2CFA7CF1124EACFC6DFA0F3959FD1F3CB
+S1132D00950F50E0551F629FF001729FBB27F00D95
+S1132D10B11D639FAA27F00DB11DAA1F649F6627EA
+S1132D20B00DA11D661F829F2227B00DA11D621F39
+S1132D30739FB00DA11D621F839FA00D611D221FF3
+S1132D40749F3327A00D611D231F849F600D211DD7
+S1132D50822F762F6A2F11249F5750408AF0E1F07A
+S1132D6088234AF0EE0FFF1FBB1F661F771F881FC3
+S1132D7091505040A9F79E3F510570F05CCFA6CF0B
+S1132D805F3FECF3983EDCF3869577956795B795AE
+S1132D90F795E7959F5FC1F7FE2B880F911D9695D8
+S1132DA0879597F9089511F40EF44BCF4AC073DF59
+S1132DB0D0F39923D9F3CEF39F57550B87FF51D006
+S1132DC056959795B0E020F4660F771F881FBB1FB8
+S1132DD01F930F9300249001A0018001F001A0E84B
+S1132DE00E0F1F1F0A1E511D601B710B8009B50BAE
+S1132DF048F4600F711F801DB51F0E1B1F0B0A0ABC
+S1132E00510907C02E0F3F1F4A1F0E0F1F1F0A1E16
+S1132E10511D660F771F881FBB1FA695F795E79571
+S1132E20F8F60617170708065B07211D311D411D1B
+S1132E300F911F91B901842F9158880F969587950A
+S1132E4008959F3F49F0915028F4869577956795AA
+S1132E50B7959F5F80389F4F880F9695879597F910
+S1132E60089591505040660F771F881FD2F7089538
+S1132E7097FB092E07260AD077FD04D049D006D047
+S1132E8000201AF4709561957F4F0895F6F7909598
+S1132E9081959F4F0895A1E21A2EAA1BBB1BFD0129
+S1132EA00DC0AA1FBB1FEE1FFF1FA217B307E40725
+S1132EB0F50720F0A21BB30BE40BF50B661F771F7D
+S1132EC0881F991F1A9469F760957095809590955D
+S1132ED09B01AC01BD01CF01089597FB092E052686
+S1132EE00ED057FD04D0D7DF0AD0001C38F450951B
+S1132EF04095309521953F4F4F4F5F4F0895F6F71A
+S1132F0090958095709561957F4F8F4F9F4F089551
+S1132F10AA1BBB1B51E107C0AA1FBB1FA617B707FB
+S1132F2010F0A61BB70B881F991F5A95A9F7809517
+S1132F309095BC01CD010895EE0FFF1F0590F4910B
+S1132F40E02D0994911106C0803219F08950855002
+S1132F50D0F70895992788270895629FD001739F19
+S1132F60F001829FE00DF11D649FE00DF11D929F21
+S1132F70F00D839FF00D749FF00D659FF00D992760
+S1132F80729FB00DE11DF91F639FB00DE11DF91F84
+S1132F90BD01CF01112408952F923F924F925F9269
+S1132FA06F927F928F929F92AF92BF92CF92DF9255
+S1132FB0EF92FF920F931F93CF93DF93CDB7DEB7BA
+S1132FC0CA1BDB0B0FB6F894DEBF0FBECDBF09944E
+S1132FD02A88398848885F846E847D848C849B84A5
+S1132FE0AA84B984C884DF80EE80FD800C811B81B3
+S1132FF0AA81B981CE0FD11D0FB6F894DEBF0FBEE2
+S10B3000CDBFED010895FFCFDF
+S11330086875683F204700543A004875683F204D6A
+S1133018006F6B0073746172740001004903360019
+S1133028FF006B00D100A000B800D500A6000A017B
+S113303899003F018E0074018400A9017C00DE011F
+S1133048740013026C00480265007D025D00B20240
+S11330585600E7024E001C03460051033D00860358
+S11330683200BB032200F00303003F800040FF014D
+S1133078014BEAFF404BEAFF400000A04300000078
+S10930883F010101FFFFFE
+S9030000FC
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/ThermistorTable.h b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/ThermistorTable.h
new file mode 100644
index 00000000..07a35377
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/ThermistorTable.h
@@ -0,0 +1,36 @@
+#ifndef THERMISTORTABLE_H_
+#define THERMISTORTABLE_H_
+
+// Thermistor lookup table for RepRap Temperature Sensor Boards (http://make.rrrf.org/ts)
+// Made with createTemperatureLookup.py (http://svn.reprap.org/trunk/reprap/firmware/Arduino/utilities/createTemperatureLookup.py)
+// ./createTemperatureLookup.py --r0=100000 --t0=25 --r1=0 --r2=4700 --beta=4066 --max-adc=1023
+// r0: 100000
+// t0: 25
+// r1: 0
+// r2: 4700
+// beta: 4066
+// max adc: 1023
+#define NUMTEMPS 20
+short temptable[NUMTEMPS][2] = {
+ {1, 841},
+ {54, 255},
+ {107, 209},
+ {160, 184},
+ {213, 166},
+ {266, 153},
+ {319, 142},
+ {372, 132},
+ {425, 124},
+ {478, 116},
+ {531, 108},
+ {584, 101},
+ {637, 93},
+ {690, 86},
+ {743, 78},
+ {796, 70},
+ {849, 61},
+ {902, 50},
+ {955, 34},
+ {1008, 3}
+};
+#endif
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/_init.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/_init.pde
index 1db13f72..1db13f72 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/_init.pde
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/_init.pde
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/core.a b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/core.a
new file mode 100644
index 00000000..f3dae0a6
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/core.a
Binary files differ
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/extruder.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/extruder.pde
index 6cb0311d..b14fbf18 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/extruder.pde
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/extruder.pde
@@ -64,6 +64,7 @@ void valve_set(bool open, int millis)
digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 1);
delay(millis);
digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, 0);
}
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/parameters.h b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/parameters.h
new file mode 100644
index 00000000..1b14eaed
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/parameters.h
@@ -0,0 +1,27 @@
+// define the parameters of our machine.
+#define X_STEPS_PER_MM 7.99735
+#define X_STEPS_PER_INCH (X_STEPS_PER_MM*25.4)
+#define X_MOTOR_STEPS 400
+
+#define Y_STEPS_PER_MM 7.99735
+#define Y_STEPS_PER_INCH (Y_STEPS_PER_MM*25.4)
+#define Y_MOTOR_STEPS 400
+
+#define Z_STEPS_PER_MM 320
+#define Z_STEPS_PER_INCH (Z_STEPS_PER_MM*25.4)
+#define Z_MOTOR_STEPS 400
+
+//our maximum feedrates
+#define FAST_XY_FEEDRATE 1600.0
+#define FAST_Z_FEEDRATE 50.0
+
+// Units in curve section
+#define CURVE_SECTION_INCHES 0.019685
+#define CURVE_SECTION_MM 0.5
+
+// Set to one if sensor outputs inverting (ie: 1 means open, 0 means closed)
+// RepRap opto endstops are *not* inverting.
+#define SENSORS_INVERTING 0
+
+// How many temperature samples to take. each sample takes about 100 usecs.
+#define TEMPERATURE_SAMPLES 3
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/pins.h b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/pins.h
new file mode 100644
index 00000000..638281bb
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/pins.h
@@ -0,0 +1,77 @@
+//#define SANGUINO
+#ifdef SANGUINO
+/****************************************************************************************
+* Sanguino digital i/o pin assignment
+*
+****************************************************************************************/
+
+//cartesian bot pins
+#define X_STEP_PIN 15
+#define X_DIR_PIN 18
+#define X_MIN_PIN 20
+#define X_MAX_PIN 21
+#define X_ENABLE_PIN 19
+
+#define Y_STEP_PIN 22
+#define Y_DIR_PIN 23
+#define Y_MIN_PIN 25
+#define Y_MAX_PIN 26
+#define Y_ENABLE_PIN 19
+
+#define Z_STEP_PIN 29
+#define Z_DIR_PIN 30
+#define Z_MIN_PIN 1
+#define Z_MAX_PIN 2
+#define Z_ENABLE_PIN 31
+
+//extruder pins
+#define EXTRUDER_0_MOTOR_SPEED_PIN 12
+#define EXTRUDER_0_MOTOR_DIR_PIN 16
+#define EXTRUDER_0_HEATER_PIN 14
+#define EXTRUDER_0_FAN_PIN 3
+#define EXTRUDER_0_THERMISTOR_PIN -1 //a -1 disables thermistor readings
+#define EXTRUDER_0_THERMOCOUPLE_PIN 4 //a -1 disables thermocouple readings
+#define EXTRUDER_0_VALVE_DIR_PIN 17
+#define EXTRUDER_0_VALVE_ENABLE_PIN 13 // Valve needs to be redesigned not to need this
+
+/*
+#define EXTRUDER_1_MOTOR_SPEED_PIN 99
+#define EXTRUDER_1_MOTOR_DIR_PIN 99
+#define EXTRUDER_1_HEATER_PIN 99
+#define EXTRUDER_1_FAN_PIN 99
+#define EXTRUDER_1_THERMISTOR_PIN 99 //a -1 disables thermistor readings
+#define EXTRUDER_1_THERMOCOUPLE_PIN 99 //a -1 disables thermocouple readings
+#define EXTRUDER_1_VALVE_DIR_PIN 99
+#define EXTRUDER_1_VALVE_ENABLE_PIN 99
+*/
+
+#else
+
+// Arduino cartesian bot pins
+#define X_STEP_PIN 2
+#define X_DIR_PIN 3
+#define X_MIN_PIN 4
+#define X_MAX_PIN 9
+//#define X_ENABLE_PIN 15
+#define Y_STEP_PIN 10
+#define Y_DIR_PIN 7
+#define Y_MIN_PIN 8
+#define Y_MAX_PIN 13
+//#define Y_ENABLE_PIN 15
+#define Z_STEP_PIN 19
+#define Z_DIR_PIN 18
+#define Z_MIN_PIN 17
+#define Z_MAX_PIN 16
+//#define Z_ENABLE_PIN 15
+
+//extruder pins
+#define EXTRUDER_0_MOTOR_SPEED_PIN 11
+#define EXTRUDER_0_MOTOR_DIR_PIN 12
+#define EXTRUDER_0_HEATER_PIN 6
+#define EXTRUDER_0_FAN_PIN 5
+#define EXTRUDER_0_THERMISTOR_PIN -1 //a -1 disables thermistor readings
+#define EXTRUDER_0_THERMOCOUPLE_PIN 0 //a -1 disables thermocouple readings
+#define EXTRUDER_0_VALVE_ENABLE_PIN 15
+#define EXTRUDER_0_VALVE_DIR_PIN 16 //NB: Conflicts with Max Z!!!!
+
+#endif
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/process_string.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/process_string.pde
index c22d83c8..c22d83c8 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/process_string.pde
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/process_string.pde
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/stepper_control.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/stepper_control.pde
index 5d59fa6c..46040eb8 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/stepper_control.pde
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/applet/stepper_control.pde
@@ -21,7 +21,9 @@ int milli_delay;
void init_steppers()
{
//turn them off to start.
+#ifdef SANGUINO
disable_steppers();
+#endif
//init our points.
current_units.x = 0.0;
@@ -33,13 +35,16 @@ void init_steppers()
pinMode(X_STEP_PIN, OUTPUT);
pinMode(X_DIR_PIN, OUTPUT);
- pinMode(X_ENABLE_PIN, OUTPUT);
pinMode(Y_STEP_PIN, OUTPUT);
pinMode(Y_DIR_PIN, OUTPUT);
- pinMode(Y_ENABLE_PIN, OUTPUT);
pinMode(Z_STEP_PIN, OUTPUT);
pinMode(Z_DIR_PIN, OUTPUT);
+
+#ifdef SANGUINO
+ pinMode(X_ENABLE_PIN, OUTPUT);
+ pinMode(Y_ENABLE_PIN, OUTPUT);
pinMode(Z_ENABLE_PIN, OUTPUT);
+#endif
#if ENDSTOPS_MIN_ENABLED == 1
pinMode(X_MIN_PIN, INPUT);
@@ -59,7 +64,9 @@ void init_steppers()
void dda_move(long micro_delay)
{
//turn on steppers to start moving =)
+#ifdef SANGUINO
enable_steppers();
+#endif
//figure out our deltas
max_delta = max(delta_steps.x, delta_steps.y);
@@ -299,6 +306,7 @@ long getMaxSpeed()
return calculate_feedrate_delay(FAST_XY_FEEDRATE);
}
+#ifdef SANGUINO
void enable_steppers()
{
// Enable steppers only for axes which are moving
@@ -347,6 +355,7 @@ void disable_steppers()
digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
}
+#endif
void delayMicrosecondsInterruptible(unsigned int us)
{
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/extruder.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/extruder.pde
new file mode 100644
index 00000000..b14fbf18
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/extruder.pde
@@ -0,0 +1,267 @@
+// Yep, this is actually -*- c++ -*-
+
+#include "ThermistorTable.h"
+
+#define EXTRUDER_0_FORWARD true
+#define EXTRUDER_0_REVERSE false
+
+//these our the default values for the extruder.
+int extruder_speed = 128;
+int extruder_target_celsius = 0;
+int extruder_max_celsius = 0;
+byte extruder_heater_low = 64;
+byte extruder_heater_high = 255;
+byte extruder_heater_current = 0;
+
+//this is for doing encoder based extruder control
+int extruder_rpm = 0;
+long extruder_delay = 0;
+int extruder_error = 0;
+int last_extruder_error = 0;
+int extruder_error_delta = 0;
+bool extruder_direction = EXTRUDER_0_FORWARD;
+bool valve_open = false;
+
+void init_extruder()
+{
+ //default to cool...
+ extruder_set_temperature(-273);
+
+ //setup our pins
+ pinMode(EXTRUDER_0_MOTOR_DIR_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_MOTOR_SPEED_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_HEATER_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_FAN_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_VALVE_DIR_PIN, OUTPUT);
+ pinMode(EXTRUDER_0_VALVE_ENABLE_PIN, OUTPUT);
+
+ //initialize values
+ digitalWrite(EXTRUDER_0_MOTOR_DIR_PIN, EXTRUDER_0_FORWARD);
+ analogWrite(EXTRUDER_0_FAN_PIN, 0);
+ analogWrite(EXTRUDER_0_HEATER_PIN, 0);
+ analogWrite(EXTRUDER_0_MOTOR_SPEED_PIN, 0);
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, false);
+ digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+}
+
+void wait_for_heater()
+{
+ //warmup if we're too cold.
+ while (extruder_get_temperature() < (extruder_target_celsius - 5))
+ {
+ extruder_manage_temperature();
+ //Serial.print("T: ");
+ //Serial.println(extruder_get_temperature());
+ delay(1000);
+ }
+}
+
+void valve_set(bool open, int millis)
+{
+ wait_for_heater();
+ valve_open = open;
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, open);
+ digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 1);
+ delay(millis);
+ digitalWrite(EXTRUDER_0_VALVE_ENABLE_PIN, 0);
+ digitalWrite(EXTRUDER_0_VALVE_DIR_PIN, 0);
+}
+
+
+void extruder_set_direction(bool direction)
+{
+ extruder_direction = direction;
+ digitalWrite(EXTRUDER_0_MOTOR_DIR_PIN, direction);
+}
+
+void extruder_set_speed(byte speed)
+{
+ if(speed > 0)
+ wait_for_heater();
+ analogWrite(EXTRUDER_0_MOTOR_SPEED_PIN, speed);
+}
+
+void extruder_set_cooler(byte speed)
+{
+ analogWrite(EXTRUDER_0_FAN_PIN, speed);
+}
+
+void extruder_set_temperature(int temp)
+{
+ extruder_target_celsius = temp;
+ extruder_max_celsius = (int)((float)temp * 1.1);
+}
+
+/**
+* Samples the temperature and converts it to degrees celsius.
+* Returns degrees celsius.
+*/
+int extruder_get_temperature()
+{
+ if (EXTRUDER_0_THERMISTOR_PIN > -1)
+ return extruder_read_thermistor();
+ else if (EXTRUDER_0_THERMOCOUPLE_PIN > -1)
+ return extruder_read_thermocouple();
+}
+
+/*
+* This function gives us the temperature from the thermistor in Celsius
+*/
+
+int extruder_read_thermistor()
+{
+ int raw = extruder_sample_temperature(EXTRUDER_0_THERMISTOR_PIN);
+
+ int celsius = 0;
+ byte i;
+
+ for (i=1; i<NUMTEMPS; i++)
+ {
+ if (temptable[i][0] > raw)
+ {
+ celsius = temptable[i-1][1] +
+ (raw - temptable[i-1][0]) *
+ (temptable[i][1] - temptable[i-1][1]) /
+ (temptable[i][0] - temptable[i-1][0]);
+
+ break;
+ }
+ }
+
+ // Overflow: Set to last value in the table
+ if (i == NUMTEMPS) celsius = temptable[i-1][1];
+ // Clamp to byte
+ if (celsius > 255) celsius = 255;
+ else if (celsius < 0) celsius = 0;
+
+ return celsius;
+}
+
+/*
+* This function gives us the temperature from the thermocouple in Celsius
+*/
+int extruder_read_thermocouple()
+{
+ return ( 5.0 * extruder_sample_temperature(EXTRUDER_0_THERMOCOUPLE_PIN) * 100.0) / 1024.0;
+}
+
+/*
+* This function gives us an averaged sample of the analog temperature pin.
+*/
+int extruder_sample_temperature(byte pin)
+{
+ int raw = 0;
+
+ //read in a certain number of samples
+ for (byte i=0; i<TEMPERATURE_SAMPLES; i++)
+ raw += analogRead(pin);
+
+ //average the samples
+ raw = raw/TEMPERATURE_SAMPLES;
+
+ //send it back.
+ return raw;
+}
+
+/*!
+ Manages motor and heater based on measured temperature:
+ o If temp is too low, don't start the motor
+ o Adjust the heater power to keep the temperature at the target
+ */
+void extruder_manage_temperature()
+{
+ //make sure we know what our temp is.
+ int current_celsius = extruder_get_temperature();
+ byte newheat = 0;
+
+ //put the heater into high mode if we're not at our target.
+ if (current_celsius < extruder_target_celsius)
+ newheat = extruder_heater_high;
+ //put the heater on low if we're at our target.
+ else if (current_celsius < extruder_max_celsius)
+ newheat = extruder_heater_low;
+
+ // Only update heat if it changed
+ if (extruder_heater_current != newheat) {
+ extruder_heater_current = newheat;
+ analogWrite(EXTRUDER_0_HEATER_PIN, extruder_heater_current);
+ }
+}
+
+#ifdef TEST_MACHINE
+
+bool heat_on;
+
+void extruder_heater_test()
+{
+ int t = extruder_get_temperature();
+ if(t < 50 && !heat_on)
+ {
+ Serial.println("\n *** Turning heater on.\n");
+ heat_on = true;
+ analogWrite(EXTRUDER_0_HEATER_PIN, extruder_heater_high);
+ }
+
+ if(t > 100 && heat_on)
+ {
+ Serial.println("\n *** Turning heater off.\n");
+ heat_on = false;
+ analogWrite(EXTRUDER_0_HEATER_PIN, 0);
+ }
+
+ Serial.print("Temperature: ");
+ Serial.print(t);
+ Serial.print(" deg C. The heater is ");
+ if(heat_on)
+ Serial.println("on.");
+ else
+ Serial.println("off.");
+
+ delay(2000);
+}
+
+void extruder_drive_test()
+{
+ Serial.println("Turning the extruder motor on forwards for 5 seconds.");
+ extruder_set_direction(true);
+ extruder_set_speed(200);
+ delay(5000);
+ extruder_set_speed(0);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+ Serial.println("Turning the extruder motor on backwards for 5 seconds.");
+ extruder_set_direction(false);
+ extruder_set_speed(200);
+ delay(5000);
+ extruder_set_speed(0);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+}
+
+void extruder_valve_test()
+{
+ Serial.println("Opening the valve.");
+ valve_set(true, 500);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+ Serial.println("Closing the valve.");
+ valve_set(false, 500);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+}
+
+void extruder_fan_test()
+{
+ Serial.println("Fan on.");
+ extruder_set_cooler(255);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+ Serial.println("Fan off.");
+ extruder_set_cooler(0);
+ Serial.println("Pausing for 2 seconds.");
+ delay(2000);
+}
+
+
+
+#endif
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/parameters.h.dist b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/parameters.h.dist
index 5f0f76f0..5f0f76f0 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/parameters.h.dist
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/parameters.h.dist
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/pins.h.dist b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/pins.h.dist
index 6156c11a..6156c11a 100644
--- a/trunk/reprap/firmware/Sanguino/GCode_Interpreter/pins.h.dist
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/pins.h.dist
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/process_string.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/process_string.pde
new file mode 100644
index 00000000..c22d83c8
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/process_string.pde
@@ -0,0 +1,579 @@
+// Yep, this is actually -*- c++ -*-
+
+// our point structure to make things nice.
+struct LongPoint
+{
+ long x;
+ long y;
+ long z;
+};
+
+struct FloatPoint
+{
+ float x;
+ float y;
+ float z;
+};
+
+/* gcode line parse results */
+struct GcodeParser
+{
+ unsigned int seen;
+ int G;
+ int M;
+ float P;
+ float X;
+ float Y;
+ float Z;
+ float I;
+ float J;
+ float F;
+ float S;
+ float R;
+ float Q;
+};
+
+FloatPoint current_units;
+FloatPoint target_units;
+FloatPoint delta_units;
+
+FloatPoint current_steps;
+FloatPoint target_steps;
+FloatPoint delta_steps;
+
+boolean abs_mode = true; //0 = incremental; 1 = absolute
+
+//default to mm for units
+float x_units = X_STEPS_PER_MM;
+float y_units = Y_STEPS_PER_MM;
+float z_units = Z_STEPS_PER_MM;
+float curve_section = CURVE_SECTION_MM;
+
+//our direction vars
+byte x_direction = 1;
+byte y_direction = 1;
+byte z_direction = 1;
+
+int scan_int(char *str, int *valp);
+int scan_float(char *str, float *valp);
+
+//init our string processing
+void init_process_string()
+{
+ //init our command
+ //for (byte i=0; i<COMMAND_SIZE; i++)
+ // word[i] = 0;
+ serial_count = 0;
+ comment = false;
+}
+
+//our feedrate variables.
+float feedrate = 0.0;
+long feedrate_micros = 0;
+
+/* keep track of the last G code - this is the command mode to use
+ * if there is no command in the current string
+ */
+int last_gcode_g = -1;
+
+/* bit-flags for commands and parameters */
+#define GCODE_G (1<<0)
+#define GCODE_M (1<<1)
+#define GCODE_P (1<<2)
+#define GCODE_X (1<<3)
+#define GCODE_Y (1<<4)
+#define GCODE_Z (1<<5)
+#define GCODE_I (1<<6)
+#define GCODE_J (1<<7)
+#define GCODE_K (1<<8)
+#define GCODE_F (1<<9)
+#define GCODE_S (1<<10)
+#define GCODE_Q (1<<11)
+#define GCODE_R (1<<12)
+
+#define TYPE_INT 1
+#define TYPE_FLOAT 2
+
+
+#define PARSE_INT(ch, str, len, val, seen, flag) \
+ case ch: \
+ len = scan_int(str, &val, &seen, flag); \
+ break;
+
+#define PARSE_FLOAT(ch, str, len, val, seen, flag) \
+ case ch: \
+ len = scan_float(str, &val, &seen, flag); \
+ break;
+
+int parse_string(struct GcodeParser * gc, char instruction[], int size)
+{
+ int ind;
+ int len; /* length of parameter argument */
+
+ gc->seen = 0;
+
+ len=0;
+ /* scan the string for commands and parameters, recording the arguments for each,
+ * and setting the seen flag for each that is seen
+ */
+ for (ind=0; ind<size; ind += (1+len))
+ {
+ len = 0;
+ switch (instruction[ind])
+ {
+ PARSE_INT('G', &instruction[ind+1], len, gc->G, gc->seen, GCODE_G);
+ PARSE_INT('M', &instruction[ind+1], len, gc->M, gc->seen, GCODE_M);
+ PARSE_FLOAT('S', &instruction[ind+1], len, gc->S, gc->seen, GCODE_S);
+ PARSE_FLOAT('P', &instruction[ind+1], len, gc->P, gc->seen, GCODE_P);
+ PARSE_FLOAT('X', &instruction[ind+1], len, gc->X, gc->seen, GCODE_X);
+ PARSE_FLOAT('Y', &instruction[ind+1], len, gc->Y, gc->seen, GCODE_Y);
+ PARSE_FLOAT('Z', &instruction[ind+1], len, gc->Z, gc->seen, GCODE_Z);
+ PARSE_FLOAT('I', &instruction[ind+1], len, gc->I, gc->seen, GCODE_I);
+ PARSE_FLOAT('J', &instruction[ind+1], len, gc->J, gc->seen, GCODE_J);
+ PARSE_FLOAT('F', &instruction[ind+1], len, gc->F, gc->seen, GCODE_F);
+ PARSE_FLOAT('R', &instruction[ind+1], len, gc->R, gc->seen, GCODE_R);
+ PARSE_FLOAT('Q', &instruction[ind+1], len, gc->Q, gc->seen, GCODE_Q);
+ default:
+ break;
+ }
+ }
+}
+
+
+//Read the string and execute instructions
+void process_string(char instruction[], int size)
+{
+
+ GcodeParser gc; /* string parse result */
+
+ //the character / means delete block... used for comments and stuff.
+ if (instruction[0] == '/')
+ return;
+
+ //init baby!
+ FloatPoint fp;
+ fp.x = 0.0;
+ fp.y = 0.0;
+ fp.z = 0.0;
+
+ //get all our parameters!
+ parse_string(&gc, instruction, size);
+ /* if no command was seen, but parameters were, then use the last G code as
+ * the current command
+ */
+ if ((!(gc.seen & (GCODE_G | GCODE_M))) &&
+ ((gc.seen != 0) &&
+ (last_gcode_g >= 0))
+ )
+ {
+ /* yes - so use the previous command with the new parameters */
+ gc.G = last_gcode_g;
+ gc.seen |= GCODE_G;
+ }
+ //did we get a gcode?
+ if (gc.seen & GCODE_G)
+ {
+ last_gcode_g = gc.G; /* remember this for future instructions */
+ fp = current_units;
+ if (abs_mode)
+ {
+ if (gc.seen & GCODE_X)
+ fp.x = gc.X;
+ if (gc.seen & GCODE_Y)
+ fp.y = gc.Y;
+ if (gc.seen & GCODE_Z)
+ fp.z = gc.Z;
+ }
+ else
+ {
+ if (gc.seen & GCODE_X)
+ fp.x += gc.X;
+ if (gc.seen & GCODE_Y)
+ fp.y += gc.Y;
+ if (gc.seen & GCODE_Z)
+ fp.z += gc.Z;
+ }
+
+ // Get feedrate if supplied
+ if ( gc.seen & GCODE_F )
+ feedrate = gc.F;
+
+ //do something!
+ switch (gc.G)
+ {
+ //Rapid Positioning
+ //Linear Interpolation
+ //these are basically the same thing.
+ case 0:
+ case 1:
+ //set our target.
+ set_target(fp.x, fp.y, fp.z);
+
+ // Use currently set feedrate if doing a G1
+ if (gc.G == 1)
+ feedrate_micros = calculate_feedrate_delay(feedrate);
+ // Use our max for G0
+ else
+ feedrate_micros = getMaxSpeed();
+ //finally move.
+ dda_move(feedrate_micros);
+ break;
+#ifdef SANGUINO
+// No room for this in the Arduino
+ //Clockwise arc
+ case 2:
+ //Counterclockwise arc
+ case 3:
+ {
+ FloatPoint cent;
+
+ // Centre coordinates are always relative
+ if (gc.seen & GCODE_I) cent.x = current_units.x + gc.I;
+ else cent.x = current_units.x;
+ if (gc.seen & GCODE_J) cent.y = current_units.y + gc.J;
+
+ float angleA, angleB, angle, radius, length, aX, aY, bX, bY;
+
+ aX = (current_units.x - cent.x);
+ aY = (current_units.y - cent.y);
+ bX = (fp.x - cent.x);
+ bY = (fp.y - cent.y);
+
+ // Clockwise
+ if (gc.G == 2)
+ {
+ angleA = atan2(bY, bX);
+ angleB = atan2(aY, aX);
+ }
+ // Counterclockwise
+ else
+ {
+ angleA = atan2(aY, aX);
+ angleB = atan2(bY, bX);
+ }
+
+ // Make sure angleB is always greater than angleA
+ // and if not add 2PI so that it is (this also takes
+ // care of the special case of angleA == angleB,
+ // ie we want a complete circle)
+ if (angleB <= angleA)
+ angleB += 2 * M_PI;
+ angle = angleB - angleA;
+
+ radius = sqrt(aX * aX + aY * aY);
+ length = radius * angle;
+ int steps, s, step;
+
+ // Maximum of either 2.4 times the angle in radians or the length of the curve divided by the constant specified in _init.pde
+ steps = (int) ceil(max(angle * 2.4, length / curve_section));
+
+ FloatPoint newPoint;
+ float arc_start_z = current_units.z;
+ for (s = 1; s <= steps; s++)
+ {
+ step = (gc.G == 3) ? s : steps - s; // Work backwards for CW
+ newPoint.x = cent.x + radius * cos(angleA + angle
+ * ((float) step / steps));
+ newPoint.y = cent.y + radius * sin(angleA + angle
+ * ((float) step / steps));
+ set_target(newPoint.x, newPoint.y, arc_start_z + (fp.z
+ - arc_start_z) * s / steps);
+
+ // Need to calculate rate for each section of curve
+ if (feedrate > 0)
+ feedrate_micros = calculate_feedrate_delay(feedrate);
+ else
+ feedrate_micros = getMaxSpeed();
+
+ // Make step
+ dda_move(feedrate_micros);
+ }
+ }
+ break;
+#endif
+
+ case 4: //Dwell
+ delay((int)(gc.P + 0.5)); // Changed by AB from 1000*gc.P
+ break;
+
+ //Inches for Units
+ case 20:
+ x_units = X_STEPS_PER_INCH;
+ y_units = Y_STEPS_PER_INCH;
+ z_units = Z_STEPS_PER_INCH;
+ curve_section = CURVE_SECTION_INCHES;
+
+ calculate_deltas();
+ break;
+
+ //mm for Units
+ case 21:
+ x_units = X_STEPS_PER_MM;
+ y_units = Y_STEPS_PER_MM;
+ z_units = Z_STEPS_PER_MM;
+ curve_section = CURVE_SECTION_MM;
+
+ calculate_deltas();
+ break;
+
+ //go home.
+ case 28:
+ set_target(0.0, 0.0, 0.0);
+ dda_move(getMaxSpeed());
+ break;
+
+ //go home via an intermediate point.
+ case 30:
+ //set our target.
+ set_target(fp.x, fp.y, fp.z);
+
+ //go there.
+ dda_move(getMaxSpeed());
+
+ //go home.
+ set_target(0.0, 0.0, 0.0);
+ dda_move(getMaxSpeed());
+ break;
+
+ // Drilling canned cycles
+ case 81: // Without dwell
+ case 82: // With dwell
+ case 83: // Peck drilling
+ {
+ float retract = gc.R;
+
+ if (!abs_mode)
+ retract += current_units.z;
+
+ // Retract to R position if Z is currently below this
+ if (current_units.z < retract)
+ {
+ set_target(current_units.x, current_units.y, retract);
+ dda_move(getMaxSpeed());
+ }
+
+ // Move to start XY
+ set_target(fp.x, fp.y, current_units.z);
+ dda_move(getMaxSpeed());
+
+ // Do the actual drilling
+ float target_z = retract;
+ float delta_z;
+
+ // For G83 move in increments specified by Q code, otherwise do in one pass
+ if (gc.G == 83)
+ delta_z = gc.Q;
+ else
+ delta_z = retract - fp.z;
+
+ do {
+ // Move rapidly to bottom of hole drilled so far (target Z if starting hole)
+ set_target(fp.x, fp.y, target_z);
+ dda_move(getMaxSpeed());
+
+ // Move with controlled feed rate by delta z (or to bottom of hole if less)
+ target_z -= delta_z;
+ if (target_z < fp.z)
+ target_z = fp.z;
+ set_target(fp.x, fp.y, target_z);
+ if (feedrate > 0)
+ feedrate_micros = calculate_feedrate_delay(feedrate);
+ else
+ feedrate_micros = getMaxSpeed();
+ dda_move(feedrate_micros);
+
+ // Dwell if doing a G82
+ if (gc.G == 82)
+ delay((int)(gc.P * 1000));
+
+ // Retract
+ set_target(fp.x, fp.y, retract);
+ dda_move(getMaxSpeed());
+ } while (target_z > fp.z);
+ }
+ break;
+
+
+ case 90: //Absolute Positioning
+ abs_mode = true;
+ break;
+
+
+ case 91: //Incremental Positioning
+ abs_mode = false;
+ break;
+
+
+ case 92: //Set position as fp
+ set_position(fp.x, fp.y, fp.z);
+ break;
+
+ /*
+ //Inverse Time Feed Mode
+ case 93:
+
+ break; //TODO: add this
+
+ //Feed per Minute Mode
+ case 94:
+
+ break; //TODO: add this
+ */
+
+ default:
+ Serial.print("huh? G");
+ Serial.println(gc.G, DEC);
+ }
+ }
+
+ //find us an m code.
+ if (gc.seen & GCODE_M)
+ {
+ switch (gc.M)
+ {
+ //TODO: this is a bug because search_string returns 0. gotta fix that.
+ case 0:
+ true;
+ break;
+ /*
+ case 0:
+ //todo: stop program
+ break;
+
+ case 1:
+ //todo: optional stop
+ break;
+
+ case 2:
+ //todo: program end
+ break;
+ */
+ //turn extruder on, forward
+ case 101:
+ extruder_set_direction(1);
+ extruder_set_speed(extruder_speed);
+ break;
+
+ //turn extruder on, reverse
+ case 102:
+ extruder_set_direction(0);
+ extruder_set_speed(extruder_speed);
+ break;
+
+ //turn extruder off
+ case 103:
+ extruder_set_speed(0);
+ break;
+
+ //custom code for temperature control
+ case 104:
+ if (gc.seen & GCODE_S)
+ {
+ extruder_set_temperature((int)gc.S);
+
+// //warmup if we're too cold.
+// while (extruder_get_temperature() < extruder_target_celsius)
+// {
+// extruder_manage_temperature();
+// Serial.print("T: ");
+// Serial.println(extruder_get_temperature());
+// delay(1000);
+// }
+ }
+ break;
+
+ //custom code for temperature reading
+ case 105:
+ Serial.print("T:");
+ Serial.println(extruder_get_temperature());
+ break;
+
+ //turn fan on
+ case 106:
+ extruder_set_cooler(255);
+ break;
+
+ //turn fan off
+ case 107:
+ extruder_set_cooler(0);
+ break;
+
+ //set max extruder speed, 0-255 PWM
+ case 108:
+ if (gc.seen & GCODE_S)
+ extruder_speed = (int)gc.S;
+ break;
+
+ // Open the valve
+ case 126:
+ valve_set(true, (int)(gc.P + 0.5));
+ break;
+
+ // Close the valve
+ case 127:
+ valve_set(false, (int)(gc.P + 0.5));
+ break;
+
+
+ default:
+ Serial.print("Huh? M");
+ Serial.println(gc.M, DEC);
+ }
+ }
+
+}
+
+int scan_float(char *str, float *valp, unsigned int *seen, unsigned int flag)
+{
+ float res;
+ int len;
+ char *end;
+
+ res = (float)strtod(str, &end);
+
+ len = end - str;
+
+ if (len > 0)
+ {
+ *valp = res;
+ *seen |= flag;
+ }
+ else
+ *valp = 0;
+
+ return len; /* length of number */
+}
+
+int scan_int(char *str, int *valp, unsigned int *seen, unsigned int flag)
+{
+ int res;
+ int len;
+ char *end;
+
+ res = (int)strtol(str, &end, 10);
+ len = end - str;
+
+ if (len > 0)
+ {
+ *valp = res;
+ *seen |= flag;
+ }
+ else
+ *valp = 0;
+
+ return len; /* length of number */
+}
+
+#ifdef TEST_MACHINE
+
+// Read and echo bytes.
+
+void comms_test()
+{
+ if (Serial.available() > 0)
+ Serial.print((char)Serial.read());
+}
+
+#endif
+
+
diff --git a/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/stepper_control.pde b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/stepper_control.pde
new file mode 100644
index 00000000..46040eb8
--- /dev/null
+++ b/trunk/reprap/firmware/Sanguino/GCode_Interpreter.old-version/stepper_control.pde
@@ -0,0 +1,466 @@
+// Yep, this is actually -*- c++ -*-
+
+//init our variables
+long max_delta;
+long x_counter;
+long y_counter;
+long z_counter;
+bool x_can_step;
+bool y_can_step;
+bool z_can_step;
+int milli_delay;
+
+#if INVERT_ENABLE_PINS == 1
+#define ENABLE_ON LOW
+#else
+#define ENABLE_ON HIGH
+#endif
+
+#define ENDSTOPS_MIN_ENABLED 1
+
+void init_steppers()
+{
+ //turn them off to start.
+#ifdef SANGUINO
+ disable_steppers();
+#endif
+
+ //init our points.
+ current_units.x = 0.0;
+ current_units.y = 0.0;
+ current_units.z = 0.0;
+ target_units.x = 0.0;
+ target_units.y = 0.0;
+ target_units.z = 0.0;
+
+ pinMode(X_STEP_PIN, OUTPUT);
+ pinMode(X_DIR_PIN, OUTPUT);
+ pinMode(Y_STEP_PIN, OUTPUT);
+ pinMode(Y_DIR_PIN, OUTPUT);
+ pinMode(Z_STEP_PIN, OUTPUT);
+ pinMode(Z_DIR_PIN, OUTPUT);
+
+#ifdef SANGUINO
+ pinMode(X_ENABLE_PIN, OUTPUT);
+ pinMode(Y_ENABLE_PIN, OUTPUT);
+ pinMode(Z_ENABLE_PIN, OUTPUT);
+#endif
+
+#if ENDSTOPS_MIN_ENABLED == 1
+ pinMode(X_MIN_PIN, INPUT);
+ pinMode(Y_MIN_PIN, INPUT);
+ pinMode(Z_MIN_PIN, INPUT);
+#endif
+#if ENDSTOPS_MAX_ENABLED == 1
+ pinMode(X_MAX_PIN, INPUT);
+ pinMode(Y_MAX_PIN, INPUT);
+ pinMode(Z_MAX_PIN, INPUT);
+#endif
+
+ //figure our stuff.
+ calculate_deltas();
+}
+
+void dda_move(long micro_delay)
+{
+ //turn on steppers to start moving =)
+#ifdef SANGUINO
+ enable_steppers();
+#endif
+
+ //figure out our deltas
+ max_delta = max(delta_steps.x, delta_steps.y);
+ max_delta = max(delta_steps.z, max_delta);
+
+ //init stuff.
+ long x_counter = -max_delta/2;
+ long y_counter = -max_delta/2;
+ long z_counter = -max_delta/2;
+
+ //our step flags
+ bool x_can_step = 0;
+ bool y_can_step = 0;
+ bool z_can_step = 0;
+
+ //how long do we delay for?
+ if (micro_delay >= 16383)
+ milli_delay = micro_delay / 1000;
+ else
+ milli_delay = 0;
+
+ //do our DDA line!
+ do
+ {
+ x_can_step = can_step(X_MIN_PIN, X_MAX_PIN, current_steps.x, target_steps.x, x_direction);
+ y_can_step = can_step(Y_MIN_PIN, Y_MAX_PIN, current_steps.y, target_steps.y, y_direction);
+ z_can_step = can_step(Z_MIN_PIN, Z_MAX_PIN, current_steps.z, target_steps.z, z_direction);
+
+ if (x_can_step)
+ {
+ x_counter += delta_steps.x;
+
+ if (x_counter > 0)
+ {
+ do_step(X_STEP_PIN);
+ x_counter -= max_delta;
+
+ if (x_direction)
+ current_steps.x++;
+ else
+ current_steps.x--;
+ }
+ }
+
+ if (y_can_step)
+ {
+ y_counter += delta_steps.y;
+
+ if (y_counter > 0)
+ {
+ do_step(Y_STEP_PIN);
+ y_counter -= max_delta;
+
+ if (y_direction)
+ current_steps.y++;
+ else
+ current_steps.y--;
+ }
+ }
+
+ if (z_can_step)
+ {
+ z_counter += delta_steps.z;
+
+ if (z_counter > 0)
+ {
+ do_step(Z_STEP_PIN);
+ z_counter -= max_delta;
+
+ if (z_direction)
+ current_steps.z++;
+ else
+ current_steps.z--;
+ }
+ }
+
+ //keep it hot =)
+ extruder_manage_temperature();
+
+ //wait for next step.
+ if (milli_delay > 0)
+ delay(milli_delay);
+ else
+ delayMicrosecondsInterruptible(micro_delay);
+ }
+ while (x_can_step || y_can_step || z_can_step);
+
+ //set our points to be the same
+ current_units.x = target_units.x;
+ current_units.y = target_units.y;
+ current_units.z = target_units.z;
+ calculate_deltas();
+}
+
+bool can_step(byte min_pin, byte max_pin, long current, long target, byte direction)
+{
+ //stop us if we're on target
+ if (target == current)
+ return false;
+#if ENDSTOPS_MIN_ENABLED == 1
+ //stop us if we're at home and still going
+ else if (read_switch(min_pin) && !direction)
+ return false;
+#endif
+#if ENDSTOPS_MAX_ENABLED == 1
+ //stop us if we're at max and still going
+ else if (read_switch(max_pin) && direction)
+ return false;
+#endif
+
+ //default to being able to step
+ return true;
+}
+
+void do_step(byte step_pin)
+{
+ digitalWrite(step_pin, HIGH);
+ delayMicroseconds(5);
+ digitalWrite(step_pin, LOW);
+}
+
+bool read_switch(byte pin)
+{
+ //dual read as crude debounce
+ #if ENDSTOPS_INVERTING == 1
+ return !digitalRead(pin) && !digitalRead(pin);
+ #else
+ return digitalRead(pin) && digitalRead(pin);
+ #endif
+}
+
+long to_steps(float steps_per_unit, float units)
+{
+ return steps_per_unit * units;
+}
+
+void set_target(float x, float y, float z)
+{
+ target_units.x = x;
+ target_units.y = y;
+ target_units.z = z;
+
+ calculate_deltas();
+}
+
+void set_position(float x, float y, float z)
+{
+ current_units.x = x;
+ current_units.y = y;
+ current_units.z = z;
+
+ calculate_deltas();
+}
+
+void calculate_deltas()
+{
+ //figure our deltas.
+ delta_units.x = abs(target_units.x - current_units.x);
+ delta_units.y = abs(target_units.y - current_units.y);
+ delta_units.z = abs(target_units.z - current_units.z);
+
+ //set our steps current, target, and delta
+ current_steps.x = to_steps(x_units, current_units.x);
+ current_steps.y = to_steps(y_units, current_units.y);
+ current_steps.z = to_steps(z_units, current_units.z);
+
+ target_steps.x = to_steps(x_units, target_units.x);
+ target_steps.y = to_steps(y_units, target_units.y);
+ target_steps.z = to_steps(z_units, target_units.z);
+
+ delta_steps.x = abs(target_steps.x - current_steps.x);
+ delta_steps.y = abs(target_steps.y - current_steps.y);
+ delta_steps.z = abs(target_steps.z - current_steps.z);
+
+ //what is our direction
+ x_direction = (target_units.x >= current_units.x);
+ y_direction = (target_units.y >= current_units.y);
+ z_direction = (target_units.z >= current_units.z);
+
+ //set our direction pins as well
+#if INVERT_X_DIR == 1
+ digitalWrite(X_DIR_PIN, !x_direction);
+#else
+ digitalWrite(X_DIR_PIN, x_direction);
+#endif
+#if INVERT_Y_DIR == 1
+ digitalWrite(Y_DIR_PIN, !y_direction);
+#else
+ digitalWrite(Y_DIR_PIN, y_direction);
+#endif
+#if INVERT_Z_DIR == 1
+ digitalWrite(Z_DIR_PIN, !z_direction);
+#else
+ digitalWrite(Z_DIR_PIN, z_direction);
+#endif
+}
+
+
+long calculate_feedrate_delay(float feedrate)
+{
+ //how long is our line length?
+ float distance = sqrt(delta_units.x*delta_units.x +
+ delta_units.y*delta_units.y +
+ delta_units.z*delta_units.z);
+ long master_steps = 0;
+
+ //find the dominant axis.
+ if (delta_steps.x > delta_steps.y)
+ {
+ if (delta_steps.z > delta_steps.x)
+ master_steps = delta_steps.z;
+ else
+ master_steps = delta_steps.x;
+ }
+ else
+ {
+ if (delta_steps.z > delta_steps.y)
+ master_steps = delta_steps.z;
+ else
+ master_steps = delta_steps.y;
+ }
+
+ //calculate delay between steps in microseconds. this is sort of tricky, but not too bad.
+ //the formula has been condensed to save space. here it is in english:
+ // (feedrate is in mm/minute)
+ // distance / feedrate * 60000000.0 = move duration in microseconds
+ // move duration / master_steps = time between steps for master axis.
+
+ return ((distance * 60000000.0) / feedrate) / master_steps;
+}
+
+long getMaxSpeed()
+{
+ if (delta_steps.z > 0)
+ return calculate_feedrate_delay(FAST_Z_FEEDRATE);
+ else
+ return calculate_feedrate_delay(FAST_XY_FEEDRATE);
+}
+
+#ifdef SANGUINO
+void enable_steppers()
+{
+ // Enable steppers only for axes which are moving
+ // taking account of the fact that some or all axes
+ // may share an enable line (check using macros at
+ // compile time to avoid needless code)
+ if ( target_units.x == current_units.x
+ #if X_ENABLE_PIN == Y_ENABLE_PIN
+ && target_units.y == current_units.y
+ #endif
+ #if X_ENABLE_PIN == Z_ENABLE_PIN
+ && target_units.z == current_units.z
+ #endif
+ )
+ digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
+ else
+ digitalWrite(X_ENABLE_PIN, ENABLE_ON);
+ if ( target_units.y == current_units.y
+ #if Y_ENABLE_PIN == X_ENABLE_PIN
+ && target_units.x == current_units.x
+ #endif
+ #if Y_ENABLE_PIN == Z_ENABLE_PIN
+ && target_units.z == current_units.z
+ #endif
+ )
+ digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
+ else
+ digitalWrite(Y_ENABLE_PIN, ENABLE_ON);
+ if ( target_units.z == current_units.z
+ #if Z_ENABLE_PIN == X_ENABLE_PIN
+ && target_units.x == current_units.x
+ #endif
+ #if Z_ENABLE_PIN == Y_ENABLE_PIN
+ && target_units.y == current_units.y
+ #endif
+ )
+ digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
+ else
+ digitalWrite(Z_ENABLE_PIN, ENABLE_ON);
+}
+
+void disable_steppers()
+{
+ //disable our steppers
+ digitalWrite(X_ENABLE_PIN, !ENABLE_ON);
+ digitalWrite(Y_ENABLE_PIN, !ENABLE_ON);
+ digitalWrite(Z_ENABLE_PIN, !ENABLE_ON);
+}
+#endif
+
+void delayMicrosecondsInterruptible(unsigned int us)
+{
+
+#if F_CPU >= 16000000L
+ // for the 16 MHz clock on most Arduino boards
+
+ // for a one-microsecond delay, simply return. the overhead
+ // of the function call yields a delay of approximately 1 1/8 us.
+ if (--us == 0)
+ return;
+
+ // the following loop takes a quarter of a microsecond (4 cycles)
+ // per iteration, so execute it four times for each microsecond of
+ // delay requested.
+ us <<= 2;
+
+ // account for the time taken in the preceeding commands.
+ us -= 2;
+#else
+ // for the 8 MHz internal clock on the ATmega168
+
+ // for a one- or two-microsecond delay, simply return. the overhead of
+ // the function calls takes more than two microseconds. can't just
+ // subtract two, since us is unsigned; we'd overflow.
+ if (--us == 0)
+ return;
+ if (--us == 0)
+ return;
+
+ // the following loop takes half of a microsecond (4 cycles)
+ // per iteration, so execute it twice for each microsecond of
+ // delay requested.
+ us <<= 1;
+
+ // partially compensate for the time taken by the preceeding commands.
+ // we can't subtract any more than this or we'd overflow w/ small delays.
+ us--;
+#endif
+
+ // busy wait
+ __asm__ __volatile__ (
+ "1: sbiw %0,1" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+}
+
+#ifdef TEST_MACHINE
+
+void X_motor_test()
+{
+ Serial.println("Moving X forward by 100 mm at half maximum speed.");
+ set_target(100, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+
+ Serial.println("Moving X back to the start.");
+ set_target(0, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+}
+
+void Y_motor_test()
+{
+
+ Serial.println("Moving Y forward by 100 mm at half maximum speed.");
+ set_target(0, 100, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+
+ Serial.println("Moving Y back to the start.");
+ set_target(0, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_XY_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+}
+
+void Z_motor_test()
+{
+ Serial.println("Moving Z down by 5 mm at half maximum speed.");
+ set_target(0, 0, 5);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_Z_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+
+ Serial.println("Moving Z back to the start.");
+ set_target(0, 0, 0);
+ enable_steppers();
+ dda_move(calculate_feedrate_delay(FAST_Z_FEEDRATE/2));
+
+ Serial.println("Pause for 2 seconds.");
+ delay(2000);
+}
+
+#endif
diff --git a/trunk/reprap/firmware/sketch_081010a/sketch_081010a.pde b/trunk/reprap/firmware/sketch_081010a/sketch_081010a.pde
index 2086374c..c7a058c6 100644
--- a/trunk/reprap/firmware/sketch_081010a/sketch_081010a.pde
+++ b/trunk/reprap/firmware/sketch_081010a/sketch_081010a.pde
@@ -1,20 +1,19 @@
#include <HardwareSerial.h>
-char* fp="12.345";
-char* end;
-float res=-1.123;
+char c;
+long count;
void setup()
{
Serial.begin(19200);
- Serial.println("start");
- // Uncomment next line to cause crash...
- res = (float)strtod(fp, &end);
- Serial.print(((int)(res*1000 + 0.5))/1000);
- Serial.print(".");
- Serial.println(((int)abs(res*1000 + 0.5))%1000);
+ Serial.println("Type a character: ");
+ while(!Serial.available());
+ c = Serial.read();
}
void loop()
{
+ Serial.println(count);
+ count++;
+ delay(1000);
}