From 1cda696e143c253e42887a240fad47e36b3e52f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Sat, 5 Aug 2023 15:39:18 +0000 Subject: [PATCH] PFW-1530 Add Tune to Selector screen and more - Rename "Idler" to "Sensitivity" - Implement ReadRegisterInner() as a way to read register in blocking contexts such as manage_response() This allows us to show the current EEPROM value on the printer's LCD --- Firmware/mmu2.cpp | 24 ++++++++++++++ Firmware/mmu2.h | 13 ++++++++ Firmware/mmu2/errors_list.h | 2 +- Firmware/mmu2_error_converter.cpp | 2 +- Firmware/mmu2_reporting.cpp | 54 +++++++++++++++++++++++++------ 5 files changed, 84 insertions(+), 11 deletions(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index d66f0560c..c03ac5aed 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -80,6 +80,7 @@ void MMU2::StopKeepPowered() { void MMU2::Tune() { switch (lastErrorCode) { + case ErrorCode::HOMING_SELECTOR_FAILED: case ErrorCode::HOMING_IDLER_FAILED: { // Prompt a menu for different values @@ -147,6 +148,29 @@ bool MMU2::ReadRegister(uint8_t address) { logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function } while (!manage_response(false, false)); + // Update cached value + lastReadRegisterValue = logic.rsp.paramValue; + return true; +} + +bool MMU2::ReadRegisterInner(uint8_t address) { + if (!WaitForMMUReady()) + return false; + + // Plan a request for the register value at address + logic.ReadRegister(address); + + do { + // Maintain MMU communications + marlin_manage_inactivity(true); + mmu_loop_inner(false); + } while ( + logicStepLastStatus != StepStatus::Finished + && logic.rsp.request.value == address // If the MMU protocol is busy decoding another request, we must wait + ); + + // Update cached value + lastReadRegisterValue = logic.rsp.paramValue; return true; } diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 4488bb92a..8945f31a5 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -88,6 +88,12 @@ public: /// @returns true upon success bool ReadRegister(uint8_t address); + /// Variant of ReadRegister which runs in blocking context such as manage_response() + /// Be careful of using this as it is not recursion protected! + /// @param address Address of register in hexidecimal + /// @return true upon success + bool ReadRegisterInner(uint8_t address); + /// Write from a MMU register (See gcode M708) /// @param address Address of register in hexidecimal /// @param data Data to write to register @@ -194,6 +200,12 @@ public: inline void IncrementTMCFailures() { ++tmcFailures; } inline void ClearTMCFailures() { tmcFailures = 0; } + /// Retrieve cached value parsed from ReadRegister() + /// or using M707 + inline uint16_t GetLastReadRegisterValue() const { + return lastReadRegisterValue; + }; + private: /// Perform software self-reset of the MMU (sends an X0 command) void ResetX0(); @@ -301,6 +313,7 @@ private: ErrorCode lastErrorCode = ErrorCode::MMU_NOT_RESPONDING; ErrorSource lastErrorSource = ErrorSource::ErrorSourceNone; Buttons lastButton = Buttons::NoButton; + uint16_t lastReadRegisterValue = 0; StepStatus logicStepLastStatus; diff --git a/Firmware/mmu2/errors_list.h b/Firmware/mmu2/errors_list.h index cfe7d45cf..d1f9b0b3b 100644 --- a/Firmware/mmu2/errors_list.h +++ b/Firmware/mmu2/errors_list.h @@ -380,7 +380,7 @@ static const uint8_t errorButtons[] PROGMEM = { Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//FSENSOR_TOO_EARLY Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//INSPECT_FINDA Btns(ButtonOperations::Continue, ButtonOperations::NoOperation),//LOAD_TO_EXTRUDER_FAILED - Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//SELECTOR_CANNOT_HOME + Btns(ButtonOperations::Retry, ButtonOperations::Tune),//SELECTOR_CANNOT_HOME Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//SELECTOR_CANNOT_MOVE Btns(ButtonOperations::Retry, ButtonOperations::Tune),//IDLER_CANNOT_HOME Btns(ButtonOperations::Retry, ButtonOperations::NoOperation),//IDLER_CANNOT_MOVE diff --git a/Firmware/mmu2_error_converter.cpp b/Firmware/mmu2_error_converter.cpp index 02226797d..44b265331 100644 --- a/Firmware/mmu2_error_converter.cpp +++ b/Firmware/mmu2_error_converter.cpp @@ -205,7 +205,6 @@ Buttons ButtonAvailable(uint16_t ec) { case ERR_MECHANICAL_FSENSOR_FILAMENT_STUCK: case ERR_MECHANICAL_FSENSOR_TOO_EARLY: case ERR_MECHANICAL_INSPECT_FINDA: - case ERR_MECHANICAL_SELECTOR_CANNOT_HOME: case ERR_MECHANICAL_SELECTOR_CANNOT_MOVE: case ERR_MECHANICAL_IDLER_CANNOT_MOVE: case ERR_MECHANICAL_PULLEY_CANNOT_MOVE: @@ -218,6 +217,7 @@ Buttons ButtonAvailable(uint16_t ec) { break; } break; + case ERR_MECHANICAL_SELECTOR_CANNOT_HOME: case ERR_MECHANICAL_IDLER_CANNOT_HOME: switch (buttonSelectedOperation) { // may be allow move selector right and left in the future diff --git a/Firmware/mmu2_reporting.cpp b/Firmware/mmu2_reporting.cpp index 3a55c6547..757664e72 100644 --- a/Firmware/mmu2_reporting.cpp +++ b/Firmware/mmu2_reporting.cpp @@ -1,3 +1,4 @@ +#include #include "mmu2.h" #include "mmu2_log.h" #include "mmu2_reporting.h" @@ -360,24 +361,59 @@ void ScreenClear(){ lcd_clear(); } -// These are global while testing this concept -uint8_t stallGuardValue = 6; // default bool tuningDone = false; +struct TuneItem { + uint8_t address; + uint8_t minValue; + uint8_t maxValue; +} __attribute__((packed)); + +static const TuneItem TuneItems[] PROGMEM = { + { (uint8_t)Register::Selector_sg_thrs_R, 1, 4}, + { (uint8_t)Register::Idler_sg_thrs_R, 4, 7}, +}; + +static_assert(sizeof(TuneItems)/sizeof(TuneItem) == 2); + +typedef struct +{ + menu_data_edit_t reserved; //13 bytes reserved for number editing functions + int8_t status; // 1 byte + uint8_t currentValue; // 1 byte + TuneItem item; // 3 bytes +} _menu_tune_data_t; + +static_assert(sizeof(_menu_tune_data_t) == 18); +static_assert(sizeof(menu_data)>= sizeof(_menu_tune_data_t),"_menu_tune_data_t doesn't fit into menu_data"); + void tuneIdlerStallguardThresholdMenu() { - constexpr uint8_t maxStallguardThreshold = 7; - constexpr uint8_t minStallguardThreshold = 4; + static constexpr _menu_tune_data_t * const _md = (_menu_tune_data_t*)&(menu_data[0]); + if (_md->status == 0) + { + _md->status = 1; // Menu entered for the first time + lcd_timeoutToStatus.stop(); // Do not timeout the screen + + // Fetch the TuneItem from PROGMEM + const uint8_t offset = (mmu2.MMUCurrentErrorCode() == ErrorCode::HOMING_IDLER_FAILED) ? 1 : 0; + memcpy_P(&(_md->item), &TuneItems[offset], sizeof(TuneItem)); + + // Fetch the value which is currently in MMU EEPROM + mmu2.ReadRegisterInner((uint8_t)_md->item.address); + _md->currentValue = mmu2.GetLastReadRegisterValue(); + } + MENU_BEGIN(); ON_MENU_LEAVE( tuningDone = true; - mmu2.WriteRegister(0x19, (uint16_t)stallGuardValue); + mmu2.WriteRegister(_md->item.address, (uint16_t)_md->currentValue); ); MENU_ITEM_BACK_P(_i("Done")); MENU_ITEM_EDIT_int3_P( - _i("Idler"), - &stallGuardValue, - minStallguardThreshold, - maxStallguardThreshold + _i("Sensitivity"), + &_md->currentValue, + _md->item.minValue, + _md->item.maxValue ); MENU_END(); }