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

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2022-07-13 11:15:50 +0300
committerDavid Crocker <dcrocker@eschertech.com>2022-07-13 11:15:50 +0300
commit15e3851a9a308e4835312d0e7d241b28399197e1 (patch)
tree47d8f71de0dd6cf7d0be1aa5d07a84856a1f2f3f
parentc69e90b589298f13aa7b7064749a6be8f5fc962d (diff)
parent4722b3af90f5c29fba30a493d84aadbca735c5b9 (diff)
Merge branch '3.4-dev' into 3.4-spi-tft
-rw-r--r--src/CAN/CanInterface.cpp114
-rw-r--r--src/CAN/CanInterface.h3
-rw-r--r--src/CAN/CanMessageGenericConstructor.cpp13
-rw-r--r--src/CAN/CanMessageGenericConstructor.h1
-rw-r--r--src/CAN/CommandProcessor.cpp2
-rw-r--r--src/Config/Configuration.h3
-rw-r--r--src/Config/Pins_Duet3_MB6HC.h2
-rw-r--r--src/Config/Pins_Duet3_MB6XD.h1
-rw-r--r--src/FilamentMonitors/LaserFilamentMonitor.cpp2
-rw-r--r--src/FilamentMonitors/RotatingMagnetFilamentMonitor.cpp2
-rw-r--r--src/GCodes/GCodeBuffer/BinaryParser.cpp8
-rw-r--r--src/GCodes/GCodeBuffer/ExpressionParser.cpp284
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.cpp2
-rw-r--r--src/GCodes/GCodes.cpp2
-rw-r--r--src/GCodes/GCodes2.cpp2
-rw-r--r--src/ObjectModel/ObjectModel.cpp28
-rw-r--r--src/ObjectModel/ObjectModel.h31
-rw-r--r--src/Platform/Platform.cpp73
-rw-r--r--src/Platform/Platform.h8
-rw-r--r--src/RepRapFirmware.h6
20 files changed, 312 insertions, 275 deletions
diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp
index a44d757d..4c3a6739 100644
--- a/src/CAN/CanInterface.cpp
+++ b/src/CAN/CanInterface.cpp
@@ -99,6 +99,7 @@ static uint8_t currentTimeSyncMarker = 0xFF;
#if SUPPORT_REMOTE_COMMANDS
static bool inExpansionMode = false;
+static bool inTestMode = false;
static bool mainBoardAcknowledgedAnnounce = false;
#endif
@@ -311,6 +312,11 @@ bool CanInterface::InExpansionMode() noexcept
return inExpansionMode;
}
+bool CanInterface::InTestMode() noexcept
+{
+ return inTestMode;
+}
+
static void ReInit() noexcept
{
can0dev->Disable();
@@ -318,12 +324,13 @@ static void ReInit() noexcept
can0dev->Enable();
}
-void CanInterface::SwitchToExpansionMode(CanAddress addr) noexcept
+void CanInterface::SwitchToExpansionMode(CanAddress addr, bool useTestMode) noexcept
{
TaskCriticalSectionLocker lock;
myAddress = addr;
inExpansionMode = true;
+ inTestMode = useTestMode;
reprap.GetGCodes().SwitchToExpansionMode();
ReInit(); // reset the CAN filters to account for our new CAN address
}
@@ -482,71 +489,76 @@ extern "C" [[noreturn]] void CanClockLoop(void *) noexcept
for (;;)
{
-#if SUPPORT_REMOTE_COMMANDS
- if (!inExpansionMode)
-#endif
- {
- CanMessageTimeSync * const msg = buf.SetupBroadcastMessage<CanMessageTimeSync>(CanInterface::GetCanAddress());
- msg->lastTimeSent = lastTimeSent;
- msg->lastTimeAcknowledgeDelay = 0; // assume we don't have the transmit delay available
+ CanMessageTimeSync * const msg = buf.SetupBroadcastMessage<CanMessageTimeSync>(CanInterface::GetCanAddress());
+ msg->lastTimeSent = lastTimeSent;
+ msg->lastTimeAcknowledgeDelay = 0; // assume we don't have the transmit delay available
- currentTimeSyncMarker = ((currentTimeSyncMarker + 1) & 0x0F) | 0xA0;
- buf.marker = currentTimeSyncMarker;
- buf.reportInFifo = 1;
+ currentTimeSyncMarker = ((currentTimeSyncMarker + 1) & 0x0F) | 0xA0;
+ buf.marker = currentTimeSyncMarker;
+ buf.reportInFifo = 1;
- if (gotTimeSyncTxTimeStamp)
- {
+ if (gotTimeSyncTxTimeStamp)
+ {
# if SAME70
- // On the SAME70 the step clock is also the external time stamp counter
- const uint32_t timeSyncTxDelay = (timeSyncTxTimeStamp - (uint16_t)lastTimeSent) & 0xFFFF;
+ // On the SAME70 the step clock is also the external time stamp counter
+ const uint32_t timeSyncTxDelay = (timeSyncTxTimeStamp - (uint16_t)lastTimeSent) & 0xFFFF;
# else
- // On the SAME5x the time stamp counter counts CAN bit times divided by 64
- const uint32_t timeSyncTxDelay = (((timeSyncTxTimeStamp - lastTimeSyncTxPreparedStamp) & 0xFFFF) * CanInterface::GetTimeStampPeriod()) >> 6;
+ // On the SAME5x the time stamp counter counts CAN bit times divided by 64
+ const uint32_t timeSyncTxDelay = (((timeSyncTxTimeStamp - lastTimeSyncTxPreparedStamp) & 0xFFFF) * CanInterface::GetTimeStampPeriod()) >> 6;
# endif
- if (timeSyncTxDelay > peakTimeSyncTxDelay)
- {
- peakTimeSyncTxDelay = timeSyncTxDelay;
- }
-
- // Occasionally on the SAME70 we get very large delays reported. These delays are not genuine.
- if (timeSyncTxDelay < MaxTimeSyncDelay)
- {
- msg->lastTimeAcknowledgeDelay = timeSyncTxDelay;
- }
- gotTimeSyncTxTimeStamp = false;
- }
-
- msg->isPrinting = reprap.GetGCodes().IsReallyPrinting();
-
- // Send the real time just once a second
- const uint32_t realTime = (uint32_t)reprap.GetPlatform().GetDateTime();
- if (realTime != lastRealTimeSent)
+ if (timeSyncTxDelay > peakTimeSyncTxDelay)
{
- msg->realTime = realTime;
- lastRealTimeSent = realTime;
+ peakTimeSyncTxDelay = timeSyncTxDelay;
}
- else
+
+ // Occasionally on the SAME70 we get very large delays reported. These delays are not genuine.
+ if (timeSyncTxDelay < MaxTimeSyncDelay)
{
- buf.dataLength = CanMessageTimeSync::SizeWithoutRealTime; // send a short message to save CAN bandwidth
+ msg->lastTimeAcknowledgeDelay = timeSyncTxDelay;
}
+ gotTimeSyncTxTimeStamp = false;
+ }
+
+ msg->isPrinting = reprap.GetGCodes().IsReallyPrinting();
+
+ // Send the real time just once a second
+ const uint32_t realTime = (uint32_t)reprap.GetPlatform().GetDateTime();
+ if (realTime != lastRealTimeSent)
+ {
+ msg->realTime = realTime;
+ lastRealTimeSent = realTime;
+ }
+ else
+ {
+ buf.dataLength = CanMessageTimeSync::SizeWithoutRealTime; // send a short message to save CAN bandwidth
+ }
#if SAME70
- lastTimeSent = StepTimer::GetTimerTicks();
+ lastTimeSent = StepTimer::GetTimerTicks();
#else
- {
- AtomicCriticalSectionLocker lock;
- lastTimeSent = StepTimer::GetTimerTicks();
- lastTimeSyncTxPreparedStamp = CanInterface::GetTimeStampCounter();
- }
-#endif
- msg->timeSent = lastTimeSent;
- SendCanMessage(TxBufferIndexTimeSync, 0, &buf);
- ++timeSyncMessagesSent;
+ {
+ AtomicCriticalSectionLocker lock;
+ lastTimeSent = StepTimer::GetTimerTicks();
+ lastTimeSyncTxPreparedStamp = CanInterface::GetTimeStampCounter();
}
+#endif
+ msg->timeSent = lastTimeSent;
+ SendCanMessage(TxBufferIndexTimeSync, 0, &buf);
+ ++timeSyncMessagesSent;
+
+ // Blink the LED at about 2Hz. Duet 3 expansion boards will blink in sync when they have established clock sync with us.
+ digitalWrite(DiagPin, XNor(DiagOnPolarity, lastTimeSent & (1u << 19)) != 0);
// Delay until it is time again
vTaskDelayUntil(&lastWakeTime, CanClockIntervalMillis);
+#if SUPPORT_REMOTE_COMMANDS
+ if (inExpansionMode)
+ {
+ vTaskDelete(nullptr); // once in expansion mode we can't revert to main board mode, so we don't need this task any more
+ }
+#endif
+
// Check that the message was sent and get the time stamp
if (can0dev->IsSpaceAvailable((CanDevice::TxBufferNumber)TxBufferIndexTimeSync, 0)) // if the buffer is free already then the message was sent
{
@@ -555,8 +567,8 @@ extern "C" [[noreturn]] void CanClockLoop(void *) noexcept
else
{
(void)can0dev->IsSpaceAvailable((CanDevice::TxBufferNumber)TxBufferIndexTimeSync, MaxTimeSyncSendWait); // free the buffer
- can0dev->PollTxEventFifo(TxCallback); // empty the fifo
- gotTimeSyncTxTimeStamp = false; // ignore any values read from it
+ can0dev->PollTxEventFifo(TxCallback); // empty the fifo
+ gotTimeSyncTxTimeStamp = false; // ignore any values read from it
}
}
}
diff --git a/src/CAN/CanInterface.h b/src/CAN/CanInterface.h
index a1c320ac..ef322205 100644
--- a/src/CAN/CanInterface.h
+++ b/src/CAN/CanInterface.h
@@ -34,7 +34,8 @@ namespace CanInterface
#if SUPPORT_REMOTE_COMMANDS
bool InExpansionMode() noexcept;
- void SwitchToExpansionMode(CanAddress addr) noexcept;
+ bool InTestMode() noexcept;
+ void SwitchToExpansionMode(CanAddress addr, bool useTestMode) noexcept;
void SendAnnounce(CanMessageBuffer *buf) noexcept;
void RaiseEvent(EventType type, uint16_t param, uint8_t device, const char *format, va_list vargs) noexcept;
diff --git a/src/CAN/CanMessageGenericConstructor.cpp b/src/CAN/CanMessageGenericConstructor.cpp
index ef61896e..a62f01bd 100644
--- a/src/CAN/CanMessageGenericConstructor.cpp
+++ b/src/CAN/CanMessageGenericConstructor.cpp
@@ -329,6 +329,19 @@ void CanMessageGenericConstructor::AddDriverIdParam(char c, DriverId did) THROWS
InsertValue(&did.localDriver, sz, pos);
}
+void CanMessageGenericConstructor::AddFloatArrayParam(char c, const float *v, size_t numV) THROWS(GCodeException)
+{
+ ParamDescriptor::ParamType t;
+ size_t sz;
+ const unsigned int pos = FindInsertPoint(c, t, sz);
+ if (t != ParamDescriptor::float_array || numV != sz)
+ {
+ throw ConstructParseException("fval array wrong parameter type or length");
+ }
+ InsertValue(&numV, sizeof(uint8_t), pos);
+ InsertValue(v, numV * sizeof(float), pos + sizeof(uint8_t));
+}
+
GCodeResult CanMessageGenericConstructor::SendAndGetResponse(CanMessageType msgType, CanAddress dest, const StringRef& reply) const noexcept
{
CanMessageBuffer * const buf = CanMessageBuffer::Allocate();
diff --git a/src/CAN/CanMessageGenericConstructor.h b/src/CAN/CanMessageGenericConstructor.h
index d23447aa..d8f80f65 100644
--- a/src/CAN/CanMessageGenericConstructor.h
+++ b/src/CAN/CanMessageGenericConstructor.h
@@ -34,6 +34,7 @@ public:
void AddCharParam(char c, char v) THROWS(GCodeException);
void AddStringParam(char c, const char* v) THROWS(GCodeException);
void AddDriverIdParam(char c, DriverId did) THROWS(GCodeException);
+ void AddFloatArrayParam(char c, const float *v, size_t numV) THROWS(GCodeException);
GCodeResult SendAndGetResponse(CanMessageType msgType, CanAddress dest, const StringRef& reply) const noexcept;
diff --git a/src/CAN/CommandProcessor.cpp b/src/CAN/CommandProcessor.cpp
index 90e04e93..d27fa6aa 100644
--- a/src/CAN/CommandProcessor.cpp
+++ b/src/CAN/CommandProcessor.cpp
@@ -694,7 +694,7 @@ void CommandProcessor::ProcessReceivedMessage(CanMessageBuffer *buf) noexcept
CanInterface::SendResponseNoFree(buf);
delay(25); // allow time for the response to be sent before we re-initialise CAN
- CanInterface::SwitchToExpansionMode(newAddress);
+ CanInterface::SwitchToExpansionMode(newAddress, true);
}
break;
#endif
diff --git a/src/Config/Configuration.h b/src/Config/Configuration.h
index 1d216b43..aa02d818 100644
--- a/src/Config/Configuration.h
+++ b/src/Config/Configuration.h
@@ -154,11 +154,12 @@ constexpr size_t StringLength256 = 256;
constexpr size_t MaxHeaterNameLength = StringLength20; // Maximum number of characters in a heater name
constexpr size_t MaxFanNameLength = StringLength20; // Maximum number of characters in a fan name
-constexpr size_t FormatStringLength = StringLength256;
#ifdef DUET3_ATE
constexpr size_t GCodeReplyLength = StringLength500; // Maximum number of characters in a GCode reply that doesn't use an OutputBuffer (ATE codes can generate long replies)
+constexpr size_t FormatStringLength = StringLength500; // GCode replies are processed by Platform::MessageF which uses an intermediate buffer of this length
#else
constexpr size_t GCodeReplyLength = StringLength256; // Maximum number of characters in a GCode reply that doesn't use an OutputBuffer
+constexpr size_t FormatStringLength = StringLength256;
#endif
constexpr size_t MachineNameLength = StringLength50;
constexpr size_t RepRapPasswordLength = StringLength20;
diff --git a/src/Config/Pins_Duet3_MB6HC.h b/src/Config/Pins_Duet3_MB6HC.h
index c59559ec..5574ff1e 100644
--- a/src/Config/Pins_Duet3_MB6HC.h
+++ b/src/Config/Pins_Duet3_MB6HC.h
@@ -149,6 +149,8 @@ constexpr float V12MonitorVoltageRange = (60.4 + 4.7)/4.7 * 3.3; // voltage di
// Digital pin number to turn the IR LED on (high) or off (low), also controls the DIAG LED
constexpr Pin DiagPin = PortCPin(20);
constexpr bool DiagOnPolarity = true;
+constexpr Pin ActLedPin = NoPin;
+constexpr bool ActOnPolarity = false;
// SD cards
constexpr size_t NumSdCards = 2; // we now allow one SPI-connected SD card to be configured at boot time
diff --git a/src/Config/Pins_Duet3_MB6XD.h b/src/Config/Pins_Duet3_MB6XD.h
index 70ec355d..514cb4ed 100644
--- a/src/Config/Pins_Duet3_MB6XD.h
+++ b/src/Config/Pins_Duet3_MB6XD.h
@@ -132,6 +132,7 @@ constexpr float V12MonitorVoltageRange = (60.4 + 4.7)/4.7 * 3.3; // voltage di
constexpr Pin DiagPin = PortBPin(6); // diag/status LED
constexpr Pin ActLedPin = PortBPin(7); // activityLED
constexpr bool DiagOnPolarity = false;
+constexpr bool ActOnPolarity = false;
// SD cards
constexpr size_t NumSdCards = 2;
diff --git a/src/FilamentMonitors/LaserFilamentMonitor.cpp b/src/FilamentMonitors/LaserFilamentMonitor.cpp
index de9eb207..aa0890fa 100644
--- a/src/FilamentMonitors/LaserFilamentMonitor.cpp
+++ b/src/FilamentMonitors/LaserFilamentMonitor.cpp
@@ -485,7 +485,7 @@ FilamentSensorStatus LaserFilamentMonitor::Clear() noexcept
// Print diagnostic info for this sensor
void LaserFilamentMonitor::Diagnostics(MessageType mtype, unsigned int extruder) noexcept
{
- String<FormatStringLength> buf;
+ String<StringLength256> buf;
buf.printf("Extruder %u: ", extruder);
if (dataReceived)
{
diff --git a/src/FilamentMonitors/RotatingMagnetFilamentMonitor.cpp b/src/FilamentMonitors/RotatingMagnetFilamentMonitor.cpp
index d2e26b45..a6563d67 100644
--- a/src/FilamentMonitors/RotatingMagnetFilamentMonitor.cpp
+++ b/src/FilamentMonitors/RotatingMagnetFilamentMonitor.cpp
@@ -532,7 +532,7 @@ FilamentSensorStatus RotatingMagnetFilamentMonitor::Clear() noexcept
// Print diagnostic info for this sensor
void RotatingMagnetFilamentMonitor::Diagnostics(MessageType mtype, unsigned int extruder) noexcept
{
- String<FormatStringLength> buf;
+ String<StringLength256> buf;
buf.printf("Extruder %u: ", extruder);
if (dataReceived)
{
diff --git a/src/GCodes/GCodeBuffer/BinaryParser.cpp b/src/GCodes/GCodeBuffer/BinaryParser.cpp
index b1e8e4fa..3dcb2650 100644
--- a/src/GCodes/GCodeBuffer/BinaryParser.cpp
+++ b/src/GCodes/GCodeBuffer/BinaryParser.cpp
@@ -841,7 +841,7 @@ void BinaryParser::AddParameters(VariableSet& vs, int codeRunning) noexcept
case DataType::String:
{
StringHandle sh(seenParameterValue, param->intValue);
- ev.Set(sh);
+ ev.SetStringHandle(sh);
}
break;
@@ -855,15 +855,15 @@ void BinaryParser::AddParameters(VariableSet& vs, int codeRunning) noexcept
break;
case DataType::Float:
- ev.Set(param->floatValue);
+ ev.SetFloat(param->floatValue);
break;
case DataType::Int:
- ev.Set(param->intValue);
+ ev.SetInt(param->intValue);
break;
case DataType::UInt:
- ev.Set((int32_t)param->uintValue);
+ ev.SetInt((int32_t)param->uintValue);
break;
default:
diff --git a/src/GCodes/GCodeBuffer/ExpressionParser.cpp b/src/GCodes/GCodeBuffer/ExpressionParser.cpp
index ce5e2fc5..f6b882b6 100644
--- a/src/GCodes/GCodeBuffer/ExpressionParser.cpp
+++ b/src/GCodes/GCodeBuffer/ExpressionParser.cpp
@@ -113,8 +113,7 @@ void ExpressionParser::ParseInternal(ExpressionValue& val, bool evaluate, uint8_
{
case TypeCode::Uint32:
// Convert enumeration to integer
- val.iVal = (int32_t)val.uVal;
- val.SetType(TypeCode::Int32);
+ val.SetInt((int32_t)val.uVal);
break;
case TypeCode::Int32:
@@ -122,8 +121,7 @@ void ExpressionParser::ParseInternal(ExpressionValue& val, bool evaluate, uint8_
break;
case TypeCode::DateTime_tc: // unary + converts a DateTime to a seconds count
- val.iVal = (uint32_t)val.Get56BitValue();
- val.SetType(TypeCode::Int32);
+ val.SetInt((uint32_t)val.Get56BitValue());
break;
default:
@@ -146,11 +144,11 @@ void ExpressionParser::ParseInternal(ExpressionValue& val, bool evaluate, uint8_
ParseInternal(val, evaluate, UnaryPriority);
if (val.GetType() == TypeCode::CString)
{
- val.Set((int32_t)strlen(val.sVal));
+ val.SetInt((int32_t)strlen(val.sVal));
}
else if (val.GetType() == TypeCode::HeapString)
{
- val.Set((int32_t)val.shVal.GetLength());
+ val.SetInt((int32_t)val.shVal.GetLength());
}
else
{
@@ -336,8 +334,7 @@ void ExpressionParser::ParseInternal(ExpressionValue& val, bool evaluate, uint8_
if (val2.GetType() == TypeCode::DateTime_tc)
{
// Difference of two data/times
- val.SetType(TypeCode::Int32);
- val.iVal = (int32_t)(val.Get56BitValue() - val2.Get56BitValue());
+ val.SetInt((int32_t)(val.Get56BitValue() - val2.Get56BitValue()));
}
else if (val2.GetType() == TypeCode::Uint32)
{
@@ -389,133 +386,130 @@ void ExpressionParser::ParseInternal(ExpressionValue& val, bool evaluate, uint8_
case '>':
BalanceTypes(val, val2, evaluate);
- switch (val.GetType())
{
- case TypeCode::Int32:
- val.bVal = (val.iVal > val2.iVal);
- break;
+ bool bResult;
+ switch (val.GetType())
+ {
+ case TypeCode::Int32:
+ bResult = (val.iVal > val2.iVal);
+ break;
- case TypeCode::Float:
- val.bVal = (val.fVal > val2.fVal);
- break;
+ case TypeCode::Float:
+ bResult = (val.fVal > val2.fVal);
+ break;
- case TypeCode::DateTime_tc:
- val.bVal = val.Get56BitValue() > val2.Get56BitValue();
- break;
+ case TypeCode::DateTime_tc:
+ bResult = val.Get56BitValue() > val2.Get56BitValue();
+ break;
- case TypeCode::Bool:
- val.bVal = (val.bVal && !val2.bVal);
- break;
+ case TypeCode::Bool:
+ bResult = (val.bVal && !val2.bVal);
+ break;
- default:
- if (evaluate)
- {
- ThrowParseException("expected numeric or Boolean operands to comparison operator");
+ default:
+ if (evaluate)
+ {
+ ThrowParseException("expected numeric or Boolean operands to comparison operator");
+ }
+ bResult = false;
+ break;
}
- val.bVal = false;
- break;
- }
- val.SetType(TypeCode::Bool);
- if (invert)
- {
- val.bVal = !val.bVal;
+ val.SetBool((invert) ? !bResult : bResult);
}
break;
case '<':
BalanceTypes(val, val2, evaluate);
- switch (val.GetType())
{
- case TypeCode::Int32:
- val.bVal = (val.iVal < val2.iVal);
- break;
-
- case TypeCode::Float:
- val.bVal = (val.fVal < val2.fVal);
- break;
-
- case TypeCode::DateTime_tc:
- val.bVal = val.Get56BitValue() < val2.Get56BitValue();
- break;
-
- case TypeCode::Bool:
- val.bVal = (!val.bVal && val2.bVal);
- break;
-
- default:
- if (evaluate)
- {
- ThrowParseException("expected numeric or Boolean operands to comparison operator");
- }
- val.bVal = false;
- break;
- }
- val.SetType(TypeCode::Bool);
- if (invert)
- {
- val.bVal = !val.bVal;
- }
- break;
-
- case '=':
- // Before balancing, handle comparisons with null
- if (val.GetType() == TypeCode::None)
- {
- val.bVal = (val2.GetType() == TypeCode::None);
- }
- else if (val2.GetType() == TypeCode::None)
- {
- val.bVal = false;
- }
- else
- {
- BalanceTypes(val, val2, evaluate);
+ bool bResult;
switch (val.GetType())
{
- case TypeCode::ObjectModel_tc:
- ThrowParseException("cannot compare objects");
-
case TypeCode::Int32:
- val.bVal = (val.iVal == val2.iVal);
- break;
-
- case TypeCode::Uint32:
- val.bVal = (val.uVal == val2.uVal);
+ bResult = (val.iVal < val2.iVal);
break;
case TypeCode::Float:
- val.bVal = (val.fVal == val2.fVal);
+ bResult = (val.fVal < val2.fVal);
break;
case TypeCode::DateTime_tc:
- val.bVal = val.Get56BitValue() == val2.Get56BitValue();
+ bResult = val.Get56BitValue() < val2.Get56BitValue();
break;
case TypeCode::Bool:
- val.bVal = (val.bVal == val2.bVal);
- break;
-
- case TypeCode::CString:
- val.bVal = (strcmp(val.sVal, (val2.GetType() == TypeCode::HeapString) ? val2.shVal.Get().Ptr() : val2.sVal) == 0);
- break;
-
- case TypeCode::HeapString:
- val.bVal = (strcmp(val.shVal.Get().Ptr(), (val2.GetType() == TypeCode::HeapString) ? val2.shVal.Get().Ptr() : val2.sVal) == 0);
+ bResult = (!val.bVal && val2.bVal);
break;
default:
if (evaluate)
{
- ThrowParseException("unexpected operand type to equality operator");
+ ThrowParseException("expected numeric or Boolean operands to comparison operator");
}
- val.bVal = false;
+ bResult = false;
break;
}
+ val.SetBool((invert) ? !bResult : bResult);
}
- val.SetType(TypeCode::Bool);
- if (invert)
+ break;
+
+ case '=':
{
- val.bVal = !val.bVal;
+ bool bResult;
+ // Before balancing, handle comparisons with null
+ if (val.GetType() == TypeCode::None)
+ {
+ bResult = (val2.GetType() == TypeCode::None);
+ }
+ else if (val2.GetType() == TypeCode::None)
+ {
+ bResult = false;
+ }
+ else
+ {
+ BalanceTypes(val, val2, evaluate);
+ switch (val.GetType())
+ {
+ case TypeCode::ObjectModel_tc:
+ ThrowParseException("cannot compare objects");
+
+ case TypeCode::Int32:
+ bResult = (val.iVal == val2.iVal);
+ break;
+
+ case TypeCode::Uint32:
+ bResult = (val.uVal == val2.uVal);
+ break;
+
+ case TypeCode::Float:
+ bResult = (val.fVal == val2.fVal);
+ break;
+
+ case TypeCode::DateTime_tc:
+ bResult = val.Get56BitValue() == val2.Get56BitValue();
+ break;
+
+ case TypeCode::Bool:
+ bResult = (val.bVal == val2.bVal);
+ break;
+
+ case TypeCode::CString:
+ bResult = (strcmp(val.sVal, (val2.GetType() == TypeCode::HeapString) ? val2.shVal.Get().Ptr() : val2.sVal) == 0);
+ break;
+
+ case TypeCode::HeapString:
+ bResult = (strcmp(val.shVal.Get().Ptr(), (val2.GetType() == TypeCode::HeapString) ? val2.shVal.Get().Ptr() : val2.sVal) == 0);
+ break;
+
+ default:
+ if (evaluate)
+ {
+ ThrowParseException("unexpected operand type to equality operator");
+ }
+ bResult = false;
+ break;
+ }
+ }
+ val.SetBool((invert) ? !bResult : bResult);
}
break;
@@ -536,7 +530,7 @@ void ExpressionParser::ParseInternal(ExpressionValue& val, bool evaluate, uint8_
val.AppendAsString(str.GetRef());
val2.AppendAsString(str.GetRef());
StringHandle sh(str.c_str());
- val.Set(sh);
+ val.SetStringHandle(sh);
}
bool ExpressionParser::ParseBoolean() THROWS(GCodeException)
@@ -673,8 +667,8 @@ void ExpressionParser::BalanceNumericTypes(ExpressionValue& val1, ExpressionValu
{
ThrowParseException("expected numeric operands");
}
- val1.Set((int32_t)0);
- val2.Set((int32_t)0);
+ val1.SetInt(0);
+ val2.SetInt(0);
}
}
@@ -734,34 +728,29 @@ void ExpressionParser::BalanceTypes(ExpressionValue& val1, ExpressionValue& val2
{
ThrowParseException("cannot convert operands to same type");
}
- val1.Set((int32_t)0);
- val2.Set((int32_t)0);
+ val1.SetInt(0);
+ val2.SetInt(0);
}
}
void ExpressionParser::ConvertToFloat(ExpressionValue& val, bool evaluate) const THROWS(GCodeException)
{
+ float fVal;
switch (val.GetType())
{
+ case TypeCode::Float:
+ return; // no conversion needed, leave the precision alone
+
case TypeCode::Uint32:
- val.SetType(TypeCode::Float);
- val.fVal = (float)val.uVal;
- val.param = 1;
+ fVal = (float)val.uVal;
break;
case TypeCode::Uint64:
- val.SetType(TypeCode::Float);
- val.fVal = (float)val.Get56BitValue();
- val.param = 1;
+ fVal = (float)val.Get56BitValue();
break;
case TypeCode::Int32:
- val.fVal = (float)val.iVal;
- val.SetType(TypeCode::Float);
- val.param = 1;
- break;
-
- case TypeCode::Float:
+ fVal = (float)val.iVal;
break;
default:
@@ -769,8 +758,10 @@ void ExpressionParser::ConvertToFloat(ExpressionValue& val, bool evaluate) const
{
ThrowParseException("expected numeric operand");
}
- val.Set(0.0f, 1);
+ fVal = 0.0f;
+ break;
}
+ val.SetFloat(fVal, 1);
}
void ExpressionParser::ConvertToBool(ExpressionValue& val, bool evaluate) const THROWS(GCodeException)
@@ -781,7 +772,7 @@ void ExpressionParser::ConvertToBool(ExpressionValue& val, bool evaluate) const
{
ThrowParseException("expected Boolean operand");
}
- val.Set(false);
+ val.SetBool(false);
}
}
@@ -794,11 +785,11 @@ void ExpressionParser::ConvertToString(ExpressionValue& val, bool evaluate) noex
String<MaxStringExpressionLength> str;
val.AppendAsString(str.GetRef());
StringHandle sh(str.c_str());
- val.Set(sh);
+ val.SetStringHandle(sh);
}
else
{
- val.Set("");
+ val.SetCString("");
}
}
}
@@ -812,9 +803,9 @@ void ExpressionParser::ConvertToDriverId(ExpressionValue& val, bool evaluate) co
case TypeCode::Int32:
#if SUPPORT_CAN_EXPANSION
- val.Set(DriverId(0, val.uVal));
+ val.SetDriverId(DriverId(0, val.uVal));
#else
- val.Set(DriverId(val.uVal));
+ val.SetDriverId(DriverId(val.uVal));
#endif
break;
@@ -825,12 +816,12 @@ void ExpressionParser::ConvertToDriverId(ExpressionValue& val, bool evaluate) co
#if SUPPORT_CAN_EXPANSION
if (ival >= 0 && fabsf(f10val - (float)ival) <= 0.002)
{
- val.Set(DriverId(ival/10, ival % 10));
+ val.SetDriverId(DriverId(ival/10, ival % 10));
}
#else
if (ival >= 0 && ival < 10 && fabsf(f10val - (float)ival) <= 0.002)
{
- val.Set(DriverId(ival % 10));
+ val.SetDriverId(DriverId(ival % 10));
}
#endif
else
@@ -874,11 +865,11 @@ void ExpressionParser::ParseNumber(ExpressionValue& rslt) noexcept
if (conv.FitsInInt32())
{
- rslt.Set(conv.GetInt32());
+ rslt.SetInt(conv.GetInt32());
}
else
{
- rslt.Set(conv.GetFloat(), constrain<unsigned int>(conv.GetDigitsAfterPoint(), 1, MaxFloatDigitsDisplayedAfterPoint));
+ rslt.SetFloat(conv.GetFloat(), constrain<unsigned int>(conv.GetDigitsAfterPoint(), 1, MaxFloatDigitsDisplayedAfterPoint));
}
}
@@ -917,7 +908,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
{
ThrowParseException("expected integer expression");
}
- index.Set((int32_t)0);
+ index.SetInt(0);
}
AdvancePointer(); // skip the ']'
context.ProvideIndex(index.iVal);
@@ -941,19 +932,19 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
switch (whichConstant.RawValue())
{
case NamedConstant::_true:
- rslt.Set(true);
+ rslt.SetBool(true);
return;
case NamedConstant::_false:
- rslt.Set(false);
+ rslt.SetBool(false);
return;
case NamedConstant::_null:
- rslt.Set(nullptr);
+ rslt.SetNull(nullptr);
return;
case NamedConstant::pi:
- rslt.Set(Pi);
+ rslt.SetFloat(Pi);
return;
case NamedConstant::iterations:
@@ -963,7 +954,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
{
ThrowParseException("'iterations' used when not inside a loop");
}
- rslt.Set(v);
+ rslt.SetInt(v);
}
return;
@@ -985,12 +976,12 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
res = 2;
break;
}
- rslt.Set(res);
+ rslt.SetInt(res);
}
return;
case NamedConstant::line:
- rslt.Set((int32_t)gb.GetLineNumber());
+ rslt.SetInt((int32_t)gb.GetLineNumber());
return;
default:
@@ -1043,7 +1034,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
{
ThrowParseException("expected numeric operand");
}
- rslt.Set((int32_t)0);
+ rslt.SetInt(0);
}
break;
@@ -1122,8 +1113,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
case Function::isnan:
ConvertToFloat(rslt, evaluate);
- rslt.SetType(TypeCode::Bool);
- rslt.bVal = (std::isnan(rslt.fVal) != 0);
+ rslt.SetBool(std::isnan(rslt.fVal) != 0);
break;
case Function::floor:
@@ -1132,8 +1122,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
const float f = floorf(rslt.fVal);
if (f <= (float)std::numeric_limits<int32_t>::max() && f >= (float)std::numeric_limits<int32_t>::min())
{
- rslt.SetType(TypeCode::Int32);
- rslt.iVal = (int32_t)f;
+ rslt.SetInt((int32_t)f);
}
else
{
@@ -1237,7 +1226,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
{
ThrowParseException("expected positive integer");
}
- rslt.Set((int32_t)random(limit));
+ rslt.SetInt((int32_t)random(limit));
}
break;
@@ -1270,8 +1259,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
default:
ThrowParseException("can't convert value to DateTime");
}
- rslt.SetType(TypeCode::DateTime_tc);
- rslt.Set56BitValue(val);
+ rslt.SetDateTime(val);
}
break;
@@ -1316,7 +1304,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
// "exists(global)" will anyway because "global" is a root key in the object model. Handle the other two here.
if (applyExists && (strcmp(id.c_str(), "param") == 0 || strcmp(id.c_str(), "var") == 0))
{
- rslt.Set(true);
+ rslt.SetBool(true);
return;
}
@@ -1329,7 +1317,7 @@ void ExpressionParser::ParseIdentifierExpression(ExpressionValue& rslt, bool eva
}
return;
}
- rslt.Set(nullptr);
+ rslt.SetNull(nullptr);
}
// Parse a string to a DateTime
@@ -1349,7 +1337,7 @@ void ExpressionParser::GetVariableValue(ExpressionValue& rslt, const VariableSet
const Variable* var = vars->Lookup(name);
if (wantExists)
{
- rslt.Set(var != nullptr);
+ rslt.SetBool(var != nullptr);
return;
}
@@ -1381,7 +1369,7 @@ void ExpressionParser::ParseQuotedString(ExpressionValue& rslt) THROWS(GCodeExce
if (CurrentCharacter() != c)
{
StringHandle sh(str.c_str());
- rslt.Set(sh);
+ rslt.SetStringHandle(sh);
return;
}
AdvancePointer();
diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp
index a4ea34a4..bd8b2c74 100644
--- a/src/GCodes/GCodeBuffer/StringParser.cpp
+++ b/src/GCodes/GCodeBuffer/StringParser.cpp
@@ -1929,7 +1929,7 @@ void StringParser::AddParameters(VariableSet& vs, int codeRunning) noexcept
catch (const GCodeException&)
{
//TODO can we report the error anywhere?
- ev.Set(nullptr);
+ ev.SetNull(nullptr);
}
char paramName[2] = { letter, 0 };
vs.InsertNewParameter(paramName, ev);
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index bf545cd6..986c3482 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -1197,7 +1197,7 @@ void GCodes::SaveResumeInfo(bool wasPowerFailure) noexcept
}
else
{
- String<FormatStringLength> buf;
+ String<StringLength256> buf;
// Write the header comment
buf.printf("; File \"%s\" resume print after %s", printingFilename, (wasPowerFailure) ? "power failure" : "print paused");
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 09686426..b63bad53 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -4518,7 +4518,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx
case 954: // configure as expansion board
{
CanAddress addr = gb.GetLimitedUIValue('A', 1, CanId::MaxCanAddress + 1);
- CanInterface::SwitchToExpansionMode(addr);
+ CanInterface::SwitchToExpansionMode(addr, false);
}
break;
#endif
diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp
index 5bffcd3c..e7f86716 100644
--- a/src/ObjectModel/ObjectModel.cpp
+++ b/src/ObjectModel/ObjectModel.cpp
@@ -193,6 +193,34 @@ void ExpressionValue::Release() noexcept
}
}
+void ExpressionValue::SetBool(bool b) noexcept
+{
+ Release();
+ type = (uint32_t)TypeCode::Bool;
+ bVal = b;
+}
+
+void ExpressionValue::SetInt(int32_t i) noexcept
+{
+ Release();
+ type = (uint32_t)TypeCode::Int32;
+ iVal = i;
+}
+
+void ExpressionValue::SetFloat(float f, uint32_t digits) noexcept { Release(); type = (uint32_t)TypeCode::Float; fVal = f; param = digits; }
+
+void ExpressionValue::SetDriverId(DriverId did) noexcept
+{
+ Release();
+ type = (uint32_t)TypeCode::DriverId_tc;
+#if SUPPORT_CAN_EXPANSION
+ param = did.boardAddress;
+#else
+ param = 0;
+#endif
+ uVal = did.localDriver;
+}
+
#if SUPPORT_CAN_EXPANSION
// Given that this is a CanExpansionBoardDetails value, extract the part requested according to the parameter and append it to the string
diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h
index a957aff6..3d05ac8c 100644
--- a/src/ObjectModel/ObjectModel.h
+++ b/src/ObjectModel/ObjectModel.h
@@ -153,32 +153,21 @@ struct ExpressionValue
void Release() noexcept; // release any associated storage
TypeCode GetType() const noexcept { return (TypeCode)type; }
- void SetType(TypeCode t) noexcept { type = (uint32_t)t; }
bool IsStringType() const noexcept { return type == (uint32_t)TypeCode::CString || type == (uint32_t)TypeCode::HeapString; }
- void Set(bool b) noexcept { Release(); type = (uint32_t)TypeCode::Bool; bVal = b; }
- void Set(char c) noexcept { Release(); type = (uint32_t)TypeCode::Char; cVal = c; }
- void Set(int32_t i) noexcept { Release(); type = (uint32_t)TypeCode::Int32; iVal = i; }
- void Set(float f) noexcept { Release(); type = (uint32_t)TypeCode::Float; fVal = f; param = MaxFloatDigitsDisplayedAfterPoint; }
- void Set(float f, uint32_t digits) noexcept { Release(); type = (uint32_t)TypeCode::Float; fVal = f; param = digits; }
- void Set(const char *_ecv_array s) noexcept { Release(); type = (uint32_t)TypeCode::CString; sVal = s; }
- void Set(DriverId did) noexcept
- {
- Release();
- type = (uint32_t)TypeCode::DriverId_tc;
-#if SUPPORT_CAN_EXPANSION
- param = did.boardAddress;
-#else
- param = 0;
-#endif
- uVal = did.localDriver;
- }
+ void SetBool(bool b) noexcept;
+ void SetInt(int32_t i) noexcept;
+ void SetFloat(float f, uint32_t digits) noexcept;
+ void SetFloat(float f) noexcept { SetFloat(f, MaxFloatDigitsDisplayedAfterPoint); }
+ void SetCString(const char *_ecv_array s) noexcept { Release(); type = (uint32_t)TypeCode::CString; sVal = s; }
+ void SetDriverId(DriverId did) noexcept;
- void Set(StringHandle sh) noexcept { Release(); type = (uint32_t)TypeCode::HeapString; shVal = sh; }
- void Set(std::nullptr_t dummy) noexcept { Release(); type = (uint32_t)TypeCode::None; }
+ void SetStringHandle(StringHandle sh) noexcept { Release(); type = (uint32_t)TypeCode::HeapString; shVal = sh; }
+ void SetNull(std::nullptr_t dummy) noexcept { Release(); type = (uint32_t)TypeCode::None; }
+ void SetDateTime(time_t t) noexcept { Release(); type = (uint32_t)TypeCode::DateTime_tc; Set56BitValue(t); }
// Store a 56-bit value
- void Set56BitValue(uint64_t v) { Release(); param = (uint32_t)(v >> 32) & 0x00FFFFFFu; uVal = (uint32_t)v; }
+ void Set56BitValue(uint64_t v) { param = (uint32_t)(v >> 32) & 0x00FFFFFFu; uVal = (uint32_t)v; }
// Extract a 56-bit value that we have stored. Used to retrieve date/times and large bitmaps.
uint64_t Get56BitValue() const noexcept { return ((uint64_t)param << 32) | uVal; }
diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp
index 4737d85a..98040d27 100644
--- a/src/Platform/Platform.cpp
+++ b/src/Platform/Platform.cpp
@@ -415,7 +415,7 @@ Platform::Platform() noexcept :
#endif
tickState(0), debugCode(0),
lastDriverPollMillis(0),
-#ifdef DUET3MINI
+#if SUPPORT_CAN_EXPANSION
whenLastCanMessageProcessed(0),
#endif
@@ -647,19 +647,9 @@ void Platform::Init() noexcept
#ifdef DUET3_MB6XD
driverErrPinsActiveLow = (numErrorHighDrivers >= NumDirectDrivers/2); // determine the error signal polarity by assuming most drivers are not in the error state
-
- // Set up the step gate timer
- pmc_enable_periph_clk(STEP_GATE_TC_ID);
- STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CCR = TC_CCR_CLKDIS;
- STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CMR = TC_CMR_BSWTRG_SET // software trigger sets TIOB
- | TC_CMR_BCPC_CLEAR // RC compare clears TIOB
- | TC_CMR_WAVE // waveform mode
- | TC_CMR_WAVSEL_UP // count up
- | TC_CMR_CPCSTOP // counter clock is stopped when counter reaches RC
- | TC_CMR_EEVT_XC0 // set external events from XC0 (this allows TIOB to be an output)
- | TC_CMR_TCCLKS_TIMER_CLOCK2; // divide MCLK (150MHz) by 8 = 18.75MHz
+ pmc_enable_periph_clk(STEP_GATE_TC_ID); // need to do this before we set up the step gate TC
+ UpdateDriverTimings(); // this also initialises the step gate TC
SetPinFunction(StepGatePin, StepGatePinFunction);
- STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CCR = TC_CCR_CLKEN;
#endif
// Set up the axis+extruder arrays
@@ -705,9 +695,7 @@ void Platform::Init() noexcept
#endif
}
-#ifdef DUET3_MB6XD
- UpdateDriverTimings();
-#else
+#ifndef DUET3_MB6XD
for (uint32_t& entry : slowDriverStepTimingClocks)
{
entry = 0; // reset all to zero as we have no known slow drivers yet
@@ -989,8 +977,7 @@ void Platform::Spin() noexcept
return;
}
-#if defined(DUET3) || defined(DUET3MINI) || defined(__LPC17xx__)
-# if SUPPORT_REMOTE_COMMANDS
+#if SUPPORT_REMOTE_COMMANDS
if (CanInterface::InExpansionMode())
{
if (StepTimer::IsSynced())
@@ -1002,21 +989,14 @@ void Platform::Spin() noexcept
digitalWrite(DiagPin, XNor(DiagOnPolarity, StepTimer::GetTimerTicks() & (1u << 17)) != 0);
}
}
- else
-# endif
- {
- // Blink the LED at about 2Hz. Duet 3 expansion boards will blink in sync when they have established clock sync with us.
- digitalWrite(DiagPin, XNor(DiagOnPolarity, StepTimer::GetTimerTicks() & (1u << 19)) != 0);
- }
#endif
-#if defined(DUET3MINI)
+#if SUPPORT_CAN_EXPANSION
// Turn off the ACT LED if it is time to do so
if (millis() - whenLastCanMessageProcessed > ActLedFlashTime)
{
digitalWrite(ActLedPin, !ActOnPolarity);
}
-
#endif
#if HAS_MASS_STORAGE || HAS_SBC_INTERFACE || HAS_EMBEDDED_FILES
@@ -1094,7 +1074,8 @@ void Platform::Spin() noexcept
{
StandardDriverStatus stat =
#if defined(DUET3_MB6XD)
- StandardDriverStatus((HasDriverError(nextDriveToPoll)) ? (uint32_t)1u << StandardDriverStatus::ExternDriverErrorBitPos : 0);
+ // Don't raise driver error events while we are being tested by ATE
+ StandardDriverStatus((!CanInterface::InTestMode() && HasDriverError(nextDriveToPoll)) ? (uint32_t)1u << StandardDriverStatus::ExternDriverErrorBitPos : 0);
#else
SmartDrivers::GetStatus(nextDriveToPoll, true, true);
#endif
@@ -2778,15 +2759,31 @@ void Platform::UpdateDriverTimings() noexcept
}
// Convert the step pulse width to clocks of the step pulse gate timer. First define some constants.
- constexpr uint32_t StepGateTcClockFrequency = (SystemCoreClockFreq/2)/8;
- constexpr float StepGateClocksPerMicrosecond = (float)StepGateTcClockFrequency/1.0e6;
+ constexpr uint32_t StepGateTcBaseClockFrequency = (SystemCoreClockFreq/2)/8; // the step gate T clock frequency when we use a prescaler of 8
+ constexpr float StepGateBaseClocksPerMicrosecond = (float)StepGateTcBaseClockFrequency * 1.0e-6;
+ const float fclocks = min<float>(ceilf(worstTimings[0] * StepGateBaseClocksPerMicrosecond), (float)(4 * 65535)); // the TC is only 16 bits wide, but we increase the prescaler to 32 if necessary
- const float fclocks = ceilf(worstTimings[0] * StepGateClocksPerMicrosecond);
- const uint32_t gateClocks = (uint32_t)fclocks;
- STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_RC = gateClocks;
+ uint32_t iclocks = (uint32_t)fclocks;
+ uint32_t clockPrescaler = TC_CMR_TCCLKS_TIMER_CLOCK2; // divide MCLK (150MHz) by 8 = 18.75MHz
+ if (iclocks > 65535)
+ {
+ clockPrescaler = TC_CMR_TCCLKS_TIMER_CLOCK3; // divide MCLK (150MHz) by 32 = 4.6875MHz
+ iclocks >>= 2;
+ }
+
+ STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CCR = TC_CCR_CLKDIS;
+ STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CMR = TC_CMR_BSWTRG_SET // software trigger sets TIOB
+ | TC_CMR_BCPC_CLEAR // RC compare clears TIOB
+ | TC_CMR_WAVE // waveform mode
+ | TC_CMR_WAVSEL_UP // count up
+ | TC_CMR_CPCSTOP // counter clock is stopped when counter reaches RC
+ | TC_CMR_EEVT_XC0 // set external events from XC0 (this allows TIOB to be an output)
+ | clockPrescaler; // divide MCLK (150MHz) by 8 or 32
+ STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_RC = iclocks;
+ STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CCR = TC_CCR_CLKEN;
// Convert the quantised step pulse width back to microseconds
- const float actualStepPulseMicroseconds = fclocks/StepGateClocksPerMicrosecond;
+ const float actualStepPulseMicroseconds = fclocks/StepGateBaseClocksPerMicrosecond;
// Now convert the other values from microseconds to step clocks
stepPulseMinimumPeriodClocks = MicrosecondsToStepClocks(worstTimings[1] + actualStepPulseMicroseconds);
@@ -2798,8 +2795,12 @@ void Platform::UpdateDriverTimings() noexcept
void Platform::GetActualDriverTimings(float timings[4]) noexcept
{
- constexpr uint32_t StepGateTcClockFrequency = (SystemCoreClockFreq/2)/8;
- constexpr float MicrosecondsPerStepGateClock = 1.0e6/(float)StepGateTcClockFrequency;
+ uint32_t StepGateTcClockFrequency = (SystemCoreClockFreq/2)/8;
+ if ((STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_CMR & TC_CMR_TCCLKS_Msk) == TC_CMR_TCCLKS_TIMER_CLOCK3)
+ {
+ StepGateTcClockFrequency >>= 2;;
+ }
+ const float MicrosecondsPerStepGateClock = 1.0e6/(float)StepGateTcClockFrequency;
constexpr float StepClocksToMicroseconds = 1.0e6/(float)StepClockRate;
timings[0] = (float)STEP_GATE_TC->TC_CHANNEL[STEP_GATE_TC_CHAN].TC_RC * MicrosecondsPerStepGateClock;
timings[1] = stepPulseMinimumPeriodClocks * StepClocksToMicroseconds - timings[0];
@@ -4543,7 +4544,7 @@ GCodeResult Platform::UpdateRemoteStepsPerMmAndMicrostepping(AxesBitmap axesAndE
void Platform::OnProcessingCanMessage() noexcept
{
-#ifdef DUET3MINI // MB6HC doesn't yet have a ACT LED
+#if SUPPORT_CAN_EXPANSION
whenLastCanMessageProcessed = millis();
digitalWrite(ActLedPin, ActOnPolarity); // turn the ACT LED on
#endif
diff --git a/src/Platform/Platform.h b/src/Platform/Platform.h
index 36462474..d8a782c8 100644
--- a/src/Platform/Platform.h
+++ b/src/Platform/Platform.h
@@ -705,12 +705,6 @@ private:
void ReportDrivers(MessageType mt, DriversBitmap& whichDrivers, const char *_ecv_array text, bool& reported) noexcept;
#endif
- // Convert microseconds to step clocks, rounding up to the next step clock
- static constexpr uint32_t MicrosecondsToStepClocks(float us) noexcept
- {
- return (uint32_t)ceilf((float)StepClockRate * 0.000001 * us);
- }
-
#ifdef DUET3_MB6XD
void UpdateDriverTimings() noexcept;
#endif
@@ -918,7 +912,7 @@ private:
// Event handling
uint32_t lastDriverPollMillis; // when we last checked the drivers and voltage monitoring
-#ifdef DUET3MINI
+#if SUPPORT_CAN_EXPANSION
uint32_t whenLastCanMessageProcessed;
#endif
diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h
index 628deac2..233791a6 100644
--- a/src/RepRapFirmware.h
+++ b/src/RepRapFirmware.h
@@ -502,6 +502,12 @@ constexpr uint32_t StepClockRate = SystemCoreClockFreq/128; // Duet 2 and Ma
constexpr uint64_t StepClockRateSquared = (uint64_t)StepClockRate * StepClockRate;
constexpr float StepClocksToMillis = 1000.0/(float)StepClockRate;
+// Convert microseconds to step clocks, rounding up to the next step clock
+static inline constexpr uint32_t MicrosecondsToStepClocks(float us) noexcept
+{
+ return (uint32_t)ceilf((float)StepClockRate * 0.000001 * us);
+}
+
// Functions to convert speeds and accelerations between seconds and step clocks
static inline constexpr float ConvertSpeedFromMmPerSec(float speed) noexcept
{