diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 6c9f6d157..72ff3330a 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -10914,13 +10914,11 @@ inline void gcode_M502() { */ inline void gcode_M7219() { if (parser.seen('I')) { - max7219.clear(); max7219.register_setup(); + max7219.clear(); } - if (parser.seen('F')) - for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) - max7219.set_column(x, 0xFFFFFFFF); + if (parser.seen('F')) max7219.fill(); const uint32_t v = parser.ulongval('V'); @@ -10940,18 +10938,18 @@ inline void gcode_M502() { max7219.led_toggle(x, y); } else if (parser.seen('D')) { - const uint8_t r = parser.value_byte(); - if (r < MAX7219_ROWS) { - max7219.led_line[r] = v; - return max7219.all(r); + const uint8_t line = parser.byteval('D') + (parser.byteval('U') << 3); + if (line < MAX7219_LINES) { + max7219.led_line[line] = v; + return max7219.refresh_line(line); } } if (parser.seen('P')) { - for (uint8_t r = 0; r < MAX7219_ROWS; r++) { + for (uint8_t r = 0; r < MAX7219_LINES; r++) { SERIAL_ECHOPGM("led_line["); - if (r < 10) SERIAL_CHAR('_'); - SERIAL_ECHO(r); + if (r < 10) SERIAL_CHAR(' '); + SERIAL_ECHO(int(r)); SERIAL_ECHO("]="); for (uint8_t b = 8; b--;) SERIAL_CHAR('0' + TEST(max7219.led_line[r], b)); SERIAL_EOL(); diff --git a/Marlin/Max7219_Debug_LEDs.cpp b/Marlin/Max7219_Debug_LEDs.cpp index 484e90716..2be4bfd4f 100644 --- a/Marlin/Max7219_Debug_LEDs.cpp +++ b/Marlin/Max7219_Debug_LEDs.cpp @@ -50,43 +50,46 @@ Max7219 max7219; -uint8_t Max7219::led_line[MAX7219_ROWS]; // = { 0 }; +uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 }; +#define LINE_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7)) #if _ROT == 0 || _ROT == 270 - #define _LED_BIT(Q) (7 - ((Q) & 0x07)) + #define _LED_BIT(Q) (7 - ((Q) & 0x7)) + #define _LED_UNIT(Q) ((Q) & ~0x7) #else - #define _LED_BIT(Q) ((Q) & 0x07) + #define _LED_BIT(Q) ((Q) & 0x7) + #define _LED_UNIT(Q) ((MAX7219_NUMBER_UNITS - 1 - ((Q) >> 3)) << 3) #endif -#if _ROT >= 180 - #define _LED_IND(P,Q) (P + ((Q) & ~0x07)) - #define _ROW_REG(Q) (max7219_reg_digit7 - ((Q) & 0x7)) +#if _ROT < 180 + #define _LED_IND(P,Q) (_LED_UNIT(P) + (Q)) #else - #define _LED_IND(P,Q) (P + ((Q) & ~0x07)) - #define _ROW_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7)) + #define _LED_IND(P,Q) (_LED_UNIT(P) + (7 - ((Q) & 0x7))) #endif #if _ROT == 0 || _ROT == 180 - #define MAX7219_LINE_AXIS y - #define LED_IND(X,Y) _LED_IND(Y,X) + #define LED_IND(X,Y) _LED_IND(X,Y) #define LED_BIT(X,Y) _LED_BIT(X) #elif _ROT == 90 || _ROT == 270 - #define MAX7219_LINE_AXIS x - #define LED_IND(X,Y) _LED_IND(X,Y) + #define LED_IND(X,Y) _LED_IND(Y,X) #define LED_BIT(X,Y) _LED_BIT(Y) -#else - #error "MAX7219_ROTATE must be a multiple of +/- 90°." #endif +#define XOR_7219(X,Y) do{ led_line[LED_IND(X,Y)] ^= _BV(LED_BIT(X,Y)); }while(0) +#define SET_7219(X,Y) do{ led_line[LED_IND(X,Y)] |= _BV(LED_BIT(X,Y)); }while(0) +#define CLR_7219(X,Y) do{ led_line[LED_IND(X,Y)] &= ~_BV(LED_BIT(X,Y)); }while(0) +#define BIT_7219(X,Y) TEST(led_line[LED_IND(X,Y)], LED_BIT(X,Y)) -#define XOR_7219(X,Y) led_line[LED_IND(X,Y)] ^= _BV(LED_BIT(X,Y)) -#define SET_LED_7219(X,Y) led_line[LED_IND(X,Y)] |= _BV(LED_BIT(X,Y)) -#define CLR_LED_7219(X,Y) led_line[LED_IND(X,Y)] &= ~_BV(LED_BIT(X,Y)) -#define BIT_7219(X,Y) TEST(led_line[LED_IND(X,Y)], LED_BIT(X,Y)) - -// Delay for 0.1875µs (16MHz AVR) or 0.15µs (20MHz AVR) -#define SIG_DELAY() DELAY_NS(188) +#ifdef CPU_32_BIT + #define SIG_DELAY() DELAY_US(1) // Approximate a 1µs delay on 32-bit ARM + #undef CRITICAL_SECTION_START + #undef CRITICAL_SECTION_END + #define CRITICAL_SECTION_START NOOP + #define CRITICAL_SECTION_END NOOP +#else + #define SIG_DELAY() DELAY_NS(188) // Delay for 0.1875µs (16MHz AVR) or 0.15µs (20MHz AVR) +#endif void Max7219::error(const char * const func, const int32_t v1, const int32_t v2/*=-1*/) { #if ENABLED(MAX7219_ERRORS) - SERIAL_ECHOPGM("??? Max7219"); + SERIAL_ECHOPGM("??? Max7219::"); serialprintPGM(func); SERIAL_CHAR('('); SERIAL_ECHO(v1); @@ -123,6 +126,7 @@ void Max7219::noop() { SIG_DELAY(); WRITE(MAX7219_CLK_PIN, LOW); SIG_DELAY(); + SIG_DELAY(); WRITE(MAX7219_CLK_PIN, HIGH); SIG_DELAY(); } @@ -163,26 +167,22 @@ void Max7219::send(const uint8_t reg, const uint8_t data) { } // Send out a single native row of bits to all units -void Max7219::all(const uint8_t line) { - for (uint8_t u = 0; u < MAX7219_ROWS; u += 8) - send(_ROW_REG(line), led_line[u + (line & 0x7)]); +void Max7219::refresh_line(const uint8_t line) { + for (uint8_t u = MAX7219_NUMBER_UNITS; u--;) + send(LINE_REG(line), led_line[(u << 3) | (line & 0x7)]); pulse_load(); } // Send out a single native row of bits to just one unit -void Max7219::one(const uint8_t line) { - for (uint8_t u = MAX7219_NUMBER_UNITS; u--;) { - if (u == (line >> 3)) - send(_ROW_REG(line), led_line[line]); - else - noop(); - } +void Max7219::refresh_unit_line(const uint8_t line) { + for (uint8_t u = MAX7219_NUMBER_UNITS; u--;) + if (u == (line >> 3)) send(LINE_REG(line), led_line[line]); else noop(); pulse_load(); } void Max7219::set(const uint8_t line, const uint8_t bits) { led_line[line] = bits; - all(line); + refresh_line(line); } #if ENABLED(MAX7219_NUMERIC) @@ -224,7 +224,7 @@ void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) { if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_set"), x, y); if (BIT_7219(x, y) == on) return; XOR_7219(x, y); - all(MAX7219_LINE_AXIS); + refresh_line(LED_IND(x, y)); } void Max7219::led_on(const uint8_t x, const uint8_t y) { @@ -243,8 +243,8 @@ void Max7219::led_toggle(const uint8_t x, const uint8_t y) { } void Max7219::send_row(const uint8_t row) { - #if _ROT == 90 || _ROT == 270 - all(row); + #if _ROT == 0 || _ROT == 180 + refresh_line(LED_IND(0, row)); #else UNUSED(row); refresh(); @@ -253,7 +253,7 @@ void Max7219::send_row(const uint8_t row) { void Max7219::send_column(const uint8_t col) { #if _ROT == 90 || _ROT == 270 - all(col); // Send the "column" out and strobe + refresh_line(LED_IND(col, 0)); #else UNUSED(col); refresh(); @@ -265,17 +265,20 @@ void Max7219::clear() { refresh(); } +void Max7219::fill() { + memset(led_line, 0xFF, sizeof(led_line)); + refresh(); +} + void Max7219::clear_row(const uint8_t row) { if (row >= MAX7219_Y_LEDS) return error(PSTR("clear_row"), row); - for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) - CLR_LED_7219(MAX7219_X_LEDS - 1 - x, row); + for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) CLR_7219(x, row); send_row(row); } void Max7219::clear_column(const uint8_t col) { if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); - for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) - CLR_LED_7219(col, MAX7219_Y_LEDS - y - 1); + for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) CLR_7219(col, y); send_column(col); } @@ -286,13 +289,10 @@ void Max7219::clear_column(const uint8_t col) { */ void Max7219::set_row(const uint8_t row, const uint32_t val) { if (row >= MAX7219_Y_LEDS) return error(PSTR("set_row"), row); - uint32_t mask = 0x0000001; + uint32_t mask = _BV32(MAX7219_X_LEDS - 1); for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) { - if (val & mask) - SET_LED_7219(MAX7219_X_LEDS - 1 - x, row); - else - CLR_LED_7219(MAX7219_X_LEDS - 1 - x, row); - mask <<= 1; + if (val & mask) SET_7219(x, row); else CLR_7219(x, row); + mask >>= 1; } send_row(row); } @@ -304,13 +304,10 @@ void Max7219::set_row(const uint8_t row, const uint32_t val) { */ void Max7219::set_column(const uint8_t col, const uint32_t val) { if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); - uint32_t mask = 0x0000001; + uint32_t mask = _BV32(MAX7219_Y_LEDS - 1); for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) { - if (val & mask) - SET_LED_7219(col, MAX7219_Y_LEDS - y - 1); - else - CLR_LED_7219(col, MAX7219_Y_LEDS - y - 1); - mask <<= 1; + if (val & mask) SET_7219(col, y); else CLR_7219(col, y); + mask >>= 1; } send_column(col); } @@ -371,8 +368,8 @@ void Max7219::set_columns_32bits(const uint8_t x, uint32_t val) { #endif } +// Initialize the Max7219 void Max7219::register_setup() { - // Initialize the Max7219 for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++) send(max7219_reg_scanLimit, 0x07); pulse_load(); // tell the chips to load the clocked out data diff --git a/Marlin/Max7219_Debug_LEDs.h b/Marlin/Max7219_Debug_LEDs.h index 2f5f759e7..3523eef40 100644 --- a/Marlin/Max7219_Debug_LEDs.h +++ b/Marlin/Max7219_Debug_LEDs.h @@ -47,14 +47,14 @@ #endif #define _ROT ((MAX7219_ROTATE + 360) % 360) -#define MAX7219_ROWS (8 * (MAX7219_NUMBER_UNITS)) +#define MAX7219_LINES (8 * (MAX7219_NUMBER_UNITS)) #if _ROT == 0 || _ROT == 180 #define MAX7219_Y_LEDS 8 - #define MAX7219_X_LEDS MAX7219_ROWS + #define MAX7219_X_LEDS MAX7219_LINES #elif _ROT == 90 || _ROT == 270 #define MAX7219_X_LEDS 8 - #define MAX7219_Y_LEDS MAX7219_ROWS + #define MAX7219_Y_LEDS MAX7219_LINES #else #error "MAX7219_ROTATE must be a multiple of +/- 90°." #endif @@ -80,7 +80,7 @@ class Max7219 { public: - static uint8_t led_line[MAX7219_ROWS]; + static uint8_t led_line[MAX7219_LINES]; Max7219() { } @@ -93,13 +93,13 @@ public: static void send(const uint8_t reg, const uint8_t data); // Refresh all units - inline static void refresh() { for (uint8_t i = 0; i < 8; i++) all(i); } + inline static void refresh() { for (uint8_t i = 0; i < 8; i++) refresh_line(i); } - // Update a single native row on all units - static void all(const uint8_t line); + // Update a single native line on all units + static void refresh_line(const uint8_t line); - // Update a single native row on the target unit - static void one(const uint8_t line); + // Update a single native line on just one unit + static void refresh_unit_line(const uint8_t line); // Set a single LED by XY coordinate static void led_set(const uint8_t x, const uint8_t y, const bool on); @@ -126,6 +126,9 @@ public: // Quickly clear the whole matrix static void clear(); + // Quickly fill the whole matrix + static void fill(); + // Apply custom code to update the matrix static void idle_tasks();