Version 0.78j
Refactored printing to strings and web server json response handling in preparation for adding support for LCD display via serial link Added a timer to record how long block writes to SD card take
This commit is contained in:
parent
8ec5f6170f
commit
46d78148b0
23 changed files with 484 additions and 386 deletions
|
@ -24,9 +24,9 @@ Licence: GPL
|
|||
#define CONFIGURATION_H
|
||||
|
||||
#define NAME "RepRapFirmware"
|
||||
#define VERSION "0.78i-dc42"
|
||||
#define DATE "2014-08-01"
|
||||
#define AUTHORS "reprappro, dc42. zpl"
|
||||
#define VERSION "0.78j-dc42"
|
||||
#define DATE "2014-08-17"
|
||||
#define AUTHORS "reprappro, dc42, zpl"
|
||||
|
||||
// Other firmware that we might switch to be compatible with.
|
||||
|
||||
|
|
230
GCodes.cpp
230
GCodes.cpp
|
@ -350,7 +350,7 @@ bool GCodes::LoadMoveBufferFromGCode(GCodeBuffer *gb, bool doingG92, bool applyL
|
|||
gb->GetFloatArray(eMovement, eMoveCount);
|
||||
if(tool->DriveCount() != eMoveCount)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Wrong number of extruder drives for the selected tool: %s\n", gb->Buffer());
|
||||
scratchString.printf("Wrong number of extruder drives for the selected tool: %s\n", gb->Buffer());
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
return false;
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ bool GCodes::OffsetAxes(GCodeBuffer* gb)
|
|||
// Returns true if completed, false if needs to be called again.
|
||||
// 'reply' is only written if there is an error.
|
||||
// 'error' is false on entry, gets changed to true if there is an error.
|
||||
bool GCodes::DoHome(char* reply, bool& error)
|
||||
bool GCodes::DoHome(StringRef& reply, bool& error)
|
||||
//pre(reply.upb == STRING_LENGTH)
|
||||
{
|
||||
if (homeX && homeY && homeZ)
|
||||
|
@ -705,7 +705,7 @@ bool GCodes::DoHome(char* reply, bool& error)
|
|||
if (platform->MustHomeXYBeforeZ() && (!axisIsHomed[X_AXIS] || !axisIsHomed[Y_AXIS]))
|
||||
{
|
||||
// We can only home Z if X and Y have already been homed
|
||||
strncpy(reply, "Must home X and Y before homing Z", STRING_LENGTH);
|
||||
reply.copy("Must home X and Y before homing Z");
|
||||
error = true;
|
||||
homeZ = false;
|
||||
return true;
|
||||
|
@ -843,7 +843,7 @@ bool GCodes::DoSingleZProbe()
|
|||
// then that value is used. If it's less than SILLY_Z_VALUE the bed is
|
||||
// probed and that value is used.
|
||||
|
||||
bool GCodes::SetSingleZProbeAtAPosition(GCodeBuffer *gb, char *reply)
|
||||
bool GCodes::SetSingleZProbeAtAPosition(GCodeBuffer *gb, StringRef& reply)
|
||||
{
|
||||
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
||||
return false;
|
||||
|
@ -895,11 +895,11 @@ bool GCodes::SetSingleZProbeAtAPosition(GCodeBuffer *gb, char *reply)
|
|||
// triangle or four in the corners), then sets the bed transformation to compensate
|
||||
// for the bed not quite being the plane Z = 0.
|
||||
|
||||
bool GCodes::DoMultipleZProbe(char *reply)
|
||||
bool GCodes::DoMultipleZProbe(StringRef& reply)
|
||||
{
|
||||
if (reprap.GetMove()->NumberOfXYProbePoints() < 3)
|
||||
{
|
||||
strncpy(reply, "Bed probing: there needs to be 3 or more points set.\n", STRING_LENGTH);
|
||||
reply.copy("Bed probing: there needs to be 3 or more points set.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -930,7 +930,7 @@ bool GCodes::GetProbeCoordinates(int count, float& x, float& y, float& z) const
|
|||
return zProbesSet;
|
||||
}
|
||||
|
||||
bool GCodes::SetPrintZProbe(GCodeBuffer* gb, char* reply)
|
||||
bool GCodes::SetPrintZProbe(GCodeBuffer* gb, StringRef& reply)
|
||||
{
|
||||
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
|
||||
return false;
|
||||
|
@ -970,13 +970,13 @@ bool GCodes::SetPrintZProbe(GCodeBuffer* gb, char* reply)
|
|||
switch(platform->GetZProbeSecondaryValues(v1, v2))
|
||||
{
|
||||
case 1:
|
||||
snprintf(reply, STRING_LENGTH, "%d (%d)", v0, v1);
|
||||
reply.printf("%d (%d)", v0, v1);
|
||||
break;
|
||||
case 2:
|
||||
snprintf(reply, STRING_LENGTH, "%d (%d, %d)", v0, v1, v2);
|
||||
reply.printf("%d (%d, %d)", v0, v1, v2);
|
||||
break;
|
||||
default:
|
||||
snprintf(reply, STRING_LENGTH, "%d", v0);
|
||||
reply.printf("%d", v0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -994,12 +994,12 @@ const char* GCodes::GetCurrentCoordinates() const
|
|||
float liveCoordinates[DRIVES + 1];
|
||||
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
||||
|
||||
snprintf(scratchString, STRING_LENGTH, "X:%.2f Y:%.2f Z:%.2f ", liveCoordinates[X_AXIS], liveCoordinates[Y_AXIS], liveCoordinates[Z_AXIS]);
|
||||
scratchString.printf("X:%.2f Y:%.2f Z:%.2f ", liveCoordinates[X_AXIS], liveCoordinates[Y_AXIS], liveCoordinates[Z_AXIS]);
|
||||
for(int i = AXES; i< DRIVES; i++)
|
||||
{
|
||||
sncatf(scratchString, STRING_LENGTH, "E%d:%.1f ", i-AXES, liveCoordinates[i]);
|
||||
scratchString.catf("E%d:%.1f ", i-AXES, liveCoordinates[i]);
|
||||
}
|
||||
return scratchString;
|
||||
return scratchString.Pointer();
|
||||
}
|
||||
|
||||
bool GCodes::OpenFileToWrite(const char* directory, const char* fileName, GCodeBuffer *gb)
|
||||
|
@ -1085,8 +1085,8 @@ void GCodes::WriteGCodeToFile(GCodeBuffer *gb)
|
|||
{
|
||||
if (gb->Seen('P'))
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "%s", gb->GetIValue());
|
||||
HandleReply(false, gb == serialGCode, scratchString, 'G', 998, true);
|
||||
scratchString.printf("%s", gb->GetIValue());
|
||||
HandleReply(false, gb == serialGCode, scratchString.Pointer(), 'G', 998, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1128,7 +1128,7 @@ void GCodes::DeleteFile(const char* fileName)
|
|||
{
|
||||
if(!platform->GetMassStorage()->Delete(platform->GetGCodeDir(), fileName))
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Unsuccessful attempt to delete: %s\n", fileName);
|
||||
scratchString.printf("Unsuccessful attempt to delete: %s\n", fileName);
|
||||
platform->Message(BOTH_ERROR_MESSAGE, scratchString);
|
||||
}
|
||||
}
|
||||
|
@ -1205,7 +1205,7 @@ bool GCodes::DoDwellTime(float dwell)
|
|||
// Set working and standby temperatures for
|
||||
// a tool. I.e. handle a G10.
|
||||
|
||||
void GCodes::SetOrReportOffsets(char* reply, GCodeBuffer *gb)
|
||||
void GCodes::SetOrReportOffsets(StringRef& reply, GCodeBuffer *gb)
|
||||
{
|
||||
if(gb->Seen('P'))
|
||||
{
|
||||
|
@ -1214,7 +1214,7 @@ void GCodes::SetOrReportOffsets(char* reply, GCodeBuffer *gb)
|
|||
Tool* tool = reprap.GetTool(toolNumber);
|
||||
if(tool == NULL)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Attempt to set/report offsets and temperatures for non-existent tool: %d\n", toolNumber);
|
||||
reply.printf("Attempt to set/report offsets and temperatures for non-existent tool: %d\n", toolNumber);
|
||||
return;
|
||||
}
|
||||
float standby[HEATERS];
|
||||
|
@ -1240,18 +1240,17 @@ void GCodes::SetOrReportOffsets(char* reply, GCodeBuffer *gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
reply[0] = 0;
|
||||
snprintf(reply, STRING_LENGTH, "Tool %d - Active/standby temperature(s): ", toolNumber);
|
||||
reply.printf("Tool %d - Active/standby temperature(s): ", toolNumber);
|
||||
for(int8_t heater = 0; heater < hCount; heater++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.1f/%.1f ", active[heater], standby[heater]);
|
||||
reply.catf("%.1f/%.1f ", active[heater], standby[heater]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GCodes::AddNewTool(GCodeBuffer *gb, char *reply)
|
||||
void GCodes::AddNewTool(GCodeBuffer *gb, StringRef& reply)
|
||||
{
|
||||
if(!gb->Seen('P'))
|
||||
{
|
||||
|
@ -1384,7 +1383,7 @@ void GCodes::SetMACAddress(GCodeBuffer *gb)
|
|||
{
|
||||
if(ipString[sp] == ':')
|
||||
{
|
||||
mac[ipp] = strtol(&ipString[spp], NULL, 0);
|
||||
mac[ipp] = strtoul(&ipString[spp], NULL, 16);
|
||||
ipp++;
|
||||
if(ipp > 5)
|
||||
{
|
||||
|
@ -1401,7 +1400,7 @@ void GCodes::SetMACAddress(GCodeBuffer *gb)
|
|||
sp++;
|
||||
}
|
||||
}
|
||||
mac[ipp] = strtol(&ipString[spp], NULL, 0);
|
||||
mac[ipp] = strtoul(&ipString[spp], NULL, 16);
|
||||
if(ipp == 5)
|
||||
{
|
||||
platform->SetMACAddress(mac);
|
||||
|
@ -1504,13 +1503,13 @@ void GCodes::HandleReply(bool error, bool fromLine, const char* reply, char gMOr
|
|||
|
||||
if (s != 0)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Emulation of %s is not yet supported.\n", s);
|
||||
scratchString.printf("Emulation of %s is not yet supported.\n", s);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
}
|
||||
|
||||
// Set PID parameters (M301 or M303 command). 'heater' is the default heater number to use.
|
||||
void GCodes::SetPidParameters(GCodeBuffer *gb, int heater, char reply[STRING_LENGTH])
|
||||
void GCodes::SetPidParameters(GCodeBuffer *gb, int heater, StringRef& reply)
|
||||
{
|
||||
if (gb->Seen('H'))
|
||||
{
|
||||
|
@ -1563,13 +1562,13 @@ void GCodes::SetPidParameters(GCodeBuffer *gb, int heater, char reply[STRING_LEN
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Heater %d P:%.2f I:%.3f D:%.2f T:%.2f S:%.2f W:%.1f B:%.1f\n",
|
||||
reply.printf("Heater %d P:%.2f I:%.3f D:%.2f T:%.2f S:%.2f W:%.1f B:%.1f\n",
|
||||
heater, pp.kP, pp.kI * platform->HeatSampleTime(), pp.kD/platform->HeatSampleTime(), pp.kT, pp.kS, pp.pidMax, pp.fullBand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GCodes::SetHeaterParameters(GCodeBuffer *gb, char reply[STRING_LENGTH])
|
||||
void GCodes::SetHeaterParameters(GCodeBuffer *gb, StringRef& reply)
|
||||
{
|
||||
if (gb->Seen('P'))
|
||||
{
|
||||
|
@ -1628,7 +1627,7 @@ void GCodes::SetHeaterParameters(GCodeBuffer *gb, char reply[STRING_LENGTH])
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "T:%.1f B:%.1f R:%.1f L:%.1f H:%.1f\n",
|
||||
reply.printf("T:%.1f B:%.1f R:%.1f L:%.1f H:%.1f\n",
|
||||
r25, beta, pp.thermistorSeriesR, pp.adcLowOffset, pp.adcHighOffset);
|
||||
}
|
||||
}
|
||||
|
@ -1687,8 +1686,9 @@ bool GCodes::HandleGcode(GCodeBuffer* gb)
|
|||
bool result = true;
|
||||
bool error = false;
|
||||
bool resend = false;
|
||||
char reply[STRING_LENGTH];
|
||||
reply[0] = 0;
|
||||
char replyBuffer[STRING_LENGTH];
|
||||
StringRef reply(replyBuffer, ARRAY_SIZE(replyBuffer));
|
||||
reply.Clear();
|
||||
|
||||
int code = gb->GetIValue();
|
||||
switch (code)
|
||||
|
@ -1760,7 +1760,7 @@ bool GCodes::HandleGcode(GCodeBuffer* gb)
|
|||
if (!(axisIsHomed[X_AXIS] && axisIsHomed[Y_AXIS]))
|
||||
{
|
||||
// We can only do bed levelling if X and Y have already been homed
|
||||
strncpy(reply, "Must home X and Y before bed probing", STRING_LENGTH);
|
||||
reply.copy("Must home X and Y before bed probing");
|
||||
error = true;
|
||||
result = true;
|
||||
}
|
||||
|
@ -1788,11 +1788,11 @@ bool GCodes::HandleGcode(GCodeBuffer* gb)
|
|||
|
||||
default:
|
||||
error = true;
|
||||
snprintf(reply, STRING_LENGTH, "invalid G Code: %s", gb->Buffer());
|
||||
reply.printf("invalid G Code: %s", gb->Buffer());
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
HandleReply(error, gb == serialGCode, reply, 'G', code, resend);
|
||||
HandleReply(error, gb == serialGCode, reply.Pointer(), 'G', code, resend);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1802,8 +1802,9 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
bool result = true;
|
||||
bool error = false;
|
||||
bool resend = false;
|
||||
char reply[STRING_LENGTH];
|
||||
reply[0] = 0;
|
||||
char replyBuffer[STRING_LENGTH];
|
||||
StringRef reply(replyBuffer, ARRAY_SIZE(replyBuffer));
|
||||
reply.Clear();
|
||||
|
||||
int code = gb->GetIValue();
|
||||
switch (code)
|
||||
|
@ -1842,12 +1843,12 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
bool encapsulate_list;
|
||||
if (platform->Emulating() == me || platform->Emulating() == reprapFirmware)
|
||||
{
|
||||
strcpy(reply, "GCode files:\n");
|
||||
reply.copy("GCode files:\n");
|
||||
encapsulate_list = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(reply, "");
|
||||
reply.Clear();
|
||||
encapsulate_list = true;
|
||||
}
|
||||
|
||||
|
@ -1858,20 +1859,20 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
do {
|
||||
if (encapsulate_list)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH -1, "%c%s%c%c", FILE_LIST_BRACKET, file_info.fileName, FILE_LIST_BRACKET, FILE_LIST_SEPARATOR);
|
||||
reply.catf("%c%s%c%c", FILE_LIST_BRACKET, file_info.fileName, FILE_LIST_BRACKET, FILE_LIST_SEPARATOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH -1, "%s\n", file_info.fileName);
|
||||
reply.catf("%s\n", file_info.fileName);
|
||||
}
|
||||
} while (platform->GetMassStorage()->FindNext(file_info));
|
||||
|
||||
// remove the last character
|
||||
reply[strlen(reply) - 1] = 0;
|
||||
reply[reply.strlen() - 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(reply, "NONE");
|
||||
reply.cat("NONE");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1884,7 +1885,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
QueueFileToPrint(gb->GetUnprecedentedString());
|
||||
if (fileToPrint.IsLive() && platform->Emulating() == marlin)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "%s", "File opened\nFile selected\n");
|
||||
reply.copy("File opened\nFile selected\n");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1901,11 +1902,11 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
case 27: // Report print status - Deprecated
|
||||
if (fileBeingPrinted.IsLive())
|
||||
{
|
||||
strncpy(reply, "SD printing.", STRING_LENGTH);
|
||||
reply.copy("SD printing.");
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(reply, "Not SD printing.", STRING_LENGTH);
|
||||
reply.copy("Not SD printing.");
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1915,11 +1916,11 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
bool ok = OpenFileToWrite(platform->GetGCodeDir(), str, gb);
|
||||
if (ok)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Writing to file: %s", str);
|
||||
reply.printf("Writing to file: %s", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Can't open file %s for writing.\n", str);
|
||||
reply.printf("Can't open file %s for writing.\n", str);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
@ -1987,7 +1988,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
gb->GetFloatArray(eVals, eCount);
|
||||
if(eCount != DRIVES-AXES)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Setting steps/mm - wrong number of E drives: %s\n", gb->Buffer());
|
||||
scratchString.printf("Setting steps/mm - wrong number of E drives: %s\n", gb->Buffer());
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
else
|
||||
|
@ -2001,15 +2002,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
if(!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Steps/mm: X: %.3f, Y: %.3f, Z: %.3f, E: ",
|
||||
reply.printf("Steps/mm: X: %.3f, Y: %.3f, Z: %.3f, E: ",
|
||||
platform->DriveStepsPerUnit(X_AXIS), platform->DriveStepsPerUnit(Y_AXIS),
|
||||
platform->DriveStepsPerUnit(Z_AXIS));
|
||||
for(int8_t drive = AXES; drive < DRIVES; drive++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.3f", platform->DriveStepsPerUnit(drive));
|
||||
reply.catf("%.3f", platform->DriveStepsPerUnit(drive));
|
||||
if(drive < DRIVES-1)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, ":");
|
||||
reply.cat(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2051,15 +2052,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
break;
|
||||
|
||||
case 105: // Deprecated...
|
||||
strncpy(reply, "T:", STRING_LENGTH);
|
||||
reply.copy("T:");
|
||||
for(int8_t heater = 1; heater < HEATERS; heater++)
|
||||
{
|
||||
if(reprap.GetHeat()->GetStatus(heater) != Heat::HS_off)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.1f ", reprap.GetHeat()->GetTemperature(heater));
|
||||
reply.catf("%.1f ", reprap.GetHeat()->GetTemperature(heater));
|
||||
}
|
||||
}
|
||||
sncatf(reply, STRING_LENGTH, "B: %.1f ", reprap.GetHeat()->GetTemperature(0));
|
||||
reply.catf("B: %.1f ", reprap.GetHeat()->GetTemperature(0));
|
||||
break;
|
||||
|
||||
case 106: // Fan on or off
|
||||
|
@ -2143,7 +2144,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
const char* str = GetCurrentCoordinates();
|
||||
if (str != 0)
|
||||
{
|
||||
strncpy(reply, str, STRING_LENGTH);
|
||||
reply.copy(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2153,8 +2154,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
break;
|
||||
|
||||
case 115: // Print firmware version
|
||||
snprintf(reply, STRING_LENGTH, "FIRMWARE_NAME:%s FIRMWARE_VERSION:%s ELECTRONICS:%s DATE:%s", NAME, VERSION,
|
||||
ELECTRONICS, DATE);
|
||||
reply.printf("FIRMWARE_NAME:%s FIRMWARE_VERSION:%s ELECTRONICS:%s DATE:%s", NAME, VERSION, ELECTRONICS, DATE);
|
||||
break;
|
||||
|
||||
case 116: // Wait for everything, especially set temperatures
|
||||
|
@ -2182,7 +2182,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
case 119:
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Endstops - ");
|
||||
reply.copy("Endstops - ");
|
||||
char comma = ',';
|
||||
for(int8_t axis = 0; axis < AXES; axis++)
|
||||
{
|
||||
|
@ -2211,7 +2211,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
comma = ' ';
|
||||
}
|
||||
|
||||
sncatf(reply, STRING_LENGTH, "%c: %s%c ", axisLetters[axis], es, comma);
|
||||
reply.catf("%c: %s%c ", axisLetters[axis], es, comma);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2253,7 +2253,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Heat sample time is %.3f seconds.", platform->HeatSampleTime());
|
||||
reply.printf("Heat sample time is %.3f seconds.", platform->HeatSampleTime());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2323,7 +2323,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
gb->GetFloatArray(eVals, eCount);
|
||||
if(eCount != DRIVES-AXES)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Setting accelerations - wrong number of E drives: %s\n", gb->Buffer());
|
||||
scratchString.printf("Setting accelerations - wrong number of E drives: %s\n", gb->Buffer());
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
else
|
||||
|
@ -2337,15 +2337,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
if(!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Accelerations: X: %.1f, Y: %.1f, Z: %.1f, E: ",
|
||||
reply.printf("Accelerations: X: %.1f, Y: %.1f, Z: %.1f, E: ",
|
||||
platform->Acceleration(X_AXIS)/distanceScale, platform->Acceleration(Y_AXIS)/distanceScale,
|
||||
platform->Acceleration(Z_AXIS)/distanceScale);
|
||||
for(int8_t drive = AXES; drive < DRIVES; drive++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.1f", platform->Acceleration(drive)/distanceScale);
|
||||
reply.catf("%.1f", platform->Acceleration(drive)/distanceScale);
|
||||
if(drive < DRIVES-1)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, ":");
|
||||
reply.cat(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2372,7 +2372,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
gb->GetFloatArray(eVals, eCount);
|
||||
if(eCount != DRIVES-AXES)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Setting feedrates - wrong number of E drives: %s\n", gb->Buffer());
|
||||
scratchString.printf("Setting feedrates - wrong number of E drives: %s\n", gb->Buffer());
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
else
|
||||
|
@ -2386,15 +2386,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
if(!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Maximum feedrates: X: %.1f, Y: %.1f, Z: %.1f, E: ",
|
||||
reply.printf("Maximum feedrates: X: %.1f, Y: %.1f, Z: %.1f, E: ",
|
||||
platform->MaxFeedrate(X_AXIS)/(distanceScale * secondsToMinutes), platform->MaxFeedrate(Y_AXIS)/(distanceScale * secondsToMinutes),
|
||||
platform->MaxFeedrate(Z_AXIS)/(distanceScale * secondsToMinutes));
|
||||
for(int8_t drive = AXES; drive < DRIVES; drive++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.1f", platform->MaxFeedrate(drive)/(distanceScale * secondsToMinutes));
|
||||
reply.catf("%.1f", platform->MaxFeedrate(drive)/(distanceScale * secondsToMinutes));
|
||||
if(drive < DRIVES-1)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, ":");
|
||||
reply.cat(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2405,7 +2405,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
// This is superseded in this firmware by M codes for the separate types (e.g. M566).
|
||||
break;
|
||||
|
||||
case 206: // Offset axes - Depricated
|
||||
case 206: // Offset axes - Deprecated
|
||||
result = OffsetAxes(gb);
|
||||
break;
|
||||
|
||||
|
@ -2432,7 +2432,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
if (!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Axis limits - ");
|
||||
reply.copy("Axis limits - ");
|
||||
char comma = ',';
|
||||
for(int8_t axis = 0; axis < AXES; axis++)
|
||||
{
|
||||
|
@ -2440,7 +2440,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
{
|
||||
comma = ' ';
|
||||
}
|
||||
sncatf(reply, STRING_LENGTH, "%c: %.1f min, %.1f max%c ", axisLetters[axis],
|
||||
reply.catf("%c: %.1f min, %.1f max%c ", axisLetters[axis],
|
||||
platform->AxisMinimum(axis), platform->AxisMaximum(axis), comma);
|
||||
}
|
||||
}
|
||||
|
@ -2462,7 +2462,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
if(!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Homing feedrates (mm/min) - ");
|
||||
reply.copy("Homing feedrates (mm/min) - ");
|
||||
char comma = ',';
|
||||
for(int8_t axis = 0; axis < AXES; axis++)
|
||||
{
|
||||
|
@ -2471,7 +2471,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
comma = ' ';
|
||||
}
|
||||
|
||||
sncatf(reply, STRING_LENGTH, "%c: %.1f%c ", axisLetters[axis],
|
||||
reply.catf("%c: %.1f%c ", axisLetters[axis],
|
||||
platform->HomeFeedRate(axis) * 60.0 / distanceScale, comma);
|
||||
}
|
||||
}
|
||||
|
@ -2490,7 +2490,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Speed factor override: %.1f%%\n", speedFactor * (60.0 * 100.0));
|
||||
reply.printf("Speed factor override: %.1f%%\n", speedFactor * (60.0 * 100.0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2516,7 +2516,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Extrusion factor override for drive %d: %.1f%%\n", drive, extrusionFactors[drive] * 100.0);
|
||||
reply.printf("Extrusion factor override for drive %d: %.1f%%\n", drive, extrusionFactors[drive] * 100.0);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2540,7 +2540,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Cold extrudes are %s, use M302 P[1/0] to allow or deny them",
|
||||
reply.printf("Cold extrudes are %s, use M302 P[1/0] to allow or deny them",
|
||||
reprap.ColdExtrude() ? "enabled" : "disabled");
|
||||
}
|
||||
break;
|
||||
|
@ -2568,7 +2568,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
else
|
||||
{
|
||||
const byte* mac = platform->MACAddress();
|
||||
snprintf(reply, STRING_LENGTH, "MAC: %x:%x:%x:%x:%x:%x ", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
reply.printf("MAC: %x:%x:%x:%x:%x:%x ", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2579,7 +2579,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "RepRap name: %s ", reprap.GetWebserver()->GetName());
|
||||
reply.printf("RepRap name: %s ", reprap.GetWebserver()->GetName());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2598,7 +2598,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
else
|
||||
{
|
||||
const byte *ip = platform->IPAddress();
|
||||
snprintf(reply, STRING_LENGTH, "IP address: %d.%d.%d.%d\n ", ip[0], ip[1], ip[2], ip[3]);
|
||||
reply.printf("IP address: %d.%d.%d.%d\n ", ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2610,7 +2610,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
else
|
||||
{
|
||||
const byte *nm = platform->NetMask();
|
||||
snprintf(reply, STRING_LENGTH, "Net mask: %d.%d.%d.%d\n ", nm[0], nm[1], nm[2], nm[3]);
|
||||
reply.printf("Net mask: %d.%d.%d.%d\n ", nm[0], nm[1], nm[2], nm[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2622,7 +2622,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
else
|
||||
{
|
||||
const byte *gw = platform->GateWay();
|
||||
snprintf(reply, STRING_LENGTH, "Gateway: %d.%d.%d.%d\n ", gw[0], gw[1], gw[2], gw[3]);
|
||||
reply.printf("Gateway: %d.%d.%d.%d\n ", gw[0], gw[1], gw[2], gw[3]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2633,32 +2633,32 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Emulating ");
|
||||
reply.copy("Emulating ");
|
||||
switch(platform->Emulating())
|
||||
{
|
||||
case me:
|
||||
case reprapFirmware:
|
||||
sncatf(reply, STRING_LENGTH, "RepRap Firmware (i.e. in native mode)");
|
||||
reply.cat("RepRap Firmware (i.e. in native mode)");
|
||||
break;
|
||||
|
||||
case marlin:
|
||||
sncatf(reply, STRING_LENGTH, "Marlin");
|
||||
reply.cat("Marlin");
|
||||
break;
|
||||
|
||||
case teacup:
|
||||
sncatf(reply, STRING_LENGTH, "Teacup");
|
||||
reply.cat("Teacup");
|
||||
break;
|
||||
|
||||
case sprinter:
|
||||
sncatf(reply, STRING_LENGTH, "Sprinter");
|
||||
reply.cat("Sprinter");
|
||||
break;
|
||||
|
||||
case repetier:
|
||||
sncatf(reply, STRING_LENGTH, "Repetier");
|
||||
reply.cat("Repetier");
|
||||
break;
|
||||
|
||||
default:
|
||||
sncatf(reply, STRING_LENGTH, "Unknown: (%d)", platform->Emulating());
|
||||
reply.catf("Unknown: (%d)", platform->Emulating());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2677,7 +2677,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Axis compensations - XY: %.5f, YZ: %.5f, ZX: %.5f ",
|
||||
reply.printf("Axis compensations - XY: %.5f, YZ: %.5f, ZX: %.5f ",
|
||||
reprap.GetMove()->AxisCompensation(X_AXIS),
|
||||
reprap.GetMove()->AxisCompensation(Y_AXIS),
|
||||
reprap.GetMove()->AxisCompensation(Z_AXIS));
|
||||
|
@ -2702,7 +2702,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
if(!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Probe point %d - [%.1f, %.1f]", point,
|
||||
reply.printf("Probe point %d - [%.1f, %.1f]", point,
|
||||
reprap.GetMove()->XBedProbePoint(point),
|
||||
reprap.GetMove()->YBedProbePoint(point));
|
||||
}
|
||||
|
@ -2735,12 +2735,12 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Z Probe type is %d and it is used for these axes:", platform->GetZProbeType());
|
||||
reply.printf("Z Probe type is %d and it is used for these axes:", platform->GetZProbeType());
|
||||
for(int axis=0; axis<AXES; axis++)
|
||||
{
|
||||
if (zProbeAxes[axis])
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, " %c", axisLetters[axis]);
|
||||
reply.catf(" %c", axisLetters[axis]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2753,11 +2753,11 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
bool ok = OpenFileToWrite(platform->GetSysDir(), str, gb);
|
||||
if (ok)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Writing to file: %s", str);
|
||||
reply.printf("Writing to file: %s", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Can't open file %s for writing.\n", str);
|
||||
reply.printf("Can't open file %s for writing.\n", str);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
@ -2769,11 +2769,11 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
bool ok = OpenFileToWrite(platform->GetWebDir(), str, gb);
|
||||
if (ok)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Writing to file: %s", str);
|
||||
reply.printf("Writing to file: %s", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Can't open file %s for writing.\n", str);
|
||||
reply.printf("Can't open file %s for writing.\n", str);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
@ -2822,7 +2822,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
gb->GetFloatArray(eVals, eCount);
|
||||
if(eCount != DRIVES-AXES)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Setting feedrates - wrong number of E drives: %s\n", gb->Buffer());
|
||||
reply.printf("Setting feedrates - wrong number of E drives: %s\n", gb->Buffer());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2834,15 +2834,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else if(!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Minimum feedrates: X: %.1f, Y: %.1f, Z: %.1f, E: ",
|
||||
reply.printf("Minimum feedrates: X: %.1f, Y: %.1f, Z: %.1f, E: ",
|
||||
platform->InstantDv(X_AXIS)/(distanceScale * secondsToMinutes), platform->InstantDv(Y_AXIS)/(distanceScale * secondsToMinutes),
|
||||
platform->InstantDv(Z_AXIS)/(distanceScale * secondsToMinutes));
|
||||
for(int8_t drive = AXES; drive < DRIVES; drive++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.1f", platform->InstantDv(drive)/(distanceScale * secondsToMinutes));
|
||||
reply.catf("%.1f", platform->InstantDv(drive)/(distanceScale * secondsToMinutes));
|
||||
if(drive < DRIVES-1)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, ":");
|
||||
reply.cat(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2868,7 +2868,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
gb->GetFloatArray(eVals, eCount);
|
||||
if(eCount != DRIVES-AXES)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Setting motor currents - wrong number of E drives: %s\n", gb->Buffer());
|
||||
reply.printf("Setting motor currents - wrong number of E drives: %s\n", gb->Buffer());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2880,15 +2880,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
}
|
||||
else if (!seen)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Axis currents (mA) - X:%.1f, Y:%.1f, Z:%.1f, E:",
|
||||
reply.printf("Axis currents (mA) - X:%.1f, Y:%.1f, Z:%.1f, E:",
|
||||
platform->MotorCurrent(X_AXIS), platform->MotorCurrent(Y_AXIS),
|
||||
platform->MotorCurrent(Z_AXIS));
|
||||
for(int8_t drive = AXES; drive < DRIVES; drive++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, "%.1f", platform->MotorCurrent(drive));
|
||||
reply.catf("%.1f", platform->MotorCurrent(drive));
|
||||
if(drive < DRIVES-1)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, ":");
|
||||
reply.cat(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2898,7 +2898,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
case 998:
|
||||
if (gb->Seen('P'))
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "%s", gb->GetIValue());
|
||||
reply.printf("%d", gb->GetIValue());
|
||||
resend = true;
|
||||
}
|
||||
break;
|
||||
|
@ -2913,11 +2913,11 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
|
|||
|
||||
default:
|
||||
error = true;
|
||||
snprintf(reply, STRING_LENGTH, "invalid M Code: %s", gb->Buffer());
|
||||
reply.printf("invalid M Code: %s", gb->Buffer());
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
HandleReply(error, gb == serialGCode, reply, 'M', code, resend);
|
||||
HandleReply(error, gb == serialGCode, reply.Pointer(), 'M', code, resend);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2953,8 +2953,8 @@ bool GCodes::ChangeTool(int newToolNumber)
|
|||
case 0: // Pre-release sequence for the old tool (if any)
|
||||
if(oldTool != NULL)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "tfree%d.g", oldTool->Number());
|
||||
if(DoFileCannedCycles(scratchString))
|
||||
scratchString.printf("tfree%d.g", oldTool->Number());
|
||||
if(DoFileCannedCycles(scratchString.Pointer()))
|
||||
{
|
||||
toolChangeSequence++;
|
||||
}
|
||||
|
@ -2976,8 +2976,8 @@ bool GCodes::ChangeTool(int newToolNumber)
|
|||
case 2: // Run the pre-tool-change canned cycle for the new tool (if any)
|
||||
if(newTool != NULL)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "tpre%d.g", newToolNumber);
|
||||
if(DoFileCannedCycles(scratchString))
|
||||
scratchString.printf("tpre%d.g", newToolNumber);
|
||||
if(DoFileCannedCycles(scratchString.Pointer()))
|
||||
{
|
||||
toolChangeSequence++;
|
||||
}
|
||||
|
@ -2996,8 +2996,8 @@ bool GCodes::ChangeTool(int newToolNumber)
|
|||
case 4: // Run the post-tool-change canned cycle for the new tool (if any)
|
||||
if(newTool != NULL)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "tpost%d.g", newToolNumber);
|
||||
if(DoFileCannedCycles(scratchString))
|
||||
scratchString.printf("tpost%d.g", newToolNumber);
|
||||
if(DoFileCannedCycles(scratchString.Pointer()))
|
||||
{
|
||||
toolChangeSequence++;
|
||||
}
|
||||
|
@ -3217,7 +3217,7 @@ const void GCodeBuffer::GetFloatArray(float a[], int& returnedLength)
|
|||
{
|
||||
if(length >= returnedLength) // Array limit has been set in here
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "GCodes: Attempt to read a GCode float array that is too long: %s\n", gcodeBuffer);
|
||||
scratchString.printf("GCodes: Attempt to read a GCode float array that is too long: %s\n", gcodeBuffer);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
readPointer = -1;
|
||||
returnedLength = 0;
|
||||
|
@ -3271,7 +3271,7 @@ const void GCodeBuffer::GetLongArray(long l[], int& returnedLength)
|
|||
{
|
||||
if(length >= returnedLength) // Array limit has been set in here
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "GCodes: Attempt to read a GCode long array that is too long: %s\n", gcodeBuffer);
|
||||
scratchString.printf("GCodes: Attempt to read a GCode long array that is too long: %s\n", gcodeBuffer);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
readPointer = -1;
|
||||
returnedLength = 0;
|
||||
|
|
16
GCodes.h
16
GCodes.h
|
@ -116,13 +116,13 @@ class GCodes
|
|||
int SetUpMove(GCodeBuffer* gb); // Pass a move on to the Move module
|
||||
bool DoDwell(GCodeBuffer *gb); // Wait for a bit
|
||||
bool DoDwellTime(float dwell); // Really wait for a bit
|
||||
bool DoHome(char *reply, bool& error); // Home some axes
|
||||
bool DoHome(StringRef& reply, bool& error); // Home some axes
|
||||
bool DoSingleZProbeAtPoint(); // Probe at a given point
|
||||
bool DoSingleZProbe(); // Probe where we are
|
||||
bool SetSingleZProbeAtAPosition(GCodeBuffer *gb, char *reply); // Probes at a given position - see the comment at the head of the function itself
|
||||
bool DoMultipleZProbe(char *reply); // Probes a series of points and sets the bed equation
|
||||
bool SetPrintZProbe(GCodeBuffer *gb, char *reply); // Either return the probe value, or set its threshold
|
||||
void SetOrReportOffsets(char* reply, GCodeBuffer *gb); // Deal with a G10
|
||||
bool SetSingleZProbeAtAPosition(GCodeBuffer *gb, StringRef& reply); // Probes at a given position - see the comment at the head of the function itself
|
||||
bool DoMultipleZProbe(StringRef& reply); // Probes a series of points and sets the bed equation
|
||||
bool SetPrintZProbe(GCodeBuffer *gb, StringRef& reply); // Either return the probe value, or set its threshold
|
||||
void SetOrReportOffsets(StringRef& reply, GCodeBuffer *gb); // Deal with a G10
|
||||
bool SetPositions(GCodeBuffer *gb); // Deal with a G92
|
||||
bool LoadMoveBufferFromGCode(GCodeBuffer *gb, // Set up a move for the Move class
|
||||
bool doingG92, bool applyLimits);
|
||||
|
@ -140,10 +140,10 @@ class GCodes
|
|||
bool SendConfigToLine(); // Deal with M503
|
||||
void WriteHTMLToFile(char b, GCodeBuffer *gb); // Save an HTML file (usually to upload a new web interface)
|
||||
bool OffsetAxes(GCodeBuffer *gb); // Set offsets - deprecated, use G10
|
||||
void SetPidParameters(GCodeBuffer *gb, int heater, char reply[STRING_LENGTH]); // Set the P/I/D parameters for a heater
|
||||
void SetHeaterParameters(GCodeBuffer *gb, char reply[STRING_LENGTH]); // Set the thermistor and ADC parameters for a heater
|
||||
void SetPidParameters(GCodeBuffer *gb, int heater, StringRef& reply); // Set the P/I/D parameters for a heater
|
||||
void SetHeaterParameters(GCodeBuffer *gb, StringRef& reply); // Set the thermistor and ADC parameters for a heater
|
||||
int8_t Heater(int8_t head) const; // Legacy G codes start heaters at 0, but we use 0 for the bed. This sorts that out.
|
||||
void AddNewTool(GCodeBuffer *gb, char* reply); // Create a new tool definition
|
||||
void AddNewTool(GCodeBuffer *gb, StringRef& reply); // Create a new tool definition
|
||||
void SetToolHeaters(Tool *tool, float temperature); // Set all a tool's heaters to the temperature. For M104...
|
||||
bool ChangeTool(int newToolNumber); // Select a new tool
|
||||
bool ToolHeatersAtSetTemperatures(const Tool *tool) const; // Wait for the heaters associated with the specified tool to reach their set temperatures
|
||||
|
|
7
Heat.cpp
7
Heat.cpp
|
@ -73,7 +73,7 @@ void Heat::Diagnostics()
|
|||
{
|
||||
if (pids[heater]->active)
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Heater %d: I-accumulator = %.1f\n", heater, pids[heater]->temp_iState);
|
||||
scratchString.printf("Heater %d: I-accumulator = %.1f\n", heater, pids[heater]->temp_iState);
|
||||
platform->AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ void PID::Spin()
|
|||
platform->SetHeater(heater, 0.0);
|
||||
temperatureFault = true;
|
||||
switchedOff = true;
|
||||
snprintf(scratchString, STRING_LENGTH, "Temperature fault on heater %d, T = %.1f\n", heater, temperature);
|
||||
scratchString.printf("Temperature fault on heater %d, T = %.1f\n", heater, temperature);
|
||||
platform->Message(BOTH_MESSAGE, scratchString);
|
||||
reprap.FlagTemperatureFault(heater);
|
||||
}
|
||||
|
@ -191,8 +191,7 @@ void PID::Spin()
|
|||
platform->SetHeater(heater, 0.0);
|
||||
temperatureFault = true;
|
||||
switchedOff = true;
|
||||
snprintf(scratchString, STRING_LENGTH, "Heating fault on heater %d, T = %.1f C; still not at temperature after %f seconds.\n",
|
||||
heater, temperature, tim);
|
||||
scratchString.printf("Heating fault on heater %d, T = %.1f C; still not at temperature after %f seconds.\n", heater, temperature, tim);
|
||||
platform->Message(BOTH_MESSAGE, scratchString);
|
||||
reprap.FlagTemperatureFault(heater);
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
/ Always set 512 for memory card and hard disk but a larger value may be
|
||||
/ required for on-board flash memory, floppy disk and optical disk.
|
||||
/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size
|
||||
/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
|
||||
/ and GET_SECTOR_SIZE command must be implemented to the disk_ioctl function. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
|
||||
|
@ -147,7 +147,7 @@
|
|||
|
||||
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
|
||||
/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
|
||||
/ should be added to the disk_ioctl functio. */
|
||||
/ should be added to the disk_ioctl function. */
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#include "../SD_HSMCI.h"
|
||||
#include "hsmci.h"
|
||||
|
||||
extern debugPrintf(const char *fmt, ...);
|
||||
#define hsmci_debug(_fmt, ...) debugPrintf(_fmt, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \ingroup sam_drivers_hsmci
|
||||
* \defgroup sam_drivers_hsmci_internal High Speed MultiMedia Card Interface
|
||||
|
@ -84,7 +87,7 @@
|
|||
|
||||
|
||||
#if (SAM3S || SAM4S)
|
||||
// PDC is used for transferts
|
||||
// PDC is used for transfers
|
||||
#elif (SAM3U || SAM3XA_SERIES)
|
||||
// DMA is used for transferts
|
||||
# include "dmac.h"
|
||||
|
@ -173,7 +176,7 @@ static bool hsmci_wait_busy(void)
|
|||
do {
|
||||
sr = HSMCI->HSMCI_SR;
|
||||
if (busy_wait-- == 0) {
|
||||
// printf("%s: timeout\n\r", __func__);
|
||||
hsmci_debug("%s: timeout\n\r", __func__);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -184,7 +187,7 @@ static bool hsmci_wait_busy(void)
|
|||
|
||||
/** \brief Send a command
|
||||
*
|
||||
* \param cmdr CMDR resgister bit to use for this command
|
||||
* \param cmdr CMDR register bit to use for this command
|
||||
* \param cmd Command definition
|
||||
* \param arg Argument of the command
|
||||
*
|
||||
|
@ -222,7 +225,7 @@ static bool hsmci_send_cmd_execute(uint32_t cmdr, sdmmc_cmd_def_t cmd,
|
|||
if (sr & (HSMCI_SR_CSTOE | HSMCI_SR_RTOE
|
||||
| HSMCI_SR_RCRCE
|
||||
| HSMCI_SR_RDIRE)) {
|
||||
// printf("%s: CMD 0x%08x sr 0x%08x CMD 3 error\n\r",__func__, cmd, sr);
|
||||
hsmci_debug("%s: CMD 0x%08x sr 0x%08x CMD 3 error\n\r",__func__, cmd, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -230,7 +233,7 @@ static bool hsmci_send_cmd_execute(uint32_t cmdr, sdmmc_cmd_def_t cmd,
|
|||
if (sr & (HSMCI_SR_CSTOE | HSMCI_SR_RTOE
|
||||
| HSMCI_SR_RENDE | HSMCI_SR_RCRCE
|
||||
| HSMCI_SR_RDIRE | HSMCI_SR_RINDE)) {
|
||||
// printf("%s: CMD 0x%08x sr 0x%08x RESP_CRC error\n\r",__func__, cmd, sr);
|
||||
hsmci_debug("%s: CMD 0x%08x sr 0x%08x RESP_CRC error\n\r",__func__, cmd, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -238,7 +241,7 @@ static bool hsmci_send_cmd_execute(uint32_t cmdr, sdmmc_cmd_def_t cmd,
|
|||
if (sr & (HSMCI_SR_CSTOE | HSMCI_SR_RTOE
|
||||
| HSMCI_SR_RENDE
|
||||
| HSMCI_SR_RDIRE | HSMCI_SR_RINDE)) {
|
||||
// printf("%s: CMD 0x%08x sr 0x%08x error\n\r",__func__, cmd, sr);
|
||||
hsmci_debug("%s: CMD 0x%08x sr 0x%08x error\n\r",__func__, cmd, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -485,7 +488,7 @@ bool hsmci_read_word(uint32_t* value)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
// printf("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -504,7 +507,7 @@ bool hsmci_read_word(uint32_t* value)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
// printf("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -523,7 +526,7 @@ bool hsmci_write_word(uint32_t value)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
// printf("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -542,7 +545,7 @@ bool hsmci_write_word(uint32_t value)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
// printf("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
@ -617,7 +620,7 @@ bool hsmci_wait_end_of_read_blocks(void)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
// printf("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
// Disable DMA
|
||||
dmac_channel_disable(DMAC, CONF_HSMCI_DMA_CHANNEL);
|
||||
|
@ -699,7 +702,7 @@ bool hsmci_wait_end_of_write_blocks(void)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
//printf("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: DMA sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
// Disable DMA
|
||||
dmac_channel_disable(DMAC, CONF_HSMCI_DMA_CHANNEL);
|
||||
|
@ -749,7 +752,7 @@ bool hsmci_wait_end_of_read_blocks(void)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
//printf("%s: PDC sr 0x%08x error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: PDC sr 0x%08x error\n\r",__func__, sr);
|
||||
HSMCI->HSMCI_PTCR = HSMCI_PTCR_RXTDIS | HSMCI_PTCR_TXTDIS;
|
||||
hsmci_reset();
|
||||
return false;
|
||||
|
@ -766,7 +769,7 @@ bool hsmci_wait_end_of_read_blocks(void)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
//printf("%s: PDC sr 0x%08x last transfer error\n\r",
|
||||
hsmci_debug("%s: PDC sr 0x%08x last transfer error\n\r",
|
||||
__func__, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
|
@ -805,8 +808,7 @@ bool hsmci_wait_end_of_write_blocks(void)
|
|||
if (sr &
|
||||
(HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
//printf("%s: PDC sr 0x%08x error\n\r",
|
||||
__func__, sr);
|
||||
hsmci_debug("%s: PDC sr 0x%08x error\n\r", __func__, sr);
|
||||
hsmci_reset();
|
||||
HSMCI->HSMCI_PTCR = HSMCI_PTCR_RXTDIS | HSMCI_PTCR_TXTDIS;
|
||||
return false;
|
||||
|
@ -823,7 +825,7 @@ bool hsmci_wait_end_of_write_blocks(void)
|
|||
sr = HSMCI->HSMCI_SR;
|
||||
if (sr & (HSMCI_SR_UNRE | HSMCI_SR_OVRE | \
|
||||
HSMCI_SR_DTOE | HSMCI_SR_DCRCE)) {
|
||||
//printf("%s: PDC sr 0x%08x last transfer error\n\r",__func__, sr);
|
||||
hsmci_debug("%s: PDC sr 0x%08x last transfer error\n\r",__func__, sr);
|
||||
hsmci_reset();
|
||||
return false;
|
||||
}
|
||||
|
|
13
Move.cpp
13
Move.cpp
|
@ -805,7 +805,7 @@ float Move::TriangleZ(float x, float y) const
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void Move::SetProbedBedEquation(char *reply)
|
||||
void Move::SetProbedBedEquation(StringRef& reply)
|
||||
{
|
||||
switch(NumberOfProbePoints())
|
||||
{
|
||||
|
@ -871,10 +871,10 @@ void Move::SetProbedBedEquation(char *reply)
|
|||
platform->Message(HOST_MESSAGE, "Attempt to set bed compensation before all probe points have been recorded.");
|
||||
}
|
||||
|
||||
snprintf(reply, STRING_LENGTH, "Bed equation fits points");
|
||||
reply.copy("Bed equation fits points");
|
||||
for(int8_t point = 0; point < NumberOfProbePoints(); point++)
|
||||
{
|
||||
sncatf(reply, STRING_LENGTH, " [%.1f, %.1f, %.3f]", xBedProbePoints[point], yBedProbePoints[point], zBedProbePoints[point]);
|
||||
reply.catf(" [%.1f, %.1f, %.3f]", xBedProbePoints[point], yBedProbePoints[point], zBedProbePoints[point]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1142,7 +1142,9 @@ MovementProfile DDA::Init(LookAhead* lookAhead, float& u, float& v)
|
|||
void DDA::Start()
|
||||
{
|
||||
for(int8_t drive = 0; drive < DRIVES; drive++)
|
||||
{
|
||||
platform->SetDirection(drive, directions[drive]);
|
||||
}
|
||||
|
||||
platform->SetInterrupt(timeStep); // seconds
|
||||
active = true;
|
||||
|
@ -1157,7 +1159,6 @@ void DDA::Step()
|
|||
return;
|
||||
|
||||
int drivesMoving = 0;
|
||||
// uint8_t extrudersMoving = 0;
|
||||
|
||||
for(size_t drive = 0; drive < DRIVES; drive++)
|
||||
{
|
||||
|
@ -1214,7 +1215,7 @@ void DDA::Step()
|
|||
else if(stepCount >= startDStep)
|
||||
{
|
||||
velocity -= acceleration*timeStep;
|
||||
if(velocity < instantDv)
|
||||
if (velocity < instantDv)
|
||||
{
|
||||
velocity = instantDv;
|
||||
}
|
||||
|
@ -1337,7 +1338,7 @@ long LookAhead::EndPointToMachine(int8_t drive, float coord)
|
|||
|
||||
void LookAhead::PrintMove()
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "X,Y,Z: %.1f %.1f %.1f, min v: %.2f, max v: %.1f, acc: %.1f, feed: %.1f, u: %.3f, v: %.3f\n",
|
||||
scratchString.printf("X,Y,Z: %.1f %.1f %.1f, min v: %.2f, max v: %.1f, acc: %.1f, feed: %.1f, u: %.3f, v: %.3f\n",
|
||||
MachineToEndPoint(X_AXIS), MachineToEndPoint(Y_AXIS), MachineToEndPoint(Z_AXIS),
|
||||
MinSpeed(), MaxSpeed(), Acceleration(), FeedRate(), Previous()->V(), V());
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
|
|
2
Move.h
2
Move.h
|
@ -191,7 +191,7 @@ class Move
|
|||
bool AllProbeCoordinatesSet(int index) const; // XY, and Z all set for this one?
|
||||
bool XYProbeCoordinatesSet(int index) const; // Just XY set for this one?
|
||||
void SetZProbing(bool probing); // Set the Z probe live
|
||||
void SetProbedBedEquation(char *reply); // When we have a full set of probed points, work out the bed's equation
|
||||
void SetProbedBedEquation(StringRef& reply); // When we have a full set of probed points, work out the bed's equation
|
||||
float SecondDegreeTransformZ(float x, float y) const; // Used for second degree bed equation
|
||||
float GetLastProbedZ() const; // What was the Z when the probe last fired?
|
||||
void SetAxisCompensation(int8_t axis, float tangent); // Set an axis-pair compensation angle
|
||||
|
|
55
Platform.cpp
55
Platform.cpp
|
@ -758,44 +758,44 @@ void Platform::Diagnostics()
|
|||
const char *ramstart = (char *) 0x20070000;
|
||||
const struct mallinfo mi = mallinfo();
|
||||
AppendMessage(BOTH_MESSAGE, "Memory usage:\n\n");
|
||||
snprintf(scratchString, STRING_LENGTH, "Program static ram used: %d\n", &_end - ramstart);
|
||||
scratchString.printf("Program static ram used: %d\n", &_end - ramstart);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
snprintf(scratchString, STRING_LENGTH, "Dynamic ram used: %d\n", mi.uordblks);
|
||||
scratchString.printf("Dynamic ram used: %d\n", mi.uordblks);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
snprintf(scratchString, STRING_LENGTH, "Recycled dynamic ram: %d\n", mi.fordblks);
|
||||
scratchString.printf("Recycled dynamic ram: %d\n", mi.fordblks);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
size_t currentStack, maxStack, neverUsed;
|
||||
GetStackUsage(¤tStack, &maxStack, &neverUsed);
|
||||
snprintf(scratchString, STRING_LENGTH, "Current stack ram used: %d\n", currentStack);
|
||||
scratchString.printf("Current stack ram used: %d\n", currentStack);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
snprintf(scratchString, STRING_LENGTH, "Maximum stack ram used: %d\n", maxStack);
|
||||
scratchString.printf("Maximum stack ram used: %d\n", maxStack);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
snprintf(scratchString, STRING_LENGTH, "Never used ram: %d\n", neverUsed);
|
||||
scratchString.printf("Never used ram: %d\n", neverUsed);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
// Show the up time and reason for the last reset
|
||||
const uint32_t now = (uint32_t)Time(); // get up time in seconds
|
||||
const char* resetReasons[8] = { "power up", "backup", "watchdog", "software", "external", "?", "?", "?" };
|
||||
snprintf(scratchString, STRING_LENGTH, "Last reset %02d:%02d:%02d ago, cause: %s\n",
|
||||
scratchString.printf("Last reset %02d:%02d:%02d ago, cause: %s\n",
|
||||
(unsigned int)(now/3600), (unsigned int)((now % 3600)/60), (unsigned int)(now % 60),
|
||||
resetReasons[(REG_RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos]);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
// Show the error code stored at the last software reset
|
||||
snprintf(scratchString, STRING_LENGTH, "Last software reset code & available RAM: 0x%04x, %u\n", nvData.resetReason, nvData.neverUsedRam);
|
||||
scratchString.printf("Last software reset code & available RAM: 0x%04x, %u\n", nvData.resetReason, nvData.neverUsedRam);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
// Show the current error codes
|
||||
snprintf(scratchString, STRING_LENGTH, "Error status: %u\n", errorCodeBits);
|
||||
scratchString.printf("Error status: %u\n", errorCodeBits);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
// Show the current probe position heights
|
||||
strncpy(scratchString, "Bed probe heights:", STRING_LENGTH);
|
||||
scratchString.copy("Bed probe heights:");
|
||||
for (size_t i = 0; i < NUMBER_OF_PROBE_POINTS; ++i)
|
||||
{
|
||||
sncatf(scratchString, STRING_LENGTH, " %.3f", reprap.GetMove()->ZBedProbePoint(i));
|
||||
scratchString.catf(" %.3f", reprap.GetMove()->ZBedProbePoint(i));
|
||||
}
|
||||
sncatf(scratchString, STRING_LENGTH, "\n");
|
||||
scratchString.cat("\n");
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
// Show the number of free entries in the file table
|
||||
|
@ -807,8 +807,13 @@ void Platform::Diagnostics()
|
|||
++numFreeFiles;
|
||||
}
|
||||
}
|
||||
snprintf(scratchString, STRING_LENGTH, "Free file entries: %u\n", numFreeFiles);
|
||||
scratchString.printf("Free file entries: %u\n", numFreeFiles);
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
// Show the longest write time
|
||||
scratchString.printf("Longest block write time: %.1fms\n", FileStore::GetAndClearLongestWriteTime());
|
||||
AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
|
||||
reprap.Timing();
|
||||
|
||||
#if LWIP_STATS
|
||||
|
@ -859,7 +864,7 @@ void Platform::ClassReport(char* className, float &lastTime)
|
|||
if (Time() - lastTime < LONG_TIME)
|
||||
return;
|
||||
lastTime = Time();
|
||||
snprintf(scratchString, STRING_LENGTH, "Class %s spinning.\n", className);
|
||||
scratchString.printf("Class %s spinning.\n", className);
|
||||
Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
|
@ -1753,8 +1758,8 @@ bool FileStore::WriteBuffer()
|
|||
{
|
||||
if (bufferPointer != 0)
|
||||
{
|
||||
FRESULT writeStatus = f_write(&file, buf, bufferPointer, &lastBufferEntry);
|
||||
if ((writeStatus != FR_OK) || (lastBufferEntry != bufferPointer))
|
||||
bool ok = InternalWriteBlock((const char*)buf, bufferPointer);
|
||||
if (!ok)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Error writing file. Disc may be full.\n");
|
||||
return false;
|
||||
|
@ -1810,9 +1815,19 @@ bool FileStore::Write(const char *s, unsigned int len)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
InternalWriteBlock(s, len);
|
||||
}
|
||||
|
||||
bool FileStore::InternalWriteBlock(const char *s, unsigned int len)
|
||||
{
|
||||
unsigned int bytesWritten;
|
||||
uint32_t time = micros();
|
||||
FRESULT writeStatus = f_write(&file, s, len, &bytesWritten);
|
||||
time = micros() - time;
|
||||
if (time > longestWriteTime)
|
||||
{
|
||||
longestWriteTime = time;
|
||||
}
|
||||
if ((writeStatus != FR_OK) || (bytesWritten != len))
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "Error writing file. Disc may be full.\n");
|
||||
|
@ -1835,6 +1850,14 @@ bool FileStore::Flush()
|
|||
return f_sync(&file) == FR_OK;
|
||||
}
|
||||
|
||||
float FileStore::GetAndClearLongestWriteTime()
|
||||
{
|
||||
float ret = (float)longestWriteTime/1000.0;
|
||||
longestWriteTime = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t FileStore::longestWriteTime = 0;
|
||||
|
||||
//***************************************************************************************************
|
||||
|
||||
|
|
|
@ -364,6 +364,7 @@ public:
|
|||
unsigned long Length(); // File size in bytes
|
||||
void Duplicate(); // Create a second reference to this file
|
||||
bool Flush(); // Write remaining buffer data
|
||||
static float GetAndClearLongestWriteTime(); // Return the longest time it took to write a block to a file, in milliseconds
|
||||
|
||||
friend class Platform;
|
||||
|
||||
|
@ -381,12 +382,15 @@ private:
|
|||
|
||||
bool ReadBuffer();
|
||||
bool WriteBuffer();
|
||||
bool InternalWriteBlock(const char *s, unsigned int len);
|
||||
|
||||
FIL file;
|
||||
Platform* platform;
|
||||
bool writing;
|
||||
unsigned int lastBufferEntry;
|
||||
unsigned int openCount;
|
||||
|
||||
static uint32_t longestWriteTime;
|
||||
};
|
||||
|
||||
|
||||
|
@ -577,8 +581,10 @@ public:
|
|||
|
||||
void Message(char type, const char* message); // Send a message. Messages may simply flash an LED, or,
|
||||
// say, display the messages on an LCD. This may also transmit the messages to the host.
|
||||
void Message(char type, const StringRef& message) { return Message(type, message.Pointer()); }
|
||||
void AppendMessage(char type, const char* message); // Send a message. Messages may simply flash an LED, or,
|
||||
// say, display the messages on an LCD. This may also transmit the messages to the host.
|
||||
void AppendMessage(char type, const StringRef& message) { return AppendMessage(type, message.Pointer()); }
|
||||
void PushMessageIndent();
|
||||
void PopMessageIndent();
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Release/RepRapFirmware-078j-dc42.bin
Normal file
BIN
Release/RepRapFirmware-078j-dc42.bin
Normal file
Binary file not shown.
|
@ -192,7 +192,7 @@ void RepRap::Init()
|
|||
coldExtrude = true; // DC42 changed default to true for compatibility because for now we are aiming for copatibility with RRP 0.78
|
||||
active = true; // must do this before we start the network, else the watchdog may time out
|
||||
|
||||
snprintf(scratchString, STRING_LENGTH, "%s Version %s dated %s\n", NAME, VERSION, DATE);
|
||||
scratchString.printf("%s Version %s dated %s\n", NAME, VERSION, DATE);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
|
||||
platform->Message(HOST_MESSAGE, ".\n\nExecuting ");
|
||||
|
@ -201,8 +201,8 @@ void RepRap::Init()
|
|||
|
||||
// We inject an M98 into the serial input stream to run the start-up macro
|
||||
|
||||
snprintf(scratchString, STRING_LENGTH, "M98 P%s\n", platform->GetConfigFile());
|
||||
platform->GetLine()->InjectString(scratchString);
|
||||
scratchString.printf("M98 P%s\n", platform->GetConfigFile());
|
||||
platform->GetLine()->InjectString(scratchString.Pointer());
|
||||
|
||||
bool runningTheFile = false;
|
||||
bool initialisingInProgress = true;
|
||||
|
@ -228,7 +228,7 @@ void RepRap::Init()
|
|||
network->Init(); // Need to do this here, as the configuration GCodes may set IP address etc.
|
||||
|
||||
platform->Message(HOST_MESSAGE, "\n");
|
||||
snprintf(scratchString, STRING_LENGTH, "%s is up and running.\n", NAME);
|
||||
scratchString.printf("%s is up and running.\n", NAME);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
fastLoop = FLT_MAX;
|
||||
slowLoop = 0.0;
|
||||
|
@ -295,7 +295,7 @@ void RepRap::Spin()
|
|||
|
||||
void RepRap::Timing()
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "Slowest main loop (seconds): %f; fastest: %f\n", slowLoop, fastLoop);
|
||||
scratchString.printf("Slowest main loop (seconds): %f; fastest: %f\n", slowLoop, fastLoop);
|
||||
platform->AppendMessage(BOTH_MESSAGE, scratchString);
|
||||
fastLoop = FLT_MAX;
|
||||
slowLoop = 0.0;
|
||||
|
@ -394,7 +394,7 @@ void RepRap::SelectTool(int toolNumber)
|
|||
|
||||
}
|
||||
|
||||
void RepRap::PrintTool(int toolNumber, char* reply) const
|
||||
void RepRap::PrintTool(int toolNumber, StringRef& reply) const
|
||||
{
|
||||
for(Tool *tool = toolList; tool != NULL; tool = tool->next)
|
||||
{
|
||||
|
@ -404,7 +404,7 @@ void RepRap::PrintTool(int toolNumber, char* reply) const
|
|||
return;
|
||||
}
|
||||
}
|
||||
strcpy(reply, "Attempt to print details of non-existent tool.");
|
||||
reply.copy("Attempt to print details of non-existent tool.");
|
||||
}
|
||||
|
||||
void RepRap::StandbyTool(int toolNumber)
|
||||
|
@ -425,7 +425,7 @@ void RepRap::StandbyTool(int toolNumber)
|
|||
tool = tool->Next();
|
||||
}
|
||||
|
||||
snprintf(scratchString, STRING_LENGTH, "Attempt to standby a non-existent tool: %d.\n", toolNumber);
|
||||
scratchString.printf("Attempt to standby a non-existent tool: %d.\n", toolNumber);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
|
@ -456,7 +456,7 @@ void RepRap::SetToolVariables(int toolNumber, float* standbyTemperatures, float*
|
|||
tool = tool->Next();
|
||||
}
|
||||
|
||||
snprintf(scratchString, STRING_LENGTH, "Attempt to set variables for a non-existent tool: %d.\n", toolNumber);
|
||||
scratchString.printf("Attempt to set variables for a non-existent tool: %d.\n", toolNumber);
|
||||
platform->Message(HOST_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
|
@ -490,39 +490,79 @@ void RepRap::Tick()
|
|||
}
|
||||
|
||||
|
||||
//*************************************************************************************************
|
||||
// StringRef class member implementations
|
||||
|
||||
size_t StringRef::strlen() const
|
||||
{
|
||||
return strnlen(p, len - 1);
|
||||
}
|
||||
|
||||
int StringRef::printf(const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
va_start(vargs, fmt);
|
||||
int ret = vsnprintf(p, len, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int StringRef::vprintf(const char *fmt, va_list vargs)
|
||||
{
|
||||
return vsnprintf(p, len, fmt, vargs);
|
||||
}
|
||||
|
||||
int StringRef::catf(const char *fmt, ...)
|
||||
{
|
||||
size_t n = strlen();
|
||||
if (n + 1 < len) // if room for at least 1 more character and a null
|
||||
{
|
||||
va_list vargs;
|
||||
va_start(vargs, fmt);
|
||||
int ret = vsnprintf(p + n, len - n, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return ret + n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is quicker than printf for printing constant strings
|
||||
size_t StringRef::copy(const char* src)
|
||||
{
|
||||
size_t length = strnlen(src, len - 1);
|
||||
memcpy(p, src, length);
|
||||
p[length] = 0;
|
||||
return length;
|
||||
}
|
||||
|
||||
// This is quicker than catf for printing constant strings
|
||||
size_t StringRef::cat(const char* src)
|
||||
{
|
||||
size_t length = strlen();
|
||||
size_t toCopy = strnlen(src, len - length - 1);
|
||||
memcpy(p + length, src, toCopy);
|
||||
length += toCopy;
|
||||
p[length] = 0;
|
||||
return length;
|
||||
}
|
||||
|
||||
//*************************************************************************************************
|
||||
|
||||
// Utilities and storage not part of any class
|
||||
|
||||
char scratchString[STRING_LENGTH];
|
||||
static char scratchStringBuffer[STRING_LENGTH];
|
||||
StringRef scratchString(scratchStringBuffer, ARRAY_SIZE(scratchStringBuffer));
|
||||
|
||||
// For debug use
|
||||
void debugPrintf(const char* fmt, ...)
|
||||
{
|
||||
va_list p;
|
||||
va_start(p, fmt);
|
||||
vsnprintf(scratchString, ARRAY_SIZE(scratchString), fmt, p);
|
||||
va_end(p);
|
||||
scratchString[ARRAY_UPB(scratchString)] = 0;
|
||||
va_list vargs;
|
||||
va_start(vargs, fmt);
|
||||
scratchString.vprintf(fmt, vargs);
|
||||
va_end(vargs);
|
||||
reprap.GetPlatform()->Message(DEBUG_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
// This behaves like snprintf but appends to an existing string
|
||||
// The second parameter is the length of the entire destination buffer, not the length remaining
|
||||
int sncatf(char *dst, size_t len, const char* fmt, ...)
|
||||
{
|
||||
size_t n = strnlen(dst, len);
|
||||
if (n + 1 < len) // if room for at least 1 more character and a null
|
||||
{
|
||||
va_list p;
|
||||
va_start(p, fmt);
|
||||
int ret = vsnprintf(dst + n, len - n, fmt, p);
|
||||
va_end(p);
|
||||
return ret + n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// String testing
|
||||
|
||||
bool StringEndsWith(const char* string, const char* ending)
|
||||
|
|
|
@ -47,8 +47,6 @@ extern RepRap reprap;
|
|||
|
||||
extern "C" void debugPrintf(const char* fmt, ...);
|
||||
|
||||
int sncatf(char *dst, size_t len, const char* fmt, ...);
|
||||
|
||||
bool StringEndsWith(const char* string, const char* ending);
|
||||
bool StringStartsWith(const char* string, const char* starting);
|
||||
bool StringEquals(const char* s1, const char* s2);
|
||||
|
@ -59,7 +57,33 @@ int StringContains(const char* string, const char* match);
|
|||
// Macro to give us the highest valid index into an array i.e. one less than the size
|
||||
#define ARRAY_UPB(_x) (ARRAY_SIZE(_x) - 1)
|
||||
|
||||
extern char scratchString[];
|
||||
// Class to describe a string buffer, including its length. This saved passing buffer lengths around everywhere.
|
||||
class StringRef
|
||||
{
|
||||
char *p; // pointer to the storage
|
||||
size_t len; // number of characters in the storage
|
||||
|
||||
public:
|
||||
StringRef(char *pp, size_t pl) : p(pp), len(pl) { }
|
||||
|
||||
size_t Length() const { return len; }
|
||||
size_t strlen() const;
|
||||
char *Pointer() { return p; }
|
||||
const char *Pointer() const { return p; }
|
||||
|
||||
char& operator[](size_t index) { return p[index]; }
|
||||
char operator[](size_t index) const { return p[index]; }
|
||||
|
||||
void Clear() { p[0] = 0; }
|
||||
|
||||
int printf(const char *fmt, ...);
|
||||
int vprintf(const char *fmt, va_list vargs);
|
||||
int catf(const char *fmt, ...);
|
||||
size_t copy(const char* src);
|
||||
size_t cat(const char *src);
|
||||
};
|
||||
|
||||
extern StringRef scratchString;
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Configuration.h"
|
||||
|
|
2
Reprap.h
2
Reprap.h
|
@ -44,7 +44,7 @@ class RepRap
|
|||
void AllowColdExtrude();
|
||||
void DenyColdExtrude();
|
||||
bool ColdExtrude() const;
|
||||
void PrintTool(int toolNumber, char* reply) const;
|
||||
void PrintTool(int toolNumber, StringRef& reply) const;
|
||||
void FlagTemperatureFault(int8_t dudHeater);
|
||||
void ClearTemperatureFault(int8_t wasDudHeater);
|
||||
Platform* GetPlatform() const;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; tfree1.g
|
||||
; Put G/M Codes in here to run when Tool 1 is freed
|
||||
G1 X1 Y5 F15000
|
||||
G1 X1 Y5 F6000
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; tfree2.g
|
||||
; Put G/M Codes in here to run when Tool 2 is freed
|
||||
G1 X1 Y5 F15000
|
||||
G1 X1 Y5 F6000
|
||||
|
||||
|
|
12
Tool.cpp
12
Tool.cpp
|
@ -75,9 +75,9 @@ Tool::Tool(int toolNumber, long d[], int dCount, long h[], int hCount)
|
|||
}
|
||||
}
|
||||
|
||||
void Tool::Print(char* reply)
|
||||
void Tool::Print(StringRef& reply)
|
||||
{
|
||||
snprintf(reply, STRING_LENGTH, "Tool %d - drives: ", myNumber);
|
||||
reply.printf("Tool %d - drives: ", myNumber);
|
||||
char comma = ',';
|
||||
for(int8_t drive = 0; drive < driveCount; drive++)
|
||||
{
|
||||
|
@ -85,10 +85,10 @@ void Tool::Print(char* reply)
|
|||
{
|
||||
comma = ';';
|
||||
}
|
||||
sncatf(reply, STRING_LENGTH, "%d%c", drives[drive], comma);
|
||||
reply.catf("%d%c", drives[drive], comma);
|
||||
}
|
||||
|
||||
sncatf(reply, STRING_LENGTH, "heaters (active/standby temps): ");
|
||||
reply.cat("heaters (active/standby temps): ");
|
||||
comma = ',';
|
||||
for(int8_t heater = 0; heater < heaterCount; heater++)
|
||||
{
|
||||
|
@ -96,11 +96,11 @@ void Tool::Print(char* reply)
|
|||
{
|
||||
comma = ';';
|
||||
}
|
||||
sncatf(reply, STRING_LENGTH, "%d (%.1f/%.1f)%c", heaters[heater],
|
||||
reply.catf("%d (%.1f/%.1f)%c", heaters[heater],
|
||||
activeTemperatures[heater], standbyTemperatures[heater], comma);
|
||||
}
|
||||
|
||||
sncatf(reply, STRING_LENGTH, " status: %s", active ? "selected" : "standby");
|
||||
reply.catf(" status: %s", active ? "selected" : "standby");
|
||||
}
|
||||
|
||||
float Tool::MaxFeedrate() const
|
||||
|
|
2
Tool.h
2
Tool.h
|
@ -47,7 +47,7 @@ public:
|
|||
bool Mixing() const;
|
||||
float MaxFeedrate() const;
|
||||
float InstantDv() const;
|
||||
void Print(char* reply);
|
||||
void Print(StringRef& reply);
|
||||
|
||||
friend class RepRap;
|
||||
|
||||
|
|
309
Webserver.cpp
309
Webserver.cpp
|
@ -101,7 +101,8 @@ const float pasvPortTimeout = 10.0; // seconds to wait for the FTP data po
|
|||
|
||||
// Constructor and initialisation
|
||||
Webserver::Webserver(Platform* p) : platform(p), webserverActive(false), readingConnection(NULL),
|
||||
fileInfoDetected(false), filamentCount(DRIVES - AXES), printStartTime(0.0)
|
||||
fileInfoDetected(false), printStartTime(0.0),
|
||||
gcodeReply(gcodeReplyBuffer, ARRAY_SIZE(gcodeReplyBuffer))
|
||||
{
|
||||
httpInterpreter = new HttpInterpreter(p, this);
|
||||
ftpInterpreter = new FtpInterpreter(p, this);
|
||||
|
@ -319,7 +320,7 @@ void Webserver::ProcessGcode(const char* gc)
|
|||
}
|
||||
else if (StringStartsWith(gc, "M23 ")) // select SD card file to print next
|
||||
{
|
||||
fileInfoDetected = GetFileInfo(platform->GetGCodeDir(), &gc[4], length, height, filament, filamentCount, layerHeight, generatedBy, ARRAY_SIZE(generatedBy));
|
||||
fileInfoDetected = GetFileInfo(platform->GetGCodeDir(), &gc[4], currentFileInfo);
|
||||
printStartTime = platform->Time();
|
||||
strncpy(fileBeingPrinted, &gc[4], ARRAY_SIZE(fileBeingPrinted));
|
||||
reprap.GetGCodes()->QueueFileToPrint(&gc[4]);
|
||||
|
@ -354,7 +355,7 @@ void Webserver::ProcessGcode(const char* gc)
|
|||
gcodeReply[i] = 0;
|
||||
|
||||
httpInterpreter->ReceivedGcodeReply();
|
||||
telnetInterpreter->HandleGcodeReply(gcodeReply);
|
||||
telnetInterpreter->HandleGcodeReply(gcodeReply.Pointer());
|
||||
}
|
||||
}
|
||||
else if (StringStartsWith(gc, "M25") && !isDigit(gc[3])) // pause SD card print
|
||||
|
@ -511,17 +512,17 @@ void Webserver::MessageStringToWebInterface(const char *s, bool error)
|
|||
|
||||
if (strlen(s) == 0 && !error)
|
||||
{
|
||||
strcpy(gcodeReply, "ok");
|
||||
gcodeReply.copy("ok");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(gcodeReply, ARRAY_SIZE(gcodeReply), "Error: %s", s);
|
||||
gcodeReply.printf("Error: %s", s);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(gcodeReply, ARRAY_SIZE(gcodeReply), "%s", s);
|
||||
gcodeReply.printf("%s", s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,7 +537,7 @@ void Webserver::AppendReplyToWebInterface(const char *s, bool error)
|
|||
return;
|
||||
}
|
||||
|
||||
sncatf(gcodeReply, ARRAY_SIZE(gcodeReply), "%s", s);
|
||||
gcodeReply.cat(s);
|
||||
httpInterpreter->ReceivedGcodeReply();
|
||||
telnetInterpreter->HandleGcodeReply(s);
|
||||
}
|
||||
|
@ -762,14 +763,36 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command)
|
|||
RequestState *req = net->GetRequest();
|
||||
bool keepOpen = false;
|
||||
bool mayKeepOpen;
|
||||
bool found;
|
||||
char jsonResponseBuffer[jsonReplyLength];
|
||||
StringRef jsonResponse(jsonResponseBuffer, ARRAY_SIZE(jsonResponseBuffer));
|
||||
if (numQualKeys == 0)
|
||||
{
|
||||
mayKeepOpen = GetJsonResponse(command, "", "", 0);
|
||||
found = GetJsonResponse(command, jsonResponse, "", "", 0, mayKeepOpen);
|
||||
}
|
||||
else
|
||||
{
|
||||
mayKeepOpen = GetJsonResponse(command, qualifiers[0].key, qualifiers[0].value, qualifiers[1].key - qualifiers[0].value - 1);
|
||||
found = GetJsonResponse(command, jsonResponse, qualifiers[0].key, qualifiers[0].value, qualifiers[1].key - qualifiers[0].value - 1, mayKeepOpen);
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
jsonResponseBuffer[ARRAY_UPB(jsonResponseBuffer)] = 0;
|
||||
if (webDebug)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "JSON response: ");
|
||||
platform->Message(HOST_MESSAGE, jsonResponseBuffer);
|
||||
platform->Message(HOST_MESSAGE, " queued\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonResponseBuffer[0] = 0;
|
||||
platform->Message(HOST_MESSAGE, "KnockOut request: ");
|
||||
platform->Message(HOST_MESSAGE, command);
|
||||
platform->Message(HOST_MESSAGE, " not recognised\n");
|
||||
}
|
||||
|
||||
if (mayKeepOpen)
|
||||
{
|
||||
// Check that the browser wants to persist the connection too
|
||||
|
@ -785,9 +808,9 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command)
|
|||
}
|
||||
req->Write("HTTP/1.1 200 OK\n");
|
||||
req->Write("Content-Type: application/json\n");
|
||||
req->Printf("Content-Length: %u\n", strlen(jsonResponse));
|
||||
req->Printf("Content-Length: %u\n", jsonResponse.strlen());
|
||||
req->Printf("Connection: %s\n\n", keepOpen ? "keep-alive" : "close");
|
||||
req->Write(jsonResponse);
|
||||
req->Write(jsonResponse.Pointer());
|
||||
net->SendAndClose(NULL, keepOpen);
|
||||
}
|
||||
|
||||
|
@ -795,58 +818,37 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command)
|
|||
|
||||
// Input from the client
|
||||
|
||||
void Webserver::HttpInterpreter::JsonReport(bool ok, const char* request)
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
jsonResponse[ARRAY_UPB(jsonResponse)] = 0;
|
||||
if (webDebug)
|
||||
{
|
||||
platform->Message(HOST_MESSAGE, "JSON response: ");
|
||||
platform->Message(HOST_MESSAGE, jsonResponse);
|
||||
platform->Message(HOST_MESSAGE, " queued\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonResponse[0] = 0;
|
||||
platform->Message(HOST_MESSAGE, "KnockOut request: ");
|
||||
platform->Message(HOST_MESSAGE, request);
|
||||
platform->Message(HOST_MESSAGE, " not recognised\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the Json response for this command.
|
||||
// 'value' is null-terminated, but we also pass its length in case it contains embedded nulls, which matter when uploading files.
|
||||
bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, const char* key, const char* value, size_t valueLength)
|
||||
bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, StringRef& response, const char* key, const char* value, size_t valueLength, bool& keepOpen)
|
||||
{
|
||||
bool found = true; // assume success
|
||||
bool keepOpen = false; // assume we don't want to persist the connection
|
||||
keepOpen = false; // assume we don't want to persist the connection
|
||||
|
||||
if (StringEquals(request, "status")) // new style status request
|
||||
{
|
||||
GetStatusResponse(1);
|
||||
GetStatusResponse(response, 1);
|
||||
}
|
||||
else if (StringEquals(request, "poll")) // old style status request
|
||||
{
|
||||
GetStatusResponse(0);
|
||||
GetStatusResponse(response, 0);
|
||||
}
|
||||
else if (StringEquals(request, "gcode") && StringEquals(key, "gcode"))
|
||||
{
|
||||
webserver->LoadGcodeBuffer(value);
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"buff\":%u}", webserver->GetGcodeBufferSpace());
|
||||
response.printf("{\"buff\":%u}", webserver->GetGcodeBufferSpace());
|
||||
}
|
||||
else if (StringEquals(request, "upload_begin") && StringEquals(key, "name"))
|
||||
{
|
||||
FileStore *file = platform->GetFileStore("0:/", value, true);
|
||||
StartUpload(file);
|
||||
GetJsonUploadResponse();
|
||||
GetJsonUploadResponse(response);
|
||||
}
|
||||
else if (StringEquals(request, "upload_data") && StringEquals(key, "data"))
|
||||
{
|
||||
StoreUploadData(value, valueLength);
|
||||
|
||||
GetJsonUploadResponse();
|
||||
GetJsonUploadResponse(response);
|
||||
keepOpen = true;
|
||||
}
|
||||
else if (StringEquals(request, "upload_end") && StringEquals(key, "size"))
|
||||
|
@ -854,17 +856,17 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, const char
|
|||
long file_length = strtoul(value, NULL, 10);
|
||||
FinishUpload(file_length);
|
||||
|
||||
GetJsonUploadResponse();
|
||||
GetJsonUploadResponse(response);
|
||||
}
|
||||
else if (StringEquals(request, "upload_cancel"))
|
||||
{
|
||||
CancelUpload();
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"err\":%d}", 0);
|
||||
response.printf("{\"err\":%d}", 0);
|
||||
}
|
||||
else if (StringEquals(request, "delete") && StringEquals(key, "name"))
|
||||
{
|
||||
bool ok = platform->GetMassStorage()->Delete("0:/", value);
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"err\":%d}", (ok) ? 0 : 1);
|
||||
response.printf("{\"err\":%d}", (ok) ? 0 : 1);
|
||||
}
|
||||
else if (StringEquals(request, "files"))
|
||||
{
|
||||
|
@ -873,19 +875,20 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, const char
|
|||
FileInfo file_info;
|
||||
if (platform->GetMassStorage()->FindFirst(dir, file_info))
|
||||
{
|
||||
strcpy(jsonResponse, "{\"files\":[");
|
||||
response.copy("{\"files\":[");
|
||||
|
||||
do {
|
||||
// build the file list here, but keep 2 characters free to terminate the JSON message
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse) - 2, "%c%s%c%c", FILE_LIST_BRACKET, file_info.fileName, FILE_LIST_BRACKET, FILE_LIST_SEPARATOR);
|
||||
response.catf("%c%s%c%c", FILE_LIST_BRACKET, file_info.fileName, FILE_LIST_BRACKET, FILE_LIST_SEPARATOR);
|
||||
} while (platform->GetMassStorage()->FindNext(file_info));
|
||||
|
||||
jsonResponse[strlen(jsonResponse) -1] = 0;
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "]}");
|
||||
response[response.strlen() - 1] = 0; // remove last separator
|
||||
response[response.Length() - 3] = 0; // ensure room for 2 more characters and a null
|
||||
response.cat("]}");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(jsonResponse, "{\"files\":[NONE]}");
|
||||
response.copy("{\"files\":[NONE]}");
|
||||
}
|
||||
}
|
||||
else if (StringEquals(request, "fileinfo"))
|
||||
|
@ -893,68 +896,62 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, const char
|
|||
// Poll file info for a specific file
|
||||
if (StringEquals(key, "name"))
|
||||
{
|
||||
unsigned long length;
|
||||
float height, filament[DRIVES - AXES], layerHeight;
|
||||
unsigned int numFilaments = DRIVES - AXES;
|
||||
char generatedBy[50];
|
||||
|
||||
bool found = webserver->GetFileInfo("0:/", value, length, height, filament, numFilaments, layerHeight, generatedBy, ARRAY_SIZE(generatedBy));
|
||||
GcodeFileInfo info;
|
||||
bool found = webserver->GetFileInfo("0:/", value, info);
|
||||
if (found)
|
||||
{
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse),
|
||||
"{\"err\":0,\"size\":%lu,\"height\":%.2f,\"layerHeight\":%.2f,\"filament\":",
|
||||
length, height, layerHeight);
|
||||
response.printf("{\"err\":0,\"size\":%lu,\"height\":%.2f,\"layerHeight\":%.2f,\"filament\":",
|
||||
info.fileSize, info.objectHeight, info.layerHeight);
|
||||
char ch = '[';
|
||||
if (numFilaments == 0)
|
||||
if (info.numFilaments == 0)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c", ch);
|
||||
response.catf("%c", ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < numFilaments; ++i)
|
||||
for (unsigned int i = 0; i < info.numFilaments; ++i)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.1f", ch, filament[i]);
|
||||
response.catf("%c%.1f", ch, info.filamentNeeded[i]);
|
||||
ch = ',';
|
||||
}
|
||||
}
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"generatedBy\":\"%s\"}", generatedBy);
|
||||
response.catf("],\"generatedBy\":\"%s\"}", info.generatedBy);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"err\":1}");
|
||||
response.printf("{\"err\":1}");
|
||||
}
|
||||
}
|
||||
else if (reprap.GetGCodes()->PrintingAFile() && webserver->fileInfoDetected)
|
||||
{
|
||||
// Poll file info about a file currently being printed
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse),
|
||||
"{\"err\":0,\"size\":%lu,\"height\":%.2f,\"layerHeight\":%.2f,\"filament\":",
|
||||
webserver->length, webserver->height, webserver->layerHeight);
|
||||
response.printf("{\"err\":0,\"size\":%lu,\"height\":%.2f,\"layerHeight\":%.2f,\"filament\":",
|
||||
webserver->currentFileInfo.fileSize, webserver->currentFileInfo.objectHeight, webserver->currentFileInfo.layerHeight);
|
||||
char ch = '[';
|
||||
if (webserver->filamentCount == 0)
|
||||
if (webserver->currentFileInfo.numFilaments == 0)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c", ch);
|
||||
response.catf("%c", ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < webserver->filamentCount; ++i)
|
||||
for (unsigned int i = 0; i < webserver->currentFileInfo.numFilaments; ++i)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.1f", ch, webserver->filament[i]);
|
||||
response.catf("%c%.1f", ch, webserver->currentFileInfo.filamentNeeded[i]);
|
||||
ch = ',';
|
||||
}
|
||||
}
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"generatedBy\":\"%s\",\"printDuration\":%d,\"fileName\":\"%s\"}",
|
||||
webserver->generatedBy, (int)((platform->Time() - webserver->printStartTime) * 1000.0), webserver->fileBeingPrinted);
|
||||
response.catf("],\"generatedBy\":\"%s\",\"printDuration\":%d,\"fileName\":\"%s\"}",
|
||||
webserver->currentFileInfo.generatedBy, (int)((platform->Time() - webserver->printStartTime) * 1000.0), webserver->fileBeingPrinted);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"err\":1}");
|
||||
response.copy("{\"err\":1}");
|
||||
}
|
||||
}
|
||||
else if (StringEquals(request, "name"))
|
||||
{
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"myName\":\"");
|
||||
size_t j = strlen(jsonResponse);
|
||||
response.printf("{\"myName\":\"");
|
||||
size_t j = response.strlen();
|
||||
const char *myName = webserver->GetName();
|
||||
for (size_t i = 0; i < SHORT_STRING_LENGTH; ++i)
|
||||
{
|
||||
|
@ -964,50 +961,49 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, const char
|
|||
if (c == '"' || c == '\\')
|
||||
{
|
||||
// Need to escape the quote-mark or backslash for JSON
|
||||
jsonResponse[j++] = '\\';
|
||||
response[j++] = '\\';
|
||||
}
|
||||
jsonResponse[j++] = c;
|
||||
response[j++] = c;
|
||||
}
|
||||
jsonResponse[j++] = '"';
|
||||
jsonResponse[j++] = '}';
|
||||
jsonResponse[j] = 0;
|
||||
response[j++] = '"';
|
||||
response[j++] = '}';
|
||||
response[j] = 0;
|
||||
}
|
||||
else if (StringEquals(request, "password") && StringEquals(key, "password"))
|
||||
{
|
||||
gotPassword = webserver->CheckPassword(value);
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"password\":\"%s\"}", (gotPassword) ? "right" : "wrong");
|
||||
response.printf("{\"password\":\"%s\"}", (gotPassword) ? "right" : "wrong");
|
||||
}
|
||||
else if (StringEquals(request, "axes"))
|
||||
{
|
||||
strcpy(jsonResponse, "{\"axes\":");
|
||||
response.copy("{\"axes\":");
|
||||
char ch = '[';
|
||||
for (int8_t drive = 0; drive < AXES; drive++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse) - 2, "%c%.1f", ch, platform->AxisTotalLength(drive));
|
||||
response.catf("%c%.1f", ch, platform->AxisTotalLength(drive));
|
||||
ch = ',';
|
||||
}
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "]}");
|
||||
response.cat("]}");
|
||||
}
|
||||
else if (StringEquals(request, "connect"))
|
||||
{
|
||||
CancelUpload();
|
||||
GetStatusResponse(1);
|
||||
GetStatusResponse(response, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
JsonReport(found, request);
|
||||
return keepOpen;
|
||||
return found;
|
||||
}
|
||||
|
||||
void Webserver::HttpInterpreter::GetJsonUploadResponse()
|
||||
void Webserver::HttpInterpreter::GetJsonUploadResponse(StringRef& response)
|
||||
{
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"ubuff\":%u,\"err\":%d}", webUploadBufferSize, (uploadState == uploadOK) ? 0 : 1);
|
||||
response.printf("{\"ubuff\":%u,\"err\":%d}", webUploadBufferSize, (uploadState == uploadOK) ? 0 : 1);
|
||||
}
|
||||
|
||||
void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
|
||||
void Webserver::HttpInterpreter::GetStatusResponse(StringRef& response, uint8_t type)
|
||||
{
|
||||
GCodes *gc = reprap.GetGCodes();
|
||||
if (type == 1)
|
||||
|
@ -1015,78 +1011,78 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
|
|||
// New-style status request
|
||||
// Send the printing/idle status
|
||||
char ch = (reprap.IsStopped()) ? 'S' : (gc->PrintingAFile()) ? 'P' : 'I';
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"status\":\"%c\",\"heaters\":", ch);
|
||||
response.printf("{\"status\":\"%c\",\"heaters\":", ch);
|
||||
|
||||
// Send the heater actual temperatures
|
||||
const Heat *heat = reprap.GetHeat();
|
||||
ch = '[';
|
||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.1f", ch, heat->GetTemperature(heater));
|
||||
response.catf("%c%.1f", ch, heat->GetTemperature(heater));
|
||||
ch = ',';
|
||||
}
|
||||
|
||||
// Send the heater active temperatures
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"active\":");
|
||||
response.catf("],\"active\":");
|
||||
ch = '[';
|
||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.1f", ch, heat->GetActiveTemperature(heater));
|
||||
response.catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
|
||||
ch = ',';
|
||||
}
|
||||
|
||||
// Send the heater standby temperatures
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"standby\":");
|
||||
response.catf("],\"standby\":");
|
||||
ch = '[';
|
||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.1f", ch, heat->GetStandbyTemperature(heater));
|
||||
response.catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
|
||||
ch = ',';
|
||||
}
|
||||
|
||||
// Send the heater statuses (0=off, 1=standby, 2=active)
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"hstat\":");
|
||||
response.cat("],\"hstat\":");
|
||||
ch = '[';
|
||||
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%d", ch, (int)heat->GetStatus(heater));
|
||||
response.catf("%c%d", ch, (int)heat->GetStatus(heater));
|
||||
ch = ',';
|
||||
}
|
||||
|
||||
// Send XYZ positions
|
||||
float liveCoordinates[DRIVES + 1];
|
||||
reprap.GetMove()->LiveCoordinates(liveCoordinates);
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"pos\":"); // announce the XYZ position
|
||||
response.catf("],\"pos\":"); // announce the XYZ position
|
||||
ch = '[';
|
||||
for (int8_t drive = 0; drive < AXES; drive++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.2f", ch, liveCoordinates[drive]);
|
||||
response.catf("%c%.2f", ch, liveCoordinates[drive]);
|
||||
ch = ',';
|
||||
}
|
||||
|
||||
// Send extruder total extrusion since power up, last G92 or last M23
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "],\"extr\":"); // announce the extruder positions
|
||||
response.catf("],\"extr\":"); // announce the extruder positions
|
||||
ch = '[';
|
||||
for (int8_t drive = 0; drive < reprap.GetExtrudersInUse(); drive++) // loop through extruders
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.1f", ch, gc->GetExtruderPosition(drive));
|
||||
response.catf("%c%.1f", ch, gc->GetExtruderPosition(drive));
|
||||
ch = ',';
|
||||
}
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "]");
|
||||
response.cat("]");
|
||||
|
||||
// Send the speed and extruder override factors
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"sfactor\":%.2f,\"efactor:\":", gc->GetSpeedFactor() * 100.0);
|
||||
response.catf(",\"sfactor\":%.2f,\"efactor:\":", gc->GetSpeedFactor() * 100.0);
|
||||
const float *extrusionFactors = gc->GetExtrusionFactors();
|
||||
for (unsigned int i = 0; i < reprap.GetExtrudersInUse(); ++i)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "%c%.2f", (i == 0) ? '[' : ',', extrusionFactors[i] * 100.0);
|
||||
response.catf("%c%.2f", (i == 0) ? '[' : ',', extrusionFactors[i] * 100.0);
|
||||
}
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "]");
|
||||
response.cat("]");
|
||||
|
||||
// Send the current tool number
|
||||
Tool* currentTool = reprap.GetCurrentTool();
|
||||
int toolNumber = (currentTool == NULL) ? 0 : currentTool->Number();
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"tool\":%d", toolNumber);
|
||||
response.catf(",\"tool\":%d", toolNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1095,10 +1091,10 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
|
|||
// This is a poor choice of format because we can't easily tell which is which unless we already know the number of heaters and extruders.
|
||||
// RRP reversed the order at version 0.65 to send the positions before the heaters, but we haven't yet done that.
|
||||
char c = (gc->PrintingAFile()) ? 'P' : 'I';
|
||||
snprintf(jsonResponse, ARRAY_SIZE(jsonResponse), "{\"poll\":[\"%c\",", c); // Printing
|
||||
response.printf("{\"poll\":[\"%c\",", c); // Printing
|
||||
for (int8_t heater = 0; heater < HEATERS; heater++)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "\"%.1f\",", reprap.GetHeat()->GetTemperature(heater));
|
||||
response.catf("\"%.1f\",", reprap.GetHeat()->GetTemperature(heater));
|
||||
}
|
||||
// Send XYZ and extruder positions
|
||||
float liveCoordinates[DRIVES + 1];
|
||||
|
@ -1106,7 +1102,7 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
|
|||
for (int8_t drive = 0; drive < DRIVES; drive++) // loop through extruders
|
||||
{
|
||||
char ch = (drive == DRIVES - 1) ? ']' : ','; // append ] to the last one but , to the others
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "\"%.2f\"%c", liveCoordinates[drive], ch);
|
||||
response.catf("\"%.2f\"%c", liveCoordinates[drive], ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1116,45 +1112,45 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
|
|||
switch (platform->GetZProbeSecondaryValues(v1, v2))
|
||||
{
|
||||
case 1:
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"probe\":\"%d (%d)\"", v0, v1);
|
||||
response.catf(",\"probe\":\"%d (%d)\"", v0, v1);
|
||||
break;
|
||||
case 2:
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
|
||||
response.catf(",\"probe\":\"%d (%d, %d)\"", v0, v1, v2);
|
||||
break;
|
||||
default:
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"probe\":\"%d\"", v0);
|
||||
response.catf(",\"probe\":\"%d\"", v0);
|
||||
break;
|
||||
}
|
||||
|
||||
// Send the amount of buffer space available for gcodes
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"buff\":%u", webserver->GetGcodeBufferSpace());
|
||||
response.catf(",\"buff\":%u", webserver->GetGcodeBufferSpace());
|
||||
|
||||
// Send the home state. To keep the messages short, we send 1 for homed and 0 for not homed, instead of true and false.
|
||||
if (type != 0)
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"homed\":[%d,%d,%d]",
|
||||
response.catf(",\"homed\":[%d,%d,%d]",
|
||||
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"hx\":%d,\"hy\":%d,\"hz\":%d",
|
||||
response.catf(",\"hx\":%d,\"hy\":%d,\"hz\":%d",
|
||||
(gc->GetAxisIsHomed(0)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(1)) ? 1 : 0,
|
||||
(gc->GetAxisIsHomed(2)) ? 1 : 0);
|
||||
}
|
||||
|
||||
// Retrieve the gcode buffer from Webserver
|
||||
const char *p = webserver->gcodeReply;
|
||||
const char *p = webserver->gcodeReply.Pointer();
|
||||
|
||||
// Send the response sequence number
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"seq\":%u", (unsigned int) seq);
|
||||
response.catf(",\"seq\":%u", (unsigned int) seq);
|
||||
|
||||
// Send the response to the last command. Do this last because it is long and may need to be truncated.
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), ",\"resp\":\"");
|
||||
size_t jp = strnlen(jsonResponse, ARRAY_SIZE(jsonResponse));
|
||||
while (*p != 0 && jp < ARRAY_SIZE(jsonResponse) - 3) // leave room for the final '"}\0'
|
||||
response.cat(",\"resp\":\"");
|
||||
size_t jp = response.strlen();
|
||||
while (*p != 0 && jp < response.Length() - 3) // leave room for the final '"}\0'
|
||||
{
|
||||
char c = *p++;
|
||||
char esc;
|
||||
|
@ -1181,20 +1177,20 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
|
|||
}
|
||||
if (esc)
|
||||
{
|
||||
if (jp == ARRAY_SIZE(jsonResponse) - 4)
|
||||
if (jp == response.Length() - 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
jsonResponse[jp++] = '\\';
|
||||
jsonResponse[jp++] = esc;
|
||||
response[jp++] = '\\';
|
||||
response[jp++] = esc;
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonResponse[jp++] = c;
|
||||
response[jp++] = c;
|
||||
}
|
||||
}
|
||||
jsonResponse[jp] = 0;
|
||||
sncatf(jsonResponse, ARRAY_SIZE(jsonResponse), "\"}");
|
||||
response[jp] = 0;
|
||||
response.cat("\"}");
|
||||
}
|
||||
|
||||
void Webserver::HttpInterpreter::ResetState()
|
||||
|
@ -1713,7 +1709,7 @@ bool Webserver::FtpInterpreter::CharFromClient(char c)
|
|||
|
||||
if (DebugEnabled())
|
||||
{
|
||||
snprintf(scratchString, STRING_LENGTH, "FtpInterpreter::ProcessLine called with state %d:\n%s\n", state, clientMessage);
|
||||
scratchString.printf("FtpInterpreter::ProcessLine called with state %d:\n%s\n", state, clientMessage);
|
||||
platform->Message(DEBUG_MESSAGE, scratchString);
|
||||
}
|
||||
|
||||
|
@ -2271,9 +2267,9 @@ void Webserver::FtpInterpreter::ChangeDirectory(const char *newDirectory)
|
|||
strncpy(combinedPath, currentDir, maxFilenameLength);
|
||||
if (strlen(currentDir) > 1)
|
||||
{
|
||||
sncatf(combinedPath, maxFilenameLength, "/");
|
||||
strncat(combinedPath, "/", maxFilenameLength - strlen(combinedPath) - 1);
|
||||
}
|
||||
sncatf(combinedPath, maxFilenameLength, "%s", newDirectory);
|
||||
strncat(combinedPath, newDirectory, maxFilenameLength - strlen(combinedPath) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2454,20 +2450,19 @@ void Webserver::TelnetInterpreter::HandleGcodeReply(const char *reply)
|
|||
//********************************************************************************************
|
||||
|
||||
// Get information for a file on the SD card
|
||||
bool Webserver::GetFileInfo(const char *directory, const char *fileName, unsigned long& length, float& height,
|
||||
float *filamentUsed, unsigned int& numFilaments, float& layerHeight, char* generatedBy, size_t generatedByLength)
|
||||
bool Webserver::GetFileInfo(const char *directory, const char *fileName, GcodeFileInfo& info)
|
||||
{
|
||||
FileStore *f = platform->GetFileStore(directory, fileName, false);
|
||||
FileStore *f = reprap.GetPlatform()->GetFileStore(directory, fileName, false);
|
||||
if (f != NULL)
|
||||
{
|
||||
// Try to find the object height by looking for the last G1 Zxxx command in the file
|
||||
length = f->Length();
|
||||
height = 0.0;
|
||||
layerHeight = 0.0;
|
||||
numFilaments = DRIVES - AXES;
|
||||
generatedBy[0] = 0;
|
||||
info.fileSize = f->Length();
|
||||
info.objectHeight = 0.0;
|
||||
info.layerHeight = 0.0;
|
||||
info.numFilaments = DRIVES - AXES;
|
||||
info.generatedBy[0] = 0;
|
||||
|
||||
if (length != 0 && (StringEndsWith(fileName, ".gcode") || StringEndsWith(fileName, ".g") || StringEndsWith(fileName, ".gco") || StringEndsWith(fileName, ".gc")))
|
||||
if (info.fileSize != 0 && (StringEndsWith(fileName, ".gcode") || StringEndsWith(fileName, ".g") || StringEndsWith(fileName, ".gco") || StringEndsWith(fileName, ".gc")))
|
||||
{
|
||||
const size_t readSize = 512; // read 512 bytes at a time (1K doesn't seem to work when we read from the end)
|
||||
const size_t overlap = 100;
|
||||
|
@ -2476,37 +2471,37 @@ bool Webserver::GetFileInfo(const char *directory, const char *fileName, unsigne
|
|||
|
||||
// Get slic3r settings by reading from the start of the file. We only read the first 1K or so, everything we are looking for should be there.
|
||||
{
|
||||
size_t sizeToRead = (size_t)min<unsigned long>(length, readSize + overlap);
|
||||
size_t sizeToRead = (size_t)min<unsigned long>(info.fileSize, readSize + overlap);
|
||||
int nbytes = f->Read(buf, sizeToRead);
|
||||
if (nbytes == (int)sizeToRead)
|
||||
{
|
||||
buf[sizeToRead] = 0;
|
||||
|
||||
// Look for layer height
|
||||
foundLayerHeight = FindLayerHeight(buf, sizeToRead, layerHeight);
|
||||
foundLayerHeight = FindLayerHeight(buf, sizeToRead, info.layerHeight);
|
||||
|
||||
const char* generatedByString = "; generated by ";
|
||||
const char* pos = strstr(buf, generatedByString);
|
||||
size_t generatedByLength = ARRAY_SIZE(info.generatedBy);
|
||||
if (pos != NULL)
|
||||
{
|
||||
pos += strlen(generatedByString);
|
||||
while (generatedByLength > 1 && *pos >= ' ')
|
||||
size_t i = 0;
|
||||
while (i < ARRAY_SIZE(info.generatedBy) - 1 && *pos >= ' ')
|
||||
{
|
||||
char c = *pos++;
|
||||
if (c == '"' || c == '\\')
|
||||
{
|
||||
// Need to escape the quote-mark for JSON
|
||||
if (generatedByLength < 3)
|
||||
if ( i > ARRAY_SIZE(info.generatedBy) - 3)
|
||||
{
|
||||
break;
|
||||
}
|
||||
*generatedBy++ = '\\';
|
||||
--generatedByLength;
|
||||
info.generatedBy[i++] = '\\';
|
||||
}
|
||||
*generatedBy++ = c;
|
||||
--generatedByLength;
|
||||
info.generatedBy[i++] = c;
|
||||
}
|
||||
*generatedBy = 0;
|
||||
info.generatedBy[i] = 0;
|
||||
}
|
||||
|
||||
// Add code to look for other values here...
|
||||
|
@ -2516,19 +2511,19 @@ bool Webserver::GetFileInfo(const char *directory, const char *fileName, unsigne
|
|||
// Now get the object height and filament used by reading the end of the file
|
||||
{
|
||||
size_t sizeToRead;
|
||||
if (length <= readSize + overlap)
|
||||
if (info.fileSize <= readSize + overlap)
|
||||
{
|
||||
sizeToRead = length; // read the whole file in one go
|
||||
sizeToRead = info.fileSize; // read the whole file in one go
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeToRead = length % readSize;
|
||||
sizeToRead = info.fileSize % readSize;
|
||||
if (sizeToRead <= overlap)
|
||||
{
|
||||
sizeToRead += readSize;
|
||||
}
|
||||
}
|
||||
unsigned long seekPos = length - sizeToRead; // read on a 512b boundary
|
||||
unsigned long seekPos = info.fileSize - sizeToRead; // read on a 512b boundary
|
||||
size_t sizeToScan = sizeToRead;
|
||||
unsigned int filamentsFound = 0;
|
||||
for (;;)
|
||||
|
@ -2549,25 +2544,25 @@ bool Webserver::GetFileInfo(const char *directory, const char *fileName, unsigne
|
|||
unsigned int nFilaments = FindFilamentUsed(buf, sizeToScan, filaments, DRIVES - AXES);
|
||||
if (nFilaments != 0 && nFilaments >= filamentsFound)
|
||||
{
|
||||
filamentsFound = min<unsigned int>(nFilaments, numFilaments);
|
||||
filamentsFound = min<unsigned int>(nFilaments, info.numFilaments);
|
||||
for (unsigned int i = 0; i < filamentsFound; ++i)
|
||||
{
|
||||
filamentUsed[i] = filaments[i];
|
||||
info.filamentNeeded[i] = filaments[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Search for layer height
|
||||
if (!foundLayerHeight)
|
||||
{
|
||||
foundLayerHeight = FindLayerHeight(buf, sizeToScan, layerHeight);
|
||||
foundLayerHeight = FindLayerHeight(buf, sizeToScan, info.layerHeight);
|
||||
}
|
||||
|
||||
// Search for object height
|
||||
if (FindHeight(buf, sizeToScan, height))
|
||||
if (FindHeight(buf, sizeToScan, info.objectHeight))
|
||||
{
|
||||
break; // quit if found height
|
||||
}
|
||||
if (seekPos == 0 || length - seekPos >= 200000uL) // scan up to about the last 200K of the file (32K wasn't enough)
|
||||
if (seekPos == 0 || info.fileSize - seekPos >= 200000uL) // scan up to about the last 200K of the file (32K wasn't enough)
|
||||
{
|
||||
break; // quit if reached start of file or already scanned the last 32K of the file
|
||||
}
|
||||
|
@ -2576,7 +2571,7 @@ bool Webserver::GetFileInfo(const char *directory, const char *fileName, unsigne
|
|||
sizeToScan = readSize + overlap;
|
||||
memcpy(buf + sizeToRead, buf, overlap);
|
||||
}
|
||||
numFilaments = filamentsFound;
|
||||
info.numFilaments = filamentsFound;
|
||||
}
|
||||
}
|
||||
f->Close();
|
||||
|
|
34
Webserver.h
34
Webserver.h
|
@ -62,6 +62,18 @@ const unsigned int telnetMessageLength = 256; // maximum line length for incomin
|
|||
|
||||
class Webserver;
|
||||
|
||||
// Class to hold Gcode file information
|
||||
class GcodeFileInfo
|
||||
{
|
||||
public:
|
||||
unsigned long fileSize;
|
||||
float objectHeight;
|
||||
float filamentNeeded[DRIVES - AXES];
|
||||
unsigned int numFilaments;
|
||||
float layerHeight;
|
||||
char generatedBy[50];
|
||||
};
|
||||
|
||||
// This is the abstract class for all supported protocols
|
||||
// Any inherited class should implement a state machine to increase performance and reduce memory usage.
|
||||
class ProtocolInterpreter
|
||||
|
@ -135,10 +147,8 @@ class Webserver
|
|||
|
||||
// File information about the file being printed
|
||||
bool fileInfoDetected;
|
||||
unsigned long length;
|
||||
float height, filament[DRIVES - AXES], layerHeight;
|
||||
unsigned int filamentCount;
|
||||
char generatedBy[50], fileBeingPrinted[255];
|
||||
char fileBeingPrinted[255];
|
||||
GcodeFileInfo currentFileInfo;
|
||||
float printStartTime;
|
||||
|
||||
void MessageStringToWebInterface(const char *s, bool error);
|
||||
|
@ -189,12 +199,11 @@ class Webserver
|
|||
|
||||
void SendFile(const char* nameOfFileToSend);
|
||||
void SendJsonResponse(const char* command);
|
||||
bool GetJsonResponse(const char* request, const char* key, const char* value, size_t valueLength);
|
||||
void GetJsonUploadResponse();
|
||||
void GetStatusResponse(uint8_t type);
|
||||
bool GetJsonResponse(const char* request, StringRef& response, const char* key, const char* value, size_t valueLength, bool& keepOpen);
|
||||
void GetJsonUploadResponse(StringRef& response);
|
||||
void GetStatusResponse(StringRef& response, uint8_t type);
|
||||
bool ProcessMessage();
|
||||
bool RejectMessage(const char* s, unsigned int code = 500);
|
||||
void JsonReport(bool ok, const char* request);
|
||||
|
||||
HttpState state;
|
||||
|
||||
|
@ -220,7 +229,6 @@ class Webserver
|
|||
unsigned int numHeaderKeys; // number of keys we have found, <= maxHeaders
|
||||
|
||||
// Buffers to hold reply
|
||||
char jsonResponse[jsonReplyLength];
|
||||
char decodeChar;
|
||||
uint16_t seq; // reply sequence number, so that the client can tell if a json reply is new or not
|
||||
bool webDebug;
|
||||
|
@ -277,7 +285,7 @@ class Webserver
|
|||
bool CharFromClient(const char c);
|
||||
void ResetState();
|
||||
|
||||
void HandleGcodeReply(const char *reply);
|
||||
void HandleGcodeReply(const char* reply);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -302,8 +310,7 @@ class Webserver
|
|||
void StoreGcodeData(const char* data, size_t len);
|
||||
|
||||
// File info methods
|
||||
bool GetFileInfo(const char *directory, const char *fileName, unsigned long& length, float& height, float *filamentUsed,
|
||||
unsigned int& numFilaments, float& layerHeight, char* generatedBy, size_t generatedByLength);
|
||||
static bool GetFileInfo(const char *directory, const char *fileName, GcodeFileInfo& info);
|
||||
static bool FindHeight(const char* buf, size_t len, float& height);
|
||||
static bool FindLayerHeight(const char* buf, size_t len, float& layerHeight);
|
||||
static unsigned int FindFilamentUsed(const char* buf, size_t len, float *filamentUsed, unsigned int maxFilaments);
|
||||
|
@ -312,7 +319,8 @@ class Webserver
|
|||
// Buffer to hold gcode that is ready for processing
|
||||
char gcodeBuffer[gcodeBufLength];
|
||||
unsigned int gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer
|
||||
char gcodeReply[2048];
|
||||
char gcodeReplyBuffer[2048];
|
||||
StringRef gcodeReply;
|
||||
|
||||
// Misc
|
||||
char password[SHORT_STRING_LENGTH + 1];
|
||||
|
|
Reference in a new issue