clang-format

This commit is contained in:
D.R.racer 2023-01-25 10:03:25 +01:00 committed by DRracer
parent 0555376502
commit 528abcb8d8
7 changed files with 231 additions and 216 deletions

View File

@ -15,22 +15,22 @@
#ifdef __AVR__
// As of FW 3.12 we only support building the FW with only one extruder, all the multi-extruder infrastructure will be removed.
// Saves at least 800B of code size
static_assert(EXTRUDERS==1);
static_assert(EXTRUDERS == 1);
constexpr float MMM_TO_MMS(float MM_M){ return MM_M / 60.0f; }
constexpr float MMM_TO_MMS(float MM_M) { return MM_M / 60.0f; }
#endif
namespace MMU2 {
template<typename F>
void waitForHotendTargetTemp(uint16_t delay, F f){
template <typename F>
void waitForHotendTargetTemp(uint16_t delay, F f) {
while (((thermal_degTargetHotend() - thermal_degHotend()) > 5)) {
f();
safe_delay_keep_alive(delay);
}
}
void WaitForHotendTargetTempBeep(){
void WaitForHotendTargetTempBeep() {
waitForHotendTargetTemp(3000, []{ });
MakeSound(Prompt);
}
@ -51,14 +51,13 @@ MMU2::MMU2()
, unloadFilamentStarted(false)
, loadingToNozzle(false)
, toolchange_counter(0)
, tmcFailures(0)
{
, tmcFailures(0) {
}
void MMU2::Start() {
mmu2Serial.begin(MMU_BAUD);
PowerOn(); // I repurposed this to serve as our EEPROM disable toggle.
PowerOn(); // I repurposed this to serve as our EEPROM disable toggle.
mmu2Serial.flush(); // make sure the UART buffer is clear before starting communication
extruder = MMU2_NO_TOOL;
@ -75,13 +74,13 @@ void MMU2::Stop() {
PowerOff(); // This also disables the MMU in the EEPROM.
}
void MMU2::StopKeepPowered(){
void MMU2::StopKeepPowered() {
state = xState::Stopped;
logic.Stop();
mmu2Serial.close();
}
void MMU2::Reset(ResetForm level){
void MMU2::Reset(ResetForm level) {
switch (level) {
case Software:
ResetX0();
@ -101,11 +100,11 @@ void MMU2::ResetX0() {
logic.ResetMMU(); // Send soft reset
}
void MMU2::TriggerResetPin(){
void MMU2::TriggerResetPin() {
reset();
}
void MMU2::PowerCycle(){
void MMU2::PowerCycle() {
// cut the power to the MMU and after a while restore it
// Sadly, MK3/S/+ cannot do this
// NOTE: the below will toggle the EEPROM var. Should we
@ -115,36 +114,36 @@ void MMU2::PowerCycle(){
PowerOn();
}
void MMU2::PowerOff(){
void MMU2::PowerOff() {
power_off();
}
void MMU2::PowerOn(){
void MMU2::PowerOn() {
power_on();
}
bool MMU2::ReadRegister(uint8_t address){
if( ! WaitForMMUReady())
bool MMU2::ReadRegister(uint8_t address) {
if (!WaitForMMUReady())
return false;
do {
logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function
} while( ! manage_response(false, false) );
} while (!manage_response(false, false));
return true;
}
bool MMU2::WriteRegister(uint8_t address, uint16_t data){
if( ! WaitForMMUReady())
bool MMU2::WriteRegister(uint8_t address, uint16_t data) {
if (!WaitForMMUReady())
return false;
// special case - intercept requests of extra loading distance and perform the change even on the printer's side
if( address == 0x0b ){
if (address == 0x0b) {
logic.PlanExtraLoadDistance(data);
}
do {
logic.WriteRegister(address, data); // we may signal the accepted/rejected status of the response as return value of this function
} while( ! manage_response(false, false) );
} while (!manage_response(false, false));
return true;
}
@ -193,13 +192,13 @@ struct ReportingRAII {
: cip(cip) {
BeginReport(cip, (uint16_t)ProgressCode::EngagingIdler);
}
inline ~ReportingRAII(){
inline ~ReportingRAII() {
EndReport(cip, (uint16_t)ProgressCode::OK);
}
};
bool MMU2::WaitForMMUReady(){
switch(State()){
bool MMU2::WaitForMMUReady() {
switch (State()) {
case xState::Stopped:
return false;
case xState::Connecting:
@ -210,11 +209,11 @@ bool MMU2::WaitForMMUReady(){
}
}
bool MMU2::RetryIfPossible(uint16_t ec){
bool MMU2::RetryIfPossible(uint16_t ec) {
if (logic.RetryAttempts()) {
SetButtonResponse(ButtonOperations::Retry);
// check, that Retry is actually allowed on that operation
if( ButtonAvailable(ec) != NoButton ){
if (ButtonAvailable(ec) != NoButton) {
logic.SetInAutoRetry(true);
SERIAL_ECHOLNPGM("RetryButtonPressed");
// We don't decrement until the button is acknowledged by the MMU.
@ -226,20 +225,19 @@ bool MMU2::RetryIfPossible(uint16_t ec){
return false;
}
bool MMU2::VerifyFilamentEnteredPTFE()
{
bool MMU2::VerifyFilamentEnteredPTFE() {
planner_synchronize();
if (WhereIsFilament() == FilamentState::NOT_PRESENT) return false;
if (WhereIsFilament() == FilamentState::NOT_PRESENT)
return false;
uint8_t fsensorState = 0;
// MMU has finished its load, push the filament further by some defined constant length
// If the filament sensor reads 0 at any moment, then report FAILURE
MoveE(MMU2_EXTRUDER_PTFE_LENGTH + MMU2_EXTRUDER_HEATBREAK_LENGTH - (logic.ExtraLoadDistance() - MMU2_FILAMENT_SENSOR_POSITION), MMU2_VERIFY_LOAD_TO_NOZZLE_FEED_RATE);
MoveE( - (MMU2_EXTRUDER_PTFE_LENGTH + MMU2_EXTRUDER_HEATBREAK_LENGTH - (logic.ExtraLoadDistance() - MMU2_FILAMENT_SENSOR_POSITION)), MMU2_VERIFY_LOAD_TO_NOZZLE_FEED_RATE);
MoveE(-(MMU2_EXTRUDER_PTFE_LENGTH + MMU2_EXTRUDER_HEATBREAK_LENGTH - (logic.ExtraLoadDistance() - MMU2_FILAMENT_SENSOR_POSITION)), MMU2_VERIFY_LOAD_TO_NOZZLE_FEED_RATE);
while(planner_any_moves())
{
while (planner_any_moves()) {
// Wait for move to finish and monitor the fsensor the entire time
// A single 0 reading will set the bit.
fsensorState |= (WhereIsFilament() == FilamentState::NOT_PRESENT);
@ -247,8 +245,7 @@ bool MMU2::VerifyFilamentEnteredPTFE()
marlin_manage_inactivity(true);
}
if (fsensorState)
{
if (fsensorState) {
IncrementLoadFails();
return false;
} else {
@ -257,14 +254,14 @@ bool MMU2::VerifyFilamentEnteredPTFE()
}
}
bool MMU2::ToolChangeCommonOnce(uint8_t slot){
bool MMU2::ToolChangeCommonOnce(uint8_t slot) {
static_assert(MAX_RETRIES > 1); // need >1 retries to do the cut in the last attempt
for(uint8_t retries = MAX_RETRIES; retries; --retries){
for(;;) {
for (uint8_t retries = MAX_RETRIES; retries; --retries) {
for (;;) {
Disable_E0(); // it may seem counterintuitive to disable the E-motor, but it gets enabled in the planner whenever the E-motor is to move
tool_change_extruder = slot;
logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in
if( manage_response(true, true) )
if (manage_response(true, true))
break;
// otherwise: failed to perform the command - unload first and then let it run again
IncrementMMUFails();
@ -280,12 +277,12 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot){
// something else is seriously broken and stopping a print is probably our best option.
}
// reset current position to whatever the planner thinks it is
planner_set_current_position_E( planner_get_current_position_E() );
if (VerifyFilamentEnteredPTFE()){
planner_set_current_position_E(planner_get_current_position_E());
if (VerifyFilamentEnteredPTFE()) {
return true; // success
} else { // Prepare a retry attempt
} else { // Prepare a retry attempt
unload();
if( retries == 2 && cutter_enabled()){
if (retries == 2 && cutter_enabled()) {
cut_filament(slot, false); // try cutting filament tip at the last attempt
}
}
@ -293,8 +290,8 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot){
return false; // couldn't accomplish the task
}
void MMU2::ToolChangeCommon(uint8_t slot){
while( ! ToolChangeCommonOnce(slot) ){ // while not successfully fed into extruder's PTFE tube
void MMU2::ToolChangeCommon(uint8_t slot) {
while (!ToolChangeCommonOnce(slot)) { // while not successfully fed into extruder's PTFE tube
// failed autoretry, report an error by forcing a "printer" error into the MMU infrastructure - it is a hack to leverage existing code
// @@TODO theoretically logic layer may not need to be spoiled with the printer error - may be just the manage_response needs it...
logic.SetPrinterError(ErrorCode::LOAD_TO_EXTRUDER_FAILED);
@ -312,7 +309,7 @@ void MMU2::ToolChangeCommon(uint8_t slot){
}
bool MMU2::tool_change(uint8_t slot) {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
if (slot != extruder) {
@ -338,14 +335,14 @@ bool MMU2::tool_change(uint8_t slot) {
///- Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load.
///- Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated.
bool MMU2::tool_change(char code, uint8_t slot) {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
FSensorBlockRunout blockRunout;
switch (code) {
case '?': {
waitForHotendTargetTemp(100, []{});
waitForHotendTargetTemp(100, [] {});
load_filament_to_nozzle(slot);
} break;
@ -357,7 +354,7 @@ bool MMU2::tool_change(char code, uint8_t slot) {
} break;
case 'c': {
waitForHotendTargetTemp(100, []{});
waitForHotendTargetTemp(100, [] {});
execute_load_to_nozzle_sequence();
} break;
}
@ -378,16 +375,16 @@ uint8_t MMU2::get_tool_change_tool() const {
}
bool MMU2::set_filament_type(uint8_t /*slot*/, uint8_t /*type*/) {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
// @@TODO - this is not supported in the new MMU yet
// slot = slot; // @@TODO
// type = type; // @@TODO
// slot = slot; // @@TODO
// type = type; // @@TODO
// cmd_arg = filamentType;
// command(MMU_CMD_F0 + index);
if( ! manage_response(false, false) ){
if (!manage_response(false, false)) {
// @@TODO failed to perform the command - retry
;
} // true, true); -- Comment: how is it possible for a filament type set to fail?
@ -396,7 +393,7 @@ bool MMU2::set_filament_type(uint8_t /*slot*/, uint8_t /*type*/) {
}
bool MMU2::unload() {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
WaitForHotendTargetTempBeep();
@ -408,10 +405,10 @@ bool MMU2::unload() {
// we assume the printer managed to relieve filament tip from the gears,
// so repeating that part in case of an MMU restart is not necessary
for(;;) {
for (;;) {
Disable_E0();
logic.UnloadFilament();
if( manage_response(false, true) )
if (manage_response(false, true))
break;
IncrementMMUFails();
}
@ -424,23 +421,23 @@ bool MMU2::unload() {
return true;
}
bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /* = true */){
if( ! WaitForMMUReady())
bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /*= true*/) {
if (!WaitForMMUReady())
return false;
if( enableFullScreenMsg ){
if (enableFullScreenMsg) {
FullScreenMsgCut(slot);
}
{
if( FindaDetectsFilament() ){
if (FindaDetectsFilament()) {
unload();
}
ReportingRAII rep(CommandInProgress::CutFilament);
for(;;){
for (;;) {
Disable_E0();
logic.CutFilament(slot);
if( manage_response(false, true) )
if (manage_response(false, true))
break;
IncrementMMUFails();
}
@ -451,7 +448,7 @@ bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /* = true */){
return true;
}
bool MMU2::loading_test(uint8_t slot){
bool MMU2::loading_test(uint8_t slot) {
FullScreenMsgTest(slot);
tool_change(slot);
planner_synchronize();
@ -461,16 +458,16 @@ bool MMU2::loading_test(uint8_t slot){
}
bool MMU2::load_filament(uint8_t slot) {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
FullScreenMsgLoad(slot);
ReportingRAII rep(CommandInProgress::LoadFilament);
for(;;) {
for (;;) {
Disable_E0();
logic.LoadFilament(slot);
if( manage_response(false, false) )
if (manage_response(false, false))
break;
IncrementMMUFails();
}
@ -484,16 +481,17 @@ bool MMU2::load_filament(uint8_t slot) {
struct LoadingToNozzleRAII {
MMU2 &mmu2;
explicit inline LoadingToNozzleRAII(MMU2 &mmu2):mmu2(mmu2){
explicit inline LoadingToNozzleRAII(MMU2 &mmu2)
: mmu2(mmu2) {
mmu2.loadingToNozzle = true;
}
inline ~LoadingToNozzleRAII(){
inline ~LoadingToNozzleRAII() {
mmu2.loadingToNozzle = false;
}
};
bool MMU2::load_filament_to_nozzle(uint8_t slot) {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
LoadingToNozzleRAII ln(*this);
@ -506,7 +504,7 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) {
ReportingRAII rep(CommandInProgress::ToolChange);
FSensorBlockRunout blockRunout;
if( extruder != MMU2_NO_TOOL ){ // we already have some filament loaded - free it + shape its tip properly
if (extruder != MMU2_NO_TOOL) { // we already have some filament loaded - free it + shape its tip properly
filament_ramming();
}
@ -521,22 +519,22 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) {
}
bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) {
if( ! WaitForMMUReady())
if (!WaitForMMUReady())
return false;
if( enableFullScreenMsg ){
if (enableFullScreenMsg) {
FullScreenMsgEject(slot);
}
{
if( FindaDetectsFilament() ){
if (FindaDetectsFilament()) {
unload();
}
ReportingRAII rep(CommandInProgress::EjectFilament);
for(;;) {
for (;;) {
Disable_E0();
logic.EjectFilament(slot);
if( manage_response(false, true) )
if (manage_response(false, true))
break;
IncrementMMUFails();
}
@ -547,19 +545,20 @@ bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) {
return true;
}
void MMU2::Button(uint8_t index){
void MMU2::Button(uint8_t index) {
LogEchoEvent_P(PSTR("Button"));
logic.Button(index);
}
void MMU2::Home(uint8_t mode){
void MMU2::Home(uint8_t mode) {
logic.Home(mode);
}
void MMU2::SaveHotendTemp(bool turn_off_nozzle) {
if (mmu_print_saved & SavedState::Cooldown) return;
if (mmu_print_saved & SavedState::Cooldown)
return;
if (turn_off_nozzle && !(mmu_print_saved & SavedState::CooldownPending)){
if (turn_off_nozzle && !(mmu_print_saved & SavedState::CooldownPending)) {
Disable_E0();
resume_hotend_temp = thermal_degTargetHotend();
mmu_print_saved |= SavedState::CooldownPending;
@ -573,7 +572,7 @@ void MMU2::SaveAndPark(bool move_axes) {
Disable_E0();
planner_synchronize();
if (move_axes){
if (move_axes) {
mmu_print_saved |= SavedState::ParkExtruder;
resume_position = planner_current_position(); // save current pos
@ -599,14 +598,14 @@ void MMU2::ResumeHotendTemp() {
}
if ((mmu_print_saved & SavedState::Cooldown) && resume_hotend_temp) {
LogEchoEvent_P(PSTR("Resuming Temp"));
// @@TODO MMU2_ECHO_MSGRPGM(PSTR("Restoring hotend temperature "));
// @@TODO MMU2_ECHO_MSGRPGM(PSTR("Restoring hotend temperature "));
SERIAL_ECHOLN(resume_hotend_temp);
mmu_print_saved &= ~(SavedState::Cooldown);
thermal_setTargetHotend(resume_hotend_temp);
FullScreenMsgRestoringTemperature();
//@todo better report the event and let the GUI do its work somewhere else
ReportErrorHookSensorLineRender();
waitForHotendTargetTemp(100, []{
waitForHotendTargetTemp(100, [] {
marlin_manage_inactivity(true);
mmu2.mmu_loop_inner(false);
ReportErrorHookDynamicRender();
@ -617,7 +616,7 @@ void MMU2::ResumeHotendTemp() {
}
}
void MMU2::ResumeUnpark(){
void MMU2::ResumeUnpark() {
if (mmu_print_saved & SavedState::ParkExtruder) {
LogEchoEvent_P(PSTR("Resuming XYZ"));
@ -631,11 +630,11 @@ void MMU2::ResumeUnpark(){
}
}
void MMU2::CheckUserInput(){
void MMU2::CheckUserInput() {
auto btn = ButtonPressed((uint16_t)lastErrorCode);
// Was a button pressed on the MMU itself instead of the LCD?
if (btn == Buttons::NoButton && lastButton != Buttons::NoButton){
if (btn == Buttons::NoButton && lastButton != Buttons::NoButton) {
btn = lastButton;
lastButton = Buttons::NoButton; // Clear it.
}
@ -648,7 +647,7 @@ void MMU2::CheckUserInput(){
SERIAL_ECHOLN(btn);
// clear the explicit printer error as soon as possible so that the MMU error screens + reporting doesn't get too confused
if( lastErrorCode == ErrorCode::LOAD_TO_EXTRUDER_FAILED ){
if (lastErrorCode == ErrorCode::LOAD_TO_EXTRUDER_FAILED) {
// A horrible hack - clear the explicit printer error allowing manage_response to recover on MMU's Finished state
// Moreover - if the MMU is currently doing something (like the LoadFilament - see comment above)
// we'll actually wait for it automagically in manage_response and after it finishes correctly,
@ -668,7 +667,7 @@ void MMU2::CheckUserInput(){
// A quick hack: for specific error codes move the E-motor every time.
// Not sure if we can rely on the fsensor.
// Just plan the move, let the MMU take over when it is ready
switch(lastErrorCode){
switch (lastErrorCode) {
case ErrorCode::FSENSOR_DIDNT_SWITCH_OFF:
case ErrorCode::FSENSOR_TOO_EARLY:
HelpUnloadToFinda();
@ -714,11 +713,11 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
// - finished ok -> proceed with reading other commands
safe_delay_keep_alive(0); // calls LogicStep() and remembers its return status
if (mmu_print_saved & SavedState::CooldownPending){
if (!nozzleTimeout.running()){
if (mmu_print_saved & SavedState::CooldownPending) {
if (!nozzleTimeout.running()) {
nozzleTimeout.start();
LogEchoEvent_P(PSTR("Cooling Timeout started"));
} else if (nozzleTimeout.expired(DEFAULT_SAFETYTIMER_TIME_MINS*60*1000ul)){ // mins->msec.
} else if (nozzleTimeout.expired(DEFAULT_SAFETYTIMER_TIME_MINS * 60 * 1000ul)) { // mins->msec.
mmu_print_saved &= ~(SavedState::CooldownPending);
mmu_print_saved |= SavedState::Cooldown;
thermal_setTargetHotend(0);
@ -734,7 +733,7 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
// command/operation completed, let Marlin continue its work
// the E may have some more moves to finish - wait for them
ResumeHotendTemp();
ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
logic.ResetRetryAttempts(); // Reset the retry counter.
planner_synchronize();
return true;
@ -755,7 +754,7 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
case CommunicationTimeout:
case ProtocolError:
case ButtonPushed:
if (! logic.InAutoRetry()){
if (!logic.InAutoRetry()) {
// Don't proceed to the park/save if we are doing an autoretry.
SaveAndPark(move_axes);
SaveHotendTemp(turn_off_nozzle);
@ -794,9 +793,8 @@ StepStatus MMU2::LogicStep(bool reportErrors) {
// can be silently handed over to a higher layer, no processing necessary at this spot
break;
default:
if(reportErrors) {
switch (ss)
{
if (reportErrors) {
switch (ss) {
case CommandError:
ReportError(logic.Error(), ErrorSourceMMU);
break;
@ -821,7 +819,7 @@ StepStatus MMU2::LogicStep(bool reportErrors) {
}
}
if( logic.Running() ){
if (logic.Running()) {
state = xState::Active;
}
return ss;
@ -852,8 +850,8 @@ void MMU2::execute_extruder_sequence(const E_Step *sequence, uint8_t steps) {
void MMU2::execute_load_to_nozzle_sequence() {
planner_synchronize();
// Compensate for configurable Extra Loading Distance
planner_set_current_position_E( planner_get_current_position_E() - (logic.ExtraLoadDistance() - MMU2_FILAMENT_SENSOR_POSITION) );
execute_extruder_sequence(load_to_nozzle_sequence, sizeof(load_to_nozzle_sequence) / sizeof (load_to_nozzle_sequence[0]));
planner_set_current_position_E(planner_get_current_position_E() - (logic.ExtraLoadDistance() - MMU2_FILAMENT_SENSOR_POSITION));
execute_extruder_sequence(load_to_nozzle_sequence, sizeof(load_to_nozzle_sequence) / sizeof(load_to_nozzle_sequence[0]));
}
void MMU2::ReportError(ErrorCode ec, ErrorSource res) {
@ -870,7 +868,7 @@ void MMU2::ReportError(ErrorCode ec, ErrorSource res) {
// Right now the filtering of MMU_NOT_RESPONDING is done in ReportErrorHook() as it is not a problem if mmu2.cpp
// Depending on the Progress code, we may want to do some action when an error occurs
switch (logic.Progress()){
switch (logic.Progress()) {
case ProgressCode::UnloadingToFinda:
unloadFilamentStarted = false;
break;
@ -882,12 +880,12 @@ void MMU2::ReportError(ErrorCode ec, ErrorSource res) {
break;
}
if( ec != lastErrorCode ){ // deduplicate: only report changes in error codes into the log
if (ec != lastErrorCode) { // deduplicate: only report changes in error codes into the log
lastErrorCode = ec;
lastErrorSource = res;
LogErrorEvent_P( _O(PrusaErrorTitle(PrusaErrorCodeIndex((uint16_t)ec))) );
LogErrorEvent_P(_O(PrusaErrorTitle(PrusaErrorCodeIndex((uint16_t)ec))));
if( ec != ErrorCode::OK ){
if (ec != ErrorCode::OK) {
IncrementMMUFails();
// check if it is a "power" failure - we consider TMC-related errors as power failures
@ -908,7 +906,7 @@ void MMU2::ReportError(ErrorCode ec, ErrorSource res) {
}
}
if( !mmu2.RetryIfPossible((uint16_t)ec) ) {
if (!mmu2.RetryIfPossible((uint16_t)ec)) {
// If retry attempts are all used up
// or if 'Retry' operation is not available
// raise the MMU error sceen and wait for user input
@ -916,21 +914,20 @@ void MMU2::ReportError(ErrorCode ec, ErrorSource res) {
}
static_assert(mmu2Magic[0] == 'M'
&& mmu2Magic[1] == 'M'
&& mmu2Magic[2] == 'U'
&& mmu2Magic[3] == '2'
&& mmu2Magic[4] == ':'
&& strlen_constexpr(mmu2Magic) == 5,
"MMU2 logging prefix mismatch, must be updated at various spots"
);
&& mmu2Magic[1] == 'M'
&& mmu2Magic[2] == 'U'
&& mmu2Magic[3] == '2'
&& mmu2Magic[4] == ':'
&& strlen_constexpr(mmu2Magic) == 5,
"MMU2 logging prefix mismatch, must be updated at various spots");
}
void MMU2::ReportProgress(ProgressCode pc) {
ReportProgressHook((CommandInProgress)logic.CommandInProgress(), (uint16_t)pc);
LogEchoEvent_P( _O(ProgressCodeToText((uint16_t)pc)) );
LogEchoEvent_P(_O(ProgressCodeToText((uint16_t)pc)));
}
void MMU2::OnMMUProgressMsg(ProgressCode pc){
void MMU2::OnMMUProgressMsg(ProgressCode pc) {
if (pc != lastProgressCode) {
OnMMUProgressMsgChanged(pc);
} else {
@ -938,7 +935,7 @@ void MMU2::OnMMUProgressMsg(ProgressCode pc){
}
}
void MMU2::OnMMUProgressMsgChanged(ProgressCode pc){
void MMU2::OnMMUProgressMsgChanged(ProgressCode pc) {
ReportProgress(pc);
lastProgressCode = pc;
switch (pc) {
@ -967,11 +964,11 @@ void MMU2::OnMMUProgressMsgChanged(ProgressCode pc){
}
}
void __attribute__((noinline)) MMU2::HelpUnloadToFinda(){
MoveE(- MMU2_RETRY_UNLOAD_TO_FINDA_LENGTH, MMU2_RETRY_UNLOAD_TO_FINDA_FEED_RATE);
void __attribute__((noinline)) MMU2::HelpUnloadToFinda() {
MoveE(-MMU2_RETRY_UNLOAD_TO_FINDA_LENGTH, MMU2_RETRY_UNLOAD_TO_FINDA_FEED_RATE);
}
void MMU2::OnMMUProgressMsgSame(ProgressCode pc){
void MMU2::OnMMUProgressMsgSame(ProgressCode pc) {
switch (pc) {
case ProgressCode::UnloadingToFinda:
if (unloadFilamentStarted && !planner_any_moves()) { // Only plan a move if there is no move ongoing

View File

@ -7,12 +7,13 @@
#ifdef __AVR__
#include "mmu2_protocol_logic.h"
typedef float feedRate_t;
#else
#include "protocol_logic.h"
#include "../../Marlin/src/core/macros.h"
#include "../../Marlin/src/core/types.h"
#include <atomic>
#include "protocol_logic.h"
#include "../../Marlin/src/core/macros.h"
#include "../../Marlin/src/core/types.h"
#include <atomic>
#endif
struct E_Step;
@ -43,25 +44,25 @@ public:
inline xState State() const { return state; }
inline bool Enabled()const { return State() == xState::Active; }
inline bool Enabled() const { return State() == xState::Active; }
/// Different levels of resetting the MMU
enum ResetForm : uint8_t {
Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself
ResetPin = 1, ///< trigger the reset pin of the MMU
Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself
ResetPin = 1, ///< trigger the reset pin of the MMU
CutThePower = 2 ///< power off and power on (that includes +5V and +24V power lines)
};
/// Saved print state on error.
enum SavedState: uint8_t {
None = 0, // No state saved.
enum SavedState : uint8_t {
None = 0, // No state saved.
ParkExtruder = 1, // The extruder was parked.
Cooldown = 2, // The extruder was allowed to cool.
Cooldown = 2, // The extruder was allowed to cool.
CooldownPending = 4,
};
/// Source of operation error
enum ErrorSource: uint8_t {
enum ErrorSource : uint8_t {
ErrorSourcePrinter = 0,
ErrorSourceMMU = 1,
ErrorSourceNone = 0xFF,
@ -150,9 +151,9 @@ public:
void Home(uint8_t mode);
/// @returns current state of FINDA (true=filament present, false=filament not present)
inline bool FindaDetectsFilament()const { return logic.FindaPressed(); }
inline bool FindaDetectsFilament() const { return logic.FindaPressed(); }
inline uint16_t TotalFailStatistics()const { return logic.FailStatistics(); }
inline uint16_t TotalFailStatistics() const { return logic.FailStatistics(); }
/// @returns Current error code
inline ErrorCode MMUCurrentErrorCode() const { return logic.Error(); }
@ -162,11 +163,11 @@ public:
/// @returns the version of the connected MMU FW.
/// In the future we'll return the trully detected FW version
Version GetMMUFWVersion()const {
if( State() == xState::Active ){
Version GetMMUFWVersion() const {
if (State() == xState::Active) {
return { logic.MmuFwVersionMajor(), logic.MmuFwVersionMinor(), logic.MmuFwVersionRevision() };
} else {
return { 0, 0, 0};
return { 0, 0, 0 };
}
}
@ -187,7 +188,7 @@ public:
/// Set toolchange counter to zero
inline void ClearToolChangeCounter() { toolchange_counter = 0; };
inline uint16_t TMCFailures()const { return tmcFailures; }
inline uint16_t TMCFailures() const { return tmcFailures; }
inline void IncrementTMCFailures() { ++tmcFailures; }
inline void ClearTMCFailures() { tmcFailures = 0; }
@ -296,8 +297,8 @@ private:
void HelpUnloadToFinda();
ProtocolLogic logic; ///< implementation of the protocol logic layer
uint8_t extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet
ProtocolLogic logic; ///< implementation of the protocol logic layer
uint8_t extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet
uint8_t tool_change_extruder; ///< only used for UI purposes
pos3d resume_position;

View File

@ -11,11 +11,11 @@ uint8_t PrusaErrorCodeIndex(uint16_t ec);
/// @returns pointer to a PROGMEM string representing the Title of the Prusa-Error-Codes error
/// @param i index of the error - obtained by calling ErrorCodeIndex
const char * PrusaErrorTitle(uint8_t i);
const char *PrusaErrorTitle(uint8_t i);
/// @returns pointer to a PROGMEM string representing the multi-page Description of the Prusa-Error-Codes error
/// @param i index of the error - obtained by calling ErrorCodeIndex
const char * PrusaErrorDesc(uint8_t i);
const char *PrusaErrorDesc(uint8_t i);
/// @returns the actual numerical value of the Prusa-Error-Codes error
/// @param i index of the error - obtained by calling ErrorCodeIndex
@ -27,10 +27,10 @@ uint8_t PrusaErrorButtons(uint8_t i);
/// @returns pointer to a PROGMEM string representing the Title of a button
/// @param i index of the error - obtained by calling PrusaErrorButtons + extracting low or high nibble from the Btns pair
const char * PrusaErrorButtonTitle(uint8_t bi);
const char *PrusaErrorButtonTitle(uint8_t bi);
/// @returns pointer to a PROGMEM string representing the "More" button
const char * PrusaErrorButtonMore();
const char *PrusaErrorButtonMore();
/// Sets the selected button for later pick-up by the MMU state machine.
/// Used to save the GUI selection/decoupling

View File

@ -8,8 +8,8 @@ namespace MMU2 {
/// Beware, the numeric codes are important and sent into the MMU
enum class FilamentState : uint_fast8_t {
NOT_PRESENT = 0, ///< filament sensor doesn't see the filament
AT_FSENSOR = 1, ///< filament detected by the filament sensor, but the nozzle has not detected the filament yet
IN_NOZZLE = 2, ///< filament detected by the filament sensor and also loaded in the nozzle
AT_FSENSOR = 1, ///< filament detected by the filament sensor, but the nozzle has not detected the filament yet
IN_NOZZLE = 2, ///< filament detected by the filament sensor and also loaded in the nozzle
UNAVAILABLE = 3 ///< sensor not available (likely not connected due broken cable)
};

View File

@ -20,18 +20,36 @@ void LogEchoEvent_P(const char *msg);
} // namespace
#define SERIAL_MMU2() { serialprintPGM(mmu2Magic); }
#define SERIAL_MMU2() \
{ serialprintPGM(mmu2Magic); }
#define MMU2_ECHO_MSGLN(S) do{ SERIAL_ECHO_START; SERIAL_MMU2(); SERIAL_ECHOLN(S); }while(0)
#define MMU2_ERROR_MSGLN(S) MMU2_ECHO_MSGLN(S) //!@todo Decide MMU2 errors on serial line
#define MMU2_ECHO_MSGRPGM(S) do{ SERIAL_ECHO_START; SERIAL_MMU2(); SERIAL_ECHORPGM(S); }while(0)
#define MMU2_ERROR_MSGRPGM(S) MMU2_ECHO_MSGRPGM(S) //!@todo Decide MMU2 errors on serial line
#define MMU2_ECHO_MSGLN(S) \
do { \
SERIAL_ECHO_START(); \
SERIAL_MMU2(); \
SERIAL_ECHOLN(S); \
} while (0)
#define MMU2_ERROR_MSGLN(S) MMU2_ECHO_MSGLN(S) //!@todo Decide MMU2 errors on serial line
#define MMU2_ECHO_MSGRPGM(S) \
do { \
SERIAL_ECHO_START(); \
SERIAL_MMU2(); \
SERIAL_ECHO(S); \
} while (0)
#define MMU2_ERROR_MSGRPGM(S) MMU2_ECHO_MSGRPGM(S) //!@todo Decide MMU2 errors on serial line
#define MMU2_ECHO_MSG(S) \
do { \
SERIAL_ECHO_START(); \
SERIAL_MMU2(); \
SERIAL_ECHO(S); \
} while (0)
#define MMU2_ERROR_MSG(S) MMU2_ECHO_MSG(S) //!@todo Decide MMU2 errors on serial line
#else // #ifndef UNITTEST
#define MMU2_ECHO_MSGLN(S) /* */
#define MMU2_ERROR_MSGLN(S) /* */
#define MMU2_ECHO_MSGRPGM(S) /* */
#define MMU2_ERROR_MSGRPGM(S) /* */
#define MMU2_ECHO_MSGLN(S) /* */
#define MMU2_ERROR_MSGLN(S) /* */
#define MMU2_ECHO_MSGRPGM(S) /* */
#define MMU2_ERROR_MSGRPGM(S) /* */
#endif // #ifndef UNITTEST

View File

@ -3,12 +3,12 @@
#include "mmu2_fsensor.h"
#ifdef __AVR__
// on MK3/S/+ we shuffle the timers a bit, thus "_millis" may not equal "millis"
#include "system_timer.h"
// on MK3/S/+ we shuffle the timers a bit, thus "_millis" may not equal "millis"
#include "system_timer.h"
#else
// irrelevant on Buddy FW, just keep "_millis" as "millis"
#include <wiring_time.h>
#define _millis millis
// irrelevant on Buddy FW, just keep "_millis" as "millis"
#include <wiring_time.h>
#define _millis millis
#endif
#include <string.h>
@ -18,13 +18,13 @@ namespace MMU2 {
static const uint8_t supportedMmuFWVersion[3] PROGMEM = { 2, 1, 6 };
const uint8_t ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = {
8, // FINDA state
8, // FINDA state
0x1b, // Selector slot
0x1c, // Idler slot
};
const uint8_t ProtocolLogic::regs16Addrs[ProtocolLogic::regs16Count] PROGMEM = {
4, // MMU errors - aka statistics
4, // MMU errors - aka statistics
0x1a, // Pulley position [mm]
};
@ -52,10 +52,10 @@ void ProtocolLogic::StartReading8bitRegisters() {
SendReadRegister(pgm_read_byte(regs8Addrs + regIndex), ScopeState::Reading8bitRegisters);
}
void ProtocolLogic::ProcessRead8bitRegister(){
void ProtocolLogic::ProcessRead8bitRegister() {
regs8[regIndex] = rsp.paramValue;
++regIndex;
if(regIndex >= regs8Count){
if (regIndex >= regs8Count) {
// proceed with reading 16bit registers
StartReading16bitRegisters();
} else {
@ -68,10 +68,10 @@ void ProtocolLogic::StartReading16bitRegisters() {
SendReadRegister(pgm_read_byte(regs16Addrs + regIndex), ScopeState::Reading16bitRegisters);
}
ProtocolLogic::ScopeState __attribute__((noinline)) ProtocolLogic::ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd){
ProtocolLogic::ScopeState __attribute__((noinline)) ProtocolLogic::ProcessRead16bitRegister(ProtocolLogic::ScopeState stateAtEnd) {
regs16[regIndex] = rsp.paramValue;
++regIndex;
if(regIndex >= regs16Count){
if (regIndex >= regs16Count) {
return stateAtEnd;
} else {
SendReadRegister(pgm_read_byte(regs16Addrs + regIndex), ScopeState::Reading16bitRegisters);
@ -84,9 +84,9 @@ void ProtocolLogic::StartWritingInitRegisters() {
SendWriteRegister(pgm_read_byte(initRegs8Addrs + regIndex), initRegs8[regIndex], ScopeState::WritingInitRegisters);
}
bool __attribute__((noinline)) ProtocolLogic::ProcessWritingInitRegister(){
bool __attribute__((noinline)) ProtocolLogic::ProcessWritingInitRegister() {
++regIndex;
if(regIndex >= initRegs8Count){
if (regIndex >= initRegs8Count) {
return true;
} else {
SendWriteRegister(pgm_read_byte(initRegs8Addrs + regIndex), initRegs8[regIndex], ScopeState::WritingInitRegisters);
@ -114,7 +114,7 @@ void ProtocolLogic::SendReadRegister(uint8_t index, ScopeState nextState) {
scopeState = nextState;
}
void ProtocolLogic::SendWriteRegister(uint8_t index, uint16_t value, ScopeState nextState){
void ProtocolLogic::SendWriteRegister(uint8_t index, uint16_t value, ScopeState nextState) {
SendWriteMsg(RequestMsg(RequestMsgCodes::Write, index, value));
scopeState = nextState;
}
@ -130,12 +130,12 @@ struct OldMMUFWDetector {
Matched };
/// @returns true when "ok\n" gets detected
State Detect(uint8_t c){
State Detect(uint8_t c) {
// consume old MMU FW's data if any -> avoid confusion of protocol decoder
if(ok == 0 && c == 'o'){
if (ok == 0 && c == 'o') {
++ok;
return State::MatchingPart;
} else if(ok == 1 && c == 'k'){
} else if (ok == 1 && c == 'k') {
++ok;
return State::Matched;
}
@ -162,16 +162,16 @@ StepStatus ProtocolLogic::ExpectingMessage() {
return MessageReady;
case DecodeStatus::NeedMoreData:
break;
case DecodeStatus::Error:{
case DecodeStatus::Error: {
// consume old MMU FW's data if any -> avoid confusion of protocol decoder
auto old = oldMMUh4x0r.Detect(c);
if( old == OldMMUFWDetector::State::Matched ){
if (old == OldMMUFWDetector::State::Matched) {
// Old MMU FW 1.0.6 detected. Firmwares are incompatible.
return VersionMismatch;
} else if( old == OldMMUFWDetector::State::MatchingPart ){
} else if (old == OldMMUFWDetector::State::MatchingPart) {
break;
}
}
}
[[fallthrough]]; // otherwise
default:
RecordUARTActivity(); // something has happened on the UART, update the timeout record
@ -195,7 +195,7 @@ void ProtocolLogic::SendMsg(RequestMsg rq) {
RecordUARTActivity();
}
void ProtocolLogic::SendWriteMsg(RequestMsg rq){
void ProtocolLogic::SendWriteMsg(RequestMsg rq) {
uint8_t txbuff[Protocol::MaxRequestSize()];
uint8_t len = Protocol::EncodeWriteRequest(rq.value, rq.value2, txbuff);
uart->write(txbuff, len);
@ -242,7 +242,7 @@ StepStatus ProtocolLogic::ProcessVersionResponse(uint8_t stage) {
}
StepStatus ProtocolLogic::ScopeStep() {
if ( ! ExpectsResponse() ) {
if (!ExpectsResponse()) {
// we are waiting for something
switch (currentScope) {
case Scope::DelayedRestart:
@ -296,7 +296,7 @@ StepStatus ProtocolLogic::StartSeqStep() {
}
return Processing;
case ScopeState::WritingInitRegisters:
if( ProcessWritingInitRegister() ){
if (ProcessWritingInitRegister()) {
SendAndUpdateFilamentSensor();
}
return Processing;
@ -354,7 +354,7 @@ StepStatus ProtocolLogic::ProcessCommandQueryResponse() {
case ResponseMsgParamCodes::Finished:
// We must check whether the "finished" is actually related to the command issued into the MMU
// It can also be an X0 F which means MMU just successfully restarted.
if( ReqMsg().code == rsp.request.code && ReqMsg().value == rsp.request.value ){
if (ReqMsg().code == rsp.request.code && ReqMsg().value == rsp.request.value) {
progressCode = ProgressCode::OK;
scopeState = ScopeState::Ready;
rq = RequestMsg(RequestMsgCodes::unknown, 0); // clear the successfully finished request
@ -449,7 +449,7 @@ StepStatus ProtocolLogic::IdleStep() {
StartReading8bitRegisters();
return ButtonPushed;
case ResponseMsgParamCodes::Finished:
if( ReqMsg().code != RequestMsgCodes::unknown ){
if (ReqMsg().code != RequestMsgCodes::unknown) {
// got reset while doing some other command - the originally issued command was interrupted!
// this must be solved by the upper layer, protocol logic doesn't have all the context (like unload before trying again)
IdleRestart();
@ -526,8 +526,7 @@ ProtocolLogic::ProtocolLogic(MMU2Serial *uart, uint8_t extraLoadDistance, uint8_
, lastFSensor((uint8_t)WhereIsFilament())
, regIndex(0)
, retryAttempts(MAX_RETRIES)
, inAutoRetry(false)
{
, inAutoRetry(false) {
// @@TODO currently, I don't see a way of writing the initialization better :(
// I'd like to write something like: initRegs8 { extraLoadDistance, pulleySlowFeedrate }
// avr-gcc seems to like such a syntax, ARM gcc doesn't
@ -583,11 +582,11 @@ void ProtocolLogic::Home(uint8_t mode) {
PlanGenericRequest(RequestMsg(RequestMsgCodes::Home, mode));
}
void ProtocolLogic::ReadRegister(uint8_t address){
void ProtocolLogic::ReadRegister(uint8_t address) {
PlanGenericRequest(RequestMsg(RequestMsgCodes::Read, address));
}
void ProtocolLogic::WriteRegister(uint8_t address, uint16_t data){
void ProtocolLogic::WriteRegister(uint8_t address, uint16_t data) {
PlanGenericRequest(RequestMsg(RequestMsgCodes::Write, address, data));
}
@ -599,23 +598,23 @@ void ProtocolLogic::PlanGenericRequest(RequestMsg rq) {
}
bool ProtocolLogic::ActivatePlannedRequest() {
switch(plannedRq.code){
switch (plannedRq.code) {
case RequestMsgCodes::Button:
// only issue the button to the MMU and do not restart the state machines
SendButton(plannedRq.value);
plannedRq = RequestMsg(RequestMsgCodes::unknown, 0);
return true;
case RequestMsgCodes::Read:
SendReadRegister(plannedRq.value, ScopeState::ReadRegisterSent );
SendReadRegister(plannedRq.value, ScopeState::ReadRegisterSent);
plannedRq = RequestMsg(RequestMsgCodes::unknown, 0);
return true;
case RequestMsgCodes::Write:
SendWriteRegister(plannedRq.value, plannedRq.value2, ScopeState::WriteRegisterSent );
SendWriteRegister(plannedRq.value, plannedRq.value2, ScopeState::WriteRegisterSent);
plannedRq = RequestMsg(RequestMsgCodes::unknown, 0);
return true;
case RequestMsgCodes::unknown:
return false;
default:// commands
default: // commands
currentScope = Scope::Command;
SetRequestMsg(plannedRq);
plannedRq = RequestMsg(RequestMsgCodes::unknown, 0);

View File

@ -1,5 +1,5 @@
#pragma once
constexpr inline int strlen_constexpr(const char* str){
constexpr inline int strlen_constexpr(const char *str) {
return *str ? 1 + strlen_constexpr(str + 1) : 0;
}