Subversion Repositories Tronxy-X3A-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
/**
2
 * Marlin 3D Printer Firmware
3
 * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
 *
5
 * Based on Sprinter and grbl.
6
 * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
 
23
/**
24
 * status_screen_DOGM.h
25
 *
26
 * Standard Status Screen for Graphical Display
27
 */
28
 
29
#ifndef _STATUS_SCREEN_DOGM_H_
30
#define _STATUS_SCREEN_DOGM_H_
31
 
32
FORCE_INLINE void _draw_centered_temp(const int16_t temp, const uint8_t x, const uint8_t y) {
33
  const char * const str = itostr3(temp);
34
  u8g.setPrintPos(x - (str[0] != ' ' ? 0 : str[1] != ' ' ? 1 : 2) * DOG_CHAR_WIDTH / 2, y);
35
  lcd_print(str);
36
  lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
37
}
38
 
39
#ifndef HEAT_INDICATOR_X
40
  #define HEAT_INDICATOR_X 8
41
#endif
42
 
43
FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, const bool blink) {
44
  #if !HEATER_IDLE_HANDLER
45
    UNUSED(blink);
46
  #endif
47
 
48
  #if HAS_HEATED_BED
49
    const bool isBed = heater < 0;
50
  #else
51
    constexpr bool isBed = false;
52
  #endif
53
 
54
  if (PAGE_UNDER(7)) {
55
    #if HEATER_IDLE_HANDLER
56
      const bool is_idle = (
57
        #if HAS_HEATED_BED
58
          isBed ? thermalManager.is_bed_idle() :
59
        #endif
60
        thermalManager.is_heater_idle(heater)
61
      );
62
 
63
      if (blink || !is_idle)
64
    #endif
65
        _draw_centered_temp(0.5f + (
66
            #if HAS_HEATED_BED
67
              isBed ? thermalManager.degTargetBed() :
68
            #endif
69
            thermalManager.degTargetHotend(heater)
70
          ), x, 7
71
        );
72
  }
73
 
74
  if (PAGE_CONTAINS(21, 28)) {
75
    _draw_centered_temp(0.5f + (
76
        #if HAS_HEATED_BED
77
          isBed ? thermalManager.degBed() :
78
        #endif
79
        thermalManager.degHotend(heater)
80
      ), x, 28
81
    );
82
 
83
    if (PAGE_CONTAINS(17, 20)) {
84
      const uint8_t h = isBed ? 7 : HEAT_INDICATOR_X,
85
                    y = isBed ? 18 : 17;
86
      if (
87
        #if HAS_HEATED_BED
88
          isBed ? thermalManager.isHeatingBed() :
89
        #endif
90
        thermalManager.isHeatingHotend(heater)
91
      ) {
92
        u8g.setColorIndex(0); // white on black
93
        u8g.drawBox(x + h, y, 2, 2);
94
        u8g.setColorIndex(1); // black on white
95
      }
96
      else
97
        u8g.drawBox(x + h, y, 2, 2);
98
    }
99
  }
100
}
101
 
102
//
103
// Before homing, blink '123' <-> '???'.
104
// Homed but unknown... '123' <-> '   '.
105
// Homed and known, display constantly.
106
//
107
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) {
108
  if (blink)
109
    lcd_print(value);
110
  else {
111
    if (!TEST(axis_homed, axis))
112
      while (const char c = *value++) lcd_print(c <= '.' ? c : '?');
113
    else {
114
      #if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
115
        if (!TEST(axis_known_position, axis))
116
          lcd_printPGM(axis == Z_AXIS ? PSTR("      ") : PSTR("    "));
117
        else
118
      #endif
119
          lcd_print(value);
120
    }
121
  }
122
}
123
 
124
inline void lcd_implementation_status_message(const bool blink) {
125
  #if ENABLED(STATUS_MESSAGE_SCROLLING)
126
    static bool last_blink = false;
127
 
128
    // Get the UTF8 character count of the string
129
    uint8_t slen = utf8_strlen(lcd_status_message);
130
 
131
    // If the string fits into the LCD, just print it and do not scroll it
132
    if (slen <= LCD_WIDTH) {
133
 
134
      // The string isn't scrolling and may not fill the screen
135
      lcd_print_utf(lcd_status_message);
136
 
137
      // Fill the rest with spaces
138
      while (slen < LCD_WIDTH) {
139
        u8g.print(' ');
140
        ++slen;
141
      }
142
    }
143
    else {
144
      // String is larger than the available space in screen.
145
 
146
      // Get a pointer to the next valid UTF8 character
147
      const char *stat = lcd_status_message + status_scroll_offset;
148
 
149
      // Get the string remaining length
150
      const uint8_t rlen = utf8_strlen(stat);
151
 
152
      // If we have enough characters to display
153
      if (rlen >= LCD_WIDTH) {
154
        // The remaining string fills the screen - Print it
155
        lcd_print_utf(stat, LCD_WIDTH);
156
      }
157
      else {
158
        // The remaining string does not completely fill the screen
159
        lcd_print_utf(stat, LCD_WIDTH);         // The string leaves space
160
        uint8_t chars = LCD_WIDTH - rlen;       // Amount of space left in characters
161
 
162
        u8g.print('.');                         // Always at 1+ spaces left, draw a dot
163
        if (--chars) {                          // Draw a second dot if there's space
164
          u8g.print('.');
165
          if (--chars)                          // Print a second copy of the message
166
            lcd_print_utf(lcd_status_message, LCD_WIDTH - (rlen + 2));
167
        }
168
      }
169
       if (last_blink != blink) {
170
         last_blink = blink;
171
 
172
        // Adjust by complete UTF8 characters
173
        if (status_scroll_offset < slen) {
174
          status_scroll_offset++;
175
          while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
176
            status_scroll_offset++;
177
        }
178
        else
179
          status_scroll_offset = 0;
180
      }
181
    }
182
  #else
183
    UNUSED(blink);
184
 
185
    // Get the UTF8 character count of the string
186
    uint8_t slen = utf8_strlen(lcd_status_message);
187
 
188
    // Just print the string to the LCD
189
    lcd_print_utf(lcd_status_message, LCD_WIDTH);
190
 
191
    // Fill the rest with spaces if there are missing spaces
192
    while (slen < LCD_WIDTH) {
193
      u8g.print(' ');
194
      ++slen;
195
    }
196
  #endif
197
}
198
 
199
static void lcd_implementation_status_screen() {
200
 
201
  const bool blink = lcd_blink();
202
 
203
  #if FAN_ANIM_FRAMES > 2
204
    static bool old_blink;
205
    static uint8_t fan_frame;
206
    if (old_blink != blink) {
207
      old_blink = blink;
208
      if (!fanSpeeds[0] || ++fan_frame >= FAN_ANIM_FRAMES) fan_frame = 0;
209
    }
210
  #endif
211
 
212
  // Status Menu Font
213
  lcd_setFont(FONT_STATUSMENU);
214
 
215
  //
216
  // Fan Animation
217
  //
218
  // Draws the whole heading image as a B/W bitmap rather than
219
  // drawing the elements separately.
220
  // This was done as an optimization, as it was slower to draw
221
  // multiple parts compared to a single bitmap.
222
  //
223
  // The bitmap:
224
  // - May be offset in X
225
  // - Includes all nozzle(s), bed(s), and the fan.
226
  //
227
  // TODO:
228
  //
229
  // - Only draw the whole header on the first
230
  //   entry to the status screen. Nozzle, bed, and
231
  //   fan outline bits don't change.
232
  //
233
  if (PAGE_UNDER(STATUS_SCREENHEIGHT + 1)) {
234
 
235
    u8g.drawBitmapP(
236
      STATUS_SCREEN_X, STATUS_SCREEN_Y,
237
      (STATUS_SCREENWIDTH + 7) / 8, STATUS_SCREENHEIGHT,
238
      #if HAS_FAN0
239
        #if FAN_ANIM_FRAMES > 2
240
          fan_frame == 1 ? status_screen1_bmp :
241
          fan_frame == 2 ? status_screen2_bmp :
242
          #if FAN_ANIM_FRAMES > 3
243
            fan_frame == 3 ? status_screen3_bmp :
244
          #endif
245
        #else
246
          blink && fanSpeeds[0] ? status_screen1_bmp :
247
        #endif
248
      #endif
249
      status_screen0_bmp
250
    );
251
 
252
  }
253
 
254
  //
255
  // Temperature Graphics and Info
256
  //
257
 
258
  if (PAGE_UNDER(28)) {
259
    // Extruders
260
    HOTEND_LOOP() _draw_heater_status(STATUS_SCREEN_HOTEND_TEXT_X(e), e, blink);
261
 
262
    // Heated bed
263
    #if HOTENDS < 4 && HAS_HEATED_BED
264
      _draw_heater_status(STATUS_SCREEN_BED_TEXT_X, -1, blink);
265
    #endif
266
 
267
    #if HAS_FAN0
268
      if (PAGE_CONTAINS(STATUS_SCREEN_FAN_TEXT_Y - 7, STATUS_SCREEN_FAN_TEXT_Y)) {
269
        // Fan
270
        const int16_t per = ((fanSpeeds[0] + 1) * 100) / 256;
271
        if (per) {
272
          u8g.setPrintPos(STATUS_SCREEN_FAN_TEXT_X, STATUS_SCREEN_FAN_TEXT_Y);
273
          lcd_print(itostr3(per));
274
          u8g.print('%');
275
        }
276
      }
277
    #endif
278
  }
279
 
280
  #if ENABLED(SDSUPPORT)
281
    //
282
    // SD Card Symbol
283
    //
284
    if (card.isFileOpen() && PAGE_CONTAINS(42 - (TALL_FONT_CORRECTION), 51 - (TALL_FONT_CORRECTION))) {
285
      // Upper box
286
      u8g.drawBox(42, 42 - (TALL_FONT_CORRECTION), 8, 7);     // 42-48 (or 41-47)
287
      // Right edge
288
      u8g.drawBox(50, 44 - (TALL_FONT_CORRECTION), 2, 5);     // 44-48 (or 43-47)
289
      // Bottom hollow box
290
      u8g.drawFrame(42, 49 - (TALL_FONT_CORRECTION), 10, 4);  // 49-52 (or 48-51)
291
      // Corner pixel
292
      u8g.drawPixel(50, 43 - (TALL_FONT_CORRECTION));         // 43 (or 42)
293
    }
294
  #endif // SDSUPPORT
295
 
296
  #if ENABLED(SDSUPPORT) || ENABLED(LCD_SET_PROGRESS_MANUALLY)
297
    //
298
    // Progress bar frame
299
    //
300
    #define PROGRESS_BAR_X 54
301
    #define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X)
302
 
303
    if (PAGE_CONTAINS(49, 52 - (TALL_FONT_CORRECTION)))       // 49-52 (or 49-51)
304
      u8g.drawFrame(
305
        PROGRESS_BAR_X, 49,
306
        PROGRESS_BAR_WIDTH, 4 - (TALL_FONT_CORRECTION)
307
      );
308
 
309
    #if DISABLED(LCD_SET_PROGRESS_MANUALLY)
310
      const uint8_t progress_bar_percent = card.percentDone();
311
    #endif
312
 
313
    if (progress_bar_percent > 1) {
314
 
315
      //
316
      // Progress bar solid part
317
      //
318
 
319
      if (PAGE_CONTAINS(50, 51 - (TALL_FONT_CORRECTION)))     // 50-51 (or just 50)
320
        u8g.drawBox(
321
          PROGRESS_BAR_X + 1, 50,
322
          (uint16_t)((PROGRESS_BAR_WIDTH - 2) * progress_bar_percent * 0.01), 2 - (TALL_FONT_CORRECTION)
323
        );
324
 
325
      //
326
      // SD Percent Complete
327
      //
328
 
329
      #if ENABLED(DOGM_SD_PERCENT)
330
        if (PAGE_CONTAINS(41, 48)) {
331
          // Percent complete
332
          u8g.setPrintPos(55, 48);
333
          u8g.print(itostr3(progress_bar_percent));
334
          u8g.print('%');
335
        }
336
      #endif
337
    }
338
 
339
    //
340
    // Elapsed Time
341
    //
342
 
343
    #if DISABLED(DOGM_SD_PERCENT)
344
      #define SD_DURATION_X (PROGRESS_BAR_X + (PROGRESS_BAR_WIDTH / 2) - len * (DOG_CHAR_WIDTH / 2))
345
    #else
346
      #define SD_DURATION_X (LCD_PIXEL_WIDTH - len * DOG_CHAR_WIDTH)
347
    #endif
348
 
349
    if (PAGE_CONTAINS(41, 48)) {
350
      char buffer[10];
351
      duration_t elapsed = print_job_timer.duration();
352
      bool has_days = (elapsed.value >= 60*60*24L);
353
      uint8_t len = elapsed.toDigital(buffer, has_days);
354
      u8g.setPrintPos(SD_DURATION_X, 48);
355
      lcd_print(buffer);
356
    }
357
 
358
  #endif // SDSUPPORT || LCD_SET_PROGRESS_MANUALLY
359
 
360
  //
361
  // XYZ Coordinates
362
  //
363
 
364
  #define XYZ_BASELINE (30 + INFO_FONT_HEIGHT)
365
 
366
  #define X_LABEL_POS  3
367
  #define X_VALUE_POS 11
368
  #define XYZ_SPACING 40
369
 
370
  #if ENABLED(XYZ_HOLLOW_FRAME)
371
    #define XYZ_FRAME_TOP 29
372
    #define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 3
373
  #else
374
    #define XYZ_FRAME_TOP 30
375
    #define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 1
376
  #endif
377
 
378
  static char xstring[5], ystring[5], zstring[7];
379
  #if ENABLED(FILAMENT_LCD_DISPLAY)
380
    static char wstring[5], mstring[4];
381
  #endif
382
 
383
  // At the first page, regenerate the XYZ strings
384
  if (page.page == 0) {
385
    strcpy(xstring, ftostr4sign(LOGICAL_X_POSITION(current_position[X_AXIS])));
386
    strcpy(ystring, ftostr4sign(LOGICAL_Y_POSITION(current_position[Y_AXIS])));
387
    strcpy(zstring, ftostr52sp(LOGICAL_Z_POSITION(current_position[Z_AXIS])));
388
    #if ENABLED(FILAMENT_LCD_DISPLAY)
389
      strcpy(wstring, ftostr12ns(filament_width_meas));
390
      strcpy(mstring, itostr3(100.0 * (
391
          parser.volumetric_enabled
392
            ? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
393
            : planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
394
        )
395
      ));
396
    #endif
397
  }
398
 
399
  if (PAGE_CONTAINS(XYZ_FRAME_TOP, XYZ_FRAME_TOP + XYZ_FRAME_HEIGHT - 1)) {
400
 
401
    #if ENABLED(XYZ_HOLLOW_FRAME)
402
      u8g.drawFrame(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 29-40  7: 29-39
403
    #else
404
      u8g.drawBox(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT);   // 8: 30-39  7: 30-37
405
    #endif
406
 
407
    if (PAGE_CONTAINS(XYZ_BASELINE - (INFO_FONT_HEIGHT - 1), XYZ_BASELINE)) {
408
 
409
      #if DISABLED(XYZ_HOLLOW_FRAME)
410
        u8g.setColorIndex(0); // white on black
411
      #endif
412
 
413
      u8g.setPrintPos(0 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
414
      lcd_printPGM(PSTR(MSG_X));
415
      u8g.setPrintPos(0 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
416
      _draw_axis_value(X_AXIS, xstring, blink);
417
 
418
      u8g.setPrintPos(1 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
419
      lcd_printPGM(PSTR(MSG_Y));
420
      u8g.setPrintPos(1 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
421
      _draw_axis_value(Y_AXIS, ystring, blink);
422
 
423
      u8g.setPrintPos(2 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
424
      lcd_printPGM(PSTR(MSG_Z));
425
      u8g.setPrintPos(2 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
426
      _draw_axis_value(Z_AXIS, zstring, blink);
427
 
428
      #if DISABLED(XYZ_HOLLOW_FRAME)
429
        u8g.setColorIndex(1); // black on white
430
      #endif
431
    }
432
  }
433
 
434
  //
435
  // Feedrate
436
  //
437
 
438
  if (PAGE_CONTAINS(51 - INFO_FONT_HEIGHT, 49)) {
439
    lcd_setFont(FONT_MENU);
440
    u8g.setPrintPos(3, 50);
441
    lcd_print(LCD_STR_FEEDRATE[0]);
442
 
443
    lcd_setFont(FONT_STATUSMENU);
444
    u8g.setPrintPos(12, 50);
445
    lcd_print(itostr3(feedrate_percentage));
446
    u8g.print('%');
447
 
448
    //
449
    // Filament sensor display if SD is disabled
450
    //
451
    #if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT)
452
      u8g.setPrintPos(56, 50);
453
      lcd_print(wstring);
454
      u8g.setPrintPos(102, 50);
455
      lcd_print(mstring);
456
      u8g.print('%');
457
      lcd_setFont(FONT_MENU);
458
      u8g.setPrintPos(47, 50);
459
      lcd_print(LCD_STR_FILAM_DIA);
460
      u8g.setPrintPos(93, 50);
461
      lcd_print(LCD_STR_FILAM_MUL);
462
    #endif
463
  }
464
 
465
  //
466
  // Status line
467
  //
468
 
469
  #define STATUS_BASELINE (55 + INFO_FONT_HEIGHT)
470
 
471
  if (PAGE_CONTAINS(STATUS_BASELINE - (INFO_FONT_HEIGHT - 1), STATUS_BASELINE)) {
472
    u8g.setPrintPos(0, STATUS_BASELINE);
473
 
474
    #if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
475
      if (PENDING(millis(), previous_lcd_status_ms + 5000UL)) {  //Display both Status message line and Filament display on the last line
476
        lcd_implementation_status_message(blink);
477
      }
478
      else {
479
        lcd_printPGM(PSTR(LCD_STR_FILAM_DIA));
480
        u8g.print(':');
481
        lcd_print(wstring);
482
        lcd_printPGM(PSTR("  " LCD_STR_FILAM_MUL));
483
        u8g.print(':');
484
        lcd_print(mstring);
485
        u8g.print('%');
486
      }
487
    #else
488
      lcd_implementation_status_message(blink);
489
    #endif
490
  }
491
}
492
 
493
#endif // _STATUS_SCREEN_DOGM_H_