diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/audiohw.xc b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/audiohw.xc index 2587dd5..f6610ae 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/audiohw.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/audiohw.xc @@ -21,13 +21,37 @@ #include "xua_hid_report.h" #include "nau88c21.h" #include "tile1_clk.h" +#include "dfu_upgrade.h" #if MQA_EN #include "MQA_XMOS.h" #endif extern "C" { #include "sw_pll.h" - #include "dfu_upgrade.h" + extern unsigned g_sync_t0_to_t1_cmd; + extern unsigned g_sync_t0_to_t1_data; + /* 改动原因:tile0/tile1 内存不共享,sync 第二数据字用于上电经 0x03 传递 FPS 三模块使能 */ + extern unsigned g_sync_t0_to_t1_data2; + extern unsigned g_fps_game_select; + extern unsigned g_fps_level_select; + extern unsigned g_fps_drc_enable; + extern unsigned g_fps_sub_enable; + extern unsigned g_fps_eq_enable; + extern unsigned g_fps_drc_mode; +#if XMOS_FPS_EN + #include "fps_eq_sync.h" + /* 改动原因:HID 0xBF/0xB5/0xBD/0xB7/0xB9经tile同步后调用FPS库接口,不在DSP任务内轮询 */ + void fps_apply_game_level_select(void); + void fps_apply_module_enable(void); + void fps_apply_drc_mode(void); + void fps_apply_eq_mode(void); + void fps_apply_eq_band_gain(unsigned band, int16_t gain); + void fps_eq_boot_publish_to_tile1(void); + void fps_drc_boot_sync_to_tile1(void); + void fps_boot_load_from_flash(void); + void sync_t0_promote_pending_to_tile1(void); +#endif + } #define TIMER_PERIOD 2000000 @@ -529,8 +553,52 @@ static void codec_init_on_i2c(client interface i2c_master_if i2c) void save_value(unsigned char * unsafe path, unsigned char value); unsigned char load_value(unsigned char * unsafe path); #define C1_MODE_INFO_PATH "c1_mode" + +#if XMOS_FPS_EN +/* 改动原因:将 g_sync_t0_to_t1_cmd 经 c_app_sync 发到 tile1;供定时器与上电 flush 复用 */ +static int tile0_send_one_sync_to_tile1(chanend c_app_sync) +{ + unsigned sync_cmd = 0; + + GET_SHARED_GLOBAL(sync_cmd, g_sync_t0_to_t1_cmd); + if (sync_cmd == 0) { + return 0; + } + + { + unsigned sync_data = 0; + unsigned sync_data2 = 0; + GET_SHARED_GLOBAL(sync_data, g_sync_t0_to_t1_data); + GET_SHARED_GLOBAL(sync_data2, g_sync_t0_to_t1_data2); + + c_app_sync <: (unsigned)(0x80 | sync_cmd); + c_app_sync <: sync_data; + c_app_sync <: sync_data2; + + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, 0); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, 0); + sync_t0_promote_pending_to_tile1(); + debug_printf("tile0: Sent sync 0x%02X to tile1, data=%u data2=%u\n", + sync_cmd, sync_data, sync_data2); + } + return 1; +} + +/* 改动原因:上电 fps_boot_load 会排队 0x03+0x0C+0x09+五包0x0B,须立即 drain 而非等 20ms 定时器 */ +static void tile0_flush_sync_queue_to_tile1(chanend c_app_sync) +{ + unsigned sync_cmd = 0; + + do { + while (tile0_send_one_sync_to_tile1(c_app_sync) != 0) {} + sync_t0_promote_pending_to_tile1(); + GET_SHARED_GLOBAL(sync_cmd, g_sync_t0_to_t1_cmd); + } while (sync_cmd != 0); +} +#endif + /* 改动原因:c_dfu 仅接收 FIRMWARE_UPGRADE_START,在此线程执行 handle_firmware_upgrade_start */ -void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, client interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_erase, streaming chanend c_dfu) +void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu, chanend c_app_sync) { unsigned cmd; int value; @@ -683,6 +751,14 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli old_adc_vol = boot_effective_adc_vol; } +#if XMOS_FPS_EN + /* 改动原因:C1 无 UART/MCU,不经过 c_uart_sync;上电直接在 tile0 从 Flash 恢复 FPS 并 sync 到 tile1 */ + /* 改动原因:tile1 app_control_slave 有约 100ms 延时,此处再等 50ms 确保 c_sync 已进 select */ + delay_milliseconds(50); + fps_boot_load_from_flash(); + tile0_flush_sync_queue_to_tile1(c_app_sync); +#endif + while(1) { select @@ -1091,6 +1167,10 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli #if ((HID_CONTROLS == 1) && (EQ_EN == 1)) + // 改动原因:检测tile0到tile1的同步命令,如果有命令则通过channel发送到tile1 +#if XMOS_FPS_EN + (void)tile0_send_one_sync_to_tile1(c_app_sync); +#endif // 改动原因:检测增益模式变化请求,当g_request_gain_mode != -1且与当前模式不同时应用 { unsigned request_gain_mode, gain_mode; @@ -1187,7 +1267,8 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli g_last_mute_switch = current_mute; } - // 改动原因:规格DNR无指示灯,按键长按切换后通过HID 0xB5主动上报APP(与0xB4监听开关上报方式一致)。 + // 改动原因:规格DNR无指示灯,按键长按切换后通过HID主动上报APP + // 改动原因:XMOS_FPS_EN 时 0xB5 为 SET_FPS_MODULE_ENABLE,DNR 上报改用 0xC5 { unsigned current_dnr; GET_SHARED_GLOBAL(current_dnr, g_dnr_enable); @@ -1197,12 +1278,16 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli { unsigned char * unsafe reportPtr = g_hid_pass_data; reportPtr[0] = 0x77; +#if XMOS_FPS_EN + reportPtr[1] = 0xC5; // GET_DNR_ENABLE(FPS 构建下与 0xB5 区分) +#else reportPtr[1] = 0xB5; // GET_DNR_ENABLE +#endif reportPtr[2] = (unsigned char)current_dnr; for (int i = 3; i < 63; i++) reportPtr[i] = 0x00; hidSetChangePending(0x1); } - debug_printf("DNR enable changed: %d -> %d, HID 0xB5 report prepared\n", g_last_dnr_enable, current_dnr); + debug_printf("DNR enable changed: %d -> %d, HID report prepared\n", g_last_dnr_enable, current_dnr); } g_last_dnr_enable = current_dnr; } @@ -1570,6 +1655,11 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli } } +// 改动原因:用于tile0到tile1同步命令的共享变量 +unsigned g_sync_t0_to_t1_cmd = 0; // 0=无命令,0x01=SET_GAME_MODE +unsigned g_sync_t0_to_t1_data = 0; // 命令数据 +unsigned g_sync_t0_to_t1_data2 = 0; // 改动原因:sync 第二数据字,上电 0x03 携带 FPS 模块使能 + extern void SetKeyFlag(unsigned x); void flag_handler() { @@ -1588,14 +1678,14 @@ void flag_handler() } -void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_erase, streaming chanend c_dfu) +void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu, chanend c_app_sync) { i2c_master_if i2c[1]; par { i2c_master(i2c, 1, p_scl, p_sda, 100); - AudioHwRemote2(c, i2c[0], i_c1_led_ctrl, c_erase, c_dfu); + AudioHwRemote2(c, i2c[0], i_c1_led_ctrl, c_dfu, c_app_sync); } } @@ -1985,7 +2075,7 @@ static inline void apply_c1_panel_leds(unsigned mode_led_color_idx, unsigned mic p_mode_led_blue <: (mode_blue ? 0 : 1); } -void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl) +void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_sync) { // 改动原因:tile1 先于 tile0 运行,上电先把硬件灯全灯且不调用 apply,避免用占位 mic/mode 组合误亮;shadow 置为全灯灯电平便于首包 set_* 时 apply 与端口一致。 unsigned led_shadow = 0xF; @@ -2022,6 +2112,154 @@ void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl) mic_mute_switch = (mute_state != 0) ? 1 : 0; apply_c1_panel_leds(mode_led_color_idx, mic_mute_switch, led_shadow); break; + // 改动原因:接收从tile0通过channel发送的同步命令(命令码 >= 0x80表示tile0到tile1的命令) + case c_sync :> unsigned sync_cmd: + if ((sync_cmd & 0x80) != 0) { + // 这是从tile0发送的命令 + unsigned sync_data1, sync_data2; + c_sync :> sync_data1; + c_sync :> sync_data2; + + unsigned actual_cmd = sync_cmd & 0x7F; // 去掉0x80标志 + + if (actual_cmd == 0x01) { // SYNC_CMD_T0_TO_T1_SET_GAME_MODE + debug_printf("tile1: Received SET_GAME_MODE command from tile0 via channel, game_mode=%d\n", sync_data1); + // 改动原因:调用UART 0x5A命令处理函数,将命令透传给MCU +#if EQ_EN + process_uart_set_game_mode((uint8_t)sync_data1); +#endif + } + else if (actual_cmd == 0x02) { // SYNC_CMD_T0_TO_T1_SET_UAC_MODE + debug_printf("tile1: Received SET_UAC_MODE command from tile0 via channel, uac_mode=%d\n", sync_data1); + // 改动原因:调用UART 0x51命令处理函数,将命令透传给MCU +#if EQ_EN + process_uart_set_uac_mode((uint8_t)sync_data1); +#endif + } + else if (actual_cmd == 0x03) { // SYNC_CMD_T0_TO_T1_SET_FPS_XMOS_GAME_SELECT + // 改动原因:sync_data1中同时打包了game和level,低8位为game,高8位为level + unsigned game_select = (sync_data1 & 0xFF); + unsigned level_select = ((sync_data1 >> 8) & 0xFF); + if (game_select > 2) { + game_select = 0; + } + // 改动原因:tile1 与 tile0/协议一致,level 有效 0-4;无效时回默认 2(与 0xBF 一致) + if (level_select > 4) { + level_select = 2; + } + debug_printf("tile1: Received SET_FPS_XMOS_GAME_SELECT command from tile0 via channel, game=%u level=%u\n", + game_select, level_select); + // 改动原因:更新全局变量后由fps_apply_game_level_select调用fps_xmos_xc_game_select,DSP任务内不再轮询 + SET_SHARED_GLOBAL(g_fps_game_select, game_select); + SET_SHARED_GLOBAL(g_fps_level_select, level_select); +#if XMOS_FPS_EN + fps_apply_game_level_select(); + /* 改动原因:tile0/tile1 内存不共享,上电使能经 sync data2(bit31) 下发后再 apply */ + if ((sync_data2 & (1u << 31)) != 0) { + unsigned drc_enable = (sync_data2 & 0xFF); + unsigned fps_sub_enable = ((sync_data2 >> 8) & 0xFF); + unsigned eq_enable = ((sync_data2 >> 16) & 0xFF); + if (drc_enable > 1) { drc_enable = 0; } + if (fps_sub_enable > 1) { fps_sub_enable = 1; } + if (eq_enable > 1) { eq_enable = 0; } + debug_printf("tile1: boot FPS module enable from sync drc=%u fps=%u eq=%u\n", + drc_enable, fps_sub_enable, eq_enable); + SET_SHARED_GLOBAL(g_fps_drc_enable, drc_enable); + SET_SHARED_GLOBAL(g_fps_sub_enable, fps_sub_enable); + SET_SHARED_GLOBAL(g_fps_eq_enable, eq_enable); + } + fps_apply_module_enable(); + /* 改动原因:fps_eq 由后续排队 sync 0x09+0x0B 应用,此处不读 tile1 默认 pack */ +#endif + } + else if (actual_cmd == 0x09) { // SYNC_CMD_T0_TO_T1_SET_FPS_EQ_MODE + unsigned mode = (sync_data1 & 0xFF); + if (mode >= 5) { + mode = 0; + } + debug_printf("tile1: SET_FPS_EQ_MODE %u\n", mode); + SET_SHARED_GLOBAL(g_fps_eq_mode, mode); + /* 改动原因:增益由紧随的 0x0B 包同步,末包 apply 时再 fps_apply_eq_mode */ + } + else if (actual_cmd == 0x0B) { // SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK + unsigned pack_idx = (sync_data1 & 0xFF); + unsigned apply_eq = ((sync_data1 >> 8) & 0xFF); + int32_t pack_val = (int32_t)sync_data2; + + if (pack_idx < 5) { + debug_printf("tile1: SET_FPS_EQ_PACK idx=%u apply=%u\n", pack_idx, apply_eq); + switch (pack_idx) { + case 0: SET_SHARED_GLOBAL(g_fps_eq_pack0, pack_val); break; + case 1: SET_SHARED_GLOBAL(g_fps_eq_pack1, pack_val); break; + case 2: SET_SHARED_GLOBAL(g_fps_eq_pack2, pack_val); break; + case 3: SET_SHARED_GLOBAL(g_fps_eq_pack3, pack_val); break; + case 4: SET_SHARED_GLOBAL(g_fps_eq_pack4, pack_val); break; + default: break; + } +#if XMOS_FPS_EN + if (apply_eq != 0) { + fps_apply_eq_mode(); + } +#endif + } + } + else if (actual_cmd == 0x0A) { // SYNC_CMD_T0_TO_T1_SET_FPS_EQ_BAND_GAIN + unsigned band = (sync_data1 & 0xFF); + int16_t gain = (int16_t)((sync_data1 >> 8) & 0xFFFF); + debug_printf("tile1: SET_FPS_EQ_BAND band=%u gain=%d\n", band, (int)gain); +#if XMOS_FPS_EN + fps_apply_eq_band_gain(band, gain); +#endif + } + else if (actual_cmd == 0x08) { // SYNC_CMD_T0_TO_T1_SET_FPS_MODULE_ENABLE + unsigned drc_enable = (sync_data1 & 0xFF); + unsigned fps_sub_enable = ((sync_data1 >> 8) & 0xFF); + unsigned eq_enable = ((sync_data1 >> 16) & 0xFF); + /* 改动原因:sync 包无效字节时与上电默认一致:DRC/fps_eq 关,FPS 开 */ + if (drc_enable > 1) { drc_enable = 0; } + if (fps_sub_enable > 1) { fps_sub_enable = 1; } + if (eq_enable > 1) { eq_enable = 0; } + debug_printf("tile1: SET_FPS_MODULE_ENABLE drc=%u fps=%u eq=%u\n", + drc_enable, fps_sub_enable, eq_enable); + SET_SHARED_GLOBAL(g_fps_drc_enable, drc_enable); + SET_SHARED_GLOBAL(g_fps_sub_enable, fps_sub_enable); + SET_SHARED_GLOBAL(g_fps_eq_enable, eq_enable); +#if XMOS_FPS_EN + fps_apply_module_enable(); +#endif + } + else if (actual_cmd == 0x0C) { // SYNC_CMD_T0_TO_T1_SET_FPS_DRC_MODE + unsigned drc_mode = (sync_data1 & 0xFF); + /* 改动原因:mode仅0=low、1=high,无效时回默认0 */ + if (drc_mode > 1) { + drc_mode = 0; + } + debug_printf("tile1: SET_FPS_DRC_MODE mode=%u\n", drc_mode); + SET_SHARED_GLOBAL(g_fps_drc_mode, drc_mode); +#if XMOS_FPS_EN + fps_apply_drc_mode(); +#endif + } + else if (actual_cmd == 0x04) { // SYNC_CMD_T0_TO_T1_SET_INPUT_SOURCE + debug_printf("tile1: Received SET_INPUT_SOURCE command from tile0 via channel, input_source=%d\n", sync_data1); +#if EQ_EN + process_uart_set_input_source((uint8_t)sync_data1); +#endif + } + else if (actual_cmd == 0x05) { // SYNC_CMD_T0_TO_T1_SET_MUTE_SWITCH + debug_printf("tile1: Received SET_MUTE_SWITCH command from tile0 via channel, mute=%d\n", sync_data1); +#if EQ_EN + process_uart_set_mute_switch((uint8_t)sync_data1); +#endif + } + else if (actual_cmd == 0x07) { // SYNC_CMD_T0_TO_T1_SET_LISTEN_SWITCH + debug_printf("tile1: Received SET_LISTEN_SWITCH command from tile0 via channel, listen=%d\n", sync_data1); +#if EQ_EN + process_uart_set_listen_switch((uint8_t)sync_data1); +#endif + } + } + break; } } } diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/br_wrapper.c b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/br_wrapper.c index e1d9b5f..e4444d4 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/br_wrapper.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/br_wrapper.c @@ -100,59 +100,4 @@ void dsp_main (chanend_t c_data , chanend_t cc_br_eof) { #endif } -extern uint8_t opt_key_read(uint8_t key[], unsigned offset); extern unsigned dnr_init_flag; -void validate_algo(chanend_t c_validate) -{ -#if BR_ALGO - uint8_t uid[20] = {0}; - char hex_string[41] = {0}; - while (!dnr_init_flag) { - delay_milliseconds(1); - } - opt_key_read(uid, 2); - delay_milliseconds(10); - for (int i = 0; i < 20; i++) { - sprintf(hex_string + i * 2, "%02x", uid[i]); - } - hex_string[40] = '\0'; - flash_cmd_init(); - int res = br_validate(c_validate, hex_string); - flash_cmd_deinit(); - debug_printf("Validate status: %d\n", res); // check validate status -#endif -} - -extern void set_core_high_priority_on(void); -void br_dsp_proc_task(chanend_t c_validate, chanend_t cc_br_eof) -{ -#if BR_ALGO - set_core_high_priority_on(); - int channel_flag = 4; - int is_br_on = 1; - - int cnt = 0; - - br_init(c_validate); - int validate = br_get_validate_status(); - debug_printf("After Validate status: %d\n", validate); // check validate status - - - while (1) - { - int tmp; - int cur_pos; - chan_in_buf_word (cc_br_eof, &tmp, 1); - cur_pos = pos == 0 ? 1 : 0; - - if (channel_flag <= 2) { - is_br_on = 0; - } - else { - is_br_on = 1; - } - br_apply(dsp_br_input_buf[cur_pos], dsp_br_out_buf[cur_pos], is_br_on); - channel_flag = br_get_channel_flag(); - } -#endif -} diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dfu_upgrade.c b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dfu_upgrade.c index 127cb8e..fddb27e 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dfu_upgrade.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dfu_upgrade.c @@ -590,6 +590,17 @@ unsigned char handle_firmware_upgrade_erase(uint8_t data[], uint16_t len) return STATUS_SUCCESS; } +// 改动原因:HID 0xAE 设备重启;补全缺失的 handle_device_reboot,调用 eq.c 中已有的 device_reboot() 避免链接错误 +unsigned char handle_device_reboot(uint8_t data[], uint16_t len) +{ + (void)data; + (void)len; + debug_printf("Firmware upgrade DEVICE_REBOOT (0xAE)\n"); + device_reboot(); + while (1); + return STATUS_SUCCESS; +} + // 固件升级主处理函数 // 改动原因:处理所有HID固件升级命令,分发到相应的处理函数 // 参数: diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dnr/libxmos_fps.a b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dnr/libxmos_fps.a index 41563b4..fad91df 100644 Binary files a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dnr/libxmos_fps.a and b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/dnr/libxmos_fps.a differ diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.c b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.c index 1c22f7d..6b8d6a5 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.c @@ -8,6 +8,7 @@ #include // 添加offsetof宏支持 #include // 添加数学函数支持 #include +#include #include "version.h" #if 0 // DEBUG_PRINT_ENABLE @@ -23,6 +24,15 @@ extern unsigned g_3d_fps; #if C1_DFS_EN extern unsigned g_tile1_lp_div; /* tile1_clk.xc: tile[1] low-power divider (动态降频) */ #endif +/* 改动原因:XMOS_FPS_EN 时 0xB5/0xB6/0xB7 归 FPS HID 协议;DNR 查询/上报改 0xC5,DFS HID 与 FPS 互斥 */ +#if XMOS_FPS_EN +#define C1_HID_GET_DNR_ENABLE_OPCODE 0xC5 +#else +#define C1_HID_GET_DNR_ENABLE_OPCODE 0xB5 +#endif +#if HID_DFU_EN +#include "dfu_upgrade.h" +#endif #if DEBUG_MEMORY_LOG_ENABLED unsigned g_log_switch = 1; #else @@ -30,17 +40,14 @@ unsigned g_log_switch = 0; #endif -// 常量定义 -#define EQ_DISABLED_MODE 10 // 禁用EQ的模式编号 - #include "xmath/filter.h" #include "eq.h" #include #include #include -#if 1// !UAC1 #include "eq_params_44100.h" +extern unsigned g_3d_fps; // 改动原因:进一步优化EQ参数存储策略,所有采样率共用44100Hz数组 // 参数在所有采样率下是相同的,只有系数需要根据采样率动态计算 // 切换采样率时,直接使用44100Hz数组的参数,重新计算系数即可 @@ -48,7 +55,7 @@ unsigned g_log_switch = 0; * @brief 获取指定采样率的EQ数组指针(统一使用44100Hz数组) * @param sample_rate 采样率 * @return EQ数组指针,始终返回44100Hz数组 - * + * * 改动原因:所有采样率共用44100Hz数组,参数相同,系数根据采样率动态计算 */ static inline eq_mode_data_t (*get_eq_array_ptr_common(uint32_t sample_rate))[NUM_EQ_MODES][NUM_EQ_CHANS] { @@ -59,7 +66,6 @@ static inline eq_mode_data_t (*get_eq_array_ptr_common(uint32_t sample_rate))[NU #include "eq_coefficient_calculator.h" #include "biquad_standalone.h" #include "eq_flash_storage.h" -#endif #include "user_func.h" // 改动原因:包含check_sum函数声明,用于uart_checksum宏定义 #include "dfu_upgrade.h" // 改动原因:包含固件升级函数声明,用于处理HID固件升级命令 #include "roleswitchflag.h" @@ -79,8 +85,190 @@ static struct { bool is_get_current_uac_mode_request; // GET_CURRENT_UAC_MODE请求标志 } uac_request = {0}; +extern unsigned g_sync_t0_to_t1_cmd; +extern unsigned g_sync_t0_to_t1_data; +/* 改动原因:上电 sync 0x03 经 data2 携带 FPS 三模块使能包(bit31=1) */ +extern unsigned g_sync_t0_to_t1_data2; +// 改动原因:从FPS算法侧引入game和level两个全局变量,用于HID与tile1之间同步当前FPS配置 +extern unsigned g_fps_game_select; +extern unsigned g_fps_level_select; +/* 改动原因:HID 0xB5/0xB6 读写 FPS 库三子模块使能,tile0 存 Flash 后经 sync 0x08 同步到 tile1 */ +extern unsigned g_fps_drc_enable; +extern unsigned g_fps_sub_enable; +extern unsigned g_fps_eq_enable; +/* 改动原因:HID 0xBD/0xBE 读写 DRC 压缩模式,tile0 存 Flash 后经 sync 0x0C 同步到 tile1 */ +extern unsigned g_fps_drc_mode; +#include "fps_eq_flash.h" +#include "fps_eq_sync.h" +#include "fps_tile_sync.h" +#include "user_uart.h" +/* 改动原因:与 eq_hid_protocol_ds1 一致,0xA7-0xAE 保留固件升级/重启;FPS game/level 置于 DRC(0xBD/0xBE) 之后 */ +#define HID_SET_FPS_XMOS_GAME_SELECT 0xBF +#define HID_GET_FPS_XMOS_GAME_SELECT 0xC0 +extern void save_value(unsigned char *path, unsigned char value); +extern unsigned char load_value(unsigned char *); #if EQ_EN +/* 改动原因:tile0侧缓存FPS fps_eq五模式Flash数据,HID读写与关机保存 */ +static fps_eq_flash_store_t s_fps_eq_store; +static unsigned char s_fps_eq_store_valid = 0; + +static void fps_eq_store_ensure_loaded(void) +{ + if (!s_fps_eq_store_valid) { + if (fps_eq_flash_load(&s_fps_eq_store) != 0) { + fps_eq_flash_set_defaults(&s_fps_eq_store); + fps_eq_flash_save(&s_fps_eq_store); + } + s_fps_eq_store_valid = 1; + } +} + +static void fps_eq_store_save(void) +{ + fps_eq_flash_save(&s_fps_eq_store); +} + +/* 改动原因:上电LOAD_CONFIGS调用,从Flash恢复fps_eq到tile0并排队 sync 0x09+0x0B 到 tile1 */ +void fps_eq_boot_publish_to_tile1(void) +{ + unsigned mode; + + fps_eq_store_ensure_loaded(); + mode = s_fps_eq_store.current_mode; + if (mode >= FPS_EQ_MODE_COUNT) { + mode = 0; + s_fps_eq_store.current_mode = 0; + } + fps_eq_publish_mode_and_gains(mode, s_fps_eq_store.gains[mode]); + /* 改动原因:0x03 已占用 sync 槽,fps_eq 须入队;pack 末包 apply 后写入算法库 */ + sync_t0_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_EQ_MODE, mode, 0); + fps_eq_queue_pack_words_to_tile1(1, 1); +} + +/* 改动原因:上电LOAD_CONFIGS调用,从Flash恢复fps_drc_mode并排队 sync 0x0C 到 tile1 */ +void fps_drc_boot_sync_to_tile1(void) +{ + unsigned mode; + + GET_SHARED_GLOBAL(mode, g_fps_drc_mode); + /* 改动原因:mode仅0=low、1=high,Flash未写入或无效时默认0 */ + if (mode > 1) { + mode = 0; + } + sync_t0_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_DRC_MODE, mode, 0); +} + +/* 改动原因:C1 无 UART,不经过 c_uart_sync/SYNC_CMD_LOAD_CONFIGS;上电在 tile0 直接读 Flash 恢复 FPS 并 sync 到 tile1 */ +void fps_boot_load_from_flash(void) +{ + unsigned fps_game_select = load_value("fps_game_select"); + unsigned l0, l1, l2; + unsigned fps_level_select; + unsigned packed_fps; + unsigned fps_drc_en, fps_sub_en, fps_eq_en; + unsigned fps_drc_mode; + unsigned packed_enable; + + if (fps_game_select > 2) { + fps_game_select = 0; + } + /* 改动原因:每种 game 单独存 level,无效或未存则默认档位 2 */ + l0 = load_value("fps_level_g0"); + l1 = load_value("fps_level_g1"); + l2 = load_value("fps_level_g2"); + if (l0 > 4) { l0 = 2; } + if (l1 > 4) { l1 = 2; } + if (l2 > 4) { l2 = 2; } + if (fps_game_select == 0) { + fps_level_select = l0; + } else if (fps_game_select == 1) { + fps_level_select = l1; + } else { + fps_level_select = l2; + } + + SET_SHARED_GLOBAL(g_fps_game_select, fps_game_select); + SET_SHARED_GLOBAL(g_fps_level_select, fps_level_select); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, (unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_XMOS_GAME_SELECT); + packed_fps = (fps_game_select & 0xFF) | ((fps_level_select & 0xFF) << 8); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, packed_fps); + + debug_printf("fps_boot: game %u level %u (from fps_level_g%u)\n", + fps_game_select, fps_level_select, fps_game_select); + + fps_drc_en = load_value("fps_drc_enable"); + fps_sub_en = load_value("fps_sub_enable"); + fps_eq_en = load_value("fps_eq_enable"); + /* 改动原因:Flash 未写入或无效(>1) 时:DRC/fps_eq 默认关,FPS 主处理默认开 */ + if (fps_drc_en > 1) { fps_drc_en = 0; } + if (fps_sub_en > 1) { fps_sub_en = 1; } + if (fps_eq_en > 1) { fps_eq_en = 0; } + SET_SHARED_GLOBAL(g_fps_drc_enable, fps_drc_en); + SET_SHARED_GLOBAL(g_fps_sub_enable, fps_sub_en); + SET_SHARED_GLOBAL(g_fps_eq_enable, fps_eq_en); + + fps_drc_mode = load_value("fps_drc_mode"); + if (fps_drc_mode > 1) { + fps_drc_mode = 0; + } + SET_SHARED_GLOBAL(g_fps_drc_mode, fps_drc_mode); + + /* 改动原因:bit31=1 表示 data2 含有效使能包,避免与 HID 0xBF 仅改 game 时 data2=0 混淆 */ + packed_enable = (fps_drc_en & 0xFF) + | ((fps_sub_en & 0xFF) << 8) + | ((fps_eq_en & 0xFF) << 16) + | (1u << 31); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, packed_enable); + + /* 改动原因:上电先发 sync 0x03(game/level+data2 使能),fps_eq/drc 经 pending 队列紧随其后 */ + fps_drc_boot_sync_to_tile1(); + fps_eq_boot_publish_to_tile1(); +} + +static void fps_eq_tile0_sync_mode(unsigned mode) +{ + /* 改动原因:tile0 发布 pack 后 sync 0x09+五包 0x0B 到 tile1,避免跨 tile SET_SHARED_GLOBAL 无效 */ + fps_eq_publish_mode_and_gains(mode, s_fps_eq_store.gains[mode]); + sync_t0_send_or_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_EQ_MODE, mode, 0); + fps_eq_queue_pack_words_to_tile1(1, 0); +} + +static void fps_eq_tile0_sync_band(unsigned band, int16_t gain) +{ + int16_t gains[FPS_EQ_BAND_COUNT]; + unsigned m; + unsigned packed; + + m = s_fps_eq_store.current_mode; + if (m >= FPS_EQ_MODE_COUNT) { + m = 0; + } + memcpy(gains, s_fps_eq_store.gains[m], sizeof(gains)); + gains[band] = gain; + s_fps_eq_store.gains[m][band] = gain; + fps_eq_publish_gains_to_shared(gains); + + packed = (band & 0xFF) | (((unsigned)(uint16_t)gain) << 8); + sync_t0_send_or_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_EQ_BAND_GAIN, packed, 0); + /* 改动原因:单段调节后同步含该段的 pack 字到 tile1,保持与 Flash 一致 */ + { + unsigned pack_idx = band / 2; + int32_t pack_val; + unsigned data1; + + switch (pack_idx) { + case 0: GET_SHARED_GLOBAL(pack_val, g_fps_eq_pack0); break; + case 1: GET_SHARED_GLOBAL(pack_val, g_fps_eq_pack1); break; + case 2: GET_SHARED_GLOBAL(pack_val, g_fps_eq_pack2); break; + case 3: GET_SHARED_GLOBAL(pack_val, g_fps_eq_pack3); break; + default: GET_SHARED_GLOBAL(pack_val, g_fps_eq_pack4); break; + } + data1 = pack_idx | (1u << 8); + sync_t0_send_or_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK, data1, (unsigned)pack_val); + } +} + #if 0 void print_float(float value, int precision) { @@ -149,6 +337,15 @@ static struct { bool is_get_filter_mode_request; // 改动原因:添加获取滤波器模式请求标志,用于GET_FILTER_MODE (0xA3) bool is_get_game_mode_request; // 改动原因:添加获取游戏模式请求标志,用于GET_GAME_MODE (0xA5) bool is_get_firmware_version_request; // 改动原因:添加获取固件版本请求标志,用于GET_FIRMWARE_VERSION (0xA6) + bool is_get_fps_xmos_game_select_request; // 改动原因:GET_FPS_XMOS_GAME_SELECT (0xC0) 查询指定 game 的 level + uint8_t fps_game_query; // 改动原因:0xC0 请求中指定的 game(0/1/2) + bool is_get_fps_module_enable_request; // 改动原因:GET_FPS_MODULE_ENABLE (0xB6) 读取 DRC/FPS主处理/fps_eq 使能 + bool is_get_fps_drc_mode_request; // 改动原因:GET_FPS_DRC_MODE (0xBE) 读取 DRC 压缩模式 0=low 1=high + bool is_get_fps_eq_mode_request; // 改动原因:GET_FPS_EQ_MODE (0xB8) 读取fps_eq当前模式0-4 + bool is_get_fps_eq_band_gain_request; // 改动原因:GET_FPS_EQ_BAND_GAIN (0xBA) + uint8_t fps_eq_band_query; // 改动原因:0xBA请求中的频段0-9 + bool is_get_fps_eq_mode_name_request; // 改动原因:GET_FPS_EQ_MODE_NAME (0xBC) + uint8_t fps_eq_mode_name_query; // 改动原因:0xBC请求中的模式0-4 bool is_get_mute_switch_request; // 改动原因:添加获取静音开关请求标志,用于GET_MUTE_SWITCH (0xB2),值由MCU通过UART 0x5F返回 bool is_get_listen_switch_request; // 改动原因:添加获取监听开关请求标志,用于GET_LISTEN_SWITCH (0xB4),直接读 g_adc_loop bool is_get_dnr_enable_request; // 改动原因:添加获取AI通话降噪请求标志,用于GET_DNR_ENABLE (0xB5),直接读 g_dnr_enable @@ -487,13 +684,12 @@ static inline int32_t apply_gain(int32_t sample, int32_t gain_db) { * 改动原因:所有采样率共用44100Hz数组,参数相同,只需要设置sample_rate标记 * 系数会根据采样率动态计算,不需要复制参数 */ -#if 1// !UAC1 static int copy_params_from_44100(uint32_t sample_rate, uint8_t mode) { if (mode >= NUM_EQ_MODES) { debug_printf("Error: Invalid mode %d in copy_params_from_44100\n", mode); return -1; } - + // 改动原因:所有采样率共用44100Hz数组,只需要设置sample_rate标记 // 参数已经存储在44100Hz数组中,不需要复制 for (int ch = 0; ch < NUM_EQ_CHANS; ch++) { @@ -501,7 +697,7 @@ static int copy_params_from_44100(uint32_t sample_rate, uint8_t mode) { // 重置total_bshift(将在计算系数时更新) sEQ_data_44100HZ[mode][ch].total_bshift = 0; } - + debug_printf("Set sample rate to %dHz for mode %d (using 44100Hz array)\n", sample_rate, mode); return 0; } @@ -675,7 +871,7 @@ void update_eq_post_gain(void) { } } } -#endif + unsigned int is_mode_changed(void) { if ((g_current_eq_mode != g_new_eq_mode) || (g_force_eq_mode_change == 1)) @@ -706,7 +902,6 @@ unsigned int is_eq_disabled(void) } void clear_eq_status(unsigned sample_freq, unsigned ch_no) { -#if 1// !UAC1 int n; debug_printf("clear_eq_status %d %d\n", sample_freq, ch_no); if(is_eq_disabled()) @@ -722,13 +917,12 @@ void clear_eq_status(unsigned sample_freq, unsigned ch_no) { (*eq_data)[g_current_eq_mode][ch_no].filter.state[0][n] = 0; (*eq_data)[g_current_eq_mode][ch_no].filter.state[1][n] = 0; } -#endif } // 复位EQ参数函数 uint8_t reset_eq_params(uint8_t mode) { debug_printf("Resetting EQ params for mode %d\n", mode); -#if 1 //!UAC1 + // 检查模式号有效性 if (mode != 0xFF && mode >= NUM_EQ_MODES) { debug_printf("Error: Invalid mode %d\n", mode); @@ -749,7 +943,6 @@ uint8_t reset_eq_params(uint8_t mode) { init_mode_info(); debug_printf("EQ params reset successful for mode %d\n", mode); -#endif return 0x00; // 成功 } @@ -890,7 +1083,6 @@ void debug_print_eq_mode(eq_mode_data_t *eq_data) { int32_t handler_eq_filter(unsigned sample_freq, uint32_t ch, int32_t new_sample) { int32_t temp_sample = new_sample; -#if 1// !UAC1 if(is_eq_disabled()) { @@ -918,7 +1110,7 @@ int32_t handler_eq_filter(unsigned sample_freq, uint32_t ch, int32_t new_sample) if (count % 100000 == 0) { debug_printf("post_gain: %d\n", post_gain); } - + temp_sample = temp_sample >> 1; //Q30 // 应用均衡器滤波 @@ -937,7 +1129,6 @@ int32_t handler_eq_filter(unsigned sample_freq, uint32_t ch, int32_t new_sample) } } -#endif return temp_sample; } @@ -1117,7 +1308,6 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { return false; } -#if 1// !UAC1 // Process read request (0x8E) - GET_EQ_PARAMS if (data[1] == 0x8E) { debug_printf("Received read request (GET_EQ_PARAMS)\n"); @@ -1433,7 +1623,7 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { led_request.is_get_led_count_request = true; return true; } -#endif + // 处理获取UAC模式信息命令 (0x9A) - GET_UAC_MODE_INFO // 改动原因:添加UAC模式信息查询命令,返回UAC模式总数和模式名称列表 if (data[1] == 0x9A) { @@ -1455,8 +1645,8 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { debug_printf("Error: Invalid UAC mode %d (must be 0-1, 0=UAC2.0, 1=UAC1.0)\n", uac_mode); return true; } - - debug_printf("HID 0x9B: Setting UAC mode to %s, forwarding to MCU via UART 0x51\n", + + debug_printf("HID 0x9B: Setting UAC mode to %s, forwarding to tile1 for UART 0x51\n", uac_mode == 0 ? "UAC2.0" : "UAC1.0"); // 改动原因:HID 0x9B命令通过UART 0x51命令透传给MCU @@ -1533,15 +1723,16 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { return true; } - // 处理获取AI通话降噪开关命令 (0xB5) - GET_DNR_ENABLE - // 改动原因:规格 mic 键长按切换 DNR 无指示灯,APP 通过 HID 0xB5 读取/接收主动上报 g_dnr_enable - if (data[1] == 0xB5) { - debug_printf("Received get DNR enable command (GET_DNR_ENABLE) via HID 0xB5\n"); + // 处理获取AI通话降噪开关命令 - GET_DNR_ENABLE + // 改动原因:XMOS_FPS_EN 时 0xB5 为 SET_FPS_MODULE_ENABLE,DNR 读改用 C1_HID_GET_DNR_ENABLE_OPCODE(0xC5) + if (data[1] == C1_HID_GET_DNR_ENABLE_OPCODE) { + debug_printf("Received get DNR enable command (GET_DNR_ENABLE) via HID 0x%02X\n", + C1_HID_GET_DNR_ENABLE_OPCODE); read_request.is_get_dnr_enable_request = true; return true; } -#if C1_DFS_EN +#if 0 // C1_DFS_EN // 处理设置tile1动态降频分频值命令 (0xB6) - SET_TILE1_DIV // 改动原因:动态降频,主机设置tile1低功耗分频值(600MHz/N);状态机下次降频或当前已降频时生效 if (data[1] == 0xB6) { @@ -1721,9 +1912,247 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { return true; } + // 处理设置FPS库三子模块使能 (0xB5) - SET_FPS_MODULE_ENABLE + // 改动原因:tile0 收 HID,写 Flash 并 sync 0x08 到 tile1 调用 fps_xmos_xc_set_module_enable + if (data[1] == 0xB5) { + uint8_t drc_enable = (data[2] != 0) ? 1 : 0; + uint8_t fps_sub_enable = (data[3] != 0) ? 1 : 0; + uint8_t eq_enable = (data[4] != 0) ? 1 : 0; + + debug_printf("HID 0xB5: FPS module enable drc=%u fps=%u eq=%u, sync to tile1\n", + drc_enable, fps_sub_enable, eq_enable); + + save_value("fps_drc_enable", drc_enable); + save_value("fps_sub_enable", fps_sub_enable); + save_value("fps_eq_enable", eq_enable); + + SET_SHARED_GLOBAL(g_fps_drc_enable, (unsigned)drc_enable); + SET_SHARED_GLOBAL(g_fps_sub_enable, (unsigned)fps_sub_enable); + SET_SHARED_GLOBAL(g_fps_eq_enable, (unsigned)eq_enable); + + unsigned packed = (drc_enable & 0xFF) + | ((fps_sub_enable & 0xFF) << 8) + | ((eq_enable & 0xFF) << 16); + /* 改动原因:与上电一致,经 channel sync 0x08 写 tile1 全局再 apply */ + sync_t0_send_or_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_MODULE_ENABLE, packed, 0); + return true; + } + + // 处理获取FPS库三子模块使能 (0xB6) - GET_FPS_MODULE_ENABLE + if (data[1] == 0xB6) { + debug_printf("Received GET_FPS_MODULE_ENABLE (0xB6)\n"); + read_request.is_get_fps_module_enable_request = true; + return true; + } + + // 处理设置DRC压缩模式 (0xBD) - SET_FPS_DRC_MODE + // 改动原因:tile0 收 HID,写 Flash 并 sync 0x0C 到 tile1 调用 fps_xmos_xc_drc_set_mode + if (data[1] == 0xBD) { + uint8_t drc_mode = data[2]; + if (drc_mode > 1) { + debug_printf("HID 0xBD: invalid drc_mode %u\n", drc_mode); + return false; + } + debug_printf("HID 0xBD: FPS DRC mode=%u, sync to tile1\n", drc_mode); + save_value("fps_drc_mode", drc_mode); + SET_SHARED_GLOBAL(g_fps_drc_mode, (unsigned)drc_mode); + sync_t0_send_or_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_DRC_MODE, (unsigned)drc_mode, 0); + return true; + } + + // 处理获取DRC压缩模式 (0xBE) - GET_FPS_DRC_MODE + if (data[1] == 0xBE) { + debug_printf("Received GET_FPS_DRC_MODE (0xBE)\n"); + read_request.is_get_fps_drc_mode_request = true; + return true; + } + + // 处理设置FPS XMOS游戏选择 (0xBF) - SET_FPS_XMOS_GAME_SELECT + // 改动原因:0xA7-0xAE 与 ds1 一致保留固件升级;game/level 命令放在 DRC(0xBD/0xBE) 之后 + if (data[1] == HID_SET_FPS_XMOS_GAME_SELECT) { + debug_printf("Received SET_FPS_XMOS_GAME_SELECT via HID 0x%02X\n", HID_SET_FPS_XMOS_GAME_SELECT); + uint8_t game_select = data[2]; + uint8_t level_select = data[3]; + if (level_select > 4) { + level_select = 2; + } + debug_printf("HID 0x%02X: game=%d level=%d, sync to tile1\n", + HID_SET_FPS_XMOS_GAME_SELECT, game_select, level_select); + if (game_select <= 2) { + save_value("fps_game_select", game_select); + if (game_select == 0) { + save_value("fps_level_g0", level_select); + } else if (game_select == 1) { + save_value("fps_level_g1", level_select); + } else { + save_value("fps_level_g2", level_select); + } + unsigned packed_fps = (game_select & 0xFF) | ((level_select & 0xFF) << 8); + SET_SHARED_GLOBAL(g_fps_game_select, game_select); + SET_SHARED_GLOBAL(g_fps_level_select, level_select); + sync_t0_send_or_enqueue_to_tile1((unsigned)SYNC_CMD_T0_TO_T1_SET_FPS_XMOS_GAME_SELECT, packed_fps, 0); + } else { + debug_printf("Error: Invalid FPS game %d (must be 0-2)\n", game_select); + return false; + } + return true; + } + + // 处理获取FPS XMOS游戏选择 (0xC0) - GET_FPS_XMOS_GAME_SELECT + if (data[1] == HID_GET_FPS_XMOS_GAME_SELECT) { + uint8_t game_to_query = (len >= 1) ? data[2] : 0; + if (game_to_query > 2) { + game_to_query = 0; + } + debug_printf("Received GET_FPS_XMOS_GAME_SELECT (0x%02X), query game=%d\n", + HID_GET_FPS_XMOS_GAME_SELECT, game_to_query); + read_request.is_get_fps_xmos_game_select_request = true; + read_request.fps_game_query = game_to_query; + return true; + } + + // 处理设置fps_eq模式 (0xB7) - SET_FPS_EQ_MODE,模式0-4,默认0,关机保存Flash + if (data[1] == 0xB7) { + uint8_t mode = data[2]; + if (mode >= FPS_EQ_MODE_COUNT) { + debug_printf("HID 0xB7: invalid mode %u\n", mode); + return false; + } + fps_eq_store_ensure_loaded(); + s_fps_eq_store.current_mode = mode; + fps_eq_store_save(); + fps_eq_tile0_sync_mode(mode); + debug_printf("HID 0xB7: fps_eq mode=%u, synced to tile1\n", mode); + return true; + } + + // 处理获取fps_eq当前模式 (0xB8) - GET_FPS_EQ_MODE + if (data[1] == 0xB8) { + read_request.is_get_fps_eq_mode_request = true; + return true; + } + + // 处理设置fps_eq单段增益 (0xB9) - SET_FPS_EQ_BAND_GAIN,单位0.01dB,-600~600 + if (data[1] == 0xB9) { + uint8_t band = data[2]; + int16_t gain = (int16_t)((uint16_t)data[3] | ((uint16_t)data[4] << 8)); + if (band >= FPS_EQ_BAND_COUNT) { + debug_printf("HID 0xB9: invalid band %u\n", band); + return false; + } + gain = fps_eq_clamp_gain(gain); + fps_eq_store_ensure_loaded(); + fps_eq_tile0_sync_band(band, gain); + fps_eq_store_save(); + debug_printf("HID 0xB9: mode=%u band=%u gain=%d, saved & synced\n", + s_fps_eq_store.current_mode, band, (int)gain); + return true; + } + + // 处理获取fps_eq单段增益 (0xBA) - GET_FPS_EQ_BAND_GAIN,读当前选中模式 + if (data[1] == 0xBA) { + uint8_t band = data[2]; + if (band >= FPS_EQ_BAND_COUNT) { + band = 0; + } + read_request.is_get_fps_eq_band_gain_request = true; + read_request.fps_eq_band_query = band; + return true; + } + + // 处理设置fps_eq模式名 (0xBB) - SET_FPS_EQ_MODE_NAME,模式0-4,写Flash断电保存 + if (data[1] == 0xBB) { + uint8_t mode = data[2]; + char mode_name[FPS_EQ_NAME_LEN]; + if (mode >= FPS_EQ_MODE_COUNT) { + debug_printf("HID 0xBB: invalid mode %u\n", mode); + return false; + } + fps_eq_store_ensure_loaded(); + memcpy(mode_name, &data[3], FPS_EQ_NAME_LEN); + mode_name[FPS_EQ_NAME_LEN - 1] = '\0'; + fps_eq_name_set(&s_fps_eq_store, mode, mode_name); + fps_eq_store_save(); + debug_printf("HID 0xBB: set fps_eq mode %u name='%s'\n", mode, mode_name); + return true; + } + + // 处理获取fps_eq模式名 (0xBC) - GET_FPS_EQ_MODE_NAME + if (data[1] == 0xBC) { + uint8_t mode = data[2]; + if (mode >= FPS_EQ_MODE_COUNT) { + mode = 0; + } + read_request.is_get_fps_eq_mode_name_request = true; + read_request.fps_eq_mode_name_query = mode; + return true; + } + + // 处理设置输入源模式命令 (0xB0) - SET_INPUT_SOURCE + // 改动原因:HID 0xB0 在 tile0 收到,通过 sync 0x04 让 tile1 发 UART 0x5D 透传 MCU + if (data[1] == 0xB0) { + debug_printf("Received set input source command (SET_INPUT_SOURCE) via HID 0xB0\n"); + uint8_t input_source = data[2]; + if (input_source > 2) { + debug_printf("Error: Invalid input source %d (must be 0-2, 0=USB, 1=OPT, 2=COAX)\n", input_source); + return true; + } + debug_printf("HID 0xB0: Setting input source to %s, forwarding to tile1 for UART 0x5D\n", + input_source == 0 ? "USB" : (input_source == 1 ? "OPT" : "COAX")); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, 0x04); // SYNC_CMD_T0_TO_T1_SET_INPUT_SOURCE + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, input_source); + return true; + } + + // 处理设置静音开关命令 (0xB1) - SET_MUTE_SWITCH + // 改动原因:HID 0xB1 在 tile0 收到,通过 sync 0x05 让 tile1 发 UART 0x5E 透传 MCU + if (data[1] == 0xB1) { + debug_printf("Received set mute switch command (SET_MUTE_SWITCH) via HID 0xB1\n"); + uint8_t mute = data[2]; + if (mute > 1) { + debug_printf("Error: Invalid mute value %d (must be 0 or 1, 0=关 1=开)\n", mute); + return true; + } + debug_printf("HID 0xB1: Setting mute switch to %s, forwarding to tile1 for UART 0x5E\n", mute ? "开" : "关"); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, 0x05); // SYNC_CMD_T0_TO_T1_SET_MUTE_SWITCH + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, mute); + return true; + } + + // 处理获取静音开关命令 (0xB2) - GET_MUTE_SWITCH + // 改动原因:tile0 设置 sync 0x06 让 tile1 向 MCU 发 0x5F 请求,MCU 返回后 tile1 经 sync 0x0E 回传静音值 + if (data[1] == 0xB2) { + debug_printf("Received get mute switch command (GET_MUTE_SWITCH) via HID 0xB2\n"); + read_request.is_get_mute_switch_request = true; + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, 0x06); // SYNC_CMD_T0_TO_T1_SEND_GET_MUTE_REQUEST + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, 0); + return true; + } + + // 处理设置监听开关命令 (0xB3) - SET_LISTEN_SWITCH + // 改动原因:HID 0xB3 在 tile0 收到,通过 sync 0x07 让 tile1 发 UART 0x60 透传 MCU + if (data[1] == 0xB3) { + uint8_t listen = data[2]; + if (listen > 1) { + debug_printf("Error: Invalid listen switch %d (must be 0 or 1, 0=关 1=开)\n", listen); + return true; + } + debug_printf("Received set listen switch command (SET_LISTEN_SWITCH) via HID 0xB3, forwarding to tile1 for UART 0x60\n"); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, 0x07); // SYNC_CMD_T0_TO_T1_SET_LISTEN_SWITCH + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, listen); + return true; + } + + // 处理获取监听开关命令 (0xB4) - GET_LISTEN_SWITCH + // 改动原因:直接读 tile0 的 g_adc_loop 返回,不经过串口(g_adc_loop 由 tile1 经 sync 0x0D 同步到 tile0) + if (data[1] == 0xB4) { + debug_printf("Received get listen switch command (GET_LISTEN_SWITCH) via HID 0xB4\n"); + read_request.is_get_listen_switch_request = true; + return true; + } + if (data[1] == 0x8d) { -#if 1// !UAC1 debug_printf("Received set EQ filter parameters command (SET_EQ_PARAMS)\n"); // Get mode value (跳过report_id字节) @@ -1837,7 +2266,7 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { } else { debug_printf("Parameter unchanged for mode %d, band %d\n", mode, band_index); } -#endif + return true; } #if 0 @@ -2015,7 +2444,7 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { /** * @brief 处理串口EQ模式设置 (0x30) - * @param mode EQ模式值 (0-9) + * @param mode EQ模式值 (0-14) * @return 处理结果 */ uint8_t process_uart_set_eq_mode(uint8_t mode) @@ -2526,9 +2955,13 @@ void get_mode_name(uint8_t mode, char* name) { // 初始化模式信息函数 void init_mode_info(void) { // 初始化默认模式名称 + // 改动原因:扩展至15模式(13预设+2用户),更新游戏音效预设名称 const char* default_names[NUM_EQ_MODES] = { - "JAZZ", "POP", "ROCK", "CLASIC", "R&B", - "3A Game", "FPS", "user 1", "user 2", "user3" + "JAZZ", "POP", "ROCK", "CLASIC", + "暗区突围", "3A Game", "战地6", + "APEX", "和平精英", "逃离塔科夫", + "穿越火线", "守望先锋", "永劫无间", + "user 1", "user 2" }; // 初始化默认增益(0dB) @@ -3124,6 +3557,146 @@ unsigned char process_read_params(uint8_t response[]) { return true; } + // 处理获取FPS库三子模块使能 (0xB6) - GET_FPS_MODULE_ENABLE + // 改动原因:0xB5 已更新 g_fps_* 共享全局;若仍 load_value 读 Flash,LFS 快速 mount/write/read 可能返回旧值,断电后才一致。与 0x9E/0xB2 一致,读运行时全局。 + if (read_request.is_get_fps_module_enable_request == true) { + unsigned drc_enable; + unsigned fps_sub_enable; + unsigned eq_enable; + GET_SHARED_GLOBAL(drc_enable, g_fps_drc_enable); + GET_SHARED_GLOBAL(fps_sub_enable, g_fps_sub_enable); + GET_SHARED_GLOBAL(eq_enable, g_fps_eq_enable); + if (drc_enable > 1) { drc_enable = 0; } /* 改动原因:无效值默认 DRC 关 */ + if (fps_sub_enable > 1) { fps_sub_enable = 1; } /* 改动原因:无效值默认 FPS 主处理开 */ + if (eq_enable > 1) { eq_enable = 0; } /* 改动原因:无效值默认 fps_eq 关 */ + + debug_printf("Building 0xB6 response: drc=%u fps=%u eq=%u (from globals)\n", + drc_enable, fps_sub_enable, eq_enable); + response[0] = 0x77; + response[1] = 0xB6; + response[2] = (uint8_t)drc_enable; + response[3] = (uint8_t)fps_sub_enable; + response[4] = (uint8_t)eq_enable; + for (int i = 5; i < 63; i++) { + response[i] = 0x00; + } + read_request.is_get_fps_module_enable_request = false; + return true; + } + + // 处理获取DRC压缩模式 (0xBE) - GET_FPS_DRC_MODE + // 改动原因:0xBD 已更新 g_fps_drc_mode 共享全局;读运行时全局与 0xB6 一致 + if (read_request.is_get_fps_drc_mode_request == true) { + unsigned drc_mode; + GET_SHARED_GLOBAL(drc_mode, g_fps_drc_mode); + if (drc_mode > 1) { + drc_mode = 0; /* 改动原因:无效值默认 low(0) */ + } + debug_printf("Building 0xBE response: drc_mode=%u (from globals)\n", drc_mode); + response[0] = 0x77; + response[1] = 0xBE; + response[2] = (uint8_t)drc_mode; + for (int i = 3; i < 63; i++) { + response[i] = 0x00; + } + read_request.is_get_fps_drc_mode_request = false; + return true; + } + + // 处理获取FPS XMOS游戏选择 (0xC0) - GET_FPS_XMOS_GAME_SELECT(位于 DRC 0xBE 之后) + if (read_request.is_get_fps_xmos_game_select_request == true) { + uint8_t req_game = read_request.fps_game_query; + if (req_game > 2) { + req_game = 0; + } + unsigned level_for_game; + if (req_game == 0) { + level_for_game = load_value("fps_level_g0"); + } else if (req_game == 1) { + level_for_game = load_value("fps_level_g1"); + } else { + level_for_game = load_value("fps_level_g2"); + } + if (level_for_game > 4) { + level_for_game = 2; + } + debug_printf("Building 0x%02X response: game=%d level=%u\n", + HID_GET_FPS_XMOS_GAME_SELECT, req_game, level_for_game); + response[0] = 0x77; + response[1] = HID_GET_FPS_XMOS_GAME_SELECT; + response[2] = req_game; + response[3] = (uint8_t)level_for_game; + for (int i = 4; i < 63; i++) { + response[i] = 0x00; + } + read_request.is_get_fps_xmos_game_select_request = false; + return true; + } + + // 处理获取fps_eq当前模式 (0xB8) + if (read_request.is_get_fps_eq_mode_request == true) { + unsigned mode; + fps_eq_store_ensure_loaded(); + mode = s_fps_eq_store.current_mode; + if (mode >= FPS_EQ_MODE_COUNT) { + mode = 0; + } + response[0] = 0x77; + response[1] = 0xB8; + response[2] = (uint8_t)mode; + for (int i = 3; i < 63; i++) { + response[i] = 0x00; + } + read_request.is_get_fps_eq_mode_request = false; + return true; + } + + // 处理获取fps_eq单段增益 (0xBA),当前模式 + if (read_request.is_get_fps_eq_band_gain_request == true) { + uint8_t band = read_request.fps_eq_band_query; + int16_t gain; + unsigned mode; + fps_eq_store_ensure_loaded(); + mode = s_fps_eq_store.current_mode; + if (mode >= FPS_EQ_MODE_COUNT) { + mode = 0; + } + if (band >= FPS_EQ_BAND_COUNT) { + band = 0; + } + gain = s_fps_eq_store.gains[mode][band]; + response[0] = 0x77; + response[1] = 0xBA; + response[2] = band; + response[3] = (uint8_t)(gain & 0xFF); + response[4] = (uint8_t)((gain >> 8) & 0xFF); + for (int i = 5; i < 63; i++) { + response[i] = 0x00; + } + read_request.is_get_fps_eq_band_gain_request = false; + return true; + } + + // 处理获取fps_eq模式名 (0xBC),指定模式0-4 + if (read_request.is_get_fps_eq_mode_name_request == true) { + uint8_t mode = read_request.fps_eq_mode_name_query; + char mode_name[FPS_EQ_NAME_LEN]; + fps_eq_store_ensure_loaded(); + if (mode >= FPS_EQ_MODE_COUNT) { + mode = 0; + } + fps_eq_name_get(&s_fps_eq_store, mode, mode_name); + response[0] = 0x77; + response[1] = 0xBC; + response[2] = mode; + memcpy(&response[3], mode_name, FPS_EQ_NAME_LEN); + for (int i = 3 + FPS_EQ_NAME_LEN; i < 63; i++) { + response[i] = 0x00; + } + read_request.is_get_fps_eq_mode_name_request = false; + return true; + } + // 处理获取固件版本请求 (0xA6) - GET_FIRMWARE_VERSION // 改动原因:添加获取固件版本响应,返回BCD格式的版本号(主版本、次版本、修订版本),参考user_uart.xc中的FW_VERSION实现 if (read_request.is_get_firmware_version_request == true) { @@ -3214,7 +3787,7 @@ unsigned char process_read_params(uint8_t response[]) { #endif if (read_request.is_read_request == true) { -#if 1 // 改动原因:fosi_c1 使用 -DUAC1=1 编译,原 #if !UAC1 导致 0x8E 读EQ参数在 HID GET_REPORT 时永不组包,eq_designer 收到全零响应 + debug_printf("Read request information:\n"); debug_printf(" Mode: %d\n", read_request.mode); debug_printf(" EQ index: %d\n", read_request.eq_index); @@ -3266,7 +3839,6 @@ unsigned char process_read_params(uint8_t response[]) { debug_printf("Parameter read processing completed\n"); return true; -#endif } #endif #if 1 @@ -3731,7 +4303,296 @@ void process_uart_set_uac_mode(uint8_t uac_mode) } /** - * @brief 处理串口设置输入源模式命令 (0x5D) + * @brief 处理串口获取当前UAC模式命令 (0x52) + * @note 改动原因:直接调用HID的process_read_params (0x9C),完全复用代码 + */ +uint8_t process_uart_get_current_uac_mode(uint8_t *response, uint8_t response_size) +{ + if (response_size < 15) return 0; + + // 调用HID获取UAC模式 + uint8_t hid_data[61]; + uint8_t len = call_hid_read_params(0x9C, NULL, 0, hid_data, sizeof(hid_data)); + + if (len >= 9) { + uint8_t uac_mode = hid_data[0]; + + // 构建UART响应(命令码应为0x52,不是0x42) + response[0] = 0x55; // 帧头1 + response[1] = 0xAA; // 帧头2 + response[2] = 0x00; + response[3] = GET_CURRENT_UAC_MODE; + response[4] = 0x09; // 数据长度 (9字节) + response[5] = uac_mode; // UAC模式值 + memcpy(&response[6], &hid_data[1], 8); // 模式名称 (8字节) + + uint8_t checksum_pos = 14; + response[checksum_pos] = uart_checksum(response, checksum_pos); + + debug_printf("UART GET_CURRENT_UAC_MODE (0x52): mode=%d (from HID 0x9C)\n", uac_mode); + return 15; + } + return 0; +} + +/** + * @brief 处理串口设置EQ使能命令 (0x43) + * @note 改动原因:直接调用HID的process_send_params (0x9D),完全复用代码 + */ +uint8_t process_uart_set_eq_enable(uint8_t enable) +{ + debug_printf("UART SET_EQ_ENABLE: enable=%d (calling HID 0x9D)\n", enable); + return call_hid_send_params(0x9D, &enable, 1) ? 0 : 1; +} + +/** + * @brief 构建EQ使能设置响应 (0x43响应) + * @note 改动原因:直接调用HID读取当前状态,完全复用代码 + */ +uint8_t process_uart_get_eq_enable_response(uint8_t result, uint8_t enable, uint8_t *response, uint8_t response_size) +{ + if (response_size < 8) return 0; + + // 调用HID获取EQ使能状态 + uint8_t hid_data[61]; + uint8_t len = call_hid_read_params(0x9E, NULL, 0, hid_data, sizeof(hid_data)); + uint8_t current_enable = (len > 0) ? hid_data[0] : enable; + + // 构建UART响应 + response[0] = 0x55; + response[1] = 0xAA; + response[2] = 0x00; + response[3] = SET_EQ_ENABLE; + response[4] = 0x02; + response[5] = result; + response[6] = current_enable; + + uint8_t checksum_pos = 7; + response[checksum_pos] = uart_checksum(response, checksum_pos); + + debug_printf("UART SET_EQ_ENABLE response: status=0x%02X, enable=%d (from HID 0x9E)\n", result, current_enable); + return 8; +} + +/** + * @brief 处理串口获取EQ使能命令 (0x44) + * @note 改动原因:直接调用HID的process_read_params (0x9E),完全复用代码 + */ +uint8_t process_uart_get_eq_enable(uint8_t *response, uint8_t response_size) +{ + debug_printf("UART GET_EQ_ENABLE: start processing, response_size=%d\n", response_size); + + if (response_size < 7) { + debug_printf("UART GET_EQ_ENABLE: error - response buffer too small (%d < 7)\n", response_size); + return 0; + } + + // 调用HID获取EQ使能 + debug_printf("UART GET_EQ_ENABLE: calling call_hid_read_params(0x9E)\n"); + uint8_t hid_data[61]; + uint8_t len = call_hid_read_params(0x9E, NULL, 0, hid_data, sizeof(hid_data)); + debug_printf("UART GET_EQ_ENABLE: call_hid_read_params returned len=%d\n", len); + + if (len > 0) { + uint8_t eq_enable = hid_data[0]; + debug_printf("UART GET_EQ_ENABLE: read eq_enable=%d from HID\n", eq_enable); + + // 构建UART响应 + response[0] = 0x55; + response[1] = 0xAA; + response[2] = 0x00; + response[3] = GET_EQ_ENABLE; + response[4] = 0x01; + response[5] = eq_enable; + + uint8_t checksum_pos = 6; + response[checksum_pos] = uart_checksum(response, checksum_pos); + + debug_printf("UART GET_EQ_ENABLE: response built, length=7, data: "); + for (int i = 0; i < 7; i++) { + debug_printf("%02X ", response[i]); + } + debug_printf("\n"); + debug_printf("UART GET_EQ_ENABLE: enable=%d (from HID 0x9E)\n", eq_enable); + return 7; + } else { + debug_printf("UART GET_EQ_ENABLE: error - call_hid_read_params returned len=0, cannot get EQ enable status\n"); + } + return 0; +} + +/** + * @brief 处理串口获取采样格式命令 (0x45) + * @note 改动原因:直接调用HID的process_read_params (0x9F),完全复用代码 + */ +uint8_t process_uart_get_sample_format(uint8_t *response, uint8_t response_size) +{ + if (response_size < 11) return 0; + + // 调用HID获取采样格式 + uint8_t hid_data[61]; + uint8_t len = call_hid_read_params(0x9F, NULL, 0, hid_data, sizeof(hid_data)); + + if (len >= 5) { + // HID返回:[rate_0, rate_1, rate_2, rate_3, dsd_mode, ...] + uint32_t sample_rate = hid_data[0] | (hid_data[1] << 8) | (hid_data[2] << 16) | (hid_data[3] << 24); + uint8_t dsd_mode = hid_data[4]; + + // 构建UART响应 + response[0] = 0x55; + response[1] = 0xAA; + response[2] = 0x00; + response[3] = GET_SAMPLE_FORMAT; + response[4] = 0x05; + response[5] = hid_data[0]; + response[6] = hid_data[1]; + response[7] = hid_data[2]; + response[8] = hid_data[3]; + response[9] = dsd_mode; + + uint8_t checksum_pos = 10; + response[checksum_pos] = uart_checksum(response, checksum_pos); + + debug_printf("UART GET_SAMPLE_FORMAT: sample_rate=%d, dsd_mode=%d (from HID 0x9F)\n", sample_rate, dsd_mode); + return 11; + } + return 0; +} + +/** + * @brief 处理串口设置增益模式命令 (0x46) + * @note 改动原因:直接调用HID的process_send_params (0xA0),完全复用代码 + */ +uint8_t process_uart_set_gain_mode(uint8_t gain_mode) +{ + debug_printf("UART SET_GAIN_MODE: gain_mode=%d (calling HID 0xA0)\n", gain_mode); + return call_hid_send_params(0xA0, &gain_mode, 1) ? 0 : 1; +} + +/** + * @brief 处理串口获取增益模式命令 (0x47) + * @note 改动原因:直接调用HID的process_read_params (0xA1),完全复用代码 + */ +uint8_t process_uart_get_gain_mode(uint8_t *response, uint8_t response_size) +{ + if (response_size < 7) return 0; + + // 调用HID获取增益模式 + uint8_t hid_data[61]; + uint8_t len = call_hid_read_params(0xA1, NULL, 0, hid_data, sizeof(hid_data)); + + if (len > 0) { + uint8_t gain_mode = hid_data[0]; + + // 构建UART响应 + response[0] = 0x55; + response[1] = 0xAA; + response[2] = 0x00; + response[3] = GET_GAIN_MODE; + response[4] = 0x01; + response[5] = gain_mode; + + uint8_t checksum_pos = 6; + response[checksum_pos] = uart_checksum(response, checksum_pos); + + debug_printf("UART GET_GAIN_MODE: gain_mode=%d (from HID 0xA1)\n", gain_mode); + return 7; + } + return 0; +} + +/** + * @brief 处理串口设置滤波器模式命令 (0x48) + * @note 改动原因:直接调用HID的process_send_params (0xA2),完全复用代码 + */ +uint8_t process_uart_set_filter_mode(uint8_t filter_mode) +{ + debug_printf("UART SET_FILTER_MODE: filter_mode=%d (calling HID 0xA2)\n", filter_mode); + return call_hid_send_params(0xA2, &filter_mode, 1) ? 0 : 1; +} + +/** + * @brief 处理串口获取滤波器模式命令 (0x49) + * @note 改动原因:直接调用HID的process_read_params (0xA3),完全复用代码 + */ +uint8_t process_uart_get_filter_mode(uint8_t *response, uint8_t response_size) +{ + if (response_size < 7) return 0; + + // 调用HID获取滤波器模式 + uint8_t hid_data[61]; + uint8_t len = call_hid_read_params(0xA3, NULL, 0, hid_data, sizeof(hid_data)); + + if (len > 0) { + uint8_t filter_mode = hid_data[0]; + + // 构建UART响应 + response[0] = 0x55; + response[1] = 0xAA; + response[2] = 0x00; + response[3] = GET_FILTER_MODE; + response[4] = 0x01; + response[5] = filter_mode; + + uint8_t checksum_pos = 6; + response[checksum_pos] = uart_checksum(response, checksum_pos); + + debug_printf("UART GET_FILTER_MODE: filter_mode=%d (from HID 0xA3)\n", filter_mode); + return 7; + } + return 0; +} + +/** + * @brief 处理串口设置游戏模式命令 (0x5A) + * @param game_mode 游戏模式值 (0=无音效, 1=FPS, 2=虚拟7.1) + * @note 改动原因:UART 0x5A命令将游戏模式设置请求透传给MCU处理,MCU负责执行模式设置和参数保存 + */ +void process_uart_set_game_mode(uint8_t game_mode) +{ + debug_printf("UART SET_GAME_MODE (0x5A): game_mode=%d, forwarding to MCU\n", game_mode); + + // 参数验证 + if (game_mode > 2) { + debug_printf("Error: Invalid game_mode %d (must be 0-2)\n", game_mode); + return; + } + + // 改动原因:构建UART 0x5A数据包并透传给MCU + // UART数据包格式:0x55 0xAA 0x00 0x5A [长度] [游戏模式值] [校验和] + uint8_t uart_packet[7]; + uart_packet[0] = 0x55; // 帧头1 + uart_packet[1] = 0xAA; // 帧头2 + uart_packet[2] = 0x00; // 版本 + uart_packet[3] = 0x5A; // 命令码 (SET_GAME_MODE) + uart_packet[4] = 0x01; // 数据长度 + uart_packet[5] = game_mode; // 游戏模式值 + + // 计算校验和(帧头到数据末尾所有字节的累加和取低8位) + uint8_t checksum = 0; + for (int i = 0; i < 6; i++) { + checksum += uart_packet[i]; + } + uart_packet[6] = checksum; // 校验和 + + // 改动原因:通过xmos_printf将UART数据包透传给MCU + // 声明xmos_printf函数(在user_uart.xc中定义) + extern int xmos_printf(unsigned char *data, unsigned char len); + + // 发送UART数据包给MCU + int result = xmos_printf(uart_packet, 7); + if (result == 7) { + debug_printf("UART 0x5A packet forwarded to MCU successfully: game_mode=%d (0=无音效, 1=FPS, 2=虚拟7.1)\n", + game_mode); + } else { + debug_printf("Error: Failed to forward UART 0x5A packet to MCU (result=%d)\n", result); + } + + // 改动原因:MCU接收到0x5A命令后会处理游戏模式设置和参数保存,XMOS设备无需执行额外操作 +} + +/** + * @brief 处理串口设置输入源模式命令 (0x5D),在 tile1 被 app_control_slave 调用 * @param input_source 输入源模式值 (0=USB, 1=OPT, 2=COAX) * @note 改动原因:HID 0xB0收到后构建UART 0x5D包透传给MCU,由MCU执行输入源(USB/OPT/COAX)切换 */ @@ -3830,296 +4691,6 @@ void process_uart_set_listen_switch(uint8_t listen) debug_printf("Error: Failed to forward UART 0x60 (result=%d)\n", result); } - -/** - * @brief 处理串口获取当前UAC模式命令 (0x52) - * @note 改动原因:直接调用HID的process_read_params (0x9C),完全复用代码 - */ -uint8_t process_uart_get_current_uac_mode(uint8_t *response, uint8_t response_size) -{ - if (response_size < 15) return 0; - - // 调用HID获取UAC模式 - uint8_t hid_data[61]; - uint8_t len = call_hid_read_params(0x9C, NULL, 0, hid_data, sizeof(hid_data)); - - if (len >= 9) { - uint8_t uac_mode = hid_data[0]; - - // 构建UART响应(命令码应为0x52,不是0x42) - response[0] = 0x55; // 帧头1 - response[1] = 0xAA; // 帧头2 - response[2] = 0x00; - response[3] = GET_CURRENT_UAC_MODE; - response[4] = 0x09; // 数据长度 (9字节) - response[5] = uac_mode; // UAC模式值 - memcpy(&response[6], &hid_data[1], 8); // 模式名称 (8字节) - - uint8_t checksum_pos = 14; - response[checksum_pos] = uart_checksum(response, checksum_pos); - - debug_printf("UART GET_CURRENT_UAC_MODE (0x52): mode=%d (from HID 0x9C)\n", uac_mode); - return 15; - } - return 0; -} - -/** - * @brief 处理串口设置EQ使能命令 (0x43) - * @note 改动原因:直接调用HID的process_send_params (0x9D),完全复用代码 - */ -uint8_t process_uart_set_eq_enable(uint8_t enable) -{ - debug_printf("UART SET_EQ_ENABLE: enable=%d (calling HID 0x9D)\n", enable); - return call_hid_send_params(0x9D, &enable, 1) ? 0 : 1; -} - -/** - * @brief 构建EQ使能设置响应 (0x43响应) - * @note 改动原因:直接调用HID读取当前状态,完全复用代码 - */ -uint8_t process_uart_get_eq_enable_response(uint8_t result, uint8_t enable, uint8_t *response, uint8_t response_size) -{ - if (response_size < 8) return 0; - - // 调用HID获取EQ使能状态 - uint8_t hid_data[61]; - uint8_t len = call_hid_read_params(0x9E, NULL, 0, hid_data, sizeof(hid_data)); - uint8_t current_enable = (len > 0) ? hid_data[0] : enable; - - // 构建UART响应 - response[0] = 0x55; - response[1] = 0xAA; - response[2] = 0x00; - response[3] = SET_EQ_ENABLE; - response[4] = 0x02; - response[5] = result; - response[6] = current_enable; - - uint8_t checksum_pos = 7; - response[checksum_pos] = uart_checksum(response, checksum_pos); - - debug_printf("UART SET_EQ_ENABLE response: status=0x%02X, enable=%d (from HID 0x9E)\n", result, current_enable); - return 8; -} - -/** - * @brief 处理串口获取EQ使能命令 (0x44) - * @note 改动原因:直接调用HID的process_read_params (0x9E),完全复用代码 - */ -uint8_t process_uart_get_eq_enable(uint8_t *response, uint8_t response_size) -{ - debug_printf("UART GET_EQ_ENABLE: start processing, response_size=%d\n", response_size); - - if (response_size < 7) { - debug_printf("UART GET_EQ_ENABLE: error - response buffer too small (%d < 7)\n", response_size); - return 0; - } - - // 调用HID获取EQ使能 - debug_printf("UART GET_EQ_ENABLE: calling call_hid_read_params(0x9E)\n"); - uint8_t hid_data[61]; - uint8_t len = call_hid_read_params(0x9E, NULL, 0, hid_data, sizeof(hid_data)); - debug_printf("UART GET_EQ_ENABLE: call_hid_read_params returned len=%d\n", len); - - if (len > 0) { - uint8_t eq_enable = hid_data[0]; - debug_printf("UART GET_EQ_ENABLE: read eq_enable=%d from HID\n", eq_enable); - - // 构建UART响应 - response[0] = 0x55; - response[1] = 0xAA; - response[2] = 0x00; - response[3] = GET_EQ_ENABLE; - response[4] = 0x01; - response[5] = eq_enable; - - uint8_t checksum_pos = 6; - response[checksum_pos] = uart_checksum(response, checksum_pos); - - debug_printf("UART GET_EQ_ENABLE: response built, length=7, data: "); - for (int i = 0; i < 7; i++) { - debug_printf("%02X ", response[i]); - } - debug_printf("\n"); - debug_printf("UART GET_EQ_ENABLE: enable=%d (from HID 0x9E)\n", eq_enable); - return 7; - } else { - debug_printf("UART GET_EQ_ENABLE: error - call_hid_read_params returned len=0, cannot get EQ enable status\n"); - } - return 0; -} - -/** - * @brief 处理串口获取采样格式命令 (0x45) - * @note 改动原因:直接调用HID的process_read_params (0x9F),完全复用代码 - */ -uint8_t process_uart_get_sample_format(uint8_t *response, uint8_t response_size) -{ - if (response_size < 11) return 0; - - // 调用HID获取采样格式 - uint8_t hid_data[61]; - uint8_t len = call_hid_read_params(0x9F, NULL, 0, hid_data, sizeof(hid_data)); - - if (len >= 5) { - // HID返回:[rate_0, rate_1, rate_2, rate_3, dsd_mode, ...] - uint32_t sample_rate = hid_data[0] | (hid_data[1] << 8) | (hid_data[2] << 16) | (hid_data[3] << 24); - uint8_t dsd_mode = hid_data[4]; - - // 构建UART响应 - response[0] = 0x55; - response[1] = 0xAA; - response[2] = 0x00; - response[3] = GET_SAMPLE_FORMAT; - response[4] = 0x05; - response[5] = hid_data[0]; - response[6] = hid_data[1]; - response[7] = hid_data[2]; - response[8] = hid_data[3]; - response[9] = dsd_mode; - - uint8_t checksum_pos = 10; - response[checksum_pos] = uart_checksum(response, checksum_pos); - - debug_printf("UART GET_SAMPLE_FORMAT: sample_rate=%d, dsd_mode=%d (from HID 0x9F)\n", sample_rate, dsd_mode); - return 11; - } - return 0; -} - -/** - * @brief 处理串口设置增益模式命令 (0x46) - * @note 改动原因:直接调用HID的process_send_params (0xA0),完全复用代码 - */ -uint8_t process_uart_set_gain_mode(uint8_t gain_mode) -{ - debug_printf("UART SET_GAIN_MODE: gain_mode=%d (calling HID 0xA0)\n", gain_mode); - return call_hid_send_params(0xA0, &gain_mode, 1) ? 0 : 1; -} - -/** - * @brief 处理串口获取增益模式命令 (0x47) - * @note 改动原因:直接调用HID的process_read_params (0xA1),完全复用代码 - */ -uint8_t process_uart_get_gain_mode(uint8_t *response, uint8_t response_size) -{ - if (response_size < 7) return 0; - - // 调用HID获取增益模式 - uint8_t hid_data[61]; - uint8_t len = call_hid_read_params(0xA1, NULL, 0, hid_data, sizeof(hid_data)); - - if (len > 0) { - uint8_t gain_mode = hid_data[0]; - - // 构建UART响应 - response[0] = 0x55; - response[1] = 0xAA; - response[2] = 0x00; - response[3] = GET_GAIN_MODE; - response[4] = 0x01; - response[5] = gain_mode; - - uint8_t checksum_pos = 6; - response[checksum_pos] = uart_checksum(response, checksum_pos); - - debug_printf("UART GET_GAIN_MODE: gain_mode=%d (from HID 0xA1)\n", gain_mode); - return 7; - } - return 0; -} - -/** - * @brief 处理串口设置滤波器模式命令 (0x48) - * @note 改动原因:直接调用HID的process_send_params (0xA2),完全复用代码 - */ -uint8_t process_uart_set_filter_mode(uint8_t filter_mode) -{ - debug_printf("UART SET_FILTER_MODE: filter_mode=%d (calling HID 0xA2)\n", filter_mode); - return call_hid_send_params(0xA2, &filter_mode, 1) ? 0 : 1; -} - -/** - * @brief 处理串口获取滤波器模式命令 (0x49) - * @note 改动原因:直接调用HID的process_read_params (0xA3),完全复用代码 - */ -uint8_t process_uart_get_filter_mode(uint8_t *response, uint8_t response_size) -{ - if (response_size < 7) return 0; - - // 调用HID获取滤波器模式 - uint8_t hid_data[61]; - uint8_t len = call_hid_read_params(0xA3, NULL, 0, hid_data, sizeof(hid_data)); - - if (len > 0) { - uint8_t filter_mode = hid_data[0]; - - // 构建UART响应 - response[0] = 0x55; - response[1] = 0xAA; - response[2] = 0x00; - response[3] = GET_FILTER_MODE; - response[4] = 0x01; - response[5] = filter_mode; - - uint8_t checksum_pos = 6; - response[checksum_pos] = uart_checksum(response, checksum_pos); - - debug_printf("UART GET_FILTER_MODE: filter_mode=%d (from HID 0xA3)\n", filter_mode); - return 7; - } - return 0; -} - -/** - * @brief 处理串口设置游戏模式命令 (0x5A) - * @param game_mode 游戏模式值 (0=无音效, 1=FPS, 2=虚拟7.1) - * @note 改动原因:UART 0x5A命令将游戏模式设置请求透传给MCU处理,MCU负责执行模式设置和参数保存 - */ -void process_uart_set_game_mode(uint8_t game_mode) -{ - debug_printf("UART SET_GAME_MODE (0x5A): game_mode=%d, forwarding to MCU\n", game_mode); - - // 参数验证 - if (game_mode > 2) { - debug_printf("Error: Invalid game_mode %d (must be 0-2)\n", game_mode); - return; - } - - // 改动原因:构建UART 0x5A数据包并透传给MCU - // UART数据包格式:0x55 0xAA 0x00 0x5A [长度] [游戏模式值] [校验和] - uint8_t uart_packet[7]; - uart_packet[0] = 0x55; // 帧头1 - uart_packet[1] = 0xAA; // 帧头2 - uart_packet[2] = 0x00; // 版本 - uart_packet[3] = 0x5A; // 命令码 (SET_GAME_MODE) - uart_packet[4] = 0x01; // 数据长度 - uart_packet[5] = game_mode; // 游戏模式值 - - // 计算校验和(帧头到数据末尾所有字节的累加和取低8位) - uint8_t checksum = 0; - for (int i = 0; i < 6; i++) { - checksum += uart_packet[i]; - } - uart_packet[6] = checksum; // 校验和 - - // 改动原因:通过xmos_printf将UART数据包透传给MCU - // 声明xmos_printf函数(在user_uart.xc中定义) - extern int xmos_printf(unsigned char *data, unsigned char len); - - // 发送UART数据包给MCU - int result = xmos_printf(uart_packet, 7); - if (result == 7) { - debug_printf("UART 0x5A packet forwarded to MCU successfully: game_mode=%d (0=无音效, 1=FPS, 2=虚拟7.1)\n", - game_mode); - } else { - debug_printf("Error: Failed to forward UART 0x5A packet to MCU (result=%d)\n", result); - } - - // 改动原因:MCU接收到0x5A命令后会处理游戏模式设置和参数保存,XMOS设备无需执行额外操作 -} - /** * @brief 处理串口获取游戏模式命令 (0x4B) * @note 改动原因:直接调用HID的process_read_params (0xA5),完全复用代码 diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.h index b9cf4a5..3370a89 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq.h @@ -7,15 +7,15 @@ #include #include -#define NUM_EQ_MODES 10 +#define NUM_EQ_MODES 15 #define NUM_EQ_CHANS 2 #define MAX_EQ_BANDS 8 -#define EQ_DISABLED_MODE 10 // 禁用EQ的模式编号 -#define EQ_PRESET_MODE_MIN 0 // 预设模式最小编号 -#define EQ_PRESET_MODE_MAX 6 // 预设模式最大编号(preset1-preset6) -#define EQ_USER_MODE_MIN 7 // 用户模式最小编号 -#define EQ_USER_MODE_MAX 9 // 用户模式最大编号(user 1-4) -#define EQ_MODE_MAX (NUM_EQ_MODES) // 模式最大编号(user 1-4) +#define EQ_DISABLED_MODE 15 // 禁用EQ的模式编号(改动原因:模式扩展至15后,禁用模式编号同步改为15) +#define EQ_PRESET_MODE_MIN 0 // 预设模式最小编号 +#define EQ_PRESET_MODE_MAX 12 // 预设模式最大编号(0-12共13个预设,含音乐与游戏曲线) +#define EQ_USER_MODE_MIN 13 // 用户模式最小编号(改动原因:仅保留2个用户自定义模式) +#define EQ_USER_MODE_MAX 14 // 用户模式最大编号(user 1-2) +#define EQ_MODE_MAX (NUM_EQ_MODES) // 有效模式上界(0-14为可用模式,15为禁用) // Filter type definition @@ -130,10 +130,6 @@ uint8_t process_uart_get_led_status(uint8_t led_index, uint8_t * unsafe response uint8_t process_uart_get_led_count(uint8_t * unsafe response, uint8_t response_size); uint8_t process_uart_get_uac_mode_info(uint8_t * unsafe response, uint8_t response_size); void process_uart_set_uac_mode(uint8_t uac_mode); -void process_uart_set_input_source(uint8_t input_source); // 设置输入源(0=USB,1=OPT,2=COAX),HID 0xB0透传MCU -void process_uart_set_mute_switch(uint8_t mute); // 设置静音开关(0=关,1=开),HID 0xB1透传MCU -void process_uart_set_listen_switch(uint8_t listen); // 设置监听开关(0=关,1=开),HID 0xB3透传MCU -void process_uart_send_get_mute_request(void); // 向MCU发送0x5F获取静音请求 uint8_t process_uart_get_current_uac_mode(uint8_t * unsafe response, uint8_t response_size); uint8_t process_uart_set_eq_enable(uint8_t enable); uint8_t process_uart_get_eq_enable_response(uint8_t result, uint8_t enable, uint8_t * unsafe response, uint8_t response_size); @@ -146,6 +142,11 @@ uint8_t process_uart_get_filter_mode(uint8_t * unsafe response, uint8_t response void process_uart_set_game_mode(uint8_t game_mode); uint8_t process_uart_get_game_mode(uint8_t * unsafe response, uint8_t response_size); uint8_t process_uart_get_firmware_version(uint8_t * unsafe response, uint8_t response_size); +/* 改动原因:添加 0xB0-0xB4 相关 UART 处理与静音值回传(XC 侧声明),HID 在 tile0、UART 在 tile1 时由 tile1 调用 */ +void process_uart_set_input_source(uint8_t input_source); +void process_uart_set_mute_switch(uint8_t mute); +void process_uart_send_get_mute_request(void); +void process_uart_set_listen_switch(uint8_t listen); #else // 独立的增益和名称设置/获取函数 @@ -171,10 +172,6 @@ uint8_t process_uart_get_led_status(uint8_t led_index, uint8_t *response, uint8_ uint8_t process_uart_get_led_count(uint8_t *response, uint8_t response_size); uint8_t process_uart_get_uac_mode_info(uint8_t *response, uint8_t response_size); void process_uart_set_uac_mode(uint8_t uac_mode); -void process_uart_set_input_source(uint8_t input_source); // 设置输入源(0=USB,1=OPT,2=COAX),HID 0xB0透传MCU -void process_uart_set_mute_switch(uint8_t mute); // 设置静音开关(0=关,1=开),HID 0xB1透传MCU -void process_uart_set_listen_switch(uint8_t listen); // 设置监听开关(0=关,1=开),HID 0xB3透传MCU -void process_uart_send_get_mute_request(void); // 向MCU发送0x5F获取静音请求 uint8_t process_uart_get_current_uac_mode(uint8_t *response, uint8_t response_size); uint8_t process_uart_set_eq_enable(uint8_t enable); uint8_t process_uart_get_eq_enable_response(uint8_t result, uint8_t enable, uint8_t *response, uint8_t response_size); @@ -187,7 +184,11 @@ uint8_t process_uart_get_filter_mode(uint8_t *response, uint8_t response_size); void process_uart_set_game_mode(uint8_t game_mode); uint8_t process_uart_get_game_mode(uint8_t *response, uint8_t response_size); uint8_t process_uart_get_firmware_version(uint8_t *response, uint8_t response_size); - +/* 改动原因:添加 0xB0-0xB4 相关 UART 处理与静音值回传(C 侧声明) */ +void process_uart_set_input_source(uint8_t input_source); +void process_uart_set_mute_switch(uint8_t mute); +void process_uart_send_get_mute_request(void); +void process_uart_set_listen_switch(uint8_t listen); #endif void init_mode_info(void); diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_designer_new.py b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_designer_new.py index a11178f..ca72aed 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_designer_new.py +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_designer_new.py @@ -53,10 +53,23 @@ from filter_utils import (BiquadFilterCalculator, make_biquad_bypass, make_biqua # 常量定义 MAX_EQ_BANDS = 8 # 最大EQ滤波器数量 (0-7) -NUM_EQ_MODES = 10 # EQ模式数量 -EQ_DISABLED_MODE = 10 # 禁用EQ的模式编号 +NUM_EQ_MODES = 15 # EQ模式数量(改动原因:13预设+2用户,共15模式) +EQ_DISABLED_MODE = 15 # 禁用EQ的模式编号(改动原因:与NUM_EQ_MODES对齐) +# 预设模式0-12,用户模式13-14 +EQ_PRESET_MODE_MAX = 12 +EQ_USER_MODE_MIN = 13 +EQ_USER_MODE_MAX = 14 -# HID 固件升级命令码(使用命令名代替裸命令码) +# 模式下拉列表显示名称(改动原因:与固件default_names及新增游戏曲线一致) +MODE_COMBO_ITEMS = [ + "JAZZ(0)", "POP(1)", "ROCK(2)", "CLASIC(3)", + "暗区突围(4)", "3A Game(5)", "战地6(6)", + "APEX(7)", "和平精英(8)", "逃离塔科夫(9)", + "穿越火线(10)", "守望先锋(11)", "永劫无望(12)", + "用户模式1(13)", "用户模式2(14)", "禁用EQ" +] + +# HID 固件升级命令码(与 eq_hid_protocol_ds1 一致,0xA7-0xAE) FIRMWARE_UPGRADE_START = 0xA7 # 开始固件升级 FIRMWARE_UPGRADE_DATA = 0xA8 # 传输固件数据块 FIRMWARE_UPGRADE_END = 0xA9 # 结束固件升级 @@ -65,6 +78,20 @@ FIRMWARE_UPGRADE_ABORT = 0xAB # 中止固件升级 FIRMWARE_UPGRADE_ERASE = 0xAC # 擦除现有升级镜像 DEVICE_REBOOT = 0xAE # 设备重启(通用命令) +# FPS XMOS 命令(改动原因:0xA7/0xA8 保留固件升级;game/level 放在 DRC 0xBD/0xBE 之后为 0xBF/0xC0) +SET_FPS_XMOS_GAME_SELECT = 0xBF +GET_FPS_XMOS_GAME_SELECT = 0xC0 +SET_FPS_MODULE_ENABLE = 0xB5 +GET_FPS_MODULE_ENABLE = 0xB6 +SET_FPS_EQ_MODE = 0xB7 +GET_FPS_EQ_MODE = 0xB8 +SET_FPS_EQ_BAND_GAIN = 0xB9 +GET_FPS_EQ_BAND_GAIN = 0xBA +SET_FPS_EQ_MODE_NAME = 0xBB +GET_FPS_EQ_MODE_NAME = 0xBC +SET_FPS_DRC_MODE = 0xBD +GET_FPS_DRC_MODE = 0xBE + class BandFilter(QGroupBox): """单个滤波器带控件""" def __init__(self, band_id, parent=None): @@ -536,7 +563,7 @@ class EQDesigner(QMainWindow): mode_layout = QFormLayout(mode_group) self.mode_label = QLabel("音效模式:") self.mode_combo = QComboBox() - self.mode_combo.addItems(["预设模式1", "预设模式2", "预设模式3", "预设模式4", "预设模式5", "预设模式6", "用户模式1", "用户模式2", "用户模式3", "bypass", "禁用EQ"]) + self.mode_combo.addItems(MODE_COMBO_ITEMS) self.mode_combo.currentIndexChanged.connect(self.on_mode_changed) mode_layout.addRow(self.mode_label, self.mode_combo) @@ -912,6 +939,129 @@ class EQDesigner(QMainWindow): listen_switch_layout.addRow(listen_switch_btn_layout) left_content_layout.addWidget(listen_switch_group) + # FPS XMOS 算法控制(HID 0xBF/0xC0 游戏档位,0xB5/0xB6 三子模块使能) + fps_xmos_group = QGroupBox("FPS算法控制") + self.ui_groups['fps_xmos'] = fps_xmos_group + fps_xmos_layout = QFormLayout(fps_xmos_group) + + fps_game_layout = QHBoxLayout() + self.fps_xmos_game_combo = QComboBox() + self.fps_xmos_game_combo.addItem("CS2 (0)", 0) + self.fps_xmos_game_combo.addItem("PUBG (1)", 1) + self.fps_xmos_game_combo.addItem("DELTA (2)", 2) + fps_game_layout.addWidget(QLabel("游戏类型:")) + fps_game_layout.addWidget(self.fps_xmos_game_combo) + fps_xmos_layout.addRow(fps_game_layout) + + fps_level_layout = QHBoxLayout() + # 改动原因:与固件默认增益档位一致,默认 level=2 + self.fps_xmos_level_spin = QSpinBox() + self.fps_xmos_level_spin.setRange(0, 4) + self.fps_xmos_level_spin.setValue(2) + fps_level_layout.addWidget(QLabel("增益档位(0-4):")) + fps_level_layout.addWidget(self.fps_xmos_level_spin) + fps_xmos_layout.addRow(fps_level_layout) + + fps_game_btn_layout = QHBoxLayout() + self.set_fps_xmos_game_btn = QPushButton("设置游戏/档位 (0xBF)") + self.set_fps_xmos_game_btn.clicked.connect(self.on_set_fps_xmos_game_select) + self.get_fps_xmos_game_btn = QPushButton("查询档位 (0xC0)") + self.get_fps_xmos_game_btn.clicked.connect(self.on_get_fps_xmos_game_select) + fps_game_btn_layout.addWidget(self.set_fps_xmos_game_btn) + fps_game_btn_layout.addWidget(self.get_fps_xmos_game_btn) + fps_xmos_layout.addRow(fps_game_btn_layout) + + self.fps_xmos_game_status_label = QLabel("游戏档位: 未查询") + fps_xmos_layout.addRow("状态:", self.fps_xmos_game_status_label) + + # 改动原因:与固件默认一致——FPS 主处理开,DRC/fps_eq 关 + self.fps_drc_enable_combo = QComboBox() + self.fps_drc_enable_combo.addItems(["关 (0)", "开 (1)"]) + self.fps_drc_enable_combo.setCurrentIndex(0) + fps_xmos_layout.addRow("DRC:", self.fps_drc_enable_combo) + + self.fps_sub_enable_combo = QComboBox() + self.fps_sub_enable_combo.addItems(["关 (0)", "开 (1)"]) + self.fps_sub_enable_combo.setCurrentIndex(1) + fps_xmos_layout.addRow("FPS主处理:", self.fps_sub_enable_combo) + + self.fps_eq_enable_combo = QComboBox() + self.fps_eq_enable_combo.addItems(["关 (0)", "开 (1)"]) + self.fps_eq_enable_combo.setCurrentIndex(0) + fps_xmos_layout.addRow("fps_eq:", self.fps_eq_enable_combo) + + fps_module_btn_layout = QHBoxLayout() + self.set_fps_module_enable_btn = QPushButton("设置使能 (0xB5)") + self.set_fps_module_enable_btn.clicked.connect(self.on_set_fps_module_enable) + self.get_fps_module_enable_btn = QPushButton("读取使能 (0xB6)") + self.get_fps_module_enable_btn.clicked.connect(self.on_get_fps_module_enable) + fps_module_btn_layout.addWidget(self.set_fps_module_enable_btn) + fps_module_btn_layout.addWidget(self.get_fps_module_enable_btn) + fps_xmos_layout.addRow(fps_module_btn_layout) + + # 改动原因:DRC压缩模式与DRC使能独立,HID 0xBD/0xBE,默认0=low柔和压缩 + self.fps_drc_mode_combo = QComboBox() + self.fps_drc_mode_combo.addItem("low 柔和压缩 (0)", 0) + self.fps_drc_mode_combo.addItem("high 强力压缩 (1)", 1) + self.fps_drc_mode_combo.setCurrentIndex(0) + fps_xmos_layout.addRow("DRC压缩模式:", self.fps_drc_mode_combo) + fps_drc_mode_btn_layout = QHBoxLayout() + self.set_fps_drc_mode_btn = QPushButton("设置DRC模式 (0xBD)") + self.set_fps_drc_mode_btn.clicked.connect(self.on_set_fps_drc_mode) + self.get_fps_drc_mode_btn = QPushButton("读取DRC模式 (0xBE)") + self.get_fps_drc_mode_btn.clicked.connect(self.on_get_fps_drc_mode) + fps_drc_mode_btn_layout.addWidget(self.set_fps_drc_mode_btn) + fps_drc_mode_btn_layout.addWidget(self.get_fps_drc_mode_btn) + fps_xmos_layout.addRow(fps_drc_mode_btn_layout) + + self.fps_eq_mode_spin = QSpinBox() + self.fps_eq_mode_spin.setRange(0, 4) + self.fps_eq_mode_spin.setValue(0) + fps_xmos_layout.addRow("fps_eq模式(0-4):", self.fps_eq_mode_spin) + fps_eq_mode_btn = QHBoxLayout() + self.set_fps_eq_mode_btn = QPushButton("设置模式 (0xB7)") + self.set_fps_eq_mode_btn.clicked.connect(self.on_set_fps_eq_mode) + self.get_fps_eq_mode_btn = QPushButton("读取模式 (0xB8)") + self.get_fps_eq_mode_btn.clicked.connect(self.on_get_fps_eq_mode) + fps_eq_mode_btn.addWidget(self.set_fps_eq_mode_btn) + fps_eq_mode_btn.addWidget(self.get_fps_eq_mode_btn) + fps_xmos_layout.addRow(fps_eq_mode_btn) + + fps_name_layout = QHBoxLayout() + self.fps_eq_mode_name_edit = QLineEdit() + self.fps_eq_mode_name_edit.setPlaceholderText("模式名称(最多15字符)") + fps_name_layout.addWidget(self.fps_eq_mode_name_edit) + self.set_fps_eq_mode_name_btn = QPushButton("设置名称 (0xBB)") + self.set_fps_eq_mode_name_btn.clicked.connect(self.on_set_fps_eq_mode_name) + self.get_fps_eq_mode_name_btn = QPushButton("读取名称 (0xBC)") + self.get_fps_eq_mode_name_btn.clicked.connect(self.on_get_fps_eq_mode_name) + fps_name_layout.addWidget(self.set_fps_eq_mode_name_btn) + fps_name_layout.addWidget(self.get_fps_eq_mode_name_btn) + fps_xmos_layout.addRow("fps_eq模式名:", fps_name_layout) + + fps_band_layout = QHBoxLayout() + self.fps_eq_band_spin = QSpinBox() + self.fps_eq_band_spin.setRange(0, 9) + self.fps_eq_gain_spin = QSpinBox() + self.fps_eq_gain_spin.setRange(-600, 600) + self.fps_eq_gain_spin.setValue(1) + fps_band_layout.addWidget(QLabel("频段:")) + fps_band_layout.addWidget(self.fps_eq_band_spin) + fps_band_layout.addWidget(QLabel("增益(0.01dB):")) + fps_band_layout.addWidget(self.fps_eq_gain_spin) + fps_xmos_layout.addRow(fps_band_layout) + + fps_band_btn = QHBoxLayout() + self.set_fps_eq_band_btn = QPushButton("设置频段 (0xB9)") + self.set_fps_eq_band_btn.clicked.connect(self.on_set_fps_eq_band_gain) + self.get_fps_eq_band_btn = QPushButton("读取频段 (0xBA)") + self.get_fps_eq_band_btn.clicked.connect(self.on_get_fps_eq_band_gain) + fps_band_btn.addWidget(self.set_fps_eq_band_btn) + fps_band_btn.addWidget(self.get_fps_eq_band_btn) + fps_xmos_layout.addRow(fps_band_btn) + + left_content_layout.addWidget(fps_xmos_group) + # 添加EQ使能控制组 eq_enable_group = QGroupBox("EQ使能控制") self.ui_groups['eq_enable'] = eq_enable_group # 保存引用 @@ -1097,6 +1247,7 @@ class EQDesigner(QMainWindow): 'input_source': '输入源控制', 'mute_switch': '静音开关', 'listen_switch': '监听开关', + 'fps_xmos': 'FPS算法控制', 'eq_enable': 'EQ使能控制', 'firmware': '固件升级', 'dfs': '动态降频' @@ -1131,6 +1282,7 @@ class EQDesigner(QMainWindow): 'input_source': '输入源控制', 'mute_switch': '静音开关', 'listen_switch': '监听开关', + 'fps_xmos': 'FPS算法控制', 'eq_enable': 'EQ使能控制', 'firmware': '固件升级' } @@ -1804,7 +1956,11 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{ fs = 48000 log_message(LOG_LEVEL_DEBUG, f" 图像显示采样率: {fs} Hz", self.log_level) - mode = self.current_mode + # 改动原因:读取参数时以UI当前选择模式为准,避免self.current_mode被异步查询结果覆盖后读取到错误模式。 + requested_mode = self.mode_combo.currentIndex() + if requested_mode == NUM_EQ_MODES: + requested_mode = EQ_DISABLED_MODE + mode = requested_mode # 读取所有MAX_EQ_BANDS个EQ参数 for eq_index in range(MAX_EQ_BANDS): @@ -1839,9 +1995,15 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{ log_message(LOG_LEVEL_ERROR, f"错误: 无效的响应同步头: 0x{reply[1]:02x} 0x{reply[2]:02x}", self.log_level) continue - # 模式值 - mode = reply[3] - log_message(LOG_LEVEL_DEBUG, f" 模式值: {mode}", self.log_level) + # 模式值(设备回包) + resp_mode = reply[3] + log_message(LOG_LEVEL_DEBUG, f" 模式值: {resp_mode}", self.log_level) + if resp_mode != requested_mode: + log_message( + LOG_LEVEL_WARN, + f" 警告: 请求模式={requested_mode}, 回包模式={resp_mode},后续仍按请求模式继续读取", + self.log_level + ) # EQ索引 eq_idx = reply[4] @@ -1882,7 +2044,9 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{ log_message(LOG_LEVEL_DEBUG, f" 带宽: {bw:.2f} Hz", self.log_level) # 增益 (4字节) - 位置18-21 - gain = struct.unpack('= 0: + self.fps_xmos_game_combo.setCurrentIndex(idx) + if resp_level <= 4: + self.fps_xmos_level_spin.setValue(resp_level) + QMessageBox.information(self, "FPS 游戏档位", + f"game={resp_game}, level={resp_level}") + else: + log_message(LOG_LEVEL_ERROR, "未收到有效的 0xC0 响应", self.log_level) + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"查询 FPS 游戏档位时出错: {str(e)}", self.log_level) + + def on_set_fps_module_enable(self): + """设置 FPS 库 DRC / FPS主处理 / fps_eq 使能(HID 0xB5)""" + if self.device_combo.currentData() is None: + log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level) + return + drc = self.fps_drc_enable_combo.currentIndex() + fps_sub = self.fps_sub_enable_combo.currentIndex() + eq_en = self.fps_eq_enable_combo.currentIndex() + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = SET_FPS_MODULE_ENABLE + data[2] = drc + data[3] = fps_sub + data[4] = eq_en + log_message(LOG_LEVEL_INFO, + f"设置 FPS 模块使能: DRC={drc}, FPS={fps_sub}, EQ={eq_en} (HID 0xB5)...", + self.log_level) + h.write([0x01] + list(data)) + + log_message(LOG_LEVEL_DEBUG, "发送的数据:", self.log_level) + log_message(LOG_LEVEL_DEBUG, " ".join(f"0x{byte:02x}" for byte in ([0x01] + list[int](data))), self.log_level) + QMessageBox.information(self, "已发送", + f"DRC={drc}, FPS主处理={fps_sub}, fps_eq={eq_en}\n(0=关, 1=开)") + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"设置 FPS 模块使能时出错: {str(e)}", self.log_level) + + def on_get_fps_module_enable(self): + """读取 FPS 库三模块使能(HID 0xB6)""" + if self.device_combo.currentData() is None: + log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level) + return + try: + import time + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = GET_FPS_MODULE_ENABLE + log_message(LOG_LEVEL_INFO, "读取 FPS 模块使能 (HID 0xB6)...", self.log_level) + h.write([0x01] + list(data)) + time.sleep(0.05) + reply = h.get_input_report(0x01, 64) + if (reply and len(reply) == 64 and reply[0] == 0x01 + and reply[1] == 0x77 and reply[2] == GET_FPS_MODULE_ENABLE): + drc = reply[3] + fps_sub = reply[4] + eq_en = reply[5] + self.fps_drc_enable_combo.setCurrentIndex(1 if drc else 0) + self.fps_sub_enable_combo.setCurrentIndex(1 if fps_sub else 0) + self.fps_eq_enable_combo.setCurrentIndex(1 if eq_en else 0) + log_message(LOG_LEVEL_DEBUG, "读取到的响应数据:", self.log_level) + log_message(LOG_LEVEL_DEBUG, " ".join(f"0x{byte:02x}" for byte in reply), self.log_level) + log_message(LOG_LEVEL_INFO, + f"FPS 模块使能: DRC={drc}, FPS={fps_sub}, EQ={eq_en}", + self.log_level) + QMessageBox.information(self, "FPS 模块使能", + f"DRC={drc}\nFPS主处理={fps_sub}\nfps_eq={eq_en}\n(0=关, 1=开)") + else: + log_message(LOG_LEVEL_ERROR, "未收到有效的 0xB6 响应", self.log_level) + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"读取 FPS 模块使能时出错: {str(e)}", self.log_level) + + def on_set_fps_drc_mode(self): + """设置 DRC 压缩模式(HID 0xBD):0=low柔和,1=high强力""" + if self.device_combo.currentData() is None: + log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level) + return + mode = self.fps_drc_mode_combo.currentData() + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = SET_FPS_DRC_MODE + data[2] = mode + mode_name = self.fps_drc_mode_combo.currentText() + log_message(LOG_LEVEL_INFO, + f"设置 DRC 压缩模式: {mode_name} (HID 0xBD)...", + self.log_level) + h.write([0x01] + list(data)) + QMessageBox.information(self, "已发送", f"DRC模式={mode}\n(0=low, 1=high)") + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"设置 DRC 压缩模式时出错: {str(e)}", self.log_level) + + def on_get_fps_drc_mode(self): + """读取 DRC 压缩模式(HID 0xBE)""" + if self.device_combo.currentData() is None: + log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level) + return + try: + import time + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = GET_FPS_DRC_MODE + log_message(LOG_LEVEL_INFO, "读取 DRC 压缩模式 (HID 0xBE)...", self.log_level) + h.write([0x01] + list(data)) + time.sleep(0.05) + reply = h.get_input_report(0x01, 64) + if (reply and len(reply) == 64 and reply[0] == 0x01 + and reply[1] == 0x77 and reply[2] == GET_FPS_DRC_MODE): + mode = reply[3] + idx = self.fps_drc_mode_combo.findData(mode) + if idx >= 0: + self.fps_drc_mode_combo.setCurrentIndex(idx) + log_message(LOG_LEVEL_INFO, f"DRC 压缩模式: {mode} (0=low, 1=high)", self.log_level) + QMessageBox.information(self, "DRC 压缩模式", f"mode={mode}\n(0=low, 1=high)") + else: + log_message(LOG_LEVEL_ERROR, "未收到有效的 0xBE 响应", self.log_level) + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"读取 DRC 压缩模式时出错: {str(e)}", self.log_level) + + def on_set_fps_eq_mode(self): + """设置 fps_eq 预设模式 0-4(HID 0xB7)""" + if self.device_combo.currentData() is None: + return + mode = self.fps_eq_mode_spin.value() + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + data = bytearray(63) + data[0] = 0x77 + data[1] = SET_FPS_EQ_MODE + data[2] = mode + h.write([0x01] + list(data)) + h.close() + QMessageBox.information(self, "已发送", f"fps_eq 模式已设为 {mode}") + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"设置 fps_eq 模式失败: {e}", self.log_level) + + def on_get_fps_eq_mode(self): + """读取 fps_eq 当前模式(HID 0xB8)""" + if self.device_combo.currentData() is None: + return + try: + import time + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = GET_FPS_EQ_MODE + h.write([0x01] + list(data)) + time.sleep(0.05) + reply = h.get_input_report(0x01, 64) + if (reply and len(reply) >= 4 and reply[0] == 0x01 + and reply[1] == 0x77 and reply[2] == GET_FPS_EQ_MODE): + mode = reply[3] + self.fps_eq_mode_spin.setValue(mode) + QMessageBox.information(self, "fps_eq 模式", f"当前模式: {mode}") + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"读取 fps_eq 模式失败: {e}", self.log_level) + + def on_set_fps_eq_mode_name(self): + """设置 fps_eq 模式名称(HID 0xBB)""" + if self.device_combo.currentData() is None: + return + mode = self.fps_eq_mode_spin.value() + mode_name = self.fps_eq_mode_name_edit.text().strip() + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + data = bytearray(63) + data[0] = 0x77 + data[1] = SET_FPS_EQ_MODE_NAME + data[2] = mode + encoded = mode_name.encode('utf-8', errors='ignore')[:15] + data[3:3 + len(encoded)] = encoded + data[3 + len(encoded)] = 0x00 + h.write([0x01] + list(data)) + h.close() + QMessageBox.information(self, "已发送", f"模式{mode} 名称已设置为: {mode_name}") + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"设置 fps_eq 模式名失败: {e}", self.log_level) + + def on_get_fps_eq_mode_name(self): + """读取 fps_eq 模式名称(HID 0xBC)""" + if self.device_combo.currentData() is None: + return + mode = self.fps_eq_mode_spin.value() + try: + import time + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = GET_FPS_EQ_MODE_NAME + data[2] = mode + h.write([0x01] + list(data)) + time.sleep(0.05) + reply = h.get_input_report(0x01, 64) + log_message(LOG_LEVEL_DEBUG, f"0xBC响应原始数据: {' '.join(f'0x{byte:02x}' for byte in reply[:16])}", self.log_level) + if (reply and len(reply) >= 20 and reply[0] == 0x01 + and reply[1] == 0x77 and reply[2] == GET_FPS_EQ_MODE_NAME): + resp_mode = reply[3] + raw_name = bytes(reply[4:20]).split(b'\x00', 1)[0] + log_message(LOG_LEVEL_DEBUG, f"raw_name: {raw_name}", self.log_level) + mode_name = raw_name.decode('utf-8', errors='ignore') + self.fps_eq_mode_spin.setValue(resp_mode if resp_mode <= 4 else 0) + self.fps_eq_mode_name_edit.setText(mode_name) + QMessageBox.information(self, "fps_eq 模式名", f"模式{resp_mode} 名称: {mode_name}") + h.close() + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"读取 fps_eq 模式名失败: {e}", self.log_level) + + def on_set_fps_eq_band_gain(self): + """设置当前模式单段增益(HID 0xB9)""" + if self.device_combo.currentData() is None: + return + band = self.fps_eq_band_spin.value() + gain = self.fps_eq_gain_spin.value() + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + data = bytearray(63) + data[0] = 0x77 + data[1] = SET_FPS_EQ_BAND_GAIN + data[2] = band + data[3] = gain & 0xFF + data[4] = (gain >> 8) & 0xFF + h.write([0x01] + list(data)) + h.close() + QMessageBox.information(self, "已发送", f"band={band}, gain={gain} (0.01dB)") + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"设置 fps_eq 频段失败: {e}", self.log_level) + + def on_get_fps_eq_band_gain(self): + """读取当前模式单段增益(HID 0xBA)""" + if self.device_combo.currentData() is None: + return + band = self.fps_eq_band_spin.value() + try: + import time + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + data = bytearray(63) + data[0] = 0x77 + data[1] = GET_FPS_EQ_BAND_GAIN + data[2] = band + h.write([0x01] + list(data)) + time.sleep(0.05) + reply = h.get_input_report(0x01, 64) + # 改动原因:64字节含ReportID[0]=0x01,协议载荷从[1]起:77 BA band gain_lo gain_hi + if (reply and len(reply) >= 6 and reply[0] == 0x01 + and reply[1] == 0x77 and reply[2] == GET_FPS_EQ_BAND_GAIN): + resp_band = reply[3] + gain = struct.unpack(' 0) { DPRINTF(" Saved %d dirty single parameters\n", saved_count); } + lfs_deinit(); return 0; } /** @@ -877,14 +897,23 @@ int eq_save_dirty_gain(void) { return 0; } + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // audiohw.xc直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_save_dirty_gain\n"); + return -1; + } + DPRINTF(" Saving dirty gain\n"); // 使用新的独立保存函数 if (eq_save_gain() == 0) { gain_dirty = 0; // 只清除增益脏标志 DPRINTF(" Successfully saved gain\n"); + lfs_deinit(); return 0; } else { DPRINTF(" Error: Failed to save gain\n"); + lfs_deinit(); return -1; } } @@ -904,6 +933,13 @@ int eq_save_dirty_names(void) { return 0; } + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // audiohw.xc直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_save_dirty_names\n"); + return -1; + } + DPRINTF(" Saving dirty mode names\n"); // 使用新的独立保存函数,逐个保存每个用户模式的name int saved_count = 0; @@ -923,12 +959,15 @@ int eq_save_dirty_names(void) { if (saved_count > 0) { DPRINTF(" Successfully saved %d mode name(s), skipped %d\n", saved_count, skipped_count); + lfs_deinit(); return 0; } else if (skipped_count > 0) { DPRINTF(" All mode names skipped (same as default or empty), %d skipped\n", skipped_count); + lfs_deinit(); return 0; // 跳过是正常的,不算错误 } else { DPRINTF(" Error: Failed to save mode names\n"); + lfs_deinit(); return -1; } } @@ -1081,6 +1120,13 @@ int eq_save_name(uint8_t mode) { int eq_save_gain_and_names(void) { int ret = 0; + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // 此函数为公共API,调用了eq_save_gain和eq_save_name(均直接操作Flash),必须提供会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_save_gain_and_names\n"); + return -1; + } + // 保存gain if (eq_save_gain() != 0) { ret = -1; @@ -1095,6 +1141,7 @@ int eq_save_gain_and_names(void) { // result == 1 表示跳过,这是正常的 } + lfs_deinit(); return ret; } @@ -1260,6 +1307,13 @@ int eq_load_name(uint8_t mode) { int eq_load_gain_and_names(void) { int ret = 0; + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // dsp_core0.xc在eq_flash_init()完成(释放锁)后直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_load_gain_and_names\n"); + return -1; + } + // 加载gain if (eq_load_gain() != 0) { ret = -1; // 文件不存在是正常的,使用默认值 @@ -1273,6 +1327,7 @@ int eq_load_gain_and_names(void) { } DPRINTF("Successfully loaded gain and mode names\n"); + lfs_deinit(); return ret; } @@ -1300,7 +1355,14 @@ int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t DPRINTF(" Error: Failed to get EQ array for sample rate %u\n", sample_rate); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // dsp_core0.xc在eq_flash_init()完成后直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_load_all_params_and_calculate_coefficients\n"); + return -1; + } + int loaded_count = 0; // 简化加载逻辑:只从44100Hz channel 0加载参数,然后应用到所有采样率和通道 @@ -1313,7 +1375,8 @@ int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t //DPRINTF(" Loaded %d single parameters and calculated coefficients for mode %d\n", // loaded_count, mode); - + + lfs_deinit(); return 0; } @@ -1367,7 +1430,14 @@ int eq_flash_save_mode(uint8_t mode) { DPRINTF(" Error: Failed to get EQ array for current sample rate %lu\n", (unsigned long)g_eq_sample_rate); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // 此前该函数直接调用lfs_write_config而无会话保护,多core同时访问会导致数据损坏。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_flash_save_mode\n"); + return -1; + } + // 保存左右两个声道的数据 for (int ch = 0; ch < NUM_EQ_CHANS; ch++) { // 构建文件路径 @@ -1421,7 +1491,8 @@ int eq_flash_save_mode(uint8_t mode) { #endif DPRINTF(" Successfully saved EQ parameters for mode %d, channel %d\n", mode, ch); } - + + lfs_deinit(); return 0; } @@ -1604,7 +1675,14 @@ int delete_flash_eq_params(uint8_t mode) { DPRINTF(" Error: Flash storage not initialized\n"); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // eq.c的reset_eq_params()直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in delete_flash_eq_params\n"); + return -1; + } + int deleted_count = 0; if (mode == 0xFF) { @@ -1646,6 +1724,7 @@ int delete_flash_eq_params(uint8_t mode) { } DPRINTF(" Deleted %d parameter files\n", deleted_count); + lfs_deinit(); return 0; } @@ -1656,7 +1735,7 @@ int delete_flash_eq_params(uint8_t mode) { * * 改动原因:修改为按模式删除,只删除指定模式的增益和名称,而不是删除所有文件 * - 如果mode == 0xFF,删除所有用户模式的增益和名称文件 - * - 如果mode是用户模式(6-8),只删除该模式的名称文件,并将该模式的增益恢复为默认值(0) + * - 如果mode是用户模式(13-14),只删除该模式的名称文件,并将该模式的增益恢复为默认值(0) * - 如果mode是预设模式(0-5),不需要删除(预设模式的增益和名称不存储在Flash中) */ int delete_flash_gain_and_names(uint8_t mode) { @@ -1666,7 +1745,14 @@ int delete_flash_gain_and_names(uint8_t mode) { DPRINTF(" Error: Flash storage not initialized\n"); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // eq.c的reset_eq_params()直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in delete_flash_gain_and_names\n"); + return -1; + } + // 处理删除所有模式的情况 if (mode == 0xFF) { DPRINTF(" Deleting all user mode gains and names\n"); @@ -1693,23 +1779,26 @@ int delete_flash_gain_and_names(uint8_t mode) { } } } - + + lfs_deinit(); return 0; } // 检查模式有效性 if (mode >= NUM_EQ_MODES) { DPRINTF(" Error: Invalid mode %d\n", mode); + lfs_deinit(); return -1; } // 预设模式(0-5)的增益和名称不存储在Flash中,不需要删除 if (mode < EQ_USER_MODE_MIN) { DPRINTF(" Mode %d is a preset mode, no Flash data to delete\n", mode); + lfs_deinit(); return 0; } - // 只处理用户模式(6-8) + // 只处理用户模式(13-14) if (mode >= EQ_USER_MODE_MIN && mode <= EQ_USER_MODE_MAX) { // 删除该模式的名称文件 char file_path[FILE_PATH_MAX_LENGTH]; @@ -1763,12 +1852,14 @@ int delete_flash_gain_and_names(uint8_t mode) { } else { DPRINTF(" Gains file does not exist: %s\n", file_path); } - + + lfs_deinit(); return 0; } // 其他模式(如模式9)不需要处理 DPRINTF(" Mode %d does not require Flash data deletion\n", mode); + lfs_deinit(); return 0; } @@ -1864,7 +1955,14 @@ int eq_flash_save_eq_enable(uint8_t enable) DPRINTF(" Error: Invalid EQ enable value %d (valid range: 0-1)\n", enable); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // 此前该函数直接调用lfs_write_config而无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_flash_save_eq_enable\n"); + return -1; + } + // 构建独立文件路径 // 改动原因:使用独立的文件名存储eq_enable,与模式存储完全分离 char file_path[FILE_PATH_MAX_LENGTH]; @@ -1891,6 +1989,7 @@ int eq_flash_save_eq_enable(uint8_t enable) // 写入文件 lfs_write_config(file_path, file_data, sizeof(file_data)); DPRINTF(" Successfully saved EQ enable %d to Flash (independent file: %s)\n", enable, file_path); + lfs_deinit(); return 0; } @@ -1911,11 +2010,19 @@ int eq_flash_save_current_mode(uint8_t mode) } // 验证模式值范围 - if (mode > 9) { - DPRINTF(" Error: Invalid mode %d (valid range: 0-9)\n", mode); + // 改动原因:EQ模式数量扩展到15,允许保存模式范围0-14。 + if (mode >= NUM_EQ_MODES) { + DPRINTF(" Error: Invalid mode %d (valid range: 0-%d)\n", mode, NUM_EQ_MODES - 1); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥, + // 防止多core并发访问导致数据损坏。此前该函数直接调用lfs_write_config而无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_flash_save_current_mode\n"); + return -1; + } + // 构建独立文件路径 // 改动原因:使用独立的文件名存储模式,与eq_enable存储完全分离 char file_path[FILE_PATH_MAX_LENGTH]; @@ -1942,6 +2049,7 @@ int eq_flash_save_current_mode(uint8_t mode) // 写入文件 lfs_write_config(file_path, file_data, sizeof(file_data)); DPRINTF(" Successfully saved EQ mode %d to Flash (independent file: %s)\n", mode, file_path); + lfs_deinit(); return 0; } @@ -1961,10 +2069,17 @@ int eq_flash_load_current_mode(void) DPRINTF(" Error: Flash storage not initialized\n"); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // dsp_core0.xc在eq_flash_init()完成后直接调用此函数,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_flash_load_current_mode\n"); + return -1; + } + // 加载模式(从独立文件) char mode_file_path[FILE_PATH_MAX_LENGTH]; - snprintf(mode_file_path, sizeof(mode_file_path), "%s", g_eq_flash_mode_file); + snprintf(mode_file_path, sizeof(mode_file_path), "%s/%s", g_eq_flash_base_dir, g_eq_flash_mode_file); if (lfs_file_exists(mode_file_path)) { eq_file_header_t header; @@ -1976,7 +2091,8 @@ int eq_flash_load_current_mode(void) mode = file_header_data[sizeof(header)]; // 验证模式值范围 - if (mode > 9) { + // 改动原因:EQ模式数量扩展到15,加载时按NUM_EQ_MODES校验范围(0-14)。 + if (mode >= NUM_EQ_MODES) { DPRINTF(" Error: Invalid mode value %d in file\n", mode); mode = 0; // 使用默认值 } else { @@ -2001,7 +2117,7 @@ int eq_flash_load_current_mode(void) // 加载使能状态(从独立文件) char enable_file_path[FILE_PATH_MAX_LENGTH]; - snprintf(enable_file_path, sizeof(enable_file_path), "%s", g_eq_flash_enable_file); + snprintf(enable_file_path, sizeof(enable_file_path), "%s/%s", g_eq_flash_base_dir, g_eq_flash_enable_file); if (lfs_file_exists(enable_file_path)) { eq_file_header_t header; @@ -2041,6 +2157,7 @@ int eq_flash_load_current_mode(void) g_eq_enable = eq_enable; DPRINTF(" Successfully loaded mode %d and EQ enable %d from Flash (independent files)\n", mode, eq_enable); + lfs_deinit(); return mode; } @@ -2059,7 +2176,14 @@ int eq_flash_load_eq_enable(void) DPRINTF(" Error: Flash storage not initialized\n"); return -1; } - + + // 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。 + // 此函数为公共API,直接进行Flash读操作,此前无会话保护。 + if (lfs_init() != 0) { + DPRINTF(" Error: Failed to open flash session in eq_flash_load_eq_enable\n"); + return -1; + } + // 加载使能状态(从独立文件) char enable_file_path[FILE_PATH_MAX_LENGTH]; snprintf(enable_file_path, sizeof(enable_file_path), "%s", g_eq_flash_enable_file); @@ -2102,6 +2226,7 @@ int eq_flash_load_eq_enable(void) g_eq_enable = eq_enable; DPRINTF(" Successfully loaded EQ enable %d from Flash (independent file)\n", eq_enable); + lfs_deinit(); return eq_enable; } diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_flash_storage.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_flash_storage.h index 1d7838e..59e20f3 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_flash_storage.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_flash_storage.h @@ -10,7 +10,7 @@ #define EQ_FLASH_MAGIC_PARAMS 0x45515041 // "EQPA" - EQ参数文件魔数 #define EQ_FLASH_VERSION 0x00020000 // 版本2.0.0 - 优化存储格式 #define EQ_FLASH_MAX_SAMPLE_RATES 6 // 支持的采样率数量 -#define EQ_FLASH_MAX_MODES 10 // 最大模式数量 +#define EQ_FLASH_MAX_MODES 15 // 最大模式数量(改动原因:EQ模式扩展至15) #define EQ_FLASH_MAX_CHANNELS 2 // 最大通道数量 // 支持的采样率列表 @@ -46,9 +46,9 @@ typedef struct { uint32_t crc32; // CRC32校验 } __attribute__((packed)) eq_gain_header_t; -// 模式增益数据(只存储用户模式6-8) +// 模式增益数据(只存储用户模式13-14) typedef struct { - int32_t mode_gains[3]; // 用户模式增益数组:mode 6, 7, 8,每个4字节 + int32_t mode_gains[2]; // 用户模式增益数组:mode 13, 14,每个4字节(改动原因:用户模式由3个减为2个) } __attribute__((packed)) eq_gain_data_t; // 单个模式名称存储结构 diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_hid_protocol.md b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_hid_protocol.md index 43cf461..544cb09 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_hid_protocol.md +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_hid_protocol.md @@ -16,7 +16,7 @@ | 0x8F | GET_DEVICE_INFO | 获取设备信息 | 主机→设备 | 读取设备PID、VID、产品字符串等信息 | | 0x90 | RESET_EQ_PARAMS | 复位EQ参数 | 主机→设备 | 删除Flash中的EQ参数并恢复头文件预设参数 | | 0x91 | GET_EQ_MODE_COUNT | 获取EQ模式总数 | 主机→设备 | 返回预定义加用户模式的总数(不包含禁用模式) | -| 0x92 | SET_AND_SAVE_EQ_MODE | 设置并保存EQ模式 | 主机→设备 | 设置当前EQ模式(0-9)并保存到Flash,开机时自动恢复 | +| 0x92 | SET_AND_SAVE_EQ_MODE | 设置并保存EQ模式 | 主机→设备 | 设置当前EQ模式(0-14)并保存到Flash,开机时自动恢复 | | 0x93 | SET_VOLUME | 设置音量级别 | 主机→设备 | 设置设备音量级别(0-255) | | 0x94 | GET_VOLUME | 获取音量级别 | 主机→设备 | 读取设备当前音量级别(0-255) | | 0x95 | GET_LED_INFO | 获取LED信息 | 主机→设备 | 读取LED索引和LED名称 | @@ -37,13 +37,30 @@ | 0xA4 | SET_GAME_MODE | 设置游戏模式 | 主机→设备 | 设置游戏模式(0=无音效,1=FPS,2=虚拟7.1) | | 0xA5 | GET_GAME_MODE | 获取游戏模式 | 主机→设备 | 读取当前游戏模式(0-2) | | 0xA6 | GET_FIRMWARE_VERSION | 获取固件版本 | 主机→设备 | 读取设备固件版本号(BCD格式:主版本.次版本.修订版本) | -| 0xB0 | SET_INPUT_SOURCE | 设置输入源模式 | 主机→设备 | 设置输入源模式(0=USB, 1=OPT, 2=COAX),通过UART 0x5D透传给MCU | -| 0xB1 | SET_MUTE_SWITCH | 设置静音开关 | 主机→设备 | 设置静音开关(0=关,1=开),通过UART 0x5E透传给MCU | -| 0xB2 | GET_MUTE_SWITCH | 获取静音开关状态 | 主机→设备 | 读取静音开关状态(0=关,1=开),设备通过串口向MCU请求后返回 | -| 0xB3 | SET_LISTEN_SWITCH | 设置监听开关 | 主机→设备 | 设置监听开关(0=关,1=开),通过UART 0x60透传给MCU | -| 0xB4 | GET_LISTEN_SWITCH | 获取监听开关状态 | 主机→设备 | 读取监听开关状态(0=关,1=开),直接返回 g_adc_loop 的值,不经过串口 | -| 0xB6 | SET_TILE1_DIV | 设置tile1动态降频分频值 | 主机→设备 | 设置tile1低功耗分频值N(core clock=600MHz/N),仅FPS镜像(C1_DFS_EN)生效,tile1空闲时降频 | -| 0xB7 | GET_TILE1_DIV | 获取tile1动态降频分频值 | 主机→设备 | 读取当前tile1低功耗分频值N(动态降频),仅FPS镜像(C1_DFS_EN)生效 | +| 0xA7 | FIRMWARE_UPGRADE_START | 开始固件升级 | 主机→设备 | 初始化升级流程,设置固件大小(与 eq_hid_protocol_ds1 一致) | +| 0xA8 | FIRMWARE_UPGRADE_DATA | 传输固件数据块 | 主机→设备 | 固定57字节数据块 | +| 0xA9 | FIRMWARE_UPGRADE_END | 结束固件升级 | 主机→设备 | 验证镜像 | +| 0xAA | FIRMWARE_UPGRADE_STATUS | 获取升级状态 | 主机→设备 | 进度与状态 | +| 0xAB | FIRMWARE_UPGRADE_ABORT | 中止固件升级 | 主机→设备 | 中止并清理 | +| 0xAC | FIRMWARE_UPGRADE_ERASE | 擦除升级镜像 | 主机→设备 | 擦除 Flash 升级区 | +| 0xAE | DEVICE_REBOOT | 设备重启 | 主机→设备 | 通用重启命令 | +| 0xB0 | SET_INPUT_SOURCE | 设置输入源模式 | 主机→设备 | 设置输入源模式(0=USB, 1=OPT, 2=COAX),tile0 经 sync 0x04 到 tile1 发 UART 0x5D 透传 MCU | +| 0xB1 | SET_MUTE_SWITCH | 设置静音开关 | 主机→设备 | 设置静音开关(0=关,1=开),tile0 经 sync 0x05 到 tile1 发 UART 0x5E 透传 MCU | +| 0xB2 | GET_MUTE_SWITCH | 获取静音开关状态 | 主机→设备 | 读取静音开关状态(0=关,1=开),tile0 经 sync 0x06 让 tile1 向 MCU 发 0x5F,MCU 返回后 tile1 经 sync 0x0E 回传静音值 | +| 0xB3 | SET_LISTEN_SWITCH | 设置监听开关 | 主机→设备 | 设置监听开关(0=关,1=开),tile0 经 sync 0x07 到 tile1 发 UART 0x60 透传 MCU | +| 0xB4 | GET_LISTEN_SWITCH | 获取监听开关状态 | 主机→设备 | 读取监听开关状态(0=关,1=开),直接返回 tile0 的 g_adc_loop 值(由 tile1 经 sync 0x0D 同步),不经过串口 | +| 0xB5 | SET_FPS_MODULE_ENABLE | 设置FPS库子模块使能 | 主机→设备 | 设置DRC/FPS主处理/fps_eq使能(0=旁路,1=开启);tile0存Flash后经sync 0x08同步tile1 | +| 0xB6 | GET_FPS_MODULE_ENABLE | 获取FPS库子模块使能 | 主机→设备 | 从Flash读取三模块使能状态(0/1) | +| 0xB7 | SET_FPS_EQ_MODE | 设置fps_eq预设模式 | 主机→设备 | 模式0-4(共5套),默认0;tile0写Flash后sync 0x09到tile1加载该模式10段增益 | +| 0xB8 | GET_FPS_EQ_MODE | 获取fps_eq当前模式 | 主机→设备 | 返回当前模式0-4 | +| 0xB9 | SET_FPS_EQ_BAND_GAIN | 设置当前模式单段增益 | 主机→设备 | band(0-9)+gain int16 LE(0.01dB,-600~600);tile0存Flash,sync 0x0A到tile1调用eq_set_band_gain | +| 0xBA | GET_FPS_EQ_BAND_GAIN | 获取当前模式单段增益 | 主机→设备 | 请求band(0-9),返回gain int16 LE | +| 0xBB | SET_FPS_EQ_MODE_NAME | 设置fps_eq模式名称 | 主机→设备 | 设置模式0-4的名称(16字节,含\0截断);tile0写Flash断电保存 | +| 0xBC | GET_FPS_EQ_MODE_NAME | 获取fps_eq模式名称 | 主机→设备 | 请求模式0-4,返回该模式16字节名称 | +| 0xBD | SET_FPS_DRC_MODE | 设置DRC压缩模式 | 主机→设备 | mode 0=low柔和压缩、1=high强力压缩,默认0;tile0存Flash后经sync 0x0C同步tile1 | +| 0xBE | GET_FPS_DRC_MODE | 获取DRC压缩模式 | 主机→设备 | 返回当前DRC压缩模式(0/1) | +| 0xBF | SET_FPS_XMOS_GAME_SELECT | 设置FPS XMOS游戏与增益 | 主机→设备 | 设置game(0-2)及该game绑定的level(0-4);每种game单独存level(fps_level_g0/g1/g2),默认level为2 | +| 0xC0 | GET_FPS_XMOS_GAME_SELECT | 获取指定game的level | 主机→设备 | 请求字节2指定game(0-2),返回该game及其在Flash中保存的level(0-4) | ### 1.3 数据包格式 - **Report ID**: 0x01 (HID报告ID) @@ -62,7 +79,7 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x8A | 命令码 -2 | 1 | uint8 | 模式值 (0-5: 预设模式, 6-8: 用户模式, 9: bypass) +2 | 1 | uint8 | 模式值 (0-12: 预设模式, 13-14: 用户模式, 15: 禁用EQ) 3-62 | 60 | 0x00 | 保留字节 ``` @@ -76,13 +93,13 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x8B | 命令码 -2 | 1 | uint8 | 模式值 (0-9: 有效模式值, 0xFF: 获取当前模式信息) +2 | 1 | uint8 | 模式值 (0-14: 有效模式值, 0xFF: 获取当前模式信息) 3-62 | 60 | 0x00 | 保留字节 ``` **设备端处理**: - 如果mode值为0xFF,返回当前模式值、整体增益和模式名称 -- 如果mode值为有效模式值(0-9),返回指定模式值、整体增益和模式名称 +- 如果mode值为有效模式值(0-14),返回指定模式值、整体增益和模式名称 @@ -101,7 +118,7 @@ **使用说明**: - 发送mode=0xFF时,返回当前激活的EQ模式信息 -- 发送mode=0-9时,返回指定模式的增益和名称信息(不切换当前模式) +- 发送mode=0-14时,返回指定模式的增益和名称信息(不切换当前模式) ### 2.3 0x8C - SET_MODE_GAIN_AND_NAME (设置模式整体增益和名称) **功能**: 设置EQ模式整体增益和名称 @@ -112,7 +129,7 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x8C | 命令码 -2 | 1 | uint8 | 模式值 (0-9) +2 | 1 | uint8 | 模式值 (0-14) 3-6 | 4 | int32 | 增益值 (范围0到-50dB,有符号整数) 7-22 | 16 | char | 模式名称 (UTF-8编码,16字节) 23-62 | 40 | 0x00 | 保留字节 @@ -132,7 +149,7 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x8D | 命令码 -2 | 1 | uint8 | 模式值 (0-9) +2 | 1 | uint8 | 模式值 (0-14) 3 | 1 | uint8 | 滤波器Band索引 (0-7) 4 | 1 | uint8 | 滤波器类型 5-8 | 4 | float | 中心频率 (Hz) @@ -166,7 +183,7 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x8E | 命令码 -2 | 1 | uint8 | 模式值 (0-9) +2 | 1 | uint8 | 模式值 (0-14) 3 | 1 | uint8 | EQ索引 (0-7) 4-62 | 59 | 0x00 | 保留字节 ``` @@ -178,7 +195,7 @@ 0 | 1 | 0x01 | Report ID 1 | 1 | 0x77 | 同步头1 2 | 1 | 0x8E | 同步头2 -3 | 1 | uint8 | 模式值 (0-9) +3 | 1 | uint8 | 模式值 (0-14) 4 | 1 | uint8 | 滤波器Band索引 (0-7) 5 | 1 | uint8 | 滤波器类型 6-9 | 4 | float | 中心频率 (Hz) @@ -224,7 +241,7 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x90 | 命令码 -2 | 1 | uint8 | 模式号 (0-9, 0xFF表示恢复所有包括EQ参数,总体增益,模式名称 ) +2 | 1 | uint8 | 模式号 (0-14, 0xFF表示恢复所有包括EQ参数,总体增益,模式名称 ) 3-62 | 60 | 0x00 | 保留字节 ``` @@ -258,8 +275,8 @@ 0 | 1 | 0x01 | Report ID 1 | 1 | 0x77 | 同步头1 2 | 1 | 0x91 | 同步头2 -3 | 1 | uint8 | 模式总数 (当前为9,包含0-8共9个模式,不包含禁用模式) -4 | 1 | uint8 | 预定义模式数量 (当前为6,包含0-5共6个预设模式) +3 | 1 | uint8 | 模式总数 (当前为15,包含0-14共15个模式,不包含禁用模式15) +4 | 1 | uint8 | 预定义模式数量 (当前为13,包含0-12共13个预设模式) 5-62 | 58 | 0x00 | 保留字节 ``` @@ -272,7 +289,7 @@ ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0x92 | 命令码 -2 | 1 | uint8 | 模式值 (0-9: 0-5预设模式, 6-8用户模式, 9: bypass) +2 | 1 | uint8 | 模式值 (0-14: 0-12预设模式, 13-14用户模式, 15=禁用EQ) 3-62 | 60 | 0x00 | 保留字节 ``` @@ -665,7 +682,7 @@ 1 | 1 | 0x77 | 同步头1 2 | 1 | 0x9E | 同步头2 3 | 1 | uint8 | EQ使能开关状态 (0=OFF禁用, 1=ON启用) -4 | 1 | uint8 | 保存的模式值 (0-9,如果之前有保存,0xFF表示未保存) +4 | 1 | uint8 | 保存的模式值 (0-14,如果之前有保存,0xFF表示未保存) 5-62 | 58 | 0x00 | 保留字节 ``` @@ -863,9 +880,221 @@ - 3个字节分别表示:主版本号、次版本号、修订版本号 - 例如:0x01 0x00 0x0C 表示版本 1.0.12 -### 2.30 0xB0 - SET_INPUT_SOURCE (设置输入源模式) -**功能**: 设置输入源模式(USB/OPT/COAX),通过UART 0x5D命令透传给MCU处理 -**方向**: 主机→设备(XMOS)→MCU +### 2.30 0xB5 - SET_FPS_MODULE_ENABLE (设置FPS库 DRC / FPS主处理 / fps_eq 使能) +**功能**: 设置 FPS 算法库三个子模块的运行时开关,对应 `fps_xmos_xc_set_module_enable(drc_enable, fps_enable, eq_enable)`。0=旁路,非0=开启。 +**方向**: 主机→设备(tile0)→tile1 +**数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0xB5 | 命令码 +2 | 1 | uint8 | drc_enable (0/1) +3 | 1 | uint8 | fps_enable,FPS主处理子模块 (0/1) +4 | 1 | uint8 | eq_enable,fps_eq子模块 (0/1) +5-62 | 58 | 0x00 | 保留字节 +``` + +**Flash 存储**: +- `fps_drc_enable` / `fps_sub_enable` / `fps_eq_enable`:各 0 或 1,未存或无效(>1) 时默认 DRC=0、FPS主处理=1、fps_eq=0。 + +**设备端处理**: +- tile0:写 Flash 与共享全局 `g_fps_drc_enable`、`g_fps_sub_enable`、`g_fps_eq_enable`。 +- 打包 `packed = drc | (fps_sub<<8) | (eq<<16)`,`g_sync_t0_to_t1_cmd=0x08`,`g_sync_t0_to_t1_data=packed`。 +- tile1:解包后调用 `fps_apply_module_enable()` → `fps_xmos_xc_set_module_enable()`。 + +**上电恢复**: `SYNC_CMD_LOAD_CONFIGS` 中从 Flash 读取三键并触发 sync 0x08。 + +### 2.31 0xB6 - GET_FPS_MODULE_ENABLE (获取FPS库子模块使能) +**功能**: 读取 DRC / FPS主处理 / fps_eq 当前使能状态(来自 tile0 运行时全局 `g_fps_*`,与 0xB5 写入一致,避免紧接读 Flash 滞后)。 +**方向**: 主机→设备 +**请求数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0xB6 | 命令码 +2-62 | 61 | 0x00 | 保留字节 +``` + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0xB6 | 同步头2 +3 | 1 | uint8 | drc_enable (0/1) +4 | 1 | uint8 | fps_enable (0/1) +5 | 1 | uint8 | eq_enable (0/1) +6-62 | 57 | 0x00 | 保留字节 +``` + +### 2.32 0xBD - SET_FPS_DRC_MODE (设置 DRC 压缩模式) +**功能**: 设置 FPS 算法库 DRC 压缩强度,对应 `fps_xmos_xc_drc_set_mode(mode)`。0=low(柔和压缩),1=high(强力压缩)。 +**方向**: 主机→设备(tile0)→tile1 + +**请求数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0xBD | 命令码 +2 | 1 | uint8 | drc_mode (0=low, 1=high) +3-62 | 60 | 0x00 | 保留字节 +``` + +**Flash 键**: `fps_drc_mode`,未存或无效(>1) 时默认 **0**(low)。 + + +### 2.33 0xBE - GET_FPS_DRC_MODE (获取 DRC 压缩模式) +**功能**: 读取当前 DRC 压缩模式(来自 tile0 运行时全局 `g_fps_drc_mode`,与 0xBD 写入一致)。 +**方向**: 主机→设备 + +**请求数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0xBE | 命令码 +2-62 | 61 | 0x00 | 保留字节 +``` + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0xBE | 同步头2 +3 | 1 | uint8 | drc_mode (0=low, 1=high) +4-62 | 59 | 0x00 | 保留字节 +``` + +### 2.34 0xBF - SET_FPS_XMOS_GAME_SELECT (设置FPS XMOS游戏类型与增益等级) +**功能**: 设置当前FPS游戏类型(game)及**该game绑定的**增益等级(level),用于 `fps_xmos_game_select(game, level)`。game 与 level 绑定:三种 game(0/1/2) 各有各自保存的 level(0/1/2/3/4),选择某 game 时使用该 game 对应的 level;默认 level 为 2。 +**方向**: 主机→设备(XMOS tile0)→tile1 +**数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0xBF | 命令码 +2 | 1 | uint8 | 游戏类型 game (0/1/2) +3 | 1 | uint8 | 该 game 的增益等级 level (0/1/2/3/4),默认 2 +4-62 | 59 | 0x00 | 保留字节 +``` + +**参数说明**: +- **game(字节2):** 游戏类型,0/1/2;对应 `fps_xmos_game_select` 的第一个参数。 +- **level(字节3):** 当前选中的 game 的增益等级,0/1/2/3/4;对应 `fps_xmos_game_select` 的第二个参数。若主机未发或无效(>4),设备按默认 2 处理。 +- **绑定关系:** 设置 (game, level) 后,仅该 game 的 level 被更新;切换 game 时(含上电恢复)会查该 game 对应的已保存 level。 + +**Flash 存储(按 game 分别存 level)**: +- `fps_game_select`:当前选中的 game (0/1/2)。 +- `fps_level_g0` / `fps_level_g1` / `fps_level_g2`:分别表示 game 0、1、2 的 level (0/1/2/3/4),默认 2。 +- 0xBF 设置 (game, level) 时:写入 `fps_game_select=game`,并将 level 写入对应键(game 0→fps_level_g0,game 1→fps_level_g1,game 2→fps_level_g2)。 +- 上电恢复:在 `fps_boot_load_from_flash` 中读 `fps_game_select`,再根据 game 查对应 level(读 fps_level_g0/g1/g2),得到当前 (game, level) 后同步到 tile1。 + +**设备端处理**: +- tile0 解析 data[2]=game、data[3]=level;level 无效(>4) 时按 2。 +- 保存:`save_value("fps_game_select", game)`,并按 game 写 `save_value("fps_level_g0"/"fps_level_g1"/"fps_level_g2", level)`。 +- 打包 `packed_fps = (game<<0) | (level<<8)`,设置 g_sync_t0_to_t1_cmd=0x03、g_sync_t0_to_t1_data=packed_fps,更新 g_fps_game_select、g_fps_level_select。 +- tile1 解包后设置 g_fps_game_select、g_fps_level_select,fps1_dsp_proc_task 调用 fps_xmos_game_select(game, level)。 + +**同步机制**: +- HID 0xBF 在 tile0 接收 → 按 game 写入对应 level 键 → 设置 sync 0x03 + packed_fps → tile1 解包并设置 g_fps_game_select、g_fps_level_select → fps1_dsp_proc_task 调用 fps_xmos_game_select(game, level)。 + +**返回值**: +无直接返回值。当前 game 及该 game 的 level 可用 GET_FPS_XMOS_GAME_SELECT (0xC0) 读取。 + +### 2.35 0xC0 - GET_FPS_XMOS_GAME_SELECT (获取指定 game 的 level) +**功能**: 按主机指定的 game(0/1/2) 查询该 game 绑定的 level(0/1/2/3/4),返回**指定 game** 及其在 Flash 中保存的 level(非当前选中的 game)。 +**方向**: 主机→设备 +**请求数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0xC0 | 命令码 +2 | 1 | uint8 | 要查询的 game (0/1/2),不传或无效时设备按 0 处理 +3-62 | 60 | 0x00 | 保留字节 +``` + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0xC0 | 同步头2 +3 | 1 | uint8 | 请求的 game (0/1/2) +4 | 1 | uint8 | 该 game 绑定的 level (0/1/2/3/4),来自 Flash fps_level_g0/g1/g2 +5-62 | 58 | 0x00 | 保留字节 +``` + +**说明**: +- 请求字节2:指定要查询的 game;未传或 >2 时设备按 game=0 查询。 + +### 2.36 0xB7 - SET_FPS_EQ_MODE (设置 fps_eq 预设模式) +**功能**: 选择 5 套 fps_eq 增益预设之一(模式 **0–4**,默认 **0**)。切换后 tile1 对该模式全部 10 段调用 `fps_xmos_xc_eq_set_all_gains`。 +**数据包**: `[0x77][0xB7][mode]`,mode 无效(>4) 拒绝。 + +**Flash**: 文件 `fps_eq_store`,含 `current_mode` 与 `gains[5][10]`,每段默认 **1** (0.01dB)。 + +**同步**: tile0 写 Flash → 发布共享 pack 字 → `g_sync_t0_to_t1_cmd=0x09`。 + +### 2.35 0xB8 - GET_FPS_EQ_MODE +**响应**: `[0x77][0xB8][mode]`,mode 为当前选中模式 0–4。 + +### 2.36 0xB9 - SET_FPS_EQ_BAND_GAIN (设置当前模式单段增益) +**功能**: 调节**当前模式**下某一频段增益,tile1 调用 `fps_xmos_xc_eq_set_band_gain(band, gain)`。 +**数据包**: +``` +0: 0x77 1: 0xB9 2: band(0-9) 3-4: gain int16 LE (0.01dB, -600~600) +``` +tile0 更新 Flash 中 `gains[current_mode][band]`,sync **0x0A**。 + +### 2.37 0xBA - GET_FPS_EQ_BAND_GAIN +**请求**: `[0x77][0xBA][band]` +**响应(含 Report ID 的 64 字节 HID 报告)**: +``` +字节 | 内容 +-----|------ +0 | 0x01 Report ID +1 | 0x77 +2 | 0xBA +3 | band (0-9) +4-5 | gain int16 小端 (0.01dB, -600~600) +``` +主机解析增益应使用 **字节 4–5**,勿与字节 3(band)拼接。 + +### 2.38 0xBB - SET_FPS_EQ_MODE_NAME (设置 fps_eq 模式名称) +**功能**: 设置 fps_eq 预设模式名称(模式 0~4,对应 5 套增益)。 +**请求格式**: +``` +0:0x77 1:0xBB 2:mode(0-4) 3..18:name[16] +``` +**说明**: +- 名称最大 15 个可见字符,第 16 字节用于 `\0` 结尾(设备侧强制截断)。 +- 名称写入 tile0 Flash (`fps_eq_store`),支持断电保存。 + +### 2.39 0xBC - GET_FPS_EQ_MODE_NAME (读取 fps_eq 模式名称) +**请求**: `[0x77][0xBC][mode]` +**响应(含 Report ID 的 64 字节 HID 报告)**: +``` +字节 | 内容 +-----|------ +0 | 0x01 Report ID +1 | 0x77 +2 | 0xBC +3 | mode(0-4) +4..19| name[16](\0 结尾,不足补0) +``` + +### 2.40 0xB0 - SET_INPUT_SOURCE (设置输入源模式) +**功能**: 设置输入源模式(0=USB, 1=OPT, 2=COAX) +**方向**: 主机→设备 **数据包格式**: ``` 字节位置 | 长度 | 内容 | 描述 @@ -875,161 +1104,61 @@ 2 | 1 | uint8 | 输入源模式值 (0=USB, 1=OPT, 2=COAX) 3-62 | 60 | 0x00 | 保留字节 ``` +**设备端处理(c3_fps 双 tile)**: +- tile0(HID)收到 0xB0 后设置 g_sync_t0_to_t1_cmd=0x04、g_sync_t0_to_t1_data=输入源 +- tile1 的 app_control_slave 收到 sync 后调用 process_uart_set_input_source,构建 UART 0x5D 包透传 MCU -**设备端处理**: -- XMOS设备接收到HID 0xB0命令后,将其转换为UART 0x5D命令格式 -- 通过UART接口将完整的0x5D数据包透传给MCU -- MCU负责处理输入源切换(USB/OPT/COAX) -- 本命令不返回HID响应 - -**透传机制**: -- HID 0xB0命令 → XMOS设备转换为UART 0x5D命令 → 透传给MCU -- UART 0x5D数据包格式:0x55 0xAA 0x00 0x5D [长度] [输入源模式值] [校验和] -- MCU根据输入源模式值执行相应的输入切换操作 - -### 2.31 0xB1 - SET_MUTE_SWITCH (设置静音开关) -**功能**: 设置静音开关(0=关,1=开),通过UART 0x5E命令透传给MCU处理 -**方向**: 主机→设备(XMOS)→MCU +### 2.33 0xB1 - SET_MUTE_SWITCH (设置静音开关) +**功能**: 设置静音开关(0=关,1=开) +**方向**: 主机→设备 **数据包格式**: ``` 字节位置 | 长度 | 内容 | 描述 ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0xB1 | 命令码 -2 | 1 | uint8 | 静音开关值 (0=关,1=开) +2 | 1 | uint8 | 静音开关值 (0=关, 1=开) 3-62 | 60 | 0x00 | 保留字节 ``` +**设备端处理(c3_fps 双 tile)**: +- tile0 收到 0xB1 后设置 sync 0x05 及数据,tile1 调用 process_uart_set_mute_switch,发 UART 0x5E 透传 MCU -**设备端处理**: -- XMOS设备接收到HID 0xB1命令后,将其转换为UART 0x5E命令格式并透传给MCU -- MCU负责处理静音开关状态 -- 本命令不返回HID响应 +### 2.34 0xB2 - GET_MUTE_SWITCH (获取静音开关状态) +**功能**: 读取静音开关状态(0=关,1=开),设备向 MCU 请求后返回 +**方向**: 主机→设备 +**请求**: 同步头 0x77 + 0xB2 + 保留字节 +**响应**: 0x01 0x77 0xB2 + 1 字节静音值 (0=关, 1=开) +**设备端处理(c3_fps 双 tile)**: +- tile0 收到 0xB2 后置 is_get_mute_switch_request,并设置 sync 0x06,tile1 调用 process_uart_send_get_mute_request 向 MCU 发 UART 0x5F +- MCU 返回 0x5F+1 字节后,tile1 的 user_uart 调用 sync_to_tile0(0x0E, mute_value, 0);tile0 的 audiohw 收到 0x0E 后设置 g_mute_switch +- 主机执行 HID 读时,process_read_params 直接读 g_mute_switch 返回。建议发送 0xB2 后延时约 50ms 再执行 HID 读 -### 2.32 0xB2 - GET_MUTE_SWITCH (获取静音开关状态) -**功能**: 读取静音开关状态(0=关,1=开);设备通过串口向MCU发送0x5F请求,MCU返回状态后设备再通过HID响应返回给主机 -**方向**: 主机→设备→MCU→设备→主机 -**请求数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x77 | 同步头1 -1 | 1 | 0xB2 | 命令码 -2-62 | 61 | 0x00 | 保留字节 -``` +**状态变化上报**: 当静音开关状态发生变化(如 MCU 通过 0x5F 返回、tile1 经 sync 0x0E 回传)时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB2 + 1 字节静音值),与音量变化上报(0x94)方式相同。 -**设备端处理**: -- 主机发送0xB2后,XMOS向MCU发送UART 0x5F(GET请求) -- MCU返回UART 0x5F响应(含静音开关值) -- 主机随后通过HID读报告获取响应 - -**响应数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x01 | Report ID -1 | 1 | 0x77 | 同步头1 -2 | 1 | 0xB2 | 同步头2 -3 | 1 | uint8 | 静音开关状态 (0=关,1=开) -4-62 | 59 | 0x00 | 保留字节 -``` - -**说明**: 主机发送0xB2后建议稍作延时(如50ms)再执行HID读,以确保MCU已返回数据。 - -**状态变化上报**: 当静音开关状态发生变化(如 MCU 通过 0x5F 返回新值)时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB2 + 1 字节静音值),与音量变化上报(0x94)方式相同,主机可通过 HID 读或中断 IN 获取。 - -### 2.33 0xB3 - SET_LISTEN_SWITCH (设置监听开关) -**功能**: 设置监听开关(0=关,1=开),通过UART 0x60命令透传给MCU处理 -**方向**: 主机→设备(XMOS)→MCU +### 2.35 0xB3 - SET_LISTEN_SWITCH (设置监听开关) +**功能**: 设置监听开关(0=关,1=开) +**方向**: 主机→设备 **数据包格式**: ``` 字节位置 | 长度 | 内容 | 描述 ---------|------|------|------ 0 | 1 | 0x77 | 同步头1 1 | 1 | 0xB3 | 命令码 -2 | 1 | uint8 | 监听开关值 (0=关,1=开) +2 | 1 | uint8 | 监听开关值 (0=关, 1=开) 3-62 | 60 | 0x00 | 保留字节 ``` +**设备端处理(c3_fps 双 tile)**: +- tile0 收到 0xB3 后设置 sync 0x07 及数据,tile1 调用 process_uart_set_listen_switch,发 UART 0x60 透传 MCU(对应 g_adc_loop 语义) -**设备端处理**: -- XMOS设备接收到HID 0xB3命令后,将其转换为UART 0x60命令格式并透传给MCU -- MCU负责处理监听开关(对应 g_adc_loop 语义) -- 本命令不返回HID响应 - -### 2.34 0xB4 - GET_LISTEN_SWITCH (获取监听开关状态) -**功能**: 读取监听开关状态(0=关,1=开),设备直接返回 g_adc_loop 的值,不经过串口 +### 2.36 0xB4 - GET_LISTEN_SWITCH (获取监听开关状态) +**功能**: 读取监听开关状态(0=关,1=开),直接返回 g_adc_loop 的值,不经过串口 **方向**: 主机→设备 -**请求数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x77 | 同步头1 -1 | 1 | 0xB4 | 命令码 -2-62 | 61 | 0x00 | 保留字节 -``` +**请求**: 同步头 0x77 + 0xB4 + 保留字节 +**响应**: 0x01 0x77 0xB4 + 1 字节监听开关状态 (0=关, 1=开) +**设备端处理(c3_fps 双 tile)**: +- tile0 收到 0xB4 后置 is_get_listen_switch_request;HID 读时 process_read_params 直接读取 tile0 的 g_adc_loop(由 tile1 经 sync 0x0D 同步)填入响应字节 3 -**响应数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x01 | Report ID -1 | 1 | 0x77 | 同步头1 -2 | 1 | 0xB4 | 同步头2 -3 | 1 | uint8 | 监听开关状态 (0=关,1=开),即 g_adc_loop 的值 -4-62 | 59 | 0x00 | 保留字节 -``` - -**设备端处理**: -- 设备直接读取 g_adc_loop,填入响应字节 3,无需向 MCU 请求 - -**状态变化上报**: 当监听开关状态(g_adc_loop)发生变化时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB4 + 1 字节监听状态),与音量变化上报(0x94)方式相同,主机可通过 HID 读或中断 IN 获取。 - -### 2.35 0xB6 - SET_TILE1_DIV (设置tile1动态降频分频值) -**功能**: 设置 tile[1] 动态降频(动态降频)的低功耗分频值 N。tile[1] core clock = 600 MHz / N。 -**方向**: 主机→设备 -**数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x77 | 同步头1 -1 | 1 | 0xB6 | 命令码 -2 | 1 | uint8 | 分频值 N (1-255,0视为1;N=1为全速600MHz,N=40约15MHz) -3-62 | 60 | 0x00 | 保留字节 -``` - -**设备端处理**: -- 仅在 FPS 镜像(编译宏 `C1_DFS_EN=1`,默认等于 `XMOS_FPS_EN`)生效;其它镜像(如 factory)忽略此命令。 -- 写入全局 `g_tile1_lp_div`。tile[1] 电源状态机下次进入 CLOCKED_DOWN(FPS 关闭或音频流停止、grace 超时后)时按此分频值降频;若当前已处于 CLOCKED_DOWN,则下次状态机 tick 立即按新值重写分频寄存器。 -- 全速运行(FPS 开启且音频流活跃)时不影响 tile[1] 实时时钟,仅更新待用分频值。 - -**返回值**: -无直接返回值。如需确认,请使用 GET_TILE1_DIV (0xB7) 读取当前分频值。 - -### 2.36 0xB7 - GET_TILE1_DIV (获取tile1动态降频分频值) -**功能**: 读取 tile[1] 动态降频当前的低功耗分频值 N。 -**方向**: 主机→设备 -**请求数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x77 | 同步头1 -1 | 1 | 0xB7 | 命令码 -2-62 | 61 | 0x00 | 保留字节 -``` - -**响应数据包格式**: -``` -字节位置 | 长度 | 内容 | 描述 ----------|------|------|------ -0 | 1 | 0x01 | Report ID -1 | 1 | 0x77 | 同步头1 -2 | 1 | 0xB7 | 同步头2 -3 | 1 | uint8 | 当前分频值 N (1-255) -4-62 | 59 | 0x00 | 保留字节 -``` - -**设备端处理**: -- 仅在 FPS 镜像(`C1_DFS_EN=1`)生效,返回 `g_tile1_lp_div`。 -- 注意:返回的 N 为"待用/当前低功耗分频值",并非实时核心频率读数;tile[1] 是否实际处于降频状态取决于 FPS 开关与音频流状态(FPS 关闭或音频停止后才会真正降频)。 +**状态变化上报**: 当监听开关状态(g_adc_loop)发生变化时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB4 + 1 字节监听状态),与音量变化上报(0x94)方式相同。 ## 5. 关键特性 diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_params_44100.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_params_44100.h index 0e0e90b..489ec47 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_params_44100.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/eq_params_44100.h @@ -1,5 +1,6 @@ // EQ参数头文件 - 44100Hz // 自动生成,请勿手动修改 +// 改动原因:修复块错位与格式问题,按模式顺序重排 #include "eq.h" @@ -672,7 +673,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 63.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 2.00f, + .gain = -4.00f, }, { .index = 1, @@ -680,7 +681,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 125.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 4.00f, + .gain = -3.00f, }, { .index = 2, @@ -688,7 +689,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 250.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 4.00f, + .gain = -2.00f, }, { .index = 3, @@ -696,7 +697,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 500.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 1.00f, + .gain = 2.00f, }, { .index = 4, @@ -704,7 +705,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 1000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -1.00f, + .gain = 3.00f, }, { .index = 5, @@ -712,7 +713,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 4000.00f, .q = 0.7100f, .bw = 1.00f, - .gain = 2.00f, + .gain = 1.00f, }, { .index = 6, @@ -720,7 +721,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 8000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 2.00f, + .gain = -3.00f, }, { .index = 7, @@ -728,18 +729,18 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 16000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 2.00f, + .gain = -2.00f, }, }, .filter = { .biquad_count = MAX_EQ_BANDS, .state = {{0}}, .coef = { - {0x40193bef, 0x40706fc7, 0x40de3b22, 0x405a90d5, 0x3f54ecd5, 0x449012f8, 0x464040bd, 0x459182a8}, - {-0x7f3bc607, -0x7e7a6540, -0x7cf3cb7a, -0x79e431a7, -0x7289a001, -0x4e189e14, -0x214d8c10, 0x37527133}, - {0x3f23da02, 0x3e0f182b, 0x3c29ddbf, 0x39d8f962, 0x3460d7e0, 0x18317347, 0x097705ac, 0x0f6b8432}, - {0x7f3bc607, 0x7e7a6540, 0x7cf3cb7a, 0x79e431a7, 0x7289a001, 0x4e189e14, 0x214d8c10, -0x37527133}, - {-0x3f3d15f2, -0x3e7f87f2, -0x3d0818e1, -0x3a338a38, -0x33b5c4b5, -0x1cc1863f, -0x0fb7466a, -0x14fd06da}, + {0x3fc73213, 0x3fb113fc, 0x3f9e3547, 0x40c02ea5, 0x42487f62, 0x4226744a, 0x3761b4a8, 0x3ae09727}, + {-0x7ecad859, -0x7dde6daa, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1cd17be8, 0x32e4d9ca}, + {0x3f04f506, 0x3e32760b, 0x3caad74a, 0x39735b92, 0x32a5d521, 0x1a9b11f4, 0x0d997ea7, 0x134ef560}, + {0x7ecad859, 0x7dde6daa, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1cd17be8, -0x32e4d9ca}, + {-0x3ecc2719, -0x3de38a07, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x04fb334f, -0x0e2f8c87}, }, } }, @@ -754,7 +755,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 63.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 2.00f, + .gain = -4.00f, }, { .index = 1, @@ -762,7 +763,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 125.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 4.00f, + .gain = -3.00f, }, { .index = 2, @@ -770,7 +771,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 250.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 4.00f, + .gain = -2.00f, }, { .index = 3, @@ -778,7 +779,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 500.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 1.00f, + .gain = 2.00f, }, { .index = 4, @@ -786,7 +787,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 1000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -1.00f, + .gain = 3.00f, }, { .index = 5, @@ -794,7 +795,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 4000.00f, .q = 0.7100f, .bw = 1.00f, - .gain = 2.00f, + .gain = 1.00f, }, { .index = 6, @@ -802,7 +803,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 8000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 2.00f, + .gain = -3.00f, }, { .index = 7, @@ -810,18 +811,18 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 16000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 2.00f, + .gain = -2.00f, }, }, .filter = { .biquad_count = MAX_EQ_BANDS, .state = {{0}}, .coef = { - {0x40193bef, 0x40706fc7, 0x40de3b22, 0x405a90d5, 0x3f54ecd5, 0x449012f8, 0x464040bd, 0x459182a8}, - {-0x7f3bc607, -0x7e7a6540, -0x7cf3cb7a, -0x79e431a7, -0x7289a001, -0x4e189e14, -0x214d8c10, 0x37527133}, - {0x3f23da02, 0x3e0f182b, 0x3c29ddbf, 0x39d8f962, 0x3460d7e0, 0x18317347, 0x097705ac, 0x0f6b8432}, - {0x7f3bc607, 0x7e7a6540, 0x7cf3cb7a, 0x79e431a7, 0x7289a001, 0x4e189e14, 0x214d8c10, -0x37527133}, - {-0x3f3d15f2, -0x3e7f87f2, -0x3d0818e1, -0x3a338a38, -0x33b5c4b5, -0x1cc1863f, -0x0fb7466a, -0x14fd06da}, + {0x3fc73213, 0x3fb113fc, 0x3f9e3547, 0x40c02ea5, 0x42487f62, 0x4226744a, 0x3761b4a8, 0x3ae09727}, + {-0x7ecad859, -0x7dde6daa, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1cd17be8, 0x32e4d9ca}, + {0x3f04f506, 0x3e32760b, 0x3caad74a, 0x39735b92, 0x32a5d521, 0x1a9b11f4, 0x0d997ea7, 0x134ef560}, + {0x7ecad859, 0x7dde6daa, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1cd17be8, -0x32e4d9ca}, + {-0x3ecc2719, -0x3de38a07, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x04fb334f, -0x0e2f8c87}, }, } }, @@ -1000,7 +1001,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 63.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -3.00f, }, { .index = 1, @@ -1008,7 +1009,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 125.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -3.00f, }, { .index = 2, @@ -1016,7 +1017,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 250.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -1.00f, + .gain = -2.00f, }, { .index = 3, @@ -1024,7 +1025,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 500.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -3.00f, + .gain = 2.00f, }, { .index = 4, @@ -1032,7 +1033,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 1000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -3.00f, + .gain = 2.00f, }, { .index = 5, @@ -1040,7 +1041,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 4000.00f, .q = 0.7100f, .bw = 1.00f, - .gain = 3.00f, + .gain = -2.00f, }, { .index = 6, @@ -1048,7 +1049,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 8000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -3.00f, }, { .index = 7, @@ -1056,18 +1057,18 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 16000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -4.00f, }, }, .filter = { .biquad_count = MAX_EQ_BANDS, .state = {{0}}, .coef = { - {0x40283469, 0x404f4dce, 0x3fd1c50d, 0x3ed36b73, 0x3dcba2d2, 0x47450e12, 0x49f5a1ad, 0x48df384d}, - {-0x7f3bc607, -0x7e7a6540, -0x7c998928, -0x77a7b914, -0x6fc2592c, -0x4e189e14, -0x214d8c10, 0x37527133}, - {0x3f14e189, 0x3e303a23, 0x3cdc02d8, 0x39223189, 0x331b932b, 0x157c782d, 0x05c1a4bd, 0x0c1dce8d}, - {0x7f3bc607, 0x7e7a6540, 0x7c998928, 0x77a7b914, 0x6fc2592c, 0x4e189e14, 0x214d8c10, -0x37527133}, - {-0x3f3d15f2, -0x3e7f87f2, -0x3cadc7e6, -0x37f59cfd, -0x30e735fd, -0x1cc1863f, -0x0fb7466a, -0x14fd06da}, + {0x3fd7e4c8, 0x3fb113fc, 0x3f9e3547, 0x40c02ea5, 0x416edac4, 0x3bbda8fe, 0x3761b4a8, 0x357cce9e}, + {-0x7eec0a91, -0x7dde6daa, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x48e620a5, -0x1cd17be8, 0x2e3c2813}, + {0x3f1574e0, 0x3e32760b, 0x3caad74a, 0x39735b92, 0x337f79bf, 0x1ad79f31, 0x0d997ea7, 0x118a77ac}, + {0x7eec0a91, 0x7dde6daa, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x48e620a5, 0x1cd17be8, -0x2e3c2813}, + {-0x3eed59a9, -0x3de38a07, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x1695482f, -0x04fb334f, -0x0707464b}, }, } }, @@ -1082,7 +1083,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 63.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -3.00f, }, { .index = 1, @@ -1090,8 +1091,254 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 125.00f, .q = 0.7500f, .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fd7e4c8, 0x3fb113fc, 0x3f9e3547, 0x40c02ea5, 0x416edac4, 0x3bbda8fe, 0x3761b4a8, 0x357cce9e}, + {-0x7eec0a91, -0x7dde6daa, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x48e620a5, -0x1cd17be8, 0x2e3c2813}, + {0x3f1574e0, 0x3e32760b, 0x3caad74a, 0x39735b92, 0x337f79bf, 0x1ad79f31, 0x0d997ea7, 0x118a77ac}, + {0x7eec0a91, 0x7dde6daa, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x48e620a5, 0x1cd17be8, -0x2e3c2813}, + {-0x3eed59a9, -0x3de38a07, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x1695482f, -0x04fb334f, -0x0707464b}, + }, + } + }, + [7][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 1.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, .gain = 3.00f, }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fc73213, 0x3fb113fc, 0x3f9e3547, 0x405a90d5, 0x42487f62, 0x3deb7030, 0x3a4e238c, 0x357cce9e}, + {-0x7ecad859, -0x7dde6daa, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4b8ec1f7, -0x1e56eff0, 0x2e3c2813}, + {0x3f04f506, 0x3e32760b, 0x3caad74a, 0x39d8f962, 0x32a5d521, 0x1bd23cf6, 0x0e5147e9, 0x118a77ac}, + {0x7ecad859, 0x7dde6daa, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4b8ec1f7, 0x1e56eff0, -0x2e3c2813}, + {-0x3ecc2719, -0x3de38a07, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x19bdad27, -0x089f6b75, -0x0707464b}, + }, + } + }, + [7][1] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 1.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 3.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fc73213, 0x3fb113fc, 0x3f9e3547, 0x405a90d5, 0x42487f62, 0x3deb7030, 0x3a4e238c, 0x357cce9e}, + {-0x7ecad859, -0x7dde6daa, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4b8ec1f7, -0x1e56eff0, 0x2e3c2813}, + {0x3f04f506, 0x3e32760b, 0x3caad74a, 0x39d8f962, 0x32a5d521, 0x1bd23cf6, 0x0e5147e9, 0x118a77ac}, + {0x7ecad859, 0x7dde6daa, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4b8ec1f7, 0x1e56eff0, -0x2e3c2813}, + {-0x3ecc2719, -0x3de38a07, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x19bdad27, -0x089f6b75, -0x0707464b}, + }, + } + }, + [8][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -1.00f, + }, { .index = 2, .type = FILTER_TYPE_PEAKING, @@ -1106,7 +1353,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 500.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -3.00f, + .gain = 2.00f, }, { .index = 4, @@ -1114,7 +1361,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 1000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -3.00f, + .gain = 3.00f, }, { .index = 5, @@ -1122,7 +1369,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 4000.00f, .q = 0.7100f, .bw = 1.00f, - .gain = 3.00f, + .gain = 0.00f, }, { .index = 6, @@ -1130,7 +1377,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 8000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -2.00f, }, { .index = 7, @@ -1138,377 +1385,787 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { .fc = 16000.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 3.00f, + .gain = -2.00f, }, }, .filter = { .biquad_count = MAX_EQ_BANDS, .state = {{0}}, .coef = { - {0x40283469, 0x404f4dce, 0x3fd1c50d, 0x3ed36b73, 0x3dcba2d2, 0x47450e12, 0x49f5a1ad, 0x48df384d}, - {-0x7f3bc607, -0x7e7a6540, -0x7c998928, -0x77a7b914, -0x6fc2592c, -0x4e189e14, -0x214d8c10, 0x37527133}, - {0x3f14e189, 0x3e303a23, 0x3cdc02d8, 0x39223189, 0x331b932b, 0x157c782d, 0x05c1a4bd, 0x0c1dce8d}, - {0x7f3bc607, 0x7e7a6540, 0x7c998928, 0x77a7b914, 0x6fc2592c, 0x4e189e14, 0x214d8c10, -0x37527133}, - {-0x3f3d15f2, -0x3e7f87f2, -0x3cadc7e6, -0x37f59cfd, -0x30e735fd, -0x1cc1863f, -0x0fb7466a, -0x14fd06da}, - }, - } - }, - [7][0] = { - .sample_rate = 44100, - .total_bshift = 0, - .post_gain_db = 0, // 0 dB - .bands = { - { - .index = 0, - .type = FILTER_TYPE_BYPASS, - .fc = 85.00f, - .q = 0.7500f, - .bw = 1.00f, - .gain = -4.00f, - }, - { - .index = 1, - .type = FILTER_TYPE_BYPASS, - .fc = 80.00f, - .q = 0.7500f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 2, - .type = FILTER_TYPE_BYPASS, - .fc = 2000.00f, - .q = 0.5000f, - .bw = 1.00f, - .gain = 1.50f, - }, - { - .index = 3, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 4, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 5, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 6, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 7, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - }, - .filter = { - .biquad_count = MAX_EQ_BANDS, - .state = {{0}}, - .coef = { - {0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - }, - } - }, - [7][1] = { - .sample_rate = 44100, - .total_bshift = 0, - .post_gain_db = 0, // 0 dB - .bands = { - { - .index = 0, - .type = FILTER_TYPE_BYPASS, - .fc = 85.00f, - .q = 0.7500f, - .bw = 1.00f, - .gain = -4.00f, - }, - { - .index = 1, - .type = FILTER_TYPE_BYPASS, - .fc = 80.00f, - .q = 0.7500f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 2, - .type = FILTER_TYPE_BYPASS, - .fc = 2000.00f, - .q = 0.5000f, - .bw = 1.00f, - .gain = 1.50f, - }, - { - .index = 3, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 4, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 5, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 6, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 7, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - }, - .filter = { - .biquad_count = MAX_EQ_BANDS, - .state = {{0}}, - .coef = { - {0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - }, - } - }, - [8][0] = { - .sample_rate = 44100, - .total_bshift = 0, - .post_gain_db = 0, // 0 dB - .bands = { - { - .index = 0, - .type = FILTER_TYPE_BYPASS, - .fc = 130.00f, - .q = 0.7500f, - .bw = 1.00f, - .gain = -4.00f, - }, - { - .index = 1, - .type = FILTER_TYPE_BYPASS, - .fc = 80.00f, - .q = 0.7500f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 2, - .type = FILTER_TYPE_BYPASS, - .fc = 2000.00f, - .q = 0.5000f, - .bw = 1.00f, - .gain = 1.50f, - }, - { - .index = 3, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 4, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 5, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 6, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - { - .index = 7, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, - .bw = 1.00f, - .gain = 0.00f, - }, - }, - .filter = { - .biquad_count = MAX_EQ_BANDS, - .state = {{0}}, - .coef = { - {0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x3ff41df7, 0x3fe893cf, 0x3fd1c50d, 0x40c02ea5, 0x42487f62, 0x3fffffff, 0x3a4e238c, 0x3ae09727}, + {-0x7f242665, -0x7e4c1b74, -0x7c998928, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1e56eff0, 0x32e4d9ca}, + {0x3f31581a, 0x3e68a876, 0x3cdc02d8, 0x39735b92, 0x32a5d521, 0x1cc1863f, 0x0e5147e9, 0x134ef560}, + {0x7f242665, 0x7e4c1b74, 0x7c998928, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1e56eff0, -0x32e4d9ca}, + {-0x3f257611, -0x3e513c45, -0x3cadc7e6, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x089f6b75, -0x0e2f8c87}, }, } }, [8][1] = { .sample_rate = 44100, .total_bshift = 0, - .post_gain_db = 0, // 0 dB + .post_gain_db = -4, // -4 dB .bands = { { .index = 0, - .type = FILTER_TYPE_BYPASS, - .fc = 130.00f, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, .q = 0.7500f, .bw = 1.00f, - .gain = -4.00f, + .gain = -1.00f, }, { .index = 1, - .type = FILTER_TYPE_BYPASS, - .fc = 80.00f, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, .q = 0.7500f, .bw = 1.00f, - .gain = 0.00f, + .gain = -1.00f, }, { .index = 2, - .type = FILTER_TYPE_BYPASS, - .fc = 2000.00f, - .q = 0.5000f, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, .bw = 1.00f, - .gain = 1.50f, + .gain = -1.00f, }, { .index = 3, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, .bw = 1.00f, - .gain = 0.00f, + .gain = 2.00f, }, { .index = 4, - .type = FILTER_TYPE_BYPASS, + .type = FILTER_TYPE_PEAKING, .fc = 1000.00f, - .q = 0.7100f, + .q = 0.7500f, .bw = 1.00f, - .gain = 0.00f, + .gain = 3.00f, }, { .index = 5, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, .q = 0.7100f, .bw = 1.00f, .gain = 0.00f, }, { .index = 6, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, .bw = 1.00f, - .gain = 0.00f, + .gain = -2.00f, }, { .index = 7, - .type = FILTER_TYPE_BYPASS, - .fc = 1000.00f, - .q = 0.7100f, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, .bw = 1.00f, - .gain = 0.00f, + .gain = -2.00f, }, }, .filter = { .biquad_count = MAX_EQ_BANDS, .state = {{0}}, .coef = { - {0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x3ff41df7, 0x3fe893cf, 0x3fd1c50d, 0x40c02ea5, 0x42487f62, 0x3fffffff, 0x3a4e238c, 0x3ae09727}, + {-0x7f242665, -0x7e4c1b74, -0x7c998928, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1e56eff0, 0x32e4d9ca}, + {0x3f31581a, 0x3e68a876, 0x3cdc02d8, 0x39735b92, 0x32a5d521, 0x1cc1863f, 0x0e5147e9, 0x134ef560}, + {0x7f242665, 0x7e4c1b74, 0x7c998928, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1e56eff0, -0x32e4d9ca}, + {-0x3f257611, -0x3e513c45, -0x3cadc7e6, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x089f6b75, -0x0e2f8c87}, }, } }, [9][0] = { .sample_rate = 44100, .total_bshift = 0, - .post_gain_db = 0, // 0 dB + .post_gain_db = -4, // -4 dB .bands = { { .index = 0, - .type = FILTER_TYPE_BYPASS, - .fc = 130.00f, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -5.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, .q = 0.7500f, .bw = 1.00f, .gain = -4.00f, }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 3.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fb48029, 0x3f905467, 0x3f64bdba, 0x40c02ea5, 0x42487f62, 0x3deb7030, 0x346e8b15, 0x38354b6d}, + {-0x7ea5add7, -0x7d9db5dd, -0x7bc4aba6, -0x79e431a7, -0x73bf050c, -0x4b8ec1f7, -0x1b488775, 0x30963485}, + {0x3ef27c0b, 0x3e127b31, 0x3c740a12, 0x39735b92, 0x32a5d521, 0x1bd23cf6, 0x0ce00e5f, 0x126ee045}, + {0x7ea5add7, 0x7d9db5dd, 0x7bc4aba6, 0x79e431a7, 0x73bf050c, 0x4b8ec1f7, 0x1b488775, -0x30963485}, + {-0x3ea6fc35, -0x3da2cf99, -0x3bd8c7cd, -0x3a338a38, -0x34ee5483, -0x19bdad27, -0x014e9974, -0x0aa42bb2}, + }, + } + }, + [9][1] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -5.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 3.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fb48029, 0x3f905467, 0x3f64bdba, 0x40c02ea5, 0x42487f62, 0x3deb7030, 0x346e8b15, 0x38354b6d}, + {-0x7ea5add7, -0x7d9db5dd, -0x7bc4aba6, -0x79e431a7, -0x73bf050c, -0x4b8ec1f7, -0x1b488775, 0x30963485}, + {0x3ef27c0b, 0x3e127b31, 0x3c740a12, 0x39735b92, 0x32a5d521, 0x1bd23cf6, 0x0ce00e5f, 0x126ee045}, + {0x7ea5add7, 0x7d9db5dd, 0x7bc4aba6, 0x79e431a7, 0x73bf050c, 0x4b8ec1f7, 0x1b488775, -0x30963485}, + {-0x3ea6fc35, -0x3da2cf99, -0x3bd8c7cd, -0x3a338a38, -0x34ee5483, -0x19bdad27, -0x014e9974, -0x0aa42bb2}, + }, + } + }, + [10][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 1.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fe6cdff, 0x3fce6059, 0x3fd1c50d, 0x405a90d5, 0x416edac4, 0x3fffffff, 0x3d2f1092, 0x3ae09727}, + {-0x7f09af46, -0x7e185409, -0x7c998928, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1fd66711, 0x32e4d9ca}, + {0x3f2430ad, 0x3e4f1267, 0x3cdc02d8, 0x39d8f962, 0x337f79bf, 0x1cc1863f, 0x0f063dc7, 0x134ef560}, + {0x7f09af46, 0x7e185409, 0x7c998928, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1fd66711, -0x32e4d9ca}, + {-0x3f0afeac, -0x3e1d72c0, -0x3cadc7e6, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x0c354e59, -0x0e2f8c87}, + }, + } + }, + [10][1] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 1.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fe6cdff, 0x3fce6059, 0x3fd1c50d, 0x405a90d5, 0x416edac4, 0x3fffffff, 0x3d2f1092, 0x3ae09727}, + {-0x7f09af46, -0x7e185409, -0x7c998928, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1fd66711, 0x32e4d9ca}, + {0x3f2430ad, 0x3e4f1267, 0x3cdc02d8, 0x39d8f962, 0x337f79bf, 0x1cc1863f, 0x0f063dc7, 0x134ef560}, + {0x7f09af46, 0x7e185409, 0x7c998928, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1fd66711, -0x32e4d9ca}, + {-0x3f0afeac, -0x3e1d72c0, -0x3cadc7e6, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x0c354e59, -0x0e2f8c87}, + }, + } + }, + [11][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fd7e4c8, 0x3fce6059, 0x3f9e3547, 0x40c02ea5, 0x416edac4, 0x3deb7030, 0x3761b4a8, 0x357cce9e}, + {-0x7eec0a91, -0x7e185409, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4b8ec1f7, -0x1cd17be8, 0x2e3c2813}, + {0x3f1574e0, 0x3e4f1267, 0x3caad74a, 0x39735b92, 0x337f79bf, 0x1bd23cf6, 0x0d997ea7, 0x118a77ac}, + {0x7eec0a91, 0x7e185409, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4b8ec1f7, 0x1cd17be8, -0x2e3c2813}, + {-0x3eed59a9, -0x3e1d72c0, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x19bdad27, -0x04fb334f, -0x0707464b}, + }, + } + }, + [11][1] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = -1.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -4.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fd7e4c8, 0x3fce6059, 0x3f9e3547, 0x40c02ea5, 0x416edac4, 0x3deb7030, 0x3761b4a8, 0x357cce9e}, + {-0x7eec0a91, -0x7e185409, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4b8ec1f7, -0x1cd17be8, 0x2e3c2813}, + {0x3f1574e0, 0x3e4f1267, 0x3caad74a, 0x39735b92, 0x337f79bf, 0x1bd23cf6, 0x0d997ea7, 0x118a77ac}, + {0x7eec0a91, 0x7e185409, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4b8ec1f7, 0x1cd17be8, -0x2e3c2813}, + {-0x3eed59a9, -0x3e1d72c0, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x19bdad27, -0x04fb334f, -0x0707464b}, + }, + } + }, + [12][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 1.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fe6cdff, 0x3fce6059, 0x3f9e3547, 0x40c02ea5, 0x40ace148, 0x3fffffff, 0x3a4e238c, 0x38354b6d}, + {-0x7f09af46, -0x7e185409, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1e56eff0, 0x30963485}, + {0x3f2430ad, 0x3e4f1267, 0x3caad74a, 0x39735b92, 0x3441733b, 0x1cc1863f, 0x0e5147e9, 0x126ee045}, + {0x7f09af46, 0x7e185409, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1e56eff0, -0x30963485}, + {-0x3f0afeac, -0x3e1d72c0, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x089f6b75, -0x0aa42bb2}, + }, + } + }, + [12][1] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = -4, // -4 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_PEAKING, + .fc = 63.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_PEAKING, + .fc = 125.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_PEAKING, + .fc = 250.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_PEAKING, + .fc = 500.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 2.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_PEAKING, + .fc = 1000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = 1.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_PEAKING, + .fc = 4000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_PEAKING, + .fc = 8000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -2.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_PEAKING, + .fc = 16000.00f, + .q = 0.7500f, + .bw = 1.00f, + .gain = -3.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x3fe6cdff, 0x3fce6059, 0x3f9e3547, 0x40c02ea5, 0x40ace148, 0x3fffffff, 0x3a4e238c, 0x38354b6d}, + {-0x7f09af46, -0x7e185409, -0x7c34de30, -0x79e431a7, -0x73bf050c, -0x4e189e14, -0x1e56eff0, 0x30963485}, + {0x3f2430ad, 0x3e4f1267, 0x3caad74a, 0x39735b92, 0x3441733b, 0x1cc1863f, 0x0e5147e9, 0x126ee045}, + {0x7f09af46, 0x7e185409, 0x7c34de30, 0x79e431a7, 0x73bf050c, 0x4e189e14, 0x1e56eff0, -0x30963485}, + {-0x3f0afeac, -0x3e1d72c0, -0x3c490c92, -0x3a338a38, -0x34ee5483, -0x1cc1863f, -0x089f6b75, -0x0aa42bb2}, + }, + } + }, + [13][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = 0, // 0 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, { .index = 1, .type = FILTER_TYPE_BYPASS, - .fc = 80.00f, - .q = 0.7500f, + .fc = 1000.00f, + .q = 0.7100f, .bw = 1.00f, .gain = 0.00f, }, { .index = 2, .type = FILTER_TYPE_BYPASS, - .fc = 2000.00f, - .q = 0.5000f, + .fc = 1000.00f, + .q = 0.7100f, .bw = 1.00f, - .gain = 1.50f, + .gain = 0.00f, }, { .index = 3, @@ -1563,7 +2220,7 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { }, } }, - [9][1] = { + [13][1] = { .sample_rate = 44100, .total_bshift = 0, .post_gain_db = 0, // 0 dB @@ -1571,26 +2228,190 @@ eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = { { .index = 0, .type = FILTER_TYPE_BYPASS, - .fc = 130.00f, - .q = 0.7500f, + .fc = 1000.00f, + .q = 0.7100f, .bw = 1.00f, - .gain = -4.00f, + .gain = 0.00f, }, { .index = 1, .type = FILTER_TYPE_BYPASS, - .fc = 80.00f, - .q = 0.7500f, + .fc = 1000.00f, + .q = 0.7100f, .bw = 1.00f, .gain = 0.00f, }, { .index = 2, .type = FILTER_TYPE_BYPASS, - .fc = 2000.00f, - .q = 0.5000f, + .fc = 1000.00f, + .q = 0.7100f, .bw = 1.00f, - .gain = 1.50f, + .gain = 0.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + }, + } + }, + [14][0] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = 0, // 0 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 3, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 4, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 5, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 6, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 7, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + }, + .filter = { + .biquad_count = MAX_EQ_BANDS, + .state = {{0}}, + .coef = { + {0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + }, + } + }, + [14][1] = { + .sample_rate = 44100, + .total_bshift = 0, + .post_gain_db = 0, // 0 dB + .bands = { + { + .index = 0, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 1, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, + }, + { + .index = 2, + .type = FILTER_TYPE_BYPASS, + .fc = 1000.00f, + .q = 0.7100f, + .bw = 1.00f, + .gain = 0.00f, }, { .index = 3, diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_api.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_api.h new file mode 100644 index 0000000..13f83ec --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_api.h @@ -0,0 +1,47 @@ +#ifndef __FPS_API_H__ +#define __FPS_API_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* 初始化 FPS 处理链及默认运行状态。 */ +void fps_xmos_xc_init(void); + +/* 选择游戏配置和档位。game: 0~2(0=cs2,1=pubg,2=delta),level: 0~4。 */ +void fps_xmos_xc_game_select(int game, int level); + +/* DRC 模式切换。mode: 0=low(柔和压缩),1=high(强力压缩)。 */ +void fps_xmos_xc_drc_set_mode(int mode); + +/* + * 设置运行时三个子模块的开关。 + * drc_enable: 0 表示旁路,非 0 表示开启 DRC + * fps_enable: 0 表示旁路 FPS 主处理,非 0 表示开启 + * eq_enable: 0 表示在 FPS 阶段旁路 EQ,非 0 表示开启 + */ +void fps_xmos_xc_set_module_enable(int drc_enable, int fps_enable, int eq_enable); + +/* 初始化运行,调节过程中不运行。 */ +/* 设置 10 段 EQ 的全部增益,单位为 0.01 dB,范围 -600 ~ 600。 */ +void fps_xmos_xc_eq_set_all_gains(int16_t *gains); + +/* 初始化不运行,调节过程中运行。 */ +/* 设置单个 EQ 频段增益,单位为 0.01 dB,范围 -600 ~ 600。 */ +void fps_xmos_xc_eq_set_band_gain(int band, int16_t gain); + +/* + * 处理一个双声道块。 + * input/output 数据格式为解交织的平面双声道: + * input[0..511] : 左声道 + * input[512..1023] : 右声道 + */ +void fps_xmos_xc_process(int16_t *input, int16_t *output); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.c b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.c new file mode 100644 index 0000000..d619f5a --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.c @@ -0,0 +1,173 @@ +/* 改动原因:FPS fps_eq 五模式增益在tile0侧LittleFS持久化 */ +#include +#include +#include "fps_eq_flash.h" +#include "lfs_io.h" +#include "debug_print.h" + +#define FPS_EQ_FLASH_PATH "fps_eq_store" +#define FPS_EQ_FLASH_VERSION 0x01u + +static void fps_eq_default_name(uint8_t mode, char out_name[FPS_EQ_NAME_LEN]) +{ + /* 改动原因:按协议约定提供小写默认模式名 fps_eq_0 ~ fps_eq_4 */ + snprintf(out_name, FPS_EQ_NAME_LEN, "fps_eq_%u", (unsigned)mode); +} + +/* 改动原因:仅判断“是否历史已存名称”,不做ASCII限制,兼容中文/多语言UTF-8 */ +static int fps_eq_name_has_saved_value(const char name[FPS_EQ_NAME_LEN]) +{ + int i; + int all_zero = 1; + int all_ff = 1; + int has_terminator = 0; + unsigned char first = (unsigned char)name[0]; + + for (i = 0; i < FPS_EQ_NAME_LEN; i++) { + unsigned char c = (unsigned char)name[i]; + if (c != 0x00) { + all_zero = 0; + } + if (c != 0xFF) { + all_ff = 0; + } + if (c == '\0') { + has_terminator = 1; + break; + } + } + + /* 旧数据或未初始化:全0或全0xFF,视为“未存名称” */ + if (all_zero || all_ff) { + return 0; + } + /* 改动原因:旧布局中常见 0x01 0x00...(增益=1)会误判为“有名称”,首字节为控制字节时视为未存 */ + if (first < 0x20) { + return 0; + } + /* 有数据但无\0终止,视为旧布局残留,回退默认名 */ + if (!has_terminator) { + return 0; + } + return 1; +} + +void fps_eq_flash_set_defaults(fps_eq_flash_store_t *store) +{ + int m, b; + + memset(store, 0, sizeof(*store)); + store->magic = FPS_EQ_FLASH_MAGIC; + store->version = FPS_EQ_FLASH_VERSION; + store->current_mode = 0; + for (m = 0; m < FPS_EQ_MODE_COUNT; m++) { + fps_eq_default_name((uint8_t)m, store->mode_names[m]); + for (b = 0; b < FPS_EQ_BAND_COUNT; b++) { + store->gains[m][b] = FPS_EQ_GAIN_DEFAULT; + } + } +} + +int16_t fps_eq_clamp_gain(int16_t gain) +{ + if (gain < FPS_EQ_GAIN_MIN) { + return FPS_EQ_GAIN_MIN; + } + if (gain > FPS_EQ_GAIN_MAX) { + return FPS_EQ_GAIN_MAX; + } + return gain; +} + +int fps_eq_flash_load(fps_eq_flash_store_t *out) +{ + fps_eq_flash_store_t tmp; + int m; + int need_repair = 0; + + fps_eq_flash_set_defaults(out); + + if (lfs_init() != 0) { + return -1; + } + + lfs_read_config((unsigned char *)FPS_EQ_FLASH_PATH, + (unsigned char *)&tmp, + sizeof(tmp)); + lfs_deinit(); + + if (tmp.magic != FPS_EQ_FLASH_MAGIC) { + debug_printf("fps_eq_flash: invalid magic, use defaults\n"); + return -1; + } + if (tmp.version != FPS_EQ_FLASH_VERSION) { + debug_printf("fps_eq_flash: version mismatch, reset defaults\n"); + return -1; + } + + if (tmp.current_mode >= FPS_EQ_MODE_COUNT) { + tmp.current_mode = 0; + need_repair = 1; + } + for (m = 0; m < FPS_EQ_MODE_COUNT; m++) { + tmp.mode_names[m][FPS_EQ_NAME_LEN - 1] = '\0'; + if (!fps_eq_name_has_saved_value(tmp.mode_names[m])) { + fps_eq_default_name((uint8_t)m, tmp.mode_names[m]); + need_repair = 1; + } + } + + *out = tmp; + /* 改动原因:检测到历史脏数据时自动修复并回写,后续读取稳定显示 */ + if (need_repair) { + (void)fps_eq_flash_save(out); + } + return 0; +} + +int fps_eq_flash_save(const fps_eq_flash_store_t *store) +{ + fps_eq_flash_store_t to_write = *store; + int m; + + to_write.magic = FPS_EQ_FLASH_MAGIC; + to_write.version = FPS_EQ_FLASH_VERSION; + if (to_write.current_mode >= FPS_EQ_MODE_COUNT) { + to_write.current_mode = 0; + } + for (m = 0; m < FPS_EQ_MODE_COUNT; m++) { + to_write.mode_names[m][FPS_EQ_NAME_LEN - 1] = '\0'; + if (to_write.mode_names[m][0] == '\0') { + fps_eq_default_name((uint8_t)m, to_write.mode_names[m]); + } + } + + if (lfs_init() != 0) { + return -1; + } + + lfs_write_config((unsigned char *)FPS_EQ_FLASH_PATH, + (unsigned char *)&to_write, + sizeof(to_write)); + lfs_deinit(); + return 0; +} + +void fps_eq_name_get(const fps_eq_flash_store_t *store, uint8_t mode, char out_name[FPS_EQ_NAME_LEN]) +{ + if (mode >= FPS_EQ_MODE_COUNT) { + mode = 0; + } + memcpy(out_name, store->mode_names[mode], FPS_EQ_NAME_LEN); + out_name[FPS_EQ_NAME_LEN - 1] = '\0'; +} + +void fps_eq_name_set(fps_eq_flash_store_t *store, uint8_t mode, const char *name) +{ + if (mode >= FPS_EQ_MODE_COUNT || name == NULL) { + return; + } + memset(store->mode_names[mode], 0, FPS_EQ_NAME_LEN); + strncpy(store->mode_names[mode], name, FPS_EQ_NAME_LEN - 1); + store->mode_names[mode][FPS_EQ_NAME_LEN - 1] = '\0'; +} diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.h new file mode 100644 index 0000000..9745d25 --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.h @@ -0,0 +1,32 @@ +#ifndef FPS_EQ_FLASH_H +#define FPS_EQ_FLASH_H + +#include + +/* 改动原因:FPS库fps_eq五套预设(模式0-4),每套10段增益,单位0.01dB,存于tile0 Flash */ +#define FPS_EQ_MODE_COUNT 5 +#define FPS_EQ_BAND_COUNT 10 +#define FPS_EQ_NAME_LEN 16 +#define FPS_EQ_GAIN_DEFAULT 1 +#define FPS_EQ_GAIN_MIN (-600) +#define FPS_EQ_GAIN_MAX 600 +#define FPS_EQ_FLASH_MAGIC 0x46505345u /* "FPSE" */ + +typedef struct { + uint32_t magic; + uint8_t version; + uint8_t current_mode; + uint8_t reserved[2]; + char mode_names[FPS_EQ_MODE_COUNT][FPS_EQ_NAME_LEN]; + int16_t gains[FPS_EQ_MODE_COUNT][FPS_EQ_BAND_COUNT]; +} fps_eq_flash_store_t; + +void fps_eq_flash_set_defaults(fps_eq_flash_store_t *store); +int fps_eq_flash_load(fps_eq_flash_store_t *out_data); +int fps_eq_flash_save(const fps_eq_flash_store_t *store); + +int16_t fps_eq_clamp_gain(int16_t gain); +void fps_eq_name_get(const fps_eq_flash_store_t *store, uint8_t mode, char out_name[FPS_EQ_NAME_LEN]); +void fps_eq_name_set(fps_eq_flash_store_t *store, uint8_t mode, const char *name); + +#endif diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_sync.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_sync.h new file mode 100644 index 0000000..75e4d5b --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_sync.h @@ -0,0 +1,22 @@ +#ifndef FPS_EQ_SYNC_H +#define FPS_EQ_SYNC_H + +#include +#include "fps_eq_flash.h" + +/* 改动原因:int16增益经5个int32共享字在tile0/tile1间传递(dp仅支持32位SHARED_GLOBAL) */ +extern unsigned g_fps_eq_mode; +extern int32_t g_fps_eq_pack0; +extern int32_t g_fps_eq_pack1; +extern int32_t g_fps_eq_pack2; +extern int32_t g_fps_eq_pack3; +extern int32_t g_fps_eq_pack4; + +void fps_eq_unpack_gains(int16_t out_gains[FPS_EQ_BAND_COUNT]); +void fps_eq_publish_gains_to_shared(const int16_t gains[FPS_EQ_BAND_COUNT]); +void fps_eq_publish_mode_and_gains(unsigned mode, const int16_t gains[FPS_EQ_BAND_COUNT]); + +void fps_apply_eq_mode(void); +void fps_apply_eq_band_gain(unsigned band, int16_t gain); + +#endif diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_tile_sync.c b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_tile_sync.c new file mode 100644 index 0000000..eb03acb --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_tile_sync.c @@ -0,0 +1,93 @@ +// Copyright 2024 XMOS LIMITED. +// 改动原因:tile0→tile1 FPS 同步命令排队,解决单槽 g_sync_t0_to_t1_cmd 被覆盖及跨 tile 全局无效问题 +#include +#include "xc_ptr.h" +#include "debug_print.h" +#include "fps_tile_sync.h" +#include "fps_eq_sync.h" +#include "user_uart.h" + +#define SYNC_T0_PENDING_MAX 12 + +extern unsigned g_sync_t0_to_t1_cmd; +extern unsigned g_sync_t0_to_t1_data; +extern unsigned g_sync_t0_to_t1_data2; + +static struct { + unsigned cmd; + unsigned data; + unsigned data2; +} s_sync_t0_pending[SYNC_T0_PENDING_MAX]; + +static unsigned s_sync_t0_pending_count = 0; + +void sync_t0_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2) +{ + if (s_sync_t0_pending_count >= SYNC_T0_PENDING_MAX) { + debug_printf("sync_t0: pending full, drop cmd 0x%02X\n", cmd); + return; + } + s_sync_t0_pending[s_sync_t0_pending_count].cmd = cmd; + s_sync_t0_pending[s_sync_t0_pending_count].data = data; + s_sync_t0_pending[s_sync_t0_pending_count].data2 = data2; + s_sync_t0_pending_count++; +} + +void sync_t0_send_or_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2) +{ + unsigned cur = 0; + + GET_SHARED_GLOBAL(cur, g_sync_t0_to_t1_cmd); + if (cur == 0) { + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, cmd); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, data); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, data2); + } else { + sync_t0_enqueue_to_tile1(cmd, data, data2); + } +} + +void sync_t0_promote_pending_to_tile1(void) +{ + unsigned cur = 0; + unsigned i; + + GET_SHARED_GLOBAL(cur, g_sync_t0_to_t1_cmd); + if (cur != 0 || s_sync_t0_pending_count == 0) { + return; + } + + SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, s_sync_t0_pending[0].cmd); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, s_sync_t0_pending[0].data); + SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, s_sync_t0_pending[0].data2); + + for (i = 1; i < s_sync_t0_pending_count; i++) { + s_sync_t0_pending[i - 1] = s_sync_t0_pending[i]; + } + s_sync_t0_pending_count--; +} + +void fps_eq_queue_pack_words_to_tile1(unsigned apply_on_last, unsigned enqueue_only) +{ + int32_t packs[5]; + unsigned i; + + GET_SHARED_GLOBAL(packs[0], g_fps_eq_pack0); + GET_SHARED_GLOBAL(packs[1], g_fps_eq_pack1); + GET_SHARED_GLOBAL(packs[2], g_fps_eq_pack2); + GET_SHARED_GLOBAL(packs[3], g_fps_eq_pack3); + GET_SHARED_GLOBAL(packs[4], g_fps_eq_pack4); + + for (i = 0; i < 5; i++) { + unsigned data1 = i; + unsigned apply_flag = (apply_on_last != 0 && i == 4) ? 1u : 0u; + + data1 |= (apply_flag << 8); + + if (enqueue_only) { + sync_t0_enqueue_to_tile1(SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK, data1, (unsigned)packs[i]); + } else { + sync_t0_send_or_enqueue_to_tile1(SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK, data1, (unsigned)packs[i]); + } + } +} diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_tile_sync.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_tile_sync.h new file mode 100644 index 0000000..1f9fb14 --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_tile_sync.h @@ -0,0 +1,16 @@ +#ifndef FPS_TILE_SYNC_H +#define FPS_TILE_SYNC_H + +/* 改动原因:tile0/tile1 内存不共享,FPS 配置须经 channel 排队同步到 tile1 */ + +void sync_t0_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2); +void sync_t0_send_or_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2); +void sync_t0_promote_pending_to_tile1(void); + +/* 改动原因:将 tile0 上已发布的 g_fps_eq_pack0..4 经 sync 0x0B 传到 tile1;末包 apply=1 时调用 fps_apply_eq_mode */ +void fps_eq_queue_pack_words_to_tile1(unsigned apply_on_last, unsigned enqueue_only); + +/* 改动原因:C1 无 UART/MCU 串口,上电在 tile0 直接从 Flash 恢复 FPS 并排队 sync 到 tile1(原 c3_fps 由 uart_handler 经 c_uart_sync 触发) */ +void fps_boot_load_from_flash(void); + +#endif diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_wrapper.c b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_wrapper.c index 93928ed..0f9d0c4 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_wrapper.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_wrapper.c @@ -10,33 +10,119 @@ #include "xc_ptr.h" #include "xua_conf.h" - -extern void fps_xmos_init(); -extern void fps_xmos_process(int16_t * input, int16_t* output, int channel); +/* 改动原因:FPS库V1.5改为单核xc接口,使用fps_api.h中的fps_xmos_xc_*声明 */ +#include "fps_api.h" +#include "fps_eq_sync.h" #define FPS_SLOT_NUM 3 #define FPS_FRAME_SIZE 512 -#define FPS_NUM_OUT 2 -short __attribute__((aligned (4))) dsp_fps_input_buf[FPS_SLOT_NUM][2][FPS_FRAME_SIZE]; -short __attribute__((aligned (4))) dsp_fps_out_buf[FPS_SLOT_NUM][2][FPS_FRAME_SIZE]; +/* 改动原因:新库process接口为平面双声道,左0..511、右512..1023,每槽1024个sample */ +#define FPS_PLANAR_SAMPLES (FPS_FRAME_SIZE * 2) -unsigned fps1_buf_ready = 0; -unsigned fps2_buf_ready = 0; -unsigned fps_write_pos = 0; -unsigned fps_process_pos = 0; +short __attribute__((aligned (4))) dsp_fps_input_buf[FPS_SLOT_NUM][FPS_PLANAR_SAMPLES]; +short __attribute__((aligned (4))) dsp_fps_out_buf[FPS_SLOT_NUM][FPS_PLANAR_SAMPLES]; +unsigned fps_buf_ready = 0; +unsigned fps_write_pos = 0; +unsigned fps_process_pos = 0; +/* 改动原因:tile0/tile1 内存不共享;game/level/使能/fps_eq 须经 channel sync 写入 tile1 副本 */ +unsigned g_fps_game_select = 1; +unsigned g_fps_level_select = 2; +/* 改动原因:FPS 默认开、DRC/fps_eq 默认关;与 audiohw 中 g_fps_enable(模式选择) 区分命名 */ +unsigned g_fps_drc_enable = 0; +unsigned g_fps_sub_enable = 1; +unsigned g_fps_eq_enable = 0; +/* 改动原因:DRC压缩模式默认0=low柔和压缩,HID 0xBD/断电保存fps_drc_mode后经sync同步到tile1 */ +unsigned g_fps_drc_mode = 0; + +/* 改动原因:fps_eq当前模式(0-4)与10段增益,经5个pack字在tile0/tile1共享 */ +unsigned g_fps_eq_mode = 0; +int32_t g_fps_eq_pack0 = 0; +int32_t g_fps_eq_pack1 = 0; +int32_t g_fps_eq_pack2 = 0; +int32_t g_fps_eq_pack3 = 0; +int32_t g_fps_eq_pack4 = 0; + +static int32_t fps_eq_make_pack(int16_t lo, int16_t hi) +{ + return ((int32_t)(uint16_t)lo) | (((int32_t)(uint16_t)hi) << 16); +} + +static int16_t fps_eq_pack_lo(int32_t w) +{ + return (int16_t)(w & 0xFFFF); +} + +static int16_t fps_eq_pack_hi(int32_t w) +{ + return (int16_t)((w >> 16) & 0xFFFF); +} + +void fps_eq_unpack_gains(int16_t out_gains[FPS_EQ_BAND_COUNT]) +{ + int32_t p0, p1, p2, p3, p4; + + GET_SHARED_GLOBAL(p0, g_fps_eq_pack0); + GET_SHARED_GLOBAL(p1, g_fps_eq_pack1); + GET_SHARED_GLOBAL(p2, g_fps_eq_pack2); + GET_SHARED_GLOBAL(p3, g_fps_eq_pack3); + GET_SHARED_GLOBAL(p4, g_fps_eq_pack4); + + out_gains[0] = fps_eq_pack_lo(p0); + out_gains[1] = fps_eq_pack_hi(p0); + out_gains[2] = fps_eq_pack_lo(p1); + out_gains[3] = fps_eq_pack_hi(p1); + out_gains[4] = fps_eq_pack_lo(p2); + out_gains[5] = fps_eq_pack_hi(p2); + out_gains[6] = fps_eq_pack_lo(p3); + out_gains[7] = fps_eq_pack_hi(p3); + out_gains[8] = fps_eq_pack_lo(p4); + out_gains[9] = fps_eq_pack_hi(p4); +} + +void fps_eq_publish_gains_to_shared(const int16_t gains[FPS_EQ_BAND_COUNT]) +{ + SET_SHARED_GLOBAL(g_fps_eq_pack0, fps_eq_make_pack(gains[0], gains[1])); + SET_SHARED_GLOBAL(g_fps_eq_pack1, fps_eq_make_pack(gains[2], gains[3])); + SET_SHARED_GLOBAL(g_fps_eq_pack2, fps_eq_make_pack(gains[4], gains[5])); + SET_SHARED_GLOBAL(g_fps_eq_pack3, fps_eq_make_pack(gains[6], gains[7])); + SET_SHARED_GLOBAL(g_fps_eq_pack4, fps_eq_make_pack(gains[8], gains[9])); +} + +void fps_eq_publish_mode_and_gains(unsigned mode, const int16_t gains[FPS_EQ_BAND_COUNT]) +{ + SET_SHARED_GLOBAL(g_fps_eq_mode, mode); + fps_eq_publish_gains_to_shared(gains); +} + +void fps_apply_eq_mode(void) +{ + int16_t gains[FPS_EQ_BAND_COUNT]; + + fps_eq_unpack_gains(gains); + /* 改动原因:切换模式时用eq_set_all_gains一次性加载当前模式10段增益 */ + fps_xmos_xc_eq_set_all_gains(gains); +} + +void fps_apply_eq_band_gain(unsigned band, int16_t gain) +{ + if (band >= FPS_EQ_BAND_COUNT) { + return; + } + /* 改动原因:运行中单段调节使用fps_xmos_xc_eq_set_band_gain */ + fps_xmos_xc_eq_set_band_gain((int)band, gain); +} void fps_main (chanend_t c_data ) { int input[2]; int output[2]; int count = 0; - unsigned write_pos = 0; - unsigned process_pos = 0; + unsigned write_pos = 0; unsigned read_pos = 0; - + while (1) { chan_in_buf_word (c_data , input, 2) ; @@ -44,19 +130,12 @@ void fps_main (chanend_t c_data ) { if (count == 0) read_pos = (write_pos + 1 + FPS_SLOT_NUM) % FPS_SLOT_NUM; - // 修改原因: 写入当前buffer,读取前一个已处理完的buffer,实现1帧延时 - // 写入位置:write_pos(当前正在填充的buffer) - for (int i = 0; i <2; i++) - { - dsp_fps_input_buf[write_pos][i][count] = (short)(input[i] >> 16); - } + /* 改动原因:按fps_xmos_xc_process要求的平面格式写入,左声道在前512,右声道在后512 */ + dsp_fps_input_buf[write_pos][count] = (short)(input[0] >> 16); + dsp_fps_input_buf[write_pos][FPS_FRAME_SIZE + count] = (short)(input[1] >> 16); - // 读取位置:read_pos(前一个已经DSP处理完成的buffer) - // 这样可以实现最小延时(1帧),避免原来的3帧延时问题 - for (int i = 0; i < 2; i++) - { - output[i] = (int)(dsp_fps_out_buf[read_pos][i][count]) << 16; - } + output[0] = (int)(dsp_fps_out_buf[read_pos][count]) << 16; + output[1] = (int)(dsp_fps_out_buf[read_pos][FPS_FRAME_SIZE + count]) << 16; if (count != (FPS_FRAME_SIZE - 1)) { @@ -64,84 +143,118 @@ void fps_main (chanend_t c_data ) { } else { - // 一帧完成,进行缓冲区切换 count = 0; // 修改原因: 实现1帧延时的三缓冲机制 // 步骤1: 将当前完成的写入buffer交给DSP处理任务 SET_SHARED_GLOBAL(fps_process_pos, write_pos); - - // 步骤2: 切换到下一个buffer进行写入(三缓冲循环:0→1→2→0) + write_pos = (write_pos + 1) % FPS_SLOT_NUM; SET_SHARED_GLOBAL(fps_write_pos, write_pos); - - SET_SHARED_GLOBAL(fps1_buf_ready, 1); - SET_SHARED_GLOBAL(fps2_buf_ready, 1); + + /* 改动原因:单核处理整帧立体声,仅需一个ready标志 */ + SET_SHARED_GLOBAL(fps_buf_ready, 1); } } } -unsigned long get_reference_time(); +/* 改动原因:按全局变量同步DRC压缩模式到算法库fps_xmos_xc_drc_set_mode */ +void fps_apply_drc_mode(void) +{ + unsigned drc_mode; + + GET_SHARED_GLOBAL(drc_mode, g_fps_drc_mode); + /* 改动原因:mode仅允许0=low、1=high,无效值回默认0 */ + if (drc_mode > 1) { + drc_mode = 0; + } + fps_xmos_xc_drc_set_mode((int)drc_mode); +} + +/* 改动原因:按全局变量同步DRC/FPS主处理/fps_eq三模块开关到算法库 */ +void fps_apply_module_enable(void) +{ + unsigned drc_enable; + unsigned fps_sub_enable; + unsigned eq_enable; + + GET_SHARED_GLOBAL(drc_enable, g_fps_drc_enable); + GET_SHARED_GLOBAL(fps_sub_enable, g_fps_sub_enable); + GET_SHARED_GLOBAL(eq_enable, g_fps_eq_enable); + + fps_xmos_xc_set_module_enable( + (drc_enable != 0) ? 1 : 0, + (fps_sub_enable != 0) ? 1 : 0, + (eq_enable != 0) ? 1 : 0); +} + +/* 改动原因:HID/tile0同步时在audiohw.xc中调用,供tile1在收到 sync 0x03(来自 HID 0xBF)时更新FPS算法参数 */ +void fps_apply_game_level_select(void) +{ + unsigned game_select; + unsigned level_select; + + GET_SHARED_GLOBAL(game_select, g_fps_game_select); + GET_SHARED_GLOBAL(level_select, g_fps_level_select); + if (game_select > 2) { + game_select = 0; + } + /* 改动原因:无效 level 默认档位 2,与 fps_level_g0/g1/g2 及 g_fps_level_select 一致 */ + if (level_select > 4) { + level_select = 2; + } + fps_xmos_xc_game_select((int)game_select, (int)level_select); +} + +/* 改动原因:集中FPS库初始化顺序——init→fps_eq全段增益→game/level→三模块使能 */ +static void fps_xmos_modules_init(void) +{ + unsigned game_select; + unsigned level_select; + int16_t gains[FPS_EQ_BAND_COUNT]; + + fps_xmos_xc_init(); + + /* 改动原因:从tile0已同步的共享pack字解出当前模式10段增益后初始化fps_eq */ + fps_eq_unpack_gains(gains); + fps_xmos_xc_eq_set_all_gains(gains); + + GET_SHARED_GLOBAL(game_select, g_fps_game_select); + GET_SHARED_GLOBAL(level_select, g_fps_level_select); + if (game_select > 2) { + game_select = 0; + } + /* 改动原因:上电/初始化时无效 level 默认档位 2 */ + if (level_select > 4) { + level_select = 2; + } + fps_xmos_xc_game_select((int)game_select, (int)level_select); + + /* 改动原因:上电/HID设置后须在module_enable前应用DRC压缩模式 */ + fps_apply_drc_mode(); + fps_apply_module_enable(); +} + void fps1_dsp_proc_task() { - fps_xmos_init(); -#if 1 + fps_xmos_modules_init(); + while (1) { - unsigned ready1; - // 修改原因: 使用声道0独立的ready标志,与声道1完全独立,避免竞态 - GET_SHARED_GLOBAL(ready1, fps1_buf_ready); - while (ready1) - { - // 修改原因: 关键修复 - 直接读取fps_main设置好的process_pos,避免自己计算导致的竞态 - unsigned cur_pos; - GET_SHARED_GLOBAL(cur_pos, fps_process_pos); - -#if 0 - for (int i = 0; i < FPS_FRAME_SIZE; i++) - { - dsp_fps_out_buf[cur_pos][0][i] = dsp_fps_input_buf[cur_pos][0][i]; - } -#else - // 处理声道0数据 - fps_xmos_process(&dsp_fps_input_buf[cur_pos][0], &dsp_fps_out_buf[cur_pos][0], 0); -#endif + unsigned ready; - ready1 = 0; - SET_SHARED_GLOBAL(fps1_buf_ready, 0); - } - } -#endif -} - -void fps2_dsp_proc_task() -{ -#if 1 - while (1) - { - unsigned ready2; - GET_SHARED_GLOBAL(ready2, fps2_buf_ready); - while (ready2) + GET_SHARED_GLOBAL(ready, fps_buf_ready); + while (ready) { unsigned cur_pos; + GET_SHARED_GLOBAL(cur_pos, fps_process_pos); - - // 处理声道1数据 - unsigned long start_time = get_reference_time(); -#if 0 - for (int i = 0; i < FPS_FRAME_SIZE; i++) - { - dsp_fps_out_buf[cur_pos][1][i] = dsp_fps_input_buf[cur_pos][1][i]; - } -#else - fps_xmos_process(&dsp_fps_input_buf[cur_pos][1], &dsp_fps_out_buf[cur_pos][1], 1); -#endif - unsigned long end_time = get_reference_time(); - // printf("fps2_dsp_proc_task time: %d ms\n", end_time - start_time); - // 修改原因: 只清除自己的ready标志,不影响声道0 - ready2 = 0; - SET_SHARED_GLOBAL(fps2_buf_ready, 0); + + /* 改动原因:单核一次处理左右声道平面块,不再分声道两次调用 */ + fps_xmos_xc_process(dsp_fps_input_buf[cur_pos], dsp_fps_out_buf[cur_pos]); + + ready = 0; + SET_SHARED_GLOBAL(fps_buf_ready, 0); } } -#endif } \ No newline at end of file diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/main.xc b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/main.xc index 61b9854..fe94159 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/main.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/main.xc @@ -14,6 +14,8 @@ #include #include #include +/* 改动原因:FPS 移植自 c3_fps,main.xc 中 fps_main/fps1_dsp_proc_task 启动日志需要 debug_printf */ +#include "debug_print.h" #ifdef XSCOPE #include #endif @@ -422,7 +424,6 @@ void usb_audio_io(chanend ?c_aud_in, #if XMOS_FPS_EN extern void fps_main(chanend c_data); extern void fps1_dsp_proc_task(); -extern void fps2_dsp_proc_task(); #endif /* Main for USB Audio Applications */ @@ -521,17 +522,16 @@ int main() #if XMOS_FPS_EN on tile[1]: { + debug_printf("start fps_main\n"); set_core_high_priority_on(); fps_main(c_data_transport); } on tile[1]: { + /* 改动原因:FPS库改为单核xc_process,仅需一个DSP任务处理整帧立体声 */ + debug_printf("start fps1_dsp_proc_task\n"); set_core_high_priority_on(); fps1_dsp_proc_task(); } - on tile[1]: { - set_core_high_priority_on(); - fps2_dsp_proc_task(); - } #else #if UAC1 on tile[1]: { diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_main.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_main.h index 501a992..a107a04 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_main.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_main.h @@ -16,7 +16,7 @@ interface c1_led_ctrl_if { void switch_handler(void); void flag_handler(); /* 改动原因:固件升级 START 在 AudioHwRemote2 处理,需传入 c_dfu;其余升级命令在 process_send_params 直接处理 */ -void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_erase, streaming chanend c_dfu); +void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu, chanend c_app_sync); void i2s_driver(chanend c); extern unsafe chanend uc_i2s; extern unsafe chanend uc_br_data; @@ -24,61 +24,47 @@ extern unsafe chanend uc_eq_data; extern void UserBufferManagementSetChan(chanend c); extern void dsp_main (chanend c_data , chanend cc_br_eof); extern void br_dsp_proc_task(chanend c_validate, chanend cc_br_eof); -extern void validate_algo(chanend c_validate); -void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl); +void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_sync); extern void dnr_dsp_proc_task(void); extern void dsp_core0(void); extern void eq_dsp_main(chanend c_data); extern unsafe streaming chanend uc_audiohw; extern unsafe streaming chanend uc_dfu; extern void fps1_dsp_proc_task(void); -extern void fps2_dsp_proc_task(void); +/* 改动原因:FPS库单核处理,fps2_dsp_proc_task已合并到fps1 */ +extern void fps_apply_game_level_select(void); +extern void fps_apply_module_enable(void); +extern void fps_apply_drc_mode(void); +extern void fps_apply_eq_mode(void); +extern void fps_apply_eq_band_gain(unsigned band, int16_t gain); +extern void fps_eq_boot_publish_to_tile1(void); +extern void fps_drc_boot_sync_to_tile1(void); +extern void fps_boot_load_from_flash(void); +extern unsigned g_fps_drc_enable; +extern unsigned g_fps_sub_enable; +extern unsigned g_fps_eq_enable; +extern unsigned g_fps_drc_mode; -#define USER_MAIN_DECLARATIONS chan c_data_transport, cc_br_eof, c_validate; \ - streaming chan c_audiohw; streaming chan c_dfu; interface c1_led_ctrl_if i_c1_led_ctrl; \ +#define USER_MAIN_DECLARATIONS streaming chan c_audiohw; streaming chan c_dfu; interface c1_led_ctrl_if i_c1_led_ctrl; \ chan c_usb_to_io; chan c_io_to_usb; chan c_io_to_dspL; chan c_dspL_to_io; chan c_io_to_dspR; chan c_dspR_to_io; \ - chan c_erase; + chan c_app_sync, c_data_transport; -#if !UAC1 #define USER_MAIN_CORES on tile[0]: {\ unsafe { \ uc_audiohw = (chanend) c_audiohw;\ uc_dfu = (chanend) c_dfu;\ - } \ - flag_handler(); \ - }\ - on tile[0]: {\ - AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_erase, c_dfu);\ - }\ - on tile[AUDIO_IO_TILE]: par {\ - dsp_core0();\ - } \ -\ - on tile[1]: app_control_slave(i_c1_led_ctrl); \ -\ - -#else -#define USER_MAIN_CORES on tile[0]: {\ - dnr_dsp_proc_task();\ - }\ - on tile[0]: {\ - unsafe { \ - uc_audiohw = (chanend) c_audiohw;\ + /* 改动原因:FPS/BR 音频经 c_data_transport 与 tile1 fps_main 交换;未赋值 uc_br_data 会导致 UserBufferManagement buffer_exchange ECALL */\ uc_br_data = (chanend) c_data_transport;\ - uc_dfu = (chanend) c_dfu;\ } \ - validate_algo(c_validate); \ }\ on tile[0]: {\ - AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_erase, c_dfu);\ + AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_dfu, c_app_sync);\ }\ - on tile[1]: { br_dsp_proc_task(c_validate, cc_br_eof); } \ - on tile[1]: app_control_slave(i_c1_led_ctrl); \ + on tile[1]: app_control_slave(i_c1_led_ctrl, c_app_sync); \ \ -#endif #else #define USER_MAIN_DECLARATIONS_A diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.h index 899977f..5fe5a6d 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.h @@ -1,11 +1,11 @@ #ifndef _UART_H_ #define _UART_H_ -#include -#include -#include -#include #include +#include +#include +#include +#include typedef enum { AUDIO_PCM_44100 = 0, @@ -263,4 +263,42 @@ typedef struct { unsigned char pendingReboot; } UserCmdConfig; +// Tile1到Tile0同步命令枚举 +// 改动原因:定义同步命令类型,用于tile1通过channel向tile0发送需要同步的操作 +typedef enum { + SYNC_CMD_NONE = 0x00, + SYNC_CMD_LOAD_CONFIGS = 0x01, // 加载配置(从Flash读取) + SYNC_CMD_SAVE_CONFIGS = 0x02, // 保存配置(写入Flash) + SYNC_CMD_SAVE_PRODUCT_INFO = 0x03, // 保存产品信息 + SYNC_CMD_SAVE_POWERUP_INFO = 0x04, // 保存上电配置 + SYNC_CMD_SAVE_USERCONFIG = 0x05, // 保存用户配置 + SYNC_CMD_GET_PID_VID = 0x06, // 获取并设置PID/VID + SYNC_CMD_SET_DAC_VOLUME = 0x07, // 设置DAC音量 + SYNC_CMD_SET_ADC_VOLUME = 0x08, // 设置ADC音量 + SYNC_CMD_SET_3D_FPS = 0x09, // 设置3D FPS(0x33命令) + SYNC_CMD_SET_ROLE_SWITCH = 0x0A, // 设置RoleSwitchFlag(oleSwitchFlag) + SYNC_CMD_STORE_MEMORY = 0x0B, // 存储内存数据(store_memory) + SYNC_CMD_SET_LED_MODE = 0x0C, // 设置LED模式(0x34命令) + SYNC_CMD_SET_ADC_LOOP = 0x0D, // 设置ADC Loop(0x31命令) + SYNC_CMD_MUTE_VALUE_FROM_MCU = 0x0E, // tile1收到MCU 0x5F响应后,将静音值传回tile0 +} SyncCmdType; + +// Tile0到Tile1同步命令枚举 +// 改动原因:定义反向同步命令类型,用于tile0通过channel向tile1发送需要同步的操作 +typedef enum { + SYNC_CMD_T0_TO_T1_NONE = 0x00, + SYNC_CMD_T0_TO_T1_SET_GAME_MODE = 0x01, // 设置游戏模式(HID 0xA4 -> UART 0x5A) + SYNC_CMD_T0_TO_T1_SET_UAC_MODE = 0x02, // 设置UAC模式(HID 0x9B -> UART 0x51) + SYNC_CMD_T0_TO_T1_SET_FPS_XMOS_GAME_SELECT = 0x03, // 设置FPS XMOS游戏选择(HID 0xBF -> fps_xmos_game_select) + SYNC_CMD_T0_TO_T1_SET_INPUT_SOURCE = 0x04, // 设置输入源(HID 0xB0 -> UART 0x5D) + SYNC_CMD_T0_TO_T1_SET_FPS_MODULE_ENABLE = 0x08, // 设置FPS库DRC/FPS/fps_eq使能(HID 0xB5 -> fps_xmos_xc_set_module_enable) + SYNC_CMD_T0_TO_T1_SET_FPS_EQ_MODE = 0x09, // 切换fps_eq模式并加载10段增益(HID 0xB7) + SYNC_CMD_T0_TO_T1_SET_FPS_EQ_BAND_GAIN = 0x0A, // 设置fps_eq单段增益(HID 0xB9) + SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK = 0x0B, // 同步fps_eq pack字到tile1(上电/HID 0xB7) + SYNC_CMD_T0_TO_T1_SET_FPS_DRC_MODE = 0x0C, // 设置DRC压缩模式(HID 0xBD -> fps_xmos_xc_drc_set_mode) + SYNC_CMD_T0_TO_T1_SET_MUTE_SWITCH = 0x05, // 设置静音开关(HID 0xB1 -> UART 0x5E) + SYNC_CMD_T0_TO_T1_SEND_GET_MUTE_REQUEST = 0x06, // 向MCU发0x5F获取静音(HID 0xB2) + SYNC_CMD_T0_TO_T1_SET_LISTEN_SWITCH = 0x07, // 设置监听开关(HID 0xB3 -> UART 0x60) +} SyncCmdT0ToT1Type; + #endif diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.xc b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.xc index c21a91f..1eb4f41 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/user_uart.xc @@ -34,6 +34,7 @@ extern "C" { #define RCV_CMD_TIMEOUT (500000000) //5s #define SEND_CMD_TIMEOUT (20000000) //200ms #define VOLUME_TIMEOUT (5500000) //55ms delay +#define BEAT_DELAY (500000) //10ms delay #define START_COUNTS (4) @@ -67,6 +68,22 @@ unsigned char g_save_configs = 0; unsigned g_usb_state = 1; unsigned int g_xu316_id; +/* 改动原因:0x07/0x08/0x09/0x0C/0x0D/0x0E 仅在值变化时同步到 tile0,用 pending 存 UART 下发的值,last_sync 存上次已同步的值,初值 -1 */ +unsigned g_pending_dac_vol = (unsigned)(-1); +unsigned g_pending_adc_vol = (unsigned)(-1); +unsigned g_pending_3d_fps = (unsigned)(-1); +unsigned g_pending_led_mode = (unsigned)(-1); +unsigned g_pending_adc_loop = (unsigned)(-1); +unsigned g_pending_mute_switch = (unsigned)(-1); +unsigned g_pending_mcu_mute = (unsigned)(-1); +unsigned g_last_sync_dac_vol = (unsigned)(-1); +unsigned g_last_sync_adc_vol = (unsigned)(-1); +unsigned g_last_sync_3d_fps = (unsigned)(-1); +unsigned g_last_sync_led_mode = (unsigned)(-1); +unsigned g_last_sync_adc_loop = (unsigned)(-1); +unsigned g_last_sync_mute_switch = (unsigned)(-1); +unsigned g_last_sync_mcu_mute = (unsigned)(-1); + extern audio_sampling g_playback_format; extern audio_type g_audio_type; extern unsigned g_led_mode; @@ -76,15 +93,18 @@ extern unsigned int read_key(void); extern unsigned g_dac_vol; extern unsigned g_adc_vol; extern unsigned g_adc_loop; -extern unsigned g_mute_switch; // 改动原因:与g_adc_loop一致,UART收到0x5F响应时直接设置,供HID变化上报 extern unsigned g_3d_fps; extern unsigned g_dac_mode; extern unsigned g_new_dac_mode; +extern unsigned g_sync_t0_to_t1_cmd; +extern unsigned g_sync_t0_to_t1_data; #if EQ_EN extern unsigned int g_current_eq_mode; // EQ当前模式 extern unsigned int g_old_eq_mode; // EQ当前模式 extern int process_eq_params_from_uart(uint8_t eq_mode, uint8_t eq_index, uint32_t sample_rate, float coefficients[5]); // EQ命令处理函数现在在eq.c中实现 +extern void process_uart_set_game_mode(uint8_t game_mode); // 改动原因:声明UART设置游戏模式函数,用于tile0到tile1同步 +extern void process_uart_set_uac_mode(uint8_t uac_mode); // 改动原因:声明UART设置UAC模式函数,用于tile0到tile1同步 #endif extern void read_uid_did(uint8_t uid[]); @@ -92,6 +112,41 @@ void device_reboot(void); uint8_t send_data[MAX_BUFFER_LEN] = {0}; +// 改动原因:用于存储需要同步的数据缓冲区(用于Flash操作等需要传递数据指针的情况) +static uint8_t sync_buffer[128]; +// 改动原因:全局同步channel,用于process_command中需要同步的操作(使用unsafe chanend因为需要在函数间传递) +static unsafe chanend g_c_uart_sync; + +// 改动原因:实现tile1到tile0的同步函数,用于将需要在tile0执行的操作通过channel发送 +static void sync_to_tile0(unsigned cmd, unsigned data1, unsigned data2) +{ + unsigned result; + unsafe { + g_c_uart_sync <: cmd; + g_c_uart_sync <: data1; + g_c_uart_sync <: data2; + g_c_uart_sync :> result; + } +} + +// 改动原因:实现tile1到tile0的数据传输函数,用于传输数据块(因为tile0和tile1内存不共享) +static void sync_data_to_tile0(unsigned cmd, uint8_t *data, unsigned len, unsigned extra_data) +{ + unsigned result; + unsigned i; + unsafe { + g_c_uart_sync <: cmd; + g_c_uart_sync <: len; // 先发送数据长度 + g_c_uart_sync <: extra_data; // 发送额外数据 + // 逐字节传输数据(因为tile0和tile1内存不共享,不能传递指针) + for(i = 0; i < len; i++) + { + g_c_uart_sync <: data[i]; + } + g_c_uart_sync :> result; + } +} + UserCmdConfig cmdConfig={0}; extern unsigned g_in_fw_upgrade; @@ -203,7 +258,7 @@ uint8_t send_user_cmd(uint8_t *request, uint8_t func_code, unsigned char version case START_FINISH: unsigned mode_code = 0; - unsigned mode = GetRoleSwitchFlag(); + unsigned mode =BT_IN_FLAG; switch (mode) { case UAC1_IN_FLAG: @@ -224,6 +279,7 @@ uint8_t send_user_cmd(uint8_t *request, uint8_t func_code, unsigned char version default: break; } + mode_code = 0x800100; request[4] = FINISH_CMD_DATA_LEN; request[5] = 0; @@ -256,10 +312,10 @@ uint8_t send_user_cmd(uint8_t *request, uint8_t func_code, unsigned char version } debug_printf("boot to user_mode %08x\n", mode_code); - SetRoleSwitchFlag(mode_code); - delay_milliseconds(1); - device_reboot(); - while(1); + //sync_to_tile0(0x0A, mode_code, 0); // SYNC_CMD_SET_ROLE_SWITCH + //delay_milliseconds(20); + //device_reboot(); + //while(1); } break; @@ -309,7 +365,6 @@ void update_button(unsigned char b) debug_printf("update_button %02x\n", 1<= 1) { - unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS]; - SET_SHARED_GLOBAL(g_mute_switch, mute_val); - debug_printf("set mcu mute state (0x61) %d\n", mute_val); - send_len = send_user_cmd(send_data, SET_MCU_MUTE_STATE, 0, 0); - xmos_printf(send_data, send_len); - } - break; #if UAC1 case SET_3D_FPS: - SET_SHARED_GLOBAL(g_3d_fps, data[CMD_DATA_POS]); + // 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0 + SET_SHARED_GLOBAL(g_pending_3d_fps, (unsigned)data[CMD_DATA_POS]); debug_printf("set 3d fps %d\n", data[CMD_DATA_POS]); send_len = send_user_cmd(send_data, SET_3D_FPS, 1, 0); xmos_printf(send_data, send_len); break; #endif case SET_LED_MODE: - SET_SHARED_GLOBAL(g_led_mode, data[CMD_DATA_POS]); + // 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0 + SET_SHARED_GLOBAL(g_pending_led_mode, (unsigned)data[CMD_DATA_POS]); debug_printf("set led mode %d\n", data[CMD_DATA_POS]); send_len = send_user_cmd(send_data, SET_LED_MODE, 1, 0); xmos_printf(send_data, send_len); break; + // 改动原因:0x5D/0x5E/0x60 仅由 XMOS 主动发给 MCU(tile1 收到 tile0 sync 后发),MCU 不会主动发这些;0x5F 响应由 MCU 发回 + case GET_MUTE_SWITCH: + // 改动原因:MCU 对 0x5F 请求的响应(1 字节静音值),与监听开关(g_adc_loop)一致,先缓存为pending,再在定时块按变化同步到tile0 + if (length >= 1) { + unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS]; + SET_SHARED_GLOBAL(g_pending_mute_switch, mute_val); + } + break; + // 改动原因:0x61 MCU设置静音状态给XU316,与0x31 SET_ADC_LOOP一致:先缓存为pending,定时块按变化同步到tile0(sync 0x0E) + case SET_MCU_MUTE_STATE: + if (length >= 1) { + unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS]; + SET_SHARED_GLOBAL(g_pending_mute_switch, mute_val); + debug_printf("set mcu mute state (0x61) %d\n", mute_val); + send_len = send_user_cmd(send_data, SET_MCU_MUTE_STATE, 0, 0); + xmos_printf(send_data, send_len); + } + break; + case SET_INPUT_SOURCE: + case SET_MUTE_SWITCH: + case SET_LISTEN_SWITCH: + // 改动原因:0x5D/0x5E/0x60 仅由 XMOS 发给 MCU,若 MCU 发来则忽略 + break; case FW_VERSION: send_len = send_user_cmd(send_data, FW_VERSION, 0, 3); xmos_printf(send_data, send_len); @@ -527,382 +613,12 @@ void process_command(uint8_t *data) send_len = send_user_cmd(send_data, FLASH_ID, 0, 20); xmos_printf(send_data, send_len); break; -#if EQ_EN - // EQ命令处理 - 调用eq.c中的函数 - case SET_EQ_MODE: - { - uint8_t mode = data[CMD_DATA_POS]; - uint8_t result = process_uart_set_eq_mode(mode); - uint8_t send_len = 0; - - // 发送确认响应 - send_len = send_user_cmd(send_data, SET_EQ_MODE, 0, 0); - xmos_printf(send_data, send_len); - } - break; - - case GET_EQ_MODE: - { - uint8_t response[64]; - // 检查是否有模式参数(数据长度>0表示有参数) - if (length > 0) { - uint8_t query_mode = data[CMD_DATA_POS]; - debug_printf("GET_EQ_MODE with mode parameter: %d\n", query_mode); - // 如果mode不是0xFF,临时设置request模式用于查询 - if (query_mode != 0xFF) { - SET_SHARED_GLOBAL(g_request_eq_mode, query_mode); - } - } - uint8_t len = process_uart_get_eq_mode(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_MODE_GAIN_AND_NAME: - { - uint8_t result = process_uart_set_mode_gain_and_name(data); - uint8_t send_len = 0; - - // 发送确认响应 - send_len = send_user_cmd(send_data, SET_MODE_GAIN_AND_NAME, 0, 0); - xmos_printf(send_data, send_len); - } - break; - - case SET_EQ_PARAMS: - { - uint8_t result = process_uart_set_eq_params(data); - uint8_t send_len = 0; - - // 发送确认响应 - send_len = send_user_cmd(send_data, SET_EQ_PARAMS, 0, 0); - xmos_printf(send_data, send_len); - } - break; - - case GET_EQ_PARAMS: - { - uint8_t response[64]; - uint8_t len = process_uart_get_eq_params(data, response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case RESET_EQ_PARAMS: - { - uint8_t result = process_uart_reset_eq_params(data); - uint8_t send_len = 0; - - // 发送响应 - send_data[CMD_DATA_POS] = result; - send_len = send_user_cmd(send_data, RESET_EQ_PARAMS, 0, 1); - xmos_printf(send_data, send_len); - } - break; - - case GET_DEVICE_INFO: - { - uint8_t response[64]; - uint8_t len = process_uart_get_device_info(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case GET_EQ_MODE_COUNT: - { - uint8_t response[64]; - uint8_t len = process_uart_get_eq_mode_count(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_AND_SAVE_EQ_MODE: - { - uint8_t result = process_uart_set_and_save_eq_mode(data); - uint8_t send_len = 0; - - // 发送响应 - send_data[CMD_DATA_POS] = result; - send_len = send_user_cmd(send_data, SET_AND_SAVE_EQ_MODE, 0, 1); - xmos_printf(send_data, send_len); - } - break; - - case SET_VOLUME: - // 改动原因:使用g_dac_vol,参考SET_DAC_VOLUME的实现方式,直接设置全局变量 - SET_SHARED_GLOBAL(g_dac_vol, data[CMD_DATA_POS]); - send_len = send_user_cmd(send_data, SET_VOLUME, 1, 0); - SET_SHARED_GLOBAL(g_dac_vol, data[CMD_DATA_POS]); - debug_printf("set volume %d\n", data[CMD_DATA_POS]); - xmos_printf(send_data, send_len); - break; - - case GET_VOLUME: - // 改动原因:直接读取g_dac_vol的值并返回,参考SET_DAC_VOLUME的实现方式 - { - uint8_t response[64]; - unsigned dac_vol; - GET_SHARED_GLOBAL(dac_vol, g_dac_vol); - // 构建响应数据包:0x55 0xAA 0x00 0x4A 0x01 [volume] [checksum] - response[0] = 0x55; // 帧头1 - response[1] = 0xAA; // 帧头2 - response[2] = 0x00; // 版本 - response[3] = GET_VOLUME; // 命令码 - response[4] = 0x01; // 数据长度 - response[5] = (uint8_t)dac_vol; // 音量级别 - // 计算校验和 - uint8_t checksum_pos = 6; - // 改动原因:使用check_sum函数计算校验和,与send_user_cmd函数保持一致 - unsafe { - response[checksum_pos] = check_sum(response, checksum_pos); - } - uint8_t len = checksum_pos + 1; - debug_printf("get volume %d\n", dac_vol); - xmos_printf(response, len); - } - break; - - case GET_LED_INFO: - { - uint8_t led_index = data[CMD_DATA_POS]; - uint8_t response[64]; - uint8_t len = process_uart_get_led_info(led_index, response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_LED_SWITCH: - // 改动原因:参考SET_LED_MODE,直接设置g_led_mode的值,0=关,1=开 - { - uint8_t led_index = data[CMD_DATA_POS]; - uint8_t led_switch = data[CMD_DATA_POS + 1]; - SET_SHARED_GLOBAL(g_led_mode, led_switch); - debug_printf("set led switch (g_led_mode) %d\n", led_switch); - uint8_t send_len = 0; - - // 发送响应 - send_data[CMD_DATA_POS] = 0; // 状态码:成功 - send_len = send_user_cmd(send_data, SET_LED_SWITCH, 0, 1); - xmos_printf(send_data, send_len); - } - break; - - case GET_LED_SWITCH: - // 改动原因:参考SET_LED_MODE,直接读取g_led_mode的值,0=关,1=开 - { - uint8_t led_index = data[CMD_DATA_POS]; - uint8_t response[64]; - unsigned led_mode; - GET_SHARED_GLOBAL(led_mode, g_led_mode); - - // 构建响应数据包:0x55 0xAA 0x00 0x4D 0x02 [led_index] [led_mode] [checksum] - response[0] = 0x55; // 帧头1 - response[1] = 0xAA; // 帧头2 - response[2] = 0x00; // 版本 - response[3] = GET_LED_SWITCH; // 命令码 - response[4] = 0x02; // 数据长度 - response[5] = led_index; // LED索引 - response[6] = (uint8_t)led_mode; // LED开关状态 - // 计算校验和 - uint8_t checksum_pos = 7; - unsafe { - response[checksum_pos] = check_sum(response, checksum_pos); - } - uint8_t len = checksum_pos + 1; - debug_printf("get led switch (g_led_mode) %d\n", led_mode); - xmos_printf(response, len); - } - break; - - case GET_LED_STATUS: - { - uint8_t led_index = data[CMD_DATA_POS]; - uint8_t response[64]; - uint8_t len = process_uart_get_led_status(led_index, response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case GET_LED_COUNT: - { - uint8_t response[64]; - uint8_t len = process_uart_get_led_count(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case GET_UAC_MODE_INFO: - { - uint8_t response[64]; - uint8_t len = process_uart_get_uac_mode_info(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_UAC_MODE: - { - uint8_t uac_mode = data[CMD_DATA_POS]; - // process_uart_set_uac_mode(uac_mode); - // 设备重启,无响应 - } - break; - - case GET_CURRENT_UAC_MODE: - { - uint8_t response[64]; - uint8_t len = process_uart_get_current_uac_mode(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_EQ_ENABLE: - { - uint8_t enable = data[CMD_DATA_POS]; - uint8_t result = process_uart_set_eq_enable(enable); - uint8_t response[64]; - uint8_t len = process_uart_get_eq_enable_response(result, enable, response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case GET_EQ_ENABLE: - { - debug_printf("user_uart.xc: GET_EQ_ENABLE command received, start processing\n"); - uint8_t response[64]; - uint8_t len = process_uart_get_eq_enable(response, sizeof(response)); - debug_printf("user_uart.xc: GET_EQ_ENABLE process_uart_get_eq_enable returned len=%d\n", len); - if (len > 0) { - debug_printf("user_uart.xc: GET_EQ_ENABLE sending response, length=%d, data: ", len); - for (int i = 0; i < len && i < 16; i++) { - debug_printf("%02X ", response[i]); - } - debug_printf("\n"); - xmos_printf(response, len); - debug_printf("user_uart.xc: GET_EQ_ENABLE response sent\n"); - } else { - debug_printf("user_uart.xc: GET_EQ_ENABLE error - process_uart_get_eq_enable returned len=0\n"); - } - } - break; - - case GET_SAMPLE_FORMAT: - { - uint8_t response[64]; - uint8_t len = process_uart_get_sample_format(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_GAIN_MODE: - { - uint8_t gain_mode = data[CMD_DATA_POS]; - uint8_t result = process_uart_set_gain_mode(gain_mode); - // 无需发送响应,根据协议描述 - } - break; - - case GET_GAIN_MODE: - { - uint8_t response[64]; - uint8_t len = process_uart_get_gain_mode(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_FILTER_MODE: - { - uint8_t filter_mode = data[CMD_DATA_POS]; - uint8_t result = process_uart_set_filter_mode(filter_mode); - // 无需发送响应,根据协议描述 - } - break; - - case GET_FILTER_MODE: - { - uint8_t response[64]; - uint8_t len = process_uart_get_filter_mode(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case SET_GAME_MODE: - { - uint8_t game_mode = data[CMD_DATA_POS]; - // 改动原因:UART 0x5A命令透传给MCU处理,MCU负责执行模式设置和参数保存 - // process_uart_set_game_mode(game_mode); - // 无需发送响应,根据协议描述 - } - break; - - case GET_GAME_MODE: - { - uint8_t response[64]; - uint8_t len = process_uart_get_game_mode(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - - case GET_FIRMWARE_VERSION: - { - uint8_t response[64]; - uint8_t len = process_uart_get_firmware_version(response, sizeof(response)); - if (len > 0) { - xmos_printf(response, len); - } - } - break; - // 改动原因:添加0x5D SET_INPUT_SOURCE,由HID 0xB0触发后XMOS主动发给MCU;若MCU发来0x5D则忽略 - case SET_INPUT_SOURCE: - break; - // 改动原因:添加0x5E SET_MUTE_SWITCH,由HID 0xB1触发后XMOS发给MCU;若MCU发来0x5E则忽略 - case SET_MUTE_SWITCH: - break; - // 改动原因:0x5F GET_MUTE_SWITCH 响应由MCU发来,含1字节静音值;与g_adc_loop一致直接设置g_mute_switch,0xB2读与变化上报均用g_mute_switch - case GET_MUTE_SWITCH: - if (length >= 1) { - unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS]; - SET_SHARED_GLOBAL(g_mute_switch, mute_val); - } - break; - // 改动原因:添加0x60 SET_LISTEN_SWITCH,由HID 0xB3触发后XMOS发给MCU;若MCU发来0x60则忽略 - case SET_LISTEN_SWITCH: - break; -#endif } } cmdConfig.cmdCount = 0; } - void xmos_uart_receive(void) { static unsigned cmd_start_time = 0; @@ -1137,115 +853,113 @@ void heatTick(unsigned long boot_time) } -extern unsigned GetDFUFlag(); -extern uint8_t key_validate(uint8_t offset); -extern void flash_opt_unlock(void); -/* 改动原因:固件升级 START 已移至 AudioHwRemote2,不再在此接收 c_dfu */ -void uart_handler(streaming chanend c_tx, streaming chanend c_rx) +void uart_handler(streaming chanend c_tx, streaming chanend c_rx,chanend c_sync) { unsigned long boot_time = get_reference_time(); - long int flag = 0; - long int dfu_flag = 0x11042011; - uint8_t uart_rx_byte; - g_xu316_id = read_key(); + unsigned long heat_tick_time = get_reference_time() + BEAT_DELAY * 10; + // 改动原因:保存同步channel到全局变量,供process_command使用(使用unsafe转换) + unsafe { + g_c_uart_sync = (chanend)c_sync; + } + cmdConfig.pendingReboot = 0; cmdConfig.cmdPending = CMD_NONE; unsigned long se_time = 0; timer se_tmr; se_tmr :> se_time; se_time += 2000000; -#if UAC1 - delay_milliseconds(100); -#endif -#if XUA_DFU_EN - flag = GetDFUFlag(); -#endif + // delay_milliseconds(100); - if (key_validate(1) == 1) - { - SetKeyFlag(0x20241224); - } - - - flash_opt_unlock(); - -#if BOOT_MODE - - load_configs(); - -#if (XUA_DFU_EN == 1) - get_pid_vid(); - if (flag == dfu_flag) - SET_SHARED_GLOBAL(g_usb_state, 1); - -#if (FACT_MODE == 1) - SET_SHARED_GLOBAL(g_usb_state, 1); - return; -#endif - -#endif - -#else cmdConfig.startApp = 3; - #if (NUM_USB_CHAN_OUT != 0) || (NUM_USB_CHAN_IN != 0) - load_configs(); - get_pid_vid(); - SET_SHARED_GLOBAL(g_usb_state, 1); -#endif - - + // 改动原因:load_configs和get_pid_vid需要在tile0执行(Flash访问和PID/VID设置),通过同步channel发送 + // 注意:此时g_c_uart_sync已经设置,可以直接使用 + sync_to_tile0(0x01, 0, 0); // SYNC_CMD_LOAD_CONFIGS + sync_to_tile0(0x06, 0, 0); // SYNC_CMD_GET_PID_VID #endif boot_time = get_reference_time(); + static unsigned char heat_tick_first_executed = 0; // 改动原因:跟踪heatTick是否已执行过第一次 while(1) { select { case c_rx :> uart_rx_byte: -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif - { X_RXbuff[X_Rxfp] = uart_rx_byte; X_Rxfp = (X_Rxfp + 1) % MAX_RX_LEN; //debug_printf("in[%02x] %d %d len %d\n", uart_rx_byte, X_Rxfp, X_Rxrp, MAX_RX_LEN - ((X_Rxfp - X_Rxrp + MAX_RX_LEN) % MAX_RX_LEN)); xmos_uart_receive(); - } break; case se_tmr when timerafter(se_time) :> void : se_time += 400000; - /* 改动原因:若有固件升级开始/结束通知,先组包 0x62 发给 MCU,再清零标志 */ -#if HID_DFU_EN - { - unsigned notify = get_firmware_upgrade_mcu_notify(); - if (notify != 0) - { - unsigned char response[8]; - response[0] = 0x55; - response[1] = 0xAA; - response[2] = 0x01; - response[3] = (unsigned char)FIRMWARE_UPGRADE_NOTIFY; - response[4] = 0x01; - response[5] = (unsigned char)notify; - unsafe { - response[6] = check_sum((unsigned char *)response, 6); - } - xmos_printf(response, 7); - clear_firmware_upgrade_mcu_notify(); - } - } -#endif - #if XUA_DFU_EN - if (flag != dfu_flag) - #endif + + { xmos_printf_pross(c_tx); - heatTick(boot_time); + // 改动原因:第一次执行要在boot_time后200ms,后续一直执行 + unsigned long tick_now = get_reference_time(); + if (heat_tick_first_executed == 0) { + // 第一次执行:检查是否已经过了boot_time + 200ms + if (timeafter(tick_now, boot_time + 20000000)) { // 200ms = 20000000 时间单位(参考SEND_CMD_TIMEOUT) + heatTick(boot_time); + heat_tick_first_executed = 1; + } + } else { + // 后续执行:一直执行 + heatTick(boot_time); + } } + /* 改动原因:0x07/0x08/0x09/0x0C/0x0D/0x0E 仅当 pending 与 last_sync 不同时才同步到 tile0 */ + { + unsigned pending_val, last_val; + GET_SHARED_GLOBAL(pending_val, g_pending_dac_vol); + GET_SHARED_GLOBAL(last_val, g_last_sync_dac_vol); + if (pending_val != last_val) { + sync_to_tile0(0x07, pending_val, 0); /* SYNC_CMD_SET_DAC_VOLUME */ + SET_SHARED_GLOBAL(g_last_sync_dac_vol, pending_val); + } + GET_SHARED_GLOBAL(pending_val, g_pending_adc_vol); + GET_SHARED_GLOBAL(last_val, g_last_sync_adc_vol); + if (pending_val != last_val) { + sync_to_tile0(0x08, pending_val, 0); /* SYNC_CMD_SET_ADC_VOLUME */ + SET_SHARED_GLOBAL(g_last_sync_adc_vol, pending_val); + } +#if UAC1 + GET_SHARED_GLOBAL(pending_val, g_pending_3d_fps); + GET_SHARED_GLOBAL(last_val, g_last_sync_3d_fps); + if (pending_val != last_val) { + sync_to_tile0(0x09, pending_val, 0); /* SYNC_CMD_SET_3D_FPS */ + SET_SHARED_GLOBAL(g_last_sync_3d_fps, pending_val); + } +#endif + GET_SHARED_GLOBAL(pending_val, g_pending_led_mode); + GET_SHARED_GLOBAL(last_val, g_last_sync_led_mode); + if (pending_val != last_val) { + sync_to_tile0(0x0C, pending_val, 0); /* SYNC_CMD_SET_LED_MODE */ + SET_SHARED_GLOBAL(g_last_sync_led_mode, pending_val); + } + GET_SHARED_GLOBAL(pending_val, g_pending_adc_loop); + GET_SHARED_GLOBAL(last_val, g_last_sync_adc_loop); + if (pending_val != last_val) { + sync_to_tile0(0x0D, pending_val, 0); /* SYNC_CMD_SET_ADC_LOOP */ + SET_SHARED_GLOBAL(g_last_sync_adc_loop, pending_val); + } + GET_SHARED_GLOBAL(pending_val, g_pending_mute_switch); + GET_SHARED_GLOBAL(last_val, g_last_sync_mute_switch); + if (pending_val != last_val) { + sync_to_tile0(0x0E, pending_val, 0); /* SYNC_CMD_MUTE_VALUE_FROM_MCU */ + SET_SHARED_GLOBAL(g_last_sync_mute_switch, pending_val); + } + GET_SHARED_GLOBAL(pending_val, g_pending_mcu_mute); + GET_SHARED_GLOBAL(last_val, g_last_sync_mcu_mute); + if (pending_val != last_val) { + sync_to_tile0(0x0F, pending_val, 0); /* SYNC_CMD_SET_MCU_MUTE_STATE */ + SET_SHARED_GLOBAL(g_last_sync_mcu_mute, pending_val); + } + } if (cmdConfig.pendingReboot == 1) {