forked from PAWPAW/lib_rgb
添加了lib库的主要内容
- HSV颜色循环驱动 - RGB灯条驱动 - 模拟呼吸灯 - 色调循环 - 颜色转换 - 颜色填充
This commit is contained in:
32
lib_rgb/api/rgb_driver.h
Normal file
32
lib_rgb/api/rgb_driver.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef RGB_DRIVER_H
|
||||
#define RGB_DRIVER_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
/** 串行输出24位值。
|
||||
*
|
||||
* 此函数接收一个32位无符号整数,并将其作为24位值串行输出。
|
||||
* 假设值的最高有效8位不使用。该函数将位顺序反转,然后使用定时器控制
|
||||
* 的时间信息逐位串行输出。
|
||||
*
|
||||
* 输出操作在第4个引脚上完成,定时信息由定时器'tmr'提供。该函数会打印
|
||||
* 每个位的值和fall_time。
|
||||
* TODO: 适配其他类型的引脚和bit口
|
||||
*
|
||||
* \param value 要串行输出为24位的32位值。
|
||||
*/
|
||||
void output_24bit_value_serially(uint32_t value);
|
||||
|
||||
/** 输出RGB值数组。
|
||||
*
|
||||
* 此函数接收一个包含32位RGB值的数组以及要输出的RGB数量。
|
||||
* 它调用'output_24bit_value_serially'函数为每个RGB值进行串行输出。
|
||||
*
|
||||
* 每个RGB值都使用'output_24bit_value_serially'函数作为24位值发送。
|
||||
*
|
||||
* \param buf 包含32位RGB值的缓冲区。
|
||||
* \param num_rgbs 要输出的RGB值数量。
|
||||
*/
|
||||
void output_rgb_array(uint32_t buf[], uint32_t num_rgbs);
|
||||
|
||||
#endif // RGB_DRIVER_H
|
||||
99
lib_rgb/api/rgb_effect.h
Normal file
99
lib_rgb/api/rgb_effect.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef RGB_EFFECT_H
|
||||
#define RGB_EFFECT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* 定义渐变方向的枚举类型。
|
||||
*
|
||||
* 该枚举用于指定颜色渐变过程中亮度的变化方向,用于控制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预处理器变量)。
|
||||
*
|
||||
* \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, uint32_t color);
|
||||
|
||||
|
||||
/**
|
||||
* 在tile[1]上启动一个永久循环,该循环会持续更新RGB灯条的颜色。
|
||||
* 它初始化一个颜色值,然后在一个无限循环中不断地调用fill_gradient和cycleRGB函数,
|
||||
* 以实现RGB灯条颜色的渐变效果。颜色的变化方向会根据GradientDirection变量进行调整。
|
||||
*/
|
||||
void cycleRGB_driver();
|
||||
|
||||
/**
|
||||
* 驱动HSV颜色空间中的颜色循环,以实现连续的颜色渐变效果。
|
||||
*
|
||||
* 此函数初始化颜色值,并进入一个无限循环,不断地计算新的颜色值并更新LED阵列。
|
||||
* 使用并发执行关键字 'par' 来实现循环内部的并行处理。这个函数假定运行环境支持并行关键字 'par'。
|
||||
*
|
||||
* 在此循环中,它首先使用当前颜色填充一个预定义大小的缓冲区,然后调用 `cycleHSV` 函数
|
||||
* 来更新当前色相值并获取新的颜色。最后,它打印出当前的GRB颜色值。
|
||||
*
|
||||
* 注意:此函数设计为在嵌入式系统或具有并行处理能力的系统上运行。
|
||||
* 它包含一个无限循环,应确保有适当的机制来安全地退出或中断执行。
|
||||
*/
|
||||
void cycleHSV_driver();
|
||||
|
||||
|
||||
/**
|
||||
* 用于测试HSV溢出
|
||||
*/
|
||||
void HSV_to_RGB_TEST();
|
||||
|
||||
#endif // RGB_EFFECT_H
|
||||
10
lib_rgb/module_build_info
Normal file
10
lib_rgb/module_build_info
Normal file
@@ -0,0 +1,10 @@
|
||||
VERSION = 0.0.1
|
||||
|
||||
DEPENDENT_MODULES =
|
||||
|
||||
MODULE_XCC_FLAGS = $(XCC_FLAGS) -g -O3 -Wall -Wextra -Werror
|
||||
|
||||
EXPORT_INCLUDE_DIRS = api
|
||||
|
||||
SOURCE_DIRS = src
|
||||
|
||||
79
lib_rgb/src/rgb_driver.xc
Normal file
79
lib_rgb/src/rgb_driver.xc
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <xs1.h> // 包含对XCORE资源的操作
|
||||
#include <platform.h> // 包含对封装的定义,引用以使用 on tile[] 语法
|
||||
#include <stdio.h> // 包含基本的输入输出函数
|
||||
#include <timer.h>
|
||||
#include "xclib.h"
|
||||
#include "stdint.h"
|
||||
|
||||
// 如果灯的显示没有出现问题,不要修改这些宏
|
||||
#define MICROSECONDS 100
|
||||
#define RT23_RST_DELAY (MICROSECONDS * 200000) // 200 ms 当前没有使用,因为引脚通常自动拉低
|
||||
#define T0H_DELAY (33) // 0.3 μs, assuming MICROSECONDS is 100 times the actual microsecond count
|
||||
#define T1H_DELAY (63) // 0.6 μs
|
||||
#define T0L_DELAY (93) // 0.9 μs
|
||||
#define T1L_DELAY (63) // 0.6 μs
|
||||
|
||||
|
||||
on tile[1] : out port p_rgb_rgb = XS1_PORT_4A; // 注意:当前代码仅适用于4bit端口
|
||||
timer tmr;
|
||||
|
||||
// 向4A3写时序,点亮RT23
|
||||
uint32_t output_bit_on_4th_pin(uint32_t bit, uint32_t fall_time)
|
||||
{
|
||||
if (bit == 1)
|
||||
{
|
||||
p_rgb_rgb<:0xff; // 输出到4位端口
|
||||
tmr when timerafter(fall_time + T1H_DELAY):> fall_time; // 等待T1H时长
|
||||
// printf("[x]fall_time: %u\n", fall_time);
|
||||
p_rgb_rgb<:0x00; // 将第4位设置为低电平
|
||||
tmr when timerafter(fall_time + T1L_DELAY):> fall_time; // 等待T1L时长
|
||||
// printf("[x]fall_time: %u\n", fall_time);
|
||||
}
|
||||
else if (bit == 0)
|
||||
{
|
||||
p_rgb_rgb<:0xff; // 输出到4位端口
|
||||
tmr when timerafter(fall_time + T0H_DELAY):> fall_time; // 等待T0H时长
|
||||
// printf("[x]fall_time: %u\n", fall_time);
|
||||
p_rgb_rgb<:0x00; // 将第4位设置为低电平
|
||||
tmr when timerafter(fall_time + T0L_DELAY):> fall_time; // 等待T0L时长
|
||||
// printf("[x]fall_time: %u\n", fall_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("[x]ERROR, ILLEGAL INPUT\n");
|
||||
}
|
||||
|
||||
return fall_time;
|
||||
}
|
||||
|
||||
// 串行输出24位值
|
||||
void output_24bit_value_serially(uint32_t value)
|
||||
{
|
||||
uint32_t fall_time = 0;
|
||||
tmr:> fall_time;
|
||||
// // 重置 RT23,
|
||||
// p_rgb_rgb <: 0x000000;
|
||||
// tmr when timerafter(fall_time + RT23_RST_DELAY):> fall_time;
|
||||
|
||||
value = value << 8;
|
||||
value = bitrev(value); // 这里会占用时间。
|
||||
|
||||
// printf("[x]value: %u\n", value);
|
||||
// Write a 24bit code
|
||||
for (int i = 0; i < 24; i++)
|
||||
{
|
||||
uint32_t bit = (value >> i) & 0x1; // 获取当前位
|
||||
tmr:> fall_time;
|
||||
fall_time = output_bit_on_4th_pin(bit, fall_time); // 通过第4位输出
|
||||
// printf("[x]fall_time: %u\n", fall_time);
|
||||
}
|
||||
}
|
||||
|
||||
// 输出RGB值数组
|
||||
void output_rgb_array(uint32_t buf[], uint32_t num_rgbs)
|
||||
{
|
||||
for (uint32_t rgb = 0; rgb < num_rgbs; ++rgb)
|
||||
{
|
||||
output_24bit_value_serially(buf[rgb]);
|
||||
}
|
||||
}
|
||||
265
lib_rgb/src/rgb_effect.xc
Normal file
265
lib_rgb/src/rgb_effect.xc
Normal file
@@ -0,0 +1,265 @@
|
||||
#include <xs1.h> // 包含对XCORE资源的操作
|
||||
#include "rgb_driver.h"
|
||||
#include "xclib.h"
|
||||
#include "timer.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// RGB灯的数量
|
||||
#ifndef NUM_RGBS
|
||||
#define NUM_RGBS (12)
|
||||
#endif
|
||||
|
||||
// 控制RGB亮度的最大值,不超过255
|
||||
#ifndef RGB_MAX
|
||||
#define RGB_MAX (10)
|
||||
#endif
|
||||
|
||||
// 开关饱和检查
|
||||
#ifndef HSV_VALID_CHECK
|
||||
#define HSV_VALID_CHECK (0)
|
||||
#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
|
||||
|
||||
// TODO: 当RGB_MAX等值超限时,raise error
|
||||
// 定义一个枚举来表示渐变方向
|
||||
typedef enum
|
||||
{
|
||||
INCREMENTING, // 亮度递增
|
||||
DECREMENTING // 亮度递减
|
||||
} GradientDirection;
|
||||
|
||||
|
||||
// 检查HSV值是否在有效范围内,如果溢出则将值设为最大值,并打印报错
|
||||
void is_HSV_valid(uint32_t *hue, uint32_t *sat, uint32_t *value)
|
||||
{
|
||||
if (*hue >= HSV_HUE_MAX)
|
||||
{
|
||||
printf("[x]hue overflow, current: %u\n", *hue);
|
||||
*hue = HSV_HUE_MAX - 1;
|
||||
}
|
||||
if (*sat > HSV_SATURATION_MAX)
|
||||
{
|
||||
printf("[x]sat overflow, current: %u\n", *sat);
|
||||
*sat = HSV_SATURATION_MAX;
|
||||
}
|
||||
if (*value > HSV_VALUE_MAX)
|
||||
{
|
||||
printf("[x]value overflow, current: %u\n", *value);
|
||||
*value = HSV_VALUE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
// 将HSV颜色值转换为RGB颜色值
|
||||
uint32_t HSV_to_RGB(uint32_t *hue, uint32_t *sat, uint32_t *value)
|
||||
{
|
||||
|
||||
#ifdef HSV_VALID_CHECK
|
||||
#if HSV_VALID_CHECK == 0
|
||||
(is_HSV_valid(hue, sat, value));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t g; // 现在G是最高8位
|
||||
uint32_t r; // 然后是R
|
||||
uint32_t b; // B是最低8位
|
||||
|
||||
float H_prime = *hue / 60.0f;
|
||||
float S_prime = *sat / 100.0f;
|
||||
float V_prime = *value / 100.0f;
|
||||
|
||||
int i = (int)(H_prime);
|
||||
float f = H_prime - (float)i;
|
||||
float p = V_prime * (1 - S_prime);
|
||||
float q = V_prime * (1 - S_prime * f);
|
||||
float t = V_prime * (1 - S_prime * (1 - f));
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
r = (uint32_t)(V_prime * RGB_MAX);
|
||||
g = (uint32_t)(t * RGB_MAX);
|
||||
b = (uint32_t)(p * RGB_MAX);
|
||||
break;
|
||||
case 1:
|
||||
r = (uint32_t)(q * RGB_MAX);
|
||||
g = (uint32_t)(V_prime * RGB_MAX);
|
||||
b = (uint32_t)(p * RGB_MAX);
|
||||
break;
|
||||
case 2:
|
||||
r = (uint32_t)(p * RGB_MAX);
|
||||
g = (uint32_t)(V_prime * RGB_MAX);
|
||||
b = (uint32_t)(t * RGB_MAX);
|
||||
break;
|
||||
case 3:
|
||||
r = (uint32_t)(p * RGB_MAX);
|
||||
g = (uint32_t)(q * RGB_MAX);
|
||||
b = (uint32_t)(V_prime * RGB_MAX);
|
||||
break;
|
||||
case 4:
|
||||
r = (uint32_t)(t * RGB_MAX);
|
||||
g = (uint32_t)(p * RGB_MAX);
|
||||
b = (uint32_t)(V_prime * RGB_MAX);
|
||||
break;
|
||||
default: // for cases 5 and 6
|
||||
r = (uint32_t)(V_prime * RGB_MAX);
|
||||
g = (uint32_t)(p * RGB_MAX);
|
||||
b = (uint32_t)(q * RGB_MAX);
|
||||
break;
|
||||
}
|
||||
|
||||
return (g << 16) | (r << 8) | b;
|
||||
}
|
||||
|
||||
|
||||
// 逐步遍历RGB颜色空间,实现呼吸灯效果
|
||||
uint32_t cycleRGB(uint32_t color, GradientDirection *direction)
|
||||
{
|
||||
uint32_t g = (color >> 16) & 0xFF; // 现在G是最高8位
|
||||
uint32_t r = (color >> 8) & 0xFF; // 然后是R
|
||||
uint32_t b = color & 0xFF; // B是最低8位
|
||||
|
||||
// 根据方向调整颜色值
|
||||
if (*direction == INCREMENTING)
|
||||
{
|
||||
if (b < RGB_MAX)
|
||||
b++;
|
||||
else if (r < RGB_MAX)
|
||||
r++;
|
||||
else if (g < RGB_MAX)
|
||||
g++;
|
||||
else
|
||||
*direction = DECREMENTING; // 达到最亮,改变方向
|
||||
}
|
||||
else
|
||||
{ // DECREMENTING
|
||||
if (b > 0)
|
||||
b--;
|
||||
else if (r > 0)
|
||||
r--;
|
||||
else if (g > 0)
|
||||
g--;
|
||||
else
|
||||
{
|
||||
*direction = INCREMENTING; // 达到最暗,改变方向
|
||||
}
|
||||
}
|
||||
|
||||
return ((uint32_t)g << 16) | ((uint32_t)r << 8) | (uint32_t)b;
|
||||
}
|
||||
|
||||
// 通过HSV颜色空间循环改变色调(Hue)以实现颜色渐变效果
|
||||
uint32_t cycleHSV(uint32_t *hue)
|
||||
{
|
||||
// Assuming sat and value should be initialized to 100 for full color
|
||||
uint32_t sat = 100;
|
||||
uint32_t value = 100;
|
||||
if (*hue < 359)
|
||||
{
|
||||
(*hue) += 1;
|
||||
printf("hue is: 0x%06X\n", *hue);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*hue) = 0;
|
||||
printf("--------hue is: 0x%06X----------\n", *hue);
|
||||
}
|
||||
return(HSV_to_RGB(hue, &sat, &value));
|
||||
}
|
||||
|
||||
// 将单一颜色填充到整个RGB条中,并控制显示颜色的时间长度
|
||||
void fill_gradient(uint32_t *buf, uint32_t color)
|
||||
{
|
||||
// 遍历缓冲区的每个元素,将其设置为提供的颜色值
|
||||
for (int i = 0; i < NUM_RGBS; i++)
|
||||
{
|
||||
buf[i] = color;
|
||||
}
|
||||
// 将缓冲区中的颜色数组输出到RGB条上
|
||||
output_rgb_array(buf, NUM_RGBS);
|
||||
|
||||
// 调用延迟函数以控制颜色显示的时间,从而控制RGB条的闪烁速度
|
||||
delay_milliseconds(DELAY_TIME_RGB);
|
||||
}
|
||||
|
||||
// TODO:添加可合并选项
|
||||
// 驱动HSV颜色空间中的颜色循环,以实现连续的颜色渐变效果。
|
||||
void cycleHSV_driver()
|
||||
{
|
||||
|
||||
uint32_t buf[NUM_RGBS]; // 定义一个用于存储RGB值的缓冲区,大小由NUM_RGBS宏确定
|
||||
uint32_t current_hue = 0; // 从红色开始的当前色相值
|
||||
uint32_t current_sat = 100; // 当前饱和度值,初始化为满饱和度
|
||||
uint32_t current_val = 100; // 当前亮度值,初始化为最大亮度
|
||||
uint32_t current_color = HSV_to_RGB(¤t_hue, ¤t_sat, ¤t_val);
|
||||
par // 使用par关键词并发执行下面的代码块,这些线程默认在tile[1]上运行
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
// 用当前渐变颜色填充RGB数组,然后发送给rgb阵列
|
||||
fill_gradient(buf, current_color);
|
||||
|
||||
// 更改下一个颜色
|
||||
current_color = cycleHSV(¤t_hue);
|
||||
|
||||
// 打印出当前的GRB颜色值
|
||||
// printf("GRB color is: 0x%06X\n", current_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 持续更新RGB灯条的颜色
|
||||
void cycleRGB_driver()
|
||||
{
|
||||
|
||||
uint32_t buf[NUM_RGBS];
|
||||
uint32_t current_color = 0x000000; // Start from black
|
||||
GradientDirection direction = INCREMENTING; // 开始时设置为递增亮度
|
||||
|
||||
par // 使用par关键词并发执行下面的代码块,这些线程默认在tile[1]上运行
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
// 用当前渐变颜色填充RGB数组
|
||||
fill_gradient(buf, current_color);
|
||||
|
||||
// 更改下一个渐变的基色
|
||||
current_color = cycleRGB(current_color, &direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试 HSV_to_RGB,以及饱和处理
|
||||
void HSV_to_RGB_TEST()
|
||||
{
|
||||
uint32_t hue, sat, value; // HSV值
|
||||
uint32_t color; // RGB值
|
||||
|
||||
// 测试转换
|
||||
hue = 999;
|
||||
sat = 999;
|
||||
value = 999;
|
||||
color = HSV_to_RGB(&hue, &sat, &value);
|
||||
printf("GRB color is: 0x%06X\n", color);
|
||||
}
|
||||
Reference in New Issue
Block a user