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
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Configuration.h18
-rw-r--r--src/Duet/Webserver.cpp57
-rw-r--r--src/DuetNG/TMC2660.cpp2
-rw-r--r--src/DuetNG/TMC2660.h2
-rw-r--r--src/Fan.cpp4
-rw-r--r--src/GCodes/GCodeBuffer.cpp51
-rw-r--r--src/GCodes/GCodeBuffer.h5
-rw-r--r--src/GCodes/GCodes.cpp65
-rw-r--r--src/GCodes/GCodes.h2
-rw-r--r--src/GCodes/GCodes2.cpp63
-rw-r--r--src/GCodes/GCodes3.cpp30
-rw-r--r--src/Heating/Heat.cpp12
-rw-r--r--src/Heating/HeaterProtection.cpp40
-rw-r--r--src/Heating/HeaterProtection.h6
-rw-r--r--src/Heating/Pid.cpp4
-rw-r--r--src/Heating/Sensors/TemperatureSensor.cpp2
-rw-r--r--src/Movement/BedProbing/Grid.cpp2
-rw-r--r--src/Movement/BedProbing/Grid.h2
-rw-r--r--src/Movement/DDA.cpp24
-rw-r--r--src/Movement/DDA.h9
-rw-r--r--src/Movement/DriveMovement.h6
-rw-r--r--src/Movement/Kinematics/Kinematics.cpp2
-rw-r--r--src/Movement/Kinematics/Kinematics.h2
-rw-r--r--src/Network2/ESP8266/Network.cpp167
-rw-r--r--src/Network2/ESP8266/WifiFirmwareUploader.cpp6
-rw-r--r--src/Network2/HttpResponder.cpp4
-rw-r--r--src/Platform.cpp181
-rw-r--r--src/Platform.h21
-rw-r--r--src/PortControl.cpp8
-rw-r--r--src/RepRap.cpp14
-rw-r--r--src/RepRapFirmware.cpp4
-rw-r--r--src/RepRapFirmware.h10
-rw-r--r--src/Scanner.cpp12
-rw-r--r--src/Storage/FileStore.cpp5
-rw-r--r--src/Storage/FileWriteBuffer.h8
-rw-r--r--src/Tools/Filament.cpp4
-rw-r--r--src/Tools/Filament.h4
-rw-r--r--src/Tools/Tool.cpp24
-rw-r--r--src/Tools/Tool.h29
-rw-r--r--src/Version.h4
-rw-r--r--src/ZProbeProgrammer.cpp2
-rw-r--r--src/ZProbeProgrammer.h2
42 files changed, 497 insertions, 422 deletions
diff --git a/src/Configuration.h b/src/Configuration.h
index ef38224c..c214acfa 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -77,16 +77,25 @@ constexpr float ThermostatHysteresis = 1.0; // How much hysteresis we use to
constexpr float BAD_ERROR_TEMPERATURE = 2000.0; // Must exceed any reasonable 5temperature limit including DEFAULT_TEMPERATURE_LIMIT
constexpr uint32_t DefaultHeaterFaultTimeout = 10 * 60 * 1000; // How long we wait (in milliseconds) for user intervention after a heater fault before shutting down
+constexpr PwmFrequency MaxHeaterPwmFrequency = 1000; // maximum supported heater PWM frequency, to avoid overheating the mosfets
+
// Heating model default parameters. For the chamber heater, we use the same values as for the bed heater.
// These parameters are about right for an E3Dv6 hot end with 30W heater.
constexpr float DefaultHotEndHeaterGain = 340.0;
constexpr float DefaultHotEndHeaterTimeConstant = 140.0;
constexpr float DefaultHotEndHeaterDeadTime = 5.5;
+#if SAM4E || SAME70
+constexpr size_t NumBedHeaters = 4;
+constexpr size_t NumChamberHeaters = 2;
+constexpr int8_t DefaultBedHeaters[NumBedHeaters] = { 0, -1, -1, -1 };
+constexpr int8_t DefaultChamberHeaters[NumChamberHeaters] = { -1, -1 };
+#else
constexpr size_t NumBedHeaters = 1;
constexpr size_t NumChamberHeaters = 2;
constexpr int8_t DefaultBedHeaters[NumBedHeaters] = { 0 };
constexpr int8_t DefaultChamberHeaters[NumChamberHeaters] = { -1, -1 };
+#endif
constexpr int8_t DefaultE0Heater = 1; // Index of the default first extruder heater
@@ -170,12 +179,17 @@ constexpr float TRIANGLE_ZERO = -0.001; // Millimetres
constexpr float SILLY_Z_VALUE = -9999.0; // Millimetres
// String lengths
-
constexpr size_t FORMAT_STRING_LENGTH = 256;
constexpr size_t MACHINE_NAME_LENGTH = 40;
constexpr size_t PASSWORD_LENGTH = 20;
-constexpr size_t GCODE_LENGTH = 100;
+#if SAM4E || SAM4S || SAME70
+// Increased GCODE_LENGTH on the SAM4 because M587 and M589 commands on the Duet WiFi can get very long
+constexpr size_t GCODE_LENGTH = 161; // maximum number of non-comment characters in a line of GCode including the null terminator
+#else
+constexpr size_t GCODE_LENGTH = 101; // maximum number of non-comment characters in a line of GCode including the null terminator
+#endif
+
constexpr size_t GCODE_REPLY_LENGTH = 2048;
constexpr size_t MESSAGE_LENGTH = 256;
diff --git a/src/Duet/Webserver.cpp b/src/Duet/Webserver.cpp
index f356008a..e3637d3e 100644
--- a/src/Duet/Webserver.cpp
+++ b/src/Duet/Webserver.cpp
@@ -93,8 +93,8 @@
//***************************************************************************************************
-const char* overflowResponse = "overflow";
-const char* badEscapeResponse = "bad escape";
+const char* const overflowResponse = "overflow";
+const char* const badEscapeResponse = "bad escape";
//**************************** Generic Webserver implementation ******************************
@@ -548,55 +548,26 @@ bool Webserver::HttpInterpreter::DoingFastUpload() const
return false;
}
+// Write some data on the SD card
void Webserver::HttpInterpreter::DoFastUpload()
{
- NetworkTransaction *transaction = webserver->currentTransaction;
-
- // Write some data on the SD card
+ NetworkTransaction * const transaction = webserver->currentTransaction;
const char *buffer;
size_t len;
if (transaction->ReadBuffer(buffer, len))
{
network->Unlock();
- // Write data in sector-aligned chunks. This also means that the buffer in fatfs is only used to hold the FAT.
- // Buffer size must be a multiple of the 512b sector size.
-#ifdef DUET_NG
- static const size_t writeBufLength = 8192;
-#else
- static const size_t writeBufLength = 2048;
-#endif
- static uint32_t writeBufStorage[writeBufLength/4]; // aligned buffer for file writes
- static size_t writeBufIndex;
- char* const writeBuf = reinterpret_cast<char *>(writeBufStorage);
-
- if (uploadedBytes == 0)
- {
- writeBufIndex = 0;
- }
-
- while (len != 0)
- {
- const size_t lengthToCopy = min<size_t>(writeBufLength - writeBufIndex, len);
- memcpy(writeBuf + writeBufIndex, buffer, lengthToCopy);
- writeBufIndex += lengthToCopy;
- uploadedBytes += lengthToCopy;
- buffer += lengthToCopy;
- len -= lengthToCopy;
- if (writeBufIndex == writeBufLength || uploadedBytes >= postFileLength)
- {
- const bool success = fileBeingUploaded.Write(writeBuf, writeBufIndex);
- writeBufIndex = 0;
- if (!success)
- {
- platform->Message(GenericMessage, "Error: Could not write upload data!\n");
- CancelUpload();
+ const bool success = fileBeingUploaded.Write(buffer, len);
+ if (!success)
+ {
+ platform->Message(GenericMessage, "Error: Could not write upload data!\n");
+ CancelUpload();
- while (!network->Lock()) { }
- SendJsonResponse("upload");
- return;
- }
- }
+ while (!network->Lock()) { }
+ SendJsonResponse("upload");
+ return;
}
+ uploadedBytes += len;
while (!network->Lock()) { }
}
@@ -604,7 +575,7 @@ void Webserver::HttpInterpreter::DoFastUpload()
if (uploadState == uploadOK && uploadedBytes >= postFileLength)
{
// Reset POST upload state for this client
- uint32_t remoteIP = transaction->GetRemoteIP();
+ const uint32_t remoteIP = transaction->GetRemoteIP();
for(size_t i = 0; i < numSessions; i++)
{
if (sessions[i].ip == remoteIP && sessions[i].isPostUploading)
diff --git a/src/DuetNG/TMC2660.cpp b/src/DuetNG/TMC2660.cpp
index 14ab5cac..e5b9e805 100644
--- a/src/DuetNG/TMC2660.cpp
+++ b/src/DuetNG/TMC2660.cpp
@@ -590,7 +590,7 @@ namespace SmartDrivers
}
// Set microstepping or chopper control register
- bool SetMicrostepping(size_t drive, int microsteps, int mode)
+ bool SetMicrostepping(size_t drive, unsigned int microsteps, int mode)
{
if (drive < numTmc2660Drivers)
{
diff --git a/src/DuetNG/TMC2660.h b/src/DuetNG/TMC2660.h
index 001f6dde..3d61df83 100644
--- a/src/DuetNG/TMC2660.h
+++ b/src/DuetNG/TMC2660.h
@@ -38,7 +38,7 @@ namespace SmartDrivers
void EnableDrive(size_t drive, bool en);
uint32_t GetLiveStatus(size_t drive);
uint32_t GetAccumulatedStatus(size_t drive, uint32_t bitsToKeep);
- bool SetMicrostepping(size_t drive, int microsteps, int mode);
+ bool SetMicrostepping(size_t drive, unsigned int microsteps, int mode);
unsigned int GetMicrostepping(size_t drive, int mode, bool& interpolation);
void SetDriversPowered(bool powered);
void SetStallThreshold(size_t drive, int sgThreshold);
diff --git a/src/Fan.cpp b/src/Fan.cpp
index 85451751..d704abbe 100644
--- a/src/Fan.cpp
+++ b/src/Fan.cpp
@@ -95,9 +95,9 @@ bool Fan::Configure(unsigned int mcode, int fanNum, GCodeBuffer& gb, StringRef&
if (gb.Seen('H')) // Set thermostatically-controlled heaters
{
seen = true;
- long heaters[Heaters + MaxVirtualHeaters];
+ int32_t heaters[Heaters + MaxVirtualHeaters]; // signed because we use H-1 to disable thermostatic mode
size_t numH = ARRAY_SIZE(heaters);
- gb.GetLongArray(heaters, numH);
+ gb.GetIntArray(heaters, numH);
// Note that M106 H-1 disables thermostatic mode. The following code implements that automatically.
heatersMonitored = 0;
diff --git a/src/GCodes/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer.cpp
index c416d93e..9add807c 100644
--- a/src/GCodes/GCodeBuffer.cpp
+++ b/src/GCodes/GCodeBuffer.cpp
@@ -436,7 +436,7 @@ float GCodeBuffer::GetFValue()
}
// Get a colon-separated list of floats after a key letter
-const void GCodeBuffer::GetFloatArray(float a[], size_t& returnedLength, bool doPad)
+const void GCodeBuffer::GetFloatArray(float arr[], size_t& returnedLength, bool doPad)
{
if (readPointer >= 0)
{
@@ -451,7 +451,7 @@ const void GCodeBuffer::GetFloatArray(float a[], size_t& returnedLength, bool do
returnedLength = 0;
return;
}
- a[length] = (float)strtod(&gcodeBuffer[readPointer + 1], 0);
+ arr[length] = (float)strtod(&gcodeBuffer[readPointer + 1], 0);
length++;
do
{
@@ -469,7 +469,7 @@ const void GCodeBuffer::GetFloatArray(float a[], size_t& returnedLength, bool do
{
for(size_t i = 1; i < returnedLength; i++)
{
- a[i] = a[0];
+ arr[i] = arr[0];
}
}
else
@@ -486,8 +486,8 @@ const void GCodeBuffer::GetFloatArray(float a[], size_t& returnedLength, bool do
}
}
-// Get a :-separated list of longs after a key letter
-const void GCodeBuffer::GetLongArray(long l[], size_t& returnedLength)
+// Get a :-separated list of ints after a key letter
+const void GCodeBuffer::GetIntArray(int32_t arr[], size_t& returnedLength)
{
if (readPointer >= 0)
{
@@ -497,12 +497,49 @@ const void GCodeBuffer::GetLongArray(long l[], size_t& returnedLength)
{
if (length >= returnedLength) // Array limit has been set in here
{
- reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode long array that is too long: %s\n", gcodeBuffer);
+ reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode int array that is too long: %s\n", gcodeBuffer);
readPointer = -1;
returnedLength = 0;
return;
}
- l[length] = strtol(&gcodeBuffer[readPointer + 1], 0, 0);
+ arr[length] = strtol(&gcodeBuffer[readPointer + 1], 0, 0);
+ length++;
+ do
+ {
+ readPointer++;
+ } while(gcodeBuffer[readPointer] != 0 && (gcodeBuffer[readPointer] != ' ') && (gcodeBuffer[readPointer] != LIST_SEPARATOR));
+ if (gcodeBuffer[readPointer] != LIST_SEPARATOR)
+ {
+ inList = false;
+ }
+ }
+ returnedLength = length;
+ readPointer = -1;
+ }
+ else
+ {
+ INTERNAL_ERROR;
+ returnedLength = 0;
+ }
+}
+
+// Get a :-separated list of unsigned ints after a key letter
+const void GCodeBuffer::GetUnsignedArray(uint32_t arr[], size_t& returnedLength)
+{
+ if (readPointer >= 0)
+ {
+ size_t length = 0;
+ bool inList = true;
+ while(inList)
+ {
+ if (length >= returnedLength) // Array limit has been set in here
+ {
+ reprap.GetPlatform().MessageF(ErrorMessage, "GCodes: Attempt to read a GCode unsigned array that is too long: %s\n", gcodeBuffer);
+ readPointer = -1;
+ returnedLength = 0;
+ return;
+ }
+ arr[length] = strtoul(&gcodeBuffer[readPointer + 1], 0, 0);
length++;
do
{
diff --git a/src/GCodes/GCodeBuffer.h b/src/GCodes/GCodeBuffer.h
index 0846a007..54a842ab 100644
--- a/src/GCodes/GCodeBuffer.h
+++ b/src/GCodes/GCodeBuffer.h
@@ -39,8 +39,9 @@ public:
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
- const void GetLongArray(long l[], size_t& length); // Get a :-separated list of longs after a key letter
+ const void GetFloatArray(float arr[], size_t& length, bool doPad) __attribute__((hot)); // Get a :-separated list of floats after a key letter
+ const void GetIntArray(int32_t arr[], size_t& length); // Get a :-separated list of ints after a key letter
+ const void GetUnsignedArray(uint32_t arr[], size_t& length); // Get a :-separated list of unsigned ints after a key letter
void TryGetFValue(char c, float& val, bool& seen);
void TryGetIValue(char c, int32_t& val, bool& seen);
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 632df2d6..23e24a4f 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -232,7 +232,8 @@ float GCodes::FractionOfFilePrinted() const
return 0.0;
}
- return (float)(fileBeingPrinted.GetPosition() - fileInput->BytesCached()) / (float)len;
+ const FilePosition bytesCached = fileGCode->IsDoingFileMacro() ? 0: fileInput->BytesCached();
+ return (float)(fileBeingPrinted.GetPosition() - bytesCached) / (float)len;
}
// Start running the config file
@@ -2886,10 +2887,9 @@ void GCodes::WriteGCodeToFile(GCodeBuffer& gb)
return;
}
- // End of file?
- if (gb.Seen('M'))
+ if (gb.GetCommandLetter() == 'M')
{
- if (gb.GetIValue() == 29)
+ if (gb.GetCommandNumber() == 29) // end of file?
{
fileBeingWritten->Close();
fileBeingWritten = nullptr;
@@ -2899,18 +2899,13 @@ void GCodes::WriteGCodeToFile(GCodeBuffer& gb)
return;
}
}
-
- // Resend request?
- if (gb.Seen('G'))
+ else if (gb.GetCommandLetter() == 'G' && gb.GetCommandNumber() == 998) // resend request?
{
- if (gb.GetIValue() == 998)
+ if (gb.Seen('P'))
{
- if (gb.Seen('P'))
- {
- scratchString.printf("%" PRIi32 "\n", gb.GetIValue());
- HandleReply(gb, false, scratchString.Pointer());
- return;
- }
+ scratchString.printf("%" PRIi32 "\n", gb.GetIValue());
+ HandleReply(gb, false, scratchString.Pointer());
+ return;
}
}
@@ -3147,11 +3142,11 @@ bool GCodes::ManageTool(GCodeBuffer& gb, StringRef& reply)
}
// Check drives
- long drives[MaxExtruders]; // There can never be more than we have...
- size_t dCount = numExtruders; // Sets the limit and returns the count
+ int32_t drives[MaxExtruders]; // There can never be more than we have...
+ size_t dCount = numExtruders; // Sets the limit and returns the count
if (gb.Seen('D'))
{
- gb.GetLongArray(drives, dCount);
+ gb.GetIntArray(drives, dCount);
seen = true;
}
else
@@ -3160,11 +3155,11 @@ bool GCodes::ManageTool(GCodeBuffer& gb, StringRef& reply)
}
// Check heaters
- long heaters[Heaters];
+ int32_t heaters[Heaters];
size_t hCount = Heaters;
if (gb.Seen('H'))
{
- gb.GetLongArray(heaters, hCount);
+ gb.GetIntArray(heaters, hCount);
seen = true;
}
else
@@ -3176,10 +3171,10 @@ bool GCodes::ManageTool(GCodeBuffer& gb, StringRef& reply)
AxesBitmap xMap;
if (gb.Seen('X'))
{
- long xMapping[MaxAxes];
+ uint32_t xMapping[MaxAxes];
size_t xCount = numVisibleAxes;
- gb.GetLongArray(xMapping, xCount);
- xMap = LongArrayToBitMap<AxesBitmap>(xMapping, xCount) & LowestNBits<AxesBitmap>(numVisibleAxes);
+ gb.GetUnsignedArray(xMapping, xCount);
+ xMap = UnsignedArrayToBitMap<AxesBitmap>(xMapping, xCount) & LowestNBits<AxesBitmap>(numVisibleAxes);
seen = true;
}
else
@@ -3191,10 +3186,10 @@ bool GCodes::ManageTool(GCodeBuffer& gb, StringRef& reply)
AxesBitmap yMap;
if (gb.Seen('Y'))
{
- long yMapping[MaxAxes];
+ uint32_t yMapping[MaxAxes];
size_t yCount = numVisibleAxes;
- gb.GetLongArray(yMapping, yCount);
- yMap = LongArrayToBitMap<AxesBitmap>(yMapping, yCount) & LowestNBits<AxesBitmap>(numVisibleAxes);
+ gb.GetUnsignedArray(yMapping, yCount);
+ yMap = UnsignedArrayToBitMap<AxesBitmap>(yMapping, yCount) & LowestNBits<AxesBitmap>(numVisibleAxes);
seen = true;
}
else
@@ -3212,10 +3207,10 @@ bool GCodes::ManageTool(GCodeBuffer& gb, StringRef& reply)
FansBitmap fanMap;
if (gb.Seen('F'))
{
- long fanMapping[NUM_FANS];
+ uint32_t fanMapping[NUM_FANS];
size_t fanCount = NUM_FANS;
- gb.GetLongArray(fanMapping, fanCount);
- fanMap = LongArrayToBitMap<FansBitmap>(fanMapping, fanCount) & LowestNBits<FansBitmap>(NUM_FANS);
+ gb.GetUnsignedArray(fanMapping, fanCount);
+ fanMap = UnsignedArrayToBitMap<FansBitmap>(fanMapping, fanCount) & LowestNBits<FansBitmap>(NUM_FANS);
seen = true;
}
else
@@ -3260,7 +3255,7 @@ void GCodes::DisableDrives()
SetAllAxesNotHomed();
}
-bool GCodes::ChangeMicrostepping(size_t drive, int microsteps, int mode) const
+bool GCodes::ChangeMicrostepping(size_t drive, unsigned int microsteps, int mode) const
{
bool dummy;
const unsigned int oldSteps = platform.GetMicrostepping(drive, mode, dummy);
@@ -3335,11 +3330,11 @@ void GCodes::HandleReply(GCodeBuffer& gb, bool error, const char* reply)
case marlin:
// We don't need to handle M20 here because we always allocate an output buffer for that one
- if (gb.Seen('M') && gb.GetIValue() == 28)
+ if (gb.GetCommandLetter() == 'M' && gb.GetCommandNumber() == 28)
{
platform.MessageF(type, "%s\n%s\n", response, reply);
}
- else if ((gb.Seen('M') && gb.GetIValue() == 105) || (gb.Seen('M') && gb.GetIValue() == 998))
+ else if (gb.GetCommandLetter() == 'M' && (gb.GetCommandNumber() == 105 || gb.GetCommandNumber() == 998))
{
platform.MessageF(type, "%s %s\n", response, reply);
}
@@ -3393,7 +3388,7 @@ void GCodes::HandleReply(GCodeBuffer& gb, bool error, OutputBuffer *reply)
const Compatibility c = (&gb == serialGCode || &gb == telnetGCode) ? platform.Emulating() : me;
const MessageType type = gb.GetResponseMessageType();
- const char* const response = (gb.Seen('M') && gb.GetIValue() == 998) ? "rs " : "ok";
+ const char* const response = (gb.GetCommandLetter() == 'M' && gb.GetCommandNumber() == 998) ? "rs " : "ok";
const char* emulationType = nullptr;
switch (c)
@@ -3408,7 +3403,7 @@ void GCodes::HandleReply(GCodeBuffer& gb, bool error, OutputBuffer *reply)
return;
case marlin:
- if (gb.Seen('M') && gb.GetIValue() == 20)
+ if (gb.GetCommandLetter() =='M' && gb.GetCommandNumber() == 20)
{
platform.Message(type, "Begin file list\n");
platform.Message(type, reply);
@@ -3418,7 +3413,7 @@ void GCodes::HandleReply(GCodeBuffer& gb, bool error, OutputBuffer *reply)
return;
}
- if (gb.Seen('M') && gb.GetIValue() == 28)
+ if (gb.GetCommandLetter() == 'M' && gb.GetCommandNumber() == 28)
{
platform.Message(type, response);
platform.Message(type, "\n");
@@ -3426,7 +3421,7 @@ void GCodes::HandleReply(GCodeBuffer& gb, bool error, OutputBuffer *reply)
return;
}
- if ((gb.Seen('M') && gb.GetIValue() == 105) || (gb.Seen('M') && gb.GetIValue() == 998))
+ if (gb.GetCommandLetter() =='M' && (gb.GetCommandNumber() == 105 || gb.GetCommandNumber() == 998))
{
platform.Message(type, response);
platform.Message(type, " ");
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index 9debf727..86d5c94a 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -283,7 +283,7 @@ private:
GCodeResult RetractFilament(GCodeBuffer& gb, bool retract); // Retract or un-retract filaments
GCodeResult LoadFilament(GCodeBuffer& gb, StringRef& reply); // Load the specified filament into a tool
GCodeResult UnloadFilament(GCodeBuffer& gb, StringRef& reply); // Unload the current filament from a tool
- bool ChangeMicrostepping(size_t drive, int microsteps, int mode) const; // Change microstepping on the specified drive
+ bool ChangeMicrostepping(size_t drive, unsigned int microsteps, int mode) const; // Change microstepping on the specified drive
void ListTriggers(StringRef reply, TriggerInputsBitmap mask); // Append a list of trigger inputs to a message
void CheckTriggers(); // Check for and execute triggers
void CheckFilament(); // Check for and respond to filament errors
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 474a05ee..b19010b8 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -396,15 +396,15 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (gb.Seen(extrudeLetter))
{
- long int eDrive[MaxExtruders];
+ uint32_t eDrive[MaxExtruders];
size_t eCount = numExtruders;
- gb.GetLongArray(eDrive, eCount);
+ gb.GetUnsignedArray(eDrive, eCount);
for (size_t i = 0; i < eCount; i++)
{
seen = true;
- if (eDrive[i] < 0 || (size_t)eDrive[i] >= numExtruders)
+ if (eDrive[i] >= numExtruders)
{
- reply.printf("Invalid extruder number specified: %ld", eDrive[i]);
+ reply.printf("Invalid extruder number specified: %" PRIu32, eDrive[i]);
result = GCodeResult::error;
break;
}
@@ -1279,9 +1279,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (!cancelWait && gb.Seen('H'))
{
// Wait for specified heaters to be ready
- long heaters[Heaters];
+ int32_t heaters[Heaters];
size_t heaterCount = Heaters;
- gb.GetLongArray(heaters, heaterCount);
+ gb.GetIntArray(heaters, heaterCount);
for (size_t i = 0; i < heaterCount; i++)
{
@@ -1298,9 +1298,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (!cancelWait && gb.Seen('C'))
{
// Wait for specified chamber(s) to be ready
- long chamberIndices[NumChamberHeaters];
+ int32_t chamberIndices[NumChamberHeaters];
size_t chamberCount = NumChamberHeaters;
- gb.GetLongArray(chamberIndices, chamberCount);
+ gb.GetIntArray(chamberIndices, chamberCount);
if (chamberCount == 0)
{
@@ -2034,7 +2034,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
{
reply.copy("Bad heater number in M303 command");
}
- else if (reprap.GetHeat().CheckHeater(heater))
+ else if (!reprap.GetHeat().CheckHeater(heater))
{
reply.copy("Heater is not ready to perform PID auto-tuning");
}
@@ -2104,7 +2104,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (seen)
{
const bool inverseTemperatureControl = (inversionParameter == 1 || inversionParameter == 3);
- if (!reprap.GetHeat().SetHeaterModel(heater, gain, tc, td, maxPwm, voltage, dontUsePid == 0, inverseTemperatureControl, (uint16_t)min<uint32_t>(freq, 65536u)))
+ if (!reprap.GetHeat().SetHeaterModel(heater, gain, tc, td, maxPwm, voltage,
+ dontUsePid == 0, inverseTemperatureControl, (uint16_t)min<uint32_t>(freq, MaxHeaterPwmFrequency)))
{
reply.copy("Error: bad model parameters");
}
@@ -2152,7 +2153,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 350: // Set/report microstepping
{
// interp is currently an int not a bool, because we use special values of interp to set the chopper control register
- int32_t mode = 0; // this is usually the interpolation rwquested (0 = off, 1 = on)
+ int32_t mode = 0; // this is usually the interpolation requested (0 = off, 1 = on)
bool dummy;
gb.TryGetIValue('I', mode, dummy);
@@ -2166,14 +2167,14 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
return false;
}
seen = true;
- const int microsteps = gb.GetIValue();
+ const unsigned int microsteps = gb.GetUIValue();
if (ChangeMicrostepping(axis, microsteps, mode))
{
SetAxisNotHomed(axis);
}
else
{
- reply.printf("Drive %c does not support %dx microstepping%s", axisLetters[axis], microsteps, ((mode) ? " with interpolation" : ""));
+ reply.printf("Drive %c does not support %ux microstepping%s", axisLetters[axis], microsteps, ((mode) ? " with interpolation" : ""));
result = GCodeResult::error;
}
}
@@ -2186,14 +2187,14 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
return false;
}
seen = true;
- long eVals[MaxExtruders];
+ uint32_t eVals[MaxExtruders];
size_t eCount = numExtruders;
- gb.GetLongArray(eVals, eCount);
+ gb.GetUnsignedArray(eVals, eCount);
for (size_t e = 0; e < eCount; e++)
{
if (!ChangeMicrostepping(numTotalAxes + e, (int)eVals[e], mode))
{
- reply.printf("Drive E%u does not support %dx microstepping%s", e, (int)eVals[e], ((mode) ? " with interpolation" : ""));
+ reply.printf("Drive E%u does not support %ux microstepping%s", e, (unsigned int)eVals[e], ((mode) ? " with interpolation" : ""));
result = GCodeResult::error;
}
}
@@ -2205,15 +2206,15 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
for (size_t axis = 0; axis < numTotalAxes; ++axis)
{
bool interp;
- const int microsteps = platform.GetMicrostepping(axis, mode, interp);
- reply.catf("%c:%d%s, ", axisLetters[axis], microsteps, (interp) ? "(on)" : "");
+ const unsigned int microsteps = platform.GetMicrostepping(axis, mode, interp);
+ reply.catf("%c:%u%s, ", axisLetters[axis], microsteps, (interp) ? "(on)" : "");
}
reply.cat("E");
for (size_t extruder = 0; extruder < numExtruders; extruder++)
{
bool interp;
- const int microsteps = platform.GetMicrostepping(extruder + numTotalAxes, mode, interp);
- reply.catf(":%d%s", microsteps, (interp) ? "(on)" : "");
+ const unsigned int microsteps = platform.GetMicrostepping(extruder + numTotalAxes, mode, interp);
+ reply.catf(":%u%s", microsteps, (interp) ? "(on)" : "");
}
}
}
@@ -2355,10 +2356,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
machineType = MachineType::cnc;
if (gb.Seen('P'))
{
- int32_t pins[2] = { NoLogicalPin, NoLogicalPin };
+ uint32_t pins[2] = { NoLogicalPin, NoLogicalPin };
size_t numPins = 2;
- gb.GetLongArray(pins, numPins);
- if (pins[0] < 0 || pins[0] > 65535)
+ gb.GetUnsignedArray(pins, numPins);
+ if (pins[0] > 65535)
{
pins[0] = NoLogicalPin;
}
@@ -3003,14 +3004,14 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
const float advance = gb.GetFValue();
if (gb.Seen('D'))
{
- long int eDrive[MaxExtruders];
+ uint32_t eDrive[MaxExtruders];
size_t eCount = MaxExtruders;
- gb.GetLongArray(eDrive, eCount);
+ gb.GetUnsignedArray(eDrive, eCount);
for (size_t i = 0; i < eCount; i++)
{
- if (eDrive[i] < 0 || (size_t)eDrive[i] >= numExtruders)
+ if (eDrive[i] >= numExtruders)
{
- reply.printf("Invalid extruder number '%ld'", eDrive[i]);
+ reply.printf("Invalid extruder number '%" PRIu32 "'", eDrive[i]);
result = GCodeResult::error;
break;
}
@@ -3161,12 +3162,12 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
// Extruder drives
- size_t eDriveCount = MaxExtruders;
- long eDrives[MaxExtruders];
if (gb.Seen(extrudeLetter))
{
- gb.GetLongArray(eDrives, eDriveCount);
- for(size_t extruder = 0; extruder < eDriveCount; extruder++)
+ size_t eDriveCount = MaxExtruders;
+ uint32_t eDrives[MaxExtruders];
+ gb.GetUnsignedArray(eDrives, eDriveCount);
+ for (size_t extruder = 0; extruder < eDriveCount; extruder++)
{
const size_t eDrive = eDrives[extruder];
if (eDrive >= MaxExtruders)
diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp
index 581796e4..349c2742 100644
--- a/src/GCodes/GCodes3.cpp
+++ b/src/GCodes/GCodes3.cpp
@@ -341,12 +341,12 @@ GCodeResult GCodes::CheckOrConfigureTrigger(GCodeBuffer& gb, StringRef& reply, i
}
if (gb.Seen(extrudeLetter))
{
- long eStops[MaxExtruders];
+ uint32_t eStops[MaxExtruders];
size_t numEntries = MaxExtruders;
- gb.GetLongArray(eStops, numEntries);
+ gb.GetUnsignedArray(eStops, numEntries);
for (size_t i = 0; i < numEntries; ++i)
{
- if (eStops[i] >= 0 && (unsigned long)eStops[i] < MaxExtruders)
+ if (eStops[i] < MaxExtruders)
{
SetBit(triggerMask, eStops[i] + E0_AXIS);
}
@@ -422,15 +422,15 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, StringRef& reply)
// Found an axis letter. Get the drivers to assign to this axis.
seen = true;
size_t numValues = MaxDriversPerAxis;
- long drivers[MaxDriversPerAxis];
- gb.GetLongArray(drivers, numValues);
+ uint32_t drivers[MaxDriversPerAxis];
+ gb.GetUnsignedArray(drivers, numValues);
// Check all the driver numbers are in range
AxisDriversConfig config;
config.numDrivers = numValues;
for (size_t i = 0; i < numValues; ++i)
{
- if ((unsigned long)drivers[i] >= DRIVES)
+ if (drivers[i] >= DRIVES)
{
badDrive = true;
}
@@ -476,12 +476,12 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, StringRef& reply)
{
seen = true;
size_t numValues = DRIVES - numTotalAxes;
- long drivers[MaxExtruders];
- gb.GetLongArray(drivers, numValues);
+ uint32_t drivers[MaxExtruders];
+ gb.GetUnsignedArray(drivers, numValues);
numExtruders = numValues;
for (size_t i = 0; i < numValues; ++i)
{
- if ((unsigned long)drivers[i] >= DRIVES)
+ if (drivers[i] >= DRIVES)
{
badDrive = true;
}
@@ -701,20 +701,20 @@ GCodeResult GCodes::UpdateFirmware(GCodeBuffer& gb, StringRef &reply)
// Find out which modules we have been asked to update
if (gb.Seen('S'))
{
- long modulesToUpdate[3];
+ uint32_t modulesToUpdate[3];
size_t numUpdateModules = ARRAY_SIZE(modulesToUpdate);
- gb.GetLongArray(modulesToUpdate, numUpdateModules);
+ gb.GetUnsignedArray(modulesToUpdate, numUpdateModules);
for (size_t i = 0; i < numUpdateModules; ++i)
{
- long t = modulesToUpdate[i];
- if (t < 0 || (unsigned long)t >= NumFirmwareUpdateModules)
+ uint32_t t = modulesToUpdate[i];
+ if (t >= NumFirmwareUpdateModules)
{
- reply.printf("Invalid module number '%ld'\n", t);
+ reply.printf("Invalid module number '%" PRIu32 "'\n", t);
firmwareUpdateModuleMap = 0;
return GCodeResult::error;
break;
}
- firmwareUpdateModuleMap |= (1u << (unsigned int)t);
+ firmwareUpdateModuleMap |= (1u << t);
}
}
else
diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp
index b1a514c5..01f2111d 100644
--- a/src/Heating/Heat.cpp
+++ b/src/Heating/Heat.cpp
@@ -53,7 +53,7 @@ void Heat::ResetHeaterModels()
{
if (pids[heater]->IsHeaterEnabled())
{
- if (IsBedHeater(heater) || IsChamberHeater(heater))
+ if (IsBedOrChamberHeater(heater))
{
pids[heater]->SetModel(DefaultBedHeaterGain, DefaultBedHeaterTimeConstant, DefaultBedHeaterDeadTime, 1.0, 0.0, false, false, 0);
}
@@ -70,9 +70,9 @@ void Heat::Init()
// Initialise the heater protection items first
for (size_t index : ARRAY_INDICES(heaterProtections))
{
- HeaterProtection *prot = heaterProtections[index];
+ HeaterProtection * const prot = heaterProtections[index];
- const float tempLimit = (IsBedHeater(index) || IsChamberHeater(index)) ? DefaultBedTemperatureLimit : DefaultExtruderTemperatureLimit;
+ const float tempLimit = (IsBedOrChamberHeater(index)) ? DefaultBedTemperatureLimit : DefaultExtruderTemperatureLimit;
prot->Init(tempLimit);
if (index < Heaters)
@@ -85,7 +85,7 @@ void Heat::Init()
for (size_t heater : ARRAY_INDICES(pids))
{
heaterSensors[heater] = nullptr; // no temperature sensor assigned yet
- if (IsBedHeater(heater) || IsChamberHeater(heater))
+ if (IsBedOrChamberHeater(heater))
{
pids[heater]->Init(DefaultBedHeaterGain, DefaultBedHeaterTimeConstant, DefaultBedHeaterDeadTime, false, false);
}
@@ -612,7 +612,7 @@ void Heat::UpdateHeaterProtection()
}
}
-// Check if the heater is able to operate
+// Check if the heater is able to operate returning true if everything is OK
bool Heat::CheckHeater(size_t heater)
{
return !pids[heater]->FaultOccurred() && pids[heater]->CheckProtection();
@@ -621,7 +621,7 @@ bool Heat::CheckHeater(size_t heater)
// Get the temperature of a real or virtual heater
float Heat::GetTemperature(size_t heater, TemperatureError& err)
{
- TemperatureSensor ** const spp = GetSensor(heater);
+ TemperatureSensor * const * const spp = GetSensor(heater);
if (spp == nullptr)
{
err = TemperatureError::unknownHeater;
diff --git a/src/Heating/HeaterProtection.cpp b/src/Heating/HeaterProtection.cpp
index e7704e57..e8d4a9a5 100644
--- a/src/Heating/HeaterProtection.cpp
+++ b/src/Heating/HeaterProtection.cpp
@@ -12,7 +12,7 @@
#include "Heat.h"
-HeaterProtection::HeaterProtection(size_t index)
+HeaterProtection::HeaterProtection(size_t index) : next(nullptr)
{
// By default each heater protection element is mapped to its corresponding heater.
// All other heater protection elements are unused and can be optionally assigned.
@@ -32,33 +32,33 @@ void HeaterProtection::Init(float tempLimit)
// Check if any action needs to be taken. Returns true if everything is OK
bool HeaterProtection::Check()
{
- TemperatureError err;
- const float temperature = reprap.GetHeat().GetTemperature(supervisedHeater, err);
-
- if (err != TemperatureError::success)
+ if (supervisedHeater >= 0)
{
- badTemperatureCount++;
+ TemperatureError err;
+ const float temperature = reprap.GetHeat().GetTemperature(supervisedHeater, err);
- if (badTemperatureCount > MAX_BAD_TEMPERATURE_COUNT)
+ if (err != TemperatureError::success)
{
- reprap.GetPlatform().MessageF(ErrorMessage, "Temperature reading error on heater %d\n", supervisedHeater);
- return false;
+ badTemperatureCount++;
+ if (badTemperatureCount > MAX_BAD_TEMPERATURE_COUNT)
+ {
+ reprap.GetPlatform().MessageF(ErrorMessage, "Temperature reading error on heater %d\n", supervisedHeater);
+ return false;
+ }
}
- }
- else
- {
- badTemperatureCount = 0;
-
- switch (trigger)
+ else
{
- case HeaterProtectionTrigger::TemperatureExceeded:
- return (temperature < limit);
+ badTemperatureCount = 0;
+ switch (trigger)
+ {
+ case HeaterProtectionTrigger::TemperatureExceeded:
+ return (temperature <= limit);
- case HeaterProtectionTrigger::TemperatureTooLow:
- return (temperature > limit);
+ case HeaterProtectionTrigger::TemperatureTooLow:
+ return (temperature >= limit);
+ }
}
}
-
return true;
}
diff --git a/src/Heating/HeaterProtection.h b/src/Heating/HeaterProtection.h
index 99f90468..4373fb51 100644
--- a/src/Heating/HeaterProtection.h
+++ b/src/Heating/HeaterProtection.h
@@ -12,7 +12,7 @@
// Condition of a heater protection event
-enum class HeaterProtectionTrigger
+enum class HeaterProtectionTrigger : uint8_t
{
TemperatureExceeded,
TemperatureTooLow
@@ -21,7 +21,7 @@ enum class HeaterProtectionTrigger
const HeaterProtectionTrigger MaxHeaterProtectionTrigger = HeaterProtectionTrigger::TemperatureTooLow;
// The action to trigger when the target condition is met
-enum class HeaterProtectionAction
+enum class HeaterProtectionAction : uint8_t
{
GenerateFault = 0,
PermanentSwitchOff,
@@ -64,8 +64,8 @@ public:
private:
HeaterProtection *next;
- int8_t heater, supervisedHeater;
float limit;
+ int8_t heater, supervisedHeater;
HeaterProtectionAction action;
HeaterProtectionTrigger trigger;
diff --git a/src/Heating/Pid.cpp b/src/Heating/Pid.cpp
index 41ec78d0..e64d382a 100644
--- a/src/Heating/Pid.cpp
+++ b/src/Heating/Pid.cpp
@@ -39,7 +39,7 @@ float tuningVoltageAccumulator; // sum of the voltage readings we take during
// Member functions and constructors
-PID::PID(Platform& p, int8_t h) : platform(p), heater(h), mode(HeaterMode::off), invertPwmSignal(false)
+PID::PID(Platform& p, int8_t h) : platform(p), heaterProtection(nullptr), heater(h), mode(HeaterMode::off), invertPwmSignal(false)
{
}
@@ -726,7 +726,7 @@ void PID::DoTuningStep()
case HeaterMode::tuning1:
// Heating up
{
- const bool isBedOrChamberHeater = (reprap.GetHeat().IsBedHeater(heater) || reprap.GetHeat().IsChamberHeater(heater));
+ const bool isBedOrChamberHeater = reprap.GetHeat().IsBedOrChamberHeater(heater);
const uint32_t heatingTime = millis() - tuningPhaseStartTime;
const float extraTimeAllowed = (isBedOrChamberHeater) ? 60.0 : 30.0;
if (heatingTime > (uint32_t)((model.GetDeadTime() + extraTimeAllowed) * SecondsToMillis) && (temperature - tuningStartTemp) < 3.0)
diff --git a/src/Heating/Sensors/TemperatureSensor.cpp b/src/Heating/Sensors/TemperatureSensor.cpp
index 0634fa4c..f97492e1 100644
--- a/src/Heating/Sensors/TemperatureSensor.cpp
+++ b/src/Heating/Sensors/TemperatureSensor.cpp
@@ -35,7 +35,7 @@ void TemperatureSensor::SetHeaterName(const char *newName)
heaterName = nullptr;
delete oldName;
- if (newName != nullptr)
+ if (newName != nullptr && strlen(newName) != 0)
{
char * const temp = new char[strlen(newName) + 1];
strcpy(temp, newName);
diff --git a/src/Movement/BedProbing/Grid.cpp b/src/Movement/BedProbing/Grid.cpp
index 5b56c518..ad3f11d1 100644
--- a/src/Movement/BedProbing/Grid.cpp
+++ b/src/Movement/BedProbing/Grid.cpp
@@ -165,7 +165,7 @@ void GridDefinition::PrintError(float originalXrange, float originalYrange, Stri
}
// Increase the version number in the following string whenever we change the format of the height map file.
-const char *HeightMap::HeightMapComment = "RepRapFirmware height map file v2";
+const char * const HeightMap::HeightMapComment = "RepRapFirmware height map file v2";
HeightMap::HeightMap() : useMap(false) { }
diff --git a/src/Movement/BedProbing/Grid.h b/src/Movement/BedProbing/Grid.h
index 7054ec35..d76346a9 100644
--- a/src/Movement/BedProbing/Grid.h
+++ b/src/Movement/BedProbing/Grid.h
@@ -83,7 +83,7 @@ public:
void ExtrapolateMissing(); // Extrapolate missing points to ensure consistency
private:
- static const char *HeightMapComment; // The start of the comment we write at the start of the height map file
+ static const char * const HeightMapComment; // The start of the comment we write at the start of the height map file
GridDefinition def;
float gridHeights[MaxGridProbePoints]; // The Z coordinates of the points on the bed that were probed
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index 35ee63aa..d75e422f 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -47,6 +47,13 @@ struct MoveParameters
(double)accelDistance, (double)steadyDistance, (double)decelDistance, (double)requestedSpeed, (double)startSpeed, (double)topSpeed, (double)endSpeed,
(double)targetNextSpeed, endstopChecks, flags);
}
+
+ static void PrintHeading()
+ {
+ reprap.GetPlatform().Message(DebugMessage,
+ "accelDistance,steadyDistance,decelDistance,requestedSpeed,startSpeed,topSpeed,endSpeed,"
+ "targetNextSpeed,endstopChecks,flags\n");
+ }
};
const size_t NumSavedMoves = 128;
@@ -58,6 +65,7 @@ static size_t savedMovePointer = 0;
/*static*/ void DDA::PrintMoves()
{
// Print the saved moved in CSV format
+ MoveParameters::PrintHeading();
for (size_t i = 0; i < NumSavedMoves; ++i)
{
savedMoves[savedMovePointer].DebugPrint();
@@ -445,7 +453,7 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
{
// Try to meld this move to the previous move to avoid stop/start
// Assuming that this move ends with zero speed, calculate the maximum possible starting speed: u^2 = v^2 - 2as
- prev->targetNextSpeed = sqrtf(acceleration * totalDistance * 2.0);
+ prev->targetNextSpeed = min<float>(sqrtf(acceleration * totalDistance * 2.0), requestedSpeed);
DoLookahead(prev);
startSpeed = prev->targetNextSpeed;
}
@@ -1003,7 +1011,7 @@ void DDA::Prepare(uint8_t simMode)
for (size_t drive = 0; drive < DRIVES; ++drive)
{
DriveMovement* const pdm = pddm[drive];
- if (pddm != nullptr && pdm->state == DMState::moving)
+ if (pdm != nullptr && pdm->state == DMState::moving)
{
if (isLeadscrewAdjustmentMove)
{
@@ -1324,7 +1332,7 @@ pre(state == frozen)
const size_t numAxes = reprap.GetGCodes().GetTotalAxes();
for (size_t i = 0; i < DRIVES; ++i)
{
- DriveMovement* const pdm = pddm[i];
+ DriveMovement* const pdm = FindDM(i);
if (pdm != nullptr && pdm->state == DMState::moving)
{
const size_t drive = pdm->drive;
@@ -1498,7 +1506,7 @@ bool DDA::Step()
// For extruder drivers, we need to be able to calculate how much of the extrusion was completed after calling this.
void DDA::StopDrive(size_t drive)
{
- DriveMovement* const pdm = pddm[drive];
+ DriveMovement* const pdm = FindDM(drive);
if (pdm != nullptr && pdm->state == DMState::moving)
{
pdm->state = DMState::idle;
@@ -1547,7 +1555,7 @@ float DDA::GetProportionDone(bool moveWasAborted) const
int32_t taken = 0, left = 0;
for (size_t drive = reprap.GetGCodes().GetTotalAxes(); drive < DRIVES; ++drive)
{
- const DriveMovement* const pdm = pddm[drive];
+ const DriveMovement* const pdm = FindDM(drive);
if (pdm != nullptr) // if this extruder is active
{
taken += pdm->GetNetStepsTaken();
@@ -1588,7 +1596,7 @@ void DDA::ReduceHomingSpeed()
// Adjust the speed in the DMs
for (size_t drive = 0; drive < DRIVES; ++drive)
{
- DriveMovement* const pdm = pddm[drive];
+ DriveMovement* const pdm = FindDM(drive);
if (pdm != nullptr && pdm->state == DMState::moving)
{
pdm->ReduceSpeed(*this, ProbingSpeedReductionFactor);
@@ -1601,7 +1609,7 @@ bool DDA::HasStepError() const
{
for (size_t drive = 0; drive < DRIVES; ++drive)
{
- const DriveMovement* const pdm = pddm[drive];
+ const DriveMovement* const pdm = FindDM(drive);
if (pdm != nullptr && pdm->state == DMState::stepError)
{
return true;
@@ -1621,7 +1629,7 @@ bool DDA::Free()
// Return the number of net steps already taken in this move by a particular drive
int32_t DDA::GetStepsTaken(size_t drive) const
{
- const DriveMovement * const dmp = pddm[drive];
+ const DriveMovement * const dmp = FindDM(drive);
return (dmp != nullptr) ? dmp->GetNetStepsTaken() : 0;
}
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 2475dfa9..6644f5ea 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -128,6 +128,7 @@ public:
static uint32_t maxReps;
private:
+ DriveMovement *FindDM(size_t drive) const;
void RecalculateMove() __attribute__ ((hot));
void CalcNewSpeeds() __attribute__ ((hot));
void ReduceHomingSpeed(); // called to reduce homing speed when a near-endstop is triggered
@@ -221,6 +222,12 @@ private:
DriveMovement *pddm[DRIVES]; // These describe the state of each drive movement
};
+// Find the DriveMovement record for a given drive, or return nullptr if there isn't one
+inline DriveMovement *DDA::FindDM(size_t drive) const
+{
+ return pddm[drive];
+}
+
// Force an end point
inline void DDA::SetDriveCoordinate(int32_t a, size_t drive)
{
@@ -233,7 +240,7 @@ inline void DDA::SetDriveCoordinate(int32_t a, size_t drive)
// Get the current full step interval for this axis or extruder
inline uint32_t DDA::GetStepInterval(size_t axis, uint32_t microstepShift) const
{
- const DriveMovement * const dm = pddm[axis];
+ const DriveMovement * const dm = FindDM(axis);
return (dm != nullptr) ? dm->GetStepInterval(microstepShift) : 0;
}
diff --git a/src/Movement/DriveMovement.h b/src/Movement/DriveMovement.h
index 9a1c535a..1d71931e 100644
--- a/src/Movement/DriveMovement.h
+++ b/src/Movement/DriveMovement.h
@@ -156,20 +156,20 @@ private:
DMState state; // whether this is active or not
uint8_t drive; // the drive that this DM controls
- uint8_t microstepShift : 4, // log2 of the microstepping factor
+ uint8_t microstepShift : 4, // log2 of the microstepping factor (for when we use dynamic microstepping adjustment)
direction : 1, // true=forwards, false=backwards
fullCurrent : 1; // true if the drivers are set to the full current, false if they are set to the standstill current
uint8_t stepsTillRecalc; // how soon we need to recalculate
uint32_t totalSteps; // total number of steps for this move
- // These values change as the step is executed
+ // These values change as the step is executed, except for reverseStartStep
uint32_t nextStep; // number of steps already done
uint32_t reverseStartStep; // the step number for which we need to reverse direction due to pressure advance or delta movement
uint32_t nextStepTime; // how many clocks after the start of this move the next step is due
uint32_t stepInterval; // how many clocks between steps
- // The following only need to be stored per-drive if we are supporting pressure advance
+ // The following only needs to be stored per-drive if we are supporting pressure advance
uint64_t twoDistanceToStopTimesCsquaredDivA;
// Parameters unique to a style of move (Cartesian, delta or extruder). Currently, extruders and Cartesian moves use the same parameters.
diff --git a/src/Movement/Kinematics/Kinematics.cpp b/src/Movement/Kinematics/Kinematics.cpp
index a258a377..52ec0262 100644
--- a/src/Movement/Kinematics/Kinematics.cpp
+++ b/src/Movement/Kinematics/Kinematics.cpp
@@ -19,7 +19,7 @@
#include "Platform.h"
#include "GCodes/GCodeBuffer.h"
-const char *Kinematics::HomeAllFileName = "homeall.g";
+const char * const Kinematics::HomeAllFileName = "homeall.g";
const char * const Kinematics::StandardHomingFileNames[] = AXES_("homex.g", "homey.g", "homez.g", "homeu.g", "homev.g", "homew.g", "homea.g", "homeb.g", "homec.g");
// Constructor. Pass segsPerSecond <= 0.0 to get non-segmented kinematics.
diff --git a/src/Movement/Kinematics/Kinematics.h b/src/Movement/Kinematics/Kinematics.h
index fe9d4e52..d6c59e5a 100644
--- a/src/Movement/Kinematics/Kinematics.h
+++ b/src/Movement/Kinematics/Kinematics.h
@@ -186,7 +186,7 @@ protected:
float segmentsPerSecond; // if we are using segmentation, the target number of segments/second
float minSegmentLength; // if we are using segmentation, the minimum segment size
- static const char *HomeAllFileName;
+ static const char * const HomeAllFileName;
static const char * const StandardHomingFileNames[];
private:
diff --git a/src/Network2/ESP8266/Network.cpp b/src/Network2/ESP8266/Network.cpp
index 79258a41..8070a417 100644
--- a/src/Network2/ESP8266/Network.cpp
+++ b/src/Network2/ESP8266/Network.cpp
@@ -404,77 +404,72 @@ void Network::Stop()
void Network::Spin(bool full)
{
- // Main state machine.
- switch (state)
+ if (full)
{
- case NetworkState::starting1:
- if (full)
+ // Main state machine.
+ switch (state)
{
- // The ESP toggles CS before it has finished starting up, so don't look at the CS signal too soon
- const uint32_t now = millis();
- if (now - lastTickMillis >= WiFiStartupMillis)
+ case NetworkState::starting1:
{
- lastTickMillis = now;
- state = NetworkState::starting2;
+ // The ESP toggles CS before it has finished starting up, so don't look at the CS signal too soon
+ const uint32_t now = millis();
+ if (now - lastTickMillis >= WiFiStartupMillis)
+ {
+ lastTickMillis = now;
+ state = NetworkState::starting2;
+ }
}
- }
- break;
+ break;
- case NetworkState::starting2:
- if (full)
- {
- // See if the ESP8266 has kept its pins at their stable values for long enough
- const uint32_t now = millis();
- if (digitalRead(SamCsPin) && digitalRead(EspTransferRequestPin) && !digitalRead(APIN_SPI_SCK))
+ case NetworkState::starting2:
{
- if (now - lastTickMillis >= WiFiStableMillis)
+ // See if the ESP8266 has kept its pins at their stable values for long enough
+ const uint32_t now = millis();
+ if (digitalRead(SamCsPin) && digitalRead(EspTransferRequestPin) && !digitalRead(APIN_SPI_SCK))
{
- // Setup the SPI controller in slave mode and assign the CS pin to it
- platform.Message(NetworkInfoMessage, "WiFi module started\n");
- SetupSpi(); // set up the SPI subsystem
-
- // Read the status to get the WiFi server version
- Receiver<NetworkStatusResponse> status;
- const int32_t rc = SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status);
- if (rc > 0)
+ if (now - lastTickMillis >= WiFiStableMillis)
{
- SafeStrncpy(wiFiServerVersion, status.Value().versionText, ARRAY_SIZE(wiFiServerVersion));
+ // Setup the SPI controller in slave mode and assign the CS pin to it
+ platform.Message(NetworkInfoMessage, "WiFi module started\n");
+ SetupSpi(); // set up the SPI subsystem
+
+ // Read the status to get the WiFi server version
+ Receiver<NetworkStatusResponse> status;
+ const int32_t rc = SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status);
+ if (rc > 0)
+ {
+ SafeStrncpy(wiFiServerVersion, status.Value().versionText, ARRAY_SIZE(wiFiServerVersion));
+
+ // Set the hostname before anything else is done
+ if (SendCommand(NetworkCommand::networkSetHostName, 0, 0, hostname, HostNameLength, nullptr, 0) != ResponseEmpty)
+ {
+ reprap.GetPlatform().Message(NetworkInfoMessage, "Error: Could not set WiFi hostname\n");
+ }
- // Set the hostname before anything else is done
- if (SendCommand(NetworkCommand::networkSetHostName, 0, 0, hostname, HostNameLength, nullptr, 0) != ResponseEmpty)
+ state = NetworkState::active;
+ espStatusChanged = true; // make sure we fetch the current state and enable the ESP interrupt
+ }
+ else
{
- reprap.GetPlatform().Message(NetworkInfoMessage, "Error: Could not set WiFi hostname\n");
+ // Something went wrong, maybe a bad firmware image was flashed
+ // Disable the WiFi chip again in this case
+ platform.MessageF(NetworkInfoMessage, "Error: Failed to initialise WiFi module, code %" PRIi32 "\n", rc);
+ Stop();
}
-
- state = NetworkState::active;
- espStatusChanged = true; // make sure we fetch the current state and enable the ESP interrupt
- }
- else
- {
- // Something went wrong, maybe a bad firmware image was flashed
- // Disable the WiFi chip again in this case
- platform.MessageF(NetworkInfoMessage, "Error: Failed to initialise WiFi module, code %" PRIi32 "\n", rc);
- Stop();
}
}
+ else
+ {
+ lastTickMillis = now;
+ }
}
- else
- {
- lastTickMillis = now;
- }
- }
- break;
+ break;
- case NetworkState::disabled:
- if (full)
- {
+ case NetworkState::disabled:
uploader->Spin();
- }
- break;
+ break;
- case NetworkState::active:
- if (full)
- {
+ case NetworkState::active:
if (espStatusChanged && digitalRead(EspTransferRequestPin))
{
if (reprap.Debug(moduleNetwork))
@@ -557,48 +552,48 @@ void Network::Spin(bool full)
nextResponderToPoll = nr;
}
}
- }
- break;
+ break;
- case NetworkState::changingMode:
- if (full && espStatusChanged && digitalRead(EspTransferRequestPin))
- {
- GetNewStatus();
- if (currentMode != WiFiState::connecting)
+ case NetworkState::changingMode:
+ if (espStatusChanged && digitalRead(EspTransferRequestPin))
{
- requestedMode = currentMode; // don't keep repeating the request if it failed
- state = NetworkState::active;
- if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint)
+ GetNewStatus();
+ if (currentMode != WiFiState::connecting)
{
- // Get our IP address, this needs to be correct for FTP to work
- Receiver<NetworkStatusResponse> status;
- if (SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status) > 0)
+ requestedMode = currentMode; // don't keep repeating the request if it failed
+ state = NetworkState::active;
+ if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint)
{
- uint32_t ip = status.Value().ipAddress;
- for (size_t i = 0; i < 4; ++i)
+ // Get our IP address, this needs to be correct for FTP to work
+ Receiver<NetworkStatusResponse> status;
+ if (SendCommand(NetworkCommand::networkGetStatus, 0, 0, nullptr, 0, status) > 0)
{
- ipAddress[i] = (uint8_t)(ip & 255);
- ip >>= 8;
+ uint32_t ip = status.Value().ipAddress;
+ for (size_t i = 0; i < 4; ++i)
+ {
+ ipAddress[i] = (uint8_t)(ip & 255);
+ ip >>= 8;
+ }
+ SafeStrncpy(actualSsid, status.Value().ssid, SsidLength);
}
- SafeStrncpy(actualSsid, status.Value().ssid, SsidLength);
+ InitSockets();
+ reconnectCount = 0;
+ platform.MessageF(NetworkInfoMessage, "Wifi module is %s%s, IP address %s\n",
+ TranslateWiFiState(currentMode),
+ actualSsid,
+ IP4String(ipAddress).c_str());
+ }
+ else
+ {
+ platform.MessageF(NetworkInfoMessage, "Wifi module is %s\n", TranslateWiFiState(currentMode));
}
- InitSockets();
- reconnectCount = 0;
- platform.MessageF(NetworkInfoMessage, "Wifi module is %s%s, IP address %s\n",
- TranslateWiFiState(currentMode),
- actualSsid,
- IP4String(ipAddress).c_str());
- }
- else
- {
- platform.MessageF(NetworkInfoMessage, "Wifi module is %s\n", TranslateWiFiState(currentMode));
}
}
- }
- break;
+ break;
- default:
- break;
+ default:
+ break;
+ }
}
// Check for debug info received from the WiFi module
diff --git a/src/Network2/ESP8266/WifiFirmwareUploader.cpp b/src/Network2/ESP8266/WifiFirmwareUploader.cpp
index a14f3d6d..0e8c1800 100644
--- a/src/Network2/ESP8266/WifiFirmwareUploader.cpp
+++ b/src/Network2/ESP8266/WifiFirmwareUploader.cpp
@@ -5,8 +5,8 @@
* Author: David
*/
-#include <Network2/ESP8266/Network.h>
-#include <Network2/ESP8266/WifiFirmwareUploader.h>
+#include "Network.h"
+#include "WifiFirmwareUploader.h"
#include "Platform.h"
#include "RepRap.h"
#include "Storage/FileStore.h"
@@ -43,7 +43,7 @@ const uint32_t ESP_FLASH_ADDR = 0x40200000; // address of start of Flash
const uint32_t ESP_FLASH_READ_STUB_BEGIN = IRAM_ADDR + 0x18;
// Messages corresponding to result codes, should make sense when followed by " error"
-const char *resultMessages[] =
+const char * const resultMessages[] =
{
"no",
"timeout",
diff --git a/src/Network2/HttpResponder.cpp b/src/Network2/HttpResponder.cpp
index ca3a3bc0..7a1fe334 100644
--- a/src/Network2/HttpResponder.cpp
+++ b/src/Network2/HttpResponder.cpp
@@ -13,8 +13,8 @@
#define KO_START "rr_"
const size_t KoFirst = 3;
-const char* overflowResponse = "overflow";
-const char* badEscapeResponse = "bad escape";
+const char* const overflowResponse = "overflow";
+const char* const badEscapeResponse = "bad escape";
const uint32_t HttpReceiveTimeout = 2000;
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 1dd6a049..7301cbae 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -317,7 +317,7 @@ Platform::Platform() :
nextDriveToPoll(0),
onBoardDriversFanRunning(false), offBoardDriversFanRunning(false), onBoardDriversFanStartMillis(0), offBoardDriversFanStartMillis(0),
#endif
- lastFanCheckTime(0), auxGCodeReply(nullptr), tickState(0), debugCode(0), lastWarningMillis(0)
+ lastFanCheckTime(0), auxGCodeReply(nullptr), tickState(0), debugCode(0), lastWarningMillis(0), deliberateError(false)
{
// Output
auxOutput = new OutputStack();
@@ -918,14 +918,14 @@ bool Platform::ProgramZProbe(GCodeBuffer& gb, StringRef& reply)
{
if (gb.Seen('S'))
{
- long zProbeProgram[MaxZProbeProgramBytes];
+ uint32_t zProbeProgram[MaxZProbeProgramBytes];
size_t len = MaxZProbeProgramBytes;
- gb.GetLongArray(zProbeProgram, len);
+ gb.GetUnsignedArray(zProbeProgram, len);
if (len != 0)
{
for (size_t i = 0; i < len; ++i)
{
- if (zProbeProgram[i] < 0 || zProbeProgram[i] > 255)
+ if (zProbeProgram[i] > 255)
{
reply.copy("Out of range value in program bytes");
return true;
@@ -1792,6 +1792,10 @@ void Platform::SoftwareReset(uint16_t reason, const uint32_t *stk)
}
reason |= (uint8_t)reprap.GetSpinningModule();
reason |= (softwareResetDebugInfo & 0x07) << 5;
+ if (deliberateError)
+ {
+ reason |= (uint16_t)SoftwareResetReason::deliberate;
+ }
// Record the reason for the software reset
// First find a free slot (wear levelling)
@@ -1823,6 +1827,7 @@ void Platform::SoftwareReset(uint16_t reason, const uint32_t *stk)
}
srdBuf[slot].magic = SoftwareResetData::magicValue;
srdBuf[slot].resetReason = reason;
+ srdBuf[slot].when = realTime;
GetStackUsage(nullptr, nullptr, &srdBuf[slot].neverUsedRam);
srdBuf[slot].hfsr = SCB->HFSR;
srdBuf[slot].cfsr = SCB->CFSR;
@@ -2147,14 +2152,14 @@ void Platform::Diagnostics(MessageType mtype)
#endif
{
// Find the last slot written
- slot = SoftwareResetData::numberOfSlots - 1;
- while (slot >= 0 && srdBuf[slot].magic == 0xFFFF)
+ slot = SoftwareResetData::numberOfSlots;
+ do
{
--slot;
}
+ while (slot >= 0 && srdBuf[slot].magic == 0xFFFF);
}
- Message(mtype, "Last software reset reason: ");
if (slot >= 0 && srdBuf[slot].magic == SoftwareResetData::magicValue)
{
const uint32_t reason = srdBuf[slot].resetReason & 0xF0;
@@ -2165,10 +2170,23 @@ void Platform::Diagnostics(MessageType mtype)
: (reason == (uint32_t)SoftwareResetReason::wdtFault) ? "Watchdog timeout"
: (reason == (uint32_t)SoftwareResetReason::otherFault) ? "Other fault"
: "Unknown";
- MessageF(mtype, "%s, spinning module %s, available RAM %" PRIu32 " bytes (slot %d)\n",
- reasonText, moduleName[srdBuf[slot].resetReason & 0x0F], srdBuf[slot].neverUsedRam, slot);
+ if (srdBuf[slot].when != 0)
+ {
+ const struct tm * const timeInfo = gmtime(&srdBuf[slot].when);
+ scratchString.printf("at %04u-%02u-%02u %02u:%02u",
+ timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min);
+ }
+ else
+ {
+ scratchString.copy("time unknown");
+ }
+
+ MessageF(mtype, "Last software reset %s, reason: %s%s, spinning module %s, available RAM %" PRIu32 " bytes (slot %d)\n",
+ scratchString.Pointer(),
+ (srdBuf[slot].resetReason & (uint32_t)SoftwareResetReason::deliberate) ? "deliberate " : "",
+ reasonText, moduleName[srdBuf[slot].resetReason & 0x0F], srdBuf[slot].neverUsedRam, slot);
// Our format buffer is only 256 characters long, so the next 2 lines must be written separately
- MessageF(mtype, "Software reset code 0x%04x, HFSR 0x%08" PRIx32 ", CFSR 0x%08" PRIx32 ", ICSR 0x%08" PRIx32 ", BFAR 0x%08" PRIx32 ", SP 0x%08" PRIx32 "\n",
+ MessageF(mtype, "Software reset code 0x%04x HFSR 0x%08" PRIx32 ", CFSR 0x%08" PRIx32 ", ICSR 0x%08" PRIx32 ", BFAR 0x%08" PRIx32 ", SP 0x%08" PRIx32 "\n",
srdBuf[slot].resetReason, srdBuf[slot].hfsr, srdBuf[slot].cfsr, srdBuf[slot].icsr, srdBuf[slot].bfar, srdBuf[slot].sp);
if (srdBuf[slot].sp != 0xFFFFFFFF)
{
@@ -2183,7 +2201,7 @@ void Platform::Diagnostics(MessageType mtype)
}
else
{
- Message(mtype, "not available\n");
+ Message(mtype, "Last software reset details not available\n");
}
}
@@ -2412,27 +2430,33 @@ bool Platform::DiagnosticTest(GCodeBuffer& gb, StringRef& reply, int d)
break;
case (int)DiagnosticTestType::TestWatchdog:
+ deliberateError = true;
SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk); // disable the system tick interrupt so that we get a watchdog timeout reset
break;
case (int)DiagnosticTestType::TestSpinLockup:
+ deliberateError = true;
debugCode = d; // tell the Spin function to loop
break;
case (int)DiagnosticTestType::TestSerialBlock: // write an arbitrary message via debugPrintf()
+ deliberateError = true;
debugPrintf("Diagnostic Test\n");
break;
case (int)DiagnosticTestType::DivideByZero: // do an integer divide by zero to test exception handling
+ deliberateError = true;
(void)RepRap::DoDivide(1, 0); // call function in another module so it can't be optimised away
break;
case (int)DiagnosticTestType::UnalignedMemoryAccess: // do an unaligned memory access to test exception handling
+ deliberateError = true;
SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; // by default, unaligned memory accesses are allowed, so change that
(void)RepRap::ReadDword(reinterpret_cast<const char*>(dummy) + 1); // call function in another module so it can't be optimised away
break;
case (int)DiagnosticTestType::BusFault:
+ deliberateError = true;
// Read from the "Undefined (Abort)" area
#if SAME70
// FIXME: The SAME70 provides an MPU, maybe we should configure it as well?
@@ -2605,84 +2629,81 @@ void Platform::UpdateConfiguredHeaters()
EndStopHit Platform::Stopped(size_t drive) const
{
- if (drive < DRIVES)
+ if (drive < reprap.GetGCodes().GetTotalAxes())
{
- if (drive >= reprap.GetGCodes().GetTotalAxes())
+ switch (endStopInputType[drive])
{
- // Endstop not used for an axis, so no configuration data available.
- // To allow us to see its status in DWC, pretend it is configured as a high-end active high endstop.
- return (endStopPins[drive] != NoPin && IoPort::ReadPin(endStopPins[drive])) ? EndStopHit::highHit : EndStopHit::noStop;
- }
- else
- {
- switch (endStopInputType[drive])
+ case EndStopInputType::zProbe:
{
- case EndStopInputType::zProbe:
- {
- const EndStopHit rslt = GetZProbeResult();
- return (rslt == EndStopHit::lowHit && endStopPos[drive] == EndStopPosition::highEndStop)
- ? EndStopHit::highHit
- : rslt;
- }
+ const EndStopHit rslt = GetZProbeResult();
+ return (rslt == EndStopHit::lowHit && endStopPos[drive] == EndStopPosition::highEndStop)
+ ? EndStopHit::highHit
+ : rslt;
+ }
#if HAS_SMART_DRIVERS
- case EndStopInputType::motorStall:
+ case EndStopInputType::motorStall:
+ {
+ bool motorIsStalled;
+ switch (reprap.GetMove().GetKinematics().GetKinematicsType())
{
- bool motorIsStalled;
- switch (reprap.GetMove().GetKinematics().GetKinematicsType())
- {
- case KinematicsType::coreXY:
- // Both X and Y motors are involved in homing X or Y
- motorIsStalled = (drive == X_AXIS || drive == Y_AXIS)
- ? AnyMotorStalled(X_AXIS) || AnyMotorStalled(Y_AXIS)
- : AnyMotorStalled(drive);
- break;
-
- case KinematicsType::coreXYU:
- // Both X and Y motors are involved in homing X or Y, and both U and V motors are involved in homing U
- motorIsStalled = (drive == X_AXIS || drive == Y_AXIS)
- ? AnyMotorStalled(X_AXIS) || AnyMotorStalled(Y_AXIS)
- : (drive == U_AXIS)
- ? AnyMotorStalled(U_AXIS) || AnyMotorStalled(V_AXIS)
- : AnyMotorStalled(drive);
- break;
-
- case KinematicsType::coreXZ:
- // Both X and Z motors are involved in homing X or Z
- motorIsStalled = (drive == X_AXIS || drive == Z_AXIS)
- ? AnyMotorStalled(X_AXIS) || AnyMotorStalled(Z_AXIS)
- : AnyMotorStalled(drive);
- break;
-
- default:
- motorIsStalled = AnyMotorStalled(drive);
- break;
- }
- return (!motorIsStalled) ? EndStopHit::noStop
- : (endStopPos[drive] == EndStopPosition::highEndStop) ? EndStopHit::highHit
- : EndStopHit::lowHit;
+ case KinematicsType::coreXY:
+ // Both X and Y motors are involved in homing X or Y
+ motorIsStalled = (drive == X_AXIS || drive == Y_AXIS)
+ ? AnyMotorStalled(X_AXIS) || AnyMotorStalled(Y_AXIS)
+ : AnyMotorStalled(drive);
+ break;
+
+ case KinematicsType::coreXYU:
+ // Both X and Y motors are involved in homing X or Y, and both U and V motors are involved in homing U
+ motorIsStalled = (drive == X_AXIS || drive == Y_AXIS)
+ ? AnyMotorStalled(X_AXIS) || AnyMotorStalled(Y_AXIS)
+ : (drive == U_AXIS)
+ ? AnyMotorStalled(U_AXIS) || AnyMotorStalled(V_AXIS)
+ : AnyMotorStalled(drive);
+ break;
+
+ case KinematicsType::coreXZ:
+ // Both X and Z motors are involved in homing X or Z
+ motorIsStalled = (drive == X_AXIS || drive == Z_AXIS)
+ ? AnyMotorStalled(X_AXIS) || AnyMotorStalled(Z_AXIS)
+ : AnyMotorStalled(drive);
+ break;
+
+ default:
+ motorIsStalled = AnyMotorStalled(drive);
+ break;
}
- break;
+ return (!motorIsStalled) ? EndStopHit::noStop
+ : (endStopPos[drive] == EndStopPosition::highEndStop) ? EndStopHit::highHit
+ : EndStopHit::lowHit;
+ }
+ break;
#endif
- case EndStopInputType::activeLow:
- case EndStopInputType::activeHigh:
- if (endStopPins[drive] != NoPin)
+ case EndStopInputType::activeLow:
+ case EndStopInputType::activeHigh:
+ if (endStopPins[drive] != NoPin)
+ {
+ bool b = IoPort::ReadPin(endStopPins[drive]);
+ if (endStopInputType[drive] == EndStopInputType::activeHigh)
{
- bool b = IoPort::ReadPin(endStopPins[drive]);
- if (endStopInputType[drive] == EndStopInputType::activeHigh)
- {
- b = !b;
- }
- return (b) ? EndStopHit::noStop : (endStopPos[drive] == EndStopPosition::highEndStop) ? EndStopHit::highHit : EndStopHit::lowHit;
+ b = !b;
}
- break;
-
- default:
- break;
+ return (b) ? EndStopHit::noStop : (endStopPos[drive] == EndStopPosition::highEndStop) ? EndStopHit::highHit : EndStopHit::lowHit;
}
+ break;
+
+ default:
+ break;
}
}
+ else if (drive < DRIVES)
+ {
+ // Endstop not used for an axis, so no configuration data available.
+ // To allow us to see its status in DWC, pretend it is configured as a high-end active high endstop.
+ return (endStopPins[drive] != NoPin && IoPort::ReadPin(endStopPins[drive])) ? EndStopHit::highHit : EndStopHit::noStop;
+ }
return EndStopHit::noStop;
}
@@ -3053,7 +3074,7 @@ void Platform::SetIdleCurrentFactor(float f)
}
// Set the microstepping for a driver, returning true if successful
-bool Platform::SetDriverMicrostepping(size_t driver, int microsteps, int mode)
+bool Platform::SetDriverMicrostepping(size_t driver, unsigned int microsteps, int mode)
{
if (driver < DRIVES)
{
@@ -4170,14 +4191,14 @@ bool Platform::ConfigureStallDetection(GCodeBuffer& gb, StringRef& reply)
DriversBitmap drivers = 0;
if (gb.Seen('P'))
{
- long int drives[DRIVES];
+ uint32_t drives[DRIVES];
size_t dCount = DRIVES;
- gb.GetLongArray(drives, dCount);
+ gb.GetUnsignedArray(drives, dCount);
for (size_t i = 0; i < dCount; i++)
{
- if (drives[i] < 0 || (size_t)drives[i] >= numSmartDrivers)
+ if (drives[i] >= numSmartDrivers)
{
- reply.printf("Invalid drive number '%ld'", drives[i]);
+ reply.printf("Invalid drive number '%" PRIu32 "'", drives[i]);
return true;
}
SetBit(drivers, drives[i]);
diff --git a/src/Platform.h b/src/Platform.h
index 4c2699e0..6fcd96b2 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -155,7 +155,8 @@ enum class SoftwareResetReason : uint16_t
otherFault = 0x70,
inAuxOutput = 0x0800, // this bit is or'ed in if we were in aux output at the time
inLwipSpin = 0x2000, // we got stuck in a call to LWIP for too long
- inUsbOutput = 0x4000 // this bit is or'ed in if we were in USB output at the time
+ inUsbOutput = 0x4000, // this bit is or'ed in if we were in USB output at the time
+ deliberate = 0x8000 // this but it or'ed in if we deliberately caused a fault
};
// Enumeration to describe various tests we do in response to the M122 command
@@ -392,7 +393,7 @@ public:
void SetIdleCurrentFactor(float f);
float GetIdleCurrentFactor() const
{ return idleCurrentFactor; }
- bool SetDriverMicrostepping(size_t driver, int microsteps, int mode);
+ bool SetDriverMicrostepping(size_t driver, unsigned int microsteps, int mode);
unsigned int GetDriverMicrostepping(size_t drive, int mode, bool& interpolation) const;
bool SetMicrostepping(size_t drive, int microsteps, int mode);
unsigned int GetMicrostepping(size_t drive, int mode, bool& interpolation) const;
@@ -606,12 +607,12 @@ private:
// directly from/to flash memory.
struct SoftwareResetData
{
- static const uint16_t versionValue = 7; // increment this whenever this struct changes
+ static const uint16_t versionValue = 8; // increment this whenever this struct changes
static const uint16_t magicValue = 0x7D00 | versionValue; // value we use to recognise that all the flash data has been written
#if SAM3XA
static const uint32_t nvAddress = 0; // must be 4-byte aligned
#endif
- static const size_t numberOfSlots = 5; // number of storage slots used to implement wear levelling - must fit in 512 bytes
+ static const size_t numberOfSlots = 4; // number of storage slots used to implement wear levelling - must fit in 512 bytes
uint16_t magic; // the magic number, including the version
uint16_t resetReason; // this records why we did a software reset, for diagnostic purposes
@@ -621,7 +622,8 @@ private:
uint32_t icsr; // interrupt control and state register
uint32_t bfar; // bus fault address register
uint32_t sp; // stack pointer
- uint32_t stack[18]; // stack when the exception occurred, with the program counter at the bottom
+ time_t when; // value of the RTC when the software reset occurred
+ uint32_t stack[24]; // stack when the exception occurred, with the program counter at the bottom
bool isVacant() const // return true if this struct can be written without erasing it first
{
@@ -734,7 +736,6 @@ private:
#endif
// Z probe
-
Pin zProbePin;
Pin zProbeModulationPin;
ZProbeProgrammer zProbeProg;
@@ -756,7 +757,6 @@ private:
void UpdateNetworkAddress(byte dst[4], const byte src[4]);
// Axes and endstops
-
float axisMaxima[MaxAxes];
float axisMinima[MaxAxes];
AxesBitmap axisMinimaProbed, axisMaximaProbed;
@@ -766,7 +766,6 @@ private:
static bool WriteAxisLimits(FileStore *f, AxesBitmap axesProbed, const float limits[MaxAxes], int sParam);
// Heaters - bed is assumed to be the first
-
Pin tempSensePins[Heaters];
Pin heatOnPins[Heaters];
Pin spiTempSenseCsPins[MaxSpiTempSensors];
@@ -774,7 +773,6 @@ private:
uint32_t heatSampleTicks;
// Fans
-
Fan fans[NUM_FANS];
Pin coolingFanRpmPin; // we currently support only one fan RPM input
uint32_t lastFanCheckTime;
@@ -782,7 +780,6 @@ private:
bool FansHardwareInverted(size_t fanNumber) const;
// Serial/USB
-
uint32_t baudRates[NUM_SERIAL_CHANNELS];
uint8_t commsParams[NUM_SERIAL_CHANNELS];
OutputStack *auxOutput;
@@ -795,7 +792,6 @@ private:
uint32_t auxSeq; // Sequence number for AUX devices
// Files
-
MassStorage* massStorage;
// Data used by the tick interrupt handler
@@ -875,6 +871,9 @@ private:
// Direct pin manipulation
int8_t logicalPinModes[HighestLogicalPin + 1]; // what mode each logical pin is set to - would ideally be class PinMode not int8_t
+
+ // Misc
+ bool deliberateError; // true if we deliberately caused an exception for testing purposes
};
// Where the htm etc files are
diff --git a/src/PortControl.cpp b/src/PortControl.cpp
index 44cbdbdd..7c8a595a 100644
--- a/src/PortControl.cpp
+++ b/src/PortControl.cpp
@@ -73,13 +73,13 @@ bool PortControl::Configure(GCodeBuffer& gb, StringRef& reply)
seen = true;
UpdatePorts(0);
numConfiguredPorts = 0;
- long portNumbers[MaxPorts];
+ uint32_t portNumbers[MaxPorts];
size_t numPorts = MaxPorts;
- gb.GetLongArray(portNumbers, numPorts);
+ gb.GetUnsignedArray(portNumbers, numPorts);
for (size_t i = 0; i < numPorts; ++i)
{
- const long pnum = portNumbers[i];
- if (pnum < 0 || pnum > HighestLogicalPin)
+ const uint32_t pnum = portNumbers[i];
+ if (pnum > HighestLogicalPin)
{
reply.printf("Port number %ld out of range", pnum);
return true;
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 8c564247..e8f88066 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -1034,6 +1034,9 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
}
response->cat("]]");
+ // Fan mapping
+ response->catf(",\"fans\":%lu", tool->GetFanMapping());
+
// Filament (if any)
if (tool->GetFilament() != nullptr)
{
@@ -1042,8 +1045,15 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
response->EncodeString(filamentName, strlen(filamentName), false);
}
- // Do we have any more tools?
- response->cat((tool->Next() != nullptr) ? "}," : "}");
+ // Offsets
+ response->cat(",\"offsets\":[");
+ for (size_t i = 0; i < numAxes; i++)
+ {
+ response->catf((i == 0) ? "%.2f" : ",%.2f", (double)tool->GetOffset(i));
+ }
+
+ // Do we have any more tools?
+ response->cat((tool->Next() != nullptr) ? "]}," : "]}");
}
response->cat("]");
}
diff --git a/src/RepRapFirmware.cpp b/src/RepRapFirmware.cpp
index 8093866a..1e193f5e 100644
--- a/src/RepRapFirmware.cpp
+++ b/src/RepRapFirmware.cpp
@@ -169,7 +169,7 @@ Licence: GPL
RepRap reprap;
-const char *moduleName[] =
+const char * const moduleName[] =
{
"Platform",
"Network",
@@ -193,7 +193,7 @@ const char *moduleName[] =
// Utilities and storage not part of any class
-static char scratchStringBuffer[170]; // this needs to be long enough to print delta parameters and 18 words of stack (162 bytes)
+static char scratchStringBuffer[220]; // this needs to be long enough to print delta parameters and 24 words of stack (217 bytes)
StringRef scratchString(scratchStringBuffer, ARRAY_SIZE(scratchStringBuffer));
// For debug use
diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h
index f37e0231..23022eda 100644
--- a/src/RepRapFirmware.h
+++ b/src/RepRapFirmware.h
@@ -59,7 +59,7 @@ enum Module : uint8_t
noModule = 15
};
-extern const char *moduleName[];
+extern const char * const moduleName[];
// Warn of what's to come, so we can use pointers to classes without including the entire header files
class Network;
@@ -182,15 +182,15 @@ template<typename BitmapType> inline void ClearBit(BitmapType &b, unsigned int n
}
// Convert an array of longs to a bit map with overflow checking
-template<typename BitmapType> BitmapType LongArrayToBitMap(const long *arr, size_t numEntries)
+template<typename BitmapType> BitmapType UnsignedArrayToBitMap(const uint32_t *arr, size_t numEntries)
{
BitmapType res = 0;
for (size_t i = 0; i < numEntries; ++i)
{
- const long f = arr[i];
- if (f >= 0 && (unsigned long)f < sizeof(BitmapType) * CHAR_BIT)
+ const uint32_t f = arr[i];
+ if (f < sizeof(BitmapType) * CHAR_BIT)
{
- SetBit(res, (unsigned int)f);
+ SetBit(res, f);
}
}
return res;
diff --git a/src/Scanner.cpp b/src/Scanner.cpp
index 7f849fbc..8afa2099 100644
--- a/src/Scanner.cpp
+++ b/src/Scanner.cpp
@@ -13,12 +13,12 @@
#include "Platform.h"
-const char* ALIGN_ON_G = "align_on.g";
-const char* ALIGN_OFF_G = "align_off.g";
-const char* SCAN_PRE_G = "scan_pre.g";
-const char* SCAN_POST_G = "scan_post.g";
-const char* CALIBRATE_PRE_G = "calibrate_pre.g";
-const char* CALIBRATE_POST_G = "calibrate_post.g";
+const char* const ALIGN_ON_G = "align_on.g";
+const char* const ALIGN_OFF_G = "align_off.g";
+const char* const SCAN_PRE_G = "scan_pre.g";
+const char* const SCAN_POST_G = "scan_post.g";
+const char* const CALIBRATE_PRE_G = "calibrate_pre.g";
+const char* const CALIBRATE_POST_G = "calibrate_post.g";
void Scanner::Init()
diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp
index 1ed6d654..c47bcce9 100644
--- a/src/Storage/FileStore.cpp
+++ b/src/Storage/FileStore.cpp
@@ -89,7 +89,10 @@ bool FileStore::Open(const char* directory, const char* fileName, OpenMode mode)
}
// Also try to allocate a write buffer so we can perform faster writes
- writeBuffer = reprap.GetPlatform().GetMassStorage()->AllocateWriteBuffer();
+ // We only do this if the mode is write, not append, because we don't want to use up a large buffer to append messages to the log file,
+ // especially as we need to flush messages to SD card regularly.
+ // Currently, append mode is used only for the log file.
+ writeBuffer = (mode == OpenMode::write) ? reprap.GetPlatform().GetMassStorage()->AllocateWriteBuffer() : nullptr;
}
const FRESULT openReturn = f_open(&file, location,
diff --git a/src/Storage/FileWriteBuffer.h b/src/Storage/FileWriteBuffer.h
index c7a04116..d5198e8c 100644
--- a/src/Storage/FileWriteBuffer.h
+++ b/src/Storage/FileWriteBuffer.h
@@ -10,7 +10,6 @@
#include "RepRapFirmware.h"
-
#if SAM4E || SAM4S || SAME70
const size_t NumFileWriteBuffers = 2; // Number of write buffers
const size_t FileWriteBufLen = 8192; // Size of each write buffer
@@ -19,7 +18,6 @@ const size_t NumFileWriteBuffers = 1;
const size_t FileWriteBufLen = 4096;
#endif
-
// Class to cache data that is about to be written to the SD card. This is NOT a ring buffer,
// instead it just provides simple interfaces to cache a certain amount of data so that fewer
// f_write() calls are needed. This effectively improves upload speeds.
@@ -36,14 +34,14 @@ public:
const size_t BytesStored() const { return index; }
const size_t BytesLeft() const { return FileWriteBufLen - index; }
- size_t Store(const char *data, size_t length); // Stores some data and returns how much could be stored
- void DataTaken() { index = 0; } // Called to indicate that the buffer has been written
+ size_t Store(const char *data, size_t length); // Stores some data and returns how much could be stored
+ void DataTaken() { index = 0; } // Called to indicate that the buffer has been written
private:
FileWriteBuffer *next;
size_t index;
- int32_t data32[FileWriteBufLen / sizeof(int32_t)]; // 32-bit aligned buffer for better HSMCI performance
+ uint32_t data32[FileWriteBufLen / sizeof(uint32_t)]; // 32-bit aligned buffer for better HSMCI performance
};
inline size_t FileWriteBuffer::Store(const char *data, size_t length)
diff --git a/src/Tools/Filament.cpp b/src/Tools/Filament.cpp
index 2efb50a4..13113bc3 100644
--- a/src/Tools/Filament.cpp
+++ b/src/Tools/Filament.cpp
@@ -13,8 +13,8 @@
#include <ctime>
-const char *Filament::FilamentAssignmentFile = "filaments.csv";
-const char *Filament::FilamentAssignmentFileComment = "RepRapFirmware filament assignment file v1";
+const char * const Filament::FilamentAssignmentFile = "filaments.csv";
+const char * const Filament::FilamentAssignmentFileComment = "RepRapFirmware filament assignment file v1";
Filament *Filament::filamentList = nullptr;
diff --git a/src/Tools/Filament.h b/src/Tools/Filament.h
index bdccf8a6..58ebd1a7 100644
--- a/src/Tools/Filament.h
+++ b/src/Tools/Filament.h
@@ -35,8 +35,8 @@ public:
static Filament *GetFilamentByExtruder(const int extruder); // Retrieve the Filament instance assigned to the given extruder drive
private:
- static const char *FilamentAssignmentFile; // In which file the extruder <-> filament assignments are stored
- static const char *FilamentAssignmentFileComment; // The comment we write at the start of this file to ensure its integrity
+ static const char * const FilamentAssignmentFile; // In which file the extruder <-> filament assignments are stored
+ static const char * const FilamentAssignmentFileComment; // The comment we write at the start of this file to ensure its integrity
static Filament *filamentList;
Filament *next;
diff --git a/src/Tools/Tool.cpp b/src/Tools/Tool.cpp
index cbda3524..8047ac60 100644
--- a/src/Tools/Tool.cpp
+++ b/src/Tools/Tool.cpp
@@ -81,7 +81,7 @@ Tool * Tool::freelist = nullptr;
if (dCount == 1)
{
// Create only one Filament instance per extruder drive, and only if this tool is assigned to exactly one extruder
- Filament *filament = Filament::GetFilamentByExtruder(d[0]);
+ Filament * const filament = Filament::GetFilamentByExtruder(d[0]);
t->filament = (filament == nullptr) ? new Filament(d[0]) : filament;
}
else
@@ -90,9 +90,19 @@ Tool * Tool::freelist = nullptr;
t->filament = nullptr;
}
- t->myNumber = toolNumber;
- SafeStrncpy(t->name, name, ToolNameLength);
+ const size_t nameLength = strlen(name);
+ if (nameLength != 0)
+ {
+ t->name = new char[nameLength + 1];
+ SafeStrncpy(t->name, name, nameLength + 1);
+ }
+ else
+ {
+ t->name = nullptr;
+ }
+
t->next = nullptr;
+ t->myNumber = toolNumber;
t->state = ToolState::off;
t->driveCount = dCount;
t->heaterCount = hCount;
@@ -111,7 +121,7 @@ Tool * Tool::freelist = nullptr;
for (size_t drive = 0; drive < t->driveCount; drive++)
{
t->drives[drive] = d[drive];
- t->mix[drive] = (drive == 0) ? 1.0 : 0.0; // initial mix ratio is 1:1:0
+ t->mix[drive] = (drive == 0) ? 1.0 : 0.0; // initial mix ratio is 1:0:0
}
for (size_t heater = 0; heater < t->heaterCount; heater++)
@@ -133,6 +143,8 @@ Tool * Tool::freelist = nullptr;
{
if (t != nullptr)
{
+ delete t->name;
+ t->name = nullptr;
t->filament = nullptr;
t->next = freelist;
freelist = t;
@@ -142,7 +154,7 @@ Tool * Tool::freelist = nullptr;
void Tool::Print(StringRef& reply) const
{
reply.printf("Tool %d - ", myNumber);
- if (!StringEquals(name, ""))
+ if (name != nullptr)
{
reply.catf("name: %s; ", name);
}
@@ -392,7 +404,7 @@ void Tool::UpdateExtruderAndHeaterCount(uint16_t &numExtruders, uint16_t &numHea
for (size_t heater = 0; heater < heaterCount; heater++)
{
- if (!reprap.GetHeat().IsBedHeater(heaters[heater]) && !reprap.GetHeat().IsChamberHeater(heaters[heater]) && heaters[heater] >= numHeaters)
+ if (!reprap.GetHeat().IsBedOrChamberHeater(heaters[heater]) && heaters[heater] >= numHeaters)
{
numHeaters = heaters[heater] + 1;
}
diff --git a/src/Tools/Tool.h b/src/Tools/Tool.h
index 5e56b1d0..b5d5063f 100644
--- a/src/Tools/Tool.h
+++ b/src/Tools/Tool.h
@@ -28,9 +28,9 @@ Licence: GPL
#include "RepRapFirmware.h"
-const size_t ToolNameLength = 32; // maximum allowed length for tool names
-const AxesBitmap DefaultXAxisMapping = 1u << X_AXIS; // by default, X is mapped to X
-const AxesBitmap DefaultYAxisMapping = 1u << Y_AXIS; // by default, Y is mapped to Y
+constexpr size_t ToolNameLength = 32; // maximum allowed length for tool names
+constexpr AxesBitmap DefaultXAxisMapping = 1u << X_AXIS; // by default, X is mapped to X
+constexpr AxesBitmap DefaultYAxisMapping = 1u << Y_AXIS; // by default, Y is mapped to Y
enum class ToolState : uint8_t
{
@@ -40,6 +40,7 @@ enum class ToolState : uint8_t
};
class Filament;
+
class Tool
{
public:
@@ -85,25 +86,27 @@ protected:
private:
static Tool *freelist;
+ Tool() : next(nullptr), filament(nullptr), name(nullptr) { }
+
void SetTemperatureFault(int8_t dudHeater);
void ResetTemperatureFault(int8_t wasDudHeater);
bool AllHeatersAtHighTemperature(bool forExtrusion) const;
- int myNumber;
- char name[ToolNameLength];
- int drives[MaxExtruders];
+ Tool* next;
+ Filament *filament;
+ char *name;
+ float offset[MaxAxes];
float mix[MaxExtruders];
- size_t driveCount;
- int heaters[Heaters];
float activeTemperatures[Heaters];
float standbyTemperatures[Heaters];
+ size_t driveCount;
size_t heaterCount;
- float offset[MaxAxes];
- AxesBitmap axisOffsetsProbed;
+ int myNumber;
AxesBitmap xMapping, yMapping;
+ AxesBitmap axisOffsetsProbed;
FansBitmap fanMapping;
- Filament *filament;
- Tool* next;
+ uint8_t drives[MaxExtruders];
+ int8_t heaters[Heaters];
ToolState state;
bool heaterFault;
@@ -127,7 +130,7 @@ inline int Tool::Heater(size_t heaterNumber) const
inline const char *Tool::GetName() const
{
- return name;
+ return (name == nullptr) ? "" : name;
}
inline int Tool::Number() const
diff --git a/src/Version.h b/src/Version.h
index 29703760..0a3ebf75 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -9,11 +9,11 @@
#define SRC_VERSION_H_
#ifndef VERSION
-# define VERSION "1.20RC1"
+# define VERSION "1.20RC2"
#endif
#ifndef DATE
-# define DATE "2017-12-08"
+# define DATE "2017-12-13"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"
diff --git a/src/ZProbeProgrammer.cpp b/src/ZProbeProgrammer.cpp
index 5eb63789..d6a12f7b 100644
--- a/src/ZProbeProgrammer.cpp
+++ b/src/ZProbeProgrammer.cpp
@@ -19,7 +19,7 @@ ZProbeProgrammer::ZProbeProgrammer()
}
// Kick off sending some program bytes
-void ZProbeProgrammer::SendProgram(const long zProbeProgram[], size_t len)
+void ZProbeProgrammer::SendProgram(const uint32_t zProbeProgram[], size_t len)
{
timer.CancelCallback(); // make quite certain that this timer isn't already pending
diff --git a/src/ZProbeProgrammer.h b/src/ZProbeProgrammer.h
index ab0bf478..02e37973 100644
--- a/src/ZProbeProgrammer.h
+++ b/src/ZProbeProgrammer.h
@@ -15,7 +15,7 @@ class ZProbeProgrammer
public:
ZProbeProgrammer();
- void SendProgram(const long zProbeProgram[], size_t len);
+ void SendProgram(const uint32_t zProbeProgram[], size_t len);
private:
static bool TimerInterrupt(void *param, uint32_t& when);