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:
authorDavid Crocker <dcrocker@eschertech.com>2018-03-16 17:49:58 +0300
committerDavid Crocker <dcrocker@eschertech.com>2018-03-16 17:50:20 +0300
commitdf7c0f0a4a20a5f8f908424e9570ffe38566c890 (patch)
treefec1f61d35f7421a95a98d724388fe4c0a7589b9 /src
parent875c2d29d4436da34ac01b6292ef658660ee948e (diff)
Version 1.21RC5
New features: - New M569 T parameter options to specify step pulse width, step pulse interval, direction setup and direction hold times - M665 now sets the M208 limits (except Z min) to match the machine limits, so that Duet Web Control reports the correct values Bug fixes: - M116 commands were sometimes executed out-of-order relative to previous G10 commands if movement commands were in progress - G10 L20 now computes the workplace coordinate origin correctly - G53 is only active until the end of the current line of GCode - The default coordinate system is the one selected by G54 - G54..G59 update the user coordinates immediately - Fixed "Error: Pop(): stack underflow!" when a file or macro is terminated due to an illegal move command - A short delay is inserted when M558 is used to change the Z probe type, to allow the averaging filters to accumulate the new data - M291 messages which are non-blocking (i.e. mode < 2) are now synchronised to queued moves, like M117 messages Other changes: - Duet Web Control and PanelDue now report the coordinates relative to the origin of the current workplace - Rewrote dhcp_rec function on Duet06/085 to avoid goto statements (possible fix for startup problem when using DHCP)
Diffstat (limited to 'src')
-rw-r--r--src/BugList.txt30
-rw-r--r--src/Duet/Lwip/lwip/src/core/dhcp.c44
-rw-r--r--src/DuetNG/SX1509.h2
-rw-r--r--src/Fan.cpp6
-rw-r--r--src/Fan.h4
-rw-r--r--src/GCodes/GCodeBuffer.cpp7
-rw-r--r--src/GCodes/GCodeMachineState.cpp3
-rw-r--r--src/GCodes/GCodeMachineState.h1
-rw-r--r--src/GCodes/GCodeQueue.cpp8
-rw-r--r--src/GCodes/GCodes.cpp24
-rw-r--r--src/GCodes/GCodes.h46
-rw-r--r--src/GCodes/GCodes2.cpp83
-rw-r--r--src/GCodes/GCodes3.cpp11
-rw-r--r--src/Movement/DDA.cpp31
-rw-r--r--src/Movement/DDA.h4
-rw-r--r--src/Movement/Kinematics/LinearDeltaKinematics.cpp11
-rw-r--r--src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp1
-rw-r--r--src/Pins.h4
-rw-r--r--src/Platform.cpp79
-rw-r--r--src/Platform.h17
-rw-r--r--src/RepRap.cpp95
-rw-r--r--src/RepRap.h1
-rw-r--r--src/Version.h4
23 files changed, 346 insertions, 170 deletions
diff --git a/src/BugList.txt b/src/BugList.txt
index 0afe7b67..5916a9b5 100644
--- a/src/BugList.txt
+++ b/src/BugList.txt
@@ -60,31 +60,45 @@ Done in 1.21RC2:
- [done, should be better] https://www.duet3d.com/forum/thread.php?pid=40183#p40183, https://www.duet3d.com/forum/thread.php?pid=39509#p39509 (not starting up correctly in access point mode)
- [done] Attempted movements outside limits or when not homed cause current print file to be aborted
-Remaining:
+Done in 1.21RC4:
- [done] for CoreXZ require just X and Y to be homed before probing (so that G30 can be used to home Z axis)
-- [done, test] Check min. 8 character password in M589, see https://www.duet3d.com/forum/thread.php?pid=40914#p40914
- [done] G10 L2
- [done] G10 L20
- [done, test] Suppress heater fault detection when heaters are suspended
- [done] DuetWiFiServer: new SDK version
- [problem gone away with latest DuetWiFiServer] Duet WiFi (Kossel): disconnects every time after I upload file xyzCalibration_cube s3d.gcode due to incomplete json reply, but can reconnect afterwards
-- [done] Ethernet: set W5500 to auto negotiate
+- [done, ok] Ethernet: set W5500 to auto negotiate
+- [done, test] Check min. 8 character password in M589, see https://www.duet3d.com/forum/thread.php?pid=40914#p40914
- [done, test] I parameter on M452, M453 and M573 didn't work
- [done, test] M564 H0 to allow axis movement before homing on Cartesian/CoreXY printers
- [done, test] Filament length comment generated by Cura, see https://www.duet3d.com/forum/thread.php?pid=40913#p40913
- [done, test] Doesn't cancel homeall.g if there is an illegal Z move at the start, https://www.duet3d.com/forum/thread.php?pid=41082#p41082
+- [done] Corrected Z probe input pin in RADDS build
+- [done, test] in M589 check password is empty or at least 8 characters
+- [done] Multi tap on G30
+- [done, didn't help] Possible fix to Duet 06/085 failure to start when using DHCP
+- [ok] Test smart effector sensitivity programming
+Remaining:
+- [done] M116 fix, see https://www.duet3d.com/forum/thread.php?pid=41954#p41954. Also M109, M190, M191
+- [done] queue M291 non-blocking messages
+- [done, networking seems OK inc. DHCP] Duet 06/085 DHCP issue; rewrite dhcp_recv without goto? https://www.duet3d.com/forum/thread.php?pid=34605#p34605 and https://www.duet3d.com/forum/thread.php?pid=41923#p41923
+- [done, hard to test] Error: Pop(): stack underflow! https://www.duet3d.com/forum/thread.php?pid=41967#p41967
+- [done, test] Short delay after M558, https://www.duet3d.com/forum/thread.php?pid=41967#p41967
+- [done, test] G10 L20 sign error, https://www.duet3d.com/forum/thread.php?pid=42044#p42044
+- [done, test] When G54 etc. are sent, update user coordinates immediately
+- [done, test] G54 is the default coordinate system; G53 only lasts until end of line
+- [done, test] DWC and PD report user coordinates, nt machine coordinates
+- [done] new step pulse timing for slow drivers
+- check out G30 H parameter, https://www.duet3d.com/forum/thread.php?pid=42322#p42322
+
+- Error message if you attempt movement with VIN < minimum
- How should we lift X on a CoreXZ printer before homing?
-- Multi tap on G30?
-
- if a homing command in an SD print file is aborted due to e.g. G1 Z5 in the homing file, error message should be written to both DWC and PanelDue
-- M116 issue
-- [made a change, but try to reproduce it] Duet 0.8/0.8.5 DHCP issue, https://www.duet3d.com/forum/thread.php?pid=34605#p34605
- stall detect on Z axis
- Files generated by Cura doesn't detect layer changes, see https://www.duet3d.com/forum/thread.php?pid=40865#p40865
- [re-test using new DuetWiFiServer] "Failed to change mode" messages after M552 S2/S0/S1 cycle
- [can't reproduce] "Attempt to seek on a non-open file", https://www.duet3d.com/forum/thread.php?pid=41175#p41175
-- Test smart effector sensitivity programming
- min/max RSSI display?
diff --git a/src/Duet/Lwip/lwip/src/core/dhcp.c b/src/Duet/Lwip/lwip/src/core/dhcp.c
index 3b9dea30..f5483bc7 100644
--- a/src/Duet/Lwip/lwip/src/core/dhcp.c
+++ b/src/Duet/Lwip/lwip/src/core/dhcp.c
@@ -1568,12 +1568,24 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
if (p->len < DHCP_MIN_REPLY_LEN) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP reply message or pbuf too short\n"));
+#if 1 //dc42
+ dhcp->msg_in = NULL;
+ pbuf_free(p);
+ return;
+#else
goto free_pbuf_and_return;
+#endif
}
if (reply_msg->op != DHCP_BOOTREPLY) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP reply message, but type %"U16_F"\n", (u16_t)reply_msg->op));
+#if 1 //dc42
+ dhcp->msg_in = NULL;
+ pbuf_free(p);
+ return;
+#else
goto free_pbuf_and_return;
+#endif
}
/* iterate through hardware address and match against DHCP message */
#if 1 //dc42 from lwip2
@@ -1585,27 +1597,51 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("netif->hwaddr[%"U16_F"]==%02"X16_F" != reply_msg->chaddr[%"U16_F"]==%02"X16_F"\n",
(u16_t)i, (u16_t)netif->hwaddr[i], (u16_t)i, (u16_t)reply_msg->chaddr[i]));
+#if 1 //dc42
+ dhcp->msg_in = NULL;
+ pbuf_free(p);
+ return;
+#else
goto free_pbuf_and_return;
+#endif
}
}
/* match transaction ID against what we expected */
if (ntohl(reply_msg->xid) != dhcp->xid) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
("transaction id mismatch reply_msg->xid(%"X32_F")!=dhcp->xid(%"X32_F")\n",ntohl(reply_msg->xid),dhcp->xid));
+#if 1 //dc42
+ dhcp->msg_in = NULL;
+ pbuf_free(p);
+ return;
+#else
goto free_pbuf_and_return;
+#endif
}
/* option fields could be unfold? */
if (dhcp_parse_reply(dhcp, p) != ERR_OK) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS,
("problem unfolding DHCP message - too short on memory?\n"));
+#if 1 //dc42
+ dhcp->msg_in = NULL;
+ pbuf_free(p);
+ return;
+#else
goto free_pbuf_and_return;
+#endif
}
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("searching DHCP_OPTION_MESSAGE_TYPE\n"));
/* obtain pointer to DHCP message type */
if (!dhcp_option_given(dhcp, DHCP_OPTION_IDX_MSG_TYPE)) {
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP_OPTION_MESSAGE_TYPE option not found\n"));
+#if 1 //dc42
+ dhcp->msg_in = NULL;
+ pbuf_free(p);
+ return;
+#else
goto free_pbuf_and_return;
+#endif
}
/* read DHCP message type */
@@ -1653,14 +1689,10 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
/* remember offered lease */
dhcp_handle_offer(netif);
}
+#if 0 //dc42
free_pbuf_and_return:
-#if 1 //dc42 from lwpi2
-if (dhcp != NULL) {
- dhcp->msg_in = NULL;
-}
-#else
- dhcp->msg_in = NULL;
#endif
+ dhcp->msg_in = NULL;
pbuf_free(p);
}
diff --git a/src/DuetNG/SX1509.h b/src/DuetNG/SX1509.h
index 76a3a92a..96a6a59b 100644
--- a/src/DuetNG/SX1509.h
+++ b/src/DuetNG/SX1509.h
@@ -27,7 +27,7 @@ Distributed as-is; no warranty is given.
#include "Core.h"
const int ReceiveTimeout = 1000; // Timeout for I2C receive
-const uint8_t DefaultOscDivider = 5; // a clock divider of 2 ^ (5 - 1) = 16 gives a PSWM frequency of 2MHz / (16 * 255) = 488Hz
+const uint8_t DefaultOscDivider = 5; // a clock divider of 2 ^ (5 - 1) = 16 gives a PWM frequency of 2MHz / (16 * 255) = 488Hz
class SX1509
{
diff --git a/src/Fan.cpp b/src/Fan.cpp
index 0a3deb9f..367433b0 100644
--- a/src/Fan.cpp
+++ b/src/Fan.cpp
@@ -116,7 +116,7 @@ bool Fan::Configure(unsigned int mcode, int fanNum, GCodeBuffer& gb, const Strin
}
if (heatersMonitored != 0)
{
- SetValue(1.0); // default the fan speed to full for safety
+ SetPwm(1.0); // default the fan speed to full for safety
}
}
@@ -124,7 +124,7 @@ bool Fan::Configure(unsigned int mcode, int fanNum, GCodeBuffer& gb, const Strin
if (seen && gb.Seen('S')) // Set new fan value - process this after processing 'H' or it may not be acted on
{
const float f = constrain<float>(gb.GetFValue(), 0.0, 255.0);
- SetValue(f);
+ SetPwm(f);
}
if (seen)
@@ -158,7 +158,7 @@ bool Fan::Configure(unsigned int mcode, int fanNum, GCodeBuffer& gb, const Strin
return seen;
}
-void Fan::SetValue(float speed)
+void Fan::SetPwm(float speed)
{
if (speed > 1.0)
{
diff --git a/src/Fan.h b/src/Fan.h
index 19cbd1cd..9fb9d9ad 100644
--- a/src/Fan.h
+++ b/src/Fan.h
@@ -25,10 +25,10 @@ public:
bool Configure(unsigned int mcode, int fanNum, GCodeBuffer& gb, const StringRef& reply, bool& error);
bool IsEnabled() const { return pin != NoPin; }
- float GetValue() const { return val; }
+ float GetConfiguredPwm() const { return val; } // returns the configured PWM. Actual PWM may be different, e.g. due to blipping or for thermostatic fans.
void Init(Pin p_pin, bool hwInverted);
- void SetValue(float speed);
+ void SetPwm(float speed);
void SetHeatersMonitored(HeatersMonitoredBitmap h);
bool Check(); // update the fan PWM returning true if it is a thermostatic fan that is on
void Disable();
diff --git a/src/GCodes/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer.cpp
index ccb20d82..a3bc359b 100644
--- a/src/GCodes/GCodeBuffer.cpp
+++ b/src/GCodes/GCodeBuffer.cpp
@@ -390,6 +390,7 @@ void GCodeBuffer::SetFinished(bool f)
}
else
{
+ machineState->useMachineCoordinates = false; // G53 does not persist beyond the current line
Init();
}
}
@@ -445,13 +446,14 @@ float GCodeBuffer::GetFValue()
}
// Get a colon-separated list of floats after a key letter
+// If doPad is true then we allow just one element to be given, in which case we fill all elements with that value
const void GCodeBuffer::GetFloatArray(float arr[], size_t& returnedLength, bool doPad)
{
if (readPointer >= 0)
{
size_t length = 0;
bool inList = true;
- while(inList)
+ while (inList)
{
if (length >= returnedLength) // array limit has been set in here
{
@@ -475,7 +477,7 @@ const void GCodeBuffer::GetFloatArray(float arr[], size_t& returnedLength, bool
// Special case if there is one entry and returnedLength requests several. Fill the array with the first entry.
if (doPad && length == 1 && returnedLength > 1)
{
- for(size_t i = 1; i < returnedLength; i++)
+ for (size_t i = 1; i < returnedLength; i++)
{
arr[i] = arr[0];
}
@@ -930,6 +932,7 @@ bool GCodeBuffer::PushState()
ms->runningM501 = machineState->runningM501;
ms->runningM502 = machineState->runningM502;
ms->volumetricExtrusion = false;
+ ms->useMachineCoordinates = false;
ms->messageAcknowledged = false;
ms->waitingForAcknowledgement = false;
machineState = ms;
diff --git a/src/GCodes/GCodeMachineState.cpp b/src/GCodes/GCodeMachineState.cpp
index dc396a3d..696d8f07 100644
--- a/src/GCodes/GCodeMachineState.cpp
+++ b/src/GCodes/GCodeMachineState.cpp
@@ -13,7 +13,8 @@ unsigned int GCodeMachineState::numAllocated = 0;
// Create a default initialised GCodeMachineState
GCodeMachineState::GCodeMachineState()
: previous(nullptr), feedrate(DefaultFeedrate * SecondsToMinutes), fileState(), lockedResources(0), errorMessage(nullptr), state(GCodeState::normal),
- drivesRelative(false), axesRelative(false), doingFileMacro(false), runningM501(false), runningM502(false), volumetricExtrusion(false), waitingForAcknowledgement(false), messageAcknowledged(false)
+ drivesRelative(false), axesRelative(false), doingFileMacro(false), runningM501(false), runningM502(false),
+ volumetricExtrusion(false), useMachineCoordinates(false), waitingForAcknowledgement(false), messageAcknowledged(false)
{
}
diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h
index 9ac29a64..d1455986 100644
--- a/src/GCodes/GCodeMachineState.h
+++ b/src/GCodes/GCodeMachineState.h
@@ -104,6 +104,7 @@ public:
runningM501 : 1,
runningM502 : 1,
volumetricExtrusion : 1,
+ useMachineCoordinates : 1, // true if seen G53 on this line of GCode
// Caution: these next 3 will be modified out-of-process when we use RTOS, so they will need to be individual bool variables
waitingForAcknowledgement : 1,
messageAcknowledged : 1,
diff --git a/src/GCodes/GCodeQueue.cpp b/src/GCodes/GCodeQueue.cpp
index 0aa44556..207bfd17 100644
--- a/src/GCodes/GCodeQueue.cpp
+++ b/src/GCodes/GCodeQueue.cpp
@@ -60,6 +60,14 @@ GCodeQueue::GCodeQueue() : freeItems(nullptr), queuedItems(nullptr)
case 420: // set RGB colour
return true;
+ case 291:
+ {
+ bool seen = false;
+ int32_t sParam = 1;
+ gb.TryGetIValue('S', sParam, seen);
+ return sParam < 2; // queue non-blocking messages only
+ }
+
default:
break;
}
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index ac9d9c0c..6062b9e8 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -160,7 +160,7 @@ void GCodes::Reset()
{
axisScaleFactors[i] = 1.0;
#if SUPPORT_WORKPLACE_COORDINATES
- for (size_t j = 0; j < 10; ++j)
+ for (size_t j = 0; j < NumCoordinateSystems; ++j)
{
workplaceCoordinates[j][i] = 0.0;
}
@@ -320,7 +320,7 @@ void GCodes::Spin()
if (gb.MachineState().messageAcknowledged)
{
const bool wasCancelled = gb.MachineState().messageCancelled;
- Pop(gb);
+ gb.PopState(); // this could fail if the current macro has already been aborted
if (wasCancelled)
{
@@ -527,7 +527,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
if (LockMovementAndWaitForStandstill(gb)) // wait for tpre.g to finish executing
{
reprap.SelectTool(gb.MachineState().newToolNumber, simulationMode != 0);
- GetCurrentUserPosition(); // get the actual position of the new tool
+ UpdateCurrentUserPosition(); // get the actual position of the new tool
gb.AdvanceState();
if (AllAxesAreHomed())
@@ -2347,6 +2347,12 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
{
currentUserPosition[axis] += moveArg;
}
+#if SUPPORT_WORKPLACE_COORDINATES
+ else if (gb.MachineState().useMachineCoordinates)
+ {
+ currentUserPosition[axis] = moveArg - workplaceCoordinates[currentCoordinateSystem][axis];
+ }
+#endif
else
{
currentUserPosition[axis] = moveArg;
@@ -2475,6 +2481,13 @@ const char* GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise)
currentUserPosition[X_AXIS] += xParam;
currentUserPosition[Y_AXIS] += yParam;
}
+#if SUPPORT_WORKPLACE_COORDINATES
+ else if (gb.MachineState().useMachineCoordinates)
+ {
+ currentUserPosition[X_AXIS] = xParam - workplaceCoordinates[currentCoordinateSystem][X_AXIS];
+ currentUserPosition[Y_AXIS] = yParam - workplaceCoordinates[currentCoordinateSystem][Y_AXIS];
+ }
+#endif
else
{
currentUserPosition[X_AXIS] = xParam;
@@ -4231,7 +4244,7 @@ void GCodes::SetMachinePosition(const float positionNow[DRIVES], bool doBedCompe
}
// Get the current position from the Move class
-void GCodes::GetCurrentUserPosition()
+void GCodes::UpdateCurrentUserPosition()
{
reprap.GetMove().GetCurrentUserPosition(moveBuffer.coords, 0, reprap.GetCurrentXAxes(), reprap.GetCurrentYAxes());
ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition);
@@ -4271,7 +4284,8 @@ void GCodes::RestorePosition(const RestorePoint& rp, GCodeBuffer *gb)
}
// Convert user coordinates to head reference point coordinates, optionally allowing for X axis mapping
-// If the X axis is mapped to some other axes not including X, then the X coordinate of coordsOut will be left unchanged. So make sure it is suitably initialised before calling this.
+// If the X axis is mapped to some other axes not including X, then the X coordinate of coordsOut will be left unchanged.
+// So make sure it is suitably initialised before calling this.
void GCodes::ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[MaxAxes], AxesBitmap explicitAxes)
{
const Tool * const currentTool = reprap.GetCurrentTool();
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index ba312f2c..cf9ab462 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -160,6 +160,7 @@ public:
float GetRawExtruderTotalByDrive(size_t extruder) const; // Get the total extrusion since start of print, for one drive
float GetTotalRawExtrusion() const { return rawExtruderTotal; } // Get the total extrusion since start of print, all drives
float GetBabyStepOffset() const { return currentBabyStepZOffset; } // Get the current baby stepping Z offset
+ const float *GetUserPosition() const { return currentUserPosition; } // Return the current user position
RegularGCodeInput *GetHTTPInput() const { return httpInput; }
RegularGCodeInput *GetTelnetInput() const { return telnetInput; }
@@ -292,42 +293,42 @@ private:
bool ToolHeatersAtSetTemperatures(const Tool *tool, bool waitWhenCooling) const; // Wait for the heaters associated with the specified tool to reach their set temperatures
void GenerateTemperatureReport(const StringRef& reply) const; // Store a standard-format temperature report in reply
OutputBuffer *GenerateJsonStatusResponse(int type, int seq, ResponseSource source) const; // Generate a M408 response
- void CheckReportDue(GCodeBuffer& gb, const StringRef& reply) const; // Check whether we need to report temperatures or status
+ void CheckReportDue(GCodeBuffer& gb, const StringRef& reply) const; // Check whether we need to report temperatures or status
- void SavePosition(RestorePoint& rp, const GCodeBuffer& gb) const; // Save position to a restore point
- void RestorePosition(const RestorePoint& rp, GCodeBuffer *gb); // Restore user position from a restore point
+ void SavePosition(RestorePoint& rp, const GCodeBuffer& gb) const; // Save position to a restore point
+ void RestorePosition(const RestorePoint& rp, GCodeBuffer *gb); // Restore user position from a restore point
- void SetAllAxesNotHomed(); // Flag all axes as not homed
+ void SetAllAxesNotHomed(); // Flag all axes as not homed
void SetMachinePosition(const float positionNow[DRIVES], bool doBedCompensation = true); // Set the current position to be this
- void GetCurrentUserPosition(); // Get the current position form the Move class
+ void UpdateCurrentUserPosition(); // Get the current position from the Move class
void ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[MaxAxes], AxesBitmap explicitAxes = 0); // Convert user coordinates to head reference point coordinates
void ToolOffsetInverseTransform(const float coordsIn[MaxAxes], float coordsOut[MaxAxes]); // Convert head reference point coordinates to user coordinates
- const char *TranslateEndStopResult(EndStopHit es); // Translate end stop result to text
- GCodeResult RetractFilament(GCodeBuffer& gb, bool retract); // Retract or un-retract filaments
- GCodeResult LoadFilament(GCodeBuffer& gb, const StringRef& reply); // Load the specified filament into a tool
- GCodeResult UnloadFilament(GCodeBuffer& gb, const StringRef& reply); // Unload the current filament from a tool
+ const char *TranslateEndStopResult(EndStopHit es); // Translate end stop result to text
+ GCodeResult RetractFilament(GCodeBuffer& gb, bool retract); // Retract or un-retract filaments
+ GCodeResult LoadFilament(GCodeBuffer& gb, const StringRef& reply); // Load the specified filament into a tool
+ GCodeResult UnloadFilament(GCodeBuffer& gb, const StringRef& reply); // Unload the current filament from a tool
bool ChangeMicrostepping(size_t drive, unsigned int microsteps, int mode) const; // Change microstepping on the specified drive
void ListTriggers(const 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
- void CheckHeaterFault(); // Check for and respond to a heater fault, returning true if we should exit
- void DoEmergencyStop(); // Execute an emergency stop
+ void CheckTriggers(); // Check for and execute triggers
+ void CheckFilament(); // Check for and respond to filament errors
+ void CheckHeaterFault(); // Check for and respond to a heater fault, returning true if we should exit
+ void DoEmergencyStop(); // Execute an emergency stop
- void DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg) // Pause the print
+ void DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg) // Pause the print
pre(resourceOwners[movementResource] = &gb);
#if HAS_VOLTAGE_MONITOR || HAS_SMART_DRIVERS
- bool DoEmergencyPause(); // Do an emergency pause following loss of power or a motor stall
+ bool DoEmergencyPause(); // Do an emergency pause following loss of power or a motor stall
#endif
- void SetMappedFanSpeed(); // Set the speeds of fans mapped for the current tool
- void SaveFanSpeeds(); // Save the speeds of all fans
+ void SetMappedFanSpeed(); // Set the speeds of fans mapped for the current tool
+ void SaveFanSpeeds(); // Save the speeds of all fans
- GCodeResult SetOrReportZProbe(GCodeBuffer& gb, const StringRef &reply); // Handle M558
+ GCodeResult SetOrReportZProbe(GCodeBuffer& gb, const StringRef &reply); // Handle M558
GCodeResult DefineGrid(GCodeBuffer& gb, const StringRef &reply); // Define the probing grid, returning true if error
- bool LoadHeightMap(GCodeBuffer& gb, const StringRef& reply) const; // Load the height map from file
- bool SaveHeightMap(GCodeBuffer& gb, const StringRef& reply) const; // Save the height map to file
- GCodeResult ProbeGrid(GCodeBuffer& gb, const StringRef& reply); // Start probing the grid, returning true if we didn't because of an error
+ bool LoadHeightMap(GCodeBuffer& gb, const StringRef& reply) const; // Load the height map from file
+ bool SaveHeightMap(GCodeBuffer& gb, const StringRef& reply) const; // Save the height map to file
+ GCodeResult ProbeGrid(GCodeBuffer& gb, const StringRef& reply); // Start probing the grid, returning true if we didn't because of an error
GCodeResult CheckOrConfigureTrigger(GCodeBuffer& gb, const StringRef& reply, int code); // Handle M581 and M582
GCodeResult UpdateFirmware(GCodeBuffer& gb, const StringRef &reply); // Handle M997
GCodeResult SendI2c(GCodeBuffer& gb, const StringRef &reply); // Handle M260
@@ -431,8 +432,9 @@ private:
float arcSegmentLength; // Length of segments that we split arc moves into
#if SUPPORT_WORKPLACE_COORDINATES
+ static const size_t NumCoordinateSystems = 9;
unsigned int currentCoordinateSystem;
- float workplaceCoordinates[10][MaxAxes]; // Workplace coordinate offsets
+ float workplaceCoordinates[NumCoordinateSystems][MaxAxes]; // Workplace coordinate offsets
#else
float axisOffsets[MaxAxes]; // M206 axis offsets
#endif
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index dea916c1..3be09f1f 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -89,13 +89,13 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply)
{
GCodeResult result = GCodeResult::ok;
const int code = gb.GetCommandNumber();
- if (simulationMode != 0 && code > 4 && code != 10 && code != 11 && code != 20 && code != 21 && code != 90 && code != 91 && code != 92)
+ if (simulationMode != 0 && code > 4 && code != 10 && code != 11 && code != 20 && code != 21 && (code < 53 || code > 59) && (code < 90 || code > 92))
{
- return true; // we only simulate some gcodes
+ return true; // we only simulate some gcodes
}
if (gb.MachineState().runningM502 && code != 31)
{
- return true; // when running M502 the only gcode we execute is G31
+ return true; // when running M502 the only gcode we execute is G31
}
switch (code)
@@ -272,26 +272,35 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, const StringRef& reply)
break;
#if SUPPORT_WORKPLACE_COORDINATES
- case 53: // Switch to coordinate system 0
+ case 53: // Temporarily use machine coordinates
+ gb.MachineState().useMachineCoordinates = true;
+ break;
+
case 54: // Switch to coordinate system 1
case 55: // Switch to coordinate system 2
case 56: // Switch to coordinate system 3
case 57: // Switch to coordinate system 4
case 58: // Switch to coordinate system 5
case 59: // Switch to coordinate system 6,7,8,9
+ if (!LockMovementAndWaitForStandstill(gb))
{
- unsigned int cs = code - 53;
+ return false;
+ }
+ {
+ unsigned int cs = code - 54;
if (code == 59)
{
const int8_t fraction = gb.GetCommandFraction();
if (fraction >= 0)
{
- cs += (unsigned int) fraction;
+ cs += (unsigned int)fraction;
}
}
- if (cs < ARRAY_SIZE(workplaceCoordinates))
+ if (cs < NumCoordinateSystems)
{
- currentCoordinateSystem = cs;
+ currentCoordinateSystem = cs; // this is the zero-base coordinate system number
+ gb.MachineState().useMachineCoordinates = false;
+ ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition); // update user coordinates
}
else
{
@@ -1239,8 +1248,15 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
break;
- case 104:
case 109: // Deprecated in RRF, but widely generated by slicers
+ if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished
+ || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution
+ )
+ {
+ return false;
+ }
+ // no break
+ case 104:
// New behaviour from 1.20beta12:
// M109 Snnn
// - If no tools are active, set Tool 0 to active
@@ -1388,6 +1404,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
break;
case 116: // Wait for set temperatures
+ if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished
+ || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution
+ )
+ {
+ return false;
+ }
+
if (!cancelWait)
{
bool seen = false;
@@ -1694,12 +1717,18 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
case 190: // Set bed temperature and wait
case 191: // Set chamber temperature and wait
+ if ( !LockMovementAndWaitForStandstill(gb) // wait until movement has finished
+ || !IsCodeQueueIdle() // also wait until deferred command queue has caught up to avoid out-of-order execution
+ )
+ {
+ return false;
+ }
{
// Check if the heater index is passed
- int index = gb.Seen('P') ? gb.GetIValue() : 0;
- if (index < 0 || index >= (int)((code == 190) ? NumBedHeaters : NumChamberHeaters))
+ const uint32_t index = gb.Seen('P') ? gb.GetUIValue() : 0;
+ if (index >= ((code == 190) ? NumBedHeaters : NumChamberHeaters))
{
- reply.printf("Invalid heater index '%d'", index);
+ reply.printf("Invalid heater index '%" PRIu32 "'", index);
result = GCodeResult::error;
break;
}
@@ -2139,6 +2168,11 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
break;
}
+ if (sParam >= 2 && !LockMovementAndWaitForStandstill(gb))
+ {
+ return false; // if it's a blocking message, wait for movement to stop before displaying it
+ }
+
float tParam;
if (sParam == 0 || sParam == 1)
{
@@ -3046,7 +3080,16 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
if (gb.Seen('T'))
{
- platform.SetDriverStepTiming(drive, gb.GetFValue());
+ float timings[4];
+ size_t numTimings = ARRAY_SIZE(timings);
+ gb.GetFloatArray(timings, numTimings, true);
+ if (numTimings != ARRAY_SIZE(timings))
+ {
+ reply.copy("bad timing parameter");
+ result = GCodeResult::error;
+ break;
+ }
+ platform.SetDriverStepTiming(drive, timings);
seen = true;
}
bool badParameter = false;
@@ -3063,14 +3106,18 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
if (badParameter)
{
- platform.Message(ErrorMessage, "M569 no longer accepts XYZE parameters; use M584 instead\n");
+ reply.copy("M569 no longer accepts XYZE parameters; use M584 instead");
+ result = GCodeResult::error;
}
else if (!seen)
{
- reply.printf("A %d sends drive %u forwards, a %d enables it, and the minimum pulse width is %.1f microseconds",
- (int)platform.GetDirectionValue(drive), drive,
- (int)platform.GetEnableValue(drive),
- (double)platform.GetDriverStepTiming(drive));
+ float timings[4];
+ platform.GetDriverStepTiming(drive, timings);
+ reply.printf("Drive %u runs %s, active %s enable, step timing %.1f,%.1f,%.1f,%.1f microseconds",
+ drive,
+ (platform.GetDirectionValue(drive)) ? "forwards" : "in reverse",
+ (platform.GetEnableValue(drive)) ? "high" : "low",
+ (double)timings[0], (double)timings[1], (double)timings[2], (double)timings[3]);
}
}
}
diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp
index 9ab7291b..1d0e20f6 100644
--- a/src/GCodes/GCodes3.cpp
+++ b/src/GCodes/GCodes3.cpp
@@ -198,7 +198,7 @@ GCodeResult GCodes::GetSetWorkplaceCoordinates(GCodeBuffer& gb, const StringRef&
if (gb.Seen('P'))
{
const uint32_t cs = gb.GetIValue();
- if (cs < ARRAY_SIZE(workplaceCoordinates))
+ if (cs > 0 && cs <= NumCoordinateSystems)
{
bool seen = false;
for (size_t axis = 0; axis < numVisibleAxes; axis++)
@@ -214,8 +214,8 @@ GCodeResult GCodes::GetSetWorkplaceCoordinates(GCodeBuffer& gb, const StringRef&
}
seen = true;
}
- workplaceCoordinates[cs][axis] = (compute)
- ? coord - currentUserPosition[axis] + workplaceCoordinates[currentCoordinateSystem][axis]
+ workplaceCoordinates[cs - 1][axis] = (compute)
+ ? currentUserPosition[axis] - coord + workplaceCoordinates[currentCoordinateSystem][axis]
: coord;
}
}
@@ -226,10 +226,10 @@ GCodeResult GCodes::GetSetWorkplaceCoordinates(GCodeBuffer& gb, const StringRef&
}
else
{
- reply.printf("Coordinates of workplace %" PRIu32 ":", cs);
+ reply.printf("Origin of workplace %" PRIu32 ":", cs);
for (size_t axis = 0; axis < numVisibleAxes; axis++)
{
- reply.catf(" %c%.2f", axisLetters[axis], (double)workplaceCoordinates[cs][axis]);
+ reply.catf(" %c%.2f", axisLetters[axis], (double)workplaceCoordinates[cs - 1][axis]);
}
}
return GCodeResult::ok;
@@ -345,6 +345,7 @@ GCodeResult GCodes::SetOrReportZProbe(GCodeBuffer& gb, const StringRef &reply)
{
platform.SetZProbeType(gb.GetIValue());
seenType = true;
+ DoDwellTime(gb, 100); // delay a little to allow the averaging filters to accumulate data from the new source
}
ZProbe params = platform.GetCurrentZProbeParameters();
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index a0bf5aab..45250ae9 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -1440,7 +1440,9 @@ pre(state == frozen)
return true; // schedule another interrupt immediately
}
-uint32_t DDA::maxReps = 0; // this holds he maximum ISR loop count
+uint32_t DDA::maxReps = 0; // this holds he maximum ISR loop count
+uint32_t DDA::lastStepLowTime = 0;
+uint32_t DDA::lastDirChangeTime = 0;
// This is called by the interrupt service routine to execute steps.
// It returns true if it needs to be called again on the DDA of the new current move, otherwise false.
@@ -1449,7 +1451,7 @@ uint32_t DDA::maxReps = 0; // this holds he maximum ISR loop count
bool DDA::Step()
{
Platform& platform = reprap.GetPlatform();
- uint32_t lastStepPulseTime = platform.GetInterruptClocks();
+ uint32_t lastStepPulseTime = lastStepLowTime;
bool repeat;
uint32_t numReps = 0;
do
@@ -1481,7 +1483,7 @@ bool DDA::Step()
//if (t3 < minCalcTime) minCalcTime = t3;
}
- if ((driversStepping & platform.GetSlowDrivers()) == 0) // if not using any external drivers
+ if ((driversStepping & platform.GetSlowDriversBitmap()) == 0) // if not using any external drivers
{
// 3. Step the drivers
Platform::StepDriversHigh(driversStepping); // generate the steps
@@ -1489,22 +1491,27 @@ bool DDA::Step()
else
{
// 3. Step the drivers
- while (Platform::GetInterruptClocks() - lastStepPulseTime < platform.GetSlowDriverClocks()) {}
+ uint32_t now;
+ do
+ {
+ now = Platform::GetInterruptClocks();
+ }
+ while (now - lastStepPulseTime < platform.GetSlowDriverStepLowClocks() || now - lastDirChangeTime < platform.GetSlowDriverDirSetupClocks());
Platform::StepDriversHigh(driversStepping); // generate the steps
lastStepPulseTime = Platform::GetInterruptClocks();
// 3a. Reset all step pins low. Do this now because some external drivers don't like the direction pins being changed before the end of the step pulse.
- while (Platform::GetInterruptClocks() - lastStepPulseTime < platform.GetSlowDriverClocks()) {}
+ while (Platform::GetInterruptClocks() - lastStepPulseTime < platform.GetSlowDriverStepHighClocks()) {}
Platform::StepDriversLow(); // set all step pins low
- lastStepPulseTime = Platform::GetInterruptClocks();
+ lastStepLowTime = lastStepPulseTime = Platform::GetInterruptClocks();
}
// 4. Remove those drives from the list, calculate the next step times, update the direction pins where necessary,
// and re-insert them so as to keep the list in step-time order.
// Note that the call to CalcNextStepTime may change the state of Direction pin.
- DriveMovement *dmToInsert = firstDM; // head of the chain we need to re-insert
- firstDM = dm; // remove the chain from the list
- while (dmToInsert != dm) // note that both of these may be nullptr
+ DriveMovement *dmToInsert = firstDM; // head of the chain we need to re-insert
+ firstDM = dm; // remove the chain from the list
+ while (dmToInsert != dm) // note that both of these may be nullptr
{
const bool hasMoreSteps = (isDeltaMovement && dmToInsert->drive < DELTA_AXES)
? dmToInsert->CalcNextStepTimeDelta(*this, true)
@@ -1518,7 +1525,7 @@ bool DDA::Step()
}
// 5. Reset all step pins low. We already did this if we are using any external drivers, but doing it again does no harm.
- Platform::StepDriversLow(); // set all step pins low
+ Platform::StepDriversLow(); // set all step pins low
// 6. Check for move completed
if (firstDM == nullptr)
@@ -1542,8 +1549,8 @@ bool DDA::Step()
// However, following a move that checks endstops or the Z probe, we always wait for the move to complete before we schedule another, so this doesn't matter.
const uint32_t finishTime = moveStartTime + clocksNeeded; // calculate how long this move should take
Move& move = reprap.GetMove();
- move.CurrentMoveCompleted(); // tell Move that the current move is complete
- return move.TryStartNextMove(finishTime); // schedule the next move
+ move.CurrentMoveCompleted(); // tell Move that the current move is complete
+ return move.TryStartNextMove(finishTime); // schedule the next move
}
return false;
}
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 5de52e3f..72124b30 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -127,7 +127,9 @@ public:
static int32_t loggedProbePositions[XYZ_AXES * MaxLoggedProbePositions];
#endif
- static uint32_t maxReps;
+ static uint32_t maxReps; // maximum number of times that the ISR looped
+ static uint32_t lastStepLowTime; // when we last completed a step pulse to a slow driver
+ static uint32_t lastDirChangeTime; // when we last change the DIR signal to a slow driver
private:
DriveMovement *FindDM(size_t drive) const;
diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.cpp b/src/Movement/Kinematics/LinearDeltaKinematics.cpp
index 4704b191..7029deee 100644
--- a/src/Movement/Kinematics/LinearDeltaKinematics.cpp
+++ b/src/Movement/Kinematics/LinearDeltaKinematics.cpp
@@ -593,6 +593,12 @@ bool LinearDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
if (gb.Seen('B'))
{
printRadius = gb.GetFValue();
+ // Set the axis limits so that DWC reports them correctly (they are not otherwise used for deltas, except Z min)
+ Platform& p = reprap.GetPlatform();
+ p.SetAxisMinimum(X_AXIS, -printRadius, false);
+ p.SetAxisMinimum(Y_AXIS, -printRadius, false);
+ p.SetAxisMaximum(X_AXIS, printRadius, false);
+ p.SetAxisMaximum(Y_AXIS, printRadius, false);
seen = true;
}
if (gb.Seen('X'))
@@ -609,15 +615,16 @@ bool LinearDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
}
if (gb.Seen('Z'))
{
- // Y tower position correction
+ // Z tower position correction
angleCorrections[DELTA_C_AXIS] = gb.GetFValue();
seen = true;
}
- // The homed height must be done last, because it gets recalculated when some of the other factors are changed
if (gb.Seen('H'))
{
homedHeight = gb.GetFValue();
+ // Set the Z axis maximum so that DWC reports it correctly (it is not otherwise used for deltas)
+ reprap.GetPlatform().SetAxisMaximum(Z_AXIS, homedHeight, false);
seen = true;
}
diff --git a/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp b/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp
index 5b325645..2ecd0af3 100644
--- a/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp
+++ b/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp
@@ -938,7 +938,6 @@ void check_DHCP_leasedIP(void)
// IP conflict detection : ARP request - ARP reply
// Broadcasting ARP Request for check the IP conflict using UDP sendto() function
- // TODO the following takes 620ms to time out - hanging for this long isn't very nice
sendto(DHCP_SOCKET, (const uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
// RCR value restore
diff --git a/src/Pins.h b/src/Pins.h
index 0b49ca74..ebe82597 100644
--- a/src/Pins.h
+++ b/src/Pins.h
@@ -44,4 +44,8 @@
# define SUPPORT_12864_LCD 0
#endif
+#ifndef USE_CACHE
+# define USE_CACHE 0
+#endif
+
#endif // PINS_H__
diff --git a/src/Platform.cpp b/src/Platform.cpp
index aee8b7c6..43dcb2c2 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -66,7 +66,7 @@ extern "C" char *sbrk(int i);
# error Missing feature definition
#endif
-#if SAM4E && USE_CACHE
+#if USE_CACHE
#include "sam/drivers/cmcc/cmcc.h"
@@ -114,7 +114,7 @@ const uint32_t fanMaxInterruptCount = 32; // number of fan interrupts that we
static volatile uint32_t fanLastResetTime = 0; // time (microseconds) at which we last reset the interrupt count, accessed inside and outside ISR
static volatile uint32_t fanInterval = 0; // written by ISR, read outside the ISR
-const float minStepPulseTiming = 0.2; // we assume that we always generate step high and low times at least this wide without special action
+const float MinStepPulseTiming = 0.2; // we assume that we always generate step high and low times at least this wide without special action
const LogicalPin Heater0LogicalPin = 0;
const LogicalPin Fan0LogicalPin = 20;
@@ -197,7 +197,7 @@ void setup()
#endif
RSTC->RSTC_MR = RSTC_MR_KEY_PASSWD | RSTC_MR_URSTEN; // ignore any signal on the NRST pin for now so that the reset reason will show as Software
-#if SAM4E && USE_CACHE
+#if USE_CACHE
// Enable the cache
struct cmcc_config g_cmcc_cfg;
cmcc_get_config_defaults(&g_cmcc_cfg);
@@ -518,8 +518,11 @@ void Platform::Init()
#endif
}
- slowDriverStepPulseClocks = 0; // no extended driver timing configured yet
- slowDrivers = 0; // assume no drivers need extended step pulse timing
+ for (uint32_t& entry : slowDriverStepTimingClocks)
+ {
+ entry = 0; // reset all to zero as we have no known slow drivers yet
+ }
+ slowDriversBitmap = 0; // assume no drivers need extended step pulse timing
for (size_t extr = 0; extr < MaxExtruders; ++extr)
{
@@ -2110,7 +2113,7 @@ void Platform::PrintUniqueId(MessageType mtype)
// Return diagnostic information
void Platform::Diagnostics(MessageType mtype)
{
-#if SAM4E && USE_CACHE
+#if USE_CACHE
// Get the cache statistics before we start messing around with the cache
const uint32_t cacheCount = cmcc_get_monitor_cnt(CMCC);
#endif
@@ -2308,8 +2311,7 @@ void Platform::Diagnostics(MessageType mtype)
Message(mtype, "not set\n");
}
-#if SAM4E && USE_CACHE
- // Get the cache statistics before we start messing around with the cache
+#if USE_CACHE
MessageF(mtype, "Cache data hit count %" PRIu32 "\n", cacheCount);
#endif
@@ -2491,7 +2493,8 @@ bool Platform::DiagnosticTest(GCodeBuffer& gb, const StringRef& reply, int d)
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
+ __DMB(); // make sure that instruction completes, don't allow prefetch
+ (void)*(reinterpret_cast<const volatile char*>(dummy) + 1);
break;
case (int)DiagnosticTestType::BusFault:
@@ -2502,9 +2505,9 @@ bool Platform::DiagnosticTest(GCodeBuffer& gb, const StringRef& reply, int d)
// I guess this can wait until we have the RTOS working though.
Message(WarningMessage, "There is no abort area on the SAME70");
#elif SAM4E || SAM4S
- (void)RepRap::ReadDword(reinterpret_cast<const char*>(0x20800000));
+ (void)*(reinterpret_cast<const volatile char*>(0x20800000));
#elif SAM3XA
- (void)RepRap::ReadDword(reinterpret_cast<const char*>(0x20200000));
+ (void)*(reinterpret_cast<const volatile char*>(0x20200000));
#else
# error
#endif
@@ -2846,6 +2849,11 @@ bool Platform::WriteAxisLimits(FileStore *f, AxesBitmap axesProbed, const float
// If drive >= DRIVES then we are setting an individual motor direction
void Platform::SetDirection(size_t drive, bool direction)
{
+ const bool isSlowDriver = (GetDriversBitmap(drive) & GetSlowDriversBitmap()) != 0;
+ if (isSlowDriver)
+ {
+ while (GetInterruptClocks() - DDA::lastStepLowTime < GetSlowDriverDirHoldClocks()) { }
+ }
const size_t numAxes = reprap.GetGCodes().GetTotalAxes();
if (drive < numAxes)
{
@@ -2862,6 +2870,10 @@ void Platform::SetDirection(size_t drive, bool direction)
{
SetDriverDirection(drive - DRIVES, direction);
}
+ if (isSlowDriver)
+ {
+ DDA::lastDirChangeTime = GetInterruptClocks();
+ }
}
// Enable a driver. Must not be called from an ISR, or with interrupts disabled.
@@ -3248,28 +3260,41 @@ void Platform::SetExtruderDriver(size_t extruder, uint8_t driver)
driveDriverBits[extruder + reprap.GetGCodes().GetTotalAxes()] = CalcDriverBitmap(driver);
}
-void Platform::SetDriverStepTiming(size_t driver, float microseconds)
+void Platform::SetDriverStepTiming(size_t driver, const float microseconds[4])
{
- if (microseconds < minStepPulseTiming)
+ const uint32_t bitmap = CalcDriverBitmap(driver);
+ slowDriversBitmap &= ~bitmap; // start by assuming this drive does not need extended timing
+ if (slowDriversBitmap == 0)
{
- slowDrivers &= ~CalcDriverBitmap(driver); // this drive does not need extended timing
+ for (uint32_t& entry : slowDriverStepTimingClocks)
+ {
+ entry = 0; // reset all to zero if we have no known slow drivers
+ }
}
- else
+
+ for (size_t i = 0; i < ARRAY_SIZE(slowDriverStepTimingClocks); ++i)
{
- const uint32_t clocks = (uint32_t)(((float)DDA::stepClockRate * microseconds * 0.000001) + 0.99); // convert microseconds to step clocks, rounding up
- if (clocks > slowDriverStepPulseClocks)
+ if (microseconds[i] > MinStepPulseTiming)
{
- slowDriverStepPulseClocks = clocks;
+ slowDriversBitmap |= CalcDriverBitmap(driver); // this drive does need extended timing
+ const uint32_t clocks = (uint32_t)(((float)DDA::stepClockRate * microseconds[i] * 0.000001) + 0.99); // convert microseconds to step clocks, rounding up
+ if (clocks > slowDriverStepTimingClocks[i])
+ {
+ slowDriverStepTimingClocks[i] = clocks;
+ }
}
- slowDrivers |= CalcDriverBitmap(driver); // this drive does need extended timing
}
}
-float Platform::GetDriverStepTiming(size_t driver) const
+void Platform::GetDriverStepTiming(size_t driver, float microseconds[4]) const
{
- return ((slowDrivers & CalcDriverBitmap(driver)) != 0)
- ? (float)slowDriverStepPulseClocks * 1000000.0/(float)DDA::stepClockRate
- : 0.0;
+ const bool isSlowDriver = ((slowDriversBitmap & CalcDriverBitmap(driver)) != 0);
+ for (size_t i = 0; i < 4; ++i)
+ {
+ microseconds[i] = (isSlowDriver)
+ ? (float)slowDriverStepTimingClocks[i] * 1000000.0/(float)DDA::stepClockRate
+ : 0.0;
+ }
}
// Set or report the parameters for the specified fan
@@ -3292,7 +3317,7 @@ bool Platform::ConfigureFan(unsigned int mcode, int fanNum, GCodeBuffer& gb, con
// Get current cooling fan speed on a scale between 0 and 1
float Platform::GetFanValue(size_t fan) const
{
- return (fan < NUM_FANS) ? fans[fan].GetValue() : -1;
+ return (fan < NUM_FANS) ? fans[fan].GetConfiguredPwm() : -1;
}
// This is a bit of a compromise - old RepRaps used fan speeds in the range
@@ -3304,7 +3329,7 @@ void Platform::SetFanValue(size_t fan, float speed)
{
if (fan < NUM_FANS)
{
- fans[fan].SetValue(speed);
+ fans[fan].SetPwm(speed);
}
}
@@ -3354,7 +3379,7 @@ void Platform::InitFans()
{
#if defined(DUET_06_085)
// Fan 1 on the Duet 0.8.5 shares its control pin with heater 6. Set it full on to make sure the heater (if present) is off.
- fans[1].SetValue(1.0); // set it full on
+ fans[1].SetPwm(1.0); // set it full on
#else
// Set fan 1 to be thermostatic by default, monitoring all heaters except the default bed and chamber heaters
Fan::HeatersMonitoredBitmap bedAndChamberHeaterMask = 0;
@@ -3373,7 +3398,7 @@ void Platform::InitFans()
}
}
fans[1].SetHeatersMonitored(LowestNBits<Fan::HeatersMonitoredBitmap>(Heaters) & ~bedAndChamberHeaterMask);
- fans[1].SetValue(1.0); // set it full on
+ fans[1].SetPwm(1.0); // set it full on
#endif
}
diff --git a/src/Platform.h b/src/Platform.h
index 5977b2fa..253b66ec 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -406,8 +406,8 @@ public:
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;
- void SetDriverStepTiming(size_t driver, float microseconds);
- float GetDriverStepTiming(size_t driver) const;
+ void SetDriverStepTiming(size_t driver, const float microseconds[4]);
+ void GetDriverStepTiming(size_t driver, float microseconds[4]) const;
float DriveStepsPerUnit(size_t drive) const;
const float *GetDriveStepsPerUnit() const
{ return driveStepsPerUnit; }
@@ -455,8 +455,11 @@ public:
{ return driveDriverBits[drive]; }
static void StepDriversLow(); // set all step pins low
static void StepDriversHigh(uint32_t driverMap); // set the specified step pins high
- uint32_t GetSlowDrivers() const { return slowDrivers; }
- uint32_t GetSlowDriverClocks() const { return slowDriverStepPulseClocks; }
+ uint32_t GetSlowDriversBitmap() const { return slowDriversBitmap; }
+ uint32_t GetSlowDriverStepHighClocks() const { return slowDriverStepTimingClocks[0]; }
+ uint32_t GetSlowDriverStepLowClocks() const { return slowDriverStepTimingClocks[1]; }
+ uint32_t GetSlowDriverDirSetupClocks() const { return slowDriverStepTimingClocks[2]; }
+ uint32_t GetSlowDriverDirHoldClocks() const { return slowDriverStepTimingClocks[3]; }
#if SUPPORT_NONLINEAR_EXTRUSION
bool GetExtrusionCoefficients(size_t extruder, float& a, float& b, float& limit) const;
@@ -739,8 +742,8 @@ private:
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
- uint32_t slowDriverStepPulseClocks; // minimum high and low step pulse widths, in processor clocks
- uint32_t slowDrivers; // bitmap of driver port bits that need extended step pulse timing
+ uint32_t slowDriverStepTimingClocks[4]; // minimum step high, step low, dir setup and dir hold timing for slow drivers
+ uint32_t slowDriversBitmap; // bitmap of driver port bits that need extended step pulse timing
float idleCurrentFactor;
#if HAS_SMART_DRIVERS
@@ -1131,7 +1134,7 @@ inline float Platform::GetPressureAdvance(size_t extruder) const
return rslt;
}
-// Function GetInterruptClocks() is quite long for these processors, so it is moved to Platform.cpp and no longer inlined
+// Function GetInterruptClocksInterruptsDisabled() is quite long for these processors, so it is moved to Platform.cpp and no longer inlined
#else // TCs are 32-bit
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 5a486c2c..6d7e8008 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -607,6 +607,32 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
// Coordinates
const size_t numVisibleAxes = gCodes->GetVisibleAxes();
+ // Homed axes
+ response->cat("\"axesHomed\":");
+ ch = '[';
+ for (size_t axis = 0; axis < numVisibleAxes; ++axis)
+ {
+ response->catf("%c%d", ch, (gCodes->GetAxisIsHomed(axis)) ? 1 : 0);
+ ch = ',';
+ }
+
+ // XYZ positions
+ // Coordinates may be NaNs or infinities, for example when delta or SCARA homing fails. We must replace any NaNs or infinities to avoid JSON parsing errors.
+ // Ideally we would report "unknown" or similar for axis positions that are not known because we haven't homed them, but that requires changes to both DWC and PanelDue.
+ // So we report 9999.9 instead.
+
+ // First the user coordinates
+ response->cat("],\"xyz\":");
+ const float * const userPos = gCodes->GetUserPosition();
+ ch = '[';
+ for (size_t axis = 0; axis < numVisibleAxes; axis++)
+ {
+ const float coord = userPos[axis];
+ response->catf("%c%.3f", ch, (double)((std::isnan(coord) || std::isinf(coord)) ? 9999.9 : coord));
+ ch = ',';
+ }
+
+ // Now the machine coordinates and the extruder coordinates
{
float liveCoordinates[DRIVES];
#if SUPPORT_ROLAND
@@ -620,47 +646,27 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
move->LiveCoordinates(liveCoordinates, GetCurrentXAxes(), GetCurrentYAxes());
}
- if (currentTool != nullptr)
- {
- for (size_t i = 0; i < numVisibleAxes; ++i)
- {
- liveCoordinates[i] += currentTool->GetOffset(i);
- }
- }
-
- // Homed axes
- response->cat("\"axesHomed\":");
+ // Machine coordinates
+ response->catf("],\"machine\":"); // announce the machine position
ch = '[';
- for (size_t axis = 0; axis < numVisibleAxes; ++axis)
+ for (size_t drive = 0; drive < numVisibleAxes; drive++)
{
- response->catf("%c%d", ch, (gCodes->GetAxisIsHomed(axis)) ? 1 : 0);
+ response->catf("%c%.3f", ch, (double)liveCoordinates[drive]);
ch = ',';
}
// Actual and theoretical extruder positions since power up, last G92 or last M23
- response->catf("],\"extr\":"); // announce actual extruder positions
+ response->catf("],\"extr\":"); // announce actual extruder positions
ch = '[';
for (size_t extruder = 0; extruder < GetExtrudersInUse(); extruder++)
{
response->catf("%c%.1f", ch, (double)liveCoordinates[gCodes->GetTotalAxes() + extruder]);
ch = ',';
}
- if (ch == '[')
+ if (ch == '[') // we may have no extruders
{
response->cat(ch);
}
-
- // XYZ positions
- // TODO ideally we would report "unknown" or similar for axis positions that are not known because we haven't homed them, but that requires changes to both DWC and PanelDue.
- response->cat("],\"xyz\":");
- ch = '[';
- for (size_t axis = 0; axis < numVisibleAxes; axis++)
- {
- // 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)) ? 9999.9 : coord));
- ch = ',';
- }
}
// Current tool number
@@ -1341,19 +1347,26 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
response->cat("]");
// Send XYZ positions
- const size_t numAxes = gCodes->GetVisibleAxes();
- float liveCoordinates[DRIVES];
- move->LiveCoordinates(liveCoordinates, GetCurrentXAxes(), GetCurrentYAxes());
- if (currentTool != nullptr)
+ const size_t numVisibleAxes = gCodes->GetVisibleAxes();
+
+ // First the user coordinates
+ response->catf(",\"pos\":"); // announce the user position
+ const float * const userPos = gCodes->GetUserPosition();
+ ch = '[';
+ for (size_t axis = 0; axis < numVisibleAxes; axis++)
{
- for (size_t i = 0; i < numAxes; ++i)
- {
- liveCoordinates[i] += currentTool->GetOffset(i);
- }
+ // 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 = userPos[axis];
+ response->catf("%c%.3f", ch, (double)((std::isnan(coord) || std::isinf(coord)) ? 9999.9 : coord));
+ ch = ',';
}
- response->catf(",\"pos\":"); // announce the XYZ position
+
+ // Now the machine coordinates
+ float liveCoordinates[DRIVES];
+ move->LiveCoordinates(liveCoordinates, GetCurrentXAxes(), GetCurrentYAxes());
+ response->catf("],\"machine\":"); // announce the machine position
ch = '[';
- for (size_t drive = 0; drive < numAxes; drive++)
+ for (size_t drive = 0; drive < numVisibleAxes; drive++)
{
response->catf("%c%.3f", ch, (double)liveCoordinates[drive]);
ch = ',';
@@ -1406,7 +1419,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
// Send the home state. To keep the messages short, we send 1 for homed and 0 for not homed, instead of true and false.
response->cat(",\"homed\":");
ch = '[';
- for (size_t axis = 0; axis < numAxes; ++axis)
+ for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
response->catf("%c%d", ch, (gCodes->GetAxisIsHomed(axis)) ? 1 : 0);
ch = ',';
@@ -1459,7 +1472,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
// Add the static fields
response->catf(",\"geometry\":\"%s\",\"axes\":%u,\"axisNames\":\"%s\",\"volumes\":%u,\"numTools\":%u,\"myName\":",
- move->GetGeometryString(), numAxes, gCodes->GetAxisLetters(), NumSdCards, GetNumberOfContiguousTools());
+ move->GetGeometryString(), numVisibleAxes, gCodes->GetAxisLetters(), NumSdCards, GetNumberOfContiguousTools());
response->EncodeString(myName.c_str(), myName.MaxLength(), false);
response->cat(",\"firmwareName\":");
response->EncodeString(FIRMWARE_NAME, strlen(FIRMWARE_NAME), false);
@@ -1862,12 +1875,6 @@ bool RepRap::WriteToolParameters(FileStore *f) const
return a/b;
}
-// Helper function for diagnostic tests in Platform.cpp, to cause a deliberate unaligned memory read
-/*static*/ uint32_t RepRap::ReadDword(const char* p)
-{
- return *reinterpret_cast<const uint32_t*>(p);
-}
-
// Report an internal error
void RepRap::ReportInternalError(const char *file, const char *func, int line) const
{
diff --git a/src/RepRap.h b/src/RepRap.h
index 0a8daa2f..145d23e5 100644
--- a/src/RepRap.h
+++ b/src/RepRap.h
@@ -114,7 +114,6 @@ public:
void ReportInternalError(const char *file, const char *func, int line) const; // Report an internal error
static uint32_t DoDivide(uint32_t a, uint32_t b); // helper function for diagnostic tests
- static uint32_t ReadDword(const char* p); // helper function for diagnostic tests
private:
static void EncodeString(StringRef& response, const char* src, size_t spaceToLeave, bool allowControlChars = false, char prefix = 0);
diff --git a/src/Version.h b/src/Version.h
index d90862b8..13abf823 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -9,11 +9,11 @@
#define SRC_VERSION_H_
#ifndef VERSION
-# define VERSION "1.21RC4"
+# define VERSION "1.21RC5"
#endif
#ifndef DATE
-# define DATE "2018-03-11 build 1"
+# define DATE "2018-03-16 build 1"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"