Browse Source

Merge pull request #1525 from mkbel/improve_mmu_load_failed_2

Improve mmu load failed 2
PavelSindler 6 years ago
parent
commit
fec64a9d5e
4 changed files with 230 additions and 186 deletions
  1. 3 3
      Firmware/Marlin_main.cpp
  2. 190 160
      Firmware/mmu.cpp
  3. 35 21
      Firmware/mmu.h
  4. 2 2
      Firmware/ultralcd.cpp

+ 3 - 3
Firmware/Marlin_main.cpp

@@ -3037,7 +3037,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float
                 lcd_set_cursor(0, 2);
                 lcd_puts_P(_T(MSG_PLEASE_WAIT));
 
-                mmu_command(MMU_CMD_R0);
+                mmu_command(MmuCmd::R0);
                 manage_response(false, false);
             }
         }
@@ -6933,7 +6933,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 				return; //dont execute the same T-code twice in a row
 			}
 			st_synchronize();
-			mmu_command(MMU_CMD_T0 + tmp_extruder);
+			mmu_command(MmuCmd::T0 + tmp_extruder);
 			manage_response(true, true, MMU_TCODE_MOVE);
 		}
 	  }
@@ -6974,7 +6974,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
                   printf_P(PSTR("Duplicit T-code ignored.\n"));
                   return; //dont execute the same T-code twice in a row
               }
-              mmu_command(MMU_CMD_T0 + tmp_extruder);
+              mmu_command(MmuCmd::T0 + tmp_extruder);
 
 			  manage_response(true, true, MMU_TCODE_MOVE);
 			  mmu_continue_loading();

+ 190 - 160
Firmware/mmu.cpp

@@ -30,13 +30,31 @@
 #define MMU_RST_PIN 76
 #endif //MMU_HWRESET
 
+namespace
+{
+    enum class S : uint_least8_t
+    {
+        WaitStealthMode,
+        GetFindaInit,
+        GetBuildNr,
+        GetVersion,
+        Init,
+        Disabled,
+        Idle,
+        GetFinda,
+        WaitCmd, //!< wait for command response
+        Pause,
+        GetDrvError, //!< get power failures count
+    };
+}
+
 bool mmu_enabled = false;
 bool mmu_ready = false;
 bool mmu_fil_loaded = false; //if true: blocks execution of duplicit T-codes
 
-static int8_t mmu_state = 0;
+static S mmu_state = S::Disabled;
 
-uint8_t mmu_cmd = 0;
+MmuCmd mmu_cmd = MmuCmd::None;
 
 //idler ir sensor
 uint8_t mmu_idl_sens = 0;
@@ -57,10 +75,27 @@ int16_t mmu_buildnr = -1;
 uint32_t mmu_last_request = 0;
 uint32_t mmu_last_response = 0;
 
-uint8_t mmu_last_cmd = 0;
+MmuCmd mmu_last_cmd = MmuCmd::None;
 uint16_t mmu_power_failures = 0;
 
 
+#ifdef MMU_DEBUG
+static const auto DEBUG_PUTS_P = puts_P;
+static const auto DEBUG_PRINTF_P = printf_P;
+#else //MMU_DEBUG
+#define DEBUG_PUTS_P(str)
+#define DEBUG_PRINTF_P( __fmt, ... )
+#endif //MMU_DEBUG
+
+#if defined(MMU_FINDA_DEBUG) && defined(MMU_DEBUG)
+static const auto FDEBUG_PUTS_P = puts_P;
+static const auto FDEBUG_PRINTF_P = printf_P;
+#else
+#define FDEBUG_PUTS_P(str)
+#define FDEBUG_PRINTF_P( __fmt, ... )
+#endif //defined(MMU_FINDA_DEBUG) && defined(MMU_DEBUG)
+
+
 //clear rx buffer
 void mmu_clr_rx_buf(void)
 {
@@ -114,12 +149,11 @@ void mmu_init(void)
 	uart2_init();                              //init uart2
 	_delay_ms(10);                             //wait 10ms for sure
 	mmu_reset();                               //reset mmu (HW or SW), do not wait for response
-	mmu_state = -1;
+	mmu_state = S::Init;
 	PIN_INP(IR_SENSOR_PIN); //input mode
 	PIN_SET(IR_SENSOR_PIN); //pullup
 }
 
-
 //if IR_SENSOR defined, always returns true
 //otherwise check for ir sensor and returns true if idler IR sensor was detected, otherwise returns false
 bool check_for_ir_sensor() 
@@ -151,181 +185,154 @@ bool check_for_ir_sensor()
 void mmu_loop(void)
 {
 	static uint8_t mmu_attempt_nr = 0;
-	int filament = 0;
 //	printf_P(PSTR("MMU loop, state=%d\n"), mmu_state);
 	switch (mmu_state)
 	{
-	case 0:
+	case S::Disabled:
 		return;
-	case -1:
+	case S::Init:
 		if (mmu_rx_start() > 0)
 		{
-#ifdef MMU_DEBUG
-			puts_P(PSTR("MMU => 'start'"));
-			puts_P(PSTR("MMU <= 'S1'"));
-#endif //MMU_DEBUG
+		    DEBUG_PUTS_P(PSTR("MMU => 'start'"));
+		    DEBUG_PUTS_P(PSTR("MMU <= 'S1'"));
 		    mmu_puts_P(PSTR("S1\n")); //send 'read version' request
-			mmu_state = -2;
+			mmu_state = S::GetVersion;
 		}
 		else if (_millis() > 30000) //30sec after reset disable mmu
 		{
 			puts_P(PSTR("MMU not responding - DISABLED"));
-			mmu_state = 0;
+			mmu_state = S::Disabled;
 		}
 		return;
-	case -2:
+	case S::GetVersion:
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%u"), &mmu_version); //scan version from buffer
-#ifdef MMU_DEBUG
-			printf_P(PSTR("MMU => '%dok'\n"), mmu_version);
-			puts_P(PSTR("MMU <= 'S2'"));
-#endif //MMU_DEBUG
+			DEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_version);
+			DEBUG_PUTS_P(PSTR("MMU <= 'S2'"));
 			mmu_puts_P(PSTR("S2\n")); //send 'read buildnr' request
-			mmu_state = -3;
+			mmu_state = S::GetBuildNr;
 		}
 		return;
-	case -3:
+	case S::GetBuildNr:
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%u"), &mmu_buildnr); //scan buildnr from buffer
-#ifdef MMU_DEBUG
-			printf_P(PSTR("MMU => '%dok'\n"), mmu_buildnr);
-#endif //MMU_DEBUG
+			DEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_buildnr);
 			bool version_valid = mmu_check_version();
 			if (!version_valid) mmu_show_warning();
 			else puts_P(PSTR("MMU version valid"));
 
 			if ((PRINTER_TYPE == PRINTER_MK3) || (PRINTER_TYPE == PRINTER_MK3_SNMM))
 			{
-#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG
-				puts_P(PSTR("MMU <= 'P0'"));
-#endif //MMU_DEBUG && MMU_FINDA_DEBUG
+				FDEBUG_PUTS_P(PSTR("MMU <= 'P0'"));
 				mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
-				mmu_state = -4;
+				mmu_state = S::GetFindaInit;
 			}
 			else
 			{
-#ifdef MMU_DEBUG
-				puts_P(PSTR("MMU <= 'M1'"));
-#endif //MMU_DEBUG
+				DEBUG_PUTS_P(PSTR("MMU <= 'M1'"));
 				mmu_puts_P(PSTR("M1\n")); //set mmu mode to stealth
-				mmu_state = -5;
+				mmu_state = S::WaitStealthMode;
 			}
 
 		}
 		return;
-	case -5:
+	case S::WaitStealthMode:
 		if (mmu_rx_ok() > 0)
 		{
-#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG
-			puts_P(PSTR("MMU <= 'P0'"));
-#endif //MMU_DEBUG && MMU_FINDA_DEBUG
+			FDEBUG_PUTS_P(PSTR("MMU <= 'P0'"));
 		    mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
-			mmu_state = -4;
+			mmu_state = S::GetFindaInit;
 		}
 		return;
-	case -4:
+	case S::GetFindaInit:
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
-#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG 
-			printf_P(PSTR("MMU => '%dok'\n"), mmu_finda);
-#endif //MMU_DEBUG && MMU_FINDA_DEBUG
+			FDEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_finda);
 			puts_P(PSTR("MMU - ENABLED"));
 			mmu_enabled = true;
-			mmu_state = 1;
+			mmu_state = S::Idle;
 		}
 		return;
-	case 1:
-		if (mmu_cmd) //command request ?
+	case S::Idle:
+		if (mmu_cmd != MmuCmd::None) //command request ?
 		{
-			if ((mmu_cmd >= MMU_CMD_T0) && (mmu_cmd <= MMU_CMD_T4))
+			if ((mmu_cmd >= MmuCmd::T0) && (mmu_cmd <= MmuCmd::T4))
 			{
-				filament = mmu_cmd - MMU_CMD_T0;
-#ifdef MMU_DEBUG
-				printf_P(PSTR("MMU <= 'T%d'\n"), filament);
-#endif //MMU_DEBUG
+				const uint8_t filament = mmu_cmd - MmuCmd::T0;
+				DEBUG_PRINTF_P(PSTR("MMU <= 'T%d'\n"), filament);
 				mmu_printf_P(PSTR("T%d\n"), filament);
-				mmu_state = 3; // wait for response
+				mmu_state = S::WaitCmd; // wait for response
 				mmu_fil_loaded = true;
 				mmu_idl_sens = 1;
 			}
-			else if ((mmu_cmd >= MMU_CMD_L0) && (mmu_cmd <= MMU_CMD_L4))
+			else if ((mmu_cmd >= MmuCmd::L0) && (mmu_cmd <= MmuCmd::L4))
 			{
-			    filament = mmu_cmd - MMU_CMD_L0;
-#ifdef MMU_DEBUG
-			    printf_P(PSTR("MMU <= 'L%d'\n"), filament);
-#endif //MMU_DEBUG
+			    const uint8_t filament = mmu_cmd - MmuCmd::L0;
+			    DEBUG_PRINTF_P(PSTR("MMU <= 'L%d'\n"), filament);
 			    mmu_printf_P(PSTR("L%d\n"), filament);
-			    mmu_state = 3; // wait for response
+			    mmu_state = S::WaitCmd; // wait for response
 			}
-			else if (mmu_cmd == MMU_CMD_C0)
+			else if (mmu_cmd == MmuCmd::C0)
 			{
-#ifdef MMU_DEBUG
-				printf_P(PSTR("MMU <= 'C0'\n"));
-#endif //MMU_DEBUG
+			    DEBUG_PRINTF_P(PSTR("MMU <= 'C0'\n"));
 				mmu_puts_P(PSTR("C0\n")); //send 'continue loading'
-				mmu_state = 3;
+				mmu_state = S::WaitCmd;
 				mmu_idl_sens = 1;
 			}
-			else if (mmu_cmd == MMU_CMD_U0)
+			else if (mmu_cmd == MmuCmd::U0)
 			{
-#ifdef MMU_DEBUG
-				printf_P(PSTR("MMU <= 'U0'\n"));
-#endif //MMU_DEBUG
+			    DEBUG_PRINTF_P(PSTR("MMU <= 'U0'\n"));
 				mmu_puts_P(PSTR("U0\n")); //send 'unload current filament'
 				mmu_fil_loaded = false;
-				mmu_state = 3;
+				mmu_state = S::WaitCmd;
 			}
-			else if ((mmu_cmd >= MMU_CMD_E0) && (mmu_cmd <= MMU_CMD_E4))
+			else if ((mmu_cmd >= MmuCmd::E0) && (mmu_cmd <= MmuCmd::E4))
 			{
-				int filament = mmu_cmd - MMU_CMD_E0;
-#ifdef MMU_DEBUG				
-				printf_P(PSTR("MMU <= 'E%d'\n"), filament);
-#endif //MMU_DEBUG
+			    const uint8_t filament = mmu_cmd - MmuCmd::E0;
+				DEBUG_PRINTF_P(PSTR("MMU <= 'E%d'\n"), filament);
 				mmu_printf_P(PSTR("E%d\n"), filament); //send eject filament
 				mmu_fil_loaded = false;
-				mmu_state = 3; // wait for response
+				mmu_state = S::WaitCmd;
 			}
-			else if (mmu_cmd == MMU_CMD_R0)
+			else if (mmu_cmd == MmuCmd::R0)
 			{
-#ifdef MMU_DEBUG
-				printf_P(PSTR("MMU <= 'R0'\n"));
-#endif //MMU_DEBUG
+			    DEBUG_PRINTF_P(PSTR("MMU <= 'R0'\n"));
 				mmu_puts_P(PSTR("R0\n")); //send recover after eject
-				mmu_state = 3; // wait for response
+				mmu_state = S::WaitCmd;
 			}
-			else if (mmu_cmd == MMU_CMD_S3)
+			else if (mmu_cmd == MmuCmd::S3)
 			{
-#ifdef MMU_DEBUG
-				printf_P(PSTR("MMU <= 'S3'\n"));
-#endif //MMU_DEBUG
+			    DEBUG_PRINTF_P(PSTR("MMU <= 'S3'\n"));
 				mmu_puts_P(PSTR("S3\n")); //send power failures request
-				mmu_state = 4; // power failures response
+				mmu_state = S::GetDrvError;
+			}
+			else if (mmu_cmd == MmuCmd::W0)
+			{
+			    DEBUG_PRINTF_P(PSTR("MMU <= 'W0'\n"));
+			    mmu_puts_P(PSTR("W0\n"));
+			    mmu_state = S::Pause;
 			}
 			mmu_last_cmd = mmu_cmd;
-			mmu_cmd = 0;
+			mmu_cmd = MmuCmd::None;
 		}
 		else if ((mmu_last_response + 300) < _millis()) //request every 300ms
 		{
 #ifndef IR_SENSOR
 			if(check_for_ir_sensor()) ir_sensor_detected = true;
 #endif //IR_SENSOR not defined
-#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG
-			puts_P(PSTR("MMU <= 'P0'"));
-#endif //MMU_DEBUG && MMU_FINDA_DEBUG
+			FDEBUG_PUTS_P(PSTR("MMU <= 'P0'"));
 		    mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
-			mmu_state = 2;
+			mmu_state = S::GetFinda;
 		}
 		return;
-	case 2: //response to command P0
+	case S::GetFinda: //response to command P0
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
-#if defined MMU_DEBUG && MMU_FINDA_DEBUG
-			printf_P(PSTR("MMU => '%dok'\n"), mmu_finda);
-#endif //MMU_DEBUG && MMU_FINDA_DEBUG
+			FDEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_finda);
 			//printf_P(PSTR("Eact: %d\n"), int(e_active()));
 			if (!mmu_finda && CHECK_FSENSOR && fsensor_enabled) {
 				fsensor_stop_and_save_print();
@@ -340,23 +347,21 @@ void mmu_loop(void)
 				    enquecommand_front_P(PSTR("M600")); //save print and run M600 command
 				}
 			}
-			mmu_state = 1;
-			if (mmu_cmd == 0)
+			mmu_state = S::Idle;
+			if (mmu_cmd == MmuCmd::None)
 				mmu_ready = true;
 		}
 		else if ((mmu_last_request + MMU_P0_TIMEOUT) < _millis())
 		{ //resend request after timeout (30s)
-			mmu_state = 1;
+			mmu_state = S::Idle;
 		}
 		return;
-	case 3: //response to mmu commands
+	case S::WaitCmd: //response to mmu commands
         if (mmu_idl_sens)
         {
             if (PIN_GET(IR_SENSOR_PIN) == 0 && mmu_loading_flag)
             {
-#ifdef MMU_DEBUG
-                printf_P(PSTR("MMU <= 'A'\n"));
-#endif //MMU_DEBUG  
+                DEBUG_PRINTF_P(PSTR("MMU <= 'A'\n"));
                 mmu_puts_P(PSTR("A\n")); //send 'abort' request
                 mmu_idl_sens = 0;
                 //printf_P(PSTR("MMU IDLER_SENSOR = 0 - ABORT\n"));
@@ -366,47 +371,56 @@ void mmu_loop(void)
         }
 		if (mmu_rx_ok() > 0)
 		{
-#ifdef MMU_DEBUG
-			printf_P(PSTR("MMU => 'ok'\n"));
-#endif //MMU_DEBUG
+		    DEBUG_PRINTF_P(PSTR("MMU => 'ok'\n"));
 			mmu_attempt_nr = 0;
-			mmu_last_cmd = 0;
+			mmu_last_cmd = MmuCmd::None;
 			mmu_ready = true;
-			mmu_state = 1;
+			mmu_state = S::Idle;
 		}
 		else if ((mmu_last_request + MMU_CMD_TIMEOUT) < _millis())
 		{ //resend request after timeout (5 min)
-			if (mmu_last_cmd)
+			if (mmu_last_cmd >= MmuCmd::T0 && mmu_last_cmd <= MmuCmd::T4)
 			{
 				if (mmu_attempt_nr++ < MMU_MAX_RESEND_ATTEMPTS) {
-#ifdef MMU_DEBUG
-					printf_P(PSTR("MMU retry attempt nr. %d\n"), mmu_attempt_nr - 1);
-#endif //MMU_DEBUG
+				    DEBUG_PRINTF_P(PSTR("MMU retry attempt nr. %d\n"), mmu_attempt_nr - 1);
 					mmu_cmd = mmu_last_cmd;
 				}
 				else {
-					mmu_cmd = 0;
-					mmu_last_cmd = 0; //check
+					mmu_cmd = MmuCmd::None;
+					mmu_last_cmd = MmuCmd::None; //check
 					mmu_attempt_nr = 0;
 				}
 			}
-			mmu_state = 1;
+			mmu_state = S::Idle;
 		}
 		return;
-	case 4:
+	case S::Pause:
+        if (mmu_rx_ok() > 0)
+        {
+            DEBUG_PRINTF_P(PSTR("MMU => 'ok', resume print\n"));
+            mmu_attempt_nr = 0;
+            mmu_last_cmd = MmuCmd::None;
+            mmu_ready = true;
+            mmu_state = S::Idle;
+            lcd_resume_print();
+        }
+        if (mmu_cmd != MmuCmd::None)
+        {
+            mmu_state = S::Idle;
+        }
+	    return;
+	case S::GetDrvError:
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%d"), &mmu_power_failures); //scan power failures
-#ifdef MMU_DEBUG
-			printf_P(PSTR("MMU => 'ok'\n"));
-#endif //MMU_DEBUG
-			mmu_last_cmd = 0;
+			DEBUG_PRINTF_P(PSTR("MMU => 'ok'\n"));
+			mmu_last_cmd = MmuCmd::None;
 			mmu_ready = true;
-			mmu_state = 1;
+			mmu_state = S::Idle;
 		}
 		else if ((mmu_last_request + MMU_CMD_TIMEOUT) < _millis())
 		{ //resend request after timeout (5 min)
-			mmu_state = 1;
+			mmu_state = S::Idle;
 		}
 	}
 }
@@ -437,20 +451,20 @@ int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament)
 //! Call manage_response() after enqueuing to process command.
 //! If T command is enqueued, it disables current for extruder motor if TMC2130 driver present.
 //! If T or L command is enqueued, it marks filament loaded in AutoDeplete module.
-void mmu_command(uint8_t cmd)
+void mmu_command(MmuCmd cmd)
 {
-	if ((cmd >= MMU_CMD_T0) && (cmd <= MMU_CMD_T4))
+	if ((cmd >= MmuCmd::T0) && (cmd <= MmuCmd::T4))
 	{
 		//disable extruder motor
 #ifdef TMC2130
 		tmc2130_set_pwr(E_AXIS, 0);
 #endif //TMC2130
 		//printf_P(PSTR("E-axis disabled\n"));
-		ad_markLoaded(cmd - MMU_CMD_T0);
+		ad_markLoaded(cmd - MmuCmd::T0);
 	}
-    if ((cmd >= MMU_CMD_L0) && (cmd <= MMU_CMD_L4))
+    if ((cmd >= MmuCmd::L0) && (cmd <= MmuCmd::L4))
     {
-        ad_markLoaded(cmd - MMU_CMD_L0);
+        ad_markLoaded(cmd - MmuCmd::L0);
     }
 
 	mmu_cmd = cmd;
@@ -495,14 +509,14 @@ bool mmu_get_response(uint8_t move)
 
 	printf_P(PSTR("mmu_get_response - begin move:%d\n"), move);
 	KEEPALIVE_STATE(IN_PROCESS);
-	while (mmu_cmd != 0)
+	while (mmu_cmd != MmuCmd::None)
 	{
 		delay_keep_alive(100);
 	}
 
 	while (!mmu_ready)
 	{
-		if ((mmu_state != 3) && (mmu_last_cmd == 0))
+		if ((mmu_state != S::WaitCmd) && (mmu_last_cmd == MmuCmd::None))
 			break;
 
 		switch (move) {
@@ -794,7 +808,7 @@ void mmu_M600_load_filament(bool automatic)
 
 //		  printf_P(PSTR("T code: %d \n"), tmp_extruder);
 //		  mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
-		  mmu_command(MMU_CMD_T0 + tmp_extruder);
+		  mmu_command(MmuCmd::T0 + tmp_extruder);
 
 		  manage_response(false, true, MMU_LOAD_MOVE);
 		  mmu_continue_loading();
@@ -885,8 +899,8 @@ void display_loading()
 void extr_adj(int extruder) //loading filament for SNMM
 {
 #ifndef SNMM
-    uint8_t cmd = MMU_CMD_L0 + extruder;
-    if (cmd > MMU_CMD_L4)
+    MmuCmd cmd = MmuCmd::L0 + extruder;
+    if (cmd > MmuCmd::L4)
     {
         printf_P(PSTR("Filament out of range %d \n"),extruder);
         return;
@@ -1006,7 +1020,7 @@ void extr_unload()
 
 		mmu_filament_ramming();
 
-		mmu_command(MMU_CMD_U0);
+		mmu_command(MmuCmd::U0);
 		// get response
 		manage_response(false, true, MMU_UNLOAD_MOVE);
 
@@ -1303,7 +1317,7 @@ void lcd_mmu_load_to_nozzle(uint8_t filament_nr)
 	lcd_set_cursor(0, 1); lcd_puts_P(_T(MSG_LOADING_FILAMENT));
 	lcd_print(" ");
 	lcd_print(tmp_extruder + 1);
-	mmu_command(MMU_CMD_T0 + tmp_extruder);
+	mmu_command(MmuCmd::T0 + tmp_extruder);
 	manage_response(true, true, MMU_TCODE_MOVE);
 	mmu_continue_loading();
 	mmu_extruder = tmp_extruder; //filament change is finished
@@ -1340,12 +1354,12 @@ void mmu_eject_filament(uint8_t filament, bool recover)
                 current_position[E_AXIS] -= 80;
                 plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2500 / 60, active_extruder);
                 st_synchronize();
-                mmu_command(MMU_CMD_E0 + filament);
+                mmu_command(MmuCmd::E0 + filament);
                 manage_response(false, false, MMU_UNLOAD_MOVE);
                 if (recover)
                 {
                     lcd_show_fullscreen_message_and_wait_P(_i("Please remove filament and then press the knob."));
-                    mmu_command(MMU_CMD_R0);
+                    mmu_command(MmuCmd::R0);
                     manage_response(false, false);
                 }
 
@@ -1362,46 +1376,62 @@ void mmu_eject_filament(uint8_t filament, bool recover)
 	}
 }
 
+static void load_more()
+{
+    for (uint8_t i = 0; i < MMU_IDLER_SENSOR_ATTEMPTS_NR; i++)
+    {
+        if (PIN_GET(IR_SENSOR_PIN) == 0) return;
+        DEBUG_PRINTF_P(PSTR("Additional load attempt nr. %d\n"), i);
+        mmu_command(MmuCmd::C0);
+        manage_response(true, true, MMU_LOAD_MOVE);
+    }
+}
+
 void mmu_continue_loading() 
 {
+	if (ir_sensor_detected)
+	{
+	    load_more();
 
-	if (ir_sensor_detected) {
-		for (uint8_t i = 0; i < MMU_IDLER_SENSOR_ATTEMPTS_NR; i++) {
-			if (PIN_GET(IR_SENSOR_PIN) == 0) return;
-#ifdef MMU_DEBUG
-			printf_P(PSTR("Additional load attempt nr. %d\n"), i);
-#endif // MMU_DEBUG
-			mmu_command(MMU_CMD_C0);
-			manage_response(true, true, MMU_LOAD_MOVE);
-		}
 		if (PIN_GET(IR_SENSOR_PIN) != 0) {
 			uint8_t mmu_load_fail = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL);
 			uint16_t mmu_load_fail_tot = eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT);
 			if(mmu_load_fail < 255) eeprom_update_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL, mmu_load_fail + 1);
 			if(mmu_load_fail_tot < 65535) eeprom_update_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT, mmu_load_fail_tot + 1);
-			char cmd[3];
-			//pause print, show error message and then repeat last T-code
-			stop_and_save_print_to_ram(0, 0);
-
-			//lift z
-			current_position[Z_AXIS] += Z_PAUSE_LIFT;
-			if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
-			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
-			st_synchronize();
 
-			//Move XY to side
-			current_position[X_AXIS] = X_PAUSE_POS;
-			current_position[Y_AXIS] = Y_PAUSE_POS;
-			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
-			st_synchronize();
-			//set nozzle target temperature to 0
-			setAllTargetHotends(0);
-			lcd_setstatuspgm(_i("MMU load failed     "));////MSG_RECOVERING_PRINT c=20 r=1
-			mmu_fil_loaded = false; //so we can retry same T-code again
-			isPrintPaused = true;
+            mmu_command(MmuCmd::T0 + tmp_extruder);
+            manage_response(true, true, MMU_TCODE_MOVE);
+            load_more();
+
+            if (PIN_GET(IR_SENSOR_PIN) != 0)
+            {
+                //pause print, show error message and then repeat last T-code
+                stop_and_save_print_to_ram(0, 0);
+
+                //lift z
+                current_position[Z_AXIS] += Z_PAUSE_LIFT;
+                if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
+                plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
+                st_synchronize();
+
+                //Move XY to side
+                current_position[X_AXIS] = X_PAUSE_POS;
+                current_position[Y_AXIS] = Y_PAUSE_POS;
+                plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
+                st_synchronize();
+
+                mmu_command(MmuCmd::U0);
+                manage_response(false, true, MMU_UNLOAD_MOVE);
+
+                setAllTargetHotends(0);
+                lcd_setstatuspgm(_i("MMU load failed     "));////MSG_RECOVERING_PRINT c=20 r=1
+                mmu_fil_loaded = false; //so we can retry same T-code again
+                isPrintPaused = true;
+                mmu_command(MmuCmd::W0);
+            }
 		}
 	}
 	else { //mmu_ir_sensor_detected == false
-		mmu_command(MMU_CMD_C0);
+		mmu_command(MmuCmd::C0);
 	}
 }

+ 35 - 21
Firmware/mmu.h

@@ -32,26 +32,40 @@ extern uint16_t mmu_power_failures;
 #define MMU_LOAD_FEEDRATE 19.02f //mm/s
 #define MMU_LOAD_TIME_MS 2000 //should be fine tuned to load time for shortest allowed PTFE tubing and maximum loading speed
 
-#define MMU_CMD_NONE 0
-#define MMU_CMD_T0   0x10
-#define MMU_CMD_T1   0x11
-#define MMU_CMD_T2   0x12
-#define MMU_CMD_T3   0x13
-#define MMU_CMD_T4   0x14
-#define MMU_CMD_L0   0x20
-#define MMU_CMD_L1   0x21
-#define MMU_CMD_L2   0x22
-#define MMU_CMD_L3   0x23
-#define MMU_CMD_L4   0x24
-#define MMU_CMD_C0   0x30
-#define MMU_CMD_U0   0x40
-#define MMU_CMD_E0   0x50
-#define MMU_CMD_E1   0x51
-#define MMU_CMD_E2   0x52
-#define MMU_CMD_E3   0x53
-#define MMU_CMD_E4   0x54
-#define MMU_CMD_R0   0x60
-#define MMU_CMD_S3	 0x73
+enum class MmuCmd : uint_least8_t
+{
+    None,
+    T0,
+    T1,
+    T2,
+    T3,
+    T4,
+    L0,
+    L1,
+    L2,
+    L3,
+    L4,
+    C0,
+    U0,
+    E0,
+    E1,
+    E2,
+    E3,
+    E4,
+    R0,
+    S3,
+    W0,
+};
+
+inline MmuCmd operator+ (MmuCmd cmd, uint8_t filament)
+{
+    return static_cast<MmuCmd>(static_cast<uint8_t>(cmd) + filament );
+}
+
+inline uint8_t operator- (MmuCmd cmda, MmuCmd cmdb)
+{
+    return (static_cast<uint8_t>(cmda) - static_cast<uint8_t>(cmdb));
+}
 
 extern int mmu_puts_P(const char* str);
 
@@ -70,7 +84,7 @@ extern void mmu_reset(void);
 
 extern int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament);
 
-extern void mmu_command(uint8_t cmd);
+extern void mmu_command(MmuCmd cmd);
 
 extern bool mmu_get_response(uint8_t move = 0);
 

+ 2 - 2
Firmware/ultralcd.cpp

@@ -1986,7 +1986,7 @@ static void lcd_menu_fails_stats_mmu_total()
 // MMU load fails  000
 //
 //////////////////////
-	mmu_command(MMU_CMD_S3);
+	mmu_command(MmuCmd::S3);
 	lcd_timeoutToStatus.stop(); //infinite timeout
     uint8_t fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL_TOT);
     uint16_t load_fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL_TOT);
@@ -7208,7 +7208,7 @@ static bool selftest_irsensor()
         mmu_filament_ramming();
     }
     progress = lcd_selftest_screen(testScreen::fsensor, progress, 1, true, 0);
-    mmu_command(MMU_CMD_U0);
+    mmu_command(MmuCmd::U0);
     manage_response(false, false);
 
     for(uint_least8_t i = 0; i < 200; ++i)