Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.settings/language.settings.xml10
-rw-r--r--.settings/org.eclipse.cdt.core.prefs8
-rw-r--r--src/Duet/Webserver.cpp76
-rw-r--r--src/DuetNG/DuetWiFi/Network.cpp25
-rw-r--r--src/DuetNG/DuetWiFi/Network.h4
-rw-r--r--src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp2
-rw-r--r--src/DuetNG/FirmwareUpdater.cpp2
-rw-r--r--src/DuetNG/FtpResponder.cpp49
-rw-r--r--src/DuetNG/HttpResponder.cpp41
-rw-r--r--src/DuetNG/HttpResponder.h1
-rw-r--r--src/DuetNG/NetworkResponder.h2
-rw-r--r--src/GCodes/GCodeBuffer.cpp187
-rw-r--r--src/GCodes/GCodeBuffer.h10
-rw-r--r--src/GCodes/GCodes.cpp71
-rw-r--r--src/GCodes/GCodes.h1
-rw-r--r--src/GCodes/GCodes2.cpp279
-rw-r--r--src/Libraries/General/StringRef.h12
-rw-r--r--src/Movement/Kinematics/ScaraKinematics.cpp22
-rw-r--r--src/Platform.cpp56
-rw-r--r--src/Platform.h9
-rw-r--r--src/RepRap.cpp38
-rw-r--r--src/RepRap.h2
-rw-r--r--src/Storage/MassStorage.cpp28
-rw-r--r--src/Version.h4
24 files changed, 529 insertions, 410 deletions
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 70674390..12317ec3 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="785353586651" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-120605374140718211" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="785353586651" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-120605374140718211" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -27,7 +27,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="785353586651" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-120605374140718211" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -38,7 +38,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="785353586651" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-120605374140718211" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -49,7 +49,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-304732438711739086" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-120605374140718211" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs
index aa815a6f..4252b5c1 100644
--- a/.settings/org.eclipse.cdt.core.prefs
+++ b/.settings/org.eclipse.cdt.core.prefs
@@ -7,6 +7,14 @@ environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.9764
environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289/LINK_FLAGS_2/value=-Wl,--end-group -lm -gcc
environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289/append=true
environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1027429289/appendContributed=true
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/LINK_FLAGS_1/delimiter=;
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/LINK_FLAGS_1/operation=append
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/LINK_FLAGS_1/value=-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry\=Reset_Handler -Wl,--unresolved-symbols\=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/LINK_FLAGS_2/delimiter=;
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/LINK_FLAGS_2/operation=append
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/LINK_FLAGS_2/value=-Wl,--end-group -lm -gcc
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/append=true
+environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887/appendContributed=true
environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290/LINK_FLAGS_1/delimiter=;
environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290/LINK_FLAGS_1/operation=append
environment/project/cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.1275216290/LINK_FLAGS_1/value=-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry\=Reset_Handler -Wl,--unresolved-symbols\=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group
diff --git a/src/Duet/Webserver.cpp b/src/Duet/Webserver.cpp
index 0351e85a..a2ba0f9c 100644
--- a/src/Duet/Webserver.cpp
+++ b/src/Duet/Webserver.cpp
@@ -378,7 +378,7 @@ bool ProtocolInterpreter::StartUpload(FileStore *file, const char *fileName)
if (file != nullptr)
{
fileBeingUploaded.Set(file);
- strncpy(filenameBeingUploaded, fileName, ARRAY_SIZE(filenameBeingUploaded));
+ SafeStrncpy(filenameBeingUploaded, fileName, ARRAY_SIZE(filenameBeingUploaded));
filenameBeingUploaded[ARRAY_UPB(filenameBeingUploaded)] = 0;
uploadState = uploadOK;
@@ -617,7 +617,7 @@ void Webserver::HttpInterpreter::DoFastUpload()
// Grab a copy of the filename and finish this upload
char filename[FILENAME_LENGTH];
- strncpy(filename, filenameBeingUploaded, FILENAME_LENGTH);
+ SafeStrncpy(filename, filenameBeingUploaded, FILENAME_LENGTH);
FinishUpload(postFileLength);
// Update the file timestamp if it was specified before
@@ -825,7 +825,7 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command)
{
const char *configPath = platform->GetMassStorage()->CombineName(platform->GetSysDir(), platform->GetConfigFile());
char fileName[FILENAME_LENGTH];
- strncpy(fileName, configPath, FILENAME_LENGTH);
+ SafeStrncpy(fileName, configPath, FILENAME_LENGTH);
SendFile(fileName, false);
return;
@@ -978,7 +978,7 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff
}
else if (StringEquals(request, "delete") && GetKeyValue("name") != nullptr)
{
- bool ok = platform->GetMassStorage()->Delete(FS_PREFIX, GetKeyValue("name"));
+ const bool ok = platform->GetMassStorage()->Delete(FS_PREFIX, GetKeyValue("name"));
response->printf("{\"err\":%d}", (ok) ? 0 : 1);
}
else if (StringEquals(request, "filelist") && GetKeyValue("dir") != nullptr)
@@ -1011,7 +1011,7 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff
if (nameVal != nullptr)
{
// Regular rr_fileinfo?name=xxx call
- strncpy(filenameBeingProcessed, nameVal, ARRAY_SIZE(filenameBeingProcessed));
+ SafeStrncpy(filenameBeingProcessed, nameVal, ARRAY_SIZE(filenameBeingProcessed));
filenameBeingProcessed[ARRAY_UPB(filenameBeingProcessed)] = 0;
}
else
@@ -1031,17 +1031,22 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff
bool success = false;
if (oldVal != nullptr && newVal != nullptr)
{
- success = platform->GetMassStorage()->Rename(oldVal, newVal);
+ MassStorage * const ms = platform->GetMassStorage();
+ if (StringEquals(GetKeyValue("deleteexisting"), "yes") && ms->FileExists(oldVal) && ms->FileExists(newVal))
+ {
+ ms->Delete(nullptr, newVal, true);
+ }
+ success = ms->Rename(oldVal, newVal);
}
response->printf("{\"err\":%d}", (success) ? 0 : 1);
}
else if (StringEquals(request, "mkdir"))
{
- const char* dirVal = GetKeyValue("dir");
+ const char* const dirVal = GetKeyValue("dir");
bool success = false;
if (dirVal != nullptr)
{
- success = (platform->GetMassStorage()->MakeDirectory(dirVal));
+ success = platform->GetMassStorage()->MakeDirectory(dirVal);
}
response->printf("{\"err\":%d}", (success) ? 0 : 1);
}
@@ -2121,7 +2126,7 @@ void Webserver::FtpInterpreter::ProcessLine()
if (filename[0] != '/')
{
const char *temp = platform->GetMassStorage()->CombineName(currentDir, filename);
- strncpy(filename, temp, FILENAME_LENGTH);
+ SafeStrncpy(filename, temp, FILENAME_LENGTH);
filename[FILENAME_LENGTH - 1] = 0;
}
@@ -2138,7 +2143,7 @@ void Webserver::FtpInterpreter::ProcessLine()
{
// Copy origin path to temp oldFilename and read new path
char oldFilename[FILENAME_LENGTH];
- strncpy(oldFilename, filename, FILENAME_LENGTH);
+ SafeStrncpy(oldFilename, filename, FILENAME_LENGTH);
oldFilename[FILENAME_LENGTH - 1] = 0;
ReadFilename(4);
@@ -2387,41 +2392,42 @@ void Webserver::FtpInterpreter::ChangeDirectory(const char *newDirectory)
/* Prepare the new directory path */
if (newDirectory[0] == '/') // absolute path
{
- strncpy(combinedPath, newDirectory, FILENAME_LENGTH);
+ SafeStrncpy(combinedPath, newDirectory, FILENAME_LENGTH);
combinedPath[FILENAME_LENGTH - 1] = 0;
}
- else // relative path
+ else if (StringEquals(newDirectory, "."))
{
- if (StringEquals(newDirectory, "..")) // go up
+ SafeStrncpy(combinedPath, currentDir, ARRAY_SIZE(combinedPath));
+ }
+ else if (StringEquals(newDirectory, "..")) // go up
+ {
+ if (StringEquals(currentDir, "/"))
{
- if (StringEquals(currentDir, "/"))
- {
- // we're already at the root, so we can't go up any more
- SendReply(550, "Failed to change directory.");
- return;
- }
- else
+ // we're already at the root, so we can't go up any more
+ SendReply(550, "Failed to change directory.");
+ return;
+ }
+ else
+ {
+ SafeStrncpy(combinedPath, currentDir, FILENAME_LENGTH);
+ for(int i=strlen(combinedPath) -2; i>=0; i--)
{
- strncpy(combinedPath, currentDir, FILENAME_LENGTH);
- for(int i=strlen(combinedPath) -2; i>=0; i--)
+ if (combinedPath[i] == '/')
{
- if (combinedPath[i] == '/')
- {
- combinedPath[i +1] = 0;
- break;
- }
+ combinedPath[i +1] = 0;
+ break;
}
}
}
- else // go to child directory
+ }
+ else // go to child directory
+ {
+ SafeStrncpy(combinedPath, currentDir, FILENAME_LENGTH);
+ if (strlen(currentDir) > 1)
{
- strncpy(combinedPath, currentDir, FILENAME_LENGTH);
- if (strlen(currentDir) > 1)
- {
- strncat(combinedPath, "/", FILENAME_LENGTH - strlen(combinedPath) - 1);
- }
- strncat(combinedPath, newDirectory, FILENAME_LENGTH - strlen(combinedPath) - 1);
+ SafeStrncat(combinedPath, "/", FILENAME_LENGTH);
}
+ SafeStrncat(combinedPath, newDirectory, FILENAME_LENGTH);
}
/* Make sure the new path does not end with a '/', because FatFs won't see the directory otherwise */
@@ -2433,7 +2439,7 @@ void Webserver::FtpInterpreter::ChangeDirectory(const char *newDirectory)
/* Verify path and change it */
if (platform->GetMassStorage()->DirectoryExists(combinedPath))
{
- strncpy(currentDir, combinedPath, FILENAME_LENGTH);
+ SafeStrncpy(currentDir, combinedPath, FILENAME_LENGTH);
SendReply(250, "Directory successfully changed.");
}
else
diff --git a/src/DuetNG/DuetWiFi/Network.cpp b/src/DuetNG/DuetWiFi/Network.cpp
index f4c9a2d2..c776fc7c 100644
--- a/src/DuetNG/DuetWiFi/Network.cpp
+++ b/src/DuetNG/DuetWiFi/Network.cpp
@@ -103,7 +103,7 @@ static inline void DisableEspInterrupt()
// WiFi interface class
Network::Network(Platform& p) : platform(p), nextResponderToPoll(nullptr), uploader(nullptr), currentSocket(0), ftpDataPort(0),
- state(NetworkState::disabled), requestedMode(WiFiState::disabled), currentMode(WiFiState::disabled), activated(false),
+ state(NetworkState::disabled), requestedMode(WiFiState::disabled), currentMode(WiFiState::disabled), activated(false), serialRunning(false),
espStatusChanged(false), spiTxUnderruns(0), spiRxOverruns(0)
{
for (size_t i = 0; i < NumProtocols; ++i)
@@ -358,7 +358,7 @@ void Network::Start()
delay(50);
// Release the reset on the ESP8266
- digitalWrite(EspResetPin, HIGH);
+ StartWiFi();
// Give it time to sample GPIO0 and GPIO15
// GPIO0 has to be held high for sufficient time:
@@ -1380,6 +1380,15 @@ void Network::SpiInterrupt()
}
}
+// Start the ESP
+void Network::StartWiFi()
+{
+ digitalWrite(EspResetPin, HIGH);
+ ConfigurePin(g_APinDescription[APINS_UART1]); // connect the pins to UART1
+ Serial1.begin(115200); // initialise the UART, to receive debug info
+ serialRunning = true;
+}
+
// Reset the ESP8266 and leave held in reset
void Network::ResetWiFi()
{
@@ -1387,6 +1396,12 @@ void Network::ResetWiFi()
pinMode(APIN_UART1_TXD, INPUT_PULLUP); // just enable pullups on TxD and RxD pins for now to avoid floating pins
pinMode(APIN_UART1_RXD, INPUT_PULLUP);
currentMode = WiFiState::disabled;
+
+ if (serialRunning)
+ {
+ Serial1.end();
+ serialRunning = false;
+ }
}
// Reset the ESP8266 to take commands from the UART or from external input. The caller must wait for the reset to complete after calling this.
@@ -1397,6 +1412,12 @@ void Network::ResetWiFi()
// 0 0 1 SD card boot (not used in on Duet)
void Network::ResetWiFiForUpload(bool external)
{
+ if (serialRunning)
+ {
+ Serial1.end();
+ serialRunning = false;
+ }
+
// Make sure the ESP8266 is in the reset state
pinMode(EspResetPin, OUTPUT_LOW);
diff --git a/src/DuetNG/DuetWiFi/Network.h b/src/DuetNG/DuetWiFi/Network.h
index fa89cb0b..c2081895 100644
--- a/src/DuetNG/DuetWiFi/Network.h
+++ b/src/DuetNG/DuetWiFi/Network.h
@@ -74,8 +74,9 @@ public:
// The remaining functions are specific to the WiFi version
WifiFirmwareUploader& GetWifiUploader() { return *uploader; }
+ void StartWiFi();
void ResetWiFi();
- static void ResetWiFiForUpload(bool external);
+ void ResetWiFiForUpload(bool external);
const char *GetWiFiServerVersion() const { return wiFiServerVersion; }
@@ -146,6 +147,7 @@ private:
WiFiState requestedMode;
WiFiState currentMode;
bool activated;
+ bool serialRunning;
volatile bool espStatusChanged;
uint8_t ipAddress[4];
diff --git a/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp b/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp
index 8a30af16..e2adb76b 100644
--- a/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp
+++ b/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp
@@ -586,7 +586,7 @@ void WifiFirmwareUploader::Spin()
}
uploadPort.begin(baud);
uploadPort.setInterruptPriority(1); // we are going to move data at seriously high speeds
- Network::ResetWiFiForUpload(false);
+ reprap.GetNetwork().ResetWiFiForUpload(false);
lastAttemptTime = lastResetTime = millis();
state = UploadState::connecting;
}
diff --git a/src/DuetNG/FirmwareUpdater.cpp b/src/DuetNG/FirmwareUpdater.cpp
index 3ed7bf74..1f3b2384 100644
--- a/src/DuetNG/FirmwareUpdater.cpp
+++ b/src/DuetNG/FirmwareUpdater.cpp
@@ -62,7 +62,7 @@ namespace FirmwareUpdater
switch(module)
{
case WifiExternalFirmwareModule:
- Network::ResetWiFiForUpload(true);
+ reprap.GetNetwork().ResetWiFiForUpload(true);
break;
case WifiFirmwareModule:
diff --git a/src/DuetNG/FtpResponder.cpp b/src/DuetNG/FtpResponder.cpp
index f849370b..5c96b30f 100644
--- a/src/DuetNG/FtpResponder.cpp
+++ b/src/DuetNG/FtpResponder.cpp
@@ -819,38 +819,39 @@ void FtpResponder::ChangeDirectory(const char *newDirectory)
{
SafeStrncpy(combinedPath, newDirectory, ARRAY_SIZE(combinedPath));
}
- else // Relative path
+ else if (StringEquals(newDirectory, "."))
{
- if (StringEquals(newDirectory, "..")) // Go up
+ SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath));
+ }
+ else if (StringEquals(newDirectory, "..")) // Go up
+ {
+ // Check if we're already at the root directory
+ if (StringEquals(currentDirectory, "/"))
{
- // Check if we're already at the root directory
- if (StringEquals(currentDirectory, "/"))
- {
- outBuf->copy("550 Failed to change directory.\r\n");
- Commit(responderState);
- return;
- }
+ outBuf->copy("550 Failed to change directory.\r\n");
+ Commit(responderState);
+ return;
+ }
- // No - find the parent directory
- SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath));
- for(int i = strlen(combinedPath) - 2; i >= 0; i--)
+ // No - find the parent directory
+ SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath));
+ for(int i = strlen(combinedPath) - 2; i >= 0; i--)
+ {
+ if (combinedPath[i] == '/')
{
- if (combinedPath[i] == '/')
- {
- combinedPath[i + 1] = 0;
- break;
- }
+ combinedPath[i + 1] = 0;
+ break;
}
}
- else // Go to child directory
+ }
+ else // Go to child directory
+ {
+ SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath));
+ if (!StringEndsWith(combinedPath, "/") && strlen(combinedPath) > 1)
{
- SafeStrncpy(combinedPath, currentDirectory, ARRAY_SIZE(combinedPath));
- if (!StringEndsWith(combinedPath, "/") && strlen(combinedPath) > 1)
- {
- SafeStrncat(combinedPath, "/", ARRAY_SIZE(combinedPath));
- }
- SafeStrncat(combinedPath, newDirectory, ARRAY_SIZE(combinedPath));
+ SafeStrncat(combinedPath, "/", ARRAY_SIZE(combinedPath));
}
+ SafeStrncat(combinedPath, newDirectory, ARRAY_SIZE(combinedPath));
}
// Make sure the new path does not end with a slash, else FatFs won't be able to see the directory
diff --git a/src/DuetNG/HttpResponder.cpp b/src/DuetNG/HttpResponder.cpp
index d48e57d8..df11cbfb 100644
--- a/src/DuetNG/HttpResponder.cpp
+++ b/src/DuetNG/HttpResponder.cpp
@@ -67,21 +67,15 @@ bool HttpResponder::Spin()
case ResponderState::reading:
{
bool readSomething = false;
- for (;;)
+ char c;
+ while (skt->ReadChar(c))
{
- char c;
- if (skt->ReadChar(c))
+ if (CharFromClient(c))
{
- if (CharFromClient(c))
- {
- return true;
- }
- readSomething = true;
- }
- else
- {
- break;
+ timer = millis(); // restart the timeout
+ return true;
}
+ readSomething = true;
}
// Here when we were not able to read a character but we didn't receive a finished message
@@ -522,7 +516,7 @@ bool HttpResponder::GetJsonResponse(const char* request, OutputBuffer *&response
}
else if (StringEquals(request, "delete") && GetKeyValue("name") != nullptr)
{
- bool ok = GetPlatform().GetMassStorage()->Delete(FS_PREFIX, GetKeyValue("name"));
+ const bool ok = GetPlatform().GetMassStorage()->Delete(FS_PREFIX, GetKeyValue("name"));
response->printf("{\"err\":%d}", (ok) ? 0 : 1);
}
else if (StringEquals(request, "filelist") && GetKeyValue("dir") != nullptr)
@@ -565,17 +559,22 @@ bool HttpResponder::GetJsonResponse(const char* request, OutputBuffer *&response
bool success = false;
if (oldVal != nullptr && newVal != nullptr)
{
- success = GetPlatform().GetMassStorage()->Rename(oldVal, newVal);
+ MassStorage * const ms = GetPlatform().GetMassStorage();
+ if (StringEquals(GetKeyValue("deleteexisting"), "yes") && ms->FileExists(oldVal) && ms->FileExists(newVal))
+ {
+ ms->Delete(nullptr, newVal, true);
+ }
+ success = ms->Rename(oldVal, newVal);
}
response->printf("{\"err\":%d}", (success) ? 0 : 1);
}
else if (StringEquals(request, "mkdir"))
{
- const char* dirVal = GetKeyValue("dir");
+ const char* const dirVal = GetKeyValue("dir");
bool success = false;
if (dirVal != nullptr)
{
- success = (GetPlatform().GetMassStorage()->MakeDirectory(dirVal));
+ success = GetPlatform().GetMassStorage()->MakeDirectory(dirVal);
}
response->printf("{\"err\":%d}", (success) ? 0 : 1);
}
@@ -1173,6 +1172,16 @@ void HttpResponder::CancelUpload()
NetworkResponder::CancelUpload();
}
+// This overrides the version in class NetworkResponder
+void HttpResponder::SendData()
+{
+ NetworkResponder::SendData();
+ if (responderState == ResponderState::reading)
+ {
+ timer = millis(); // restart the timer
+ }
+}
+
void HttpResponder::Diagnostics(MessageType mt) const
{
GetPlatform().MessageF(mt, " HTTP(%d)", (int)responderState);
diff --git a/src/DuetNG/HttpResponder.h b/src/DuetNG/HttpResponder.h
index a11f561a..e1e84416 100644
--- a/src/DuetNG/HttpResponder.h
+++ b/src/DuetNG/HttpResponder.h
@@ -28,6 +28,7 @@ public:
protected:
void ConnectionLost() override;
void CancelUpload() override;
+ void SendData() override;
private:
static const size_t MaxHttpSessions = 8; // maximum number of simultaneous HTTP sessions
diff --git a/src/DuetNG/NetworkResponder.h b/src/DuetNG/NetworkResponder.h
index 6e4ace6c..92187380 100644
--- a/src/DuetNG/NetworkResponder.h
+++ b/src/DuetNG/NetworkResponder.h
@@ -46,7 +46,7 @@ protected:
// States machine control. Not all derived classes use all states.
enum class ResponderState
{
- free, // ready to be allocated
+ free = 0, // ready to be allocated
reading, // ready to receive data
sending, // sending data
uploading, // uploading a file to SD card
diff --git a/src/GCodes/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer.cpp
index 666731b5..c416d93e 100644
--- a/src/GCodes/GCodeBuffer.cpp
+++ b/src/GCodes/GCodeBuffer.cpp
@@ -523,67 +523,53 @@ const void GCodeBuffer::GetLongArray(long l[], size_t& returnedLength)
}
}
-// Get a string after a G Code letter found by a call to Seen().
-// It will be the whole of the rest of the GCode string, so strings should always be the last parameter.
-// Use the other overload of GetString to get strings that may not be the last parameter, or may be quoted.
-const char* GCodeBuffer::GetString()
+// Get and copy a quoted string returning true if successful
+bool GCodeBuffer::GetQuotedString(const StringRef& str)
{
+ str.Clear();
if (readPointer >= 0)
{
- commandEnd = gcodeLineEnd; // the string is the remainder of the line of gcode
- const char* const result = &gcodeBuffer[readPointer + 1];
- readPointer = -1;
- return result;
+ ++readPointer; // skip the character that introduced the string
+ return gcodeBuffer[readPointer] == '"' && InternalGetQuotedString(str);
}
INTERNAL_ERROR;
- return "";
+ return false;
}
-// Get and copy a quoted string returning true if successful
-bool GCodeBuffer::GetQuotedString(const StringRef& str)
+// Given that the current character is double-quote, fetch the quoted string
+bool GCodeBuffer::InternalGetQuotedString(const StringRef& str)
{
- str.Clear();
- if (readPointer >= 0)
+ ++readPointer;
+ for (;;)
{
- ++readPointer; // skip the character that introduced the string
- if (gcodeBuffer[readPointer] == '"')
+ char c = gcodeBuffer[readPointer++];
+ if (c < ' ')
+ {
+ return false;
+ }
+ if (c == '"')
{
- ++readPointer;
- for (;;)
+ if (gcodeBuffer[readPointer++] != '"')
{
- char c = gcodeBuffer[readPointer++];
- if (c < ' ')
- {
- return false;
- }
- if (c == '"')
- {
- if (gcodeBuffer[readPointer++] != '"')
- {
- return true;
- }
- }
- else if (c == '\'')
- {
- if (isalpha(gcodeBuffer[readPointer]))
- {
- // Single quote before an alphabetic character forces that character to lower case
- c = tolower(gcodeBuffer[readPointer++]);
- }
- else if (gcodeBuffer[readPointer] == c)
- {
- // Two single quotes are used to represent one
- ++readPointer;
- }
- }
- str.cat(c);
+ return true;
}
}
- return false;
+ else if (c == '\'')
+ {
+ if (isalpha(gcodeBuffer[readPointer]))
+ {
+ // Single quote before an alphabetic character forces that character to lower case
+ c = tolower(gcodeBuffer[readPointer++]);
+ }
+ else if (gcodeBuffer[readPointer] == c)
+ {
+ // Two single quotes are used to represent one
+ ++readPointer;
+ }
+ }
+ str.cat(c);
}
-
- INTERNAL_ERROR;
return false;
}
@@ -592,54 +578,51 @@ bool GCodeBuffer::GetPossiblyQuotedString(const StringRef& str)
{
if (readPointer >= 0)
{
- if (gcodeBuffer[readPointer + 1] == '"')
- {
- return GetQuotedString(str);
- }
-
- commandEnd = gcodeLineEnd; // the string is the remainder of the line of gcode
- str.Clear();
- for (;;)
- {
- ++readPointer;
- const char c = gcodeBuffer[readPointer];
- if (c < ' ')
- {
- break;
- }
- str.cat(c);
- }
- str.StripTrailingSpaces();
- return !str.IsEmpty();
+ ++readPointer;
+ return InternalGetPossiblyQuotedString(str);
}
INTERNAL_ERROR;
return false;
}
-// This returns a pointer to the end of the buffer where a string starts.
+// Get and copy a string which may or may not be quoted, starting at readPointer
+bool GCodeBuffer::InternalGetPossiblyQuotedString(const StringRef& str)
+{
+ str.Clear();
+ if (gcodeBuffer[readPointer] == '"')
+ {
+ return InternalGetQuotedString(str);
+ }
+
+ commandEnd = gcodeLineEnd; // the string is the remainder of the line of gcode
+ for (;;)
+ {
+ const char c = gcodeBuffer[readPointer++];
+ if (c < ' ')
+ {
+ break;
+ }
+ str.cat(c);
+ }
+ str.StripTrailingSpaces();
+ return !str.IsEmpty();
+}
+
+// This returns a string comprising the rest of the line, excluding any comment
// It is provided for legacy use, in particular in the M23
// command that sets the name of a file to be printed. In
// preference use GetString() which requires the string to have
// been preceded by a tag letter.
-// If no string was provided, it produces an error message if the string was not optional, and returns nullptr.
-const char* GCodeBuffer::GetUnprecedentedString(bool optional)
+bool GCodeBuffer::GetUnprecedentedString(const StringRef& str)
{
- commandEnd = gcodeLineEnd; // the string is the remainder of the line
- size_t i;
+ readPointer = parameterStart;
char c;
- for (i = parameterStart; i < commandEnd && ((c = gcodeBuffer[i]) == ' ' || c == '\t'); ++i) { }
-
- if (i == commandEnd)
+ while ((unsigned int)readPointer < commandEnd && ((c = gcodeBuffer[readPointer]) == ' ' || c == '\t'))
{
- if (!optional)
- {
- reprap.GetPlatform().MessageF(ErrorMessage, "%c%d: String expected but not seen.\n", commandLetter, commandNumber);
- }
- return nullptr;
+ ++readPointer; // skip leading spaces
}
-
- return &gcodeBuffer[i];
+ return InternalGetPossiblyQuotedString(str);
}
// Get an int32 after a G Code letter
@@ -802,6 +785,44 @@ bool GCodeBuffer::GetIPAddress(uint32_t& ip)
return ok;
}
+// Get a MAX address sextet after a key letter
+bool GCodeBuffer::GetMacAddress(uint8_t mac[6])
+{
+ if (readPointer < 0)
+ {
+ INTERNAL_ERROR;
+ return false;
+ }
+
+ const char* p = &gcodeBuffer[readPointer + 1];
+ unsigned int n = 0;
+ for (;;)
+ {
+ char *pp;
+ const unsigned long v = strtoul(p, &pp, 16);
+ if (pp == p || v > 255)
+ {
+ readPointer = -1;
+ return false;
+ }
+ mac[n] = (uint8_t)v;
+ ++n;
+ p = pp;
+ if (*p != ':')
+ {
+ break;
+ }
+ if (n == 6)
+ {
+ readPointer = -1;
+ return false;
+ }
+ ++p;
+ }
+ readPointer = -1;
+ return n == 6;
+}
+
// Get the original machine state before we pushed anything
GCodeMachineState& GCodeBuffer::OriginalMachineState() const
{
@@ -882,4 +903,10 @@ void GCodeBuffer::MessageAcknowledged(bool cancelled)
}
}
+// Return true if we can queue gcodes from this source
+bool GCodeBuffer::CanQueueCodes() const
+{
+ return queueCodes || machineState->doingFileMacro; // return true if we queue commands form this source or we are executing a macro
+}
+
// End
diff --git a/src/GCodes/GCodeBuffer.h b/src/GCodes/GCodeBuffer.h
index f8a71b61..0846a007 100644
--- a/src/GCodes/GCodeBuffer.h
+++ b/src/GCodes/GCodeBuffer.h
@@ -35,8 +35,8 @@ public:
uint32_t GetUIValue(); // Get an unsigned integer value
bool GetIPAddress(uint8_t ip[4]); // Get an IP address quad after a key letter
bool GetIPAddress(uint32_t& ip); // Get an IP address quad after a key letter
- const char* GetUnprecedentedString(bool optional = false); // Get a string with no preceding key letter
- const char* GetString(); // Get an unquoted string after a key letter
+ bool GetMacAddress(uint8_t mac[6]); // Get a MAX address sextet after a key letter
+ bool GetUnprecedentedString(const StringRef& str); // Get a string with no preceding key letter
bool GetQuotedString(const StringRef& str); // Get and copy a quoted string
bool GetPossiblyQuotedString(const StringRef& str); // Get and copy a string which may or may not be quoted
const void GetFloatArray(float a[], size_t& length, bool doPad) __attribute__((hot)); // Get a :-separated list of floats after a key letter
@@ -71,7 +71,7 @@ public:
void SetState(GCodeState newState);
void AdvanceState();
const char *GetIdentity() const { return identity; }
- const bool CanQueueCodes() const { return queueCodes; }
+ bool CanQueueCodes() const;
void MessageAcknowledged(bool cancelled);
FilePosition GetFilePosition(size_t bytesCached) const; // Get the file position at the start of the current command
bool IsWritingBinary() const; // returns true if writing binary
@@ -102,6 +102,10 @@ private:
void StoreAndAddToChecksum(char c);
bool LineFinished(); // Deal with receiving end-of-line and return true if we have a command
void DecodeCommand();
+ bool InternalGetQuotedString(const StringRef& str)
+ pre (gcodeBuffer[readPointer] == '"'; str.IsEmpty());
+ bool InternalGetPossiblyQuotedString(const StringRef& str)
+ pre (readPointer >= 0);
GCodeMachineState *machineState; // Machine state for this gcode source
char gcodeBuffer[GCODE_LENGTH]; // The G Code
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 72a10788..dfb93a62 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -630,26 +630,29 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, StringRef& reply)
case GCodeState::stopping: // MO after executing stop.g if present
case GCodeState::sleeping: // M1 after executing sleep.g if present
- // Deselect the active tool and turn off all heaters, unless parameter Hn was used with n > 0
- if (!gb.Seen('H') || gb.GetIValue() <= 0)
+ if (simulationMode == 0)
{
- Tool* tool = reprap.GetCurrentTool();
- if (tool != nullptr)
+ // Deselect the active tool and turn off all heaters, unless parameter Hn was used with n > 0
+ if (!gb.Seen('H') || gb.GetIValue() <= 0)
{
- reprap.StandbyTool(tool->Number());
+ Tool* tool = reprap.GetCurrentTool();
+ if (tool != nullptr)
+ {
+ reprap.StandbyTool(tool->Number());
+ }
+ reprap.GetHeat().SwitchOffAll();
}
- reprap.GetHeat().SwitchOffAll();
- }
- // chrishamm 2014-18-10: Although RRP says M0 is supposed to turn off all drives and heaters,
- // I think M1 is sufficient for this purpose. Leave M0 for a normal reset.
- if (gb.GetState() == GCodeState::sleeping)
- {
- DisableDrives();
- }
- else
- {
- platform.SetDriversIdle();
+ // chrishamm 2014-18-10: Although RRP says M0 is supposed to turn off all drives and heaters,
+ // I think M1 is sufficient for this purpose. Leave M0 for a normal reset.
+ if (gb.GetState() == GCodeState::sleeping)
+ {
+ DisableDrives();
+ }
+ else
+ {
+ platform.SetDriversIdle();
+ }
}
gb.SetState(GCodeState::normal);
break;
@@ -3376,42 +3379,6 @@ void GCodes::DisableDrives()
SetAllAxesNotHomed();
}
-void GCodes::SetMACAddress(GCodeBuffer& gb)
-{
- uint8_t mac[6];
- const char* ipString = gb.GetString();
- uint8_t sp = 0;
- uint8_t spp = 0;
- uint8_t ipp = 0;
- while (ipString[sp])
- {
- if (ipString[sp] == ':')
- {
- mac[ipp] = strtoul(&ipString[spp], nullptr, 16);
- ipp++;
- if (ipp > 5)
- {
- break;
- }
- sp++;
- spp = sp;
- }
- else
- {
- sp++;
- }
- }
- if (ipp == 5)
- {
- mac[ipp] = strtoul(&ipString[spp], nullptr, 16);
- platform.SetMACAddress(mac);
- }
- else
- {
- platform.MessageF(ErrorMessage, "Dud MAC address: %s\n", gb.Buffer());
- }
-}
-
bool GCodes::ChangeMicrostepping(size_t drive, int microsteps, int mode) const
{
bool dummy;
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index f3ce9b91..e44f7756 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -246,7 +246,6 @@ private:
bool Push(GCodeBuffer& gb); // Push feedrate etc on the stack
void Pop(GCodeBuffer& gb); // Pop feedrate etc
void DisableDrives(); // Turn the motors off
- void SetMACAddress(GCodeBuffer& gb); // Deals with an M540
void HandleReply(GCodeBuffer& gb, bool error, const char *reply); // Handle G-Code replies
void HandleReply(GCodeBuffer& gb, bool error, OutputBuffer *reply);
bool OpenFileToWrite(GCodeBuffer& gb, const char* directory, const char* fileName, const FilePosition size, const bool binaryWrite, const uint32_t fileCRC32);
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 4d1bfec9..ff398b1a 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -294,7 +294,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
{
const bool wasPaused = isPaused; // isPaused gets cleared by CancelPrint
- StopPrint(&gb == fileGCode); // if this is normal end-of-print commanded by the file, deleted the resurrect.g file
+ StopPrint(&gb == fileGCode); // if this is normal end-of-print commanded by the file, delete the resurrect.g file
// If we are cancelling a paused print with M0 and we are homed and cancel.g exists then run it and do nothing else
if (wasPaused && code == 0 && AllAxesAreHomed() && DoFileMacro(gb, CANCEL_G, false))
@@ -443,11 +443,19 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
{
OutputBuffer *fileResponse;
const int sparam = (gb.Seen('S')) ? gb.GetIValue() : 0;
- const char* dir = (gb.Seen('P')) ? gb.GetString() : platform.GetGCodeDir();
+ String<FILENAME_LENGTH> dir;
+ if (gb.Seen('P'))
+ {
+ gb.GetPossiblyQuotedString(dir.GetRef());
+ }
+ else
+ {
+ dir.GetRef().copy(platform.GetGCodeDir());
+ }
if (sparam == 2)
{
- fileResponse = reprap.GetFilesResponse(dir, true); // Send the file list in JSON format
+ fileResponse = reprap.GetFilesResponse(dir.Pointer(), true); // Send the file list in JSON format
fileResponse->cat('\n');
}
else
@@ -469,7 +477,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
bool encapsulateList = ((&gb != serialGCode && &gb != telnetGCode) || platform.Emulating() != marlin);
FileInfo fileInfo;
- if (platform.GetMassStorage()->FindFirst(dir, fileInfo))
+ if (platform.GetMassStorage()->FindFirst(dir.Pointer(), fileInfo))
{
// iterate through all entries and append each file name
do {
@@ -537,12 +545,12 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
return false;
}
{
- const char* filename = gb.GetUnprecedentedString();
- if (filename != nullptr)
+ String<FILENAME_LENGTH> filename;
+ if (gb.GetUnprecedentedString(filename.GetRef()))
{
- if (QueueFileToPrint(filename, reply))
+ if (QueueFileToPrint(filename.Pointer(), reply))
{
- reprap.GetPrintMonitor().StartingPrint(filename);
+ reprap.GetPrintMonitor().StartingPrint(filename.Pointer());
if (platform.Emulating() == marlin && (&gb == serialGCode || &gb == telnetGCode))
{
reply.copy("File opened\nFile selected");
@@ -550,7 +558,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
else
{
// Command came from web interface or PanelDue, or not emulating Marlin, so send a nicer response
- reply.printf("File %s selected for printing", filename);
+ reply.printf("File %s selected for printing", filename.Pointer());
}
if (code == 32)
@@ -563,6 +571,11 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
result = GCodeResult::error;
}
}
+ else
+ {
+ reply.copy("Filename expected");
+ result = GCodeResult::error;
+ }
}
break;
@@ -697,20 +710,25 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 28: // Write to file
{
- const char* const str = gb.GetUnprecedentedString();
- if (str != nullptr)
+ String<FILENAME_LENGTH> filename;
+ if (gb.GetUnprecedentedString(filename.GetRef()))
{
- const bool ok = OpenFileToWrite(gb, platform.GetGCodeDir(), str, 0, false, 0);
+ const bool ok = OpenFileToWrite(gb, platform.GetGCodeDir(), filename.Pointer(), 0, false, 0);
if (ok)
{
- reply.printf("Writing to file: %s", str);
+ reply.printf("Writing to file: %s", filename.Pointer());
}
else
{
- reply.printf("Can't open file %s for writing.", str);
+ reply.printf("Can't open file %s for writing.", filename.Pointer());
result = GCodeResult::error;
}
}
+ else
+ {
+ reply.copy("Filename expected");
+ result = GCodeResult::error;
+ }
}
break;
@@ -720,10 +738,15 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 30: // Delete file
{
- const char *filename = gb.GetUnprecedentedString();
- if (filename != nullptr)
+ String<FILENAME_LENGTH> filename;
+ if (gb.GetUnprecedentedString(filename.GetRef()))
{
- platform.GetMassStorage()->Delete(platform.GetGCodeDir(), filename, false);;
+ platform.GetMassStorage()->Delete(platform.GetGCodeDir(), filename.Pointer(), false);
+ }
+ else
+ {
+ reply.copy("Filename expected");
+ result = GCodeResult::error;
}
}
break;
@@ -736,9 +759,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
return false;
}
{
- const char* filename = gb.GetUnprecedentedString(true); // get filename, or nullptr if none provided
+ String<FILENAME_LENGTH> filename;
+ const bool gotFilename = gb.GetUnprecedentedString(filename.GetRef());
OutputBuffer *fileInfoResponse;
- bool done = reprap.GetPrintMonitor().GetFileInfoResponse(filename, fileInfoResponse);
+ const bool done = reprap.GetPrintMonitor().GetFileInfoResponse((gotFilename) ? filename.Pointer() : nullptr, fileInfoResponse);
if (done)
{
fileInfoResponse->cat('\n');
@@ -835,15 +859,23 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (fileBeingHashed == nullptr)
{
// See if we can open the file and start hashing
- const char* filename = gb.GetUnprecedentedString(true);
- if (StartHash(filename))
+ String<FILENAME_LENGTH> filename;
+ if (gb.GetUnprecedentedString(filename.GetRef()))
{
- // Hashing is now in progress...
- result = GCodeResult::notFinished;
+ if (StartHash(filename.Pointer()))
+ {
+ // Hashing is now in progress...
+ result = GCodeResult::notFinished;
+ }
+ else
+ {
+ reply.printf("Cannot open file: %s", filename.Pointer());
+ result = GCodeResult::error;
+ }
}
else
{
- reply.printf("Cannot open file: %s", filename);
+ reply.copy("Filename expected");
result = GCodeResult::error;
}
}
@@ -973,7 +1005,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 98: // Call Macro/Subprogram
if (gb.Seen('P'))
{
- DoFileMacro(gb, gb.GetString(), true);
+ String<FILENAME_LENGTH> filename;
+ gb.GetPossiblyQuotedString(filename.GetRef());
+ DoFileMacro(gb, filename.Pointer(), true);
}
break;
@@ -1254,8 +1288,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 117: // Display message
{
- const char *msg = gb.GetUnprecedentedString(true);
- reprap.SetMessage((msg == nullptr) ? "" : msg);
+ String<FILENAME_LENGTH> msg;
+ gb.GetUnprecedentedString(msg.GetRef());
+ reprap.SetMessage(msg.Pointer());
}
break;
@@ -1301,72 +1336,16 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
break;
- case 140: // Set bed temperature
- {
- Heat& heat = reprap.GetHeat();
- int8_t bedHeater;
- if (gb.Seen('H'))
- {
- bedHeater = gb.GetIValue();
- if (bedHeater < 0)
- {
- // Make sure we stay within reasonable boundaries...
- bedHeater = -1;
- }
- else if (bedHeater >= (int)Heaters)
- {
- reply.printf("Invalid heater number '%d'", bedHeater);
- result = GCodeResult::error;
- break;
- }
- heat.SetBedHeater(bedHeater);
- platform.UpdateConfiguredHeaters();
-
- if (bedHeater < 0)
- {
- // Stop here if the hot bed has been disabled
- break;
- }
- }
- else
- {
- bedHeater = heat.GetBedHeater();
- if (bedHeater < 0)
- {
- reply.copy("Hot bed is not present");
- result = GCodeResult::error;
- break;
- }
- }
-
- if (gb.Seen('S'))
- {
- const float temperature = gb.GetFValue();
- if (temperature < NEARLY_ABS_ZERO)
- {
- heat.SwitchOff(bedHeater);
- }
- else
- {
- heat.SetActiveTemperature(bedHeater, temperature);
- heat.Activate(bedHeater);
- }
- }
- if (gb.Seen('R'))
- {
- heat.SetStandbyTemperature(bedHeater, gb.GetFValue());
- }
- }
- break;
-
+ case 140: // Bed temperature
case 141: // Chamber temperature
{
Heat& heat = reprap.GetHeat();
bool seen = false;
+
+ // See if the heater number is being set
if (gb.Seen('H'))
{
seen = true;
-
int heater = gb.GetIValue();
if (heater < 0)
{
@@ -1374,23 +1353,35 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
else if (heater >= (int)Heaters)
{
- reply.printf("Bad heater number '%d'", heater);
+ reply.printf("Invalid heater number '%d'", heater);
result = GCodeResult::error;
break;
}
- else
+
+ if (code == 141)
{
heat.SetChamberHeater(heater);
- platform.UpdateConfiguredHeaters();
}
+ else
+ {
+ heat.SetBedHeater(heater);
+ }
+ platform.UpdateConfiguredHeaters();
}
+ const int8_t currentHeater = (code == 141) ? heat.GetChamberHeater() : heat.GetBedHeater();
+ const char* heaterName = (code == 141) ? "chamber" : "bed";
+
+ // Active temperature
if (gb.Seen('S'))
{
seen = true;
-
- const int8_t currentHeater = heat.GetChamberHeater();
- if (currentHeater != -1)
+ if (currentHeater < 0)
+ {
+ reply.printf("No %s heater has been configured", heaterName);
+ result = GCodeResult::error;
+ }
+ else
{
const float temperature = gb.GetFValue();
if (temperature < NEARLY_ABS_ZERO)
@@ -1403,23 +1394,32 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
heat.Activate(currentHeater);
}
}
- else
+ }
+
+ if (gb.Seen('R'))
+ {
+ seen = true;
+ if (currentHeater < 0)
{
- reply.copy("No chamber heater has been configured");
+ reply.printf("No %s heater has been configured", heaterName);
result = GCodeResult::error;
}
+ else
+ {
+ heat.SetStandbyTemperature(currentHeater, gb.GetFValue());
+ }
}
if (!seen)
{
- const int8_t currentHeater = reprap.GetHeat().GetChamberHeater();
- if (currentHeater != -1)
+ if (currentHeater < 0)
{
- reply.printf("Chamber heater %d is currently at %.1f" DEGREE_SYMBOL "C", currentHeater, (double)reprap.GetHeat().GetTemperature(currentHeater));
+ reply.printf("No %s heater has been configured", heaterName);
}
else
{
- reply.copy("No chamber heater has been configured");
+ reply.printf("%c%s heater %d is currently at %.1f" DEGREE_SYMBOL "C",
+ toupper(heaterName[0]), heaterName + 1, currentHeater, (double)reprap.GetHeat().GetTemperature(currentHeater));
}
}
}
@@ -2360,12 +2360,21 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 540: // Set/report MAC address
if (gb.Seen('P'))
{
- SetMACAddress(gb);
+ uint8_t mac[6];
+ if (gb.GetMacAddress(mac))
+ {
+ platform.SetMACAddress(mac);
+ }
+ else
+ {
+ reply.copy("Bad MAC address");
+ result = GCodeResult::error;
+ }
}
else
{
- const byte* mac = platform.MACAddress();
- reply.printf("MAC: %x:%x:%x:%x:%x:%x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ const uint8_t *mac = platform.MACAddress();
+ reply.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
break;
@@ -2620,17 +2629,25 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
folder = platform.GetWebDir();
defaultFile = INDEX_PAGE_FILE;
}
- const char* filename = (gb.Seen('P') ? gb.GetString() : defaultFile);
+ String<FILENAME_LENGTH> filename;
+ if (gb.Seen('P'))
+ {
+ gb.GetPossiblyQuotedString(filename.GetRef());
+ }
+ else
+ {
+ filename.GetRef().copy(defaultFile);
+ }
const FilePosition size = (gb.Seen('S') ? (FilePosition)gb.GetIValue() : 0);
const uint32_t crc32 = (gb.Seen('C') ? gb.GetUIValue() : 0);
- const bool ok = OpenFileToWrite(gb, folder, filename, size, true, crc32);
+ const bool ok = OpenFileToWrite(gb, folder, filename.Pointer(), size, true, crc32);
if (ok)
{
- reply.printf("Writing to file: %s", filename);
+ reply.printf("Writing to file: %s", filename.Pointer());
}
else
{
- reply.printf("Can't open file %s for writing.", filename);
+ reply.printf("Can't open file %s for writing.", filename.Pointer());
result = GCodeResult::error;
}
}
@@ -3926,7 +3943,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 752: // Start 3D scan
if (gb.Seen('P'))
{
- const char *file = gb.GetString();
+ String<FILENAME_LENGTH> file;
+ gb.GetPossiblyQuotedString(file.GetRef());
if (gb.Seen('S'))
{
const int sParam = gb.GetIValue();
@@ -3934,7 +3952,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
{
if (reprap.GetScanner().IsRegistered())
{
- result = GetGCodeResultFromFinished(reprap.GetScanner().StartScan(file, sParam));
+ result = GetGCodeResultFromFinished(reprap.GetScanner().StartScan(file.Pointer(), sParam));
}
else
{
@@ -4066,8 +4084,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
seen = true;
// Set date
- const char * const dateString = gb.GetString();
- if (strptime(dateString, "%Y-%m-%d", &timeInfo) == nullptr)
+ String<12> dateString;
+ gb.GetPossiblyQuotedString(dateString.GetRef());
+ if (strptime(dateString.Pointer(), "%Y-%m-%d", &timeInfo) == nullptr)
{
reply.copy("Invalid date format");
result = GCodeResult::error;
@@ -4080,8 +4099,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
seen = true;
// Set time
- const char * const timeString = gb.GetString();
- if (strptime(timeString, "%H:%M:%S", &timeInfo) == nullptr)
+ String<12> timeString;
+ gb.GetPossiblyQuotedString(timeString.GetRef());
+ if (strptime(timeString.Pointer(), "%H:%M:%S", &timeInfo) == nullptr)
{
reply.copy("Invalid time format");
result = GCodeResult::error;
@@ -4112,14 +4132,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 906: // Set/report Motor currents
case 913: // Set/report motor current percent
- // Note that we no longer wait for movement to stop. This is so that we can use these commands in the M911 power fail script.
+#if HAS_SMART_DRIVERS
+ case 917: // Set/report standstill motor current percentage
+#endif
+ // Note that we no longer wait for movement to stop. This is so that we can use these commands (in particular, M913) in the M911 power fail script.
{
bool seen = false;
for (size_t axis = 0; axis < numTotalAxes; axis++)
{
if (gb.Seen(axisLetters[axis]))
{
- platform.SetMotorCurrent(axis, gb.GetFValue(), code == 913);
+ platform.SetMotorCurrent(axis, gb.GetFValue(), code);
seen = true;
}
}
@@ -4132,7 +4155,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
// 2014-09-29 DC42: we no longer insist that the user supplies values for all possible extruder drives
for (size_t e = 0; e < eCount; e++)
{
- platform.SetMotorCurrent(numTotalAxes + e, eVals[e], code == 913);
+ platform.SetMotorCurrent(numTotalAxes + e, eVals[e], code);
}
seen = true;
}
@@ -4149,15 +4172,20 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (!seen)
{
- reply.copy((code == 913) ? "Motor current % of normal - " : "Motor current (mA) - ");
+ reply.copy( (code == 913) ? "Motor current % of normal - "
+#if HAS_SMART_DRIVERS
+ : (code == 917) ? "Motor standstill current % of normal - "
+#endif
+ : "Motor current (mA) - "
+ );
for (size_t axis = 0; axis < numTotalAxes; ++axis)
{
- reply.catf("%c:%d, ", axisLetters[axis], (int)platform.GetMotorCurrent(axis, code == 913));
+ reply.catf("%c:%d, ", axisLetters[axis], (int)platform.GetMotorCurrent(axis, code));
}
reply.cat("E");
for (size_t extruder = 0; extruder < numExtruders; extruder++)
{
- reply.catf(":%d", (int)platform.GetMotorCurrent(extruder + numTotalAxes, code == 913));
+ reply.catf(":%d", (int)platform.GetMotorCurrent(extruder + numTotalAxes, code));
}
if (code == 906)
{
@@ -4372,9 +4400,20 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (result != GCodeResult::notFinished)
{
reprap.EmergencyStop(); // this disables heaters and drives - Duet WiFi pre-production boards need drives disabled here
- uint16_t reason = (gb.Seen('P') && StringStartsWith(gb.GetString(), "ERASE"))
- ? (uint16_t)SoftwareResetReason::erase
- : (uint16_t)SoftwareResetReason::user;
+ bool doErase;
+ if (gb.Seen('P'))
+ {
+ String<8> eraseString;
+ gb.GetPossiblyQuotedString(eraseString.GetRef());
+ doErase = StringStartsWith(eraseString.Pointer(), "ERASE");
+ }
+ else
+ {
+ doErase = false;
+ }
+ const uint16_t reason = (doErase)
+ ? (uint16_t)SoftwareResetReason::erase
+ : (uint16_t)SoftwareResetReason::user;
platform.SoftwareReset(reason); // doesn't return
}
break;
diff --git a/src/Libraries/General/StringRef.h b/src/Libraries/General/StringRef.h
index 09ddaa24..4bfe4dba 100644
--- a/src/Libraries/General/StringRef.h
+++ b/src/Libraries/General/StringRef.h
@@ -12,7 +12,8 @@
#include <cstdarg> // for va_args
#include <cstring> // for strlen
-#undef printf
+// Need to declare strnlen here because it isn't ISO standard
+size_t strnlen(const char *s, size_t n);
// Class to describe a string buffer, including its length. This saves passing buffer lengths around everywhere.
class StringRef
@@ -25,6 +26,7 @@ public:
size_t Length() const { return len; }
size_t strlen() const;
+ bool IsEmpty() const { return p[0] == 0; }
char *Pointer() { return p; }
const char *Pointer() const { return p; }
@@ -43,7 +45,6 @@ public:
size_t StripTrailingSpaces() const;
size_t Prepend(const char *src) const;
- bool IsEmpty() const { return p[0] == 0; }
};
// Class to describe a string which we can get a StringRef reference to
@@ -54,8 +55,13 @@ public:
StringRef GetRef() { return StringRef(storage, Len + 1); }
const char *c_str() const { return storage; }
- size_t strlen() const { return ::strlen(storage); }
+ size_t strlen() const { return strnlen(storage, Len); }
bool IsEmpty() const { return storage[0] == 0; }
+ const char *Pointer() const { return storage; }
+ char& operator[](size_t index) { return storage[index]; }
+ char operator[](size_t index) const { return storage[index]; }
+
+ void Clear() const { storage[0] = 0; }
private:
char storage[Len + 1];
diff --git a/src/Movement/Kinematics/ScaraKinematics.cpp b/src/Movement/Kinematics/ScaraKinematics.cpp
index 2bfbc5b3..ace7160d 100644
--- a/src/Movement/Kinematics/ScaraKinematics.cpp
+++ b/src/Movement/Kinematics/ScaraKinematics.cpp
@@ -124,8 +124,8 @@ bool ScaraKinematics::CartesianToMotorSteps(const float machinePos[], const floa
//debugPrintf("psi = %.2f, theta = %.2f\n", psi * RadiansToDegrees, theta * RadiansToDegrees);
motorPos[X_AXIS] = lrintf(theta * RadiansToDegrees * stepsPerMm[X_AXIS]);
- motorPos[Y_AXIS] = lrintf((psi * RadiansToDegrees * stepsPerMm[Y_AXIS]) - (crosstalk[0] * motorPos[X_AXIS]));
- motorPos[Z_AXIS] = lrintf((machinePos[Z_AXIS] * stepsPerMm[Z_AXIS]) - (motorPos[X_AXIS] * crosstalk[1]) - (motorPos[Y_AXIS] * crosstalk[2]));
+ motorPos[Y_AXIS] = lrintf((psi - (crosstalk[0] * theta)) * RadiansToDegrees * stepsPerMm[Y_AXIS]);
+ motorPos[Z_AXIS] = lrintf((machinePos[Z_AXIS] - (crosstalk[1] * theta) - (crosstalk[2] * psi)) * stepsPerMm[Z_AXIS]);
// Transform any additional axes linearly
for (size_t axis = XYZ_AXES; axis < numVisibleAxes; ++axis)
@@ -139,14 +139,14 @@ bool ScaraKinematics::CartesianToMotorSteps(const float machinePos[], const floa
// For Scara, the X and Y components of stepsPerMm are actually steps per degree angle.
void ScaraKinematics::MotorStepsToCartesian(const int32_t motorPos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, float machinePos[]) const
{
- const float psi = ((float)motorPos[X_AXIS]/stepsPerMm[X_AXIS]) * DegreesToRadians;
- const float theta = (((float)motorPos[Y_AXIS] + ((float)motorPos[X_AXIS] * crosstalk[0]))/stepsPerMm[Y_AXIS]) * DegreesToRadians;
+ const float theta = ((float)motorPos[X_AXIS]/stepsPerMm[X_AXIS]) * DegreesToRadians;
+ const float psi = (((float)motorPos[Y_AXIS]/stepsPerMm[Y_AXIS]) * DegreesToRadians) + (crosstalk[0] * theta);
- machinePos[X_AXIS] = (cosf(psi) * proximalArmLength + cosf(psi + theta) * distalArmLength) - xOffset;
- machinePos[Y_AXIS] = (sinf(psi) * proximalArmLength + sinf(psi + theta) * distalArmLength) - yOffset;
+ machinePos[X_AXIS] = (cosf(theta) * proximalArmLength + cosf(psi + theta) * distalArmLength) - xOffset;
+ machinePos[Y_AXIS] = (sinf(theta) * proximalArmLength + sinf(psi + theta) * distalArmLength) - yOffset;
// On some machines (e.g. Helios), the X and/or Y arm motors also affect the Z height
- machinePos[Z_AXIS] = ((float)motorPos[Z_AXIS] + ((float)motorPos[X_AXIS] * crosstalk[1]) + ((float)motorPos[Y_AXIS] * crosstalk[2]))/stepsPerMm[Z_AXIS];
+ machinePos[Z_AXIS] = ((float)motorPos[Z_AXIS]/stepsPerMm[Z_AXIS]) + (crosstalk[1] * theta) + (crosstalk[2] * psi);
// Convert any additional axes linearly
for (size_t drive = XYZ_AXES; drive < numVisibleAxes; ++drive)
@@ -370,7 +370,9 @@ const char* ScaraKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap
// Return true if the entire homing move should be terminated, false if only the motor associated with the endstop switch should be stopped.
bool ScaraKinematics::QueryTerminateHomingMove(size_t axis) const
{
- return false;
+ // If crosstalk causes the axis mkotor concerned to affect other axes then must terminate the entire move
+ return (axis == X_AXIS && (crosstalk[0] != 0.0 || crosstalk[1] != 0.0))
+ || (axis == Y_AXIS && crosstalk[2] != 0.0);
}
// This function is called from the step ISR when an endstop switch is triggered during homing after stopping just one motor or all motors.
@@ -411,7 +413,9 @@ void ScaraKinematics::Recalc()
distalArmLengthSquared = fsquare(distalArmLength);
twoPd = proximalArmLength * distalArmLength * 2.0f;
- minRadius = (proximalArmLength + distalArmLength * min<float>(cosf(psiLimits[0] * DegreesToRadians), cosf(psiLimits[1] * DegreesToRadians))) * 1.005;
+ minRadius = sqrtf(proximalArmLengthSquared + distalArmLengthSquared
+ - twoPd * max<float>(cosf(psiLimits[0] * DegreesToRadians), cosf(psiLimits[1] * DegreesToRadians))) * 1.005;
+
if (psiLimits[0] < 0.0 && psiLimits[1] > 0.0)
{
// Zero distal arm angle is reachable
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 133b2964..130fa306 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -498,6 +498,9 @@ void Platform::Init()
motorCurrents[drive] = 0.0;
motorCurrentFraction[drive] = 1.0;
+#if HAS_SMART_DRIVERS
+ motorStandstillCurrentFraction[drive] = 1.0;
+#endif
driverState[drive] = DriverStatus::disabled;
// Enable pullup resistors on endstop inputs here if necessary.
@@ -937,7 +940,7 @@ bool Platform::CheckFirmwareUpdatePrerequisites(StringRef& reply)
bool ok = firmwareFile->Read(reinterpret_cast<char*>(&firstDword), sizeof(firstDword)) == (int)sizeof(firstDword);
firmwareFile->Close();
if (!ok || firstDword !=
-#if (SAM4S || SAM4E)
+#if SAM4E || SAM4S
IRAM_ADDR + IRAM_SIZE
#else
IRAM1_ADDR + IRAM1_SIZE
@@ -984,7 +987,7 @@ void Platform::UpdateFirmware()
uint32_t data32[IFLASH_PAGE_SIZE/4];
char* const data = reinterpret_cast<char *>(data32);
-#if (SAM4S || SAM4E)
+#if SAM4E || SAM4S
// The EWP command is not supported for non-8KByte sectors in the SAM4 series.
// So we have to unlock and erase the complete 64Kb sector first.
flash_unlock(IAP_FLASH_START, IAP_FLASH_END, nullptr, nullptr);
@@ -1126,7 +1129,7 @@ void Platform::UpdateFirmware()
static const char filename[] = "0:/sys/" IAP_FIRMWARE_FILE;
const uint32_t topOfStack = *reinterpret_cast<uint32_t *>(IAP_FLASH_START);
if (topOfStack + sizeof(filename) <=
-#if (SAM4S || SAM4E)
+#if SAM4E || SAM4S
IRAM_ADDR + IRAM_SIZE
#else
IRAM1_ADDR + IRAM1_SIZE
@@ -2578,37 +2581,48 @@ void Platform::SetDriversIdle()
}
// Set the current for a drive. Current is in mA.
-void Platform::SetDriverCurrent(size_t driver, float currentOrPercent, bool isPercent)
+void Platform::SetDriverCurrent(size_t driver, float currentOrPercent, int code)
{
if (driver < DRIVES)
{
- if (isPercent)
- {
- motorCurrentFraction[driver] = 0.01 * currentOrPercent;
- }
- else
+ switch (code)
{
+ case 906:
motorCurrents[driver] = currentOrPercent;
+ break;
+
+ case 913:
+ motorCurrentFraction[driver] = 0.01 * currentOrPercent;
+ break;
+
+#if HAS_SMART_DRIVERS
+ case 917:
+ motorStandstillCurrentFraction[driver] = 0.01 * currentOrPercent;
+ break;
+#endif
+ default:
+ break;
}
+
UpdateMotorCurrent(driver);
}
}
// Set the current for all drivers on an axis or extruder. Current is in mA.
-void Platform::SetMotorCurrent(size_t drive, float currentOrPercent, bool isPercent)
+void Platform::SetMotorCurrent(size_t drive, float currentOrPercent, int code)
{
const size_t numAxes = reprap.GetGCodes().GetTotalAxes();
if (drive < numAxes)
{
for (size_t i = 0; i < axisDrivers[drive].numDrivers; ++i)
{
- SetDriverCurrent(axisDrivers[drive].driverNumbers[i], currentOrPercent, isPercent);
+ SetDriverCurrent(axisDrivers[drive].driverNumbers[i], currentOrPercent, code);
}
}
else if (drive < DRIVES)
{
- SetDriverCurrent(extruderDrivers[drive - numAxes], currentOrPercent, isPercent);
+ SetDriverCurrent(extruderDrivers[drive - numAxes], currentOrPercent, code);
}
}
@@ -2680,7 +2694,7 @@ void Platform::UpdateMotorCurrent(size_t driver)
// Get the configured motor current for a drive.
// Currently we don't allow multiple motors on a single axis to have different currents, so we can just return the current for the first one.
-float Platform::GetMotorCurrent(size_t drive, bool isPercent) const
+float Platform::GetMotorCurrent(size_t drive, int code) const
{
if (drive < DRIVES)
{
@@ -2688,7 +2702,21 @@ float Platform::GetMotorCurrent(size_t drive, bool isPercent) const
const uint8_t driver = (drive < numAxes) ? axisDrivers[drive].driverNumbers[0] : extruderDrivers[drive - numAxes];
if (driver < DRIVES)
{
- return (isPercent) ? motorCurrentFraction[driver] * 100.0 : motorCurrents[driver];
+ switch (code)
+ {
+ case 906:
+ return motorCurrents[driver];
+
+ case 913:
+ return motorCurrentFraction[driver] * 100.0;
+
+#if HAS_SMART_DRIVERS
+ case 917:
+ return motorStandstillCurrentFraction[driver] * 100.0;
+#endif
+ default:
+ break;
+ }
}
}
return 0.0;
diff --git a/src/Platform.h b/src/Platform.h
index 436ccf90..84c44edb 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -403,8 +403,8 @@ public:
void DisableDrive(size_t drive);
void DisableAllDrives();
void SetDriversIdle();
- void SetMotorCurrent(size_t drive, float current, bool isPercent);
- float GetMotorCurrent(size_t drive, bool isPercent) const;
+ void SetMotorCurrent(size_t drive, float current, int code);
+ float GetMotorCurrent(size_t drive, int code) const;
void SetIdleCurrentFactor(float f);
float GetIdleCurrentFactor() const
{ return idleCurrentFactor; }
@@ -686,7 +686,7 @@ private:
// DRIVES
- void SetDriverCurrent(size_t driver, float current, bool isPercent);
+ void SetDriverCurrent(size_t driver, float current, int code);
void UpdateMotorCurrent(size_t driver);
void SetDriverDirection(uint8_t driver, bool direction)
pre(driver < DRIVES);
@@ -706,6 +706,9 @@ private:
float pressureAdvance[MaxExtruders];
float motorCurrents[DRIVES]; // the normal motor current for each stepper driver
float motorCurrentFraction[DRIVES]; // the percentages of normal motor current that each driver is set to
+#if HAS_SMART_DRIVERS
+ float motorStandstillCurrentFraction[DRIVES];
+#endif
AxisDriversConfig axisDrivers[MaxAxes]; // the driver numbers assigned to each axis
uint8_t extruderDrivers[MaxExtruders]; // the driver number assigned to each extruder
uint32_t driveDriverBits[2 * DRIVES]; // the bitmap of driver port bits for each axis or extruder, followed by the raw versions
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 2e2d8279..a7033656 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -310,11 +310,11 @@ void RepRap::SetDebug(Module m, bool enable)
{
if (enable)
{
- debug |= (1 << m);
+ debug |= (1u << m);
}
else
{
- debug &= ~(1 << m);
+ debug &= ~(1u << m);
}
PrintDebug();
}
@@ -326,30 +326,24 @@ void RepRap::SetDebug(bool enable)
void RepRap::PrintDebug()
{
- if (debug != 0)
+ platform->Message(GenericMessage, "Debugging enabled for modules:");
+ for (size_t i = 0; i < numModules; i++)
{
- platform->Message(GenericMessage, "Debugging enabled for modules:");
- for (size_t i = 0; i < numModules; i++)
+ if ((debug & (1u << i)) != 0)
{
- if ((debug & (1 << i)) != 0)
- {
- platform->MessageF(GenericMessage, " %s(%u)", moduleName[i], i);
- }
- }
- platform->Message(GenericMessage, "\nDebugging disabled for modules:");
- for (size_t i = 0; i < numModules; i++)
- {
- if ((debug & (1 << i)) == 0)
- {
- platform->MessageF(GenericMessage, " %s(%u)", moduleName[i], i);
- }
+ platform->MessageF(GenericMessage, " %s(%u)", moduleName[i], i);
}
- platform->Message(GenericMessage, "\n");
}
- else
+
+ platform->Message(GenericMessage, "\nDebugging disabled for modules:");
+ for (size_t i = 0; i < numModules; i++)
{
- platform->Message(GenericMessage, "Debugging disabled\n");
+ if ((debug & (1u << i)) == 0)
+ {
+ platform->MessageF(GenericMessage, " %s(%u)", moduleName[i], i);
+ }
}
+ platform->Message(GenericMessage, "\n");
}
// Add a tool.
@@ -629,9 +623,9 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
ch = '[';
for (size_t axis = 0; axis < numAxes; axis++)
{
- // Coordinates may be NaNs, for example when delta or SCARA homing fails. Replace any NaNs by 999.9 to prevent JSON parsing errors.
+ // Coordinates may be NaNs, for example when delta or SCARA homing fails. Replace any NaNs or infinities by 9999.9 to prevent JSON parsing errors.
const float coord = liveCoordinates[axis];
- response->catf("%c%.3f", ch, (double)((std::isnan(coord) || std::isinf(coord)) ? 999.9 : coord));
+ response->catf("%c%.3f", ch, (double)((std::isnan(coord) || std::isinf(coord)) ? 9999.9 : coord));
ch = ',';
}
}
diff --git a/src/RepRap.h b/src/RepRap.h
index c84d1416..8d77df7c 100644
--- a/src/RepRap.h
+++ b/src/RepRap.h
@@ -145,7 +145,7 @@ private:
uint32_t fastLoop, slowLoop;
uint32_t lastTime;
- uint16_t debug;
+ uint32_t debug;
bool stopped;
bool active;
bool resetting;
diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp
index 19f9d9a0..8d29e8e8 100644
--- a/src/Storage/MassStorage.cpp
+++ b/src/Storage/MassStorage.cpp
@@ -86,7 +86,7 @@ FileWriteBuffer *MassStorage::AllocateWriteBuffer()
return nullptr;
}
- FileWriteBuffer *buffer = freeWriteBuffers;
+ FileWriteBuffer * const buffer = freeWriteBuffers;
freeWriteBuffers = buffer->Next();
buffer->SetNext(nullptr);
return buffer;
@@ -224,9 +224,9 @@ const char* MassStorage::GetMonthName(const uint8_t month)
// Delete a file or directory
bool MassStorage::Delete(const char* directory, const char* fileName, bool silent)
{
- const char* location = (directory != nullptr)
- ? platform->GetMassStorage()->CombineName(directory, fileName)
- : fileName;
+ const char* const location = (directory != nullptr)
+ ? platform->GetMassStorage()->CombineName(directory, fileName)
+ : fileName;
if (f_unlink(location) != FR_OK)
{
if (!silent)
@@ -241,7 +241,7 @@ bool MassStorage::Delete(const char* directory, const char* fileName, bool silen
// Create a new directory
bool MassStorage::MakeDirectory(const char *parentDir, const char *dirName)
{
- const char* location = platform->GetMassStorage()->CombineName(parentDir, dirName);
+ const char* const location = platform->GetMassStorage()->CombineName(parentDir, dirName);
if (f_mkdir(location) != FR_OK)
{
platform->MessageF(ErrorMessage, "Failed to create directory %s\n", location);
@@ -288,9 +288,9 @@ bool MassStorage::FileExists(const char *file) const
bool MassStorage::FileExists(const char *directory, const char *fileName) const
{
- const char *location = (directory != nullptr)
- ? platform->GetMassStorage()->CombineName(directory, fileName)
- : fileName;
+ const char * const location = (directory != nullptr)
+ ? platform->GetMassStorage()->CombineName(directory, fileName)
+ : fileName;
return FileExists(location);
}
@@ -310,9 +310,9 @@ bool MassStorage::DirectoryExists(const char* directory, const char* subDirector
// Return the last modified time of a file, or zero if failure
time_t MassStorage::GetLastModifiedTime(const char* directory, const char *fileName) const
{
- const char *location = (directory != nullptr)
- ? platform->GetMassStorage()->CombineName(directory, fileName)
- : fileName;
+ const char * const location = (directory != nullptr)
+ ? platform->GetMassStorage()->CombineName(directory, fileName)
+ : fileName;
FILINFO fil;
fil.lfname = nullptr;
if (f_stat(location, &fil) == FR_OK)
@@ -324,9 +324,9 @@ time_t MassStorage::GetLastModifiedTime(const char* directory, const char *fileN
bool MassStorage::SetLastModifiedTime(const char* directory, const char *fileName, time_t time)
{
- const char *location = (directory != nullptr)
- ? platform->GetMassStorage()->CombineName(directory, fileName)
- : fileName;
+ const char * const location = (directory != nullptr)
+ ? platform->GetMassStorage()->CombineName(directory, fileName)
+ : fileName;
const struct tm * const timeInfo = gmtime(&time);
FILINFO fno;
fno.fdate = (WORD)(((timeInfo->tm_year - 80) * 512U) | (timeInfo->tm_mon + 1) * 32U | timeInfo->tm_mday);
diff --git a/src/Version.h b/src/Version.h
index 0f667117..bb93cca3 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -9,11 +9,11 @@
#define SRC_VERSION_H_
#ifndef VERSION
-# define VERSION "1.20beta6"
+# define VERSION "1.20beta6+1"
#endif
#ifndef DATE
-# define DATE "2017-11-03"
+# define DATE "2017-11-09"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"