Browse Source

Cleanup and refactor EXTENSIBLE_UI (#12227)

- Add `axis_t`, `extruder_t`, `heater_t`, and `fan_t` to eliminate ambiguity, improve type safety.
- Regularized getter/setter argument order and naming.
- `setAxisPosition` no longer stacks moves in the buffer, allowing it to be called repeatedly on each touch ui tap.
- Implement better manual moves for `EXTENSIBLE_UI` (#12205)
- Calling `setAxisPosition_mm` no longer buffers the entire move to the new position, but instead causes small moves towards it to be made during the idle loop. This allows the user to adjust the destination even after the move has started and makes the UI feel much more responsive.
- As suggested by @ejtagle, the new code keeps the planner buffer full to ensure smooth motion without stops and starts.
- Change `En`, `Hn` and `FANn` to zero-based indices.
- Labels consistent with the rest of Marlin code.
pull/1/head
Marcio Teixeira 6 years ago
committed by Scott Lahteine
parent
commit
72d8adfd1e
  1. 448
      Marlin/src/lcd/extensible_ui/ui_api.cpp
  2. 189
      Marlin/src/lcd/extensible_ui/ui_api.h

448
Marlin/src/lcd/extensible_ui/ui_api.cpp

@ -68,9 +68,6 @@
#if ENABLED(PRINTCOUNTER) #if ENABLED(PRINTCOUNTER)
#include "../../core/utility.h" #include "../../core/utility.h"
#include "../../module/printcounter.h" #include "../../module/printcounter.h"
#define IFPC(A,B) (A)
#else
#define IFPC(A,B) (B)
#endif #endif
#include "ui_api.h" #include "ui_api.h"
@ -90,7 +87,10 @@ inline float clamp(const float value, const float minimum, const float maximum)
return MAX(MIN(value, maximum), minimum); return MAX(MIN(value, maximum), minimum);
} }
static bool printer_killed = false; static struct {
uint8_t printer_killed : 1;
uint8_t manual_motion : 1;
} flags;
namespace UI { namespace UI {
#ifdef __SAM3X8E__ #ifdef __SAM3X8E__
@ -102,7 +102,7 @@ namespace UI {
*/ */
uint32_t safe_millis() { uint32_t safe_millis() {
// Not killed? Just call millis() // Not killed? Just call millis()
if (!printer_killed) return millis(); if (!flags.printer_killed) return millis();
static uint32_t currTimeHI = 0; /* Current time */ static uint32_t currTimeHI = 0; /* Current time */
@ -145,186 +145,256 @@ namespace UI {
} }
void delay_ms(unsigned long ms) { void delay_ms(unsigned long ms) {
if (printer_killed) if (flags.printer_killed)
DELAY_US(ms * 1000); DELAY_US(ms * 1000);
else else
safe_delay(ms); safe_delay(ms);
} }
void yield() { void yield() {
if (!printer_killed) if (!flags.printer_killed)
thermalManager.manage_heater(); thermalManager.manage_heater();
} }
float getActualTemp_celsius(const uint8_t extruder) { float getActualTemp_celsius(const heater_t heater) {
return extruder ? return heater == BED ?
thermalManager.degHotend(extruder - 1) :
#if HAS_HEATED_BED #if HAS_HEATED_BED
thermalManager.degBed() thermalManager.degBed()
#else #else
0 0
#endif #endif
; : thermalManager.degHotend(heater - H0);
}
float getActualTemp_celsius(const extruder_t extruder) {
return thermalManager.degHotend(extruder - E0);
} }
float getTargetTemp_celsius(const uint8_t extruder) { float getTargetTemp_celsius(const heater_t heater) {
return extruder ? return heater == BED ?
thermalManager.degTargetHotend(extruder - 1) :
#if HAS_HEATED_BED #if HAS_HEATED_BED
thermalManager.degTargetBed() thermalManager.degTargetBed()
#else #else
0 0
#endif #endif
; : thermalManager.degTargetHotend(heater - H0);
}
float getTargetTemp_celsius(const extruder_t extruder) {
return thermalManager.degTargetHotend(extruder - E0);
} }
float getFan_percent(const uint8_t fan) { return ((float(fan_speed[fan]) + 1) * 100) / 256; } float getFan_percent(const fan_t fan) { return ((float(fan_speed[fan - FAN0]) + 1) * 100) / 256; }
float getAxisPosition_mm(const axis_t axis) { float getAxisPosition_mm(const axis_t axis) {
switch (axis) { return flags.manual_motion ? destination[axis] : current_position[axis];
case X: case Y: case Z:
return current_position[axis];
case E0: case E1: case E2: case E3: case E4: case E5:
return current_position[E_AXIS];
default: return 0;
}
} }
void setAxisPosition_mm(const axis_t axis, float position, float _feedrate_mm_s) { float getAxisPosition_mm(const extruder_t extruder) {
#if EXTRUDERS > 1 return flags.manual_motion ? destination[E_AXIS] : current_position[E_AXIS];
const int8_t old_extruder = active_extruder; }
#endif
switch (axis) { void setAxisPosition_mm(const float position, const axis_t axis) {
case X: case Y: case Z: break; // Start with no limits to movement
case E0: case E1: case E2: case E3: case E4: case E5: float min = current_position[axis] - 1000,
#if EXTRUDERS > 1 max = current_position[axis] + 1000;
active_extruder = axis - E0;
#endif
break;
default: return;
}
set_destination_from_current();
switch (axis) {
case X: case Y: case Z:
destination[axis] = position;
break;
case E0: case E1: case E2: case E3: case E4: case E5:
destination[E_AXIS] = position;
break;
}
const float old_feedrate = feedrate_mm_s; // Limit to software endstops, if enabled
feedrate_mm_s = _feedrate_mm_s; #if ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS)
prepare_move_to_destination(); if (soft_endstops_enabled) switch (axis) {
feedrate_mm_s = old_feedrate; case X_AXIS:
#if EXTRUDERS > 1 #if ENABLED(MIN_SOFTWARE_ENDSTOP_X)
active_extruder = old_extruder; min = soft_endstop_min[X_AXIS];
#endif
#if ENABLED(MAX_SOFTWARE_ENDSTOP_X)
max = soft_endstop_max[X_AXIS];
#endif
break;
case Y_AXIS:
#if ENABLED(MIN_SOFTWARE_ENDSTOP_Y)
min = soft_endstop_min[Y_AXIS];
#endif
#if ENABLED(MAX_SOFTWARE_ENDSTOP_Y)
max = soft_endstop_max[Y_AXIS];
#endif
break;
case Z_AXIS:
#if ENABLED(MIN_SOFTWARE_ENDSTOP_Z)
min = soft_endstop_min[Z_AXIS];
#endif
#if ENABLED(MAX_SOFTWARE_ENDSTOP_Z)
max = soft_endstop_max[Z_AXIS];
#endif
default: break;
}
#endif // MIN_SOFTWARE_ENDSTOPS || MAX_SOFTWARE_ENDSTOPS
// Delta limits XY based on the current offset from center
// This assumes the center is 0,0
#if ENABLED(DELTA)
if (axis != Z_AXIS) {
max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis
min = -max;
}
#endif #endif
if (!flags.manual_motion)
set_destination_from_current();
destination[axis] = clamp(position, min, max);
flags.manual_motion = true;
}
void setAxisPosition_mm(const float position, const extruder_t extruder) {
setActiveTool(extruder, true);
if (!flags.manual_motion)
set_destination_from_current();
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();
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(uint8_t extruder, bool no_move) { void setActiveTool(const extruder_t extruder, bool no_move) {
extruder--; // Make zero based const uint8_t e = extruder - E0;
#if DO_SWITCH_EXTRUDER || ENABLED(SWITCHING_NOZZLE) || ENABLED(PARKING_EXTRUDER) #if DO_SWITCH_EXTRUDER || ENABLED(SWITCHING_NOZZLE) || ENABLED(PARKING_EXTRUDER)
if (extruder != active_extruder) if (e != active_extruder)
tool_change(extruder, 0, no_move); tool_change(e, 0, no_move);
#endif
#if EXTRUDERS > 1
active_extruder = extruder;
#endif #endif
active_extruder = e;
} }
uint8_t getActiveTool() { return active_extruder + 1; } extruder_t getActiveTool() {
switch (active_extruder) {
case 5: return E5;
case 4: return E4;
case 3: return E3;
case 2: return E2;
case 1: return E1;
default: return E0;
}
}
bool isMoving() { return planner.has_blocks_queued(); } bool isMoving() { return planner.has_blocks_queued(); }
float getAxisSteps_per_mm(const axis_t axis) { bool canMove(const axis_t axis) {
switch (axis) { switch (axis) {
case X: case Y: case Z: #if IS_KINEMATIC || ENABLED(NO_MOTION_BEFORE_HOMING)
return planner.settings.axis_steps_per_mm[axis]; case X: return TEST(axis_homed, X_AXIS);
case E0: case E1: case E2: case E3: case E4: case E5: case Y: return TEST(axis_homed, Y_AXIS);
return planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)]; case Z: return TEST(axis_homed, Z_AXIS);
default: return 0; #else
case X: case Y: case Z: return true;
#endif
default: return false;
} }
} }
void setAxisSteps_per_mm(const axis_t axis, const float steps_per_mm) { bool canMove(const extruder_t extruder) {
switch (axis) { return !thermalManager.tooColdToExtrude(extruder - E0);
case X: case Y: case Z: }
planner.settings.axis_steps_per_mm[axis] = steps_per_mm;
break; float getAxisSteps_per_mm(const axis_t axis) {
case E0: case E1: case E2: case E3: case E4: case E5: return planner.settings.axis_steps_per_mm[axis];
planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = steps_per_mm; }
break;
} float getAxisSteps_per_mm(const extruder_t extruder) {
return planner.settings.axis_steps_per_mm[E_AXIS_N(extruder - E0)];
}
void setAxisSteps_per_mm(const float value, const axis_t axis) {
planner.settings.axis_steps_per_mm[axis] = value;
}
void setAxisSteps_per_mm(const float value, const extruder_t extruder) {
planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value;
} }
float getAxisMaxFeedrate_mm_s(const axis_t axis) { float getAxisMaxFeedrate_mm_s(const axis_t axis) {
switch (axis) { return planner.settings.max_feedrate_mm_s[axis];
case X: case Y: case Z:
return planner.settings.max_feedrate_mm_s[axis];
case E0: case E1: case E2: case E3: case E4: case E5:
return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
default: return 0;
}
} }
void setAxisMaxFeedrate_mm_s(const axis_t axis, const float max_feedrate_mm_s) { float getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
switch (axis) { return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
case X: case Y: case Z: }
planner.settings.max_feedrate_mm_s[axis] = max_feedrate_mm_s;
break; void setAxisMaxFeedrate_mm_s(const float value, const axis_t axis) {
case E0: case E1: case E2: case E3: case E4: case E5: planner.settings.max_feedrate_mm_s[axis] = value;
planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = max_feedrate_mm_s; }
break;
default: return; void setAxisMaxFeedrate_mm_s(const float value, const extruder_t extruder) {
} planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value;
} }
float getAxisMaxAcceleration_mm_s2(const axis_t axis) { float getAxisMaxAcceleration_mm_s2(const axis_t axis) {
switch (axis) { return planner.settings.max_acceleration_mm_per_s2[axis];
case X: case Y: case Z:
return planner.settings.max_acceleration_mm_per_s2[axis];
case E0: case E1: case E2: case E3: case E4: case E5:
return planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(axis - E0)];
default: return 0;
}
} }
void setAxisMaxAcceleration_mm_s2(const axis_t axis, const float max_acceleration_mm_per_s2) { float getAxisMaxAcceleration_mm_s2(const extruder_t extruder) {
switch (axis) { return planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(extruder - E0)];
case X: case Y: case Z: }
planner.settings.max_acceleration_mm_per_s2[axis] = max_acceleration_mm_per_s2;
break; void setAxisMaxAcceleration_mm_s2(const float value, const axis_t axis) {
case E0: case E1: case E2: case E3: case E4: case E5: planner.settings.max_acceleration_mm_per_s2[axis] = value;
planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(axis - E0)] = max_acceleration_mm_per_s2; }
break;
default: return; void setAxisMaxAcceleration_mm_s2(const float value, const extruder_t extruder) {
} planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(extruder - E0)] = value;
} }
#if ENABLED(FILAMENT_RUNOUT_SENSOR) #if ENABLED(FILAMENT_RUNOUT_SENSOR)
bool isFilamentRunoutEnabled() { return runout.enabled; } bool getFilamentRunoutEnabled() { return runout.enabled; }
void toggleFilamentRunout(const bool state) { runout.enabled = state; } void setFilamentRunoutEnabled(const bool value) { runout.enabled = value; }
#if FILAMENT_RUNOUT_DISTANCE_MM > 0 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
float getFilamentRunoutDistance_mm() { float getFilamentRunoutDistance_mm() {
return RunoutResponseDelayed::runout_distance_mm; return RunoutResponseDelayed::runout_distance_mm;
} }
void setFilamentRunoutDistance_mm(const float distance) { void setFilamentRunoutDistance_mm(const float value) {
RunoutResponseDelayed::runout_distance_mm = clamp(distance, 0, 999); RunoutResponseDelayed::runout_distance_mm = clamp(value, 0, 999);
} }
#endif #endif
#endif #endif
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
float getLinearAdvance_mm_mm_s(const uint8_t extruder) { float getLinearAdvance_mm_mm_s(const extruder_t extruder) {
return (extruder < EXTRUDERS) ? planner.extruder_advance_K[extruder] : 0; return (extruder < EXTRUDERS) ? planner.extruder_advance_K[extruder - E0] : 0;
} }
void setLinearAdvance_mm_mm_s(const uint8_t extruder, const float k) { void setLinearAdvance_mm_mm_s(const float value, const extruder_t extruder) {
if (extruder < EXTRUDERS) if (extruder < EXTRUDERS)
planner.extruder_advance_K[extruder] = clamp(k, 0, 999); planner.extruder_advance_K[extruder - E0] = clamp(value, 0, 999);
} }
#endif #endif
@ -333,39 +403,35 @@ namespace UI {
return planner.junction_deviation_mm; return planner.junction_deviation_mm;
} }
void setJunctionDeviation_mm(const float junc_dev) { void setJunctionDeviation_mm(const float value) {
planner.junction_deviation_mm = clamp(junc_dev, 0.01, 0.3); planner.junction_deviation_mm = clamp(value, 0.01, 0.3);
planner.recalculate_max_e_jerk(); planner.recalculate_max_e_jerk();
} }
#else #else
float getAxisMaxJerk_mm_s(const axis_t axis) { float getAxisMaxJerk_mm_s(const axis_t axis) {
switch (axis) { return planner.max_jerk[axis];
case X: case Y: case Z:
return planner.max_jerk[axis];
case E0: case E1: case E2: case E3: case E4: case E5:
return planner.max_jerk[E_AXIS];
default: return 0;
}
} }
void setAxisMaxJerk_mm_s(const axis_t axis, const float max_jerk) { float getAxisMaxJerk_mm_s(const extruder_t extruder) {
switch (axis) { return planner.max_jerk[E_AXIS];
case X: case Y: case Z: }
planner.max_jerk[axis] = max_jerk;
break; void setAxisMaxJerk_mm_s(const float value, const axis_t axis) {
case E0: case E1: case E2: case E3: case E4: case E5: planner.max_jerk[axis] = value;
planner.max_jerk[E_AXIS] = max_jerk; }
break;
default: return; void setAxisMaxJerk_mm_s(const float value, const extruder_t extruder) {
} planner.max_jerk[E_AXIS] = value;
} }
#endif #endif
float getFeedrate_mm_s() { return feedrate_mm_s; }
float getMinFeedrate_mm_s() { return planner.settings.min_feedrate_mm_s; } float getMinFeedrate_mm_s() { return planner.settings.min_feedrate_mm_s; }
float getMinTravelFeedrate_mm_s() { return planner.settings.min_travel_feedrate_mm_s; } float getMinTravelFeedrate_mm_s() { return planner.settings.min_travel_feedrate_mm_s; }
float getPrintingAcceleration_mm_s2() { return planner.settings.acceleration; } float getPrintingAcceleration_mm_s2() { return planner.settings.acceleration; }
float getRetractAcceleration_mm_s2() { return planner.settings.retract_acceleration; } float getRetractAcceleration_mm_s2() { return planner.settings.retract_acceleration; }
float getTravelAcceleration_mm_s2() { return planner.settings.travel_acceleration; } float getTravelAcceleration_mm_s2() { return planner.settings.travel_acceleration; }
void setFeedrate_mm_s(const float fr) { feedrate_mm_s = fr; }
void setMinFeedrate_mm_s(const float fr) { planner.settings.min_feedrate_mm_s = fr; } void setMinFeedrate_mm_s(const float fr) { planner.settings.min_feedrate_mm_s = fr; }
void setMinTravelFeedrate_mm_s(const float fr) { planner.settings.min_travel_feedrate_mm_s = fr; } void setMinTravelFeedrate_mm_s(const float fr) { planner.settings.min_travel_feedrate_mm_s = fr; }
void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; } void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }
@ -382,12 +448,12 @@ namespace UI {
return zprobe_zoffset; return zprobe_zoffset;
} }
void setZOffset_mm(const float zoffset_mm) { void setZOffset_mm(const float value) {
const float diff = (zoffset_mm - getZOffset_mm()) / planner.steps_to_mm[Z_AXIS]; const float diff = (value - getZOffset_mm()) / planner.steps_to_mm[Z_AXIS];
incrementZOffset_steps(diff > 0 ? ceil(diff) : floor(diff)); addZOffset_steps(diff > 0 ? ceil(diff) : floor(diff));
} }
void incrementZOffset_steps(int16_t babystep_increment) { void addZOffset_steps(int16_t babystep_increment) {
#if ENABLED(BABYSTEP_HOTEND_Z_OFFSET) #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
const bool do_probe = (active_extruder == 0); const bool do_probe = (active_extruder == 0);
#else #else
@ -415,28 +481,28 @@ namespace UI {
#endif // ENABLED(BABYSTEP_ZPROBE_OFFSET) #endif // ENABLED(BABYSTEP_ZPROBE_OFFSET)
#if HOTENDS > 1 #if HOTENDS > 1
float getNozzleOffset_mm(const axis_t axis, uint8_t extruder) { float getNozzleOffset_mm(const axis_t axis, const extruder_t extruder) {
if (extruder >= HOTENDS) return 0; if (extruder - E0 >= HOTENDS) return 0;
return hotend_offset[axis][extruder]; return hotend_offset[axis][extruder - E0];
} }
void setNozzleOffset_mm(const axis_t axis, uint8_t extruder, float offset) { void setNozzleOffset_mm(const float value, const axis_t axis, const extruder_t extruder) {
if (extruder >= HOTENDS) return; if (extruder - E0 >= HOTENDS) return;
hotend_offset[axis][extruder] = offset; hotend_offset[axis][extruder - E0] = value;
} }
#endif #endif
#if ENABLED(BACKLASH_GCODE) #if ENABLED(BACKLASH_GCODE)
float getAxisBacklash_mm(const axis_t axis) {return backlash_distance_mm[axis];} float getAxisBacklash_mm(const axis_t axis) { return backlash_distance_mm[axis]; }
void setAxisBacklash_mm(const axis_t axis, float distance) void setAxisBacklash_mm(const float value, const axis_t axis)
{backlash_distance_mm[axis] = clamp(distance,0,5);} { backlash_distance_mm[axis] = clamp(value,0,5); }
float getBacklashCorrection_percent() {return backlash_correction*100;} float getBacklashCorrection_percent() { return backlash_correction * 100; }
void setBacklashCorrection_percent(float percent) {backlash_correction = clamp(percent, 0, 100)/100;} void setBacklashCorrection_percent(const float value) { backlash_correction = clamp(value, 0, 100) / 100.0f; }
#ifdef BACKLASH_SMOOTHING_MM #ifdef BACKLASH_SMOOTHING_MM
float getBacklashSmoothing_mm() {return backlash_smoothing_mm;} float getBacklashSmoothing_mm() { return backlash_smoothing_mm; }
void setBacklashSmoothing_mm(float distance) {backlash_smoothing_mm = clamp(distance,0,999);} void setBacklashSmoothing_mm(const float value) { backlash_smoothing_mm = clamp(value, 0, 999); }
#endif #endif
#endif #endif
@ -445,7 +511,8 @@ namespace UI {
} }
uint32_t getProgress_seconds_elapsed() { uint32_t getProgress_seconds_elapsed() {
return IFPC(print_job_timer.duration() / 1000UL, 0); const duration_t elapsed = print_job_timer.duration();
return elapsed.value;
} }
#if ENABLED(PRINTCOUNTER) #if ENABLED(PRINTCOUNTER)
@ -460,46 +527,43 @@ namespace UI {
} }
#endif #endif
float getFeedRate_percent() { float getFeedrate_percent() { return feedrate_percentage; }
return feedrate_percentage;
}
void enqueueCommands(progmem_str gcode) { void enqueueCommands(progmem_str gcode) {
enqueue_and_echo_commands_P((PGM_P)gcode); enqueue_and_echo_commands_P((PGM_P)gcode);
} }
bool isAxisPositionKnown(const axis_t axis) { bool isAxisPositionKnown(const axis_t axis) {
switch (axis) { return TEST(axis_known_position, axis);
case X: case Y: case Z:
return TEST(axis_known_position, axis);
default: return true;
}
} }
progmem_str getFirmwareName() { progmem_str getFirmwareName_str() {
return F("Marlin " SHORT_BUILD_VERSION); return F("Marlin " SHORT_BUILD_VERSION);
} }
void setTargetTemp_celsius(const uint8_t extruder, float temp) { void setTargetTemp_celsius(float value, const heater_t heater) {
if (extruder)
thermalManager.setTargetHotend(clamp(temp,0,500), extruder-1);
#if HAS_HEATED_BED #if HAS_HEATED_BED
else if (heater == BED)
thermalManager.setTargetBed(clamp(temp,0,200)); thermalManager.setTargetBed(clamp(value,0,200));
#endif #endif
thermalManager.setTargetHotend(clamp(value,0,500), heater - H0);
}
void setTargetTemp_celsius(float value, const extruder_t extruder) {
thermalManager.setTargetHotend(clamp(value,0,500), extruder - E0);
} }
void setFan_percent(const uint8_t fan, float percent) { void setFan_percent(float value, const fan_t fan) {
if (fan < FAN_COUNT) if (fan < FAN_COUNT)
fan_speed[fan] = clamp(round(percent * 255 / 100), 0, 255); fan_speed[fan - FAN0] = clamp(round(value * 255 / 100), 0, 255);
} }
void setFeedrate_percent(const float percent) { void setFeedrate_percent(const float value) {
feedrate_percentage = clamp(percent, 10, 500); feedrate_percentage = clamp(value, 10, 500);
} }
void printFile(const char *filename) { void printFile(const char *filename) {
IFSD(card.openAndPrintFile(filename), 0); IFSD(card.openAndPrintFile(filename), NOOP);
} }
bool isPrintingFromMediaPaused() { bool isPrintingFromMediaPaused() {
@ -511,7 +575,7 @@ namespace UI {
} }
bool isPrinting() { bool isPrinting() {
return (planner.movesplanned() || IFSD(IS_SD_PRINTING(), false) || isPrintingFromMedia()); return (planner.movesplanned() || IS_SD_PRINTING() || isPrintingFromMedia());
} }
bool isMediaInserted() { bool isMediaInserted() {
@ -521,9 +585,7 @@ namespace UI {
void pausePrint() { void pausePrint() {
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
card.pauseSDPrint(); card.pauseSDPrint();
#if ENABLED(PRINTCOUNTER) print_job_timer.pause();
print_job_timer.pause();
#endif
#if ENABLED(PARK_HEAD_ON_PAUSE) #if ENABLED(PARK_HEAD_ON_PAUSE)
enqueue_and_echo_commands_P(PSTR("M125")); enqueue_and_echo_commands_P(PSTR("M125"));
#endif #endif
@ -537,9 +599,7 @@ namespace UI {
enqueue_and_echo_commands_P(PSTR("M24")); enqueue_and_echo_commands_P(PSTR("M24"));
#else #else
card.startFileprint(); card.startFileprint();
#if ENABLED(PRINTCOUNTER) print_job_timer.start();
print_job_timer.start();
#endif
#endif #endif
UI::onStatusChanged(PSTR(MSG_PRINTING)); UI::onStatusChanged(PSTR(MSG_PRINTING));
#endif #endif
@ -553,13 +613,9 @@ namespace UI {
#endif #endif
} }
FileList::FileList() { FileList::FileList() { refresh(); }
refresh();
}
void FileList::refresh() { void FileList::refresh() { num_files = 0xFFFF; }
num_files = 0xFFFF;
}
bool FileList::seek(uint16_t pos, bool skip_range_check) { bool FileList::seek(uint16_t pos, bool skip_range_check) {
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
@ -645,39 +701,41 @@ void lcd_update() {
else { else {
const bool ok = card.cardOK; const bool ok = card.cardOK;
card.release(); card.release();
if (ok) if (ok) UI::onMediaRemoved();
UI::onMediaRemoved();
} }
} }
#endif // SDSUPPORT #endif // SDSUPPORT
UI::_processManualMoveToDestination();
UI::onIdle(); UI::onIdle();
} }
bool lcd_hasstatus() { return true; } bool lcd_hasstatus() { return true; }
bool lcd_detected() { return true; } bool lcd_detected() { return true; }
void lcd_reset_alert_level() {} void lcd_reset_alert_level() { }
void lcd_refresh() {} void lcd_refresh() { }
void lcd_setstatus(const char * const message, const bool persist /* = false */) { UI::onStatusChanged(message); } void lcd_setstatus(const char * const message, const bool persist /* = false */) { UI::onStatusChanged(message); }
void lcd_setstatusPGM(const char * const message, int8_t level /* = 0 */) { UI::onStatusChanged((progmem_str)message); } void lcd_setstatusPGM(const char * const message, int8_t level /* = 0 */) { UI::onStatusChanged((progmem_str)message); }
void lcd_setalertstatusPGM(const char * const message) { lcd_setstatusPGM(message, 0); } void lcd_setalertstatusPGM(const char * const message) { lcd_setstatusPGM(message, 0); }
void lcd_reset_status() { void lcd_reset_status() {
static const char paused[] PROGMEM = MSG_PRINT_PAUSED; static const char paused[] PROGMEM = MSG_PRINT_PAUSED;
static const char printing[] PROGMEM = MSG_PRINTING; static const char printing[] PROGMEM = MSG_PRINTING;
static const char welcome[] PROGMEM = WELCOME_MSG; static const char welcome[] PROGMEM = WELCOME_MSG;
PGM_P msg; PGM_P msg;
if (IFPC(print_job_timer.isPaused(), false)) if (print_job_timer.isPaused())
msg = paused; msg = paused;
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
else if (card.sdprinting) else if (card.sdprinting)
return lcd_setstatus(card.longest_filename(), true); return lcd_setstatus(card.longest_filename(), true);
#endif #endif
else if (IFPC(print_job_timer.isRunning(), false)) else if (print_job_timer.isRunning())
msg = printing; msg = printing;
else else
msg = welcome; msg = welcome;
lcd_setstatusPGM(msg, -1); lcd_setstatusPGM(msg, -1);
} }
void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) { void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
char buff[64]; char buff[64];
va_list args; va_list args;
@ -689,8 +747,8 @@ void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
} }
void kill_screen(PGM_P msg) { void kill_screen(PGM_P msg) {
if (!printer_killed) { if (!flags.printer_killed) {
printer_killed = true; flags.printer_killed = true;
UI::onPrinterKilled(msg); UI::onPrinterKilled(msg);
} }
} }

189
Marlin/src/lcd/extensible_ui/ui_api.h

@ -49,147 +49,180 @@ typedef const __FlashStringHelper *progmem_str;
namespace UI { namespace UI {
enum axis_t : uint8_t { X, Y, Z, E0, E1, E2, E3, E4, E5 }; enum axis_t : uint8_t { X, Y, Z };
enum extruder_t : uint8_t { E0, E1, E2, E3, E4, E5 };
enum heater_t : uint8_t { H0, H1, H2, H3, H4, H5, BED };
enum fan_t : uint8_t { FAN0, FAN1, FAN2, FAN3, FAN4, FAN5 };
constexpr uint8_t extruderCount = EXTRUDERS; constexpr uint8_t extruderCount = EXTRUDERS;
constexpr uint8_t hotendCount = HOTENDS;
constexpr uint8_t fanCount = FAN_COUNT; constexpr uint8_t fanCount = FAN_COUNT;
// The following methods should be used by the extension module to
// query or change Marlin's state.
progmem_str getFirmwareName();
bool isAxisPositionKnown(const axis_t axis);
bool isMoving(); bool isMoving();
bool isAxisPositionKnown(const axis_t);
float getActualTemp_celsius(const uint8_t extruder); bool canMove(const axis_t);
float getTargetTemp_celsius(const uint8_t extruder); bool canMove(const extruder_t);
float getFan_percent(const uint8_t fan); void enqueueCommands(progmem_str);
float getAxisPosition_mm(const axis_t axis);
float getAxisSteps_per_mm(const axis_t axis); /**
float getAxisMaxFeedrate_mm_s(const axis_t axis); * Getters and setters
float getAxisMaxAcceleration_mm_s2(const axis_t axis); * Should be used by the EXTENSIBLE_UI to query or change Marlin's state.
*/
progmem_str getFirmwareName_str();
float getActualTemp_celsius(const heater_t);
float getActualTemp_celsius(const extruder_t);
float getTargetTemp_celsius(const heater_t);
float getTargetTemp_celsius(const extruder_t);
float getFan_percent(const fan_t);
float getAxisPosition_mm(const axis_t);
float getAxisPosition_mm(const extruder_t);
float getAxisSteps_per_mm(const axis_t);
float getAxisSteps_per_mm(const extruder_t);
float getAxisMaxFeedrate_mm_s(const axis_t);
float getAxisMaxFeedrate_mm_s(const extruder_t);
float getAxisMaxAcceleration_mm_s2(const axis_t);
float getAxisMaxAcceleration_mm_s2(const extruder_t);
float getMinFeedrate_mm_s(); float getMinFeedrate_mm_s();
float getMinTravelFeedrate_mm_s(); float getMinTravelFeedrate_mm_s();
float getPrintingAcceleration_mm_s2(); float getPrintingAcceleration_mm_s2();
float getRetractAcceleration_mm_s2(); float getRetractAcceleration_mm_s2();
float getTravelAcceleration_mm_s2(); float getTravelAcceleration_mm_s2();
float getFeedRate_percent(); float getFeedrate_percent();
uint8_t getProgress_percent(); uint8_t getProgress_percent();
uint32_t getProgress_seconds_elapsed(); uint32_t getProgress_seconds_elapsed();
#if ENABLED(PRINTCOUNTER) #if ENABLED(PRINTCOUNTER)
char *getTotalPrints_str(char buffer[21]); char* getTotalPrints_str(char buffer[21]);
char *getFinishedPrints_str(char buffer[21]); char* getFinishedPrints_str(char buffer[21]);
char *getTotalPrintTime_str(char buffer[21]); char* getTotalPrintTime_str(char buffer[21]);
char *getLongestPrint_str(char buffer[21]); char* getLongestPrint_str(char buffer[21]);
char *getFilamentUsed_str(char buffer[21]); char* getFilamentUsed_str(char buffer[21]);
#endif #endif
void setTargetTemp_celsius(const uint8_t extruder, float temp); void setTargetTemp_celsius(const float, const heater_t);
void setFan_percent(const uint8_t fan, const float percent); void setTargetTemp_celsius(const float, const extruder_t);
void setAxisPosition_mm(const axis_t axis, float position, float _feedrate_mm_s); void setFan_percent(const float, const fan_t);
void setAxisSteps_per_mm(const axis_t axis, const float steps_per_mm); void setAxisPosition_mm(const float, const axis_t);
void setAxisMaxFeedrate_mm_s(const axis_t axis, const float max_feedrate_mm_s); void setAxisPosition_mm(const float, const extruder_t);
void setAxisMaxAcceleration_mm_s2(const axis_t axis, const float max_acceleration_mm_per_s2); void setAxisSteps_per_mm(const float, const axis_t);
void setMinFeedrate_mm_s(const float min_feedrate_mm_s); void setAxisSteps_per_mm(const float, const extruder_t);
void setMinTravelFeedrate_mm_s(const float min_travel_feedrate_mm_s); void setAxisMaxFeedrate_mm_s(const float, const axis_t);
void setPrintingAcceleration_mm_s2(const float acceleration); void setAxisMaxFeedrate_mm_s(const float, const extruder_t);
void setRetractAcceleration_mm_s2(const float retract_acceleration); void setAxisMaxAcceleration_mm_s2(const float, const axis_t);
void setTravelAcceleration_mm_s2(const float travel_acceleration); void setAxisMaxAcceleration_mm_s2(const float, const extruder_t);
void setFeedrate_percent(const float percent); void setFeedrate_mm_s(const float);
void setMinFeedrate_mm_s(const float);
void setMinTravelFeedrate_mm_s(const float);
void setPrintingAcceleration_mm_s2(const float);
void setRetractAcceleration_mm_s2(const float);
void setTravelAcceleration_mm_s2(const float);
void setFeedrate_percent(const float);
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
float getLinearAdvance_mm_mm_s(const uint8_t extruder); float getLinearAdvance_mm_mm_s(const extruder_t);
void setLinearAdvance_mm_mm_s(const uint8_t extruder, const float k); void setLinearAdvance_mm_mm_s(const float, const extruder_t);
#endif #endif
#if ENABLED(JUNCTION_DEVIATION) #if ENABLED(JUNCTION_DEVIATION)
float getJunctionDeviation_mm(); float getJunctionDeviation_mm();
void setJunctionDeviation_mm(const float junc_dev); void setJunctionDeviation_mm(const float);
#else #else
float getAxisMaxJerk_mm_s(const axis_t axis); float getAxisMaxJerk_mm_s(const axis_t);
void setAxisMaxJerk_mm_s(const axis_t axis, const float max_jerk); float getAxisMaxJerk_mm_s(const extruder_t);
void setAxisMaxJerk_mm_s(const float, const axis_t);
void setAxisMaxJerk_mm_s(const float, const extruder_t);
#endif #endif
void setActiveTool(uint8_t extruder, bool no_move); extruder_t getActiveTool();
uint8_t getActiveTool(); void setActiveTool(const extruder_t, bool no_move);
#if HOTENDS > 1 #if HOTENDS > 1
float getNozzleOffset_mm(const axis_t axis, uint8_t extruder); float getNozzleOffset_mm(const axis_t, const extruder_t);
void setNozzleOffset_mm(const axis_t axis, uint8_t extruder, float offset); void setNozzleOffset_mm(const float, const axis_t, const extruder_t);
#endif #endif
#if ENABLED(BABYSTEP_ZPROBE_OFFSET) #if ENABLED(BABYSTEP_ZPROBE_OFFSET)
float getZOffset_mm(); float getZOffset_mm();
void setZOffset_mm(const float zoffset_mm); void setZOffset_mm(const float);
void incrementZOffset_steps(const int16_t babystep_increment); void addZOffset_steps(const int16_t);
#endif #endif
#if ENABLED(BACKLASH_GCODE) #if ENABLED(BACKLASH_GCODE)
float getAxisBacklash_mm(const axis_t axis); float getAxisBacklash_mm(const axis_t);
void setAxisBacklash_mm(const axis_t axis, float distance); void setAxisBacklash_mm(const float, const axis_t);
float getBacklashCorrection_percent(); float getBacklashCorrection_percent();
void setBacklashCorrection_percent(float percent); void setBacklashCorrection_percent(const float);
#ifdef BACKLASH_SMOOTHING_MM #ifdef BACKLASH_SMOOTHING_MM
float getBacklashSmoothing_mm(); float getBacklashSmoothing_mm();
void setBacklashSmoothing_mm(float distance); void setBacklashSmoothing_mm(const float);
#endif #endif
#endif #endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR) #if ENABLED(FILAMENT_RUNOUT_SENSOR)
bool isFilamentRunoutEnabled(); bool getFilamentRunoutEnabled();
void toggleFilamentRunout(const bool state); void setFilamentRunoutEnabled(const bool);
#if FILAMENT_RUNOUT_DISTANCE_MM > 0 #if FILAMENT_RUNOUT_DISTANCE_MM > 0
float getFilamentRunoutDistance_mm(); float getFilamentRunoutDistance_mm();
void setFilamentRunoutDistance_mm(const float distance); void setFilamentRunoutDistance_mm(const float);
#endif #endif
#endif #endif
// This safe_millis is safe to use even when printer is killed (as long as called at least every 1 second) /**
* Delay and timing routines
* Should be used by the EXTENSIBLE_UI to safely pause or measure time
* safe_millis must be called at least every 1 sec to guarantee time
* yield should be called within lengthy loops
*/
uint32_t safe_millis(); uint32_t safe_millis();
void delay_us(unsigned long us); void delay_us(unsigned long us);
void delay_ms(unsigned long ms); void delay_ms(unsigned long ms);
void yield(); // Within lengthy loop, call this periodically void yield();
void enqueueCommands(progmem_str gcode);
void printFile(const char *filename); /**
* Media access routines
*
* Should be used by the EXTENSIBLE_UI to operate on files
*/
bool isMediaInserted();
bool isPrintingFromMediaPaused(); bool isPrintingFromMediaPaused();
bool isPrintingFromMedia(); bool isPrintingFromMedia();
bool isPrinting(); bool isPrinting();
void printFile(const char *filename);
void stopPrint(); void stopPrint();
void pausePrint(); void pausePrint();
void resumePrint(); void resumePrint();
bool isMediaInserted();
class FileList { class FileList {
private: private:
uint16_t num_files; uint16_t num_files;
public: public:
FileList(); FileList();
void refresh(); void refresh();
bool seek(uint16_t, bool skip_range_check = false); bool seek(uint16_t, bool skip_range_check = false);
const char *longFilename(); const char *longFilename();
const char *shortFilename(); const char *shortFilename();
const char *filename(); const char *filename();
bool isDir(); bool isDir();
void changeDir(const char *dirname); void changeDir(const char *dirname);
void upDir(); void upDir();
bool isAtRootDir(); bool isAtRootDir();
uint16_t count(); uint16_t count();
}; };
// The following event handlers are to be declared by the extension /**
// module and will be called by Marlin. * Event callback routines
*
* Should be declared by EXTENSIBLE_UI and will be called by Marlin
*/
void onStartup(); void onStartup();
void onIdle(); void onIdle();
void onMediaInserted(); void onMediaInserted();
@ -207,3 +240,25 @@ namespace UI {
void onStoreSettings(); void onStoreSettings();
void onLoadSettings(); void onLoadSettings();
}; };
/**
* Helper macros to increment or decrement a value. For example:
*
* UI_INCREMENT_BY(TargetTemp_celsius, 10, E0)
*
* Expands to:
*
* setTargetTemp_celsius(getTargetTemp_celsius(E0) + 10, E0);
*
* Or, in the case where a constant increment is desired:
*
* constexpr float increment = 10;
*
* UI_INCREMENT(TargetTemp_celsius, E0)
*
*/
#define UI_INCREMENT_BY(method, inc, ...) UI::set ## method(UI::get ## method (__VA_ARGS__) + inc, ##__VA_ARGS__)
#define UI_DECREMENT_BY(method, inc, ...) UI::set ## method(UI::get ## method (__VA_ARGS__) - inc, ##__VA_ARGS__)
#define UI_INCREMENT(method, ...) UI_INCREMENT_BY(method, increment, ##__VA_ARGS__)
#define UI_DECREMENT(method, ...) UI_DECREMENT_BY(method, increment, ##__VA_ARGS__)

Loading…
Cancel
Save