diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiohw.xc b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiohw.xc index 585b9c3..7d612d6 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiohw.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiohw.xc @@ -573,8 +573,123 @@ static void tx1_apply_mic_hid_level(unsigned hid_level) SET_SHARED_GLOBAL(g_request_mic_volume_set, 1); } +/* 改动原因:枪声/脚步 feature 条 0~12 格映射 EX3D 协议范围(LMT -35~0 dB,EXPAND 0~20) */ +#define TX1_LMT_THRESHOLD_MIN (-35) +#define TX1_LMT_THRESHOLD_MAX (0) +#define TX1_EXPAND_GAIN_MAX 20 + +static int tx1_bar_to_lmt_threshold(unsigned bar) +{ + if (bar > TX1_VOL_BAR_MAX) { + bar = TX1_VOL_BAR_MAX; + } + return TX1_LMT_THRESHOLD_MIN + + (int)((bar * 35u + (TX1_VOL_BAR_MAX / 2u)) / TX1_VOL_BAR_MAX); +} + +static unsigned tx1_bar_to_expand_gain(unsigned bar) +{ + if (bar > TX1_VOL_BAR_MAX) { + bar = TX1_VOL_BAR_MAX; + } + return (bar * 20u + (TX1_VOL_BAR_MAX / 2u)) / TX1_VOL_BAR_MAX; +} + +static unsigned tx1_lmt_threshold_to_bar(int threshold) +{ + if (threshold < TX1_LMT_THRESHOLD_MIN) { + threshold = TX1_LMT_THRESHOLD_MIN; + } + if (threshold > TX1_LMT_THRESHOLD_MAX) { + threshold = TX1_LMT_THRESHOLD_MAX; + } + return (unsigned)((threshold - TX1_LMT_THRESHOLD_MIN) * TX1_VOL_BAR_MAX + 17) / 35u; +} + +static unsigned tx1_expand_gain_to_bar(unsigned gain) +{ + if (gain > TX1_EXPAND_GAIN_MAX) { + gain = TX1_EXPAND_GAIN_MAX; + } + return (gain * TX1_VOL_BAR_MAX + 10u) / 20u; +} + +static void tx1_send_lmt_threshold_to_tile1(chanend cc_mic_level, int threshold) +{ + if (threshold < TX1_LMT_THRESHOLD_MIN) { + threshold = TX1_LMT_THRESHOLD_MIN; + } + if (threshold > TX1_LMT_THRESHOLD_MAX) { + threshold = TX1_LMT_THRESHOLD_MAX; + } + cc_mic_level <: TX1_CC_CMD_LMT_THRESHOLD; + cc_mic_level <: (unsigned)threshold; + debug_printf("cc_mic_level send lmt_threshold=%d\n", threshold); +} + +static void tx1_send_expand_gain_to_tile1(chanend cc_mic_level, unsigned gain) +{ + if (gain > TX1_EXPAND_GAIN_MAX) { + gain = TX1_EXPAND_GAIN_MAX; + } + cc_mic_level <: TX1_CC_CMD_EXPAND_GAIN; + cc_mic_level <: gain; + debug_printf("cc_mic_level send expand_gain=%u\n", gain); +} + +/* 改动原因:面板调节枪声/脚步后,按 0xB1 GET_EX3D 格式主动上报,便于主机同步 UI */ +static void tx1_hid_report_ex3d_get_value(unsigned ex3d_get_cmd, int value) +{ + unsigned uval = (unsigned)value; + + unsafe { + unsigned char * unsafe reportPtr = g_hid_pass_data; + + reportPtr[0] = 0x77; + reportPtr[1] = 0xB1; + reportPtr[2] = (unsigned char)(ex3d_get_cmd & 0xFF); + reportPtr[3] = (unsigned char)((ex3d_get_cmd >> 8) & 0xFF); + reportPtr[4] = (unsigned char)((ex3d_get_cmd >> 16) & 0xFF); + reportPtr[5] = (unsigned char)((ex3d_get_cmd >> 24) & 0xFF); + reportPtr[6] = (unsigned char)(uval & 0xFF); + reportPtr[7] = (unsigned char)((uval >> 8) & 0xFF); + reportPtr[8] = (unsigned char)((uval >> 16) & 0xFF); + reportPtr[9] = (unsigned char)((uval >> 24) & 0xFF); + for (int i = 10; i < 63; i++) { + reportPtr[i] = 0x00; + } + hidSetChangePending(0x1); + } +} + +static unsigned tx1_apply_gunshot_bar(unsigned bar, chanend cc_mic_level, int &gunshot_thr) +{ + int th = tx1_bar_to_lmt_threshold(bar); + unsigned char save_code = tx1_lmt_threshold_to_save_code(th); + + gunshot_thr = th; + tx1_save_lmt_threshold_code(save_code); + tx1_send_lmt_threshold_to_tile1(cc_mic_level, th); + tx1_hid_report_ex3d_get_value(TX1_HID_GET_LMT_THRESHOLD, th); + debug_printf("TX1: gunshot bar=%u threshold=%d\n", bar, th); + return 1; +} + +static unsigned tx1_apply_footstep_bar(unsigned bar, chanend cc_mic_level, unsigned &footstep_gain) +{ + unsigned gain = tx1_bar_to_expand_gain(bar); + + footstep_gain = gain; + tx1_save_expand_gain((unsigned char)gain); + tx1_send_expand_gain_to_tile1(cc_mic_level, gain); + tx1_hid_report_ex3d_get_value(TX1_HID_GET_EXPAND_GAIN, (int)gain); + debug_printf("TX1: footstep bar=%u expand_gain=%u\n", bar, gain); + return 1; +} + /* 改动原因:FPS 切换 feature 时,把当前硬件音量同步到 0~12 格 RGB 条 */ -static void tx1_sync_feature_volume_from_hw(tx1_feature_mode_t mode, unsigned &feature_volume) +static void tx1_sync_feature_volume_from_hw(tx1_feature_mode_t mode, unsigned &feature_volume, + int gunshot_thr, unsigned footstep_gain) { unsigned hid; @@ -587,6 +702,12 @@ static void tx1_sync_feature_volume_from_hw(tx1_feature_mode_t mode, unsigned &f GET_SHARED_GLOBAL(hid, g_mic_volume_level); feature_volume = tx1_hid_level_to_bar(hid); break; + case FEATURE_MODE_GUNSHOT_LEVEL: + feature_volume = tx1_lmt_threshold_to_bar(gunshot_thr); + break; + case FEATURE_MODE_FOOTSTEPS_LEVEL: + feature_volume = tx1_expand_gain_to_bar(footstep_gain); + break; default: break; } @@ -838,7 +959,8 @@ static void tx1_sync_game_mode_state(unsigned mode, unsigned persist, * SYSTEM_VOLUME 按 12 格步进 DAC HID(0~48) 并写寄存器+Flash;MIC_LEVEL 同理写 ADC。 * 返回 1 表示需要 gpio_leds_dirty。 */ -static unsigned tx1_vol_plus_step(tx1_feature_mode_t mode, unsigned &feature_volume) +static unsigned tx1_vol_plus_step(tx1_feature_mode_t mode, unsigned &feature_volume, + chanend cc_mic_level, int &gunshot_thr, unsigned &footstep_gain) { switch (mode) { case FEATURE_MODE_NONE: @@ -857,11 +979,17 @@ static unsigned tx1_vol_plus_step(tx1_feature_mode_t mode, unsigned &feature_vol return 1; } case FEATURE_MODE_GUNSHOT_LEVEL: - case FEATURE_MODE_FOOTSTEPS_LEVEL: - if (feature_volume < TX1_VOL_BAR_MAX) { - feature_volume++; + if (feature_volume >= TX1_VOL_BAR_MAX) { + return 0; } - return 1; + feature_volume++; + return tx1_apply_gunshot_bar(feature_volume, cc_mic_level, gunshot_thr); + case FEATURE_MODE_FOOTSTEPS_LEVEL: + if (feature_volume >= TX1_VOL_BAR_MAX) { + return 0; + } + feature_volume++; + return tx1_apply_footstep_bar(feature_volume, cc_mic_level, footstep_gain); case FEATURE_MODE_MIC_LEVEL: if (feature_volume < TX1_VOL_BAR_MAX) { feature_volume++; @@ -876,7 +1004,8 @@ static unsigned tx1_vol_plus_step(tx1_feature_mode_t mode, unsigned &feature_vol /** * 改动原因:对齐 jok on_vol_minus_short_press,逻辑同 tx1_vol_plus_step 方向相反。 */ -static unsigned tx1_vol_minus_step(tx1_feature_mode_t mode, unsigned &feature_volume) +static unsigned tx1_vol_minus_step(tx1_feature_mode_t mode, unsigned &feature_volume, + chanend cc_mic_level, int &gunshot_thr, unsigned &footstep_gain) { switch (mode) { case FEATURE_MODE_NONE: @@ -895,11 +1024,17 @@ static unsigned tx1_vol_minus_step(tx1_feature_mode_t mode, unsigned &feature_vo return 1; } case FEATURE_MODE_GUNSHOT_LEVEL: - case FEATURE_MODE_FOOTSTEPS_LEVEL: - if (feature_volume > 0) { - feature_volume--; + if (feature_volume == 0) { + return 0; } - return 1; + feature_volume--; + return tx1_apply_gunshot_bar(feature_volume, cc_mic_level, gunshot_thr); + case FEATURE_MODE_FOOTSTEPS_LEVEL: + if (feature_volume == 0) { + return 0; + } + feature_volume--; + return tx1_apply_footstep_bar(feature_volume, cc_mic_level, footstep_gain); case FEATURE_MODE_MIC_LEVEL: if (feature_volume > 0) { feature_volume--; @@ -975,6 +1110,7 @@ static void tx1_send_ex3d_onoff_to_tile1(chanend cc_mic_level, unsigned onoff) cc_mic_level <: onoff; debug_printf("cc_mic_level send ex3d_onoff=%u\n", onoff); } + /* 改动原因:c_dfu 仅接收 FIRMWARE_UPGRADE_START,在此线程执行 handle_firmware_upgrade_start。 * 移除未使用的 chanend c_erase:原占位参数无任何 select/通信,会导致 main 侧被迫接 dummy 通道且与当前拓扑无关。 */ #if HID_DFU_EN @@ -1009,6 +1145,9 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface /* 改动原因:超时退出后再次 FPS 短按恢复上次调节项;首次进入默认系统音量。 */ tx1_feature_mode_t last_feature_mode = FEATURE_MODE_SYSTEM_VOLUME; unsigned feature_volume = 12; // 改动原因:与 jok ui_app gunshot/footstep/mic 默认 12 一致 + /* 改动原因:枪声 LMT_THRESHOLD(-35~0)、脚步 EXPAND_GAIN(0~20),与 EX3D HID 一致,断电 Flash 恢复 */ + int gunshot_lmt_threshold = -15; + unsigned footstep_expand_gain = 12; unsigned mic_muted = 0; /* 改动原因:与 phaten golden 相同 LFS 键名,断电保存 MIC 静音;255=首次无记录默认未静音 */ unsigned char mic_mute_path[] = "mic_mute"; @@ -1126,6 +1265,18 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface debug_printf("TX1: Loaded game_mode from flash: %u\n", (unsigned)game_mode); } + /* 改动原因:开机从 Flash 恢复枪声阈值/脚步增益并同步 tile1 EX3D(0xFA/0xFD) */ + { + unsigned char lmt_code = tx1_load_lmt_threshold_code(); + unsigned char exp_gain = tx1_load_expand_gain(); + + gunshot_lmt_threshold = tx1_lmt_threshold_from_save_code(lmt_code); + footstep_expand_gain = (unsigned)exp_gain; + tx1_send_lmt_threshold_to_tile1(cc_mic_level, gunshot_lmt_threshold); + tx1_send_expand_gain_to_tile1(cc_mic_level, footstep_expand_gain); + debug_printf("TX1: Loaded ex3d lmt=%d expand=%u\n", gunshot_lmt_threshold, footstep_expand_gain); + } + #if defined(FPS71_UAC2) debug_printf("FPS71_UAC2 running, g_3d_fps=%u\n", (unsigned)game_mode); #endif @@ -1305,6 +1456,43 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface } } + /* 改动原因:HID 0xB0 SET CMD_LMT_THRESHOLD/EXPAND_GAIN 经 eq.c 置位后,保存 Flash 并同步 tile1 */ + { + unsigned req_lmt; + GET_SHARED_GLOBAL(req_lmt, g_hid_lmt_threshold_request); + if (req_lmt != (unsigned)-1) { + SET_SHARED_GLOBAL(g_hid_lmt_threshold_request, (unsigned)-1); + if (req_lmt >= 1 && req_lmt <= 36) { + gunshot_lmt_threshold = tx1_lmt_threshold_from_save_code((unsigned char)req_lmt); + tx1_save_lmt_threshold_code((unsigned char)req_lmt); + tx1_send_lmt_threshold_to_tile1(cc_mic_level, gunshot_lmt_threshold); + if (feature_mode == FEATURE_MODE_GUNSHOT_LEVEL) { + feature_volume = tx1_lmt_threshold_to_bar(gunshot_lmt_threshold); + gpio_leds_dirty = 1; + } + debug_printf("HID SET LMT_THRESHOLD: save_code=%u thr=%d\n", + req_lmt, gunshot_lmt_threshold); + } + } + } + { + unsigned req_exp; + GET_SHARED_GLOBAL(req_exp, g_hid_expand_gain_request); + if (req_exp != (unsigned)-1) { + SET_SHARED_GLOBAL(g_hid_expand_gain_request, (unsigned)-1); + if (req_exp <= TX1_EXPAND_GAIN_MAX) { + footstep_expand_gain = req_exp; + tx1_save_expand_gain((unsigned char)req_exp); + tx1_send_expand_gain_to_tile1(cc_mic_level, footstep_expand_gain); + if (feature_mode == FEATURE_MODE_FOOTSTEPS_LEVEL) { + feature_volume = tx1_expand_gain_to_bar(footstep_expand_gain); + gpio_leds_dirty = 1; + } + debug_printf("HID SET EXPAND_GAIN: %u\n", footstep_expand_gain); + } + } + } + GET_SHARED_GLOBAL(dac_vol, g_dac_vol); GET_SHARED_GLOBAL(adc_vol, g_adc_vol); unsigned mute_switch; @@ -1880,7 +2068,9 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface if (!fps_long_fired && (now - fps_press_time) < 1000000000ull) { tx1_feature_mode_fps_short_press(feature_mode, last_feature_mode); feature_timeout_ticks = 0; - tx1_sync_feature_volume_from_hw(feature_mode, feature_volume); + tx1_sync_feature_volume_from_hw(feature_mode, feature_volume, + gunshot_lmt_threshold, + footstep_expand_gain); gpio_leds_dirty = 1; debug_printf("TX1: FPS short press - feature_mode=%d last=%d\n", feature_mode, last_feature_mode); @@ -1942,7 +2132,8 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface } else { if (!vol_plus_long_fired && (now - vol_plus_press_time) < TX1_LONG_PRESS_TICKS) { - if (tx1_vol_plus_step(feature_mode, feature_volume)) { + if (tx1_vol_plus_step(feature_mode, feature_volume, cc_mic_level, + gunshot_lmt_threshold, footstep_expand_gain)) { /* 改动原因:在 feature 模式下检测到 VOL+ 有效加值后,立即清零超时计数, * 防止用户持续调节时被 TX1_FEATURE_TIMEOUT_MAX 误判超时退出。 */ feature_timeout_ticks = 0; @@ -1961,7 +2152,8 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface static unsigned last_vol_plus_trigger = 0; if ((now - last_vol_plus_trigger) >= TX1_VOL_REPEAT_TICKS) { last_vol_plus_trigger = now; - if (tx1_vol_plus_step(feature_mode, feature_volume)) { + if (tx1_vol_plus_step(feature_mode, feature_volume, cc_mic_level, + gunshot_lmt_threshold, footstep_expand_gain)) { /* 改动原因:长按连发期间每次检测到 VOL+ 有效加值都重置 feature_timeout_ticks, * 保证 feature 页面在用户连续操作时保持激活。 */ feature_timeout_ticks = 0; @@ -1978,7 +2170,8 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface } else { if (!vol_minus_long_fired && (now - vol_minus_press_time) < TX1_LONG_PRESS_TICKS) { - if (tx1_vol_minus_step(feature_mode, feature_volume)) { + if (tx1_vol_minus_step(feature_mode, feature_volume, cc_mic_level, + gunshot_lmt_threshold, footstep_expand_gain)) { /* 改动原因:在 feature 模式下检测到 VOL- 有效减值后,立即清零超时计数, * 避免用户调整参数时触发 feature 超时返回。 */ feature_timeout_ticks = 0; @@ -1997,7 +2190,8 @@ void AudioHwRemote2(streaming chanend c, chanend cc_mic_level, client interface static unsigned last_vol_minus_trigger = 0; if ((now - last_vol_minus_trigger) >= TX1_VOL_REPEAT_TICKS) { last_vol_minus_trigger = now; - if (tx1_vol_minus_step(feature_mode, feature_volume)) { + if (tx1_vol_minus_step(feature_mode, feature_volume, cc_mic_level, + gunshot_lmt_threshold, footstep_expand_gain)) { /* 改动原因:长按连发期间每次检测到 VOL- 有效减值都重置 feature_timeout_ticks, * 与短按行为一致,避免连续减值过程中超时退出。 */ feature_timeout_ticks = 0; diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/tx1_ex3d_game.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/tx1_ex3d_game.h index 89b9e45..a9400a9 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/tx1_ex3d_game.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/tx1_ex3d_game.h @@ -36,4 +36,12 @@ extern unsigned g_3d_enable; /* tile0 audiohw → tile1 hid_button_task:0xFB + onoff(0/1) → audio_ex3d_set_onoff */ #define TX1_CC_CMD_EX3D_ONOFF 0xFB +/* tile0 → tile1:与 dsp.c hid_button_task 中 0xFA/0xFD 一致 */ +#define TX1_CC_CMD_LMT_THRESHOLD 0xFA +#define TX1_CC_CMD_EXPAND_GAIN 0xFD + +/* 主动 HID 上报用 GET 命令码(ex3d_protocol CMD_GET) */ +#define TX1_HID_GET_LMT_THRESHOLD 0x187 +#define TX1_HID_GET_EXPAND_GAIN 0x193 + #endif /* TX1_EX3D_GAME_H */ diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.c b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.c index ac819b4..a512f1a 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.c @@ -185,6 +185,73 @@ unsigned char tx1_load_mic_volume(void) return v; } +/* 改动原因:Flash 存 save_code=(-threshold)+1,范围 1~36,避免 0 作未初始化哨兵(与 eq.c HID 一致) */ +static unsigned char tx1_lmt_thr_lfs_path[] = "tx1_lmt_thr"; +static unsigned char tx1_expand_gain_lfs_path[] = "tx1_exp_gain"; + +void tx1_save_lmt_threshold_code(unsigned char save_code) +{ + if (save_code < 1) { + save_code = 1; + } + if (save_code > 36) { + save_code = 36; + } + save_value(tx1_lmt_thr_lfs_path, save_code); +} + +unsigned char tx1_load_lmt_threshold_code(void) +{ + unsigned char v = load_value(tx1_lmt_thr_lfs_path); + + if (v == 255 || v < 1 || v > 36) { + v = tx1_lmt_threshold_to_save_code(-15); + save_value(tx1_lmt_thr_lfs_path, v); + } + return v; +} + +int tx1_lmt_threshold_from_save_code(unsigned char save_code) +{ + if (save_code < 1) { + save_code = 1; + } + if (save_code > 36) { + save_code = 36; + } + return -(int)(save_code - 1); +} + +unsigned char tx1_lmt_threshold_to_save_code(int threshold) +{ + if (threshold > 0) { + threshold = 0; + } + if (threshold < -35) { + threshold = -35; + } + return (unsigned char)(-threshold + 1); +} + +void tx1_save_expand_gain(unsigned char gain) +{ + if (gain > 20) { + gain = 20; + } + save_value(tx1_expand_gain_lfs_path, gain); +} + +unsigned char tx1_load_expand_gain(void) +{ + unsigned char v = load_value(tx1_expand_gain_lfs_path); + + if (v == 255 || v > 20) { + v = 12; + save_value(tx1_expand_gain_lfs_path, v); + } + return v; +} + unsigned char load_value(unsigned char *path) { unsigned char value = 255; diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.h index 1874643..5ae2427 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_func.h @@ -70,5 +70,13 @@ unsigned char tx1_load_dac_volume(void); void tx1_save_mic_volume(unsigned char level); unsigned char tx1_load_mic_volume(void); +/* 改动原因:枪声 CMD_LMT_THRESHOLD(-35~0) 与脚步声 CMD_EXPAND_GAIN(0~20) 断电记忆,编码同 eq.c HID 0xB0 */ +void tx1_save_lmt_threshold_code(unsigned char save_code); +unsigned char tx1_load_lmt_threshold_code(void); +int tx1_lmt_threshold_from_save_code(unsigned char save_code); +unsigned char tx1_lmt_threshold_to_save_code(int threshold); +void tx1_save_expand_gain(unsigned char gain); +unsigned char tx1_load_expand_gain(void); + #endif