|
@@ -235,6 +235,14 @@ void ST7920_Lite_Status_Screen::draw_gdram_icon(uint8_t x, uint8_t y, const void
|
235
|
235
|
#define CGRAM_ICON_3_WORD 0x04
|
236
|
236
|
#define CGRAM_ICON_4_WORD 0x06
|
237
|
237
|
|
|
238
|
+const uint8_t degree_symbol_y_top = 1;
|
|
239
|
+PROGMEM const uint8_t degree_symbol[] = {
|
|
240
|
+ 0b00110000,
|
|
241
|
+ 0b01001000,
|
|
242
|
+ 0b01001000,
|
|
243
|
+ 0b00110000,
|
|
244
|
+};
|
|
245
|
+
|
238
|
246
|
const uint16_t nozzle_icon[] PROGMEM = {
|
239
|
247
|
0b0000000000000000,
|
240
|
248
|
0b0000000000000000,
|
|
@@ -352,24 +360,54 @@ const uint16_t fan2_icon[] PROGMEM = {
|
352
|
360
|
const uint16_t feedrate_icon[] PROGMEM = {
|
353
|
361
|
0b0000000000000000,
|
354
|
362
|
0b0111111000000000,
|
355
|
|
- 0b0100000000000000,
|
356
|
|
- 0b0100000000000000,
|
357
|
|
- 0b0100000000000000,
|
|
363
|
+ 0b0110000000000000,
|
|
364
|
+ 0b0110000000000000,
|
|
365
|
+ 0b0110000000000000,
|
358
|
366
|
0b0111111011111000,
|
359
|
|
- 0b0100000010000100,
|
360
|
|
- 0b0100000010000100,
|
361
|
|
- 0b0100000010000100,
|
362
|
|
- 0b0100000011111000,
|
363
|
|
- 0b0000000010001000,
|
364
|
|
- 0b0000000010000100,
|
365
|
|
- 0b0000000010000100,
|
366
|
|
- 0b0000000010000010,
|
|
367
|
+ 0b0110000011001100,
|
|
368
|
+ 0b0110000011001100,
|
|
369
|
+ 0b0110000011001100,
|
|
370
|
+ 0b0110000011111000,
|
|
371
|
+ 0b0000000011001100,
|
|
372
|
+ 0b0000000011001100,
|
|
373
|
+ 0b0000000011001100,
|
|
374
|
+ 0b0000000011001100,
|
367
|
375
|
0b0000000000000000,
|
368
|
376
|
0b0000000000000000
|
369
|
377
|
};
|
370
|
378
|
|
371
|
379
|
/************************** MAIN SCREEN *************************************/
|
372
|
380
|
|
|
381
|
+// The ST7920 does not have a degree character, but we
|
|
382
|
+// can fake it by writing it to GDRAM.
|
|
383
|
+// This function takes as an argument character positions
|
|
384
|
+// i.e x is [1-16], while the y position is [1-4]
|
|
385
|
+void ST7920_Lite_Status_Screen::draw_degree_symbol(uint8_t x, uint8_t y, bool draw) {
|
|
386
|
+ const uint8_t *p_bytes = degree_symbol;
|
|
387
|
+ if (y > 2) {
|
|
388
|
+ // Handle display folding
|
|
389
|
+ y -= 2;
|
|
390
|
+ x += 16;
|
|
391
|
+ }
|
|
392
|
+ x -= 1;
|
|
393
|
+ y -= 1;
|
|
394
|
+ const bool oddChar = x & 1;
|
|
395
|
+ const uint8_t x_word = x >> 1;
|
|
396
|
+ const uint8_t y_top = degree_symbol_y_top;
|
|
397
|
+ const uint8_t y_bot = y_top + sizeof(degree_symbol)/sizeof(degree_symbol[0]);
|
|
398
|
+ for(uint8_t i = y_top; i < y_bot; i++) {
|
|
399
|
+ uint8_t byte = pgm_read_byte_near(p_bytes++);
|
|
400
|
+ set_gdram_address(x_word,i+y*16);
|
|
401
|
+ begin_data();
|
|
402
|
+ if (draw) {
|
|
403
|
+ write_byte(oddChar ? 0x00 : byte);
|
|
404
|
+ write_byte(oddChar ? byte : 0x00);
|
|
405
|
+ }
|
|
406
|
+ else
|
|
407
|
+ write_word(0x0000);
|
|
408
|
+ }
|
|
409
|
+}
|
|
410
|
+
|
373
|
411
|
void ST7920_Lite_Status_Screen::draw_static_elements() {
|
374
|
412
|
scroll_or_addr_select(0);
|
375
|
413
|
|
|
@@ -406,13 +444,13 @@ void ST7920_Lite_Status_Screen::draw_progress_bar(const uint8_t value) {
|
406
|
444
|
// If we have only one extruder, draw a long progress bar on the third line
|
407
|
445
|
const uint8_t top = 1, // Top in pixels
|
408
|
446
|
bottom = 13, // Bottom in pixels
|
409
|
|
- left = 8, // Left edge, in 16-bit words
|
410
|
|
- width = 5; // Width of progress bar, in 16-bit words
|
|
447
|
+ left = 12, // Left edge, in 16-bit words
|
|
448
|
+ width = 4; // Width of progress bar, in 16-bit words
|
411
|
449
|
#else
|
412
|
|
- const uint8_t top = 16 + 1, // Top in pixels
|
413
|
|
- bottom = 16 + 13, // Bottom in pixels
|
414
|
|
- left = 5, // Left edge, in 16-bit words
|
415
|
|
- width = 3; // Width of progress bar, in 16-bit words
|
|
450
|
+ const uint8_t top = 16 + 1,
|
|
451
|
+ bottom = 16 + 13,
|
|
452
|
+ left = 5,
|
|
453
|
+ width = 3;
|
416
|
454
|
#endif
|
417
|
455
|
const uint8_t char_pcnt = 100 / width; // How many percent does each 16-bit word represent?
|
418
|
456
|
|
|
@@ -439,15 +477,16 @@ void ST7920_Lite_Status_Screen::draw_progress_bar(const uint8_t value) {
|
439
|
477
|
}
|
440
|
478
|
|
441
|
479
|
// Draw the percentage as text in DDRAM
|
442
|
|
- set_ddram_address(
|
443
|
|
- #if EXTRUDERS == 1
|
444
|
|
- DDRAM_LINE_3 + 1
|
445
|
|
- #else
|
446
|
|
- DDRAM_LINE_2 + left
|
447
|
|
- #endif
|
448
|
|
- );
|
|
480
|
+ #if EXTRUDERS == 1
|
|
481
|
+ set_ddram_address(DDRAM_LINE_3 + 4);
|
|
482
|
+ begin_data();
|
|
483
|
+ write_byte(' ');
|
|
484
|
+ #else
|
|
485
|
+ set_ddram_address(DDRAM_LINE_2 + left);
|
|
486
|
+ begin_data();
|
|
487
|
+ #endif
|
449
|
488
|
|
450
|
|
- begin_data();
|
|
489
|
+ // Draw centered
|
451
|
490
|
if (value > 9) {
|
452
|
491
|
write_number(value, 4);
|
453
|
492
|
write_str(F("% "));
|
|
@@ -481,65 +520,85 @@ void ST7920_Lite_Status_Screen::draw_heat_icon(const bool whichIcon, const bool
|
481
|
520
|
}
|
482
|
521
|
}
|
483
|
522
|
|
484
|
|
-#define FAR(a,b) (((a > b) ? (a-b) : (b-a)) > 1)
|
|
523
|
+#define FAR(a,b) (((a > b) ? (a-b) : (b-a)) > 2)
|
|
524
|
+
|
|
525
|
+static struct {
|
|
526
|
+ bool E1_show_target : 1;
|
|
527
|
+ bool E2_show_target : 1;
|
|
528
|
+ #if HAS_HEATER_BED
|
|
529
|
+ bool bed_show_target : 1;
|
|
530
|
+ #endif
|
|
531
|
+} display_state = {
|
|
532
|
+ true, true
|
|
533
|
+ #if HAS_HEATER_BED
|
|
534
|
+ , true
|
|
535
|
+ #endif
|
|
536
|
+};
|
485
|
537
|
|
486
|
|
-void ST7920_Lite_Status_Screen::draw_extruder_1_temp(const int16_t temp, const int16_t target) {
|
487
|
|
- set_ddram_address(DDRAM_LINE_1 + 1);
|
|
538
|
+void ST7920_Lite_Status_Screen::draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange) {
|
|
539
|
+ switch (line) {
|
|
540
|
+ case 1: set_ddram_address(DDRAM_LINE_1 + 1); break;
|
|
541
|
+ case 2: set_ddram_address(DDRAM_LINE_2 + 1); break;
|
|
542
|
+ case 3: set_ddram_address(DDRAM_LINE_3 + 1); break;
|
|
543
|
+ case 4: set_ddram_address(DDRAM_LINE_3 + 1); break;
|
|
544
|
+ }
|
488
|
545
|
begin_data();
|
489
|
546
|
write_number(temp);
|
490
|
|
- if (target && FAR(temp, target)) {
|
|
547
|
+
|
|
548
|
+ if (showTarget) {
|
491
|
549
|
write_str(F("\x1A"));
|
492
|
550
|
write_number(target);
|
|
551
|
+ };
|
|
552
|
+
|
|
553
|
+ if (targetStateChange) {
|
|
554
|
+ if (!showTarget) write_str(F(" "));
|
|
555
|
+ draw_degree_symbol(6, line, !showTarget);
|
|
556
|
+ draw_degree_symbol(10, line, showTarget);
|
493
|
557
|
}
|
494
|
|
- else
|
495
|
|
- write_str(F(" "));
|
496
|
558
|
}
|
497
|
559
|
|
498
|
|
-void ST7920_Lite_Status_Screen::draw_extruder_2_temp(const int16_t temp, const int16_t target) {
|
499
|
|
- set_ddram_address(DDRAM_LINE_2 + 1);
|
500
|
|
- begin_data();
|
501
|
|
- write_number(temp);
|
502
|
|
- if (target && FAR(temp, target)) {
|
503
|
|
- write_str(F("\x1A"));
|
504
|
|
- write_number(target);
|
505
|
|
- }
|
506
|
|
- else
|
507
|
|
- write_str(F(" "));
|
|
560
|
+void ST7920_Lite_Status_Screen::draw_extruder_1_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
|
|
561
|
+ const bool show_target = target && FAR(temp, target);
|
|
562
|
+ draw_temps(1, temp, target, show_target, display_state.E1_show_target != show_target || forceUpdate);
|
|
563
|
+ display_state.E1_show_target = show_target;
|
508
|
564
|
}
|
509
|
565
|
|
510
|
|
-void ST7920_Lite_Status_Screen::draw_bed_temp(const int16_t temp, const int16_t target) {
|
511
|
|
- set_ddram_address(
|
512
|
|
- #if EXTRUDERS == 1
|
513
|
|
- DDRAM_LINE_2 + 1
|
514
|
|
- #else
|
515
|
|
- DDRAM_LINE_3 + 1
|
516
|
|
- #endif
|
517
|
|
- );
|
518
|
|
- begin_data();
|
519
|
|
- write_number(temp);
|
520
|
|
- if (target && FAR(temp, target)) {
|
521
|
|
- write_str(F("\x1A"));
|
522
|
|
- write_number(target);
|
523
|
|
- }
|
524
|
|
- else
|
525
|
|
- write_str(F(" "));
|
|
566
|
+void ST7920_Lite_Status_Screen::draw_extruder_2_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
|
|
567
|
+ const bool show_target = target && FAR(temp, target);
|
|
568
|
+ draw_temps(2, temp, target, show_target, display_state.E2_show_target != show_target || forceUpdate);
|
|
569
|
+ display_state.E2_show_target = show_target;
|
526
|
570
|
}
|
527
|
571
|
|
|
572
|
+#if HAS_HEATER_BED
|
|
573
|
+ void ST7920_Lite_Status_Screen::draw_bed_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
|
|
574
|
+ const bool show_target = target && FAR(temp, target);
|
|
575
|
+ draw_temps(2
|
|
576
|
+ #if EXTRUDERS > 1
|
|
577
|
+ + 1
|
|
578
|
+ #endif
|
|
579
|
+ , temp, target, show_target, display_state.bed_show_target != show_target || forceUpdate
|
|
580
|
+ );
|
|
581
|
+ display_state.bed_show_target = show_target;
|
|
582
|
+ }
|
|
583
|
+#endif
|
|
584
|
+
|
528
|
585
|
void ST7920_Lite_Status_Screen::draw_fan_speed(const uint8_t value) {
|
529
|
586
|
set_ddram_address(DDRAM_LINE_1 + 6);
|
530
|
587
|
begin_data();
|
531
|
|
- write_number(value, 4);
|
|
588
|
+ write_number(value, 3);
|
|
589
|
+ write_byte('%');
|
532
|
590
|
}
|
533
|
591
|
|
534
|
|
-void ST7920_Lite_Status_Screen::draw_print_time(const uint32_t elapsed) {
|
535
|
|
- const uint8_t hrs = elapsed / 3600,
|
536
|
|
- min = (elapsed / 60) % 60;
|
|
592
|
+void ST7920_Lite_Status_Screen::draw_print_time(const duration_t &elapsed) {
|
|
593
|
+ #if EXTRUDERS == 1
|
|
594
|
+ set_ddram_address(DDRAM_LINE_3);
|
|
595
|
+ #else
|
|
596
|
+ set_ddram_address(DDRAM_LINE_3 + 5);
|
|
597
|
+ #endif
|
537
|
598
|
char str[7];
|
538
|
|
- sprintf_P(str, hrs > 99 ? PSTR("%03d:%02d") : PSTR(" %02d:%02d"), hrs, min);
|
539
|
|
-
|
540
|
|
- set_ddram_address(DDRAM_LINE_3 + 5);
|
|
599
|
+ str[elapsed.toDigital(str)] = ' ';
|
541
|
600
|
begin_data();
|
542
|
|
- write_str(str);
|
|
601
|
+ write_str(str, 6);
|
543
|
602
|
}
|
544
|
603
|
|
545
|
604
|
void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint8_t percentage) {
|
|
@@ -548,7 +607,8 @@ void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint8_t percentag
|
548
|
607
|
#if EXTRUDERS == 1
|
549
|
608
|
set_ddram_address(DDRAM_LINE_2 + 6);
|
550
|
609
|
begin_data();
|
551
|
|
- write_number(percentage, 4);
|
|
610
|
+ write_number(percentage, 3);
|
|
611
|
+ write_byte('%');
|
552
|
612
|
#endif
|
553
|
613
|
}
|
554
|
614
|
|
|
@@ -616,26 +676,23 @@ bool ST7920_Lite_Status_Screen::indicators_changed() {
|
616
|
676
|
const bool blink = lcd_blink();
|
617
|
677
|
const uint8_t feedrate_perc = feedrate_percentage;
|
618
|
678
|
const uint8_t fan_speed = ((fanSpeeds[0] + 1) * 100) / 256;
|
619
|
|
- const float extruder_1_target = thermalManager.degTargetHotend(0);
|
|
679
|
+ const int16_t extruder_1_target = thermalManager.degTargetHotend(0);
|
620
|
680
|
#if EXTRUDERS == 2
|
621
|
|
- const float extruder_2_target = thermalManager.degTargetHotend(1);
|
|
681
|
+ const int16_t extruder_2_target = thermalManager.degTargetHotend(1);
|
622
|
682
|
#endif
|
623
|
|
- const float bed_target = thermalManager.degTargetBed();
|
624
|
|
-
|
625
|
|
- static uint8_t last_checksum = 0;
|
626
|
|
-
|
627
|
|
- const uint8_t checksum =
|
628
|
|
- uint8_t(blink) ^
|
629
|
|
- uint8_t(feedrate_perc) ^
|
630
|
|
- uint8_t(fan_speed) ^
|
631
|
|
- uint8_t(extruder_1_target) ^
|
|
683
|
+ #if HAS_HEATER_BED
|
|
684
|
+ const int16_t bed_target = thermalManager.degTargetBed();
|
|
685
|
+ #endif
|
|
686
|
+ static uint16_t last_checksum = 0;
|
|
687
|
+ const uint16_t checksum = blink ^ feedrate_perc ^ fan_speed ^ extruder_1_target
|
632
|
688
|
#if EXTRUDERS == 2
|
633
|
|
- uint8_t(extruder_2_target) ^
|
|
689
|
+ ^ extruder_2_target
|
634
|
690
|
#endif
|
635
|
|
- uint8_t(bed_target);
|
636
|
|
-
|
|
691
|
+ #if HAS_HEATER_BED
|
|
692
|
+ ^ bed_target
|
|
693
|
+ #endif
|
|
694
|
+ ;
|
637
|
695
|
if (last_checksum == checksum) return false;
|
638
|
|
-
|
639
|
696
|
last_checksum = checksum;
|
640
|
697
|
return true;
|
641
|
698
|
}
|
|
@@ -644,33 +701,38 @@ void ST7920_Lite_Status_Screen::update_indicators(const bool forceUpdate) {
|
644
|
701
|
if (forceUpdate || indicators_changed()) {
|
645
|
702
|
const bool blink = lcd_blink();
|
646
|
703
|
const duration_t elapsed = print_job_timer.duration();
|
647
|
|
- const uint32_t seconds_elapsed = elapsed.value;
|
648
|
704
|
const uint8_t feedrate_perc = feedrate_percentage;
|
649
|
705
|
const uint8_t fan_speed = ((fanSpeeds[0] + 1) * 100) / 256;
|
650
|
|
- const float extruder_1_temp = thermalManager.degHotend(0);
|
651
|
|
- const float extruder_1_target = thermalManager.degTargetHotend(0);
|
|
706
|
+ const int16_t extruder_1_temp = thermalManager.degHotend(0),
|
|
707
|
+ extruder_1_target = thermalManager.degTargetHotend(0);
|
652
|
708
|
#if EXTRUDERS == 2
|
653
|
|
- const float extruder_2_temp = thermalManager.degHotend(1);
|
654
|
|
- const float extruder_2_target = thermalManager.degTargetHotend(1);
|
|
709
|
+ const int16_t extruder_2_temp = thermalManager.degHotend(1),
|
|
710
|
+ extruder_2_target = thermalManager.degTargetHotend(1);
|
|
711
|
+ #endif
|
|
712
|
+ #if HAS_HEATER_BED
|
|
713
|
+ const int16_t bed_temp = thermalManager.degBed(),
|
|
714
|
+ bed_target = thermalManager.degTargetBed();
|
655
|
715
|
#endif
|
656
|
|
- const float bed_temp = thermalManager.degBed();
|
657
|
|
- const float bed_target = thermalManager.degTargetBed();
|
658
|
716
|
|
659
|
|
- draw_extruder_1_temp(extruder_1_temp, extruder_1_target);
|
|
717
|
+ draw_extruder_1_temp(extruder_1_temp, extruder_1_target, forceUpdate);
|
660
|
718
|
#if EXTRUDERS == 2
|
661
|
|
- draw_extruder_2_temp(extruder_2_temp, extruder_2_target);
|
|
719
|
+ draw_extruder_2_temp(extruder_2_temp, extruder_2_target, forceUpdate);
|
|
720
|
+ #endif
|
|
721
|
+ #if HAS_HEATER_BED
|
|
722
|
+ draw_bed_temp(bed_temp, bed_target, forceUpdate);
|
662
|
723
|
#endif
|
663
|
|
- draw_bed_temp(bed_temp, bed_target);
|
664
|
724
|
draw_fan_speed(fan_speed);
|
665
|
|
- draw_print_time(seconds_elapsed);
|
|
725
|
+ draw_print_time(elapsed);
|
666
|
726
|
draw_feedrate_percentage(feedrate_perc);
|
667
|
727
|
|
668
|
728
|
// Update the fan and bed animations
|
669
|
729
|
if (fan_speed > 0) draw_fan_icon(blink);
|
670
|
|
- if (bed_target > 0)
|
671
|
|
- draw_heat_icon(blink, true);
|
672
|
|
- else
|
673
|
|
- draw_heat_icon(false, false);
|
|
730
|
+ #if HAS_HEATER_BED
|
|
731
|
+ if (bed_target > 0)
|
|
732
|
+ draw_heat_icon(blink, true);
|
|
733
|
+ else
|
|
734
|
+ draw_heat_icon(false, false);
|
|
735
|
+ #endif
|
674
|
736
|
}
|
675
|
737
|
}
|
676
|
738
|
|
|
@@ -689,7 +751,6 @@ bool ST7920_Lite_Status_Screen::position_changed() {
|
689
|
751
|
bool ST7920_Lite_Status_Screen::status_changed() {
|
690
|
752
|
uint8_t checksum = 0;
|
691
|
753
|
for (const char *p = lcd_status_message; *p; p++) checksum ^= *p;
|
692
|
|
-
|
693
|
754
|
static uint8_t last_checksum = 0;
|
694
|
755
|
if (last_checksum == checksum) return false;
|
695
|
756
|
last_checksum = checksum;
|
|
@@ -766,23 +827,24 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
|
766
|
827
|
}
|
767
|
828
|
|
768
|
829
|
void ST7920_Lite_Status_Screen::update_progress(const bool forceUpdate) {
|
769
|
|
- const uint8_t percent_done =
|
770
|
|
- #if ENABLED(SDSUPPORT)
|
771
|
|
- card.percentDone()
|
772
|
|
- #else
|
773
|
|
- 0
|
774
|
|
- #endif
|
775
|
|
- ;
|
|
830
|
+ #if DISABLED(LCD_SET_PROGRESS_MANUALLY)
|
|
831
|
+ uint8_t progress_bar_percent;
|
|
832
|
+ #endif
|
|
833
|
+
|
|
834
|
+ // Set current percentage from SD when actively printing
|
|
835
|
+ #if ENABLED(SDSUPPORT)
|
|
836
|
+ if (IS_SD_PRINTING) progress_bar_percent = card.percentDone();
|
|
837
|
+ #endif
|
776
|
838
|
|
777
|
839
|
// Since the progress bar involves writing
|
778
|
840
|
// quite a few bytes to GDRAM, only do this
|
779
|
841
|
// when an update is actually necessary.
|
780
|
842
|
|
781
|
843
|
static uint8_t last_progress = 0;
|
782
|
|
- if (!forceUpdate && last_progress == percent_done) return;
|
783
|
|
- last_progress = percent_done;
|
|
844
|
+ if (!forceUpdate && last_progress == progress_bar_percent) return;
|
|
845
|
+ last_progress = progress_bar_percent;
|
784
|
846
|
|
785
|
|
- draw_progress_bar(percent_done);
|
|
847
|
+ draw_progress_bar(progress_bar_percent);
|
786
|
848
|
}
|
787
|
849
|
|
788
|
850
|
void ST7920_Lite_Status_Screen::update(const bool forceUpdate) {
|