Refactor joystick support in ExtUI (#15318)
This commit is contained in:
		
				
					committed by
					
						
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							04e4eb35be
						
					
				
				
					commit
					8cbb5350ad
				
			@@ -77,13 +77,15 @@ Joystick joystick;
 | 
				
			|||||||
      if (READ(JOY_EN_PIN)) return;
 | 
					      if (READ(JOY_EN_PIN)) return;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto _normalize_joy = [](float &adc, const int16_t raw, const int16_t (&joy_limits)[4]) {
 | 
					    auto _normalize_joy = [](float &norm_jog, const int16_t raw, const int16_t (&joy_limits)[4]) {
 | 
				
			||||||
      if (WITHIN(raw, joy_limits[0], joy_limits[3])) {
 | 
					      if (WITHIN(raw, joy_limits[0], joy_limits[3])) {
 | 
				
			||||||
        // within limits, check deadzone
 | 
					        // within limits, check deadzone
 | 
				
			||||||
        if (raw > joy_limits[2])
 | 
					        if (raw > joy_limits[2])
 | 
				
			||||||
          adc = (raw - joy_limits[2]) / float(joy_limits[3] - joy_limits[2]);
 | 
					          norm_jog = (raw - joy_limits[2]) / float(joy_limits[3] - joy_limits[2]);
 | 
				
			||||||
        else if (raw < joy_limits[1])
 | 
					        else if (raw < joy_limits[1])
 | 
				
			||||||
          adc = (raw - joy_limits[1]) / float(joy_limits[1] - joy_limits[0]);  // negative value
 | 
					          norm_jog = (raw - joy_limits[1]) / float(joy_limits[1] - joy_limits[0]);  // negative value
 | 
				
			||||||
 | 
					        // Map normal to jog value via quadratic relationship
 | 
				
			||||||
 | 
					        norm_jog = SIGN(norm_jog) * sq(norm_jog);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,18 +140,22 @@ Joystick joystick;
 | 
				
			|||||||
    // with "jogging" encapsulated as a more general class.
 | 
					    // with "jogging" encapsulated as a more general class.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if ENABLED(EXTENSIBLE_UI)
 | 
					    #if ENABLED(EXTENSIBLE_UI)
 | 
				
			||||||
      norm_jog[X_AXIS] = ExtUI::norm_jog[X_AXIS];
 | 
					      ExtUI::_joystick_update(norm_jog);
 | 
				
			||||||
      norm_jog[Y_AXIS] = ExtUI::norm_jog[Y_AXIS];
 | 
					 | 
				
			||||||
      norm_jog[Z_AXIS] = ExtUI::norm_jog[Z_AXIS];
 | 
					 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Jogging value maps continuously (quadratic relationship) to feedrate
 | 
					    #if EITHER(ULTIPANEL, EXTENSIBLE_UI)
 | 
				
			||||||
 | 
					      constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
				
			||||||
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // norm_jog values of [-1 .. 1] maps linearly to [-feedrate .. feedrate]
 | 
				
			||||||
    float move_dist[XYZ] = { 0 }, hypot2 = 0;
 | 
					    float move_dist[XYZ] = { 0 }, hypot2 = 0;
 | 
				
			||||||
    LOOP_XYZ(i) if (norm_jog[i]) {
 | 
					    LOOP_XYZ(i) if (norm_jog[i]) {
 | 
				
			||||||
      move_dist[i] = seg_time * sq(norm_jog[i]) * planner.settings.max_feedrate_mm_s[i];
 | 
					      move_dist[i] = seg_time * norm_jog[i] *
 | 
				
			||||||
      // Very small movements disappear when printed as decimal with 4 digits of precision
 | 
					        #if EITHER(ULTIPANEL, EXTENSIBLE_UI)
 | 
				
			||||||
      NOLESS(move_dist[i], 0.0002f);
 | 
					          MMM_TO_MMS(manual_feedrate[i]);
 | 
				
			||||||
      if (norm_jog[i] < 0) move_dist[i] *= -1;  // preserve sign
 | 
					        #else
 | 
				
			||||||
 | 
					          planner.settings.max_feedrate_mm_s[i];
 | 
				
			||||||
 | 
					        #endif
 | 
				
			||||||
      hypot2 += sq(move_dist[i]);
 | 
					      hypot2 += sq(move_dist[i]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,12 +105,10 @@
 | 
				
			|||||||
namespace ExtUI {
 | 
					namespace ExtUI {
 | 
				
			||||||
  static struct {
 | 
					  static struct {
 | 
				
			||||||
    uint8_t printer_killed : 1;
 | 
					    uint8_t printer_killed : 1;
 | 
				
			||||||
    uint8_t manual_motion   : 1;
 | 
					 | 
				
			||||||
  } flags;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    #if ENABLED(JOYSTICK)
 | 
					    #if ENABLED(JOYSTICK)
 | 
				
			||||||
    float norm_jog[XYZ];
 | 
					      uint8_t jogging : 1;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					  } flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #ifdef __SAM3X8E__
 | 
					  #ifdef __SAM3X8E__
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -197,14 +195,46 @@ namespace ExtUI {
 | 
				
			|||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void jog(float dx, float dy, float dz) {
 | 
					 | 
				
			||||||
  #if ENABLED(JOYSTICK)
 | 
					  #if ENABLED(JOYSTICK)
 | 
				
			||||||
      norm_jog[X] = dx;
 | 
					    /**
 | 
				
			||||||
      norm_jog[Y] = dy;
 | 
					     * Jogs in the direction given by the vector (dx, dy, dz).
 | 
				
			||||||
      norm_jog[Z] = dz;
 | 
					     * The values range from -1 to 1 mapping to the maximum
 | 
				
			||||||
    #endif
 | 
					     * feedrate for an axis.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The axis will continue to jog until this function is
 | 
				
			||||||
 | 
					     * called with all zeros.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void jog(float dx, float dy, float dz) {
 | 
				
			||||||
 | 
					      // The "destination" variable is used as a scratchpad in
 | 
				
			||||||
 | 
					      // Marlin by GCODE routines, but should remain untouched
 | 
				
			||||||
 | 
					      // during manual jogging, allowing us to reuse the space
 | 
				
			||||||
 | 
					      // for our direction vector.
 | 
				
			||||||
 | 
					      destination[X] = dx;
 | 
				
			||||||
 | 
					      destination[Y] = dy;
 | 
				
			||||||
 | 
					      destination[Z] = dz;
 | 
				
			||||||
 | 
					      flags.jogging = !NEAR_ZERO(dx) || !NEAR_ZERO(dy) || !NEAR_ZERO(dz);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Called by the polling routine in "joystick.cpp"
 | 
				
			||||||
 | 
					    void _joystick_update(float (&norm_jog)[XYZ]) {
 | 
				
			||||||
 | 
					      if (flags.jogging) {
 | 
				
			||||||
 | 
					        #define OUT_OF_RANGE(VALUE) (VALUE < -1.0f || VALUE > 1.0f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (OUT_OF_RANGE(destination[X_AXIS]) || OUT_OF_RANGE(destination[Y_AXIS]) || OUT_OF_RANGE(destination[Z_AXIS])) {
 | 
				
			||||||
 | 
					          // If destination[] on any axis is out of range, it
 | 
				
			||||||
 | 
					          // probably means the UI forgot to stop jogging and
 | 
				
			||||||
 | 
					          // ran GCODE that wrote a position to destination[].
 | 
				
			||||||
 | 
					          // To prevent a disaster, stop jogging.
 | 
				
			||||||
 | 
					          flags.jogging = false;
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        norm_jog[X_AXIS] = destination[X_AXIS];
 | 
				
			||||||
 | 
					        norm_jog[Y_AXIS] = destination[Y_AXIS];
 | 
				
			||||||
 | 
					        norm_jog[Z_AXIS] = destination[Z_AXIS];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool isHeaterIdle(const extruder_t extruder) {
 | 
					  bool isHeaterIdle(const extruder_t extruder) {
 | 
				
			||||||
    return false
 | 
					    return false
 | 
				
			||||||
      #if HOTENDS && HEATER_IDLE_HANDLER
 | 
					      #if HOTENDS && HEATER_IDLE_HANDLER
 | 
				
			||||||
@@ -288,13 +318,22 @@ namespace ExtUI {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float getAxisPosition_mm(const axis_t axis) {
 | 
					  float getAxisPosition_mm(const axis_t axis) {
 | 
				
			||||||
    return flags.manual_motion ? destination[axis] : current_position[axis];
 | 
					    return
 | 
				
			||||||
 | 
					      #if ENABLED(JOYSTICK)
 | 
				
			||||||
 | 
					        flags.jogging ? destination[axis] :
 | 
				
			||||||
 | 
					      #endif
 | 
				
			||||||
 | 
					      current_position[axis];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float getAxisPosition_mm(const extruder_t extruder) {
 | 
					  float getAxisPosition_mm(const extruder_t extruder) {
 | 
				
			||||||
    const extruder_t old_tool = getActiveTool();
 | 
					    const extruder_t old_tool = getActiveTool();
 | 
				
			||||||
    setActiveTool(extruder, true);
 | 
					    setActiveTool(extruder, true);
 | 
				
			||||||
    const float pos = flags.manual_motion ? destination[E_AXIS] : current_position[E_AXIS];
 | 
					    const float pos = (
 | 
				
			||||||
 | 
					      #if ENABLED(JOYSTICK)
 | 
				
			||||||
 | 
					        flags.jogging ? destination[E_AXIS] :
 | 
				
			||||||
 | 
					      #endif
 | 
				
			||||||
 | 
					      current_position[E_AXIS]
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
    setActiveTool(old_tool, true);
 | 
					    setActiveTool(old_tool, true);
 | 
				
			||||||
    return pos;
 | 
					    return pos;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -343,54 +382,23 @@ namespace ExtUI {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constexpr float max_manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
					    constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
				
			||||||
    setFeedrate_mm_s(MMM_TO_MMS(max_manual_feedrate[axis]));
 | 
					    setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[axis]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!flags.manual_motion) set_destination_from_current();
 | 
					    set_destination_from_current();
 | 
				
			||||||
    destination[axis] = constrain(position, min, max);
 | 
					    destination[axis] = constrain(position, min, max);
 | 
				
			||||||
    flags.manual_motion = true;
 | 
					    prepare_move_to_destination();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setAxisPosition_mm(const float position, const extruder_t extruder) {
 | 
					  void setAxisPosition_mm(const float position, const extruder_t extruder) {
 | 
				
			||||||
    setActiveTool(extruder, true);
 | 
					    setActiveTool(extruder, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constexpr float max_manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
					    constexpr float manual_feedrate[XYZE] = MANUAL_FEEDRATE;
 | 
				
			||||||
    setFeedrate_mm_s(MMM_TO_MMS(max_manual_feedrate[E_AXIS]));
 | 
					    setFeedrate_mm_s(MMM_TO_MMS(manual_feedrate[E_AXIS]));
 | 
				
			||||||
    if (!flags.manual_motion) set_destination_from_current();
 | 
					
 | 
				
			||||||
 | 
					    set_destination_from_current();
 | 
				
			||||||
    destination[E_AXIS] = position;
 | 
					    destination[E_AXIS] = position;
 | 
				
			||||||
    flags.manual_motion = true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void _processManualMoveToDestination() {
 | 
					 | 
				
			||||||
    // Lower max_response_lag makes controls more responsive, but makes CPU work harder
 | 
					 | 
				
			||||||
    constexpr float   max_response_lag = 0.1; // seconds
 | 
					 | 
				
			||||||
    constexpr uint8_t segments_to_buffer = 4; // keep planner filled with this many segments
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (flags.manual_motion && planner.movesplanned() < segments_to_buffer) {
 | 
					 | 
				
			||||||
      float saved_destination[XYZ];
 | 
					 | 
				
			||||||
      COPY(saved_destination, destination);
 | 
					 | 
				
			||||||
      // Compute direction vector from current_position towards destination.
 | 
					 | 
				
			||||||
      destination[X_AXIS] -= current_position[X_AXIS];
 | 
					 | 
				
			||||||
      destination[Y_AXIS] -= current_position[Y_AXIS];
 | 
					 | 
				
			||||||
      destination[Z_AXIS] -= current_position[Z_AXIS];
 | 
					 | 
				
			||||||
      const float inv_length = RSQRT(sq(destination[X_AXIS]) + sq(destination[Y_AXIS]) + sq(destination[Z_AXIS]));
 | 
					 | 
				
			||||||
      // Find move segment length so that all segments can execute in less time than max_response_lag
 | 
					 | 
				
			||||||
      const float scale = inv_length * feedrate_mm_s * max_response_lag / segments_to_buffer;
 | 
					 | 
				
			||||||
      if (scale < 1) {
 | 
					 | 
				
			||||||
        // Move a small bit towards the destination.
 | 
					 | 
				
			||||||
        destination[X_AXIS] = scale * destination[X_AXIS] + current_position[X_AXIS];
 | 
					 | 
				
			||||||
        destination[Y_AXIS] = scale * destination[Y_AXIS] + current_position[Y_AXIS];
 | 
					 | 
				
			||||||
        destination[Z_AXIS] = scale * destination[Z_AXIS] + current_position[Z_AXIS];
 | 
					 | 
				
			||||||
    prepare_move_to_destination();
 | 
					    prepare_move_to_destination();
 | 
				
			||||||
        COPY(destination, saved_destination);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      else {
 | 
					 | 
				
			||||||
        // We are close enough to finish off the move.
 | 
					 | 
				
			||||||
        COPY(destination, saved_destination);
 | 
					 | 
				
			||||||
        prepare_move_to_destination();
 | 
					 | 
				
			||||||
        flags.manual_motion = false;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setActiveTool(const extruder_t extruder, bool no_move) {
 | 
					  void setActiveTool(const extruder_t extruder, bool no_move) {
 | 
				
			||||||
@@ -1044,7 +1052,6 @@ void MarlinUI::update() {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  #endif // SDSUPPORT
 | 
					  #endif // SDSUPPORT
 | 
				
			||||||
  ExtUI::_processManualMoveToDestination();
 | 
					 | 
				
			||||||
  ExtUI::onIdle();
 | 
					  ExtUI::onIdle();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,10 +46,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace ExtUI {
 | 
					namespace ExtUI {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if ENABLED(JOYSTICK)
 | 
					 | 
				
			||||||
    extern float norm_jog[];
 | 
					 | 
				
			||||||
  #endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // The ExtUI implementation can store up to this many bytes
 | 
					  // The ExtUI implementation can store up to this many bytes
 | 
				
			||||||
  // in the EEPROM when the methods onStoreSettings and
 | 
					  // in the EEPROM when the methods onStoreSettings and
 | 
				
			||||||
  // onLoadSettings are called.
 | 
					  // onLoadSettings are called.
 | 
				
			||||||
@@ -84,7 +80,10 @@ namespace ExtUI {
 | 
				
			|||||||
  void enableHeater(const heater_t);
 | 
					  void enableHeater(const heater_t);
 | 
				
			||||||
  void enableHeater(const extruder_t);
 | 
					  void enableHeater(const extruder_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #if ENABLED(JOYSTICK)
 | 
				
			||||||
    void jog(float dx, float dy, float dz);
 | 
					    void jog(float dx, float dy, float dz);
 | 
				
			||||||
 | 
					    void _joystick_update(float (&norm_jog)[XYZ]);
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Getters and setters
 | 
					   * Getters and setters
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user