diff --git a/sys/include/color.h b/sys/include/color.h index 8612e898b9..63a204bfe6 100644 --- a/sys/include/color.h +++ b/sys/include/color.h @@ -127,6 +127,45 @@ static inline void color_rgb_invert(const color_rgb_t *rgb, color_rgb_t *inv_rgb inv_rgb->b = rgb->b ^ 0xFF; } +/** + * @brief Shifts a given rgb color to change it's brightness + * + * @pre ((rgb != NULL) && (out != NULL)) + * + * @param[in] rgb Input rgb color, that should be shifted. Must be NOT NULL + * @param[out] out Output rgb color, result of the shift. Must be NOT NULL + * @param[in] shift Amount by which the color components should be shifted. + * May be positive (shift to left) or negative (shift to right). + */ +static inline void color_rgb_shift(const color_rgb_t *rgb, color_rgb_t *out, int8_t shift) +{ + if (shift > 0) { + out->r = rgb->r << shift; + out->g = rgb->g << shift; + out->b = rgb->b << shift; + } else { + out->r = rgb->r >> -shift; + out->g = rgb->g >> -shift; + out->b = rgb->b >> -shift; + } +} + +/** + * @brief Change the brightness of a RGB color by multiplying it with a set factor. + * + * @pre ((rgb != NULL) && (out != NULL)) + * + * @param[in] rgb Input rgb color, that should be multiplied. Must be NOT NULL + * @param[out] out Output rgb color. Must be NOT NULL + * @param[in] level New brightness level. 255 = Full Brightness, 0 = Off. + */ +static inline void color_rgb_set_brightness(const color_rgb_t *rgb, color_rgb_t *out, uint8_t level) +{ + out->r = ((unsigned)rgb->r * level + 128) >> 8; + out->g = ((unsigned)rgb->g * level + 128) >> 8; + out->b = ((unsigned)rgb->b * level + 128) >> 8; +} + /** * @brief Calculate the complementary color of a given rgb color. * diff --git a/tests/driver_ws281x/main.c b/tests/driver_ws281x/main.c index 21575846ab..fc6e0d20e4 100644 --- a/tests/driver_ws281x/main.c +++ b/tests/driver_ws281x/main.c @@ -73,24 +73,18 @@ int main(void) puts("Animation: Fading rainbow..."); last_wakeup = xtimer_now(); for (unsigned i = 0; i < RAINBOW_LEN; i++) { - for (unsigned j = 0; j < 100; j++) { - color_rgb_t col = { - .r = (uint8_t)(((unsigned)rainbow[i].r * j + 50) / 100), - .g = (uint8_t)(((unsigned)rainbow[i].g * j + 50) / 100), - .b = (uint8_t)(((unsigned)rainbow[i].b * j + 50) / 100), - }; + for (unsigned j = 0; j < 255; j++) { + color_rgb_t col; + color_rgb_set_brightness(&rainbow[i], &col, j); for (uint16_t k = 0; k < dev.params.numof; k++) { ws281x_set(&dev, k, col); } ws281x_write(&dev); xtimer_periodic_wakeup(&last_wakeup, 10 * US_PER_MS); } - for (unsigned j = 100; j > 0; j--) { - color_rgb_t col = { - .r = (uint8_t)(((unsigned)rainbow[i].r * j + 50) / 100), - .g = (uint8_t)(((unsigned)rainbow[i].g * j + 50) / 100), - .b = (uint8_t)(((unsigned)rainbow[i].b * j + 50) / 100), - }; + for (unsigned j = 255; j > 0; j--) { + color_rgb_t col; + color_rgb_set_brightness(&rainbow[i], &col, j); for (uint16_t k = 0; k < dev.params.numof; k++) { ws281x_set(&dev, k, col); }