✨ MAX7219 idle profiler (#24375)
This commit is contained in:
parent
537af0bb03
commit
4694a7fe74
@ -3595,7 +3595,7 @@
|
|||||||
// ESP32: If SPINDLE_LASER_PWM_PIN is onboard then <=78125Hz. For I2S expander
|
// ESP32: If SPINDLE_LASER_PWM_PIN is onboard then <=78125Hz. For I2S expander
|
||||||
// the frequency determines the PWM resolution. 2500Hz = 0-100, 977Hz = 0-255, ...
|
// the frequency determines the PWM resolution. 2500Hz = 0-100, 977Hz = 0-255, ...
|
||||||
// (250000 / SPINDLE_LASER_FREQUENCY) = max value.
|
// (250000 / SPINDLE_LASER_FREQUENCY) = max value.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
|
//#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
|
||||||
#if ENABLED(AIR_EVACUATION)
|
#if ENABLED(AIR_EVACUATION)
|
||||||
@ -4289,7 +4289,8 @@
|
|||||||
#define MAX7219_NUMBER_UNITS 1 // Number of Max7219 units in chain.
|
#define MAX7219_NUMBER_UNITS 1 // Number of Max7219 units in chain.
|
||||||
#define MAX7219_ROTATE 0 // Rotate the display clockwise (in multiples of +/- 90°)
|
#define MAX7219_ROTATE 0 // Rotate the display clockwise (in multiples of +/- 90°)
|
||||||
// connector at: right=0 bottom=-90 top=90 left=180
|
// connector at: right=0 bottom=-90 top=90 left=180
|
||||||
//#define MAX7219_REVERSE_ORDER // The individual LED matrix units may be in reversed order
|
//#define MAX7219_REVERSE_ORDER // The order of the LED matrix units may be reversed
|
||||||
|
//#define MAX7219_REVERSE_EACH // The LEDs in each matrix unit row may be reversed
|
||||||
//#define MAX7219_SIDE_BY_SIDE // Big chip+matrix boards can be chained side-by-side
|
//#define MAX7219_SIDE_BY_SIDE // Big chip+matrix boards can be chained side-by-side
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4297,12 +4298,15 @@
|
|||||||
* If you add more debug displays, be careful to avoid conflicts!
|
* If you add more debug displays, be careful to avoid conflicts!
|
||||||
*/
|
*/
|
||||||
#define MAX7219_DEBUG_PRINTER_ALIVE // Blink corner LED of 8x8 matrix to show that the firmware is functioning
|
#define MAX7219_DEBUG_PRINTER_ALIVE // Blink corner LED of 8x8 matrix to show that the firmware is functioning
|
||||||
#define MAX7219_DEBUG_PLANNER_HEAD 3 // Show the planner queue head position on this and the next LED matrix row
|
#define MAX7219_DEBUG_PLANNER_HEAD 2 // Show the planner queue head position on this and the next LED matrix row
|
||||||
#define MAX7219_DEBUG_PLANNER_TAIL 5 // Show the planner queue tail position on this and the next LED matrix row
|
#define MAX7219_DEBUG_PLANNER_TAIL 4 // Show the planner queue tail position on this and the next LED matrix row
|
||||||
|
|
||||||
#define MAX7219_DEBUG_PLANNER_QUEUE 0 // Show the current planner queue depth on this and the next LED matrix row
|
#define MAX7219_DEBUG_PLANNER_QUEUE 0 // Show the current planner queue depth on this and the next LED matrix row
|
||||||
// If you experience stuttering, reboots, etc. this option can reveal how
|
// If you experience stuttering, reboots, etc. this option can reveal how
|
||||||
// tweaks made to the configuration are affecting the printer in real-time.
|
// tweaks made to the configuration are affecting the printer in real-time.
|
||||||
|
#define MAX7219_DEBUG_PROFILE 6 // Display the fraction of CPU time spent in profiled code on this LED matrix
|
||||||
|
// row. By default idle() is profiled so this shows how "idle" the processor is.
|
||||||
|
// See class CodeProfiler.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -776,6 +776,10 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
|
|||||||
* - Handle Joystick jogging
|
* - Handle Joystick jogging
|
||||||
*/
|
*/
|
||||||
void idle(bool no_stepper_sleep/*=false*/) {
|
void idle(bool no_stepper_sleep/*=false*/) {
|
||||||
|
#ifdef MAX7219_DEBUG_PROFILE
|
||||||
|
CodeProfiler idle_profiler;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLED(MARLIN_DEV_MODE)
|
#if ENABLED(MARLIN_DEV_MODE)
|
||||||
static uint16_t idle_depth = 0;
|
static uint16_t idle_depth = 0;
|
||||||
if (++idle_depth > 5) SERIAL_ECHOLNPGM("idle() call depth: ", idle_depth);
|
if (++idle_depth > 5) SERIAL_ECHOLNPGM("idle() call depth: ", idle_depth);
|
||||||
|
@ -62,6 +62,15 @@
|
|||||||
#error "MAX7219_ROTATE must be a multiple of +/- 90°."
|
#error "MAX7219_ROTATE must be a multiple of +/- 90°."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAX7219_DEBUG_PROFILE
|
||||||
|
CodeProfiler::Mode CodeProfiler::mode = ACCUMULATE_AVERAGE;
|
||||||
|
uint8_t CodeProfiler::instance_count = 0;
|
||||||
|
uint32_t CodeProfiler::last_calc_time = micros();
|
||||||
|
uint8_t CodeProfiler::time_fraction = 0;
|
||||||
|
uint32_t CodeProfiler::total_time = 0;
|
||||||
|
uint16_t CodeProfiler::call_count = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
Max7219 max7219;
|
Max7219 max7219;
|
||||||
|
|
||||||
uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
|
uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
|
||||||
@ -69,7 +78,7 @@ uint8_t Max7219::suspended; // = 0;
|
|||||||
|
|
||||||
#define LINE_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7))
|
#define LINE_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7))
|
||||||
|
|
||||||
#if _ROT == 0 || _ROT == 270
|
#if (_ROT == 0 || _ROT == 270) == DISABLED(MAX7219_REVERSE_EACH)
|
||||||
#define _LED_BIT(Q) (7 - ((Q) & 0x7))
|
#define _LED_BIT(Q) (7 - ((Q) & 0x7))
|
||||||
#else
|
#else
|
||||||
#define _LED_BIT(Q) ((Q) & 0x7)
|
#define _LED_BIT(Q) ((Q) & 0x7)
|
||||||
@ -266,26 +275,27 @@ void Max7219::set(const uint8_t line, const uint8_t bits) {
|
|||||||
#endif // MAX7219_NUMERIC
|
#endif // MAX7219_NUMERIC
|
||||||
|
|
||||||
// Modify a single LED bit and send the changed line
|
// Modify a single LED bit and send the changed line
|
||||||
void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) {
|
void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm/*=nullptr*/) {
|
||||||
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y);
|
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y);
|
||||||
if (BIT_7219(x, y) == on) return;
|
if (BIT_7219(x, y) == on) return;
|
||||||
XOR_7219(x, y);
|
XOR_7219(x, y);
|
||||||
refresh_unit_line(LED_IND(x, y));
|
refresh_unit_line(LED_IND(x, y));
|
||||||
|
if (rcm != nullptr) *rcm |= _BV(LED_IND(x, y) & 0x07);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max7219::led_on(const uint8_t x, const uint8_t y) {
|
void Max7219::led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
|
||||||
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y);
|
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y);
|
||||||
led_set(x, y, true);
|
led_set(x, y, true, rcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max7219::led_off(const uint8_t x, const uint8_t y) {
|
void Max7219::led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
|
||||||
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y);
|
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y);
|
||||||
led_set(x, y, false);
|
led_set(x, y, false, rcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max7219::led_toggle(const uint8_t x, const uint8_t y) {
|
void Max7219::led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) {
|
||||||
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y);
|
if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y);
|
||||||
led_set(x, y, !BIT_7219(x, y));
|
led_set(x, y, !BIT_7219(x, y), rcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Max7219::send_row(const uint8_t row) {
|
void Max7219::send_row(const uint8_t row) {
|
||||||
@ -448,7 +458,7 @@ void Max7219::register_setup() {
|
|||||||
pulse_load(); // Tell the chips to load the clocked out data
|
pulse_load(); // Tell the chips to load the clocked out data
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAX7219_INIT_TEST
|
#if MAX7219_INIT_TEST
|
||||||
|
|
||||||
uint8_t test_mode = 0;
|
uint8_t test_mode = 0;
|
||||||
millis_t next_patt_ms;
|
millis_t next_patt_ms;
|
||||||
@ -536,13 +546,9 @@ void Max7219::init() {
|
|||||||
|
|
||||||
register_setup();
|
register_setup();
|
||||||
|
|
||||||
LOOP_LE_N(i, 7) { // Empty registers to turn all LEDs off
|
clear();
|
||||||
led_line[i] = 0x00;
|
|
||||||
send(max7219_reg_digit0 + i, 0);
|
|
||||||
pulse_load(); // Tell the chips to load the clocked out data
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MAX7219_INIT_TEST
|
#if MAX7219_INIT_TEST
|
||||||
start_test_pattern();
|
start_test_pattern();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -554,41 +560,47 @@ void Max7219::init() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Apply changes to update a marker
|
// Apply changes to update a marker
|
||||||
void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2) {
|
void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2, uint8_t * const rcm/*=nullptr*/) {
|
||||||
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
|
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
|
||||||
led_off(v1 & 0xF, pos);
|
led_off(v1 & 0xF, pos, rcm);
|
||||||
led_on(v2 & 0xF, pos);
|
led_on(v2 & 0xF, pos, rcm);
|
||||||
#elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column.
|
#elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column.
|
||||||
led_off(pos, v1 & 0xF);
|
led_off(pos, v1 & 0xF, rcm);
|
||||||
led_on(pos, v2 & 0xF);
|
led_on(pos, v2 & 0xF, rcm);
|
||||||
#else // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
|
#else // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
|
||||||
led_off(v1 & 0x7, pos + (v1 >= 8));
|
led_off(v1 & 0x7, pos + (v1 >= 8), rcm);
|
||||||
led_on(v2 & 0x7, pos + (v2 >= 8));
|
led_on(v2 & 0x7, pos + (v2 >= 8), rcm);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply changes to update a tail-to-head range
|
// Apply changes to update a tail-to-head range
|
||||||
void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) {
|
void Max7219::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*/) {
|
||||||
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
|
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
|
||||||
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
||||||
led_off(n & 0xF, y);
|
led_off(n & 0xF, y, rcm);
|
||||||
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
||||||
led_on(n & 0xF, y);
|
led_on(n & 0xF, y, rcm);
|
||||||
#elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column.
|
#elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column.
|
||||||
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
||||||
led_off(y, n & 0xF);
|
led_off(y, n & 0xF, rcm);
|
||||||
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
||||||
led_on(y, n & 0xF);
|
led_on(y, n & 0xF, rcm);
|
||||||
#else // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
|
#else // Single 8x8 LED matrix. Use two lines to get 16 LEDs.
|
||||||
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
|
||||||
led_off(n & 0x7, y + (n >= 8));
|
led_off(n & 0x7, y + (n >= 8), rcm);
|
||||||
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
|
||||||
led_on(n & 0x7, y + (n >= 8));
|
led_on(n & 0x7, y + (n >= 8), rcm);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply changes to update a quantity
|
// Apply changes to update a quantity
|
||||||
void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv) {
|
void Max7219::quantity(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) {
|
||||||
|
for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
|
||||||
|
led_set(i, pos, nv >= ov, rcm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) {
|
||||||
for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
|
for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++)
|
||||||
led_set(
|
led_set(
|
||||||
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
|
#if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line.
|
||||||
@ -599,6 +611,7 @@ void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv)
|
|||||||
i >> 1, pos + (i & 1)
|
i >> 1, pos + (i & 1)
|
||||||
#endif
|
#endif
|
||||||
, nv >= ov
|
, nv >= ov
|
||||||
|
, rcm
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,16 +649,20 @@ void Max7219::idle_tasks() {
|
|||||||
register_setup();
|
register_setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAX7219_INIT_TEST
|
#if MAX7219_INIT_TEST
|
||||||
if (test_mode) {
|
if (test_mode) {
|
||||||
run_test_pattern();
|
run_test_pattern();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// suspend updates and record which lines have changed for batching later
|
||||||
|
suspended++;
|
||||||
|
uint8_t row_change_mask = 0x00;
|
||||||
|
|
||||||
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
|
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
|
||||||
if (do_blink) {
|
if (do_blink) {
|
||||||
led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1);
|
led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1, &row_change_mask);
|
||||||
next_blink = ms + 1000;
|
next_blink = ms + 1000;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -655,7 +672,7 @@ void Max7219::idle_tasks() {
|
|||||||
static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
|
static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
|
||||||
|
|
||||||
if (last_head_cnt != head || last_tail_cnt != tail) {
|
if (last_head_cnt != head || last_tail_cnt != tail) {
|
||||||
range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head);
|
range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head, &row_change_mask);
|
||||||
last_head_cnt = head;
|
last_head_cnt = head;
|
||||||
last_tail_cnt = tail;
|
last_tail_cnt = tail;
|
||||||
}
|
}
|
||||||
@ -665,7 +682,7 @@ void Max7219::idle_tasks() {
|
|||||||
#ifdef MAX7219_DEBUG_PLANNER_HEAD
|
#ifdef MAX7219_DEBUG_PLANNER_HEAD
|
||||||
static int16_t last_head_cnt = 0x1;
|
static int16_t last_head_cnt = 0x1;
|
||||||
if (last_head_cnt != head) {
|
if (last_head_cnt != head) {
|
||||||
mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head);
|
mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head, &row_change_mask);
|
||||||
last_head_cnt = head;
|
last_head_cnt = head;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -673,7 +690,7 @@ void Max7219::idle_tasks() {
|
|||||||
#ifdef MAX7219_DEBUG_PLANNER_TAIL
|
#ifdef MAX7219_DEBUG_PLANNER_TAIL
|
||||||
static int16_t last_tail_cnt = 0x1;
|
static int16_t last_tail_cnt = 0x1;
|
||||||
if (last_tail_cnt != tail) {
|
if (last_tail_cnt != tail) {
|
||||||
mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail);
|
mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail, &row_change_mask);
|
||||||
last_tail_cnt = tail;
|
last_tail_cnt = tail;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -684,11 +701,26 @@ void Max7219::idle_tasks() {
|
|||||||
static int16_t last_depth = 0;
|
static int16_t last_depth = 0;
|
||||||
const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
|
const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
|
||||||
if (current_depth != last_depth) {
|
if (current_depth != last_depth) {
|
||||||
quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth);
|
quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth, &row_change_mask);
|
||||||
last_depth = current_depth;
|
last_depth = current_depth;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAX7219_DEBUG_PROFILE
|
||||||
|
static uint8_t last_time_fraction = 0;
|
||||||
|
const uint8_t current_time_fraction = (uint16_t(CodeProfiler::get_time_fraction()) * MAX7219_NUMBER_UNITS + 8) / 16;
|
||||||
|
if (current_time_fraction != last_time_fraction) {
|
||||||
|
quantity(MAX7219_DEBUG_PROFILE, last_time_fraction, current_time_fraction, &row_change_mask);
|
||||||
|
last_time_fraction = current_time_fraction;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// batch line updates
|
||||||
|
suspended--;
|
||||||
|
if (!suspended)
|
||||||
|
LOOP_L_N(i, 8) if (row_change_mask & _BV(i))
|
||||||
|
refresh_line(i);
|
||||||
|
|
||||||
// After resume() automatically do a refresh()
|
// After resume() automatically do a refresh()
|
||||||
if (suspended == 0x80) {
|
if (suspended == 0x80) {
|
||||||
suspended = 0;
|
suspended = 0;
|
||||||
|
@ -73,6 +73,67 @@
|
|||||||
#define max7219_reg_shutdown 0x0C
|
#define max7219_reg_shutdown 0x0C
|
||||||
#define max7219_reg_displayTest 0x0F
|
#define max7219_reg_displayTest 0x0F
|
||||||
|
|
||||||
|
#ifdef MAX7219_DEBUG_PROFILE
|
||||||
|
// This class sums up the amount of time for which its instances exist.
|
||||||
|
// By default there is one instantiated for the duration of the idle()
|
||||||
|
// function. But an instance can be created in any code block to measure
|
||||||
|
// the time spent from the point of instantiation until the CPU leaves
|
||||||
|
// block. Be careful about having multiple instances of CodeProfiler as
|
||||||
|
// it does not guard against double counting. In general mixing ISR and
|
||||||
|
// non-ISR use will require critical sections but note that mode setting
|
||||||
|
// is atomic so the total or average times can safely be read if you set
|
||||||
|
// mode to FREEZE first.
|
||||||
|
class CodeProfiler {
|
||||||
|
public:
|
||||||
|
enum Mode : uint8_t { ACCUMULATE_AVERAGE, ACCUMULATE_TOTAL, FREEZE };
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Mode mode;
|
||||||
|
static uint8_t instance_count;
|
||||||
|
static uint32_t last_calc_time;
|
||||||
|
static uint32_t total_time;
|
||||||
|
static uint8_t time_fraction;
|
||||||
|
static uint16_t call_count;
|
||||||
|
|
||||||
|
uint32_t start_time;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CodeProfiler() : start_time(micros()) { instance_count++; }
|
||||||
|
~CodeProfiler() {
|
||||||
|
instance_count--;
|
||||||
|
if (mode == FREEZE) return;
|
||||||
|
|
||||||
|
call_count++;
|
||||||
|
|
||||||
|
const uint32_t now = micros();
|
||||||
|
total_time += now - start_time;
|
||||||
|
|
||||||
|
if (mode == ACCUMULATE_TOTAL) return;
|
||||||
|
|
||||||
|
// update time_fraction every hundred milliseconds
|
||||||
|
if (instance_count == 0 && ELAPSED(now, last_calc_time + 100000)) {
|
||||||
|
time_fraction = total_time * 128 / (now - last_calc_time);
|
||||||
|
last_calc_time = now;
|
||||||
|
total_time = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_mode(Mode _mode) { mode = _mode; }
|
||||||
|
static void reset() {
|
||||||
|
time_fraction = 0;
|
||||||
|
last_calc_time = micros();
|
||||||
|
total_time = 0;
|
||||||
|
call_count = 0;
|
||||||
|
}
|
||||||
|
// returns fraction of total time which was measured, scaled from 0 to 128
|
||||||
|
static uint8_t get_time_fraction() { return time_fraction; }
|
||||||
|
// returns total time in microseconds
|
||||||
|
static uint32_t get_total_time() { return total_time; }
|
||||||
|
|
||||||
|
static uint16_t get_call_count() { return call_count; }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class Max7219 {
|
class Max7219 {
|
||||||
public:
|
public:
|
||||||
static uint8_t led_line[MAX7219_LINES];
|
static uint8_t led_line[MAX7219_LINES];
|
||||||
@ -110,10 +171,10 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set a single LED by XY coordinate
|
// Set a single LED by XY coordinate
|
||||||
static void led_set(const uint8_t x, const uint8_t y, const bool on);
|
static void led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm=nullptr);
|
||||||
static void led_on(const uint8_t x, const uint8_t y);
|
static void led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
|
||||||
static void led_off(const uint8_t x, const uint8_t y);
|
static void led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
|
||||||
static void led_toggle(const uint8_t x, const uint8_t y);
|
static void led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr);
|
||||||
|
|
||||||
// Set all LEDs in a single column
|
// Set all LEDs in a single column
|
||||||
static void set_column(const uint8_t col, const uint32_t val);
|
static void set_column(const uint8_t col, const uint32_t val);
|
||||||
@ -147,11 +208,12 @@ private:
|
|||||||
static void set(const uint8_t line, const uint8_t bits);
|
static void set(const uint8_t line, const uint8_t bits);
|
||||||
static void send_row(const uint8_t row);
|
static void send_row(const uint8_t row);
|
||||||
static void send_column(const uint8_t col);
|
static void send_column(const uint8_t col);
|
||||||
static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2);
|
static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2, uint8_t * const rcm=nullptr);
|
||||||
static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh);
|
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);
|
||||||
static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv);
|
static void quantity(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr);
|
||||||
|
static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr);
|
||||||
|
|
||||||
#ifdef MAX7219_INIT_TEST
|
#if MAX7219_INIT_TEST
|
||||||
static void test_pattern();
|
static void test_pattern();
|
||||||
static void run_test_pattern();
|
static void run_test_pattern();
|
||||||
static void start_test_pattern();
|
static void start_test_pattern();
|
||||||
|
Loading…
Reference in New Issue
Block a user