From 479a1316c34073fb10381af93643ec95f7f732bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Thu, 21 Jul 2022 21:24:13 +0200 Subject: [PATCH] app: reuse matrix control for WS2812b --- application.c | 114 +++++++++++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/application.c b/application.c index 53b7d42..d98aab0 100644 --- a/application.c +++ b/application.c @@ -103,6 +103,9 @@ static volatile uint32_t dial_steps = 0; /**< set to drv8825_steps when dial is static uint8_t rgbmatrix_data[RGBMATRIX_HEIGHT / 2][RGBMATRIX_WIDTH * 2]; /**< data to be sent to RGB matrix (one byte includes upper and lower half values, each byte has 2 clock edges) */ #define RGBMATRIX_TIMER 3 /**< timer to update lines */ +#define WSMATRIX_HEIGHT (2 * 8) /**< WS2812b panel height, in pixels */ +#define WSMATRIX_WIDTH 32 /**< WS2812b panel width, in pixels */ + // RGBW LED strips #define STRIP_TIMER 4 /**< timer used for the PWM */ #define STRIP_R_PIN PB9 /**< pin used to drive gate for red channel */ @@ -154,56 +157,80 @@ static void rgbmatrix_clear(void) } } -/** set color of the LED on the RGB matrix +/** set color of the LED on the RGB matrix or WS2812b panel + * @param[in] ws false to display on RGB matrix, true on WS2812b panel * @param[in] x horizontal position (0 = left) * @param[in] y vertical position (0 = top) * @param[in] r if the red LED should be on * @param[in] g if the green LED should be on * @param[in] b if the blue LED should be on */ -static void rgbmatrix_set(int16_t x, int16_t y, bool r, bool g, bool b) +static void matrix_set(bool ws, int16_t x, int16_t y, bool r, bool g, bool b) { - if (x < 0 || x >= RGBMATRIX_WIDTH) { + if (x < 0 || x >= (ws ? WSMATRIX_WIDTH : RGBMATRIX_WIDTH)) { return; } - if (y < 0 || y >= RGBMATRIX_HEIGHT) { + if (y < 0 || y >= (ws ? WSMATRIX_HEIGHT : RGBMATRIX_HEIGHT)) { return; } - const uint8_t row = y % (RGBMATRIX_HEIGHT / 2); // get the actual line/row - const uint8_t col = x * 2; // get the actual column - uint8_t data = 0; // there we will set the color bits - if (y < (RGBMATRIX_HEIGHT / 2)) { - data = rgbmatrix_data[row][col] & 0xe0; // keep lower line colors - if (r) { - data |= (1 << 2); - } - if (g) { - data |= (1 << 3); - } - if (b) { - data |= (1 << 4); + if (ws) { +#define WSMATRIX_BRIGHTNESS 0x20 + uint8_t col = 0, row = 0; + if (y < WSMATRIX_HEIGHT / 2) { + col = WSMATRIX_WIDTH - 1 - x; + if (1 == x % 2) { + row = WSMATRIX_HEIGHT / 2 - 1 - y; + } else { + row = y; + } + } else { + col = x + WSMATRIX_WIDTH; + y -= WSMATRIX_HEIGHT / 2; + if (1 == x % 2) { + row = WSMATRIX_HEIGHT / 2 - 1 - y; + } else { + row = y; + } } + led_ws2812b_set_rgb(col * (WSMATRIX_HEIGHT / 2U) + row, g * WSMATRIX_BRIGHTNESS, r * WSMATRIX_BRIGHTNESS, b * WSMATRIX_BRIGHTNESS); } else { - data = rgbmatrix_data[row][col] & 0x1c; // keep upper line colors - if (r) { - data |= (1 << 5); - } - if (g) { - data |= (1 << 6); - } - if (b) { - data |= (1 << 7); + const uint8_t row = y % (RGBMATRIX_HEIGHT / 2); // get the actual line/row + const uint8_t col = x * 2; // get the actual column + uint8_t data = 0; // there we will set the color bits + if (y < (RGBMATRIX_HEIGHT / 2)) { + data = rgbmatrix_data[row][col] & 0xe0; // keep lower line colors + if (r) { + data |= (1 << 2); + } + if (g) { + data |= (1 << 3); + } + if (b) { + data |= (1 << 4); + } + } else { + data = rgbmatrix_data[row][col] & 0x1c; // keep upper line colors + if (r) { + data |= (1 << 5); + } + if (g) { + data |= (1 << 6); + } + if (b) { + data |= (1 << 7); + } } + // set data on low edge + rgbmatrix_data[row][col + 0] &= 0x3; // clear color data (don't touch clock and latch data) + rgbmatrix_data[row][col + 0] |= data; // set the LED data + // set data on high edge + rgbmatrix_data[row][col + 1] &= 0x3; // clear color data (don't touch clock and latch data) + rgbmatrix_data[row][col + 1] |= data; // set the LED data on clock high edge } - // set data on low edge - rgbmatrix_data[row][col + 0] &= 0x3; // clear color data (don't touch clock and latch data) - rgbmatrix_data[row][col + 0] |= data; // set the LED data - // set data on high edge - rgbmatrix_data[row][col + 1] &= 0x3; // clear color data (don't touch clock and latch data) - rgbmatrix_data[row][col + 1] |= data; // set the LED data on clock high edge } -/** draw character on RGB matrix +/** draw character on matrix + * @param[in] ws false to display on RGB matrix, true on WS2812b panel * @param[in] x horizontal position (0 = left) * @param[in] y vertical position (0 = top) * @param[in] c character to draw @@ -212,7 +239,7 @@ static void rgbmatrix_set(int16_t x, int16_t y, bool r, bool g, bool b) * @param[in] g if the character should be drawn in green * @param[in] b if the character should be drawn in blue */ -static void rgbmatrix_putc(int16_t x, int16_t y, char c, enum font_name font, bool red, bool green, bool blue) +static void matrix_putc(bool ws, int16_t x, int16_t y, char c, enum font_name font, bool red, bool green, bool blue) { // sanity checks if (font >= FONT_MAX) { @@ -221,10 +248,10 @@ static void rgbmatrix_putc(int16_t x, int16_t y, char c, enum font_name font, bo if (c < ' ' || c > '~') { return; } - if (x + fonts[font].width < 0 || x >= RGBMATRIX_WIDTH) { + if (x + fonts[font].width < 0 || x >= (ws ? WSMATRIX_WIDTH : RGBMATRIX_WIDTH)) { return; } - if (y + fonts[font].height < 0 || y >= RGBMATRIX_HEIGHT) { + if (y + fonts[font].height < 0 || y >= (ws ? WSMATRIX_HEIGHT : RGBMATRIX_HEIGHT)) { return; } @@ -234,15 +261,16 @@ static void rgbmatrix_putc(int16_t x, int16_t y, char c, enum font_name font, bo for (uint8_t row = 0; row < fonts[font].height; row++) { const bool dot = (column >> (fonts[font].height - 1 - row)) & 0x01; if (dot) { - rgbmatrix_set(x + col, y + row, red, green, blue); + matrix_set(ws, x + col, y + row, red, green, blue); } else { - rgbmatrix_set(x + col, y + row, false, false, false); + matrix_set(ws, x + col, y + row, false, false, false); } } } } /** draw text on RGB matrix + * @param[in] ws false to display on RGB matrix, true on WS2812b panel * @param[in] x horizontal position (0 = left) * @param[in] y vertical position (0 = top) * @param[in] str text to draw @@ -251,7 +279,7 @@ static void rgbmatrix_putc(int16_t x, int16_t y, char c, enum font_name font, bo * @param[in] g if the character should be drawn in green * @param[in] b if the character should be drawn in blue */ -static void rgbmatrix_puts(int16_t x, int16_t y, const char* str, enum font_name font, bool red, bool green, bool blue) +static void matrix_puts(bool ws, int16_t x, int16_t y, const char* str, enum font_name font, bool red, bool green, bool blue) { // sanity checks if (NULL == str) { @@ -260,17 +288,17 @@ static void rgbmatrix_puts(int16_t x, int16_t y, const char* str, enum font_name if (font >= FONT_MAX) { return; } - if (y + fonts[font].height < 0 || y >= RGBMATRIX_HEIGHT) { + if (y + fonts[font].height < 0 || y >= (ws ? WSMATRIX_HEIGHT : RGBMATRIX_HEIGHT)) { return; } const uint8_t len = strlen(str); for (uint8_t i = 0; i < len; i++) { - if (x >= RGBMATRIX_WIDTH) { + if (x >= (ws ? WSMATRIX_WIDTH : RGBMATRIX_WIDTH)) { return; } if (x + fonts[font].width >= 0) { - rgbmatrix_putc(x, y, str[i], font, red, green, blue); + matrix_putc(ws, x, y, str[i], font, red, green, blue); } x += fonts[font].width + 1; } @@ -1105,7 +1133,7 @@ void main(void) if (wakeup_flag) { // time to do periodic checks wakeup_flag = false; // clear flag rgbmatrix_clear(); - rgbmatrix_puts(scroll_pos, 8, scroll_text, FONT_KING14, true, true, true); + matrix_puts(false, scroll_pos, 8, scroll_text, FONT_KING14, true, true, true); if (scroll_pos < -1 * (int16_t)strlen(scroll_text) * (fonts[FONT_KING14].width + 1)) { scroll_pos = 64; } else {