Files
menu/src/param/menu_param.c
2025-12-18 21:24:20 +08:00

302 lines
7.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file menu_param.c
* @brief 菜单参数管理模块(可裁剪功能)
*/
#include "menu_core.h"
#include "menu_data.h"
#if MENU_CONFIG_ENABLE_PARAM
/************************** 全局变量定义 **************************/
MenuParam s_menu_params[MENU_CONFIG_MAX_PARAMS];
/**
* @brief 查找参数通过参数ID
* @param param_id 参数ID
* @return 参数指针NULL表示未找到
*/
static MenuParam* menu_param_find(uint16_t param_id)
{
for (uint16_t i = 0; i < MENU_CONFIG_MAX_PARAMS; i++)
{
if (s_menu_params[i].is_registered && s_menu_params[i].id == param_id)
{
return &s_menu_params[i];
}
}
return NULL;
}
/**
* @brief 将浮点值转换为参数内部值(根据类型)
* @param param 参数指针
* @param value 浮点值
* @return 转换后的内部值(通过指针返回)
*/
static void menu_param_float_to_internal(MenuParam* param, float value)
{
MENU_ASSERT(param != NULL);
// 确保值在范围内
if (value < param->min_val)
{
value = param->min_val;
}
else if (value > param->max_val)
{
value = param->max_val;
}
// 应用缩放因子
value /= param->scale;
// 根据参数类型转换
switch (param->type)
{
case MENU_PARAM_TYPE_INT8:
param->value.i8 = (int8_t)value;
break;
case MENU_PARAM_TYPE_UINT8:
param->value.u8 = (uint8_t)value;
break;
case MENU_PARAM_TYPE_INT16:
param->value.i16 = (int16_t)value;
break;
case MENU_PARAM_TYPE_UINT16:
param->value.u16 = (uint16_t)value;
break;
case MENU_PARAM_TYPE_INT32:
param->value.i32 = (int32_t)value;
break;
case MENU_PARAM_TYPE_UINT32:
param->value.u32 = (uint32_t)value;
break;
case MENU_PARAM_TYPE_FLOAT:
param->value.f = value;
break;
default:
break;
}
}
/**
* @brief 将参数内部值转换为浮点值(根据类型)
* @param param 参数指针
* @return 浮点值
*/
static float menu_param_internal_to_float(const MenuParam* param)
{
MENU_ASSERT(param != NULL);
float value = 0.0f;
// 根据参数类型转换
switch (param->type)
{
case MENU_PARAM_TYPE_INT8:
value = (float)param->value.i8;
break;
case MENU_PARAM_TYPE_UINT8:
value = (float)param->value.u8;
break;
case MENU_PARAM_TYPE_INT16:
value = (float)param->value.i16;
break;
case MENU_PARAM_TYPE_UINT16:
value = (float)param->value.u16;
break;
case MENU_PARAM_TYPE_INT32:
value = (float)param->value.i32;
break;
case MENU_PARAM_TYPE_UINT32:
value = (float)param->value.u32;
break;
case MENU_PARAM_TYPE_FLOAT:
value = param->value.f;
break;
default:
break;
}
// 应用缩放因子
return value * param->scale;
}
/**
* @brief 注册参数到菜单节点(参数管理功能)
* @param node_id 菜单节点ID参数与菜单绑定
* @param param_id 参数ID唯一
* @param type 参数类型
* @param min_val 最小值(浮点型,内部自动转换)
* @param max_val 最大值(浮点型,内部自动转换)
* @param default_val 默认值(浮点型,内部自动转换)
* @param scale 缩放因子如0.1表示保留1位小数
* @return 错误码
*/
MenuErrCode menu_param_register(MenuNodeId node_id, uint16_t param_id, MenuParamType type, float min_val, float max_val, float default_val, float scale)
{
if (scale <= 0.0f)
{
return MENU_ERR_INVALID_PARAM;
}
// 查找菜单节点
MenuNode* node = menu_core_find_node(node_id);
if (node == NULL)
{
return MENU_ERR_NODE_NOT_FOUND;
}
// 检查参数ID是否已存在
if (menu_param_find(param_id) != NULL)
{
return MENU_ERR_INVALID_PARAM;
}
// 查找空闲参数位置
MenuParam* param = NULL;
for (uint16_t i = 0; i < MENU_CONFIG_MAX_PARAMS; i++)
{
if (!s_menu_params[i].is_registered)
{
param = &s_menu_params[i];
break;
}
}
if (param == NULL)
{
return MENU_ERR_OUT_OF_MEMORY;
}
// 初始化参数
MENU_MEM_SET_ZERO(param, sizeof(MenuParam));
param->id = param_id;
param->type = type;
param->min_val = min_val;
param->max_val = max_val;
param->scale = scale;
param->is_registered = true;
// 设置默认值
menu_param_float_to_internal(param, default_val);
// 保存默认值
menu_param_float_to_internal((MenuParam*)&param->default_val, default_val);
// 将参数与菜单节点绑定
node->param_id = param_id;
MENU_DEBUG("Param registered: ID=%d, Type=%d, Range=[%0.2f, %0.2f], Default=%0.2f, Scale=%0.2f",
param_id, type, min_val, max_val, default_val, scale);
return MENU_OK;
}
/**
* @brief 设置参数值
* @param param_id 参数ID
* @param value 新值(浮点型,内部自动转换)
* @return 错误码
*/
MenuErrCode menu_param_set_value(uint16_t param_id, float value)
{
// 查找参数
MenuParam* param = menu_param_find(param_id);
if (param == NULL)
{
return MENU_ERR_NODE_NOT_FOUND;
}
// 设置新值
menu_param_float_to_internal(param, value);
MENU_DEBUG("Param set: ID=%d, Value=%0.2f (Internal: %0.2f)",
param_id, value, menu_param_internal_to_float(param));
return MENU_OK;
}
/**
* @brief 获取参数值
* @param param_id 参数ID
* @param value 输出参数,当前值(浮点型)
* @return 错误码
*/
MenuErrCode menu_param_get_value(uint16_t param_id, float* value)
{
if (value == NULL)
{
return MENU_ERR_INVALID_PARAM;
}
// 查找参数
MenuParam* param = menu_param_find(param_id);
if (param == NULL)
{
return MENU_ERR_NODE_NOT_FOUND;
}
// 获取当前值
*value = menu_param_internal_to_float(param);
MENU_DEBUG("Param get: ID=%d, Value=%0.2f", param_id, *value);
return MENU_OK;
}
/**
* @brief 将参数恢复为默认值
* @param param_id 参数ID
* @return 错误码
*/
MenuErrCode menu_param_restore_default(uint16_t param_id)
{
// 查找参数
MenuParam* param = menu_param_find(param_id);
if (param == NULL)
{
return MENU_ERR_NODE_NOT_FOUND;
}
// 恢复默认值
float default_val = menu_param_internal_to_float((const MenuParam*)&param->default_val);
return menu_param_set_value(param_id, default_val);
}
/**
* @brief 增加参数值(用于菜单上下键调整)
* @param param_id 参数ID
* @param step 步长(浮点型)
* @return 错误码
*/
MenuErrCode menu_param_increase(uint16_t param_id, float step)
{
float current_val = 0.0f;
MenuErrCode err = menu_param_get_value(param_id, &current_val);
if (err != MENU_OK)
{
return err;
}
return menu_param_set_value(param_id, current_val + step);
}
/**
* @brief 减少参数值(用于菜单上下键调整)
* @param param_id 参数ID
* @param step 步长(浮点型)
* @return 错误码
*/
MenuErrCode menu_param_decrease(uint16_t param_id, float step)
{
float current_val = 0.0f;
MenuErrCode err = menu_param_get_value(param_id, &current_val);
if (err != MENU_OK)
{
return err;
}
return menu_param_set_value(param_id, current_val - step);
}
#endif // MENU_CONFIG_ENABLE_PARAM