Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RGBW support to PWM and SPI drivers for ChibiOS #14327

Merged
merged 2 commits into from
Sep 18, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 35 additions & 3 deletions platforms/chibios/drivers/ws2812_pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
/* Adapted from https://github.com/joewa/WS2812-LED-Driver_ChibiOS/ */

#ifdef RGBW
# error "RGBW not supported"
# define WS2812_CHANNELS 4
#else
# define WS2812_CHANNELS 3
#endif

#ifndef WS2812_PWM_DRIVER
Expand Down Expand Up @@ -68,8 +70,9 @@
* The reset period for each frame is defined in WS2812_TRST_US.
* Calculate the number of zeroes to add at the end assuming 1.25 uS/bit:
*/
#define WS2812_COLOR_BITS (WS2812_CHANNELS * 8)
#define WS2812_RESET_BIT_N (1000 * WS2812_TRST_US / 1250)
#define WS2812_COLOR_BIT_N (RGBLED_NUM * 24) /**< Number of data bits */
#define WS2812_COLOR_BIT_N (RGBLED_NUM * WS2812_COLOR_BITS) /**< Number of data bits */
#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */

/**
Expand Down Expand Up @@ -114,7 +117,7 @@
*
* @return The bit index
*/
#define WS2812_BIT(led, byte, bit) (24 * (led) + 8 * (byte) + (7 - (bit)))
#define WS2812_BIT(led, byte, bit) (WS2812_COLOR_BITS * (led) + 8 * (byte) + (7 - (bit)))

#if (WS2812_BYTE_ORDER == WS2812_BYTE_ORDER_GRB)
/**
Expand Down Expand Up @@ -228,6 +231,20 @@
# define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 0, (bit))
#endif

#ifdef RGBW
/**
* @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given white bit
*
* @note The white byte is the last byte in the color packet
*
* @param[in] led: The led index [0, @ref WS2812_LED_N)
* @param[in] bit: The bit index [0, 7]
*
* @return The bit index
*/
# define WS2812_WHITE_BIT(led, bit) WS2812_BIT((led), 3, (bit))
#endif

/* --- PRIVATE VARIABLES ---------------------------------------------------- */

static uint32_t ws2812_frame_buffer[WS2812_BIT_N + 1]; /**< Buffer for a frame */
Expand Down Expand Up @@ -296,6 +313,17 @@ void ws2812_write_led(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b) {
ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
}
}
void ws2812_write_led_rgbw(uint16_t led_number, uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
// Write color to frame buffer
for (uint8_t bit = 0; bit < 8; bit++) {
ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
#ifdef RGBW
ws2812_frame_buffer[WS2812_WHITE_BIT(led_number, bit)] = ((w >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0;
#endif
}
}

// Setleds for standard RGB
void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
Expand All @@ -306,6 +334,10 @@ void ws2812_setleds(LED_TYPE* ledarray, uint16_t leds) {
}

for (uint16_t i = 0; i < leds; i++) {
#ifdef RGBW
ws2812_write_led_rgbw(i, ledarray[i].r, ledarray[i].g, ledarray[i].b, ledarray[i].w);
#else
ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b);
#endif
}
}
15 changes: 9 additions & 6 deletions platforms/chibios/drivers/ws2812_spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@

/* Adapted from https://github.com/gamazeps/ws2812b-chibios-SPIDMA/ */

#ifdef RGBW
# error "RGBW not supported"
#endif

// Define the spi your LEDs are plugged to here
#ifndef WS2812_SPI
# define WS2812_SPI SPID1
Expand Down Expand Up @@ -74,8 +70,12 @@
#endif

#define BYTES_FOR_LED_BYTE 4
#define NB_COLORS 3
#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * NB_COLORS)
#ifdef RGBW
# define WS2812_CHANNELS 4
#else
# define WS2812_CHANNELS 3
#endif
#define BYTES_FOR_LED (BYTES_FOR_LED_BYTE * WS2812_CHANNELS)
#define DATA_SIZE (BYTES_FOR_LED * RGBLED_NUM)
#define RESET_SIZE (1000 * WS2812_TRST_US / (2 * 1250))
#define PREAMBLE_SIZE 4
Expand Down Expand Up @@ -116,6 +116,9 @@ static void set_led_color_rgb(LED_TYPE color, int pos) {
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE + j] = get_protocol_eq(color.g, j);
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 2 + j] = get_protocol_eq(color.r, j);
#endif
#ifdef RGBW
for (int j = 0; j < 4; j++) tx_start[BYTES_FOR_LED * pos + BYTES_FOR_LED_BYTE * 4 + j] = get_protocol_eq(color.w, j);
#endif
}

void ws2812_init(void) {
Expand Down