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.
Marcio Teixeira 5 years ago
parent
commit
72d8adfd1e
2 changed files with 375 additions and 262 deletions
  1. 253
    195
      Marlin/src/lcd/extensible_ui/ui_api.cpp
  2. 122
    67
      Marlin/src/lcd/extensible_ui/ui_api.h

+ 253
- 195
Marlin/src/lcd/extensible_ui/ui_api.cpp View File

@@ -68,9 +68,6 @@
68 68
 #if ENABLED(PRINTCOUNTER)
69 69
   #include "../../core/utility.h"
70 70
   #include "../../module/printcounter.h"
71
-  #define IFPC(A,B) (A)
72
-#else
73
-  #define IFPC(A,B) (B)
74 71
 #endif
75 72
 
76 73
 #include "ui_api.h"
@@ -90,7 +87,10 @@ inline float clamp(const float value, const float minimum, const float maximum)
90 87
   return MAX(MIN(value, maximum), minimum);
91 88
 }
92 89
 
93
-static bool printer_killed = false;
90
+static struct {
91
+  uint8_t printer_killed  : 1;
92
+  uint8_t manual_motion : 1;
93
+} flags;
94 94
 
95 95
 namespace UI {
96 96
   #ifdef __SAM3X8E__
@@ -102,7 +102,7 @@ namespace UI {
102 102
      */
103 103
     uint32_t safe_millis() {
104 104
       // Not killed? Just call millis()
105
-      if (!printer_killed) return millis();
105
+      if (!flags.printer_killed) return millis();
106 106
 
107 107
       static uint32_t currTimeHI = 0; /* Current time */
108 108
 
@@ -145,186 +145,256 @@ namespace UI {
145 145
   }
146 146
 
147 147
   void delay_ms(unsigned long ms) {
148
-    if (printer_killed)
148
+    if (flags.printer_killed)
149 149
       DELAY_US(ms * 1000);
150 150
     else
151 151
       safe_delay(ms);
152 152
   }
153 153
 
154 154
   void yield() {
155
-    if (!printer_killed)
155
+    if (!flags.printer_killed)
156 156
       thermalManager.manage_heater();
157 157
   }
158 158
 
159
-  float getActualTemp_celsius(const uint8_t extruder) {
160
-    return extruder ?
161
-      thermalManager.degHotend(extruder - 1) :
159
+  float getActualTemp_celsius(const heater_t heater) {
160
+    return heater == BED ?
162 161
       #if HAS_HEATED_BED
163 162
         thermalManager.degBed()
164 163
       #else
165 164
         0
166 165
       #endif
167
-    ;
166
+      : thermalManager.degHotend(heater - H0);
167
+  }
168
+
169
+  float getActualTemp_celsius(const extruder_t extruder) {
170
+    return thermalManager.degHotend(extruder - E0);
168 171
   }
169 172
 
170
-  float getTargetTemp_celsius(const uint8_t extruder) {
171
-    return extruder ?
172
-      thermalManager.degTargetHotend(extruder - 1) :
173
+  float getTargetTemp_celsius(const heater_t heater) {
174
+    return heater == BED ?
173 175
       #if HAS_HEATED_BED
174 176
         thermalManager.degTargetBed()
175 177
       #else
176 178
         0
177 179
       #endif
178
-    ;
180
+      : thermalManager.degTargetHotend(heater - H0);
181
+  }
182
+
183
+  float getTargetTemp_celsius(const extruder_t extruder) {
184
+    return thermalManager.degTargetHotend(extruder - E0);
179 185
   }
180 186
 
181
-  float getFan_percent(const uint8_t fan) { return ((float(fan_speed[fan]) + 1) * 100) / 256; }
187
+  float getFan_percent(const fan_t fan) { return ((float(fan_speed[fan - FAN0]) + 1) * 100) / 256; }
182 188
 
183 189
   float getAxisPosition_mm(const axis_t axis) {
184
-    switch (axis) {
185
-      case X: case Y: case Z:
186
-        return current_position[axis];
187
-      case E0: case E1: case E2: case E3: case E4: case E5:
188
-        return current_position[E_AXIS];
189
-      default: return 0;
190
-    }
190
+    return flags.manual_motion ? destination[axis] : current_position[axis];
191 191
   }
192 192
 
193
-  void setAxisPosition_mm(const axis_t axis, float position, float _feedrate_mm_s) {
194
-    #if EXTRUDERS > 1
195
-      const int8_t old_extruder = active_extruder;
196
-    #endif
197
-    switch (axis) {
198
-      case X: case Y: case Z: break;
199
-      case E0: case E1: case E2: case E3: case E4: case E5:
200
-        #if EXTRUDERS > 1
201
-          active_extruder = axis - E0;
202
-        #endif
203
-        break;
204
-      default: return;
205
-    }
206
-    set_destination_from_current();
207
-    switch (axis) {
208
-      case X: case Y: case Z:
209
-        destination[axis] = position;
210
-        break;
211
-      case E0: case E1: case E2: case E3: case E4: case E5:
212
-        destination[E_AXIS] = position;
213
-        break;
214
-    }
193
+  float getAxisPosition_mm(const extruder_t extruder) {
194
+    return flags.manual_motion ? destination[E_AXIS] : current_position[E_AXIS];
195
+  }
196
+
197
+  void setAxisPosition_mm(const float position, const axis_t axis) {
198
+    // Start with no limits to movement
199
+    float min = current_position[axis] - 1000,
200
+          max = current_position[axis] + 1000;
215 201
 
216
-    const float old_feedrate = feedrate_mm_s;
217
-    feedrate_mm_s = _feedrate_mm_s;
218
-    prepare_move_to_destination();
219
-    feedrate_mm_s = old_feedrate;
220
-    #if EXTRUDERS > 1
221
-      active_extruder = old_extruder;
202
+    // Limit to software endstops, if enabled
203
+    #if ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS)
204
+      if (soft_endstops_enabled) switch (axis) {
205
+        case X_AXIS:
206
+          #if ENABLED(MIN_SOFTWARE_ENDSTOP_X)
207
+            min = soft_endstop_min[X_AXIS];
208
+          #endif
209
+          #if ENABLED(MAX_SOFTWARE_ENDSTOP_X)
210
+            max = soft_endstop_max[X_AXIS];
211
+          #endif
212
+          break;
213
+        case Y_AXIS:
214
+          #if ENABLED(MIN_SOFTWARE_ENDSTOP_Y)
215
+            min = soft_endstop_min[Y_AXIS];
216
+          #endif
217
+          #if ENABLED(MAX_SOFTWARE_ENDSTOP_Y)
218
+            max = soft_endstop_max[Y_AXIS];
219
+          #endif
220
+          break;
221
+        case Z_AXIS:
222
+          #if ENABLED(MIN_SOFTWARE_ENDSTOP_Z)
223
+            min = soft_endstop_min[Z_AXIS];
224
+          #endif
225
+          #if ENABLED(MAX_SOFTWARE_ENDSTOP_Z)
226
+            max = soft_endstop_max[Z_AXIS];
227
+          #endif
228
+        default: break;
229
+      }
230
+    #endif // MIN_SOFTWARE_ENDSTOPS || MAX_SOFTWARE_ENDSTOPS
231
+
232
+    // Delta limits XY based on the current offset from center
233
+    // This assumes the center is 0,0
234
+    #if ENABLED(DELTA)
235
+      if (axis != Z_AXIS) {
236
+        max = SQRT(sq((float)(DELTA_PRINTABLE_RADIUS)) - sq(current_position[Y_AXIS - axis])); // (Y_AXIS - axis) == the other axis
237
+        min = -max;
238
+      }
222 239
     #endif
240
+
241
+    if (!flags.manual_motion)
242
+      set_destination_from_current();
243
+    destination[axis] = clamp(position, min, max);
244
+    flags.manual_motion = true;
245
+  }
246
+
247
+  void setAxisPosition_mm(const float position, const extruder_t extruder) {
248
+    setActiveTool(extruder, true);
249
+
250
+    if (!flags.manual_motion)
251
+      set_destination_from_current();
252
+    destination[E_AXIS] = position;
253
+    flags.manual_motion = true;
254
+  }
255
+
256
+  void _processManualMoveToDestination() {
257
+    // Lower max_response_lag makes controls more responsive, but makes CPU work harder
258
+    constexpr float   max_response_lag = 0.1; // seconds
259
+    constexpr uint8_t segments_to_buffer = 4; // keep planner filled with this many segments
260
+
261
+    if (flags.manual_motion && planner.movesplanned() < segments_to_buffer) {
262
+      float saved_destination[XYZ];
263
+      COPY(saved_destination, destination);
264
+      // Compute direction vector from current_position towards destination.
265
+      destination[X_AXIS] -= current_position[X_AXIS];
266
+      destination[Y_AXIS] -= current_position[Y_AXIS];
267
+      destination[Z_AXIS] -= current_position[Z_AXIS];
268
+      const float inv_length = RSQRT(sq(destination[X_AXIS]) + sq(destination[Y_AXIS]) + sq(destination[Z_AXIS]));
269
+      // Find move segment length so that all segments can execute in less time than max_response_lag
270
+      const float scale = inv_length * feedrate_mm_s * max_response_lag / segments_to_buffer;
271
+      if (scale < 1) {
272
+        // Move a small bit towards the destination.
273
+        destination[X_AXIS] = scale * destination[X_AXIS] + current_position[X_AXIS];
274
+        destination[Y_AXIS] = scale * destination[Y_AXIS] + current_position[Y_AXIS];
275
+        destination[Z_AXIS] = scale * destination[Z_AXIS] + current_position[Z_AXIS];
276
+        prepare_move_to_destination();
277
+        COPY(destination, saved_destination);
278
+      }
279
+      else {
280
+        // We are close enough to finish off the move.
281
+        COPY(destination, saved_destination);
282
+        prepare_move_to_destination();
283
+        flags.manual_motion = false;
284
+      }
285
+    }
223 286
   }
224 287
 
225
-  void setActiveTool(uint8_t extruder, bool no_move) {
226
-    extruder--; // Make zero based
288
+  void setActiveTool(const extruder_t extruder, bool no_move) {
289
+    const uint8_t e = extruder - E0;
227 290
     #if DO_SWITCH_EXTRUDER || ENABLED(SWITCHING_NOZZLE) || ENABLED(PARKING_EXTRUDER)
228
-      if (extruder != active_extruder)
229
-        tool_change(extruder, 0, no_move);
230
-    #endif
231
-    #if EXTRUDERS > 1
232
-      active_extruder = extruder;
291
+      if (e != active_extruder)
292
+        tool_change(e, 0, no_move);
233 293
     #endif
294
+    active_extruder = e;
234 295
   }
235 296
 
236
-  uint8_t getActiveTool() { return active_extruder + 1; }
297
+  extruder_t getActiveTool() {
298
+    switch (active_extruder) {
299
+      case 5:  return E5;
300
+      case 4:  return E4;
301
+      case 3:  return E3;
302
+      case 2:  return E2;
303
+      case 1:  return E1;
304
+      default: return E0;
305
+    }
306
+  }
237 307
 
238 308
   bool isMoving() { return planner.has_blocks_queued(); }
239 309
 
240
-  float getAxisSteps_per_mm(const axis_t axis) {
310
+  bool canMove(const axis_t axis) {
241 311
     switch (axis) {
242
-      case X: case Y: case Z:
243
-        return planner.settings.axis_steps_per_mm[axis];
244
-      case E0: case E1: case E2: case E3: case E4: case E5:
245
-        return planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)];
246
-      default: return 0;
312
+      #if IS_KINEMATIC || ENABLED(NO_MOTION_BEFORE_HOMING)
313
+        case X: return TEST(axis_homed, X_AXIS);
314
+        case Y: return TEST(axis_homed, Y_AXIS);
315
+        case Z: return TEST(axis_homed, Z_AXIS);
316
+      #else
317
+        case X: case Y: case Z: return true;
318
+      #endif
319
+      default: return false;
247 320
     }
248 321
   }
249 322
 
250
-  void setAxisSteps_per_mm(const axis_t axis, const float steps_per_mm) {
251
-    switch (axis) {
252
-      case X: case Y: case Z:
253
-        planner.settings.axis_steps_per_mm[axis] = steps_per_mm;
254
-        break;
255
-      case E0: case E1: case E2: case E3: case E4: case E5:
256
-        planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = steps_per_mm;
257
-        break;
258
-    }
323
+  bool canMove(const extruder_t extruder) {
324
+    return !thermalManager.tooColdToExtrude(extruder - E0);
325
+  }
326
+
327
+  float getAxisSteps_per_mm(const axis_t axis) {
328
+    return planner.settings.axis_steps_per_mm[axis];
329
+  }
330
+
331
+  float getAxisSteps_per_mm(const extruder_t extruder) {
332
+    return planner.settings.axis_steps_per_mm[E_AXIS_N(extruder - E0)];
333
+  }
334
+
335
+  void setAxisSteps_per_mm(const float value, const axis_t axis) {
336
+    planner.settings.axis_steps_per_mm[axis] = value;
337
+  }
338
+
339
+  void setAxisSteps_per_mm(const float value, const extruder_t extruder) {
340
+    planner.settings.axis_steps_per_mm[E_AXIS_N(axis - E0)] = value;
259 341
   }
260 342
 
261 343
   float getAxisMaxFeedrate_mm_s(const axis_t axis) {
262
-    switch (axis) {
263
-      case X: case Y: case Z:
264
-        return planner.settings.max_feedrate_mm_s[axis];
265
-      case E0: case E1: case E2: case E3: case E4: case E5:
266
-        return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
267
-      default: return 0;
268
-    }
344
+    return planner.settings.max_feedrate_mm_s[axis];
269 345
   }
270 346
 
271
-  void setAxisMaxFeedrate_mm_s(const axis_t axis, const float max_feedrate_mm_s) {
272
-    switch (axis) {
273
-      case X: case Y: case Z:
274
-        planner.settings.max_feedrate_mm_s[axis] = max_feedrate_mm_s;
275
-        break;
276
-      case E0: case E1: case E2: case E3: case E4: case E5:
277
-        planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = max_feedrate_mm_s;
278
-        break;
279
-      default: return;
280
-    }
347
+  float getAxisMaxFeedrate_mm_s(const extruder_t extruder) {
348
+    return planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)];
349
+  }
350
+
351
+  void setAxisMaxFeedrate_mm_s(const float value, const axis_t axis) {
352
+    planner.settings.max_feedrate_mm_s[axis] = value;
353
+  }
354
+
355
+  void setAxisMaxFeedrate_mm_s(const float value, const extruder_t extruder) {
356
+    planner.settings.max_feedrate_mm_s[E_AXIS_N(axis - E0)] = value;
281 357
   }
282 358
 
283 359
   float getAxisMaxAcceleration_mm_s2(const axis_t axis) {
284
-    switch (axis) {
285
-      case X: case Y: case Z:
286
-        return planner.settings.max_acceleration_mm_per_s2[axis];
287
-      case E0: case E1: case E2: case E3: case E4: case E5:
288
-        return planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(axis - E0)];
289
-      default: return 0;
290
-    }
360
+    return planner.settings.max_acceleration_mm_per_s2[axis];
291 361
   }
292 362
 
293
-  void setAxisMaxAcceleration_mm_s2(const axis_t axis, const float max_acceleration_mm_per_s2) {
294
-    switch (axis) {
295
-      case X: case Y: case Z:
296
-        planner.settings.max_acceleration_mm_per_s2[axis] = max_acceleration_mm_per_s2;
297
-        break;
298
-      case E0: case E1: case E2: case E3: case E4: case E5:
299
-        planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(axis - E0)] = max_acceleration_mm_per_s2;
300
-        break;
301
-      default: return;
302
-    }
363
+  float getAxisMaxAcceleration_mm_s2(const extruder_t extruder) {
364
+    return planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(extruder - E0)];
365
+  }
366
+
367
+  void setAxisMaxAcceleration_mm_s2(const float value, const axis_t axis) {
368
+    planner.settings.max_acceleration_mm_per_s2[axis] = value;
369
+  }
370
+
371
+  void setAxisMaxAcceleration_mm_s2(const float value, const extruder_t extruder) {
372
+    planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(extruder - E0)] = value;
303 373
   }
304 374
 
305 375
   #if ENABLED(FILAMENT_RUNOUT_SENSOR)
306
-    bool isFilamentRunoutEnabled()              { return runout.enabled; }
307
-    void toggleFilamentRunout(const bool state) { runout.enabled = state; }
376
+    bool getFilamentRunoutEnabled()                 { return runout.enabled; }
377
+    void setFilamentRunoutEnabled(const bool value) { runout.enabled = value; }
308 378
 
309 379
     #if FILAMENT_RUNOUT_DISTANCE_MM > 0
310 380
       float getFilamentRunoutDistance_mm() {
311 381
         return RunoutResponseDelayed::runout_distance_mm;
312 382
       }
313 383
 
314
-      void setFilamentRunoutDistance_mm(const float distance) {
315
-        RunoutResponseDelayed::runout_distance_mm = clamp(distance, 0, 999);
384
+      void setFilamentRunoutDistance_mm(const float value) {
385
+        RunoutResponseDelayed::runout_distance_mm = clamp(value, 0, 999);
316 386
       }
317 387
     #endif
318 388
   #endif
319 389
 
320 390
   #if ENABLED(LIN_ADVANCE)
321
-    float getLinearAdvance_mm_mm_s(const uint8_t extruder) {
322
-      return (extruder < EXTRUDERS) ? planner.extruder_advance_K[extruder] : 0;
391
+    float getLinearAdvance_mm_mm_s(const extruder_t extruder) {
392
+      return (extruder < EXTRUDERS) ? planner.extruder_advance_K[extruder - E0] : 0;
323 393
     }
324 394
 
325
-    void setLinearAdvance_mm_mm_s(const uint8_t extruder, const float k) {
395
+    void setLinearAdvance_mm_mm_s(const float value, const extruder_t extruder) {
326 396
       if (extruder < EXTRUDERS)
327
-        planner.extruder_advance_K[extruder] = clamp(k, 0, 999);
397
+        planner.extruder_advance_K[extruder - E0] = clamp(value, 0, 999);
328 398
     }
329 399
   #endif
330 400
 
@@ -333,39 +403,35 @@ namespace UI {
333 403
       return planner.junction_deviation_mm;
334 404
     }
335 405
 
336
-    void setJunctionDeviation_mm(const float junc_dev) {
337
-      planner.junction_deviation_mm = clamp(junc_dev, 0.01, 0.3);
406
+    void setJunctionDeviation_mm(const float value) {
407
+      planner.junction_deviation_mm = clamp(value, 0.01, 0.3);
338 408
       planner.recalculate_max_e_jerk();
339 409
     }
340 410
   #else
341 411
     float getAxisMaxJerk_mm_s(const axis_t axis) {
342
-      switch (axis) {
343
-        case X: case Y: case Z:
344
-          return planner.max_jerk[axis];
345
-        case E0: case E1: case E2: case E3: case E4: case E5:
346
-          return planner.max_jerk[E_AXIS];
347
-        default: return 0;
348
-      }
412
+        return planner.max_jerk[axis];
349 413
     }
350 414
 
351
-    void setAxisMaxJerk_mm_s(const axis_t axis, const float max_jerk) {
352
-      switch (axis) {
353
-        case X: case Y: case Z:
354
-          planner.max_jerk[axis] = max_jerk;
355
-          break;
356
-        case E0: case E1: case E2: case E3: case E4: case E5:
357
-          planner.max_jerk[E_AXIS] = max_jerk;
358
-          break;
359
-        default: return;
360
-      }
415
+    float getAxisMaxJerk_mm_s(const extruder_t extruder) {
416
+        return planner.max_jerk[E_AXIS];
417
+    }
418
+
419
+    void setAxisMaxJerk_mm_s(const float value, const axis_t axis) {
420
+      planner.max_jerk[axis] = value;
421
+    }
422
+
423
+    void setAxisMaxJerk_mm_s(const float value, const extruder_t extruder) {
424
+      planner.max_jerk[E_AXIS] = value;
361 425
     }
362 426
   #endif
363 427
 
428
+  float getFeedrate_mm_s()                            { return feedrate_mm_s; }
364 429
   float getMinFeedrate_mm_s()                         { return planner.settings.min_feedrate_mm_s; }
365 430
   float getMinTravelFeedrate_mm_s()                   { return planner.settings.min_travel_feedrate_mm_s; }
366 431
   float getPrintingAcceleration_mm_s2()               { return planner.settings.acceleration; }
367 432
   float getRetractAcceleration_mm_s2()                { return planner.settings.retract_acceleration; }
368 433
   float getTravelAcceleration_mm_s2()                 { return planner.settings.travel_acceleration; }
434
+  void setFeedrate_mm_s(const float fr)               { feedrate_mm_s = fr; }
369 435
   void setMinFeedrate_mm_s(const float fr)            { planner.settings.min_feedrate_mm_s = fr; }
370 436
   void setMinTravelFeedrate_mm_s(const float fr)      { planner.settings.min_travel_feedrate_mm_s = fr; }
371 437
   void setPrintingAcceleration_mm_s2(const float acc) { planner.settings.acceleration = acc; }
@@ -382,12 +448,12 @@ namespace UI {
382 448
           return zprobe_zoffset;
383 449
     }
384 450
 
385
-    void setZOffset_mm(const float zoffset_mm) {
386
-      const float diff = (zoffset_mm - getZOffset_mm()) / planner.steps_to_mm[Z_AXIS];
387
-      incrementZOffset_steps(diff > 0 ? ceil(diff) : floor(diff));
451
+    void setZOffset_mm(const float value) {
452
+      const float diff = (value - getZOffset_mm()) / planner.steps_to_mm[Z_AXIS];
453
+      addZOffset_steps(diff > 0 ? ceil(diff) : floor(diff));
388 454
     }
389 455
 
390
-    void incrementZOffset_steps(int16_t babystep_increment) {
456
+    void addZOffset_steps(int16_t babystep_increment) {
391 457
       #if ENABLED(BABYSTEP_HOTEND_Z_OFFSET)
392 458
         const bool do_probe = (active_extruder == 0);
393 459
       #else
@@ -415,28 +481,28 @@ namespace UI {
415 481
   #endif // ENABLED(BABYSTEP_ZPROBE_OFFSET)
416 482
 
417 483
   #if HOTENDS > 1
418
-    float getNozzleOffset_mm(const axis_t axis, uint8_t extruder) {
419
-      if (extruder >= HOTENDS) return 0;
420
-      return hotend_offset[axis][extruder];
484
+    float getNozzleOffset_mm(const axis_t axis, const extruder_t extruder) {
485
+      if (extruder - E0 >= HOTENDS) return 0;
486
+      return hotend_offset[axis][extruder - E0];
421 487
     }
422 488
 
423
-    void setNozzleOffset_mm(const axis_t axis, uint8_t extruder, float offset) {
424
-      if (extruder >= HOTENDS) return;
425
-      hotend_offset[axis][extruder] = offset;
489
+    void setNozzleOffset_mm(const float value, const axis_t axis, const extruder_t extruder) {
490
+      if (extruder - E0 >= HOTENDS) return;
491
+      hotend_offset[axis][extruder - E0] = value;
426 492
     }
427 493
   #endif
428 494
 
429 495
   #if ENABLED(BACKLASH_GCODE)
430
-    float getAxisBacklash_mm(const axis_t axis)       {return backlash_distance_mm[axis];}
431
-    void setAxisBacklash_mm(const axis_t axis, float distance)
432
-                                                      {backlash_distance_mm[axis] = clamp(distance,0,5);}
496
+    float getAxisBacklash_mm(const axis_t axis)       { return backlash_distance_mm[axis]; }
497
+    void setAxisBacklash_mm(const float value, const axis_t axis)
498
+                                                      { backlash_distance_mm[axis] = clamp(value,0,5); }
433 499
 
434
-    float getBacklashCorrection_percent()             {return backlash_correction*100;}
435
-    void setBacklashCorrection_percent(float percent) {backlash_correction = clamp(percent, 0, 100)/100;}
500
+    float getBacklashCorrection_percent()             { return backlash_correction * 100; }
501
+    void setBacklashCorrection_percent(const float value) { backlash_correction = clamp(value, 0, 100) / 100.0f; }
436 502
 
437 503
     #ifdef BACKLASH_SMOOTHING_MM
438
-      float getBacklashSmoothing_mm()                 {return backlash_smoothing_mm;}
439
-      void setBacklashSmoothing_mm(float distance)    {backlash_smoothing_mm = clamp(distance,0,999);}
504
+      float getBacklashSmoothing_mm()                 { return backlash_smoothing_mm; }
505
+      void setBacklashSmoothing_mm(const float value) { backlash_smoothing_mm = clamp(value, 0, 999); }
440 506
     #endif
441 507
   #endif
442 508
 
@@ -445,7 +511,8 @@ namespace UI {
445 511
   }
446 512
 
447 513
   uint32_t getProgress_seconds_elapsed() {
448
-    return IFPC(print_job_timer.duration() / 1000UL, 0);
514
+    const duration_t elapsed = print_job_timer.duration();
515
+    return elapsed.value;
449 516
   }
450 517
 
451 518
   #if ENABLED(PRINTCOUNTER)
@@ -460,46 +527,43 @@ namespace UI {
460 527
     }
461 528
   #endif
462 529
 
463
-  float getFeedRate_percent() {
464
-    return feedrate_percentage;
465
-  }
530
+  float getFeedrate_percent() { return feedrate_percentage; }
466 531
 
467 532
   void enqueueCommands(progmem_str gcode) {
468 533
     enqueue_and_echo_commands_P((PGM_P)gcode);
469 534
   }
470 535
 
471 536
   bool isAxisPositionKnown(const axis_t axis) {
472
-    switch (axis) {
473
-      case X: case Y: case Z:
474
-        return TEST(axis_known_position, axis);
475
-      default: return true;
476
-    }
537
+    return TEST(axis_known_position, axis);
477 538
   }
478 539
 
479
-  progmem_str getFirmwareName() {
540
+  progmem_str getFirmwareName_str() {
480 541
     return F("Marlin " SHORT_BUILD_VERSION);
481 542
   }
482 543
 
483
-  void setTargetTemp_celsius(const uint8_t extruder, float temp) {
484
-    if (extruder)
485
-      thermalManager.setTargetHotend(clamp(temp,0,500), extruder-1);
544
+  void setTargetTemp_celsius(float value, const heater_t heater) {
486 545
     #if HAS_HEATED_BED
487
-      else
488
-        thermalManager.setTargetBed(clamp(temp,0,200));
546
+    if (heater == BED)
547
+      thermalManager.setTargetBed(clamp(value,0,200));
489 548
     #endif
549
+      thermalManager.setTargetHotend(clamp(value,0,500), heater - H0);
550
+  }
551
+
552
+  void setTargetTemp_celsius(float value, const extruder_t extruder) {
553
+    thermalManager.setTargetHotend(clamp(value,0,500), extruder - E0);
490 554
   }
491 555
 
492
-  void setFan_percent(const uint8_t fan, float percent) {
556
+  void setFan_percent(float value, const fan_t fan) {
493 557
     if (fan < FAN_COUNT)
494
-      fan_speed[fan] = clamp(round(percent * 255 / 100), 0, 255);
558
+      fan_speed[fan - FAN0] = clamp(round(value * 255 / 100), 0, 255);
495 559
   }
496 560
 
497
-  void setFeedrate_percent(const float percent) {
498
-    feedrate_percentage = clamp(percent, 10, 500);
561
+  void setFeedrate_percent(const float value) {
562
+    feedrate_percentage = clamp(value, 10, 500);
499 563
   }
500 564
 
501 565
   void printFile(const char *filename) {
502
-    IFSD(card.openAndPrintFile(filename), 0);
566
+    IFSD(card.openAndPrintFile(filename), NOOP);
503 567
   }
504 568
 
505 569
   bool isPrintingFromMediaPaused() {
@@ -511,7 +575,7 @@ namespace UI {
511 575
   }
512 576
 
513 577
   bool isPrinting() {
514
-    return (planner.movesplanned() || IFSD(IS_SD_PRINTING(), false) || isPrintingFromMedia());
578
+    return (planner.movesplanned() || IS_SD_PRINTING() || isPrintingFromMedia());
515 579
   }
516 580
 
517 581
   bool isMediaInserted() {
@@ -521,9 +585,7 @@ namespace UI {
521 585
   void pausePrint() {
522 586
     #if ENABLED(SDSUPPORT)
523 587
       card.pauseSDPrint();
524
-      #if ENABLED(PRINTCOUNTER)
525
-        print_job_timer.pause();
526
-      #endif
588
+      print_job_timer.pause();
527 589
       #if ENABLED(PARK_HEAD_ON_PAUSE)
528 590
         enqueue_and_echo_commands_P(PSTR("M125"));
529 591
       #endif
@@ -537,9 +599,7 @@ namespace UI {
537 599
         enqueue_and_echo_commands_P(PSTR("M24"));
538 600
       #else
539 601
         card.startFileprint();
540
-        #if ENABLED(PRINTCOUNTER)
541
-          print_job_timer.start();
542
-        #endif
602
+        print_job_timer.start();
543 603
       #endif
544 604
       UI::onStatusChanged(PSTR(MSG_PRINTING));
545 605
     #endif
@@ -553,13 +613,9 @@ namespace UI {
553 613
     #endif
554 614
   }
555 615
 
556
-  FileList::FileList() {
557
-    refresh();
558
-  }
616
+  FileList::FileList() { refresh(); }
559 617
 
560
-  void FileList::refresh() {
561
-    num_files = 0xFFFF;
562
-  }
618
+  void FileList::refresh() { num_files = 0xFFFF; }
563 619
 
564 620
   bool FileList::seek(uint16_t pos, bool skip_range_check) {
565 621
     #if ENABLED(SDSUPPORT)
@@ -645,39 +701,41 @@ void lcd_update() {
645 701
       else {
646 702
         const bool ok = card.cardOK;
647 703
         card.release();
648
-        if (ok)
649
-          UI::onMediaRemoved();
704
+        if (ok) UI::onMediaRemoved();
650 705
       }
651 706
     }
652 707
   #endif // SDSUPPORT
708
+  UI::_processManualMoveToDestination();
653 709
   UI::onIdle();
654 710
 }
655 711
 
656
-bool lcd_hasstatus()                                                             { return true; }
657
-bool lcd_detected()                                                              { return true; }
658
-void lcd_reset_alert_level()                                                     {}
659
-void lcd_refresh()                                                               {}
712
+bool lcd_hasstatus() { return true; }
713
+bool lcd_detected() { return true; }
714
+void lcd_reset_alert_level() { }
715
+void lcd_refresh() { }
660 716
 void lcd_setstatus(const char * const message, const bool persist /* = false */) { UI::onStatusChanged(message); }
661 717
 void lcd_setstatusPGM(const char * const message, int8_t level /* = 0 */)        { UI::onStatusChanged((progmem_str)message); }
662 718
 void lcd_setalertstatusPGM(const char * const message)                           { lcd_setstatusPGM(message, 0); }
719
+
663 720
 void lcd_reset_status() {
664 721
   static const char paused[] PROGMEM = MSG_PRINT_PAUSED;
665 722
   static const char printing[] PROGMEM = MSG_PRINTING;
666 723
   static const char welcome[] PROGMEM = WELCOME_MSG;
667 724
   PGM_P msg;
668
-  if (IFPC(print_job_timer.isPaused(), false))
725
+  if (print_job_timer.isPaused())
669 726
     msg = paused;
670 727
   #if ENABLED(SDSUPPORT)
671 728
     else if (card.sdprinting)
672 729
       return lcd_setstatus(card.longest_filename(), true);
673 730
   #endif
674
-  else if (IFPC(print_job_timer.isRunning(), false))
731
+  else if (print_job_timer.isRunning())
675 732
     msg = printing;
676 733
   else
677 734
     msg = welcome;
678 735
 
679 736
   lcd_setstatusPGM(msg, -1);
680 737
 }
738
+
681 739
 void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
682 740
   char buff[64];
683 741
   va_list args;
@@ -689,8 +747,8 @@ void lcd_status_printf_P(const uint8_t level, const char * const fmt, ...) {
689 747
 }
690 748
 
691 749
 void kill_screen(PGM_P msg) {
692
-  if (!printer_killed) {
693
-    printer_killed = true;
750
+  if (!flags.printer_killed) {
751
+    flags.printer_killed = true;
694 752
     UI::onPrinterKilled(msg);
695 753
   }
696 754
 }

+ 122
- 67
Marlin/src/lcd/extensible_ui/ui_api.h View File

@@ -49,147 +49,180 @@ typedef const __FlashStringHelper *progmem_str;
49 49
 
50 50
 namespace UI {
51 51
 
52
-  enum axis_t : uint8_t { X, Y, Z, E0, E1, E2, E3, E4, E5 };
52
+  enum axis_t     : uint8_t { X, Y, Z };
53
+  enum extruder_t : uint8_t { E0, E1, E2, E3, E4, E5 };
54
+  enum heater_t   : uint8_t { H0, H1, H2, H3, H4, H5, BED };
55
+  enum fan_t      : uint8_t { FAN0, FAN1, FAN2, FAN3, FAN4, FAN5 };
53 56
 
54 57
   constexpr uint8_t extruderCount = EXTRUDERS;
58
+  constexpr uint8_t hotendCount   = HOTENDS;
55 59
   constexpr uint8_t fanCount      = FAN_COUNT;
56 60
 
57
-  // The following methods should be used by the extension module to
58
-  // query or change Marlin's state.
59
-
60
-  progmem_str getFirmwareName();
61
-
62
-  bool isAxisPositionKnown(const axis_t axis);
63 61
   bool isMoving();
64
-
65
-  float getActualTemp_celsius(const uint8_t extruder);
66
-  float getTargetTemp_celsius(const uint8_t extruder);
67
-  float getFan_percent(const uint8_t fan);
68
-  float getAxisPosition_mm(const axis_t axis);
69
-  float getAxisSteps_per_mm(const axis_t axis);
70
-  float getAxisMaxFeedrate_mm_s(const axis_t axis);
71
-  float getAxisMaxAcceleration_mm_s2(const axis_t axis);
62
+  bool isAxisPositionKnown(const axis_t);
63
+  bool canMove(const axis_t);
64
+  bool canMove(const extruder_t);
65
+  void enqueueCommands(progmem_str);
66
+
67
+  /**
68
+   * Getters and setters
69
+   * Should be used by the EXTENSIBLE_UI to query or change Marlin's state.
70
+   */
71
+  progmem_str getFirmwareName_str();
72
+
73
+  float getActualTemp_celsius(const heater_t);
74
+  float getActualTemp_celsius(const extruder_t);
75
+  float getTargetTemp_celsius(const heater_t);
76
+  float getTargetTemp_celsius(const extruder_t);
77
+  float getFan_percent(const fan_t);
78
+  float getAxisPosition_mm(const axis_t);
79
+  float getAxisPosition_mm(const extruder_t);
80
+  float getAxisSteps_per_mm(const axis_t);
81
+  float getAxisSteps_per_mm(const extruder_t);
82
+  float getAxisMaxFeedrate_mm_s(const axis_t);
83
+  float getAxisMaxFeedrate_mm_s(const extruder_t);
84
+  float getAxisMaxAcceleration_mm_s2(const axis_t);
85
+  float getAxisMaxAcceleration_mm_s2(const extruder_t);
72 86
   float getMinFeedrate_mm_s();
73 87
   float getMinTravelFeedrate_mm_s();
74 88
   float getPrintingAcceleration_mm_s2();
75 89
   float getRetractAcceleration_mm_s2();
76 90
   float getTravelAcceleration_mm_s2();
77
-  float getFeedRate_percent();
91
+  float getFeedrate_percent();
78 92
   uint8_t getProgress_percent();
79 93
   uint32_t getProgress_seconds_elapsed();
80 94
 
81 95
   #if ENABLED(PRINTCOUNTER)
82
-    char *getTotalPrints_str(char buffer[21]);
83
-    char *getFinishedPrints_str(char buffer[21]);
84
-    char *getTotalPrintTime_str(char buffer[21]);
85
-    char *getLongestPrint_str(char buffer[21]);
86
-    char *getFilamentUsed_str(char buffer[21]);
96
+    char* getTotalPrints_str(char buffer[21]);
97
+    char* getFinishedPrints_str(char buffer[21]);
98
+    char* getTotalPrintTime_str(char buffer[21]);
99
+    char* getLongestPrint_str(char buffer[21]);
100
+    char* getFilamentUsed_str(char buffer[21]);
87 101
   #endif
88 102
 
89
-  void setTargetTemp_celsius(const uint8_t extruder, float temp);
90
-  void setFan_percent(const uint8_t fan, const float percent);
91
-  void setAxisPosition_mm(const axis_t axis, float position, float _feedrate_mm_s);
92
-  void setAxisSteps_per_mm(const axis_t axis, const float steps_per_mm);
93
-  void setAxisMaxFeedrate_mm_s(const axis_t axis, const float max_feedrate_mm_s);
94
-  void setAxisMaxAcceleration_mm_s2(const axis_t axis, const float max_acceleration_mm_per_s2);
95
-  void setMinFeedrate_mm_s(const float min_feedrate_mm_s);
96
-  void setMinTravelFeedrate_mm_s(const float min_travel_feedrate_mm_s);
97
-  void setPrintingAcceleration_mm_s2(const float acceleration);
98
-  void setRetractAcceleration_mm_s2(const float retract_acceleration);
99
-  void setTravelAcceleration_mm_s2(const float travel_acceleration);
100
-  void setFeedrate_percent(const float percent);
103
+  void setTargetTemp_celsius(const float, const heater_t);
104
+  void setTargetTemp_celsius(const float, const extruder_t);
105
+  void setFan_percent(const float, const fan_t);
106
+  void setAxisPosition_mm(const float, const axis_t);
107
+  void setAxisPosition_mm(const float, const extruder_t);
108
+  void setAxisSteps_per_mm(const float, const axis_t);
109
+  void setAxisSteps_per_mm(const float, const extruder_t);
110
+  void setAxisMaxFeedrate_mm_s(const float, const axis_t);
111
+  void setAxisMaxFeedrate_mm_s(const float, const extruder_t);
112
+  void setAxisMaxAcceleration_mm_s2(const float, const axis_t);
113
+  void setAxisMaxAcceleration_mm_s2(const float, const extruder_t);
114
+  void setFeedrate_mm_s(const float);
115
+  void setMinFeedrate_mm_s(const float);
116
+  void setMinTravelFeedrate_mm_s(const float);
117
+  void setPrintingAcceleration_mm_s2(const float);
118
+  void setRetractAcceleration_mm_s2(const float);
119
+  void setTravelAcceleration_mm_s2(const float);
120
+  void setFeedrate_percent(const float);
101 121
 
102 122
   #if ENABLED(LIN_ADVANCE)
103
-    float getLinearAdvance_mm_mm_s(const uint8_t extruder);
104
-    void setLinearAdvance_mm_mm_s(const uint8_t extruder, const float k);
123
+    float getLinearAdvance_mm_mm_s(const extruder_t);
124
+    void setLinearAdvance_mm_mm_s(const float, const extruder_t);
105 125
   #endif
106 126
 
107 127
   #if ENABLED(JUNCTION_DEVIATION)
108 128
     float getJunctionDeviation_mm();
109
-    void setJunctionDeviation_mm(const float junc_dev);
129
+    void setJunctionDeviation_mm(const float);
110 130
   #else
111
-    float getAxisMaxJerk_mm_s(const axis_t axis);
112
-    void setAxisMaxJerk_mm_s(const axis_t axis, const float max_jerk);
131
+    float getAxisMaxJerk_mm_s(const axis_t);
132
+    float getAxisMaxJerk_mm_s(const extruder_t);
133
+    void setAxisMaxJerk_mm_s(const float, const axis_t);
134
+    void setAxisMaxJerk_mm_s(const float, const extruder_t);
113 135
   #endif
114 136
 
115
-  void setActiveTool(uint8_t extruder, bool no_move);
116
-  uint8_t getActiveTool();
137
+  extruder_t getActiveTool();
138
+  void setActiveTool(const extruder_t, bool no_move);
139
+
117 140
 
118 141
   #if HOTENDS > 1
119
-    float getNozzleOffset_mm(const axis_t axis, uint8_t extruder);
120
-    void setNozzleOffset_mm(const axis_t axis, uint8_t extruder, float offset);
142
+    float getNozzleOffset_mm(const axis_t, const extruder_t);
143
+    void setNozzleOffset_mm(const float, const axis_t, const extruder_t);
121 144
   #endif
122 145
 
123 146
   #if ENABLED(BABYSTEP_ZPROBE_OFFSET)
124 147
     float getZOffset_mm();
125
-    void setZOffset_mm(const float zoffset_mm);
126
-    void incrementZOffset_steps(const int16_t babystep_increment);
148
+    void setZOffset_mm(const float);
149
+    void addZOffset_steps(const int16_t);
127 150
   #endif
128 151
 
129 152
   #if ENABLED(BACKLASH_GCODE)
130
-    float getAxisBacklash_mm(const axis_t axis);
131
-    void setAxisBacklash_mm(const axis_t axis, float distance);
153
+    float getAxisBacklash_mm(const axis_t);
154
+    void setAxisBacklash_mm(const float, const axis_t);
132 155
 
133 156
     float getBacklashCorrection_percent();
134
-    void setBacklashCorrection_percent(float percent);
157
+    void setBacklashCorrection_percent(const float);
135 158
 
136 159
     #ifdef BACKLASH_SMOOTHING_MM
137 160
       float getBacklashSmoothing_mm();
138
-      void setBacklashSmoothing_mm(float distance);
161
+      void setBacklashSmoothing_mm(const float);
139 162
     #endif
140 163
   #endif
141 164
 
142 165
   #if ENABLED(FILAMENT_RUNOUT_SENSOR)
143
-    bool isFilamentRunoutEnabled();
144
-    void toggleFilamentRunout(const bool state);
166
+    bool getFilamentRunoutEnabled();
167
+    void setFilamentRunoutEnabled(const bool);
145 168
 
146 169
     #if FILAMENT_RUNOUT_DISTANCE_MM > 0
147 170
       float getFilamentRunoutDistance_mm();
148
-      void setFilamentRunoutDistance_mm(const float distance);
171
+      void setFilamentRunoutDistance_mm(const float);
149 172
     #endif
150 173
   #endif
151 174
 
152
-  // This safe_millis is safe to use even when printer is killed (as long as called at least every 1 second)
175
+  /**
176
+   * Delay and timing routines
177
+   * Should be used by the EXTENSIBLE_UI to safely pause or measure time
178
+   * safe_millis must be called at least every 1 sec to guarantee time
179
+   * yield should be called within lengthy loops
180
+   */
153 181
   uint32_t safe_millis();
154 182
   void delay_us(unsigned long us);
155 183
   void delay_ms(unsigned long ms);
156
-  void yield(); // Within lengthy loop, call this periodically
157
-
158
-  void enqueueCommands(progmem_str gcode);
184
+  void yield();
159 185
 
160
-  void printFile(const char *filename);
186
+  /**
187
+   * Media access routines
188
+   *
189
+   * Should be used by the EXTENSIBLE_UI to operate on files
190
+   */
191
+  bool isMediaInserted();
161 192
   bool isPrintingFromMediaPaused();
162 193
   bool isPrintingFromMedia();
163 194
   bool isPrinting();
195
+
196
+  void printFile(const char *filename);
164 197
   void stopPrint();
165 198
   void pausePrint();
166 199
   void resumePrint();
167 200
 
168
-  bool isMediaInserted();
169
-
170 201
   class FileList {
171 202
     private:
172 203
       uint16_t num_files;
173 204
 
174 205
     public:
175 206
       FileList();
176
-      void        refresh();
177
-      bool        seek(uint16_t, bool skip_range_check = false);
207
+      void refresh();
208
+      bool seek(uint16_t, bool skip_range_check = false);
178 209
 
179 210
       const char *longFilename();
180 211
       const char *shortFilename();
181 212
       const char *filename();
182
-      bool        isDir();
213
+      bool isDir();
183 214
 
184
-      void        changeDir(const char *dirname);
185
-      void        upDir();
186
-      bool        isAtRootDir();
215
+      void changeDir(const char *dirname);
216
+      void upDir();
217
+      bool isAtRootDir();
187 218
       uint16_t    count();
188 219
   };
189 220
 
190
-  // The following event handlers are to be declared by the extension
191
-  // module and will be called by Marlin.
192
-
221
+  /**
222
+   * Event callback routines
223
+   *
224
+   * Should be declared by EXTENSIBLE_UI and will be called by Marlin
225
+   */
193 226
   void onStartup();
194 227
   void onIdle();
195 228
   void onMediaInserted();
@@ -207,3 +240,25 @@ namespace UI {
207 240
   void onStoreSettings();
208 241
   void onLoadSettings();
209 242
 };
243
+
244
+/**
245
+ * Helper macros to increment or decrement a value. For example:
246
+ *
247
+ *   UI_INCREMENT_BY(TargetTemp_celsius, 10, E0)
248
+ *
249
+ * Expands to:
250
+ *
251
+ *   setTargetTemp_celsius(getTargetTemp_celsius(E0) + 10, E0);
252
+ *
253
+ * Or, in the case where a constant increment is desired:
254
+ *
255
+ *   constexpr float increment = 10;
256
+ *
257
+ *   UI_INCREMENT(TargetTemp_celsius, E0)
258
+ *
259
+ */
260
+#define UI_INCREMENT_BY(method, inc, ...) UI::set ## method(UI::get ## method (__VA_ARGS__) + inc, ##__VA_ARGS__)
261
+#define UI_DECREMENT_BY(method, inc, ...) UI::set ## method(UI::get ## method (__VA_ARGS__) - inc, ##__VA_ARGS__)
262
+
263
+#define UI_INCREMENT(method, ...) UI_INCREMENT_BY(method, increment, ##__VA_ARGS__)
264
+#define UI_DECREMENT(method, ...) UI_DECREMENT_BY(method, increment, ##__VA_ARGS__)

Loading…
Cancel
Save