File upload + other improvements
Added new request code rr_data for file uploading, and made other changes to improve file upload speed. Implemented S parameter to M208 command, to allow the negative limits of axes to be set. Also reports current limits of no X/Y/Z parameter. Reduced max reported free buffer size to 950 bytes to avoid problems with file upload from Windows 8.1.
This commit is contained in:
parent
5fe612dd79
commit
75829fcaad
13 changed files with 219 additions and 167 deletions
|
@ -24,8 +24,8 @@ Licence: GPL
|
|||
#define CONFIGURATION_H
|
||||
|
||||
#define NAME "RepRapFirmware"
|
||||
#define VERSION "0.59a-dc42"
|
||||
#define DATE "2014-05-14"
|
||||
#define VERSION "0.59b-dc42"
|
||||
#define DATE "2014-05-16"
|
||||
#define LAST_AUTHOR "dc42"
|
||||
|
||||
// Other firmware that we might switch to be compatible with.
|
||||
|
|
142
GCodes.cpp
142
GCodes.cpp
|
@ -97,7 +97,7 @@ void GCodes::Reset()
|
|||
gFeedRate = platform->MaxFeedrate(Z_AXIS); // Typically the slowest
|
||||
speedFactor = 1.0/60.0; // default is just to convert from mm/minute to mm/second
|
||||
extrusionFactor = 1.0;
|
||||
|
||||
writingWebFile = false;
|
||||
}
|
||||
|
||||
void GCodes::doFilePrint(GCodeBuffer* gb)
|
||||
|
@ -167,21 +167,32 @@ void GCodes::Spin()
|
|||
do
|
||||
{
|
||||
char b = webserver->ReadGCode();
|
||||
if (webGCode->Put(b))
|
||||
if (webGCode->WritingFileDirectory() == platform->GetWebDir())
|
||||
{
|
||||
// we have a complete gcode
|
||||
if (webGCode->WritingFileDirectory() != NULL)
|
||||
if (b == 0)
|
||||
{
|
||||
WriteGCodeToFile(webGCode);
|
||||
b = '\n'; // webserver replaces newline by null
|
||||
}
|
||||
else
|
||||
WriteHTMLToFile(b, webGCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (webGCode->Put(b))
|
||||
{
|
||||
webGCode->SetFinished(ActOnGcode(webGCode));
|
||||
// we have a complete gcode
|
||||
if (webGCode->WritingFileDirectory() != NULL)
|
||||
{
|
||||
WriteGCodeToFile(webGCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
webGCode->SetFinished(ActOnGcode(webGCode));
|
||||
}
|
||||
break; // stop after receiving a complete gcode in case we haven't finished processing it
|
||||
}
|
||||
break; // stop after receiving a complete gcode in case we haven't finished processing it
|
||||
}
|
||||
++i;
|
||||
} while (i < 16 && webserver->GCodeAvailable());
|
||||
} while (i < 50 && webserver->GCodeAvailable());
|
||||
platform->ClassReport("GCodes", longWait);
|
||||
return;
|
||||
}
|
||||
|
@ -343,13 +354,13 @@ void GCodes::LoadMoveBufferFromGCode(GCodeBuffer *gb, bool doingG92, bool applyL
|
|||
}
|
||||
if (applyLimits && i < 2 && axisIsHomed[i] && !doingG92) // limit X and Y moves unless doing G92
|
||||
{
|
||||
if (moveArg < 0.0)
|
||||
if (moveArg < platform->AxisMinimum(i))
|
||||
{
|
||||
moveArg = 0.0;
|
||||
moveArg = platform->AxisMinimum(i);
|
||||
}
|
||||
else if (moveArg > platform->AxisLength(i))
|
||||
else if (moveArg > platform->AxisMaximum(i))
|
||||
{
|
||||
moveArg = platform->AxisLength(i);
|
||||
moveArg = platform->AxisMaximum(i);
|
||||
}
|
||||
}
|
||||
moveBuffer[i] = moveArg;
|
||||
|
@ -723,7 +734,7 @@ bool GCodes::DoSingleZProbeAtPoint()
|
|||
return false;
|
||||
|
||||
case 2: // Probe the bed
|
||||
moveToDo[Z_AXIS] = -2.0 * platform->AxisLength(Z_AXIS);
|
||||
moveToDo[Z_AXIS] = -2.0 * platform->AxisMaximum(Z_AXIS);
|
||||
activeDrive[Z_AXIS] = true;
|
||||
moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS);
|
||||
activeDrive[DRIVES] = true;
|
||||
|
@ -771,7 +782,7 @@ bool GCodes::DoSingleZProbe()
|
|||
return false;
|
||||
|
||||
case 1:
|
||||
moveToDo[Z_AXIS] = -1.1 * platform->AxisLength(Z_AXIS);
|
||||
moveToDo[Z_AXIS] = -1.1 * platform->AxisTotalLength(Z_AXIS);
|
||||
activeDrive[Z_AXIS] = true;
|
||||
moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS);
|
||||
activeDrive[DRIVES] = true;
|
||||
|
@ -980,16 +991,20 @@ bool GCodes::OpenFileToWrite(const char* directory, const char* fileName, GCodeB
|
|||
|
||||
void GCodes::WriteHTMLToFile(char b, GCodeBuffer *gb)
|
||||
{
|
||||
char reply[1];
|
||||
reply[0] = 0;
|
||||
|
||||
if (fileBeingWritten == NULL)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Attempt to write to a null file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fileBeingWritten->Write(b);
|
||||
if (eofStringCounter != 0 && b != eofString[eofStringCounter])
|
||||
{
|
||||
for (size_t i = 0; i < eofStringCounter; ++i)
|
||||
{
|
||||
fileBeingWritten->Write(eofString[i]);
|
||||
}
|
||||
eofStringCounter = 0;
|
||||
}
|
||||
|
||||
if (b == eofString[eofStringCounter])
|
||||
{
|
||||
|
@ -999,22 +1014,19 @@ void GCodes::WriteHTMLToFile(char b, GCodeBuffer *gb)
|
|||
fileBeingWritten->Close();
|
||||
fileBeingWritten = NULL;
|
||||
gb->SetWritingFileDirectory(NULL);
|
||||
char* r = reply;
|
||||
if (platform->Emulating() == marlin)
|
||||
r = "Done saving file.";
|
||||
const char* r = (platform->Emulating() == marlin) ? "Done saving file." : "";
|
||||
HandleReply(false, gb == serialGCode, r, 'M', 560, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
eofStringCounter = 0;
|
||||
{
|
||||
fileBeingWritten->Write(b);
|
||||
}
|
||||
}
|
||||
|
||||
void GCodes::WriteGCodeToFile(GCodeBuffer *gb)
|
||||
{
|
||||
char reply[1];
|
||||
reply[0] = 0;
|
||||
|
||||
if (fileBeingWritten == NULL)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Attempt to write to a null file.\n");
|
||||
|
@ -1030,9 +1042,7 @@ void GCodes::WriteGCodeToFile(GCodeBuffer *gb)
|
|||
fileBeingWritten->Close();
|
||||
fileBeingWritten = NULL;
|
||||
gb->SetWritingFileDirectory(NULL);
|
||||
char* r = reply;
|
||||
if (platform->Emulating() == marlin)
|
||||
r = "Done saving file.";
|
||||
const char* r = (platform->Emulating() == marlin) ? "Done saving file." : "";
|
||||
HandleReply(false, gb == serialGCode, r, 'M', 29, false);
|
||||
return;
|
||||
}
|
||||
|
@ -1055,7 +1065,7 @@ void GCodes::WriteGCodeToFile(GCodeBuffer *gb)
|
|||
|
||||
fileBeingWritten->Write(gb->Buffer());
|
||||
fileBeingWritten->Write('\n');
|
||||
HandleReply(false, gb == serialGCode, reply, 'G', 1, false);
|
||||
HandleReply(false, gb == serialGCode, "", 'G', 1, false);
|
||||
}
|
||||
|
||||
// Set up a file to print, but don't print it yet.
|
||||
|
@ -1726,9 +1736,9 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
reprap.GetMove()->SetStepHypotenuse();
|
||||
if (!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Steps/mm: X: %d, Y: %d, Z: %d, E: %d",
|
||||
(int) platform->DriveStepsPerUnit(X_AXIS), (int) platform->DriveStepsPerUnit(Y_AXIS),
|
||||
(int) platform->DriveStepsPerUnit(Z_AXIS), (int) platform->DriveStepsPerUnit(AXES)); // FIXME - needs to do multiple extruders
|
||||
snprintf(reply, STRING_LENGTH, "Steps/mm: X:%f, Y:%f, Z:%f, E:%f",
|
||||
platform->DriveStepsPerUnit(X_AXIS), platform->DriveStepsPerUnit(Y_AXIS),
|
||||
platform->DriveStepsPerUnit(Z_AXIS), platform->DriveStepsPerUnit(AXES)); // FIXME - needs to do multiple extruders
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1910,13 +1920,43 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
result = OffsetAxes(gb);
|
||||
break;
|
||||
|
||||
case 208: // Set maximum axis lengths
|
||||
for (int8_t axis = 0; axis < AXES; axis++)
|
||||
case 208: // Set maximum axis lengths. If there is an S parameter with value 1 then we set the min value, alse we set the max value.
|
||||
{
|
||||
if (gb->Seen(gCodeLetters[axis]))
|
||||
bool setMin;
|
||||
if (gb->Seen('S'))
|
||||
{
|
||||
float value = gb->GetFValue() * distanceScale;
|
||||
platform->SetAxisLength(axis, value);
|
||||
setMin = (gb->GetIValue() == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
setMin = false;
|
||||
}
|
||||
|
||||
bool setSomething = false;
|
||||
for (int8_t axis = 0; axis < AXES; axis++)
|
||||
{
|
||||
if (gb->Seen(gCodeLetters[axis]))
|
||||
{
|
||||
float value = gb->GetFValue() * distanceScale;
|
||||
if (setMin)
|
||||
{
|
||||
platform->SetAxisMinimum(axis, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
platform->SetAxisMaximum(axis, value);
|
||||
}
|
||||
setSomething = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!setSomething)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "X:%.1f Y:%.1f Z:%.1f",
|
||||
(setMin) ? platform->AxisMinimum(X_AXIS) : platform->AxisMaximum(X_AXIS),
|
||||
(setMin) ? platform->AxisMinimum(Y_AXIS) : platform->AxisMaximum(Y_AXIS),
|
||||
(setMin) ? platform->AxisMinimum(Z_AXIS) : platform->AxisMaximum(Z_AXIS)
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2042,7 +2082,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
break;
|
||||
|
||||
case 559: // Upload config.g
|
||||
case 559: // Upload config.g or another gcode file to put in the sys directory
|
||||
{
|
||||
const char* str;
|
||||
if (gb->Seen('P'))
|
||||
|
@ -2066,12 +2106,21 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
break;
|
||||
|
||||
case 560: // Upload reprap.htm
|
||||
case 560: // Upload reprap.htm or another web interface file
|
||||
{
|
||||
const char* str = INDEX_PAGE;
|
||||
const char* str;
|
||||
if (gb->Seen('P'))
|
||||
{
|
||||
str = gb->GetString();
|
||||
}
|
||||
else
|
||||
{
|
||||
str = INDEX_PAGE;
|
||||
}
|
||||
bool ok = OpenFileToWrite(platform->GetWebDir(), str, gb);
|
||||
if (ok)
|
||||
{
|
||||
writingWebFile = true;
|
||||
snprintf(reply, STRING_LENGTH, "Writing to file: %s", str);
|
||||
}
|
||||
else
|
||||
|
@ -2227,7 +2276,9 @@ bool GCodeBuffer::Put(char c)
|
|||
gcodeBuffer[gcodePointer] = c;
|
||||
|
||||
if (c == ';')
|
||||
{
|
||||
inComment = true;
|
||||
}
|
||||
|
||||
if (c == '\n' || !c)
|
||||
{
|
||||
|
@ -2308,11 +2359,12 @@ bool GCodeBuffer::Put(char c)
|
|||
bool GCodeBuffer::Seen(char c)
|
||||
{
|
||||
readPointer = 0;
|
||||
while (gcodeBuffer[readPointer])
|
||||
for (;;)
|
||||
{
|
||||
if (gcodeBuffer[readPointer] == c)
|
||||
return true;
|
||||
readPointer++;
|
||||
char b = gcodeBuffer[readPointer];
|
||||
if (b == 0 || b == ';') break;
|
||||
if (b == c) return true;
|
||||
++readPointer;
|
||||
}
|
||||
readPointer = -1;
|
||||
return false;
|
||||
|
|
1
GCodes.h
1
GCodes.h
|
@ -238,6 +238,7 @@ class GCodes
|
|||
bool coolingInverted;
|
||||
float speedFactor; // speed factor, including the conversion from mm/min to mm/sec, normally 1/60
|
||||
float extrusionFactor; // extrusion factor, normally 1.0
|
||||
bool writingWebFile;
|
||||
};
|
||||
|
||||
//*****************************************************************************************************
|
||||
|
|
6
Move.cpp
6
Move.cpp
|
@ -112,13 +112,13 @@ void Move::Init()
|
|||
|
||||
for(uint8_t point = 0; point < NUMBER_OF_PROBE_POINTS; point++)
|
||||
{
|
||||
xBedProbePoints[point] = (0.3 + 0.6*(float)(point%2))*platform->AxisLength(X_AXIS);
|
||||
yBedProbePoints[point] = (0.0 + 0.9*(float)(point/2))*platform->AxisLength(Y_AXIS);
|
||||
xBedProbePoints[point] = (0.3 + 0.6*(float)(point%2))*platform->AxisMaximum(X_AXIS);
|
||||
yBedProbePoints[point] = (0.0 + 0.9*(float)(point/2))*platform->AxisMaximum(Y_AXIS);
|
||||
zBedProbePoints[point] = 0.0;
|
||||
probePointSet[point] = unset;
|
||||
}
|
||||
|
||||
xRectangle = 1.0/(0.8*platform->AxisLength(X_AXIS));
|
||||
xRectangle = 1.0/(0.8*platform->AxisMaximum(X_AXIS));
|
||||
yRectangle = xRectangle;
|
||||
|
||||
secondDegreeCompensation = false;
|
||||
|
|
6
Move.h
6
Move.h
|
@ -540,7 +540,7 @@ inline float Move::SecondDegreeTransformZ(float x, float y) const
|
|||
|
||||
inline void Move::HitLowStop(int8_t drive, LookAhead* la, DDA* hitDDA)
|
||||
{
|
||||
float hitPoint = 0.0;
|
||||
float hitPoint = platform->AxisMinimum(drive);
|
||||
if(drive == Z_AXIS)
|
||||
{
|
||||
if(zProbing)
|
||||
|
@ -558,7 +558,7 @@ inline void Move::HitLowStop(int8_t drive, LookAhead* la, DDA* hitDDA)
|
|||
// Z axis has not yet been homed, so treat this probe as a homing command
|
||||
la->SetDriveCoordinateAndZeroEndSpeed(platform->ZProbeStopHeight(), drive);
|
||||
gCodes->SetAxisIsHomed(drive);
|
||||
lastZHit = 0.0;
|
||||
lastZHit = hitPoint;
|
||||
}
|
||||
return;
|
||||
} else
|
||||
|
@ -578,7 +578,7 @@ inline void Move::HitLowStop(int8_t drive, LookAhead* la, DDA* hitDDA)
|
|||
|
||||
inline void Move::HitHighStop(int8_t drive, LookAhead* la, DDA* hitDDA)
|
||||
{
|
||||
la->SetDriveCoordinateAndZeroEndSpeed(platform->AxisLength(drive), drive);
|
||||
la->SetDriveCoordinateAndZeroEndSpeed(platform->AxisMaximum(drive), drive);
|
||||
gCodes->SetAxisIsHomed(drive);
|
||||
}
|
||||
|
||||
|
|
65
Network.cpp
65
Network.cpp
|
@ -397,6 +397,8 @@ void Network::Spin()
|
|||
AppendTransaction(&freeTransactions, r);
|
||||
}
|
||||
}
|
||||
|
||||
ethernet_task(); // call this again (attempt to speed up file uploading)
|
||||
}
|
||||
else if (establish_ethernet_link())
|
||||
{
|
||||
|
@ -406,48 +408,6 @@ void Network::Spin()
|
|||
}
|
||||
}
|
||||
|
||||
bool Network::HaveData() const
|
||||
{
|
||||
return active && readyTransactions != NULL;
|
||||
}
|
||||
|
||||
bool Network::Read(char& b)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
return readyTransactions->Read(b);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Network::Write(char b)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
readyTransactions->Write(b);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::Write(const char* s)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
readyTransactions->Write(s);
|
||||
}
|
||||
}
|
||||
|
||||
// Write formatted data to the output buffer
|
||||
void Network::Printf(const char* fmt, ...)
|
||||
{
|
||||
if (readyTransactions != NULL)
|
||||
{
|
||||
va_list p;
|
||||
va_start(p, fmt);
|
||||
readyTransactions->Vprintf(fmt, p);
|
||||
va_end(p);
|
||||
}
|
||||
}
|
||||
|
||||
void Network::SentPacketAcknowledged(HttpState *hs)
|
||||
{
|
||||
RequestState *r = FindHs(&writingTransactions, hs);
|
||||
|
@ -584,20 +544,6 @@ void RequestState::Set(const char* d, int l, void* pc, HttpState* h)
|
|||
fileBeingSent = NULL;
|
||||
}
|
||||
|
||||
// Webserver calls this to read bytes that have come in from the network
|
||||
|
||||
bool RequestState::Read(char& b)
|
||||
{
|
||||
if (LostConnection() || inputPointer >= inputLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
b = inputData[inputPointer];
|
||||
inputPointer++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Webserver calls this to write bytes that need to go out to the network
|
||||
|
||||
void RequestState::Write(char b)
|
||||
|
@ -630,17 +576,20 @@ void RequestState::Write(const char* s)
|
|||
}
|
||||
|
||||
// Write formatted data to the output buffer
|
||||
void RequestState::Vprintf(const char* fmt, va_list v)
|
||||
void RequestState::Printf(const char* fmt, ...)
|
||||
{
|
||||
va_list p;
|
||||
va_start(p, fmt);
|
||||
int spaceLeft = ARRAY_SIZE(outputBuffer) - outputPointer;
|
||||
if (spaceLeft > 0)
|
||||
{
|
||||
int len = vsnprintf(&outputBuffer[outputPointer], spaceLeft, fmt, v);
|
||||
int len = vsnprintf(&outputBuffer[outputPointer], spaceLeft, fmt, p);
|
||||
if (len > 0)
|
||||
{
|
||||
outputPointer += min(len, spaceLeft);
|
||||
}
|
||||
}
|
||||
va_end(p);
|
||||
}
|
||||
|
||||
// Send some data if we can, returning true if all data has been sent
|
||||
|
|
22
Network.h
22
Network.h
|
@ -58,14 +58,13 @@ class RequestState
|
|||
public:
|
||||
friend class Network;
|
||||
|
||||
protected:
|
||||
RequestState(RequestState* n);
|
||||
void Set(const char* d, int l, void* pc, HttpState* h);
|
||||
bool Read(char& b);
|
||||
void SentPacketAcknowledged();
|
||||
void Write(char b);
|
||||
void Write(const char* s);
|
||||
void Vprintf(const char *fmt, va_list v);
|
||||
void Printf(const char *fmt, ...);
|
||||
void Close();
|
||||
bool TrySendData();
|
||||
void SetConnectionLost();
|
||||
|
@ -100,10 +99,7 @@ public:
|
|||
void ConnectionError(HttpState* h);
|
||||
bool Active() const;
|
||||
bool LinkIsUp();
|
||||
bool Read(char& b);
|
||||
void Write(char b);
|
||||
void Write(const char* s);
|
||||
void Printf(const char *fmt, ...);
|
||||
RequestState *GetRequest() const { return readyTransactions; }
|
||||
void SendAndClose(FileStore *f);
|
||||
bool HaveData() const;
|
||||
|
||||
|
@ -123,4 +119,18 @@ private:
|
|||
bool active;
|
||||
};
|
||||
|
||||
// Webserver calls this to read bytes that have come in from the network.
|
||||
// Inlined to improve upload speed.
|
||||
|
||||
inline bool RequestState::Read(char& b)
|
||||
{
|
||||
if (LostConnection() || inputPointer >= inputLength)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
b = inputData[inputPointer++];
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -190,7 +190,8 @@ void Platform::Init()
|
|||
|
||||
// AXES
|
||||
|
||||
axisLengths = AXIS_LENGTHS;
|
||||
axisMaxima = AXIS_MAXIMA;
|
||||
axisMinima = AXIS_MINIMA;
|
||||
homeFeedrates = HOME_FEEDRATES;
|
||||
headOffsets = HEAD_OFFSETS;
|
||||
|
||||
|
|
39
Platform.h
39
Platform.h
|
@ -103,7 +103,8 @@ const unsigned int numZProbeReadingsAveraged = 8; // we average this number of r
|
|||
|
||||
// AXES
|
||||
|
||||
#define AXIS_LENGTHS {220, 200, 200} // mm
|
||||
#define AXIS_MAXIMA {220, 200, 200} // mm
|
||||
#define AXIS_MINIMA {0, 0, 0} // mm
|
||||
#define HOME_FEEDRATES {50.0, 50.0, 1.0} // mm/sec
|
||||
#define HEAD_OFFSETS {0.0, 0.0, 0.0}
|
||||
|
||||
|
@ -567,11 +568,11 @@ public:
|
|||
float HomeFeedRate(int8_t axis) const;
|
||||
void SetHomeFeedRate(int8_t axis, float value);
|
||||
EndStopHit Stopped(int8_t drive);
|
||||
float AxisLength(int8_t axis) const;
|
||||
void SetAxisLength(int8_t axis, float value);
|
||||
#if 0 // not used
|
||||
bool HighStopButNotLow(int8_t axis) const;
|
||||
#endif
|
||||
float AxisMaximum(int8_t axis) const;
|
||||
void SetAxisMaximum(int8_t axis, float value);
|
||||
float AxisMinimum(int8_t axis) const;
|
||||
void SetAxisMinimum(int8_t axis, float value);
|
||||
float AxisTotalLength(int8_t axis) const;
|
||||
|
||||
// Z probe
|
||||
|
||||
|
@ -669,7 +670,8 @@ private:
|
|||
void UpdateNetworkAddress(byte dst[4], const byte src[4]);
|
||||
void WriteNvData();
|
||||
|
||||
float axisLengths[AXES];
|
||||
float axisMaxima[AXES];
|
||||
float axisMinima[AXES];
|
||||
float homeFeedrates[AXES];
|
||||
float headOffsets[AXES]; // FIXME - needs a 2D array
|
||||
|
||||
|
@ -798,14 +800,29 @@ inline void Platform::SetHomeFeedRate(int8_t axis, float value)
|
|||
homeFeedrates[axis] = value;
|
||||
}
|
||||
|
||||
inline float Platform::AxisLength(int8_t axis) const
|
||||
inline float Platform::AxisMaximum(int8_t axis) const
|
||||
{
|
||||
return axisLengths[axis];
|
||||
return axisMaxima[axis];
|
||||
}
|
||||
|
||||
inline void Platform::SetAxisLength(int8_t axis, float value)
|
||||
inline void Platform::SetAxisMaximum(int8_t axis, float value)
|
||||
{
|
||||
axisLengths[axis] = value;
|
||||
axisMaxima[axis] = value;
|
||||
}
|
||||
|
||||
inline float Platform::AxisMinimum(int8_t axis) const
|
||||
{
|
||||
return axisMinima[axis];
|
||||
}
|
||||
|
||||
inline void Platform::SetAxisMinimum(int8_t axis, float value)
|
||||
{
|
||||
axisMinima[axis] = value;
|
||||
}
|
||||
|
||||
inline float Platform::AxisTotalLength(int8_t axis) const
|
||||
{
|
||||
return axisMaxima[axis] - axisMinima[axis];
|
||||
}
|
||||
|
||||
inline float Platform::MaxFeedrate(int8_t drive) const
|
||||
|
|
BIN
Release/RepRapFirmware-059b-dc42.bin
Normal file
BIN
Release/RepRapFirmware-059b-dc42.bin
Normal file
Binary file not shown.
|
@ -229,6 +229,10 @@ void RepRap::Spin()
|
|||
ticksInSpinState = 0;
|
||||
webserver->Spin();
|
||||
|
||||
++spinState;
|
||||
ticksInSpinState = 0;
|
||||
network->Spin();
|
||||
|
||||
++spinState;
|
||||
ticksInSpinState = 0;
|
||||
gCodes->Spin();
|
||||
|
|
|
@ -133,6 +133,32 @@ void Webserver::LoadGcodeBuffer(const char* gc)
|
|||
}
|
||||
}
|
||||
|
||||
// Process a received string of file upload data
|
||||
// For now we just copy the data to our large buffer, bypassing the usual checks for specific gcodes.
|
||||
// Eventually, the file writing code will be moved here.
|
||||
void Webserver::LoadFileData(const char* data, size_t len)
|
||||
{
|
||||
if (len > GetGcodeBufferSpace())
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Webserver: GCode buffer overflow.\n");
|
||||
HandleReply("Webserver: GCode buffer overflow", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t remaining = gcodeBufLength - gcodeWriteIndex;
|
||||
if (len <= remaining)
|
||||
{
|
||||
memcpy(&gcodeBuffer[gcodeWriteIndex], data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&gcodeBuffer[gcodeWriteIndex], data, remaining);
|
||||
memcpy(gcodeBuffer, data + remaining, len - remaining);
|
||||
}
|
||||
gcodeWriteIndex = (gcodeWriteIndex + len) % gcodeBufLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Process a null-terminated gcode
|
||||
// We intercept four G/M Codes so we can deal with file manipulation and emergencies. That
|
||||
// way things don't get out of sync, and - as a file name can contain
|
||||
|
@ -197,29 +223,7 @@ void Webserver::ProcessGcode(const char* gc)
|
|||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
// Copy the gcode to the buffer
|
||||
size_t len = strlen(gc) + 1; // number of characters to copy
|
||||
if (len > GetGcodeBufferSpace())
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Webserver: GCode buffer overflow.\n");
|
||||
HandleReply("Webserver: GCode buffer overflow", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t remaining = gcodeBufLength - gcodeWriteIndex;
|
||||
if (len <= remaining)
|
||||
{
|
||||
memcpy(&gcodeBuffer[gcodeWriteIndex], gc, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&gcodeBuffer[gcodeWriteIndex], gc, remaining);
|
||||
memcpy(gcodeBuffer, gc + remaining, len - remaining);
|
||||
}
|
||||
gcodeWriteIndex = (gcodeWriteIndex + len) % gcodeBufLength;
|
||||
}
|
||||
}
|
||||
LoadFileData(gc, strlen(gc) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -254,7 +258,8 @@ void Webserver::SendFile(const char* nameOfFileToSend)
|
|||
}
|
||||
|
||||
Network *net = reprap.GetNetwork();
|
||||
net->Write("HTTP/1.1 200 OK\n");
|
||||
RequestState *req = net->GetRequest();
|
||||
req->Write("HTTP/1.1 200 OK\n");
|
||||
|
||||
const char* contentType;
|
||||
bool zip = false;
|
||||
|
@ -291,24 +296,24 @@ void Webserver::SendFile(const char* nameOfFileToSend)
|
|||
{
|
||||
contentType = "application/octet-stream";
|
||||
}
|
||||
net->Printf("Content-Type: %s\n", contentType);
|
||||
req->Printf("Content-Type: %s\n", contentType);
|
||||
|
||||
if (doingJsonResponse)
|
||||
{
|
||||
net->Printf("Content-Length: %u\n", strlen(jsonResponse));
|
||||
req->Printf("Content-Length: %u\n", strlen(jsonResponse));
|
||||
}
|
||||
else if (zip && fileToSend != NULL)
|
||||
{
|
||||
net->Write("Content-Encoding: gzip\n");
|
||||
net->Printf("Content-Length: %lu", fileToSend->Length());
|
||||
req->Write("Content-Encoding: gzip\n");
|
||||
req->Printf("Content-Length: %lu", fileToSend->Length());
|
||||
}
|
||||
|
||||
net->Write("Connection: close\n");
|
||||
net->Write('\n');
|
||||
req->Write("Connection: close\n");
|
||||
req->Write('\n');
|
||||
|
||||
if (doingJsonResponse)
|
||||
{
|
||||
net->Write(jsonResponse);
|
||||
req->Write(jsonResponse);
|
||||
}
|
||||
net->SendAndClose(fileToSend);
|
||||
}
|
||||
|
@ -361,7 +366,15 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
|
||||
if (StringStartsWith(request, "gcode") && StringStartsWith(clientQualifier, "gcode="))
|
||||
{
|
||||
LoadGcodeBuffer(&clientQualifier[6]);
|
||||
LoadGcodeBuffer(clientQualifier + 6);
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"buff\":%u}", GetReportedGcodeBufferSpace());
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringStartsWith(request, "data") && StringStartsWith(clientQualifier, "data="))
|
||||
{
|
||||
LoadFileData(clientQualifier + 5, strlen(clientQualifier + 5));
|
||||
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"buff\":%u}", GetReportedGcodeBufferSpace());
|
||||
JsonReport(true, request);
|
||||
return;
|
||||
|
@ -413,7 +426,7 @@ void Webserver::GetJsonResponse(const char* request)
|
|||
char ch = '[';
|
||||
for (int8_t drive = 0; drive < AXES; drive++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\"%.1f\"", ch, platform->AxisLength(drive));
|
||||
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\"%.1f\"", ch, platform->AxisTotalLength(drive));
|
||||
ch = ',';
|
||||
}
|
||||
strncat(jsonResponse, "]}", ARRAY_UPB(jsonResponse));
|
||||
|
@ -656,7 +669,9 @@ void Webserver::ParseClientLine()
|
|||
postSeen = false;
|
||||
getSeen = true;
|
||||
if (!clientRequest[0])
|
||||
{
|
||||
strncpy(clientRequest, INDEX_PAGE, ARRAY_SIZE(clientRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -802,12 +817,14 @@ void Webserver::Spin()
|
|||
return;
|
||||
|
||||
Network *net = reprap.GetNetwork();
|
||||
if (net->HaveData())
|
||||
RequestState *req = net->GetRequest();
|
||||
if (req != NULL)
|
||||
{
|
||||
for (uint8_t i = 0; i < 16; ++i)
|
||||
// To achieve a high upload speed, we try to process a complete request here
|
||||
for (;;)
|
||||
{
|
||||
char c;
|
||||
bool ok = net->Read(c);
|
||||
bool ok = req->Read(c);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ const unsigned int postLength = 1400; // max amount of POST data we can accept
|
|||
const unsigned int webInputLength = 1400; // max size of web interface requests and related stuff
|
||||
const unsigned int gcodeBufLength = 2048; // size of our gcode ring buffer, ideally a power of 2
|
||||
const unsigned int minReportedFreeBuf = 100; // the minimum free buffer we report if not zero
|
||||
const unsigned int maxReportedFreeBuf = 1024; // the max we own up to having free, to avoid overlong messages
|
||||
const unsigned int maxReportedFreeBuf = 950; // the max we own up to having free, to avoid overlong messages. 1024 is too long for Chrome/Windows 8.1.
|
||||
const unsigned int jsopnReplyLength = 1200; // size of buffer used to hold JSON reply
|
||||
|
||||
class Webserver
|
||||
|
@ -65,6 +65,7 @@ class Webserver
|
|||
void ParseQualifier();
|
||||
void CheckPassword();
|
||||
void LoadGcodeBuffer(const char* gc);
|
||||
void LoadFileData(const char* data, size_t len);
|
||||
bool PrintHeadString();
|
||||
bool PrintLinkTable();
|
||||
void GetGCodeList();
|
||||
|
@ -96,7 +97,7 @@ class Webserver
|
|||
bool getSeen;
|
||||
bool clientLineIsBlank;
|
||||
|
||||
char clientLine[webInputLength];
|
||||
char clientLine[webInputLength + 2];
|
||||
char clientRequest[webInputLength];
|
||||
char clientQualifier[webInputLength];
|
||||
char jsonResponse[jsopnReplyLength];
|
||||
|
|
Reference in a new issue