Fix up Max7219 orientations (#11596)
This commit is contained in:
		
							parent
							
								
									d05b23941d
								
							
						
					
					
						commit
						8f0bbdcc9b
					
				| @ -50,36 +50,32 @@ | |||||||
| 
 | 
 | ||||||
| Max7219 max7219; | 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 | #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 | #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 | #endif | ||||||
| #if _ROT >= 180 | #if _ROT < 180 | ||||||
|   #define _LED_IND(P,Q) (P + ((Q) & ~0x07)) |   #define _LED_IND(P,Q) (_LED_UNIT(P) + (Q)) | ||||||
|   #define _ROW_REG(Q)   (max7219_reg_digit7 - ((Q) & 0x7)) |  | ||||||
| #else | #else | ||||||
|   #define _LED_IND(P,Q) (P + ((Q) & ~0x07)) |   #define _LED_IND(P,Q) (_LED_UNIT(P) + (7 - ((Q) & 0x7))) | ||||||
|   #define _ROW_REG(Q)   (max7219_reg_digit0 + ((Q) & 0x7)) |  | ||||||
| #endif | #endif | ||||||
| #if _ROT == 0 || _ROT == 180 | #if _ROT == 0 || _ROT == 180 | ||||||
|   #define MAX7219_LINE_AXIS y |   #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(X) |   #define LED_BIT(X,Y)  _LED_BIT(X) | ||||||
| #elif _ROT == 90 || _ROT == 270 | #elif _ROT == 90 || _ROT == 270 | ||||||
|   #define MAX7219_LINE_AXIS x |   #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(Y) |   #define LED_BIT(X,Y)  _LED_BIT(Y) | ||||||
| #else |  | ||||||
|   #error "MAX7219_ROTATE must be a multiple of +/- 90°." |  | ||||||
| #endif | #endif | ||||||
| 
 | #define XOR_7219(X,Y) do{ led_line[LED_IND(X,Y)] ^=  _BV(LED_BIT(X,Y)); }while(0) | ||||||
| #define XOR_7219(X,Y)     led_line[LED_IND(X,Y)] ^= _BV(LED_BIT(X,Y)) | #define SET_7219(X,Y) do{ led_line[LED_IND(X,Y)] |=  _BV(LED_BIT(X,Y)); }while(0) | ||||||
| #define SET_LED_7219(X,Y) led_line[LED_IND(X,Y)] |= _BV(LED_BIT(X,Y)) | #define CLR_7219(X,Y) do{ led_line[LED_IND(X,Y)] &= ~_BV(LED_BIT(X,Y)); }while(0) | ||||||
| #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 BIT_7219(X,Y)     TEST(led_line[LED_IND(X,Y)], LED_BIT(X,Y)) |  | ||||||
| 
 | 
 | ||||||
| #ifdef CPU_32_BIT | #ifdef CPU_32_BIT | ||||||
|   #define SIG_DELAY() DELAY_US(1)   // Approximate a 1µs delay on 32-bit ARM
 |   #define SIG_DELAY() DELAY_US(1)   // Approximate a 1µs delay on 32-bit ARM
 | ||||||
| @ -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*/) { | void Max7219::error(const char * const func, const int32_t v1, const int32_t v2/*=-1*/) { | ||||||
|   #if ENABLED(MAX7219_ERRORS) |   #if ENABLED(MAX7219_ERRORS) | ||||||
|     SERIAL_ECHOPGM("??? Max7219"); |     SERIAL_ECHOPGM("??? Max7219::"); | ||||||
|     serialprintPGM(func); |     serialprintPGM(func); | ||||||
|     SERIAL_CHAR('('); |     SERIAL_CHAR('('); | ||||||
|     SERIAL_ECHO(v1); |     SERIAL_ECHO(v1); | ||||||
| @ -130,6 +126,7 @@ void Max7219::noop() { | |||||||
|     SIG_DELAY(); |     SIG_DELAY(); | ||||||
|     WRITE(MAX7219_CLK_PIN, LOW); |     WRITE(MAX7219_CLK_PIN, LOW); | ||||||
|     SIG_DELAY(); |     SIG_DELAY(); | ||||||
|  |     SIG_DELAY(); | ||||||
|     WRITE(MAX7219_CLK_PIN, HIGH); |     WRITE(MAX7219_CLK_PIN, HIGH); | ||||||
|     SIG_DELAY(); |     SIG_DELAY(); | ||||||
|   } |   } | ||||||
| @ -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
 | // Send out a single native row of bits to all units
 | ||||||
| void Max7219::all(const uint8_t line) { | void Max7219::refresh_line(const uint8_t line) { | ||||||
|   for (uint8_t u = 0; u < MAX7219_ROWS; u += 8) |   for (uint8_t u = MAX7219_NUMBER_UNITS; u--;) | ||||||
|     send(_ROW_REG(line), led_line[u + (line & 0x7)]); |     send(LINE_REG(line), led_line[(u << 3) | (line & 0x7)]); | ||||||
|   pulse_load(); |   pulse_load(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Send out a single native row of bits to just one unit
 | // Send out a single native row of bits to just one unit
 | ||||||
| void Max7219::one(const uint8_t line) { | void Max7219::refresh_unit_line(const uint8_t line) { | ||||||
|   for (uint8_t u = MAX7219_NUMBER_UNITS; u--;) { |   for (uint8_t u = MAX7219_NUMBER_UNITS; u--;) | ||||||
|     if (u == (line >> 3)) |     if (u == (line >> 3)) send(LINE_REG(line), led_line[line]); else noop(); | ||||||
|       send(_ROW_REG(line), led_line[line]); |  | ||||||
|     else |  | ||||||
|       noop(); |  | ||||||
|   } |  | ||||||
|   pulse_load(); |   pulse_load(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Max7219::set(const uint8_t line, const uint8_t bits) { | void Max7219::set(const uint8_t line, const uint8_t bits) { | ||||||
|   led_line[line] = bits; |   led_line[line] = bits; | ||||||
|   all(line); |   refresh_line(line); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #if ENABLED(MAX7219_NUMERIC) | #if ENABLED(MAX7219_NUMERIC) | ||||||
| @ -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 (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("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); | ||||||
|   all(MAX7219_LINE_AXIS); |   refresh_line(LED_IND(x, y)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Max7219::led_on(const uint8_t x, const uint8_t y) { | void Max7219::led_on(const uint8_t x, const uint8_t y) { | ||||||
| @ -250,8 +243,8 @@ void Max7219::led_toggle(const uint8_t x, const uint8_t y) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Max7219::send_row(const uint8_t row) { | void Max7219::send_row(const uint8_t row) { | ||||||
|   #if _ROT == 90 || _ROT == 270 |   #if _ROT == 0 || _ROT == 180 | ||||||
|     all(row); |     refresh_line(LED_IND(0, row)); | ||||||
|   #else |   #else | ||||||
|     UNUSED(row); |     UNUSED(row); | ||||||
|     refresh(); |     refresh(); | ||||||
| @ -260,7 +253,7 @@ void Max7219::send_row(const uint8_t row) { | |||||||
| 
 | 
 | ||||||
| void Max7219::send_column(const uint8_t col) { | void Max7219::send_column(const uint8_t col) { | ||||||
|   #if _ROT == 90 || _ROT == 270 |   #if _ROT == 90 || _ROT == 270 | ||||||
|     all(col);                               // Send the "column" out and strobe
 |     refresh_line(LED_IND(col, 0)); | ||||||
|   #else |   #else | ||||||
|     UNUSED(col); |     UNUSED(col); | ||||||
|     refresh(); |     refresh(); | ||||||
| @ -272,17 +265,20 @@ void Max7219::clear() { | |||||||
|   refresh(); |   refresh(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Max7219::fill() { | ||||||
|  |   memset(led_line, 0xFF, sizeof(led_line)); | ||||||
|  |   refresh(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Max7219::clear_row(const uint8_t row) { | void Max7219::clear_row(const uint8_t row) { | ||||||
|   if (row >= MAX7219_Y_LEDS) return error(PSTR("clear_row"), row); |   if (row >= MAX7219_Y_LEDS) return error(PSTR("clear_row"), row); | ||||||
|   for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) |   for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) CLR_7219(x, row); | ||||||
|     CLR_LED_7219(MAX7219_X_LEDS - 1 - x, row); |  | ||||||
|   send_row(row); |   send_row(row); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Max7219::clear_column(const uint8_t col) { | void Max7219::clear_column(const uint8_t col) { | ||||||
|   if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); |   if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); | ||||||
|   for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) |   for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) CLR_7219(col, y); | ||||||
|     CLR_LED_7219(col, MAX7219_Y_LEDS - y - 1); |  | ||||||
|   send_column(col); |   send_column(col); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -293,13 +289,10 @@ void Max7219::clear_column(const uint8_t col) { | |||||||
|  */ |  */ | ||||||
| void Max7219::set_row(const uint8_t row, const uint32_t val) { | void Max7219::set_row(const uint8_t row, const uint32_t val) { | ||||||
|   if (row >= MAX7219_Y_LEDS) return error(PSTR("set_row"), row); |   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++) { |   for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) { | ||||||
|     if (val & mask) |     if (val & mask) SET_7219(x, row); else CLR_7219(x, row); | ||||||
|       SET_LED_7219(MAX7219_X_LEDS - 1 - x, row); |     mask >>= 1; | ||||||
|     else |  | ||||||
|       CLR_LED_7219(MAX7219_X_LEDS - 1 - x, row); |  | ||||||
|     mask <<= 1; |  | ||||||
|   } |   } | ||||||
|   send_row(row); |   send_row(row); | ||||||
| } | } | ||||||
| @ -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) { | void Max7219::set_column(const uint8_t col, const uint32_t val) { | ||||||
|   if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col); |   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++) { |   for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) { | ||||||
|     if (val & mask) |     if (val & mask) SET_7219(col, y); else CLR_7219(col, y); | ||||||
|       SET_LED_7219(col, MAX7219_Y_LEDS - y - 1); |     mask >>= 1; | ||||||
|     else |  | ||||||
|       CLR_LED_7219(col, MAX7219_Y_LEDS - y - 1); |  | ||||||
|     mask <<= 1; |  | ||||||
|   } |   } | ||||||
|   send_column(col); |   send_column(col); | ||||||
| } | } | ||||||
| @ -378,8 +368,8 @@ void Max7219::set_columns_32bits(const uint8_t x, uint32_t val) { | |||||||
|   #endif |   #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Initialize the Max7219
 | ||||||
| void Max7219::register_setup() { | void Max7219::register_setup() { | ||||||
|   // Initialize the Max7219
 |  | ||||||
|   for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++) |   for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++) | ||||||
|     send(max7219_reg_scanLimit, 0x07); |     send(max7219_reg_scanLimit, 0x07); | ||||||
|   pulse_load();                        // tell the chips to load the clocked out data
 |   pulse_load();                        // tell the chips to load the clocked out data
 | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ | |||||||
|  *   #define MAX7219_DIN_PIN   78 |  *   #define MAX7219_DIN_PIN   78 | ||||||
|  *   #define MAX7219_LOAD_PIN  79 |  *   #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. |  * 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 |  * If you are using the Max7219 matrix for firmware debug purposes in time sensitive | ||||||
| @ -47,14 +47,14 @@ | |||||||
| #endif | #endif | ||||||
| #define _ROT ((MAX7219_ROTATE + 360) % 360) | #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 | #if _ROT == 0 || _ROT == 180 | ||||||
|   #define MAX7219_Y_LEDS          8 |   #define MAX7219_Y_LEDS          8 | ||||||
|   #define MAX7219_X_LEDS          MAX7219_ROWS |   #define MAX7219_X_LEDS          MAX7219_LINES | ||||||
| #elif _ROT == 90 || _ROT == 270 | #elif _ROT == 90 || _ROT == 270 | ||||||
|   #define MAX7219_X_LEDS          8 |   #define MAX7219_X_LEDS          8 | ||||||
|   #define MAX7219_Y_LEDS          MAX7219_ROWS |   #define MAX7219_Y_LEDS          MAX7219_LINES | ||||||
| #else | #else | ||||||
|   #error "MAX7219_ROTATE must be a multiple of +/- 90°." |   #error "MAX7219_ROTATE must be a multiple of +/- 90°." | ||||||
| #endif | #endif | ||||||
| @ -80,7 +80,7 @@ | |||||||
| 
 | 
 | ||||||
| class Max7219 { | class Max7219 { | ||||||
| public: | public: | ||||||
|   static uint8_t led_line[MAX7219_ROWS]; |   static uint8_t led_line[MAX7219_LINES]; | ||||||
| 
 | 
 | ||||||
|   Max7219() { } |   Max7219() { } | ||||||
| 
 | 
 | ||||||
| @ -93,13 +93,13 @@ public: | |||||||
|   static void send(const uint8_t reg, const uint8_t data); |   static void send(const uint8_t reg, const uint8_t data); | ||||||
| 
 | 
 | ||||||
|   // Refresh all units
 |   // 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
 |   // Update a single native line on all units
 | ||||||
|   static void all(const uint8_t line); |   static void refresh_line(const uint8_t line); | ||||||
| 
 | 
 | ||||||
|   // Update a single native row on the target unit
 |   // Update a single native line on just one unit
 | ||||||
|   static void one(const uint8_t line); |   static void refresh_unit_line(const uint8_t line); | ||||||
| 
 | 
 | ||||||
|   // 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); | ||||||
| @ -126,6 +126,9 @@ public: | |||||||
|   // Quickly clear the whole matrix
 |   // Quickly clear the whole matrix
 | ||||||
|   static void clear(); |   static void clear(); | ||||||
| 
 | 
 | ||||||
|  |   // Quickly fill the whole matrix
 | ||||||
|  |   static void fill(); | ||||||
|  | 
 | ||||||
|   // Apply custom code to update the matrix
 |   // Apply custom code to update the matrix
 | ||||||
|   static void idle_tasks(); |   static void idle_tasks(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -43,13 +43,11 @@ | |||||||
|  */ |  */ | ||||||
| void GcodeSuite::M7219() { | void GcodeSuite::M7219() { | ||||||
|   if (parser.seen('I')) { |   if (parser.seen('I')) { | ||||||
|     max7219.clear(); |  | ||||||
|     max7219.register_setup(); |     max7219.register_setup(); | ||||||
|  |     max7219.clear(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (parser.seen('F')) |   if (parser.seen('F')) max7219.fill(); | ||||||
|     for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) |  | ||||||
|       max7219.set_column(x, 0xFFFFFFFF); |  | ||||||
| 
 | 
 | ||||||
|   const uint32_t v = parser.ulongval('V'); |   const uint32_t v = parser.ulongval('V'); | ||||||
| 
 | 
 | ||||||
| @ -69,18 +67,18 @@ void GcodeSuite::M7219() { | |||||||
|       max7219.led_toggle(x, y); |       max7219.led_toggle(x, y); | ||||||
|   } |   } | ||||||
|   else if (parser.seen('D')) { |   else if (parser.seen('D')) { | ||||||
|     const uint8_t r = parser.value_byte(); |     const uint8_t line = parser.byteval('D') + (parser.byteval('U') << 3); | ||||||
|     if (r < MAX7219_ROWS) { |     if (line < MAX7219_LINES) { | ||||||
|       max7219.led_line[r] = v; |       max7219.led_line[line] = v; | ||||||
|       return max7219.all(r); |       return max7219.refresh_line(line); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (parser.seen('P')) { |   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["); |       SERIAL_ECHOPGM("led_line["); | ||||||
|       if (r < 10) SERIAL_CHAR('_'); |       if (r < 10) SERIAL_CHAR(' '); | ||||||
|       SERIAL_ECHO(r); |       SERIAL_ECHO(int(r)); | ||||||
|       SERIAL_ECHO("]="); |       SERIAL_ECHO("]="); | ||||||
|       for (uint8_t b = 8; b--;) SERIAL_CHAR('0' + TEST(max7219.led_line[r], b)); |       for (uint8_t b = 8; b--;) SERIAL_CHAR('0' + TEST(max7219.led_line[r], b)); | ||||||
|       SERIAL_EOL(); |       SERIAL_EOL(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user