/** * @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*)¶m->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*)¶m->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, ¤t_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, ¤t_val); if (err != MENU_OK) { return err; } return menu_param_set_value(param_id, current_val - step); } #endif // MENU_CONFIG_ENABLE_PARAM