forked from PAWPAW/lib_rgb
209 lines
8.6 KiB
C
209 lines
8.6 KiB
C
#ifndef RGB_EFFECT_H
|
||
#define RGB_EFFECT_H
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
#include "rgb_driver.h"
|
||
#include "volume_level.h"
|
||
#include "misc_utils.h"
|
||
|
||
// RGB灯的数量
|
||
#ifndef NUM_RGBS
|
||
#define NUM_RGBS (12)
|
||
#endif
|
||
|
||
// RGB灯组的数量,不应超过NUM_RGBS
|
||
#ifndef NUM_RGB_GROUPS
|
||
#define NUM_RGB_GROUPS (2)
|
||
#endif
|
||
|
||
// 控制RGB亮度的最大值,不超过255
|
||
#ifndef RGB_MAX
|
||
#define RGB_MAX (20)
|
||
#endif
|
||
|
||
// TODO:优化为编译时检查?
|
||
// 开关饱和检查,该检查会引入性能损失,在需要高刷新率时关闭它
|
||
#ifndef HSV_VALID_CHECK
|
||
#define HSV_VALID_CHECK (1)
|
||
#endif
|
||
|
||
// 控制HUE的最大值,不超过360°
|
||
#ifndef HSV_HUE_MAX
|
||
#define HSV_HUE_MAX (360)
|
||
#endif
|
||
|
||
// 控制饱和度的最大值,不超过100
|
||
#ifndef HSV_SATURATION_MAX
|
||
#define HSV_SATURATION_MAX (100)
|
||
#endif
|
||
|
||
// 控制VALUE,不超过100
|
||
#ifndef HSV_VALUE_MAX
|
||
#define HSV_VALUE_MAX (100)
|
||
#endif
|
||
|
||
// 微秒,定义每次颜色更新的延迟,在cycleRGB下,
|
||
// (1000/RGB_MAX)代表每个B/R/G值的爬升/缓降时间约为1000ms
|
||
#ifndef DELAY_TIME_RGB
|
||
#define DELAY_TIME_RGB (1000 / RGB_MAX)
|
||
#endif
|
||
|
||
/**
|
||
* 定义渐变方向的枚举类型。
|
||
*
|
||
* 该枚举用于指定颜色渐变过程中亮度的变化方向,用于控制RGB颜色空间的遍历,
|
||
* 实现颜色的平滑过渡,如呼吸灯效果。
|
||
*/
|
||
typedef enum
|
||
{
|
||
INCREMENTING, ///< 亮度递增:用于指示颜色亮度逐渐增加的渐变方向。
|
||
DECREMENTING ///< 亮度递减:用于指示颜色亮度逐渐减少的渐变方向。
|
||
} GradientDirection;
|
||
|
||
|
||
/** 遍历RGB颜色空间以实现呼吸灯效果。
|
||
*
|
||
* 此函数通过逐步调整RGB值来模拟呼吸灯效果,根据提供的方向增加或减少颜色亮度。
|
||
* 它更新颜色值,并将新颜色值通过RGB条输出。
|
||
*
|
||
* \param buf 指向存储RGB值的缓冲区的指针。
|
||
* \param color 当前颜色值。
|
||
* \param direction 指向当前渐变方向的指针,可以是递增或递减。
|
||
* \return 更新后的颜色值。
|
||
*/
|
||
uint32_t cycleRGB(uint32_t color, GradientDirection *direction);
|
||
|
||
/**
|
||
* 通过HSV颜色空间循环改变色调(Hue)以实现颜色渐变效果。
|
||
*
|
||
* 此函数负责在HSV颜色模型中改变色调值,从而在不改变饱和度(Saturation)和亮度(Value)的情况下
|
||
* 遍历不同的颜色。色调值会在0到359之间循环,每次调用函数色调值增加1,当达到359后重置为0。
|
||
* 函数输出当前色调值并将新的RGB值存储在提供的缓冲区中。
|
||
*
|
||
* \param buf 指向存储RGB值的缓冲区的指针。此缓冲区将被更新为对应的RGB值。
|
||
* \param hue 指向当前色调值的指针。色调值在0到359之间变化。
|
||
*
|
||
* \return 根据当前色调值、饱和度和亮度计算出的RGB颜色值。
|
||
*/
|
||
uint32_t cycleHSV(uint32_t *hue);
|
||
|
||
/**
|
||
* 将HSV颜色空间转换为RGB颜色空间。
|
||
*
|
||
* 此函数接受HSV(色相、饱和度、亮度)颜色空间的值,并将其转换为RGB(红、绿、蓝)颜色空间的值。
|
||
* 转换过程中,可能会执行有效性检查(取决于HSV_VALID_CHECK预处理器变量)。
|
||
*
|
||
* 实现步骤:
|
||
* 1. **规范化色调值:**
|
||
* $ H' = \frac{H}{360} $
|
||
*
|
||
* 2. **计算色度(Chroma):**
|
||
* $ C = S \times V $
|
||
*
|
||
* 3. **计算X值:**
|
||
* $ X = C \times (1 - |(H' \times 6) \mod 2 - 1|) $
|
||
*
|
||
* 4. **计算中间RGB值:**
|
||
* 根据H'的值,我们有:
|
||
* - 如果 $( 0 \leq H' < 1 )$:$ R1 = C, G1 = X, B1 = 0 $
|
||
* - 如果 $( 1 \leq H' < 2 )$:$ R1 = X, G1 = C, B1 = 0 $
|
||
* - 如果 $( 2 \leq H' < 3 )$:$ R1 = 0, G1 = C, B1 = X $
|
||
* - 如果 $( 3 \leq H' < 4 )$:$ R1 = 0, G1 = X, B1 = C $
|
||
* - 如果 $( 4 \leq H' < 5 )$:$ R1 = X, G1 = 0, B1 = C $
|
||
* - 如果 $( 5 \leq H' < 6 )$:$ R1 = C, G1 = 0, B1 = X $
|
||
*
|
||
* 5. **计算最终RGB值:**
|
||
* $ R' = (R1 + (V - C)) \times 255 $
|
||
* $ G' = (G1 + (V - C)) \times 255 $
|
||
* $ B' = (B1 + (V - C)) \times 255 $
|
||
*
|
||
* 6. **限制最终值范围:**
|
||
* $ R'' = \min(\max(R', 0), 255) $
|
||
* $ G'' = \min(\max(G', 0), 255) $
|
||
* $ B'' = \min(\max(B', 0), 255) $
|
||
*
|
||
* \param hue 指向色相值的指针,色相值的范围通常是0-360。
|
||
* \param sat 指向饱和度值的指针,饱和度值的范围通常是0-100。
|
||
* \param value 指向亮度值的指针,亮度值的范围通常是0-100。
|
||
*
|
||
* \return 转换后的RGB值,其中G占最高8位,R占中间8位,B占最低8位。
|
||
*/
|
||
uint32_t HSV_to_RGB(uint32_t *hue, uint32_t *sat, uint32_t *value);
|
||
|
||
/**
|
||
* 将单一颜色填充到整个RGB条中,并控制显示颜色的时间长度。
|
||
*
|
||
* 此函数遍历RGB条的每个颜色单元,将它们统一设置为提供的颜色值。设置完成后,
|
||
* 通过调用输出函数将这些颜色输出到RGB条上。之后,函数会调用延迟函数以保持
|
||
* 当前颜色一段时间,从而控制颜色显示的持续时间,这可以用于创建闪烁效果。
|
||
*
|
||
* \param buf 指向存储RGB值的缓冲区的指针,每个元素代表RGB条中一个颜色单元的颜色值。
|
||
* \param color 要填充的统一颜色值。
|
||
*/
|
||
void fill_gradient(uint32_t *buf, size_t num_filled_rgb, uint32_t color);
|
||
|
||
|
||
/**
|
||
* 在tile[1]上启动一个永久循环,该循环会持续更新RGB灯条的颜色。
|
||
* 它初始化一个颜色值,然后在一个无限循环中不断地调用fill_gradient和cycleRGB函数,
|
||
* 以实现RGB灯条颜色的渐变效果。颜色的变化方向会根据GradientDirection变量进行调整。
|
||
*/
|
||
void cycleRGB_driver();
|
||
|
||
/**
|
||
* 驱动HSV颜色空间中的颜色循环,以实现连续的颜色渐变效果。
|
||
*
|
||
* 此函数初始化颜色值,并进入一个无限循环,不断地计算新的颜色值并更新LED阵列。
|
||
* 使用并发执行关键字 'par' 来实现循环内部的并行处理。这个函数假定运行环境支持并行关键字 'par'。
|
||
*
|
||
* 在此循环中,它首先使用当前颜色填充一个预定义大小的缓冲区,然后调用 `cycleHSV` 函数
|
||
* 来更新当前色相值并获取新的颜色。最后,它打印出当前的GRB颜色值。
|
||
*
|
||
* 注意:此函数设计为在嵌入式系统或具有并行处理能力的系统上运行。
|
||
* 它包含一个无限循环,应确保有适当的机制来安全地退出或中断执行。
|
||
*/
|
||
void cycleHSV_driver();
|
||
|
||
/**
|
||
* 将多种颜色分组填充到RGB条中,并控制显示颜色的时间长度。
|
||
*
|
||
* 此函数将RGB条分为若干组,每组填充指定的颜色。每组可以填充不同数量的RGB单元,
|
||
* 数量由num_filled_rgb数组指定。填充完所有组指定的颜色后,剩余的RGB单元将被熄灭。
|
||
* 如果组号为奇数,则该组的颜色顺序将被翻转。所有颜色设置完成后,通过调用输出函数
|
||
* 将这些颜色输出到RGB条上。最后,函数调用延迟函数以保持当前颜色一段时间。
|
||
*
|
||
* \param buf 指向存储RGB值的缓冲区的指针,每个元素代表RGB条中一个颜色单元的颜色值。
|
||
* \param colors 指向存储每组颜色值的数组的指针,每个元素代表一个组的颜色值。
|
||
* \param num_filled_rgb 指向存储每组已填充RGB单元数量的数组的指针,每个元素代表一个组已填充的RGB单元数量。
|
||
*/
|
||
void fill_gradient_with_groups(uint32_t *buf, uint32_t *colors, size_t *num_filled_rgb);
|
||
|
||
/**
|
||
* 测试音量响应&HSV色彩循环
|
||
*
|
||
* 此函数不断地循环通过HSV色彩空间,并根据音量水平来更新RGB条的颜色。
|
||
* 每个颜色组都会根据音量水平的随机值来更新其亮度。当前色相值从红色开始,
|
||
* 并在每次循环中更新,以通过HSV色彩空间进行循环。每次循环后,将当前颜色
|
||
* 应用到RGB条的相应组中。此函数旨在并发执行,以模拟实时音乐响应的灯光效果。
|
||
*
|
||
* 注意:此函数包含无限循环,仅用于测试目的。
|
||
* 注意:使用了par关键词来并发执行代码块,这依赖于特定的硬件或并发模型。
|
||
*/
|
||
void test_cycleHSV_with_vol_level();
|
||
|
||
/**
|
||
* 用于测试HSV溢出
|
||
*/
|
||
void test_HSV_to_RGB();
|
||
|
||
/**
|
||
* 测试 fill_gradient_with_groups 函数。
|
||
*
|
||
* 此测试函数创建一个缓冲区,并定义两种颜色和每组的填充数量,然后调用
|
||
* fill_gradient_with_groups 函数来填充缓冲区。之后,它会验证缓冲区中的颜色
|
||
* 是否符合预期:每组的前N个LED应该是指定的颜色,剩余的LED应该是关闭的(黑色)。
|
||
* 如果所有LED的颜色都正确,测试通过;否则,输出错误信息并标记测试失败。
|
||
*/
|
||
void test_fill_gradient_with_groups();
|
||
#endif // RGB_EFFECT_H
|