Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 42 additions & 52 deletions Marlin/src/feature/Max7219_Debug_LEDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,36 +50,32 @@

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) 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))
#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))

#ifdef CPU_32_BIT
#define SIG_DELAY() DELAY_US(1) // Approximate a 1µs delay on 32-bit ARM
Expand All @@ -93,7 +89,7 @@ uint8_t Max7219::led_line[MAX7219_ROWS]; // = { 0 };

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);
Expand Down Expand Up @@ -130,6 +126,7 @@ void Max7219::noop() {
SIG_DELAY();
WRITE(MAX7219_CLK_PIN, LOW);
SIG_DELAY();
SIG_DELAY();
WRITE(MAX7219_CLK_PIN, HIGH);
SIG_DELAY();
}
Expand Down Expand Up @@ -170,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)
Expand Down Expand Up @@ -231,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) {
Expand All @@ -250,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();
Expand All @@ -260,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();
Expand All @@ -272,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);
}

Expand All @@ -293,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);
}
Expand All @@ -311,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);
}
Expand Down Expand Up @@ -378,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
Expand Down
23 changes: 13 additions & 10 deletions Marlin/src/feature/Max7219_Debug_LEDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
* #define MAX7219_DIN_PIN 78
* #define MAX7219_LOAD_PIN 79
*
* Max7219_init() is called automatically at startup, and then there are a number of
* max7219.init() is called automatically at startup, and then there are a number of
* support functions available to control the LEDs in the 8x8 grid.
*
* If you are using the Max7219 matrix for firmware debug purposes in time sensitive
Expand All @@ -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
Expand All @@ -80,7 +80,7 @@

class Max7219 {
public:
static uint8_t led_line[MAX7219_ROWS];
static uint8_t led_line[MAX7219_LINES];

Max7219() { }

Expand All @@ -93,13 +93,13 @@ class Max7219 {
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);
Expand All @@ -126,6 +126,9 @@ class Max7219 {
// 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();

Expand Down
20 changes: 9 additions & 11 deletions Marlin/src/gcode/feature/leds/M7219.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,11 @@
*/
void GcodeSuite::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');

Expand All @@ -69,18 +67,18 @@ void GcodeSuite::M7219() {
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();
Expand Down