Pārlūkot izejas kodu

✨ MAX7219 idle profiler (#24375)

tombrazier 3 gadus atpakaļ
vecāks
revīzija
2266f1ad67
Revīzijas autora e-pasta adrese nav piesaistīta nevienam kontam

+ 8
- 4
Marlin/Configuration_adv.h Parādīt failu

3595
                                                // ESP32: If SPINDLE_LASER_PWM_PIN is onboard then <=78125Hz. For I2S expander
3595
                                                // ESP32: If SPINDLE_LASER_PWM_PIN is onboard then <=78125Hz. For I2S expander
3596
                                                //  the frequency determines the PWM resolution. 2500Hz = 0-100, 977Hz = 0-255, ...
3596
                                                //  the frequency determines the PWM resolution. 2500Hz = 0-100, 977Hz = 0-255, ...
3597
                                                //  (250000 / SPINDLE_LASER_FREQUENCY) = max value.
3597
                                                //  (250000 / SPINDLE_LASER_FREQUENCY) = max value.
3598
-#endif
3598
+  #endif
3599
 
3599
 
3600
   //#define AIR_EVACUATION                     // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
3600
   //#define AIR_EVACUATION                     // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
3601
   #if ENABLED(AIR_EVACUATION)
3601
   #if ENABLED(AIR_EVACUATION)
4289
   #define MAX7219_NUMBER_UNITS 1   // Number of Max7219 units in chain.
4289
   #define MAX7219_NUMBER_UNITS 1   // Number of Max7219 units in chain.
4290
   #define MAX7219_ROTATE       0   // Rotate the display clockwise (in multiples of +/- 90°)
4290
   #define MAX7219_ROTATE       0   // Rotate the display clockwise (in multiples of +/- 90°)
4291
                                    // connector at:  right=0   bottom=-90  top=90  left=180
4291
                                    // connector at:  right=0   bottom=-90  top=90  left=180
4292
-  //#define MAX7219_REVERSE_ORDER  // The individual LED matrix units may be in reversed order
4292
+  //#define MAX7219_REVERSE_ORDER  // The order of the LED matrix units may be reversed
4293
+  //#define MAX7219_REVERSE_EACH   // The LEDs in each matrix unit row may be reversed
4293
   //#define MAX7219_SIDE_BY_SIDE   // Big chip+matrix boards can be chained side-by-side
4294
   //#define MAX7219_SIDE_BY_SIDE   // Big chip+matrix boards can be chained side-by-side
4294
 
4295
 
4295
   /**
4296
   /**
4297
    * If you add more debug displays, be careful to avoid conflicts!
4298
    * If you add more debug displays, be careful to avoid conflicts!
4298
    */
4299
    */
4299
   #define MAX7219_DEBUG_PRINTER_ALIVE    // Blink corner LED of 8x8 matrix to show that the firmware is functioning
4300
   #define MAX7219_DEBUG_PRINTER_ALIVE    // Blink corner LED of 8x8 matrix to show that the firmware is functioning
4300
-  #define MAX7219_DEBUG_PLANNER_HEAD  3  // Show the planner queue head position on this and the next LED matrix row
4301
-  #define MAX7219_DEBUG_PLANNER_TAIL  5  // Show the planner queue tail position on this and the next LED matrix row
4301
+  #define MAX7219_DEBUG_PLANNER_HEAD  2  // Show the planner queue head position on this and the next LED matrix row
4302
+  #define MAX7219_DEBUG_PLANNER_TAIL  4  // Show the planner queue tail position on this and the next LED matrix row
4302
 
4303
 
4303
   #define MAX7219_DEBUG_PLANNER_QUEUE 0  // Show the current planner queue depth on this and the next LED matrix row
4304
   #define MAX7219_DEBUG_PLANNER_QUEUE 0  // Show the current planner queue depth on this and the next LED matrix row
4304
                                          // If you experience stuttering, reboots, etc. this option can reveal how
4305
                                          // If you experience stuttering, reboots, etc. this option can reveal how
4305
                                          // tweaks made to the configuration are affecting the printer in real-time.
4306
                                          // tweaks made to the configuration are affecting the printer in real-time.
4307
+  #define MAX7219_DEBUG_PROFILE       6  // Display the fraction of CPU time spent in profiled code on this LED matrix
4308
+                                         // row. By default idle() is profiled so this shows how "idle" the processor is.
4309
+                                         // See class CodeProfiler.
4306
 #endif
4310
 #endif
4307
 
4311
 
4308
 /**
4312
 /**

+ 4
- 0
Marlin/src/MarlinCore.cpp Parādīt failu

776
  *  - Handle Joystick jogging
776
  *  - Handle Joystick jogging
777
  */
777
  */
778
 void idle(bool no_stepper_sleep/*=false*/) {
778
 void idle(bool no_stepper_sleep/*=false*/) {
779
+  #ifdef MAX7219_DEBUG_PROFILE
780
+    CodeProfiler idle_profiler;
781
+  #endif
782
+
779
   #if ENABLED(MARLIN_DEV_MODE)
783
   #if ENABLED(MARLIN_DEV_MODE)
780
     static uint16_t idle_depth = 0;
784
     static uint16_t idle_depth = 0;
781
     if (++idle_depth > 5) SERIAL_ECHOLNPGM("idle() call depth: ", idle_depth);
785
     if (++idle_depth > 5) SERIAL_ECHOLNPGM("idle() call depth: ", idle_depth);

+ 68
- 36
Marlin/src/feature/max7219.cpp Parādīt failu

62
   #error "MAX7219_ROTATE must be a multiple of +/- 90°."
62
   #error "MAX7219_ROTATE must be a multiple of +/- 90°."
63
 #endif
63
 #endif
64
 
64
 
65
+#ifdef MAX7219_DEBUG_PROFILE
66
+  CodeProfiler::Mode CodeProfiler::mode = ACCUMULATE_AVERAGE;
67
+  uint8_t CodeProfiler::instance_count = 0;
68
+  uint32_t CodeProfiler::last_calc_time = micros();
69
+  uint8_t CodeProfiler::time_fraction = 0;
70
+  uint32_t CodeProfiler::total_time = 0;
71
+  uint16_t CodeProfiler::call_count = 0;
72
+#endif
73
+
65
 Max7219 max7219;
74
 Max7219 max7219;
66
 
75
 
67
 uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
76
 uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
69
 
78
 
70
 #define LINE_REG(Q)     (max7219_reg_digit0 + ((Q) & 0x7))
79
 #define LINE_REG(Q)     (max7219_reg_digit0 + ((Q) & 0x7))
71
 
80
 
72
-#if _ROT == 0 || _ROT == 270
81
+#if (_ROT == 0 || _ROT == 270) == DISABLED(MAX7219_REVERSE_EACH)
73
   #define _LED_BIT(Q)   (7 - ((Q) & 0x7))
82
   #define _LED_BIT(Q)   (7 - ((Q) & 0x7))
74
 #else
83
 #else
75
   #define _LED_BIT(Q)   ((Q) & 0x7)
84
   #define _LED_BIT(Q)   ((Q) & 0x7)
266
 #endif // MAX7219_NUMERIC
275
 #endif // MAX7219_NUMERIC
267
 
276
 
268
 // Modify a single LED bit and send the changed line
277
 // Modify a single LED bit and send the changed line
269
-void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) {
278
+void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm/*=nullptr*/) {
270
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y);
279
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y);
271
   if (BIT_7219(x, y) == on) return;
280
   if (BIT_7219(x, y) == on) return;
272
   XOR_7219(x, y);
281
   XOR_7219(x, y);
273
   refresh_unit_line(LED_IND(x, y));
282
   refresh_unit_line(LED_IND(x, y));
283
+  if (rcm != nullptr) *rcm |= _BV(LED_IND(x, y) & 0x07);
274
 }
284
 }
275
 
285
 
276
-void Max7219::led_on(const uint8_t x, const uint8_t y) {
286
+void Max7219::led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
277
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y);
287
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y);
278
-  led_set(x, y, true);
288
+  led_set(x, y, true, rcm);
279
 }
289
 }
280
 
290
 
281
-void Max7219::led_off(const uint8_t x, const uint8_t y) {
291
+void Max7219::led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
282
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y);
292
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y);
283
-  led_set(x, y, false);
293
+  led_set(x, y, false, rcm);
284
 }
294
 }
285
 
295
 
286
-void Max7219::led_toggle(const uint8_t x, const uint8_t y) {
296
+void Max7219::led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
287
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y);
297
   if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y);
288
-  led_set(x, y, !BIT_7219(x, y));
298
+  led_set(x, y, !BIT_7219(x, y), rcm);
289
 }
299
 }
290
 
300
 
291
 void Max7219::send_row(const uint8_t row) {
301
 void Max7219::send_row(const uint8_t row) {
448
   pulse_load();                               // Tell the chips to load the clocked out data
458
   pulse_load();                               // Tell the chips to load the clocked out data
449
 }
459
 }
450
 
460
 
451
-#ifdef MAX7219_INIT_TEST
461
+#if MAX7219_INIT_TEST
452
 
462
 
453
   uint8_t test_mode = 0;
463
   uint8_t test_mode = 0;
454
   millis_t next_patt_ms;
464
   millis_t next_patt_ms;
536
 
546
 
537
   register_setup();
547
   register_setup();
538
 
548
 
539
-  LOOP_LE_N(i, 7) {  // Empty registers to turn all LEDs off
540
-    led_line[i] = 0x00;
541
-    send(max7219_reg_digit0 + i, 0);
542
-    pulse_load();                     // Tell the chips to load the clocked out data
543
-  }
549
+  clear();
544
 
550
 
545
-  #ifdef MAX7219_INIT_TEST
551
+  #if MAX7219_INIT_TEST
546
     start_test_pattern();
552
     start_test_pattern();
547
   #endif
553
   #endif
548
 }
554
 }
554
  */
560
  */
555
 
561
 
556
 // Apply changes to update a marker
562
 // Apply changes to update a marker
557
-void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2) {
563
+void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2, uint8_t * const rcm/*=nullptr*/) {
558
   #if MAX7219_X_LEDS > 8    // At least 16 LEDs on the X-Axis. Use single line.
564
   #if MAX7219_X_LEDS > 8    // At least 16 LEDs on the X-Axis. Use single line.
559
-    led_off(v1 & 0xF, pos);
560
-     led_on(v2 & 0xF, pos);
565
+    led_off(v1 & 0xF, pos, rcm);
566
+     led_on(v2 & 0xF, pos, rcm);
561
   #elif MAX7219_Y_LEDS > 8  // At least 16 LEDs on the Y-Axis. Use a single column.
567
   #elif MAX7219_Y_LEDS > 8  // At least 16 LEDs on the Y-Axis. Use a single column.
562
-    led_off(pos, v1 & 0xF);
563
-     led_on(pos, v2 & 0xF);
568
+    led_off(pos, v1 & 0xF, rcm);
569
+     led_on(pos, v2 & 0xF, rcm);
564
   #else                     // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
570
   #else                     // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
565
-    led_off(v1 & 0x7, pos + (v1 >= 8));
566
-     led_on(v2 & 0x7, pos + (v2 >= 8));
571
+    led_off(v1 & 0x7, pos + (v1 >= 8), rcm);
572
+     led_on(v2 & 0x7, pos + (v2 >= 8), rcm);
567
   #endif
573
   #endif
568
 }
574
 }
569
 
575
 
570
 // Apply changes to update a tail-to-head range
576
 // Apply changes to update a tail-to-head range
571
-void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) {
577
+void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh,
578
+  const uint8_t nh, uint8_t * const rcm/*=nullptr*/) {
572
   #if MAX7219_X_LEDS > 8    // At least 16 LEDs on the X-Axis. Use single line.
579
   #if MAX7219_X_LEDS > 8    // At least 16 LEDs on the X-Axis. Use single line.
573
     if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
580
     if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
574
-      led_off(n & 0xF, y);
581
+      led_off(n & 0xF, y, rcm);
575
     if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
582
     if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
576
-       led_on(n & 0xF, y);
583
+       led_on(n & 0xF, y, rcm);
577
   #elif MAX7219_Y_LEDS > 8  // At least 16 LEDs on the Y-Axis. Use a single column.
584
   #elif MAX7219_Y_LEDS > 8  // At least 16 LEDs on the Y-Axis. Use a single column.
578
     if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
585
     if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
579
-      led_off(y, n & 0xF);
586
+      led_off(y, n & 0xF, rcm);
580
     if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
587
     if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
581
-       led_on(y, n & 0xF);
588
+       led_on(y, n & 0xF, rcm);
582
   #else                     // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
589
   #else                     // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
583
     if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
590
     if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
584
-      led_off(n & 0x7, y + (n >= 8));
591
+      led_off(n & 0x7, y + (n >= 8), rcm);
585
     if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
592
     if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
586
-       led_on(n & 0x7, y + (n >= 8));
593
+       led_on(n & 0x7, y + (n >= 8), rcm);
587
   #endif
594
   #endif
588
 }
595
 }
589
 
596
 
590
 // Apply changes to update a quantity
597
 // Apply changes to update a quantity
591
-void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv) {
598
+void Max7219::quantity(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) {
599
+  for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
600
+    led_set(i, pos, nv >= ov, rcm);
601
+}
602
+
603
+void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) {
592
   for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
604
   for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
593
     led_set(
605
     led_set(
594
       #if MAX7219_X_LEDS > 8    // At least 16 LEDs on the X-Axis. Use single line.
606
       #if MAX7219_X_LEDS > 8    // At least 16 LEDs on the X-Axis. Use single line.
599
         i >> 1, pos + (i & 1)
611
         i >> 1, pos + (i & 1)
600
       #endif
612
       #endif
601
       , nv >= ov
613
       , nv >= ov
614
+      , rcm
602
     );
615
     );
603
 }
616
 }
604
 
617
 
636
     register_setup();
649
     register_setup();
637
   }
650
   }
638
 
651
 
639
-  #ifdef MAX7219_INIT_TEST
652
+  #if MAX7219_INIT_TEST
640
     if (test_mode) {
653
     if (test_mode) {
641
       run_test_pattern();
654
       run_test_pattern();
642
       return;
655
       return;
643
     }
656
     }
644
   #endif
657
   #endif
645
 
658
 
659
+  // suspend updates and record which lines have changed for batching later
660
+  suspended++;
661
+  uint8_t row_change_mask = 0x00;
662
+
646
   #if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
663
   #if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
647
     if (do_blink) {
664
     if (do_blink) {
648
-      led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1);
665
+      led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1, &row_change_mask);
649
       next_blink = ms + 1000;
666
       next_blink = ms + 1000;
650
     }
667
     }
651
   #endif
668
   #endif
655
     static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
672
     static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
656
 
673
 
657
     if (last_head_cnt != head || last_tail_cnt != tail) {
674
     if (last_head_cnt != head || last_tail_cnt != tail) {
658
-      range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head);
675
+      range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head, &row_change_mask);
659
       last_head_cnt = head;
676
       last_head_cnt = head;
660
       last_tail_cnt = tail;
677
       last_tail_cnt = tail;
661
     }
678
     }
665
     #ifdef MAX7219_DEBUG_PLANNER_HEAD
682
     #ifdef MAX7219_DEBUG_PLANNER_HEAD
666
       static int16_t last_head_cnt = 0x1;
683
       static int16_t last_head_cnt = 0x1;
667
       if (last_head_cnt != head) {
684
       if (last_head_cnt != head) {
668
-        mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head);
685
+        mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head, &row_change_mask);
669
         last_head_cnt = head;
686
         last_head_cnt = head;
670
       }
687
       }
671
     #endif
688
     #endif
673
     #ifdef MAX7219_DEBUG_PLANNER_TAIL
690
     #ifdef MAX7219_DEBUG_PLANNER_TAIL
674
       static int16_t last_tail_cnt = 0x1;
691
       static int16_t last_tail_cnt = 0x1;
675
       if (last_tail_cnt != tail) {
692
       if (last_tail_cnt != tail) {
676
-        mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail);
693
+        mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail, &row_change_mask);
677
         last_tail_cnt = tail;
694
         last_tail_cnt = tail;
678
       }
695
       }
679
     #endif
696
     #endif
684
     static int16_t last_depth = 0;
701
     static int16_t last_depth = 0;
685
     const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
702
     const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
686
     if (current_depth != last_depth) {
703
     if (current_depth != last_depth) {
687
-      quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth);
704
+      quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth, &row_change_mask);
688
       last_depth = current_depth;
705
       last_depth = current_depth;
689
     }
706
     }
690
   #endif
707
   #endif
691
 
708
 
709
+  #ifdef MAX7219_DEBUG_PROFILE
710
+    static uint8_t last_time_fraction = 0;
711
+    const uint8_t current_time_fraction = (uint16_t(CodeProfiler::get_time_fraction()) * MAX7219_NUMBER_UNITS + 8) / 16;
712
+    if (current_time_fraction != last_time_fraction) {
713
+      quantity(MAX7219_DEBUG_PROFILE, last_time_fraction, current_time_fraction, &row_change_mask);
714
+      last_time_fraction = current_time_fraction;
715
+    }
716
+  #endif
717
+
718
+  // batch line updates
719
+  suspended--;
720
+  if (!suspended)
721
+    LOOP_L_N(i, 8) if (row_change_mask & _BV(i))
722
+      refresh_line(i);
723
+
692
   // After resume() automatically do a refresh()
724
   // After resume() automatically do a refresh()
693
   if (suspended == 0x80) {
725
   if (suspended == 0x80) {
694
     suspended = 0;
726
     suspended = 0;

+ 70
- 8
Marlin/src/feature/max7219.h Parādīt failu

73
 #define max7219_reg_shutdown    0x0C
73
 #define max7219_reg_shutdown    0x0C
74
 #define max7219_reg_displayTest 0x0F
74
 #define max7219_reg_displayTest 0x0F
75
 
75
 
76
+#ifdef MAX7219_DEBUG_PROFILE
77
+  // This class sums up the amount of time for which its instances exist.
78
+  // By default there is one instantiated for the duration of the idle()
79
+  // function. But an instance can be created in any code block to measure
80
+  // the time spent from the point of instantiation until the CPU leaves
81
+  // block. Be careful about having multiple instances of CodeProfiler as
82
+  // it does not guard against double counting. In general mixing ISR and
83
+  // non-ISR use will require critical sections but note that mode setting
84
+  // is atomic so the total or average times can safely be read if you set
85
+  // mode to FREEZE first.
86
+  class CodeProfiler {
87
+  public:
88
+    enum Mode : uint8_t { ACCUMULATE_AVERAGE, ACCUMULATE_TOTAL, FREEZE };
89
+
90
+  private:
91
+    static Mode mode;
92
+    static uint8_t instance_count;
93
+    static uint32_t last_calc_time;
94
+    static uint32_t total_time;
95
+    static uint8_t time_fraction;
96
+    static uint16_t call_count;
97
+
98
+    uint32_t start_time;
99
+
100
+  public:
101
+    CodeProfiler() : start_time(micros()) { instance_count++; }
102
+    ~CodeProfiler() {
103
+      instance_count--;
104
+      if (mode == FREEZE) return;
105
+
106
+      call_count++;
107
+
108
+      const uint32_t now = micros();
109
+      total_time += now - start_time;
110
+
111
+      if (mode == ACCUMULATE_TOTAL) return;
112
+
113
+      // update time_fraction every hundred milliseconds
114
+      if (instance_count == 0 && ELAPSED(now, last_calc_time + 100000)) {
115
+        time_fraction = total_time * 128 / (now - last_calc_time);
116
+        last_calc_time = now;
117
+        total_time = 0;
118
+      }
119
+    }
120
+
121
+    static void set_mode(Mode _mode) { mode = _mode; }
122
+    static void reset() {
123
+      time_fraction = 0;
124
+      last_calc_time = micros();
125
+      total_time = 0;
126
+      call_count = 0;
127
+    }
128
+    // returns fraction of total time which was measured, scaled from 0 to 128
129
+    static uint8_t get_time_fraction() { return time_fraction; }
130
+    // returns total time in microseconds
131
+    static uint32_t get_total_time() { return total_time; }
132
+
133
+    static uint16_t get_call_count() { return call_count; }
134
+  };
135
+#endif
136
+
76
 class Max7219 {
137
 class Max7219 {
77
 public:
138
 public:
78
   static uint8_t led_line[MAX7219_LINES];
139
   static uint8_t led_line[MAX7219_LINES];
110
   #endif
171
   #endif
111
 
172
 
112
   // Set a single LED by XY coordinate
173
   // Set a single LED by XY coordinate
113
-  static void led_set(const uint8_t x, const uint8_t y, const bool on);
114
-  static void led_on(const uint8_t x, const uint8_t y);
115
-  static void led_off(const uint8_t x, const uint8_t y);
116
-  static void led_toggle(const uint8_t x, const uint8_t y);
174
+  static void led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm=nullptr);
175
+  static void led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
176
+  static void led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
177
+  static void led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
117
 
178
 
118
   // Set all LEDs in a single column
179
   // Set all LEDs in a single column
119
   static void set_column(const uint8_t col, const uint32_t val);
180
   static void set_column(const uint8_t col, const uint32_t val);
147
   static void set(const uint8_t line, const uint8_t bits);
208
   static void set(const uint8_t line, const uint8_t bits);
148
   static void send_row(const uint8_t row);
209
   static void send_row(const uint8_t row);
149
   static void send_column(const uint8_t col);
210
   static void send_column(const uint8_t col);
150
-  static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2);
151
-  static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh);
152
-  static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv);
211
+  static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2, uint8_t * const rcm=nullptr);
212
+  static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh, uint8_t * const rcm=nullptr);
213
+  static void quantity(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr);
214
+  static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr);
153
 
215
 
154
-  #ifdef MAX7219_INIT_TEST
216
+  #if MAX7219_INIT_TEST
155
     static void test_pattern();
217
     static void test_pattern();
156
     static void run_test_pattern();
218
     static void run_test_pattern();
157
     static void start_test_pattern();
219
     static void start_test_pattern();

Notiek ielāde…
Atcelt
Saglabāt