diff options
Diffstat (limited to 'src/GCodes')
-rw-r--r-- | src/GCodes/GCodeBuffer/GCodeBuffer.cpp | 16 | ||||
-rw-r--r-- | src/GCodes/GCodeBuffer/GCodeBuffer.h | 6 | ||||
-rw-r--r-- | src/GCodes/GCodeBuffer/StringParser.cpp | 22 | ||||
-rw-r--r-- | src/GCodes/GCodes.cpp | 29 | ||||
-rw-r--r-- | src/GCodes/GCodes.h | 2 | ||||
-rw-r--r-- | src/GCodes/GCodes2.cpp | 59 | ||||
-rw-r--r-- | src/GCodes/GCodes3.cpp | 12 | ||||
-rw-r--r-- | src/GCodes/GCodes4.cpp | 15 |
8 files changed, 110 insertions, 51 deletions
diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp index ba67c95b..87c126d6 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.cpp +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.cpp @@ -84,7 +84,7 @@ const char *GCodeBuffer::GetStateText() const noexcept // Create a default GCodeBuffer GCodeBuffer::GCodeBuffer(GCodeChannel::RawType channel, GCodeInput *normalIn, FileGCodeInput *fileIn, MessageType mt, Compatibility::RawType c) noexcept - : codeChannel(channel), normalInput(normalIn), + : codeChannel(channel), normalInput(normalIn), whenReportDueTimerStarted(millis()), #if HAS_MASS_STORAGE fileInput(fileIn), #endif @@ -167,6 +167,20 @@ bool GCodeBuffer::DoDwellTime(uint32_t dwellMillis) noexcept return false; } +// Delay executing this GCodeBuffer for the specified time. Return true when the timer has expired. +bool GCodeBuffer::IsReportDue() noexcept +{ + const uint32_t now = millis(); + + // Are we due? + if (now - whenReportDueTimerStarted >= reportDueInterval) + { + ResetReportDueTimer(); + return true; + } + return false; +} + // Write some debug info void GCodeBuffer::Diagnostics(MessageType mtype) noexcept { diff --git a/src/GCodes/GCodeBuffer/GCodeBuffer.h b/src/GCodes/GCodeBuffer/GCodeBuffer.h index bbd18dae..4b37981a 100644 --- a/src/GCodes/GCodeBuffer/GCodeBuffer.h +++ b/src/GCodes/GCodeBuffer/GCodeBuffer.h @@ -194,6 +194,9 @@ public: void StopTimer() noexcept { timerRunning = false; } bool DoDwellTime(uint32_t dwellMillis) noexcept; // Execute a dwell returning true if it has finished + void ResetReportDueTimer() noexcept { whenReportDueTimerStarted = millis(); }; + bool IsReportDue() noexcept; + void RestartFrom(FilePosition pos) noexcept; #if HAS_MASS_STORAGE @@ -244,6 +247,9 @@ private: bool timerRunning; // True if we are waiting bool motionCommanded; // true if this GCode stream has commanded motion since it last waited for motion to stop + uint32_t whenReportDueTimerStarted; // When the report-due-timer has been started + static constexpr uint32_t reportDueInterval = 1000; // Interval in which we send in ms + #if HAS_LINUX_INTERFACE alignas(4) char buffer[MaxCodeBufferSize]; // must be aligned because we do dword fetches from it #else diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp index d7ee0e7b..9978b658 100644 --- a/src/GCodes/GCodeBuffer/StringParser.cpp +++ b/src/GCodes/GCodeBuffer/StringParser.cpp @@ -749,42 +749,34 @@ void StringParser::DecodeCommand() noexcept } } - // Find where the end of the command is. We assume that a G or M preceded by a space and not inside quotes or { } is the start of a new command. + // Find where the end of the command is. We assume that a G or M not inside quotes or { } is the start of a new command. bool inQuotes = false; - unsigned int braceCount = 0; - bool primed = false; + unsigned int localBraceCount = 0; for (commandEnd = parameterStart; commandEnd < gcodeLineEnd; ++commandEnd) { const char c = gb.buffer[commandEnd]; if (c == '"') { inQuotes = !inQuotes; - primed = false; } else if (!inQuotes) { char c2; if (c == '{') { - ++braceCount; - primed = false; + ++localBraceCount; } - else if (c == '}') + else if (localBraceCount != 0) { - if (braceCount != 0) + if (c == '}') { - --braceCount; + --localBraceCount; } - primed = false; } - else if (primed && ((c2 = toupper(c)) == 'G' || c2 == 'M')) + else if ((c2 = toupper(c)) == 'G' || c2 == 'M') { break; } - else if (braceCount == 0) - { - primed = (c == ' ' || c == '\t'); - } } } } diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 23a8e48b..52682a5a 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -485,6 +485,10 @@ void GCodes::Spin() noexcept { RunStateMachine(gb, reply.GetRef()); // execute the state machine } + if (gb.IsExecuting()) + { + CheckReportDue(gb, reply.GetRef()); + } } #if HAS_LINUX_INTERFACE @@ -1688,7 +1692,7 @@ const char * GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, bool isP } } - if (moveBuffer.moveType == 1) + if (moveBuffer.moveType == 1 || moveBuffer.moveType == 4) { if (!platform.GetEndstops().EnableExtruderEndstops(extrudersMoving)) { @@ -1737,7 +1741,7 @@ bool GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated, const char *& e if (gb.Seen('H') || (machineType != MachineType::laser && gb.Seen('S'))) { const int ival = gb.GetIValue(); - if (ival >= 1 && ival <= 3) + if (ival >= 1 && ival <= 4) { if (!LockMovementAndWaitForStandstill(gb)) { @@ -1892,6 +1896,7 @@ bool GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated, const char *& e axesToSenseLength = axesMentioned & AxesBitmap::MakeLowestNBits(numTotalAxes); // no break case 1: + case 4: if (!platform.GetEndstops().EnableAxisEndstops(axesMentioned & AxesBitmap::MakeLowestNBits(numTotalAxes), moveBuffer.moveType == 1)) { err = "Failed to enable endstops"; @@ -3368,15 +3373,15 @@ void GCodes::DisableDrives() noexcept SetAllAxesNotHomed(); } -bool GCodes::ChangeMicrostepping(size_t drive, unsigned int microsteps, bool interp, const StringRef& reply) const noexcept +bool GCodes::ChangeMicrostepping(size_t axisOrExtruder, unsigned int microsteps, bool interp, const StringRef& reply) const noexcept { bool dummy; - const unsigned int oldSteps = platform.GetMicrostepping(drive, dummy); - const bool success = platform.SetMicrostepping(drive, microsteps, interp, reply); + const unsigned int oldSteps = platform.GetMicrostepping(axisOrExtruder, dummy); + const bool success = platform.SetMicrostepping(axisOrExtruder, microsteps, interp, reply); if (success) { // We changed the microstepping, so adjust the steps/mm to compensate - platform.SetDriveStepsPerUnit(drive, platform.DriveStepsPerUnit(drive), oldSteps); + platform.SetDriveStepsPerUnit(axisOrExtruder, platform.DriveStepsPerUnit(axisOrExtruder), oldSteps); } return success; } @@ -4378,16 +4383,17 @@ void GCodes::GenerateTemperatureReport(const StringRef& reply) const noexcept // 'reply' is a convenient buffer that is free for us to use. void GCodes::CheckReportDue(GCodeBuffer& gb, const StringRef& reply) const { - if (gb.DoDwellTime(1000)) + if (gb.IsReportDue()) { - if (gb.MachineState().compatibility == Compatibility::Marlin) + if (&gb == usbGCode && gb.MachineState().compatibility == Compatibility::Marlin) { // In Marlin emulation mode we should return a standard temperature report every second GenerateTemperatureReport(reply); reply.cat('\n'); platform.Message(UsbMessage, reply.c_str()); + reply.Clear(); } - if (lastAuxStatusReportType >= 0) + if (&gb == auxGCode && platform.IsAuxEnabled(0) && lastAuxStatusReportType >= 0) { // Send a standard status response for PanelDue OutputBuffer * const statusBuf = @@ -4397,9 +4403,12 @@ void GCodes::CheckReportDue(GCodeBuffer& gb, const StringRef& reply) const if (statusBuf != nullptr) { platform.AppendAuxReply(0, statusBuf, true); + if (reprap.Debug(moduleGcodes)) + { + reprap.GetPlatform().MessageF(DebugMessage, "%s: Sent unsolicited status report\n", gb.GetChannel().ToString()); + } } } - gb.StartTimer(); } } diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index cbaa7bfb..9c41de4b 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -384,7 +384,7 @@ private: 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, bool interp, const StringRef& reply) const noexcept; // Change microstepping on the specified drive + bool ChangeMicrostepping(size_t axisOrExtruder, unsigned int microsteps, bool interp, const StringRef& reply) const noexcept; // Change microstepping on the specified drive void CheckTriggers() noexcept; // Check for and execute triggers void CheckFilament() noexcept; // Check for and respond to filament errors void CheckHeaterFault() noexcept; // Check for and respond to a heater fault, returning true if we should exit diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 189773af..a0b0d814 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -1212,6 +1212,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx gb.TryGetUIValue('S', ustepMultiplier, seenUstepMultiplier); bool seen = false; +#if SUPPORT_CAN_EXPANSION + AxesBitmap axesToUpdate; +#endif for (size_t axis = 0; axis < numTotalAxes; axis++) { if (gb.Seen(axisLetters[axis])) @@ -1221,6 +1224,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx return false; } platform.SetDriveStepsPerUnit(axis, gb.GetFValue(), ustepMultiplier); +#if SUPPORT_CAN_EXPANSION + axesToUpdate.SetBit(axis); +#endif seen = true; } } @@ -1239,7 +1245,11 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // The user may not have as many extruders as we allow for, so just set the ones for which a value is provided for (size_t e = 0; e < eCount; e++) { - platform.SetDriveStepsPerUnit(ExtruderToLogicalDrive(e), eVals[e], ustepMultiplier); + const size_t drive = ExtruderToLogicalDrive(e); +#if SUPPORT_CAN_EXPANSION + axesToUpdate.SetBit(drive); +#endif + platform.SetDriveStepsPerUnit(drive, eVals[e], ustepMultiplier); } } @@ -1247,6 +1257,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { // On a delta, if we change the drive steps/mm then we need to recalculate the motor positions reprap.GetMove().SetNewPosition(moveBuffer.coords, true); +#if SUPPORT_CAN_EXPANSION + result = platform.UpdateRemoteStepsPerMmAndMicrostepping(axesToUpdate, reply); +#endif } else { @@ -1568,7 +1581,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // Wait for the heaters associated with the specified tool to be ready if (!ToolHeatersAtSetTemperatures(reprap.GetTool(gb.GetIValue()).Ptr(), true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } @@ -1586,7 +1598,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { if (!reprap.GetHeat().HeaterAtSetTemperature(heaters[i], true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } @@ -1609,7 +1620,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx const int8_t heater = reprap.GetHeat().GetChamberHeater(i); if (heater >= 0 && !reprap.GetHeat().HeaterAtSetTemperature(heater, true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } @@ -1625,7 +1635,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx const int8_t heater = reprap.GetHeat().GetChamberHeater(chamberIndices[i]); if (heater >= 0 && !reprap.GetHeat().HeaterAtSetTemperature(heater, true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } @@ -1638,7 +1647,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // Wait for all heaters except chamber(s) to be ready if (!seen && !reprap.GetHeat().AllHeatersAtSetTemperatures(true, tolerance)) { - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } @@ -1912,7 +1920,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx break; } - CheckReportDue(gb, reply); // check whether we need to send a temperature or status report isWaiting = true; return false; } @@ -2485,6 +2492,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx case 350: // Set/report microstepping { +#if SUPPORT_CAN_EXPANSION + AxesBitmap axesToUpdate; +#endif bool interp = (gb.Seen('I') && gb.GetIValue() > 0); bool seen = false; for (size_t axis = 0; axis < numTotalAxes; axis++) @@ -2496,6 +2506,9 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx return false; } seen = true; +#if SUPPORT_CAN_EXPANSION + axesToUpdate.SetBit(axis); +#endif const unsigned int microsteps = gb.GetUIValue(); if (ChangeMicrostepping(axis, microsteps, interp, reply)) { @@ -2520,14 +2533,24 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx gb.GetUnsignedArray(eVals, eCount, true); for (size_t e = 0; e < eCount; e++) { - if (!ChangeMicrostepping(ExtruderToLogicalDrive(e), eVals[e], interp, reply)) + const size_t drive = ExtruderToLogicalDrive(e); +#if SUPPORT_CAN_EXPANSION + axesToUpdate.SetBit(drive); +#endif + if (!ChangeMicrostepping(drive, eVals[e], interp, reply)) { result = GCodeResult::error; } } } - if (!seen) + if (seen) + { +#if SUPPORT_CAN_EXPANSION + result = max(result, platform.UpdateRemoteStepsPerMmAndMicrostepping(axesToUpdate, reply)); +#endif + } + else { reply.copy("Microstepping - "); for (size_t axis = 0; axis < numTotalAxes; ++axis) @@ -2684,6 +2707,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx // We don't delay and retry here, in case the user asked for too much of the object model in one go for the output buffers to contain it reply.copy("{\"err\":-1}\n"); } + if (&gb == auxGCode) + { + gb.ResetReportDueTimer(); + } } } break; @@ -4090,10 +4117,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx { if (gb.Seen(axisLetters[axis])) { - if (!platform.SetMotorCurrent(axis, gb.GetFValue(), code, reply)) - { - result = GCodeResult::error; - } + result = max(result, platform.SetMotorCurrent(axis, gb.GetFValue(), code, reply)); seen = true; } } @@ -4106,10 +4130,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx gb.GetFloatArray(eVals, eCount, true); for (size_t e = 0; e < eCount; e++) { - if (!platform.SetMotorCurrent(ExtruderToLogicalDrive(e), eVals[e], code, reply)) - { - result = GCodeResult::error; - } + result = max(result, platform.SetMotorCurrent(ExtruderToLogicalDrive(e), eVals[e], code, reply)); } } @@ -4344,14 +4365,14 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx reprap.EmergencyStop(); // this disables heaters and drives - Duet WiFi pre-production boards need drives disabled here { - uint16_t reason = (uint16_t)SoftwareResetReason::user; + SoftwareResetReason reason = SoftwareResetReason::user; if (gb.Seen('P')) { String<StringLength20> eraseString; gb.GetQuotedString(eraseString.GetRef()); if (eraseString.Equals("ERASE")) { - reason = (uint16_t)SoftwareResetReason::erase; + reason = SoftwareResetReason::erase; } } SoftwareReset(reason); // doesn't return diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp index 369da43f..035b6250 100644 --- a/src/GCodes/GCodes3.cpp +++ b/src/GCodes/GCodes3.cpp @@ -542,6 +542,9 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply) THRO const char *lettersToTry = AllowedAxisLetters; char c; +#if SUPPORT_CAN_EXPANSION + AxesBitmap axesToUpdate; +#endif const bool newAxesAreContinuousRotation = (gb.Seen('R') && gb.GetIValue() > 0); while ((c = *lettersToTry) != 0) { @@ -623,6 +626,9 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply) THRO reprap.MoveUpdated(); } platform.SetAxisDriversConfig(drive, numValues, drivers); +#if SUPPORT_CAN_EXPANSION + axesToUpdate.SetBit(drive); +#endif } } ++lettersToTry; @@ -638,6 +644,9 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply) THRO for (size_t i = 0; i < numValues; ++i) { platform.SetExtruderDriver(i, drivers[i]); +#if SUPPORT_CAN_EXPANSION + axesToUpdate.SetBit(ExtruderToLogicalDrive(i)); +#endif } if (FilamentMonitor::CheckDriveAssignments(reply) && rslt == GCodeResult::ok) { @@ -670,6 +679,9 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply) THRO ToolOffsetTransform(currentUserPosition, moveBuffer.coords); // ensure that the position of any new axes are updated in moveBuffer reprap.GetMove().SetNewPosition(moveBuffer.coords, true); // tell the Move system where the axes are } +#if SUPPORT_CAN_EXPANSION + rslt = max(rslt, platform.UpdateRemoteStepsPerMmAndMicrostepping(axesToUpdate, reply)); +#endif return rslt; } diff --git a/src/GCodes/GCodes4.cpp b/src/GCodes/GCodes4.cpp index 9858c68a..87dce185 100644 --- a/src/GCodes/GCodes4.cpp +++ b/src/GCodes/GCodes4.cpp @@ -29,6 +29,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept // Perform the next operation of the state machine for this gcode source GCodeResult stateMachineResult = GCodeResult::ok; + if (gb.GetState() != GCodeState::normal) + { + CheckReportDue(gb, reply); + } + switch (gb.GetState()) { case GCodeState::waitingForSpecialMoveToComplete: @@ -333,7 +338,6 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept } else { - CheckReportDue(gb, reply); isWaiting = true; } break; @@ -429,10 +433,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply) noexcept case GCodeState::flashing1: #if HAS_WIFI_NETWORKING - if (&gb == auxGCode) // if M997 S1 is sent from USB, don't keep sending temperature reports - { - CheckReportDue(gb, reply); // this is so that the ATE gets status reports and can tell when flashing is complete - } +// wilriker: This probably can be removed +// if (&gb == auxGCode) // if M997 S1 is sent from USB, don't keep sending temperature reports +// { +// CheckReportDue(gb, reply); // this is so that the ATE gets status reports and can tell when flashing is complete +// } // Update additional modules before the main firmware if (FirmwareUpdater::IsReady()) |