diff --git a/GCodes.cpp b/GCodes.cpp
index f241a26..f2f8b1b 100644
--- a/GCodes.cpp
+++ b/GCodes.cpp
@@ -5,6 +5,10 @@ RepRapFirmware - G Codes
This class interprets G Codes from one or more sources, and calls the functions in Move, Heat etc
that drive the machine to do what the G Codes command.
+Most of the functions in here are designed not to wait, and they return a boolean. When you want them to do
+something, you call them. If they return false, the machine can't do what you want yet. So you go away
+and do something else. Then you try again. If they return true, the thing you wanted done has been done.
+
-----------------------------------------------------------------------------------------------------
Version 0.1
@@ -45,7 +49,6 @@ void GCodes::Init()
fileGCode->SetFinished(true);
serialGCode->SetFinished(true);
moveAvailable = false;
- // heatAvailable = false;
drivesRelative = true;
axesRelative = false;
checkEndStops = false;
@@ -59,9 +62,6 @@ void GCodes::Init()
homeY = false;
homeZ = false;
homeZFinalMove = false;
-// homeXQueued = false;
-// homeYQueued = false;
-// homeZQueued = false;
dwellWaiting = false;
stackPointer = 0;
selectedHead = -1;
@@ -71,7 +71,6 @@ void GCodes::Init()
zProbesSet = false;
probeCount = 0;
cannedCycleMoveCount = 0;
-// probeMoveQueued = false;
cannedCycleMoveQueued = false;
active = true;
dwellTime = platform->Time();
@@ -83,7 +82,15 @@ void GCodes::Spin()
return;
char b;
-
+
+ // Check each of the sources of G Codes (web, serial, and file) to
+ // see if what they are doing has been done. If it hasn't, return without
+ // looking at anything else.
+ //
+ // Note the order establishes a priority: web first, then serial, and file
+ // last. If file weren't last, then the others would never get a look in when
+ // a file was being printed.
+
if(!webGCode->Finished())
{
webGCode->SetFinished(ActOnGcode(webGCode));
@@ -102,6 +109,9 @@ void GCodes::Spin()
return;
}
+ // Now check if a G Code byte is available from each of the sources
+ // in the same order for the same reason.
+
if(webserver->GCodeAvailable())
{
if(webGCode->Put(webserver->ReadGCode()))
@@ -138,6 +148,11 @@ void GCodes::Diagnostics()
platform->Message(HOST_MESSAGE, "GCodes Diagnostics:\n");
}
+// The wait till everything's done function. If you need the machine to
+// be idle before you do something (for example homeing an axis, or shutting down) call this
+// until it returns true. As a side-effect it loads moveBuffer with the last
+// position and feedrate for you.
+
bool GCodes::AllMovesAreFinishedAndMoveBufferIsLoaded()
{
// Last one gone?
@@ -159,6 +174,9 @@ bool GCodes::AllMovesAreFinishedAndMoveBufferIsLoaded()
return true;
}
+// Save (some of) the state of the machine for recovery in the future.
+// Call repeatedly till it returns true.
+
bool GCodes::Push()
{
if(stackPointer >= STACK)
@@ -178,6 +196,8 @@ bool GCodes::Push()
return true;
}
+// Recover a saved state. Call repeatedly till it returns true.
+
bool GCodes::Pop()
{
if(stackPointer <= 0)
@@ -209,6 +229,7 @@ bool GCodes::Pop()
return true;
}
+// This function is called for a G Code that makes a move.
// If the Move class can't receive the move (i.e. things have to wait)
// this returns false, otherwise true.
@@ -245,26 +266,24 @@ bool GCodes::ReadMove(float* m, bool& ce)
return true;
}
-
-bool GCodes::ReadHeat(float* h)
-{
-
-}
-
// To execute any move, call this until it returns true.
-// false entries in action[] will be ignored.
+// moveToDo[] entries corresponding with false entries in action[] will
+// be ignored. Recall that moveToDo[DRIVES] should contain the feedrate
+// you want (if action[DRIVES] is true).
bool GCodes::DoCannedCycleMove(float moveToDo[], bool action[], bool ce)
{
+ // Is the move already running?
+
if(cannedCycleMoveQueued)
- {
- if(!Pop()) // Wait for the move to finish
+ { // Yes.
+ if(!Pop()) // Wait for the move to finish then restore the state
return false;
cannedCycleMoveQueued = false;
return true;
} else
- {
- if(!Push()) // Wait for the RepRap to finish whatever it was doing
+ { // No.
+ if(!Push()) // Wait for the RepRap to finish whatever it was doing and save it's state
return false;
for(int8_t drive = 0; drive <= DRIVES; drive++)
{
@@ -278,6 +297,9 @@ bool GCodes::DoCannedCycleMove(float moveToDo[], bool action[], bool ce)
return false;
}
+// Home one or more of the axes. Which ones are decided by the
+// booleans homeX, homeY and homeZ.
+
bool GCodes::DoHome()
{
// Treat more or less like any other move
@@ -405,6 +427,10 @@ bool GCodes::DoSingleZProbe()
}
}
+// This probes multiple points on the bed (usually three in a
+// triangle), then sets the bed transformation to compensate
+// for the bed not quite being the plane Z = 0.
+
bool GCodes::DoMultipleZProbe()
{
if(DoSingleZProbe())
@@ -420,6 +446,10 @@ bool GCodes::DoMultipleZProbe()
return false;
}
+// This returns the (X, Y) points to probe the bed at probe point count. When probing,
+// it returns false. If called after probing has ended it returns true, and the Z coordinate
+// probed is also returned.
+
bool GCodes::GetProbeCoordinates(int count, float& x, float& y, float& z)
{
switch(count)
@@ -444,6 +474,10 @@ bool GCodes::GetProbeCoordinates(int count, float& x, float& y, float& z)
return zProbesSet;
}
+// Return the current coordinates as a printable string. Coordinates
+// are updated at the end of each movement, so this won't tell you
+// where you are mid-movement.
+
// FIXME - needs to deal with multiple extruders
char* GCodes::GetCurrentCoordinates()
@@ -455,6 +489,7 @@ char* GCodes::GetCurrentCoordinates()
return scratchString;
}
+// Set up a file to print, but don't print it yet.
void GCodes::QueueFileToPrint(char* fileName)
{
@@ -463,6 +498,9 @@ void GCodes::QueueFileToPrint(char* fileName)
platform->Message(HOST_MESSAGE, "GCode file not found\n");
}
+// Run the configuration G Code file to set up the machine. Usually just called once
+// on re-boot.
+
void GCodes::RunConfigurationGCodes()
{
fileToPrint = platform->GetFileStore(platform->GetSysDir(), platform->GetConfigFile(), false);
@@ -477,11 +515,11 @@ void GCodes::RunConfigurationGCodes()
// Function to handle dwell delays. Return true for
-// Dwell finished, false otherwise.
+// dwell finished, false otherwise.
bool GCodes::DoDwell(GCodeBuffer *gb)
{
- unsigned long dwell;
+ float dwell;
if(gb->Seen('P'))
dwell = 0.001*(float)gb->GetLValue(); // P values are in milliseconds; we need seconds
@@ -493,7 +531,7 @@ bool GCodes::DoDwell(GCodeBuffer *gb)
if(!reprap.GetMove()->AllMovesAreFinished())
return false;
- // Are we already in a dwell?
+ // Are we already in the dwell?
if(dwellWaiting)
{
@@ -513,6 +551,9 @@ bool GCodes::DoDwell(GCodeBuffer *gb)
return false;
}
+// Set distance offsets and working and standby temperatures for
+// an extruder. I.e. handle a G10.
+
bool GCodes::SetOffsets(GCodeBuffer *gb)
{
int8_t head;
@@ -572,6 +613,8 @@ void GCodes::LoadMoveBufferFromGCode(GCodeBuffer *gb)
moveBuffer[DRIVES] = gFeedRate; // We always set it, as Move may have modified the last one.
}
+// This sets positions. I.e. it handles G92.
+
bool GCodes::SetPositions(GCodeBuffer *gb)
{
if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
@@ -584,16 +627,26 @@ bool GCodes::SetPositions(GCodeBuffer *gb)
return true;
}
-void GCodes::DisableDrives()
+// Does what it says.
+
+bool GCodes::DisableDrives()
{
+ if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
+ return false;
for(int8_t drive = 0; drive < DRIVES; drive++)
platform->Disable(drive);
+ return true;
}
-void GCodes::StandbyHeaters()
+// Does what it says.
+
+bool GCodes::StandbyHeaters()
{
+ if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
+ return false;
for(int8_t heater = 0; heater < DRIVES; heater++)
reprap.GetHeat()->Standby(heater);
+ return true;
}
// If the GCode to act on is completed, this returns true,
@@ -649,7 +702,7 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
result = DoHome();
break;
- case 31:
+ case 31: // Return the probe value, or set probe variables
if(gb->Seen(gCodeLetters[Z_AXIS]))
{
platform->SetZProbeStopHeight(gb->GetFValue());
@@ -674,8 +727,8 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
break;
case 91: // Relative coordinates
- drivesRelative = true;
- axesRelative = true;
+ drivesRelative = true; // Non-axis movements (i.e. extruders)
+ axesRelative = true; // Axis movements (i.e. X, Y and Z)
break;
case 92: // Set position
@@ -697,16 +750,19 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
{
case 0: // Stop
case 1: // Sleep
- if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
+ if(fileBeingPrinted != NULL)
+ {
+ fileToPrint = fileBeingPrinted;
+ fileBeingPrinted = NULL;
+ }
+ if(!DisableDrives())
return false;
- DisableDrives();
- StandbyHeaters();
+ if(!StandbyHeaters())
+ return false; // Should never happen
break;
case 18: // Motors off
- if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
- return false;
- DisableDrives();
+ result = DisableDrives();
break;
case 20: // Deprecated...
@@ -744,6 +800,9 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
break;
+ case 85: // Set inactive time
+ break;
+
case 92: // Set steps/mm for each axis
if(reprap.debug())
platform->GetLine()->Write("Steps/mm: ");
@@ -786,13 +845,10 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
case 107: // Fan off
platform->Message(HOST_MESSAGE, "Fan off received\n");
break;
-
- case 116: // Wait for everything
- if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
- return false;
- result = reprap.GetHeat()->AllHeatersAtSetTemperatures();
- break;
+ case 112: // Emergency stop
+ break;
+
case 111: // Debug level
if(gb->Seen('S'))
reprap.debug(gb->GetIValue());
@@ -808,6 +864,12 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
result = false;
break;
+ case 116: // Wait for everything, especially set temperatures
+ if(!AllMovesAreFinishedAndMoveBufferIsLoaded())
+ return false;
+ result = reprap.GetHeat()->AllHeatersAtSetTemperatures();
+ break;
+
case 120:
result = Push();
break;
@@ -828,6 +890,9 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
platform->Message(HOST_MESSAGE, "M127 - valves not yet implemented\n");
break;
+ case 135: // Set PID sample interval
+ break;
+
case 140: // Set bed temperature
if(gb->Seen('S'))
{
@@ -851,11 +916,11 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
}else{
value = -1;
}
- float accel = platform->Acceleration(i, value);
+ platform->SetAcceleration(i, value);
if(reprap.debug())
{
platform->GetLine()->Write(gCodeLetters[i]);
- platform->GetLine()->Write(ftoa(NULL,accel,1));
+ platform->GetLine()->Write(ftoa(NULL,platform->Acceleration(i),1));
platform->GetLine()->Write(" ");
}
}
@@ -863,12 +928,42 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
platform->GetLine()->Write("\n");
break;
- case 906: // Motor currents
+ case 203: // Set maximum feedrates
+ break;
+
+ case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
+ break;
+
+ case 208: // Set maximum axis lengths
+ break;
+
+ case 210: // Set homing feedrates
+ break;
+
+ case 301: // Set PID values
+ break;
+
+ case 302: // Allow cold extrudes
+ break;
+
+ case 304: // Set thermistor parameters
+ break;
+
+ case 500: // Set password
+ break;
+
+ case 501: // Set machine name
+ break;
+
+ case 502: // Set IP address
+ break;
+
+ case 906: // Set Motor currents
for(uint8_t i = 0; i < DRIVES; i++)
{
if(gb->Seen(gCodeLetters[i]))
{
- value = gb->GetFValue();
+ value = gb->GetFValue(); // mA
platform->SetMotorCurrent(i, value);
}
}
@@ -892,7 +987,7 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
for(int8_t i = AXES; i < DRIVES; i++)
{
if(selectedHead == i - AXES)
- reprap.GetHeat()->Standby(selectedHead + 1); // 0 is the Bed
+ reprap.GetHeat()->Standby(selectedHead + 1); // + 1 because 0 is the Bed
}
for(int8_t i = AXES; i < DRIVES; i++)
{
@@ -923,6 +1018,8 @@ bool GCodes::ActOnGcode(GCodeBuffer *gb)
//*************************************************************************************
+// This class stores a single G Code and provides functions to allow it to be parsed
+
GCodeBuffer::GCodeBuffer(Platform* p, char* id)
{
platform = p;
@@ -936,6 +1033,9 @@ void GCodeBuffer::Init()
inComment = false;
}
+// Add a byte to the code being assembled. If false is returned, the code is
+// not yet complete. If true, it is complete and ready to be acted upon.
+
bool GCodeBuffer::Put(char c)
{
bool result = false;
@@ -987,7 +1087,7 @@ bool GCodeBuffer::Seen(char c)
return false;
}
-// Get a float after a G Code letter
+// Get a float after a G Code letter found by a call to Seen()
float GCodeBuffer::GetFValue()
{
@@ -1007,6 +1107,10 @@ float GCodeBuffer::GetFValue()
// be -1. It absorbs "M/Gnnn " (including the space) from the
// start and returns a pointer to the next location.
+// It would be nice if the string was preceded by (say) 'S', but
+// for legacy compatibility (M code to queue a file) that can't
+// be done.
+
char* GCodeBuffer::GetString()
{
readPointer = 0;
diff --git a/GCodes.h b/GCodes.h
index 57758eb..0b03f1e 100644
--- a/GCodes.h
+++ b/GCodes.h
@@ -26,7 +26,7 @@ Licence: GPL
#define GCODE_LETTERS { 'X', 'Y', 'Z', 'E', 'F' } // The drives and feedrate in a GCode
-// Small class to hold an individual GCode
+// Small class to hold an individual GCode and provide functions to allow it to be parsed
class GCodeBuffer
{
@@ -67,7 +67,6 @@ class GCodes
void Exit();
void RunConfigurationGCodes();
bool ReadMove(float* m, bool& ce);
- bool ReadHeat(float* h);
void QueueFileToPrint(char* fileName);
bool GetProbeCoordinates(int count, float& x, float& y, float& z);
char* GetCurrentCoordinates();
@@ -90,8 +89,8 @@ class GCodes
bool NoHome();
bool Push();
bool Pop();
- void DisableDrives();
- void StandbyHeaters();
+ bool DisableDrives();
+ bool StandbyHeaters();
int8_t Heater(int8_t head);
Platform* platform;
diff --git a/Move.cpp b/Move.cpp
index 58b71ff..ee5423e 100644
--- a/Move.cpp
+++ b/Move.cpp
@@ -45,7 +45,7 @@ Move::Move(Platform* p, GCodes* g)
lookAheadRingGetPointer = new LookAhead(this, platform, lookAheadRingGetPointer);
lookAheadRingAddPointer->next = lookAheadRingGetPointer;
- // Set the lookahead backwards pointers
+ // Set the lookahead backwards pointers (some oxymoron, surely?)
lookAheadRingGetPointer = lookAheadRingAddPointer;
for(i = 0; i <= LOOK_AHEAD_RING_LENGTH; i++)
diff --git a/Platform.cpp b/Platform.cpp
index 6809839..b9f4b03 100644
--- a/Platform.cpp
+++ b/Platform.cpp
@@ -64,7 +64,7 @@ void Platform::Init()
line->Init();
- network->Init();
+ //network->Init();
massStorage->Init();
@@ -93,15 +93,10 @@ void Platform::Init()
potWipes = POT_WIPES;
senseResistor = SENSE_RESISTOR;
maxStepperDigipotVoltage = MAX_STEPPER_DIGIPOT_VOLTAGE;
-// zProbeGradient = Z_PROBE_GRADIENT;
-// zProbeConstant = Z_PROBE_CONSTANT;
zProbePin = Z_PROBE_PIN;
zProbeCount = 0;
zProbeSum = 0;
zProbeValue = 0;
-// zProbeStarting = false;
-// zProbeHigh = Z_PROBE_HIGH;
-// zProbeLow = Z_PROBE_LOW;
zProbeADValue = Z_PROBE_AD_VALUE;
zProbeStopHeight = Z_PROBE_STOP_HEIGHT;
@@ -197,6 +192,11 @@ void Platform::Init()
active = true;
}
+void Platform::StartNetwork()
+{
+ network->Init();
+}
+
//int zcount; // NASTY - FIX ME
diff --git a/Platform.h b/Platform.h
index 57d5ab2..c2f393f 100644
--- a/Platform.h
+++ b/Platform.h
@@ -151,24 +151,6 @@ Licence: GPL
// Networking
-// Enter a MAC address and IP address for your controller below.
-// The IP address will be dependent on your local network:
-//#define MAC { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
-//#define MAC_BYTES 6
-//
-//#define IP0 192
-//#define IP1 168
-//#define IP2 1
-//#define IP3 14
-//
-//#define IP_BYTES 4
-
-//#define ETH_B_PIN 10
-
-// port 80 is default for HTTP
-
-//#define HTTP_PORT 80
-
// Seconds to wait after serving a page
#define CLIENT_CLOSE_DELAY 0.002
@@ -425,6 +407,7 @@ class Platform
MassStorage* GetMassStorage();
FileStore* GetFileStore(char* directory, char* fileName, bool write);
+ void StartNetwork();
char* GetWebDir(); // Where the htm etc files are
char* GetGCodeDir(); // Where the gcodes are
char* GetSysDir(); // Where the system files are
@@ -442,7 +425,8 @@ class Platform
void SetMotorCurrent(byte drive, float current);
float DriveStepsPerUnit(int8_t drive);
void SetDriveStepsPerUnit(int8_t drive, float value);
- float Acceleration(int8_t drive, float value);
+ float Acceleration(int8_t drive);
+ void SetAcceleration(int8_t drive, float value);
float MaxFeedrate(int8_t drive);
float InstantDv(int8_t drive);
float HomeFeedRate(int8_t drive);
@@ -458,10 +442,6 @@ class Platform
float GetTemperature(int8_t heater); // Result is in degrees celsius
void SetHeater(int8_t heater, const float& power); // power is a fraction in [0,1]
- //void SetStandbyTemperature(int8_t heater, const float& t);
- //void SetActiveTemperature(int8_t heater, const float& t);
- //float StandbyTemperature(int8_t heater);
- //float ActiveTemperature(int8_t heater);
float PidKp(int8_t heater);
float PidKi(int8_t heater);
float PidKd(int8_t heater);
@@ -631,11 +611,14 @@ inline void Platform::SetDriveStepsPerUnit(int8_t drive, float value)
driveStepsPerUnit[drive] = value;
}
-inline float Platform::Acceleration(int8_t drive, float value = -1)
+inline float Platform::Acceleration(int8_t drive)
{
- if(drive >= 0 && drive < DRIVES && value > 0)
- accelerations[drive] = value;
- return accelerations[drive];
+ return accelerations[drive];
+}
+
+inline void Platform::SetAcceleration(int8_t drive, float value)
+{
+ accelerations[drive] = value;
}
inline float Platform::InstantDv(int8_t drive)
diff --git a/RepRapFirmware.cpp b/RepRapFirmware.cpp
index 5576d33..40f8ebf 100644
--- a/RepRapFirmware.cpp
+++ b/RepRapFirmware.cpp
@@ -177,6 +177,7 @@ void RepRap::Init()
heat->Init();
active = true;
gCodes->RunConfigurationGCodes();
+ platform->StartNetwork(); // Need to do this hare, as the configuration GCodes may set IP address etc.
platform->Message(HOST_MESSAGE, "RepRapPro RepRap Firmware (Re)Started\n");
// platform->Message(HOST_MESSAGE, "Free memory: ");
// sprintf(scratchString,"%d\n",platform->GetFreeMemory());
diff --git a/SD-image/www/reprap.htm b/SD-image/www/reprap.htm
index 6294c7d..50ad346 100644
--- a/SD-image/www/reprap.htm
+++ b/SD-image/www/reprap.htm
@@ -288,10 +288,36 @@ Click a file to