Sync MK3<->MK4 MMU2 protocol logic
This commit is contained in:
parent
9e794a47a4
commit
f235976f26
|
|
@ -1,8 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
namespace MMU2 {
|
||||||
|
|
||||||
// Register map for MMU
|
// Register map for MMU
|
||||||
enum class Register : uint8_t
|
enum class Register : uint8_t {
|
||||||
{
|
|
||||||
Project_Major = 0x00,
|
Project_Major = 0x00,
|
||||||
Project_Minor = 0x01,
|
Project_Minor = 0x01,
|
||||||
Project_Revision = 0x02,
|
Project_Revision = 0x02,
|
||||||
|
|
@ -38,3 +40,5 @@ enum class Register : uint8_t
|
||||||
Set_Get_Idler_iRun = 0x20,
|
Set_Get_Idler_iRun = 0x20,
|
||||||
Reserved = 0x21,
|
Reserved = 0x21,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace MMU2
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@
|
||||||
// irrelevant on Buddy FW, just keep "_millis" as "millis"
|
// irrelevant on Buddy FW, just keep "_millis" as "millis"
|
||||||
#include <wiring_time.h>
|
#include <wiring_time.h>
|
||||||
#define _millis millis
|
#define _millis millis
|
||||||
|
#ifdef UNITTEST
|
||||||
|
#define strncmp_P strncmp
|
||||||
|
#else
|
||||||
|
#include <Marlin/src/core/serial.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -16,7 +21,7 @@
|
||||||
|
|
||||||
namespace MMU2 {
|
namespace MMU2 {
|
||||||
|
|
||||||
/// Beware:
|
/// Beware - on AVR/MK3S:
|
||||||
/// Changing the supportedMmuVersion numbers requires patching MSG_DESC_FW_UPDATE_NEEDED and all its related translations by hand.
|
/// Changing the supportedMmuVersion numbers requires patching MSG_DESC_FW_UPDATE_NEEDED and all its related translations by hand.
|
||||||
///
|
///
|
||||||
/// The message reads:
|
/// The message reads:
|
||||||
|
|
@ -24,6 +29,8 @@ namespace MMU2 {
|
||||||
///
|
///
|
||||||
/// Currently, this is not possible to perform automatically at compile time with the existing languages/translations infrastructure.
|
/// Currently, this is not possible to perform automatically at compile time with the existing languages/translations infrastructure.
|
||||||
/// To save space a "dumb" solution was chosen + a few static_assert checks in errors_list.h preventing the code from compiling when the string doesn't match.
|
/// To save space a "dumb" solution was chosen + a few static_assert checks in errors_list.h preventing the code from compiling when the string doesn't match.
|
||||||
|
/// -----
|
||||||
|
/// On Buddy FW we should improve the error screen to be able to print formatted strings
|
||||||
static constexpr uint8_t supportedMmuFWVersion[3] PROGMEM = { mmuVersionMajor, mmuVersionMinor, mmuVersionPatch };
|
static constexpr uint8_t supportedMmuFWVersion[3] PROGMEM = { mmuVersionMajor, mmuVersionMinor, mmuVersionPatch };
|
||||||
|
|
||||||
const Register ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = {
|
const Register ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = {
|
||||||
|
|
@ -197,7 +204,11 @@ StepStatus ProtocolLogic::ExpectingMessage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolLogic::SendMsg(RequestMsg rq) {
|
void ProtocolLogic::SendMsg(RequestMsg rq) {
|
||||||
|
#ifdef __AVR__
|
||||||
|
// Buddy FW cannot use stack-allocated txbuff - DMA doesn't work with CCMRAM
|
||||||
|
// No restrictions on MK3/S/+ though
|
||||||
uint8_t txbuff[Protocol::MaxRequestSize()];
|
uint8_t txbuff[Protocol::MaxRequestSize()];
|
||||||
|
#endif
|
||||||
uint8_t len = Protocol::EncodeRequest(rq, txbuff);
|
uint8_t len = Protocol::EncodeRequest(rq, txbuff);
|
||||||
uart->write(txbuff, len);
|
uart->write(txbuff, len);
|
||||||
LogRequestMsg(txbuff, len);
|
LogRequestMsg(txbuff, len);
|
||||||
|
|
@ -205,7 +216,11 @@ void ProtocolLogic::SendMsg(RequestMsg rq) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolLogic::SendWriteMsg(RequestMsg rq) {
|
void ProtocolLogic::SendWriteMsg(RequestMsg rq) {
|
||||||
|
#ifdef __AVR__
|
||||||
|
// Buddy FW cannot use stack-allocated txbuff - DMA doesn't work with CCMRAM
|
||||||
|
// No restrictions on MK3/S/+ though
|
||||||
uint8_t txbuff[Protocol::MaxRequestSize()];
|
uint8_t txbuff[Protocol::MaxRequestSize()];
|
||||||
|
#endif
|
||||||
uint8_t len = Protocol::EncodeWriteRequest(rq.value, rq.value2, txbuff);
|
uint8_t len = Protocol::EncodeWriteRequest(rq.value, rq.value2, txbuff);
|
||||||
uart->write(txbuff, len);
|
uart->write(txbuff, len);
|
||||||
LogRequestMsg(txbuff, len);
|
LogRequestMsg(txbuff, len);
|
||||||
|
|
@ -349,6 +364,7 @@ StepStatus ProtocolLogic::ProcessCommandQueryResponse() {
|
||||||
return Processing;
|
return Processing;
|
||||||
case ResponseMsgParamCodes::Error:
|
case ResponseMsgParamCodes::Error:
|
||||||
// in case of an error the progress code remains as it has been before
|
// in case of an error the progress code remains as it has been before
|
||||||
|
progressCode = ProgressCode::ERRWaitingForUser;
|
||||||
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
||||||
// keep on reporting the state of fsensor regularly even in command error state
|
// keep on reporting the state of fsensor regularly even in command error state
|
||||||
// - the MMU checks FINDA and fsensor even while recovering from errors
|
// - the MMU checks FINDA and fsensor even while recovering from errors
|
||||||
|
|
@ -469,9 +485,11 @@ StepStatus ProtocolLogic::IdleStep() {
|
||||||
case ResponseMsgParamCodes::Processing:
|
case ResponseMsgParamCodes::Processing:
|
||||||
// @@TODO we may actually use this branch to report progress of manual operation on the MMU
|
// @@TODO we may actually use this branch to report progress of manual operation on the MMU
|
||||||
// The MMU sends e.g. X0 P27 after its restart when the user presses an MMU button to move the Selector
|
// The MMU sends e.g. X0 P27 after its restart when the user presses an MMU button to move the Selector
|
||||||
|
progressCode = static_cast<ProgressCode>(rsp.paramValue);
|
||||||
errorCode = ErrorCode::OK;
|
errorCode = ErrorCode::OK;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
progressCode = ProgressCode::ERRWaitingForUser;
|
||||||
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
errorCode = static_cast<ErrorCode>(rsp.paramValue);
|
||||||
StartReading8bitRegisters(); // continue Idle state without restarting the communication
|
StartReading8bitRegisters(); // continue Idle state without restarting the communication
|
||||||
return CommandError;
|
return CommandError;
|
||||||
|
|
@ -758,6 +776,7 @@ void ProtocolLogic::LogResponse() {
|
||||||
StepStatus ProtocolLogic::SuppressShortDropOuts(const char *msg_P, StepStatus ss) {
|
StepStatus ProtocolLogic::SuppressShortDropOuts(const char *msg_P, StepStatus ss) {
|
||||||
if (dataTO.Record(ss)) {
|
if (dataTO.Record(ss)) {
|
||||||
LogError(msg_P);
|
LogError(msg_P);
|
||||||
|
dataTO.Reset(); // prepare for another run of consecutive retries before firing an error
|
||||||
return dataTO.InitialCause();
|
return dataTO.InitialCause();
|
||||||
} else {
|
} else {
|
||||||
return Processing; // suppress short drop outs of communication
|
return Processing; // suppress short drop outs of communication
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ namespace std {
|
||||||
template <typename T, uint8_t N>
|
template <typename T, uint8_t N>
|
||||||
class array {
|
class array {
|
||||||
T data[N];
|
T data[N];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
array() = default;
|
array() = default;
|
||||||
inline constexpr T *begin() const { return data; }
|
inline constexpr T *begin() const { return data; }
|
||||||
|
|
@ -23,7 +24,7 @@ public:
|
||||||
return data[i];
|
return data[i];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace std
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
@ -34,6 +35,7 @@ public:
|
||||||
#undef CRC
|
#undef CRC
|
||||||
#include "../../../../../../Prusa-Firmware-MMU/src/modules/protocol.h"
|
#include "../../../../../../Prusa-Firmware-MMU/src/modules/protocol.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
|
#include "registers.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mmu2_serial.h"
|
#include "mmu2_serial.h"
|
||||||
|
|
@ -63,16 +65,14 @@ enum StepStatus : uint_fast8_t {
|
||||||
ButtonPushed, ///< The MMU reported the user pushed one of its three buttons.
|
ButtonPushed, ///< The MMU reported the user pushed one of its three buttons.
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uint32_t linkLayerTimeout = 2000; ///< default link layer communication timeout
|
inline constexpr uint32_t linkLayerTimeout = 2000; ///< default link layer communication timeout
|
||||||
static constexpr uint32_t dataLayerTimeout = linkLayerTimeout * 3; ///< data layer communication timeout
|
inline constexpr uint32_t dataLayerTimeout = linkLayerTimeout * 3; ///< data layer communication timeout
|
||||||
static constexpr uint32_t heartBeatPeriod = linkLayerTimeout / 2; ///< period of heart beat messages (Q0)
|
inline constexpr uint32_t heartBeatPeriod = linkLayerTimeout / 2; ///< period of heart beat messages (Q0)
|
||||||
|
|
||||||
static_assert(heartBeatPeriod < linkLayerTimeout && linkLayerTimeout < dataLayerTimeout, "Incorrect ordering of timeouts");
|
static_assert(heartBeatPeriod < linkLayerTimeout && linkLayerTimeout < dataLayerTimeout, "Incorrect ordering of timeouts");
|
||||||
|
|
||||||
///< Filter of short consecutive drop outs which are recovered instantly
|
///< Filter of short consecutive drop outs which are recovered instantly
|
||||||
class DropOutFilter {
|
class DropOutFilter {
|
||||||
StepStatus cause;
|
|
||||||
uint8_t occurrences;
|
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t maxOccurrences = 10; // ideally set this to >8 seconds -> 12x heartBeatPeriod
|
static constexpr uint8_t maxOccurrences = 10; // ideally set this to >8 seconds -> 12x heartBeatPeriod
|
||||||
static_assert(maxOccurrences > 1, "we should really silently ignore at least 1 comm drop out if recovered immediately afterwards");
|
static_assert(maxOccurrences > 1, "we should really silently ignore at least 1 comm drop out if recovered immediately afterwards");
|
||||||
|
|
@ -86,6 +86,10 @@ public:
|
||||||
|
|
||||||
/// Rearms the object for further processing - basically call this once the MMU responds with something meaningful (e.g. S0 A2)
|
/// Rearms the object for further processing - basically call this once the MMU responds with something meaningful (e.g. S0 A2)
|
||||||
inline void Reset() { occurrences = maxOccurrences; }
|
inline void Reset() { occurrences = maxOccurrences; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
StepStatus cause;
|
||||||
|
uint8_t occurrences = maxOccurrences;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Logic layer of the MMU vs. printer communication protocol
|
/// Logic layer of the MMU vs. printer communication protocol
|
||||||
|
|
@ -228,15 +232,6 @@ private:
|
||||||
Running ///< normal operation - Idle + Command processing
|
Running ///< normal operation - Idle + Command processing
|
||||||
};
|
};
|
||||||
|
|
||||||
// individual sub-state machines - may be they can be combined into a union since only one is active at once
|
|
||||||
// or we can blend them into ProtocolLogic at the cost of a less nice code (but hopefully shorter)
|
|
||||||
// Stopped stopped;
|
|
||||||
// StartSeq startSeq;
|
|
||||||
// DelayedRestart delayedRestart;
|
|
||||||
// Idle idle;
|
|
||||||
// Command command;
|
|
||||||
// ProtocolLogicPartBase *currentState; ///< command currently being processed
|
|
||||||
|
|
||||||
enum class Scope : uint_fast8_t {
|
enum class Scope : uint_fast8_t {
|
||||||
Stopped,
|
Stopped,
|
||||||
StartSeq,
|
StartSeq,
|
||||||
|
|
@ -370,6 +365,11 @@ private:
|
||||||
|
|
||||||
uint8_t lastFSensor; ///< last state of filament sensor
|
uint8_t lastFSensor; ///< last state of filament sensor
|
||||||
|
|
||||||
|
#ifndef __AVR__
|
||||||
|
uint8_t txbuff[Protocol::MaxRequestSize()]; ///< In Buddy FW - a static transmit buffer needs to exist as DMA cannot be used from CCMRAM.
|
||||||
|
///< On MK3/S/+ the transmit buffer is allocated on the stack without restrictions
|
||||||
|
#endif
|
||||||
|
|
||||||
// 8bit registers
|
// 8bit registers
|
||||||
static constexpr uint8_t regs8Count = 3;
|
static constexpr uint8_t regs8Count = 3;
|
||||||
static_assert(regs8Count > 0); // code is not ready for empty lists of registers
|
static_assert(regs8Count > 0); // code is not ready for empty lists of registers
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue