forked from PAWPAW/lib_rgb
新增:随响度响应的RGB灯组
This commit is contained in:
31
examples/Makefile
Normal file
31
examples/Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
# This variable should contain a space separated list of all
|
||||
# the directories containing buildable applications (usually
|
||||
# prefixed with the app_ prefix)
|
||||
BUILD_SUBDIRS = ./app_rgb_cycle_breathing_example \
|
||||
./app_hsv_cycle_example \
|
||||
./app_volume_level_example \
|
||||
./app_test_fill_gradient_with_groups \
|
||||
|
||||
# This variable should contain a space separated list of all
|
||||
# the directories containing buildable plugins (usually
|
||||
# prefixed with the plugin_ prefix)
|
||||
PLUGIN_SUBDIRS =
|
||||
|
||||
# This variable should contain a space separated list of all
|
||||
# the directories containing applications with a 'test' make target
|
||||
TEST_SUBDIRS =
|
||||
|
||||
# Provided that the above variables are set you shouldn't need to modify
|
||||
# the targets below here.
|
||||
|
||||
%.all:
|
||||
cd $* && xmake BUILD_TEST_CONFIGS=1 all
|
||||
|
||||
%.clean:
|
||||
cd $* && xmake BUILD_TEST_CONFIGS=1 clean
|
||||
|
||||
all: $(foreach x, $(BUILD_SUBDIRS), $x.all)
|
||||
plugins: $(foreach x, $(PLUGIN_SUBDIRS), $x.all)
|
||||
clean: $(foreach x, $(BUILD_SUBDIRS), $x.clean)
|
||||
clean_plugins: $(foreach x, $(PLUGIN_SUBDIRS), $x.clean)
|
||||
test: $(foreach x, $(TEST_SUBDIRS), $x.test)
|
||||
Binary file not shown.
Binary file not shown.
21
examples/app_test_fill_gradient_with_groups/Makefile
Normal file
21
examples/app_test_fill_gradient_with_groups/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
# `TARGET` 变量决定了应用程序编译的目标系统。它可以引用源目录中的一个 XN 文件,或者是在编译时作为 `--target` 选项的一个有效参数。
|
||||
|
||||
TARGET = XCORE-AI-EXPLORER
|
||||
|
||||
# 编译选项
|
||||
# 构建应用程序时传递给 xcc 的参数
|
||||
# O2: xcc编译器优化等级2
|
||||
# report: 打开编译报告
|
||||
# g: 生成调试信息
|
||||
# fxscope: 使用 xSCOPE,对代码进行跟踪(默认使用xlink)
|
||||
BUILD_FLAGS = -O2 -g -DDEBUG_PRINT_ENABLE=1 -report -fxscope
|
||||
|
||||
USED_MODULES = lib_rgb
|
||||
|
||||
XCC_FLAGS = $(BUILD_FLAGS)
|
||||
|
||||
#=============================================================================
|
||||
# 下面部分的 Makefile 包含了用于编译 XMOS 应用程序的公共构建基础设施。你无需编辑此处以下的内容。
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
Binary file not shown.
24
examples/app_test_fill_gradient_with_groups/src/main.xc
Normal file
24
examples/app_test_fill_gradient_with_groups/src/main.xc
Normal file
@@ -0,0 +1,24 @@
|
||||
/** @brief 循环输出整个HSV色域
|
||||
* @author Vergil Wong
|
||||
* @date 2023-11-11
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include <stdio.h> // 包含基本的输入输出函数
|
||||
#include <platform.h> // 包含对封装的定义,引用以使用 on tile[] 语法
|
||||
#include "volume_level.h"
|
||||
#include "rgb_effect.h"
|
||||
|
||||
int main() // 定义主函数
|
||||
{
|
||||
par
|
||||
{
|
||||
on tile[1]:
|
||||
{
|
||||
test_fill_gradient_with_groups();
|
||||
}
|
||||
}
|
||||
return 0; // 返回0,表示程序正常结束
|
||||
}
|
||||
21
examples/app_volume_level_example/Makefile
Normal file
21
examples/app_volume_level_example/Makefile
Normal file
@@ -0,0 +1,21 @@
|
||||
# `TARGET` 变量决定了应用程序编译的目标系统。它可以引用源目录中的一个 XN 文件,或者是在编译时作为 `--target` 选项的一个有效参数。
|
||||
|
||||
TARGET = XCORE-AI-EXPLORER
|
||||
|
||||
# 编译选项
|
||||
# 构建应用程序时传递给 xcc 的参数
|
||||
# O2: xcc编译器优化等级2
|
||||
# report: 打开编译报告
|
||||
# g: 生成调试信息
|
||||
# fxscope: 使用 xSCOPE,对代码进行跟踪(默认使用xlink)
|
||||
BUILD_FLAGS = -O2 -g -DDEBUG_PRINT_ENABLE=1 -report -fxscope
|
||||
|
||||
USED_MODULES = lib_rgb
|
||||
|
||||
XCC_FLAGS = $(BUILD_FLAGS)
|
||||
|
||||
#=============================================================================
|
||||
# 下面部分的 Makefile 包含了用于编译 XMOS 应用程序的公共构建基础设施。你无需编辑此处以下的内容。
|
||||
|
||||
XMOS_MAKE_PATH ?= ../..
|
||||
include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
|
||||
Binary file not shown.
25
examples/app_volume_level_example/src/main.xc
Normal file
25
examples/app_volume_level_example/src/main.xc
Normal file
@@ -0,0 +1,25 @@
|
||||
/** @brief 循环输出整个HSV色域
|
||||
* @author Vergil Wong
|
||||
* @date 2023-11-11
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include <stdio.h> // 包含基本的输入输出函数
|
||||
#include <platform.h> // 包含对封装的定义,引用以使用 on tile[] 语法
|
||||
#include "volume_level.h"
|
||||
#include "rgb_effect.h"
|
||||
|
||||
int main() // 定义主函数
|
||||
{
|
||||
par
|
||||
{
|
||||
on tile[1]:
|
||||
{
|
||||
// volume_level_test();
|
||||
test_cycleHSV_with_vol_level();
|
||||
}
|
||||
}
|
||||
return 0; // 返回0,表示程序正常结束
|
||||
}
|
||||
4
lib_rgb/api/misc_utils.h
Normal file
4
lib_rgb/api/misc_utils.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void reverse_buf(uint32_t *start, size_t count);
|
||||
@@ -90,10 +90,11 @@ void cycleRGB_driver();
|
||||
*/
|
||||
void cycleHSV_driver();
|
||||
|
||||
|
||||
void test_cycleHSV_with_vol_level();
|
||||
/**
|
||||
* 用于测试HSV溢出
|
||||
*/
|
||||
void HSV_to_RGB_TEST();
|
||||
void test_HSV_to_RGB();
|
||||
|
||||
void test_fill_gradient_with_groups();
|
||||
#endif // RGB_EFFECT_H
|
||||
5
lib_rgb/api/volume_level.h
Normal file
5
lib_rgb/api/volume_level.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#include <stdint.h>
|
||||
|
||||
unsigned get_volume_level(int loudness_value);
|
||||
|
||||
void volume_level_test();
|
||||
13
lib_rgb/src/misc_utils.xc
Normal file
13
lib_rgb/src/misc_utils.xc
Normal file
@@ -0,0 +1,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void reverse_buf(uint32_t *start, size_t count) {
|
||||
uint32_t *end = start + count - 1;
|
||||
while (start < end) {
|
||||
uint32_t temp = *start;
|
||||
*start = *end;
|
||||
*end = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,17 @@
|
||||
#include "xclib.h"
|
||||
#include "timer.h"
|
||||
#include "rgb_driver.h"
|
||||
#include "volume_level.h"
|
||||
#include "misc_utils.h"
|
||||
|
||||
// RGB灯的数量
|
||||
#ifndef NUM_RGBS
|
||||
#define NUM_RGBS (12)
|
||||
#endif
|
||||
|
||||
#ifndef NUM_RGB_GROUPS
|
||||
#define NUM_RGB_GROUPS (2)
|
||||
#endif
|
||||
// 控制RGB亮度的最大值,不超过255
|
||||
#ifndef RGB_MAX
|
||||
#define RGB_MAX (20)
|
||||
@@ -72,6 +77,7 @@ void is_HSV_valid(uint32_t *hue, uint32_t *sat, uint32_t *value)
|
||||
}
|
||||
|
||||
// 将HSV颜色值转换为RGB颜色值
|
||||
// TODO:使用定点/S32以增加计算效率
|
||||
uint32_t HSV_to_RGB(uint32_t *hue, uint32_t *sat, uint32_t *value)
|
||||
{
|
||||
|
||||
@@ -178,24 +184,29 @@ uint32_t cycleHSV(uint32_t *hue)
|
||||
if (*hue < 359)
|
||||
{
|
||||
(*hue) += 1;
|
||||
printf("hue is: 0x%06X\n", *hue);
|
||||
// printf("hue is: 0x%06X\n", *hue);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*hue) = 0;
|
||||
printf("--------hue is: 0x%06X----------\n", *hue);
|
||||
// printf("--------hue is: 0x%06X----------\n", *hue);
|
||||
}
|
||||
return(HSV_to_RGB(hue, &sat, &value));
|
||||
}
|
||||
|
||||
// 将单一颜色填充到整个RGB条中,并控制显示颜色的时间长度
|
||||
void fill_gradient(uint32_t *buf, uint32_t color)
|
||||
void fill_gradient(uint32_t *buf, size_t num_filled_rgb, uint32_t color)
|
||||
{
|
||||
// 遍历缓冲区的每个元素,将其设置为提供的颜色值
|
||||
for (int i = 0; i < NUM_RGBS; i++)
|
||||
for (size_t i = 0; i < num_filled_rgb; i++)
|
||||
{
|
||||
buf[i] = color;
|
||||
}
|
||||
// 熄灭剩下的RGB灯
|
||||
for (size_t i = num_filled_rgb; i < NUM_RGBS; i++)
|
||||
{
|
||||
buf[i] = 0x000000;
|
||||
}
|
||||
// 将缓冲区中的颜色数组输出到RGB条上
|
||||
output_rgb_array(buf, NUM_RGBS);
|
||||
|
||||
@@ -203,6 +214,37 @@ void fill_gradient(uint32_t *buf, uint32_t color)
|
||||
delay_milliseconds(DELAY_TIME_RGB);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void fill_gradient_with_groups(uint32_t *buf, uint32_t *colors, size_t *num_filled_rgb, size_t num_groups)
|
||||
{
|
||||
size_t max_leds_per_group = NUM_RGBS / num_groups;
|
||||
|
||||
for (size_t group = 0; group < num_groups; group++) {
|
||||
// 填充每个组的LED
|
||||
uint32_t *group_buf = buf + group * max_leds_per_group;
|
||||
for (size_t i = 0; i < num_filled_rgb[group]; i++) {
|
||||
*(group_buf + i) = colors[group];
|
||||
}
|
||||
|
||||
// 熄灭该组剩余的LED
|
||||
for (size_t i = num_filled_rgb[group]; i < max_leds_per_group; i++) {
|
||||
*(group_buf + i) = 0x000000;
|
||||
}
|
||||
|
||||
// 如果组号为奇数,翻转该组对应的buffer元素
|
||||
if (group % 2 != 0) {
|
||||
reverse_buf(group_buf, max_leds_per_group);
|
||||
}
|
||||
}
|
||||
|
||||
// 将缓冲区输出到RGB条
|
||||
output_rgb_array(buf, NUM_RGBS);
|
||||
|
||||
// 延迟以控制显示持续时间
|
||||
delay_milliseconds(DELAY_TIME_RGB);
|
||||
}
|
||||
|
||||
// TODO:添加可合并选项
|
||||
// 驱动HSV颜色空间中的颜色循环,以实现连续的颜色渐变效果。
|
||||
void cycleHSV_driver()
|
||||
@@ -218,7 +260,7 @@ void cycleHSV_driver()
|
||||
while (1)
|
||||
{
|
||||
// 用当前渐变颜色填充RGB数组,然后发送给rgb阵列
|
||||
fill_gradient(buf, current_color);
|
||||
fill_gradient(buf, NUM_RGBS, current_color);
|
||||
|
||||
// 更改下一个颜色
|
||||
current_color = cycleHSV(¤t_hue);
|
||||
@@ -242,7 +284,7 @@ void cycleRGB_driver()
|
||||
while (1)
|
||||
{
|
||||
// 用当前渐变颜色填充RGB数组
|
||||
fill_gradient(buf, current_color);
|
||||
fill_gradient(buf, NUM_RGBS, current_color);
|
||||
|
||||
// 更改下一个渐变的基色
|
||||
current_color = cycleRGB(current_color, &direction);
|
||||
@@ -250,8 +292,43 @@ void cycleRGB_driver()
|
||||
}
|
||||
}
|
||||
|
||||
void test_cycleHSV_with_vol_level()
|
||||
{
|
||||
|
||||
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[NUM_RGB_GROUPS] = {0x000000, 0x000000};
|
||||
|
||||
srand(1); // 初始化随机数种子
|
||||
size_t random_levels[NUM_RGB_GROUPS];
|
||||
par // 使用par关键词并发执行下面的代码块,这些线程默认在tile[1]上运行
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_RGB_GROUPS; i++)
|
||||
{
|
||||
*(random_levels + i) = get_volume_level(rand() % 101 - 100);
|
||||
}
|
||||
|
||||
// 用当前渐变颜色填充RGB数组,然后发送给rgb阵列
|
||||
fill_gradient_with_groups(buf, current_color, random_levels, NUM_RGB_GROUPS);
|
||||
|
||||
// 更改下一个颜色
|
||||
for (size_t i = 0; i < NUM_RGB_GROUPS; i++)
|
||||
{
|
||||
*(current_color + i) = cycleHSV(¤t_hue);
|
||||
}
|
||||
|
||||
// 打印出当前的GRB颜色值
|
||||
// printf("GRB color is: 0x%06X\n", current_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试 HSV_to_RGB,以及饱和处理
|
||||
void HSV_to_RGB_TEST()
|
||||
void test_HSV_to_RGB()
|
||||
{
|
||||
uint32_t hue, sat, value; // HSV值
|
||||
uint32_t color; // RGB值
|
||||
@@ -263,3 +340,29 @@ void HSV_to_RGB_TEST()
|
||||
color = HSV_to_RGB(&hue, &sat, &value);
|
||||
printf("GRB color is: 0x%06X\n", color);
|
||||
}
|
||||
|
||||
void test_fill_gradient_with_groups() {
|
||||
uint32_t buffer[NUM_RGBS];
|
||||
uint32_t colors[] = {0xFF0000, 0x00FF00}; // 红,绿
|
||||
size_t num_filled_rgb[] = {2, 3}; // 每组填充数量
|
||||
size_t num_groups = sizeof(colors) / sizeof(colors[0]);
|
||||
int success = 1; // 使用int代替bool,1代表true,0代表false
|
||||
|
||||
fill_gradient_with_groups(buffer, colors, num_filled_rgb, num_groups);
|
||||
|
||||
// 验证
|
||||
for (size_t i = 0; i < NUM_RGBS; i++) {
|
||||
size_t group = i / (NUM_RGBS / num_groups);
|
||||
size_t group_led_start = group * (NUM_RGBS / num_groups);
|
||||
uint32_t expected_color = (i < group_led_start + num_filled_rgb[group]) ? colors[group] : 0x000000;
|
||||
if (buffer[i] != expected_color) {
|
||||
success = 0; // 设置为false
|
||||
printf("Test failed at LED %zu: expected 0x%06X, got 0x%06X\n", i, expected_color, buffer[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
printf("Test passed: All LEDs are correctly set.\n");
|
||||
}
|
||||
}
|
||||
|
||||
47
lib_rgb/src/volume_level.xc
Normal file
47
lib_rgb/src/volume_level.xc
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define VOL_LEVEL_TABLE \
|
||||
{ 0 , 6 }, \
|
||||
{ -3 , 5 }, \
|
||||
{ -9 , 4 }, \
|
||||
{ -14, 3 }, \
|
||||
{ -30, 2 }, \
|
||||
{ -62, 1 },
|
||||
|
||||
// 定义音量等级结构体
|
||||
typedef struct {
|
||||
int vol; // 响度值
|
||||
unsigned level; // 音量等级
|
||||
} vol_level_table_t;
|
||||
|
||||
const vol_level_table_t vol_level_table[] = {VOL_LEVEL_TABLE};
|
||||
#define VOLUME_LEVELS_COUNT (sizeof(vol_level_table) / sizeof(vol_level_table[0]))
|
||||
|
||||
unsigned get_volume_level(int loudness_value) {
|
||||
// 默认返回音量等级0
|
||||
int level = 0;
|
||||
|
||||
// 从最大响度值开始向下找
|
||||
for (int i = 0; i < VOLUME_LEVELS_COUNT; ++i) {
|
||||
if (loudness_value >= vol_level_table[i].vol) {
|
||||
level = vol_level_table[i].level;
|
||||
break; // 找到后立即退出循环
|
||||
}
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
void volume_level_test() {
|
||||
// 测试不同的响度值
|
||||
uint32_t test_loudness_values[] = {1, 0, -2, -5, -8, -20, -30, -40, -60, -62, -70, };
|
||||
int num_tests = sizeof(test_loudness_values) / sizeof(test_loudness_values[0]);
|
||||
|
||||
for (int i = 0; i < num_tests; ++i) {
|
||||
printf("Loudness: %d dB, Volume Level: %d\n",
|
||||
test_loudness_values[i],
|
||||
get_volume_level(test_loudness_values[i]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user