From b9303bccb8a4361f9f548d6ecb1c23bb8d358e56 Mon Sep 17 00:00:00 2001 From: Steven Dan Date: Thu, 14 May 2026 11:57:07 +0800 Subject: [PATCH] update app_usb_aud_fosi_c1_v71 --- .../app_usb_aud_fosi_c1/src/core/xua_conf.h | 6 +- .../app_usb_aud_fosi_c1_v71/CMakeLists.txt | 25 +- .../app_usb_aud_fosi_c1_v71/mode_cal.cmake | 53 + .../src/core/xua_conf.h | 2 +- .../src/extensions/audiohw.xc | 4071 +++++++---------- .../src/extensions/audiostream.xc | 25 +- .../src/extensions/codec_ti3204.h | 77 - .../src/extensions/dfu_upgrade.c | 48 +- .../src/extensions/dnr_dsp_buf.h | 7 - .../src/extensions/dsp.c | 18 +- .../src/extensions/dsp_core0.xc | 2 +- .../src/extensions/gpio_access.c | 50 + .../src/extensions/gpio_access.h | 17 + .../src/extensions/htr3236.xc | 252 - .../src/extensions/led_control.c | 331 -- .../src/extensions/main.xc | 59 +- .../src/extensions/user_func.c | 32 + .../src/extensions/user_main.h | 10 +- 18 files changed, 1996 insertions(+), 3089 deletions(-) create mode 100644 sw_usb_audio/app_usb_aud_fosi_c1_v71/mode_cal.cmake delete mode 100644 sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/codec_ti3204.h create mode 100644 sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.c create mode 100644 sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.h delete mode 100644 sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/htr3236.xc delete mode 100644 sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/led_control.c diff --git a/sw_usb_audio/app_usb_aud_fosi_c1/src/core/xua_conf.h b/sw_usb_audio/app_usb_aud_fosi_c1/src/core/xua_conf.h index 0dc5507..9cf5415 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1/src/core/xua_conf.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1/src/core/xua_conf.h @@ -162,7 +162,11 @@ /* Board power source - Default is bus-powered */ #ifndef XUA_POWERMODE -#define XUA_POWERMODE XUA_POWERMODE_SELF +#define XUA_POWERMODE XUA_POWERMODE_BUS +#endif + +#ifndef _XUA_BMAX_POWER +#define _XUA_BMAX_POWER (50) #endif /* Enable/Disable example HID code - Default is off */ diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/CMakeLists.txt b/sw_usb_audio/app_usb_aud_fosi_c1_v71/CMakeLists.txt index e55d34e..336e053 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/CMakeLists.txt +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/CMakeLists.txt @@ -40,28 +40,20 @@ set(SW_FACT_AUDIO_FLAGS ${EXTRA_BUILD_FLAGS} ${SW_FACT_VERSION} -LINK_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/../../lib_dnr/lib_dnr) - - - - - - - - set(APP_COMPILER_FLAGS_v71_uac2 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2 -DI2S_CHANS_ADC=2 -DMIN_FREQ=48000 -DMAX_FREQ=48000 + -DUAC1_MODE=0 -DUSE_EX3D=1 -DF3_F4_FPS_UAC2=1 -DMIXER=0 -DUAC2_MODE=1 -ldnr_50ms -llib_ex3d_all - -DEQ_EN=1 - -DDNR_ENABLE=1 + -DEQ_EN=0 + #-DDNR_ENABLE=1 -DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16 -DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16 -DINPUT_FORMAT_COUNT=1 @@ -83,15 +75,17 @@ set(APP_COMPILER_FLAGS_v71_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2 -DI2S_CHANS_ADC=2 -DMIN_FREQ=48000 -DAUDIO_CLASS=1 + -DUAC1_MODE=1 -DMAX_FREQ=48000 + -DWIN_OS_DETECTION=1 -DUSE_EX3D=1 -DF3_F4_FPS_UAC2=1 -DMIXER=0 -DUAC2_MODE=1 -ldnr_50ms -llib_ex3d_all - -DEQ_EN=1 - -DDNR_ENABLE=1 + -DEQ_EN=0 + #-DDNR_ENABLE=1 -DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=32 -DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=32 -DINPUT_FORMAT_COUNT=1 @@ -110,7 +104,10 @@ set(APP_COMPILER_FLAGS_v71_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2 -DHID_CONTROLS=1) -set(APP_INCLUDES src src/core src/extensions ../../lib_dnr/lib_dnr) +LINK_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/../../lib_dnr/lib_dnr ${CMAKE_CURRENT_LIST_DIR}/../../lib_ex3d/lib_ex3d/lib) + +set(APP_INCLUDES src src/core src/extensions ../shared/) + set(XMOS_SANDBOX_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) XMOS_REGISTER_APP() diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/mode_cal.cmake b/sw_usb_audio/app_usb_aud_fosi_c1_v71/mode_cal.cmake new file mode 100644 index 0000000..4c971e0 --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/mode_cal.cmake @@ -0,0 +1,53 @@ +function(calculate_config_value VALUES_VAR CONFIG_VALUE_VAR) + set(BYTE0 0) + set(BYTE1 0) + set(BYTE2 0) + set(BYTE3 0) + + foreach(FLAG ${${VALUES_VAR}}) + string(REPLACE "=" ";" FLAG_LIST ${FLAG}) + list(GET FLAG_LIST 0 KEY) + list(GET FLAG_LIST 1 VALUE) + + if("${KEY}" STREQUAL "I2S_MODE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 7" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "SYNC_MODE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 6" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "MIDI_ENABLE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 5" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "SPDIF_IN_ENABLE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 4" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "SPDIF_OUT_ENABLE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 3" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "ADAT_IN_ENABLE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 2" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "ADAT_OUT_ENABLE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE} << 1" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "DSD_OUT_ENABLE") + math(EXPR BYTE0 "${BYTE0} | ${VALUE}" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "AUDIO_SAMPLE_RATE") + math(EXPR BYTE1 "${BYTE1} | ${VALUE} & 0x0F" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "MQA_ENABLE") + math(EXPR BYTE1 "${BYTE1} | (${VALUE} << 4)" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "AUDIO_CLASS") + math(EXPR BYTE1 "${BYTE1} | (${VALUE} << 5)" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "AUDIO_WIDTH") + math(EXPR BYTE1 "${BYTE1} | (${VALUE} << 6)" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "INPUT_CHANNEL") + math(EXPR BYTE2 "${BYTE2} | ${VALUE} & 0x3F" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "OUTPUT_CHANNEL") + math(EXPR BYTE2 "${BYTE2} | (${VALUE} << 6) & 0xFC0" OUTPUT_FORMAT HEXADECIMAL) + elseif("${KEY}" STREQUAL "OTHER_CFG") + math(EXPR BYTE2 "${BYTE2} | (${VALUE} << 12) & 0xF000" OUTPUT_FORMAT HEXADECIMAL) + endif() + endforeach() + + # 打印每个字节的值 + #message(STATUS "BYTE0: 0x${BYTE0}") + #message(STATUS "BYTE1: 0x${BYTE1}") + #message(STATUS "BYTE2: 0x${BYTE2}") + #message(STATUS "BYTE3: 0x${BYTE3}") + math(EXPR CONFIG_VALUE "${BYTE3} << 24 | ${BYTE2} << 16 | ${BYTE1} << 8 | ${BYTE0}" OUTPUT_FORMAT HEXADECIMAL) + set(${CONFIG_VALUE_VAR} "${CONFIG_VALUE}" PARENT_SCOPE) +endfunction() + diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/core/xua_conf.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/core/xua_conf.h index a18eb3b..f5d2ccf 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/core/xua_conf.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/core/xua_conf.h @@ -131,7 +131,7 @@ #define XUD_TILE (0) #define PLL_REF_TILE (0) -#define AUDIO_IO_TILE (1) +#define AUDIO_IO_TILE (0) #define MIDI_TILE (1) /*** Defines relating to USB descriptor strings and ID's ***/ 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 6653234..9562997 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 @@ -1,9 +1,7 @@ #if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED #define DEBUG_PRINT_ENABLE 1 -#else -#define DEBUG_PRINT_ENABLE 0 #endif -//#define DISABLE_REBOOT 1 +#define DEBUG_PRINT_ENABLE 1 #include #include @@ -11,198 +9,237 @@ #include "xassert.h" #include "i2c.h" #include "xua.h" -#include +#include "gpio_access.h" #include "xc_ptr.h" -#include "user_uart.h" +#include #include "debug_print.h" +#include "user_uart.h" +#include "eq_flash_storage.h" +#include "lfs_io.h" #include "roleswitchflag.h" #include "xua_hid_report.h" -#include "lfs_io.h" - -#if defined (CODEC_AIC3204) -#include "eq_flash_storage.h" -#include "codec_ti3204.h" -#else -#error "No codec selected" +#include "nau88c21.h" +#if MQA_EN +#include "MQA_XMOS.h" #endif extern "C" { #include "sw_pll.h" + #include "dfu_upgrade.h" } -#include "xc_ptr.h" -unsigned g_ch0_level = 0; -unsigned g_ch1_level = 0; +#define TIMER_PERIOD 2000000 -#define NAU88C25 0 +#define DISABLE_REBOOT 1 -#if NAU88C25 -#include "nau88c25.h" -#else -#include "nau88c21.h" -#endif +#define MODE_FPS_UAC2 COAX_IN_FLAG // 1 FPS +#define MODE_FPS_UAC1 USB_IN_FLAG // 2 UAC1 +#define MODE_BR_UAC2 OPT_IN_FLAG // 3 BR +#define MODE_V71_UAC2 UAC1_IN_FLAG // 4 V71 +#define MODE_V71_UAC1 BT_IN_FLAG // 5 UAC1 -#if NAU88C25 -#define NAU88_I2C_DEVICE_ADDR 0x15 -#else -#define NAU88_I2C_DEVICE_ADDR 0x1B -#endif - -#include "htr3236.h" -#include "led_control.h" -#include "xmath/scalar/f32.h" - -#include "dnr_dsp_buf.h" - -#include "xua_hid_report.h" - -#if (XUA_PCM_FORMAT == XUA_PCM_FORMAT_TDM) && (XUA_I2S_N_BITS != 32) -#warning ADC only supports TDM operation at 32 bits -#endif - -#ifndef I2S_LOOPBACK -#define I2S_LOOPBACK (0) -#endif - - -#if UAC1 -unsigned g_uac_mode = 1; // 2 for UAC2.0, 1 for UAC1.0 -#else -unsigned g_uac_mode = 2; // 2 for UAC2.0, 1 for UAC1.0 -#endif - -unsafe client interface i2c_master_if i_i2c_client; +extern unsigned g_host_os; // 1 -> Windows, 2 -> Others audio_sampling g_new_playback_format, g_playback_format; audio_type g_new_audio_type, g_audio_type = 0; unsigned g_mute_enable = 0; -unsigned g_mute_state = 0; -unsigned g_mute_state_old = 1; unsigned g_unmute_dac_state, g_unmute_time, g_format_time; -// 改动原因:DAC音量协议扩展到49级(0~48),默认值同步到最大级48。 -unsigned g_volume_level = 24, g_saved_volume_level = 24; +unsigned g_volume_level = 60, g_saved_volume_level = 60; unsigned g_request_volume_set = 0; -unsigned g_init_saved_settings = 0; -unsigned g_host_volume = 0x0; -unsigned g_last_volume_level = 0xFF; // 上次已上报的音量级别,0xFF表示初始化未完成 -// 改动原因:麦克风HID等级调整为49级(0~48),并将最大模拟增益限制到24dB。 -unsigned g_mic_volume_level = 24; // 麦克风音量等级(0=mute, 1~48=0~24dB,0.5dB/级) -unsigned g_request_mic_volume_set = 0; -unsigned g_last_mic_volume_level = 0xFF; // 上次已上报的麦克风增益级别,0xFF表示初始化未完成 -unsigned g_dnr_strength = 100; // AI降噪强度HID值(1-100=档位,步进1;100→-200dB最强;关断由g_dnr_on控制,此处不再用0表示强度) -// 改动原因:用户要求与强度分离的开关量;关时仍保留g_dnr_strength供0x86读取与再次开启时恢复 -unsigned g_dnr_on = 1; // AI降噪总开关(0=关仅停算法,1=开且用g_dnr_strength档位) -unsigned g_last_dnr_strength = 0xFF; // 上次已上报的降噪强度,0xFF表示首次未上报(触发开机上报) -unsigned g_last_game_mode = 0xFF; // 上次已上报的音效模式,0xFF表示首次未上报(触发开机上报) -unsigned g_request_dnr_strength_set = 0; // HID 0x85 SET_AI_NOISE_STRENGTH待处理标志 -unsigned g_monitor_switch = 0; // 耳返开关(0=关闭,1=开启),默认关闭 -unsigned g_request_monitor_switch_set = 0; // HID 0x87 SET_MONITOR_SWITCH待处理标志 -unsigned g_dac_m_gain = 0; -unsigned g_unmute_delay_time = 0; -unsigned g_format_delay_time = 0; -unsigned g_mclk_select = 0; -// 改动原因:添加LED开关全局变量,控制LED是否显示(0=关闭,1=开启) -unsigned g_led_enable = 1; // LED开关,默认开启 -// HID 0xB0 CMD_EXPAND_GAIN到达时由eq.c设置,button_task读取后更新footstep LED -// -1 (0xFFFFFFFF) 表示无待处理请求 -unsigned g_hid_expand_gain_request = (unsigned)-1; -// HID 0xB0 CMD_LMT_THRESHOLD到达时由eq.c设置,button_task读取后保存到flash -// 存储值为-threshold (0~35);-1 (0xFFFFFFFF) 表示无待处理请求 -unsigned g_hid_lmt_threshold_request = (unsigned)-1; -// HID 0xB0 CMD_ANGLE到达时由eq.c设置,button_task读取后保存到flash -// channel=0xFFFFFFFF 表示批量更新所有通道 -#define EX3D_ANGLE_CHANNELS 8 - -unsigned g_hid_angle_values[EX3D_ANGLE_CHANNELS] = {0}; -unsigned g_hid_angle_values_old[EX3D_ANGLE_CHANNELS] = { 315, 45, 0, 0, 225, 135, 270, 90 }; - -// HID 0x84 FACTORY_RESET命令到达时由eq.c设置,button_task轮询后执行重启 -unsigned g_request_factory_reset = 0; +unsigned g_dac_vol = 0xB8; +unsigned g_adc_vol = 0x25; +unsigned g_adc_loop = 0; +unsigned g_mute_switch = 0; // 改动原因:与g_adc_loop一致,记录MCU回传的静音开关状态并用于HID变化上报(k6 UART在tile0可直接设置) +unsigned g_led_enable = 0; +unsigned g_dnr_enable = 1; +unsigned g_3d_enable = 1; +unsigned g_led_mode = 0; +unsigned g_fps_enable = 0; uint32_t get_reference_time(); -unsigned g_disable_i2c = 0; unsigned g_dac_mode = 10; unsigned g_new_dac_mode = 0; -unsigned g_samfreq = 48000; -unsigned g_dsd_mode = 0; - -void save_value(unsigned char * unsafe path, unsigned char value); -unsigned char load_value(unsigned char * unsafe path); -void save_value32(unsigned char * unsafe path, unsigned value); -unsigned load_value32(unsigned char * unsafe path); - -// mic detect events: mute_handler (tile[1]) → button_task (tile[0]) -#define MIC_DET_MUTE 1 // mic插入或全拔出,立即mute mic -#define MIC_DET_UNMUTE 2 // 插入1s后恢复mic音量 -#define MIC_DET_DAC_MUTE 3 // mic插入时mute DAC防pop -#define MIC_DET_DAC_UNMUTE 4 // 1s后恢复DAC音量 - -unsafe chanend uc_audiohw; // tile[1] end: AudioHwConfig → button_task (tile[0]) -#if HID_DFU_EN -unsafe streaming chanend uc_dfu; // tile[1] send end: hid_button_task → button_task (tile[0]) -#endif - -static void ex3d_angle_load_defaults(unsigned angles[EX3D_ANGLE_CHANNELS]) -{ - angles[0] = 315; - angles[1] = 45; - angles[2] = 0; - angles[3] = 0; - angles[4] = 225; - angles[5] = 135; - angles[6] = 270; - angles[7] = 90; -} - -static void ex3d_angle_make_path(unsigned channel, unsigned char path[6]) -{ - path[0] = 'x'; - path[1] = '3'; - path[2] = 'd'; - path[3] = 'a'; - path[4] = (unsigned char)('1' + channel); - path[5] = 0; -} - -static void ex3d_angle_save_channel(unsigned channel, unsigned angle) -{ - unsigned char path[6]; - debug_printf("ex3d_angle_save_channel: %d, %d\n", channel, angle); - // 改动原因:角度值改为单key一次写入32位,减少4次拆分写入的flash调用,提升效率并简化流程。 - ex3d_angle_make_path(channel, path); - save_value32(path, angle); -} - -static unsigned ex3d_angle_load_channel(unsigned channel, unsigned default_angle) -{ - unsigned char path[6]; - ex3d_angle_make_path(channel, path); - unsigned angle = load_value32(path); - - if (angle == 0xFFFFFFFF) { - // 改动原因:按用户要求去掉legacy迁移与归一化,未初始化时直接使用并保存默认值,流程最简。 - ex3d_angle_save_channel(channel, default_angle); - return default_angle; - } - - // debug_printf("ex3d_angle_load_channel: %d, %d\n", channel, angle); - // 改动原因:按用户要求去掉normalize,读取后直接返回原始32位角度值。 - return angle; -} +unsigned g_samfreq = DEFAULT_FREQ; +unsigned g_old_audio_type = 0; +// 改动原因:添加DSD模式全局变量,用于HID命令读取采样率和格式信息(已去掉DAC采样分辨率) +unsigned g_dsd_mode = 0; // DSD模式:0=PCM, >0=DSD +unsigned g_gain_mode = 0; // 0: 低阻, 1: 高阻 +// 改动原因:支持8种滤波器模式(0-7),与g_filter_map[8]数组定义一致 +unsigned g_filter_mode = 0; // 0-7: 对应8种滤波器模式 // 改动原因:添加增益模式和滤波器模式的请求变量,用于HID命令设置模式 +unsigned g_request_gain_mode = -1; // -1表示无请求,0=低阻,1=高阻 +// 改动原因:支持8种滤波器模式(0-7),与g_filter_map[8]数组定义一致 +unsigned g_request_filter_mode = -1; // -1表示无请求,0-7=滤波器模式 unsigned g_request_game_mode = -1; - +// 改动原因:新增C1模式全局变量,按需求定义0=蓝灯、1=绿灯;默认值为0并在开机时用Flash中的持久化值覆盖。 +unsigned g_c1_mode_value = 0; #if EQ_EN extern unsigned g_request_eq_mode, g_new_eq_mode; #endif +unsigned g_update_led = 0x0; -// tile 1, 3d_on_off -#define LED_ON 0 -#define LED_OFF 1 -#define S3D_ON LED_ON -#define S3D_OFF LED_OFF +/* 改动原因:eq.c 与 audiohw.xc 内 HID/EX3D/DNR 逻辑通过 GET/SET_SHARED_GLOBAL 访问下列符号; + * 此前仅保留 extern 或未声明导致链接器报 Undefined reference;在此补回与 audiohw.xc.bak / fosi_c1 一致的 + * 全局定义与初值(g_hid_pass_data 供 hidSetChangePending 等组包上报)。 */ +#define C1_EX3D_ANGLE_CHANNELS 8 +extern unsigned char g_hid_pass_data[64];; +unsigned g_3d_fps = 0; +unsigned g_mic_volume_level = 37; +unsigned g_request_mic_volume_set = 0; +unsigned g_dnr_strength = 100; +unsigned g_dnr_on = 1; +unsigned g_request_dnr_strength_set = 0; +unsigned g_monitor_switch = 0; +unsigned g_request_monitor_switch_set = 0; +unsigned g_hid_expand_gain_request = (unsigned)-1; +unsigned g_hid_lmt_threshold_request = (unsigned)-1; +unsigned g_hid_angle_values[C1_EX3D_ANGLE_CHANNELS] = {0}; +unsigned g_request_factory_reset = 0; -unsigned g_led_color = LED_OFF; -unsigned g_led_blink_count = 0; -unsigned g_led_blink_is_white = 0; +// CODEC I2C lines +on tile[0]: port p_scl = PORT_I2C_SCL; +on tile[0]: port p_sda = PORT_I2C_SDA; +on tile[0]: in port p_button = XS1_PORT_8D; //bit 4: mode button, bit 5: volume down button, bit 6: mic mute button, bit 7: volume up button + +on tile[1]: out port p_mode_led_red = XS1_PORT_1F; +on tile[1]: out port p_leds = XS1_PORT_4D; //bit 0: mode led green, bit 1: mode led blue, bit 2: mic mute led red, bit 3: mic mute led green +on tile[1]: out port p_mic_mute_led_blue = XS1_PORT_1G; + +timer tm; +#define SE_DELAY (2000000000) //20s delay +#define BOOT_TIMEOUT (1000000000) //5s delay +#define MUTE_ENABLE_DELAY (100000000) //1s delay +#define UMUTE_DELAY (15000000) //150ms delay +#define FORMAT_DELAY (30000000) //300ms delay +#define EQ_MODE_DELAY (100000000) //100ms delay +#define EQ_SYNC_DELAY (50000000) //500ms delay for EQ parameter sync + +// 改动原因:C1四个实体按键全部接在XS1_PORT_8D的bit4-bit7,统一定义位掩码,避免在按键状态机中直接使用魔数。 +#define C1_KEY_MODE_MASK 0x10 +#define C1_KEY_VOL_DOWN_MASK 0x20 +#define C1_KEY_MIC_MUTE_MASK 0x40 +#define C1_KEY_VOL_UP_MASK 0x80 + +// 改动原因:g_dac_vol在C1中按NAU88C22 DAC音量寄存器值保存,限制在现有dac_volume注释对应的-66dB~0dB范围内。 +#define C1_DAC_VOL_MIN 0x4B +#define C1_DAC_VOL_MAX 0xCF +#define C1_DAC_MUTE 0x00 +// 改动原因:DAC寄存器按2个码值对应1dB,按键每次调节步进固定为2,确保与硬件音量刻度一致。 +#define C1_DAC_VOL_STEP 0x02 + +// 改动原因:C1的TIMER_PERIOD为20ms,按DS1同类短按/长按模型换算阈值;mode/mic 仍用 LONG 区分短按窗口;音量键已取消长按连调故不再使用 REPEAT 间隔宏。 +#define C1_KEY_SHORT_TICKS 1 +#define C1_KEY_LONG_TICKS 50 +// 改动原因:规格要求 mic 键长按 1.5s 触发 AI 通话降噪开关;20ms*75=1.5s,与 mode 键的 C1_KEY_LONG_TICKS(1s) 解耦,避免误触。 +#define C1_KEY_MIC_AI_NR_TICKS 75 +// 改动原因:双击第二下需在首击释放后约 500ms 内按下,否则判为单击静音;20ms*25=500ms。 +#define C1_MIC_DOUBLE_DEFER_TICKS 25 +// 改动原因:新增C1模式持久化文件路径,使用LittleFS保存mode按键状态,保证断电重启后可恢复。 +#define C1_MODE_VALUE_PATH "c1_mode_value" + +// 改动原因:c1_mode 与 tile1 mode 灯索引一致:1=灭 2=蓝 3=绿 4=橙 5=紫;合法范围 1~5,interface 原样传 c1_mode。 +#define C1_MODE_VALUE_DEFAULT 1 +#define C1_MODE_VALUE_MIN 1 +#define C1_MODE_VALUE_MAX 5 + +// 改动原因:DAC 音量单独持久化路径,与 mode 的 c1_mode 文件分离,避免互相覆盖且便于维护。 +#define C1_DAC_VOL_INFO_PATH "c1_dac_vol" +// 改动原因:与 FORMAT_DELAY(30000000) 相同时间基准(get_reference_time 滴答),用户停止调节 300ms 后再写 Flash,减少磨损并满足需求。 +#define C1_DAC_VOL_SAVE_DELAY (30000000) + +// 改动原因:XS1_PORT_4E 耳机/MIC 插入检测位定义——bit2 高=耳机插入;bit3 低=MIC 插入、高=拔出(与硬件原理图一致)。 +#define C1_HP_DETECT_MASK 0x04u +#define C1_MIC_DETECT_MASK 0x08u +// 改动原因:插入后延迟与 EQ_SYNC_DELAY 相同 tick(get_reference_time),固定 500ms 再恢复 DAC/ADC 硬件音量,减轻插拔 pop。 +#define C1_JACK_RESTORE_DELAY EQ_SYNC_DELAY +// 改动原因:TIMER_PERIOD≈20ms,连续 3 次采样一致再认定电平稳定,避免检测脚抖动误触发。 +#define C1_JACK_DEBOUNCE_SAMPLES 3u + +extern void device_reboot(void); + +// 改动原因:判断 Flash 读出字节是否为合法 NAU88C22 DAC 音量码:0x00 表示按键规则下的 mute,0x4B~0xCF 为正常衰减范围。 +static unsigned c1_saved_dac_vol_is_valid(unsigned char v) +{ + if (v == C1_DAC_MUTE) + return 1; + if (v >= C1_DAC_VOL_MIN && v <= C1_DAC_VOL_MAX) + return 1; + return 0; +} + +// 改动原因:灯索引与 c1_mode 同值;仅钳位非法 Flash 读数,合法值原样下发 tile1,避免误映射。 +static inline unsigned c1_mode_to_tile_mode_led_code(unsigned mode_value) +{ + if (mode_value > C1_MODE_VALUE_MAX || mode_value < C1_MODE_VALUE_MIN) + return C1_MODE_VALUE_DEFAULT; + return mode_value; +} + +void switch_mode_by_c1_mode(unsigned c1_mode, unsigned force_reboot) +{ + unsigned reboot_need = 0; +#if UAC1_MODE == 0 + switch (c1_mode) + { + case 1: + SetRoleSwitchFlag(MODE_FPS_UAC2); + reboot_need = 0; + break; + case 2: + SetRoleSwitchFlag(MODE_BR_UAC2); + reboot_need = 1; + break; + case 3: + SetRoleSwitchFlag(MODE_V71_UAC2); + reboot_need = 1; + break; + case 4: + SetRoleSwitchFlag(MODE_FPS_UAC2); + reboot_need = 1; + break; + case 5: + SetRoleSwitchFlag(MODE_FPS_UAC2); + reboot_need = 0; + break; + } +#else + switch (c1_mode) + { + case 1: + SetRoleSwitchFlag(MODE_FPS_UAC1); + reboot_need = 0; + break; + case 2: + SetRoleSwitchFlag(MODE_V71_UAC1); + reboot_need = 1; + break; + case 3: + SetRoleSwitchFlag(MODE_V71_UAC1); + reboot_need = 0; + break; + case 4: + SetRoleSwitchFlag(MODE_FPS_UAC1); + reboot_need = 1; + break; + case 5: + SetRoleSwitchFlag(MODE_FPS_UAC1); + reboot_need = 0; + break; + } +#endif + if (reboot_need || force_reboot) + { + delay_milliseconds(20); + device_reboot(); + while (1); + } +} + +#define NAU88L21_PGA_GAIN_REG_MIN_USED_VALUE 0x0 // 0x1=1, 0dB (0x0, -1dB which is not used in this design) +#define NAU88L21_PGA_GAIN_REG_MAX_VALUE 0x25+1 // 0x25=37, 36dB. +1 is for extra 1.5dB digital gain +#define NAU88L21_PGA_GAIN_REG_DEFAULT_VALUE (NAU88L21_PGA_GAIN_REG_MAX_VALUE) + +// 改动原因:4E 为耳机/MIC 检测输入(读 bit2/bit3),原先声明为 out 无法采样;改为 in port 与硬件方向一致。 +on tile[0]: in port p_mic_phone_detect = XS1_PORT_4E; +on tile[0]: out port p_gpio = XS1_PORT_4F; #define LED_OFF 0x7F // 修改:清除最高位,只保留低7位 #define LED_RED 0b01011111 // 修改:清除最高位,只保留低7位 @@ -213,59 +250,100 @@ unsigned g_led_blink_is_white = 0; #define LED_PURPLE (LED_RED & LED_BLUE) #define LED_WHITE (LED_RED & LED_GREEN & LED_BLUE) enum { OS_WIN = 1, OS_OTHERS = 2 }; -// 改动原因:定义模式切换标志值,用于在SPATIAL_GAME、STEREO_8K、STEREO_2K、UAC1之间循环切换 -#define MODE_F3_F4_FPS_UAC2 COAX_IN_FLAG //1 SPATIAL_GAME模式标志 -#define MODE_F5_MUSIC_UAC1 USB_IN_FLAG // 2 F5 MUSIC -#define MODE_F1_MUSIC_UAC2 OPT_IN_FLAG // 3 F1 MUSIC -#define MODE_F6_F7_FPS_UAC1 UAC1_IN_FLAG // 4 STEREO_2K模式标志 +unsigned g_led_blink_count = 0; +unsigned g_led_blink_is_white = 0; -/* All on tile[0] */ -port p_scl = PORT_I2C_SCL; -port p_sda = PORT_I2C_SDA; +// 改动原因:g_hid_pass_data[] 定义已上移至与其它 HID 全局量同块,避免 extern 无实体导致链接失败。 +static unsigned g_last_dac_vol = 0xFF; // 改动原因:改为检测g_dac_vol的变化,初始化为0xFF表示未初始化 +static unsigned g_last_mute_switch = 0xFF; // 改动原因:检测静音开关变化并上报0xB2,0xFF=未初始化 +static unsigned g_last_adc_loop = 0xFF; // 改动原因:检测监听开关(g_adc_loop)变化并上报0xB4,0xFF=未初始化 +static unsigned g_last_audio_type = 0xFF; // 改动原因:上次检测到的音频类型,初始化为0xFF表示未初始化,用于LED颜色判断 +static unsigned g_last_led_status = 0xFF; // 上次检测到的LED状态,初始化为0xFF表示未初始化 +// 改动原因:添加采样率和格式监控变量,用于检测变化并上报HID(已去掉DAC采样分辨率) +unsigned g_last_samfreq = 0xFFFFFFFF; // 上次检测到的采样率,初始化为0xFFFFFFFF表示未初始化 +unsigned g_last_dsd_mode = 0xFF; // 上次检测到的DSD模式,初始化为0xFF表示未初始化 +// 改动原因:添加增益模式、滤波器模式和游戏模式监控变量,用于检测变化并上报HID +static unsigned g_last_gain_mode = 0xFF; // 上次检测到的增益模式,初始化为0xFF表示未初始化 +static unsigned g_last_filter_mode = 0xFF; // 上次检测到的滤波器模式,初始化为0xFF表示未初始化 +static unsigned g_last_game_mode = 0xFF; // 上次检测到的游戏模式,初始化为0xFF表示未初始化 +#if UAC1 +unsigned g_uac_mode = 1; // 2 for UAC2.0, 1 for UAC1.0 +#else +unsigned g_uac_mode = 2; // 2 for UAC2.0, 1 for UAC1.0 +#endif -//out port p_htr3235_sdb = PORT_HTR3236_SDB; /* 连接到HTR3236的SDB引脚,用于控制其电源状态 */ - -out port p_ctl_mute = PORT_CTL_MUTE; -port p_ctl_det = PORT_CTL_DET; +// 改动原因:XS1_PORT_8D现在作为C1四个实体按键端口p_button使用;旧p_8ch_in只在#if 0代码块中引用,继续声明会造成重复端口映射错误。 +// on tile[0]: in port p_8ch_in = XS1_PORT_8D; -/* Board setup for XU316 MC Audio (1v1) */ -void board_setup() +void device_reboot(void); + +unsafe streaming chanend uc_audiohw; +/* 改动原因:main 在绑定 uc_audiohw 后置 1;AudioHwInit 内自旋等待,避免与 usb_audio_io(同 tile 另一逻辑核)并行启动时 + * CODEC_REGWRITE 早于 uc_audiohw 初始化触发的 ET_ILLEGAL_RESOURCE。(xC 中 volatile 仅用于 unsafe 指针目标,故用普通 unsigned。) */ +unsigned g_uc_audiohw_chan_bound = 0; +/* 改动原因:添加 uc_dfu 全局 streaming chanend,用于从 EP0 HID 处理 + * (process_send_params) 向 uart_handler 转发固件升级命令。 + * sender 端在此处赋值(AudioHwRemote par 分支),receiver 端传给 uart_handler。 */ +unsafe streaming chanend uc_dfu; + +typedef enum { + AUDIOHW_CMD_REGWR, + AUDIOHW_CMD_REGRD +} audioHwCmd_t; +void unmute_dac(void); +void mute_dac(void); + +// 新增函数声明 +void pcm_to_dsd_switch(unsigned targetFreq); +void dsd_to_pcm_switch(unsigned targetFreq); + +void CODEC_REGWRITE(unsigned device, unsigned reg, unsigned val) +{ + unsafe + { + uc_audiohw <: (unsigned) AUDIOHW_CMD_REGWR; + uc_audiohw <: device; + uc_audiohw <: reg; + uc_audiohw <: val; + } } -// tile 0 -// called on tile 0 - start -// 改动原因:协议层改为49级(0~48),硬件仍是1dB步进;通过“2个等级映射1dB”实现24dB上限。 -#define MIC_HID_LEVEL_MIN 0 -#define MIC_HID_LEVEL_MAX 48 -#define MIC_HID_LEVEL_DEFAULT 24 // 24dB,保持原默认听感接近 -#define DAC_HID_LEVEL_DEFAULT 24 // 24dB,保持原默认听感接近 - -#define NAU88L21_PGA_GAIN_REG_MIN_USED_VALUE 0x0 // 0=mute -#define NAU88L21_PGA_GAIN_REG_MAX_VALUE 0x18 // 24dB上限 -#define NAU88L21_PGA_GAIN_REG_DEFAULT_VALUE 0x16 // 22dB默认 - -// 改动原因:49级HID等级(0.5dB/级)需映射到Codec 1dB步进寄存器,避免改动底层codec写寄存器逻辑。 -static inline unsigned mic_hid_level_to_codec_gain(unsigned hid_level) +/* 改动原因:实现 DFU channel 转发函数,将 HID 收到的 63 字节固件升级命令 + * 打包为 16 个 unsigned word 通过 streaming channel 发送到 uart_handler。 + * 该函数从 eq.c 的 process_send_params 中调用(代替原来直接调用 handle_* 函数)。 */ +void dfu_chan_forward(unsigned char data[], unsigned len) { - if (hid_level == 0) { - return 0; + unsafe + { + for (int i = 0; i < 16; i++) { + unsigned word = 0; + for (int j = 0; j < 4; j++) { + int idx = i * 4 + j; + if (idx < 63) { + word |= ((unsigned)data[idx]) << (j * 8); + } + } + uc_dfu <: word; + } } - // ceil(hid_level / 2),把两档HID映射到1dB硬件步进 - unsigned codec_gain = (hid_level + 1) >> 1; - if (codec_gain > NAU88L21_PGA_GAIN_REG_MAX_VALUE) { - codec_gain = NAU88L21_PGA_GAIN_REG_MAX_VALUE; - } - return codec_gain; } -// 改动原因:按 SY102dac对应表.csv,将DAC HID范围扩展为49级(0~48)。 -// 0 = mute,1~48 = 有效音量等级(LED按csv映射显示)。 -#define DAC_LEVEL_MIN 0 // mute,0 LEDs -#define DAC_LEVEL_MAX 48 // max level,15 LEDs -#define DAC_LEVEL_DEFAULT DAC_LEVEL_MAX + +static inline void CODEC_REGREAD(unsigned device, unsigned reg, unsigned &val) +{ + unsafe + { + uc_audiohw <: (unsigned) AUDIOHW_CMD_REGRD; + uc_audiohw <: device; + uc_audiohw <: reg; + uc_audiohw :> val; + } +} + +#define NAU88_I2C_DEVICE_ADDR 0x1B static inline void NAU88C22_REGREAD(unsigned reg, unsigned &val, client interface i2c_master_if i2c) { @@ -287,103 +365,55 @@ static inline i2c_regop_res_t NAU88C22_REGWRITE(unsigned reg, unsigned val, clie } else { - debug_printf("I2C write success: reg=%08x, val=%08x\n", reg, val); - //debug_printf("I2C write success: reg="); - //printhex(reg); - //debug_printf(", val="); - //printhex(val); - //debug_printf("\n"); - //debug_printf("."); + // debug_printf("write reg [0x%02X] [0x%02X]\n", reg, val); } return result; } -// 改动原因:按 SY102dac对应表.csv 建立 0~48 级到 DAC 寄存器值的精确映射, -// 修复旧线性公式导致的 dB 对应错误(例如 47级应为-0.5dB,46级应为-1dB)。 -static const uint8_t dac_level_to_reg[49] = { - 0x0E, // [0] mute(调用方通常直接写0x0000) - 0x4B, // [1] -66dB - 0x4F, // [2] -64dB - 0x53, // [3] -62dB - 0x57, // [4] -60dB - 0x5B, // [5] -58dB - 0x5F, // [6] -56dB - 0x63, // [7] -54dB - 0x67, // [8] -52dB - 0x6B, // [9] -50dB - 0x6F, // [10] -48dB - 0x73, // [11] -46dB - 0x77, // [12] -44dB - 0x7B, // [13] -42dB - 0x7F, // [14] -40dB - 0x83, // [15] -38dB - 0x87, // [16] -36dB - 0x8B, // [17] -34dB - 0x8F, // [18] -32dB - 0x93, // [19] -30dB - 0x97, // [20] -28dB - 0x9B, // [21] -26dB - 0x9F, // [22] -24dB - 0xA3, // [23] -22dB - 0xA7, // [24] -20dB - 0xA9, // [25] -19dB - 0xAB, // [26] -18dB - 0xAD, // [27] -17dB - 0xAF, // [28] -16dB - 0xB1, // [29] -15dB - 0xB3, // [30] -14dB - 0xB5, // [31] -13dB - 0xB7, // [32] -12dB - 0xB9, // [33] -11dB - 0xBB, // [34] -10dB - 0xBD, // [35] -9dB - 0xBF, // [36] -8dB - 0xC1, // [37] -7dB - 0xC3, // [38] -6dB - 0xC5, // [39] -5dB - 0xC7, // [40] -4dB - 0xC8, // [41] -3.5dB - 0xC9, // [42] -3dB - 0xCA, // [43] -2.5dB - 0xCB, // [44] -2dB - 0xCC, // [45] -1.5dB - 0xCD, // [46] -1dB - 0xCE, // [47] -0.5dB - 0xCF // [48] 0dB -}; - -void dac_volume(unsigned level) +static inline void HT5943_REGREAD(unsigned device, unsigned reg, unsigned &val, client interface i2c_master_if i2c) { - if (level > DAC_LEVEL_MAX) { - level = DAC_LEVEL_MAX; - } - unsigned tmp = dac_level_to_reg[level]; -#if 0 - int half_db = ((int)tmp - 0xCF); // 以 0.5dB 为单位(负数表示衰减) - int sign = (half_db < 0) ? -1 : 1; - int abs_half_db = (half_db < 0) ? -half_db : half_db; - debug_printf("dac_volume write level=%d reg=0x%02X db=%s%d.%d\n", - level, tmp, (sign < 0) ? "-" : "", abs_half_db / 2, (abs_half_db & 1) ? 5 : 0); -#endif - unsafe {NAU88C22_REGWRITE(0x0034, (tmp<<8|tmp), (client interface i2c_master_if)i_i2c_client);} + i2c_regop_res_t result; + val = i2c.read_reg(device, reg, result); + // debug_printf("HT5943_REGREAD: device = 0x%02X, reg = 0x%02X, val = 0x%02X\n", device, reg, val); } -void mic_volume(unsigned level) +static inline void HT5943_REGWRITE(unsigned device, unsigned reg, unsigned val, client interface i2c_master_if i2c) { - if (level == 0) + // debug_printf("HT5943_REGWRITE: device = 0x%02X, reg = 0x%02X, val = 0x%02X\n", device, reg, val); + i2c.write_reg(device, reg, val); +} + + +extern unsigned GetKeyFlag(); +extern unsigned g_force_eq_mode_change; +extern unsigned g_focce_request_eq_mode_change; + +#if HID_DFU_EN +extern void firmware_upgrade_init(void); +#endif + +uint8_t samp_support(unsigned samFreq) +{ + switch (samFreq) { - // mute: 关闭PGA和输出放大器 - unsafe {NAU88C22_REGWRITE(0x007E, 0, (client interface i2c_master_if)i_i2c_client);} - unsafe {NAU88C22_REGWRITE(0x0035, 0, (client interface i2c_master_if)i_i2c_client);} - debug_printf("mic_volume mute\n"); - } - else - { - // 改动原因:移除旧版37~38寄存器额外数字增益路径,最大限制到24dB(1~24,1dB/步)。 - debug_printf("mic_volume write reg=%d\n", level); - unsafe {NAU88C22_REGWRITE(0x007E, (level << 8), (client interface i2c_master_if)i_i2c_client);} - unsafe {NAU88C22_REGWRITE(0x0035, (0xcfcf), (client interface i2c_master_if)i_i2c_client);} + case 44100: + case 48000: + case 88200: + case 96000: + case 176400: + case 192000: + case 352800: + case 384000: + case 705600: + case 768000: + case 2822400: + case 5644800: + case 11289600: + case 22579200: + return 1; + default: + return 0; } } @@ -396,2236 +426,1565 @@ void codec_init(void) for (int i = 0; i < sizeof(nau88c22_registers) / sizeof(nau88c22_registers[0]); i++) { addr = nau88c22_registers[i][1]; val = (nau88c22_registers[i][2] << 8) | nau88c22_registers[i][3]; - unsafe {NAU88C22_REGWRITE(addr, val, (client interface i2c_master_if)i_i2c_client);} + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, addr, val); } // ADCL PGA default setting - unsafe {NAU88C22_REGWRITE(0x007E, NAU88L21_PGA_GAIN_REG_DEFAULT_VALUE << 8, (client interface i2c_master_if)i_i2c_client);} + if(NAU88L21_PGA_GAIN_REG_DEFAULT_VALUE == NAU88L21_PGA_GAIN_REG_MAX_VALUE) + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x007E, (NAU88L21_PGA_GAIN_REG_MAX_VALUE-1) << 8); + else + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x007E, NAU88L21_PGA_GAIN_REG_DEFAULT_VALUE << 8); - //debug_printfln("Codec init finished"); + debug_printf("Codec init finished\n"); } -in port p_mic_gain_encoder1 = PORT_MIC_GAIN_ENCODER1; // 4F2 -in port p_mic_gain_encoder2 = PORT_MIC_GAIN_ENCODER2; // 4E2 -in port p_hp_gain_encoder = PORT_HP_GAIN_ENCODER; // 8D4, 8D5 - -in port p_button_music_mode = PORT_BUTTON_MUSIC_MODE; // 1A -in port p_button_game_mode = PORT_BUTTON_GAME_MODE; // 1L -in port p_button_ai71_onoff = PORT_BUTTON_AI71_ONOFF; // 1M - -// -// -// -// -// -// -// -// -// - -#define KEY_POLLING_INTERVAL 10000000L // 100ms polling interval -#define TIMER_PERIOD (100000) -#define FACTORY_RESET_HOLD_TICKS 3000 // 3000 × 1ms = 3秒 -#define FACTORY_RESET_BLINK_TICKS 400 // 每相400ms -#define MUTE_BLINK_HALF_PERIOD 500 // mute LED blink half period 250ms -#define BTN_COMBO_DELAY_TICKS 40 // 单键去抖/组合检测窗口(50ms) - -unsigned g_windows_detect_done = 0; - -#define MUTE_ON 1 -#define MUTE_OFF 0 - -extern unsigned g_host_os; // 1 -> Windows, 2 -> Others -extern unsigned g_mute_on_off_t0; -extern unsigned g_uac_vol; -#define DNR_STRENGTH_off 10 -extern void dnr_set_mode(unsigned char mode); -extern void dnr_set_strength_level(unsigned char strength); - -extern void device_reboot(void); - - -enum {IR_OFF=0, IR_GAME=1, IR_MUSIC=2, IR_MOVIE=3, IR_7_1_GAME=4, IR_7_1_MUSIC=5, IR_7_1_MOVIE=6}; - -#ifndef HID_MAX_DATA_BYTES -#define HID_MAX_DATA_BYTES ( 64 ) -#endif -extern unsigned hidSendData[]; - -#if HID_DFU_EN -#include "dfu_upgrade.h" -/* 将HID收到的63字节固件升级START命令打包为16个unsigned word, - * 通过uc_dfu streaming channel发送到button_task (tile[0])执行。 - * 从eq.c的process_send_params中对0xA7命令调用此函数。 */ -void dfu_chan_forward(unsigned char data[], unsigned len) +void dac_volume(signed level, client interface i2c_master_if i2c) { - unsafe + // 1dB/步: level 范围 -28 ~ 0,对应寄存器 0xcf-28=0xb3 ~ 0xcf + + + unsigned tmp = 0xcf + level; + unsafe {NAU88C22_REGWRITE(0x0034, (tmp<<8|tmp), i2c);} +} + +void mic_volume(unsigned level, client interface i2c_master_if i2c) +{ + if (level == 0 || level == 1) { - for (int i = 0; i < 16; i++) { - unsigned word = 0; - for (int j = 0; j < 4; j++) { - int idx = i * 4 + j; - if (idx < 63) { - word |= ((unsigned)data[idx]) << (j * 8); - } - } - uc_dfu <: word; - } + // mute: 关闭PGA和输出放大器 + unsafe {NAU88C22_REGWRITE(0x007E, 0, i2c);} + unsafe {NAU88C22_REGWRITE(0x0035, 0, i2c);} + } + else if(level == NAU88L21_PGA_GAIN_REG_MAX_VALUE) + { + // 内部最大值 (reg=38, +1.5dB数字增益,仅firmware使用) + // PGA设到最大(37=0x25),数字增益额外+1.5dB + unsafe {NAU88C22_REGWRITE(0x007E, (NAU88L21_PGA_GAIN_REG_MAX_VALUE-1) << 8, i2c);} + unsafe {NAU88C22_REGWRITE(0x0035, (0xd2d2), i2c);} + } + else + { + // 1-37: 0dB ~ 36dB,1dB/步 + debug_printf("mic_volume write reg=%d\n", level); + unsafe {NAU88C22_REGWRITE(0x007E, (level << 8), i2c);} + unsafe {NAU88C22_REGWRITE(0x0035, (0xcfcf), i2c);} } } -#endif -void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx +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" +/* 改动原因:c_dfu 仅接收 FIRMWARE_UPGRADE_START,在此线程执行 handle_firmware_upgrade_start。 + * 移除未使用的 chanend c_erase:原占位参数无任何 select/通信,会导致 main 侧被迫接 dummy 通道且与当前拓扑无关。 */ #if HID_DFU_EN - , streaming chanend c_dfu_rx +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) +#else +void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, client interface c1_led_ctrl_if i_c1_led_ctrl) #endif - , chanend c_mic_det - ) { - //hwtimer_t timer = hwtimer_alloc(); + unsigned cmd; + int value; unsigned time = 0; - timer tmr; + unsigned eq_mode_time = 0; + unsigned se_time = 0; + unsigned se_count = 0; + timer tmr, se_tmr, eq_mode_timer, eq_sync_timer, button_tmr; + unsigned eq_sync_time = 0; + unsigned old_format = 14; + unsigned unmute_dac_state; + unsigned old_dac_vol = 0; + unsigned old_adc_vol = 0; + unsigned old_dac_mode = 0; + // 改动原因:记录上次用于防抖持久化的 g_dac_vol;deadline=0 表示当前无待写入 Flash 的定时保存任务。 + unsigned dac_vol_persist_snapshot = 0; + unsigned dac_vol_persist_deadline = 0; + // 改动原因:耳机拔出强制 DAC 寄存器静音(不改 g_dac_vol,类比 phaten 的 dac_det_muted);插入后延时再写回逻辑音量。 + unsigned hp_jack_dac_mute = 0; + unsigned hp_restore_deadline = 0; + unsigned hp_stable_prev = 0xFFFFFFFFu; + unsigned hp_db_cnt = 0; + unsigned hp_cand = 0xFFFFFFFFu; + unsigned hp_stable = 0; + // 改动原因:记录上次写入 0x0034 时的“插拔强制哑音”组合态(耳机拔出 | MIC 拔出 | MIC 插入),任一路变化都要重推寄存器。 + unsigned old_dac_jack_force_mute = 0; + // 改动原因:MIC 拔出瞬间哑 DAC(参考 phaten MIC_DET_DAC_MUTE),拔出边沿起 500ms 后恢复 DAC 寄存器;不改 g_dac_vol。 + unsigned mic_pull_dac_mute = 0; + unsigned mic_pull_dac_deadline = 0; + // 改动原因:MIC 插入(去抖稳定后)立即哑 DAC 防 pop,稳定插入起再计 500ms 后恢复 DAC;拔出时清零;不改 g_dac_vol。 + unsigned mic_insert_dac_mute = 0; + unsigned mic_insert_dac_deadline = 0; + // 改动原因:MIC 拔出强制 ADC mute;插入 500ms 后按 g_mute_switch+g_adc_vol 恢复,不修改 g_mute_switch,故 mic mute LED 不受插拔影响。 + unsigned mic_jack_adc_mute = 0; + unsigned mic_restore_deadline = 0; + unsigned mic_stable_prev = 0xFFFFFFFFu; + unsigned mic_db_cnt = 0; + unsigned mic_cand = 0xFFFFFFFFu; + unsigned mic_stable = 0; + // 改动原因:按DS1按键状态机思路保存每个按键按下时长;mode/mic 仍用短/长按窗口区分,音量键仅用于释放时短按去抖(不支持长按连调)。 + unsigned mode_press_ticks = 0; + unsigned vol_down_press_ticks = 0; + unsigned mic_mute_press_ticks = 0; + unsigned vol_up_press_ticks = 0; + // 改动原因:mic 键双击需延迟首轮短按的静音动作,用 stage1=等超时单击 / stage2=已收到第二下按下等释放;与长按 AI 互斥靠 mic_ai_long_fired。 + unsigned mic_dbl_stage = 0; + unsigned mic_defer_left = 0; + unsigned mic_ai_long_fired = 0; + // 改动原因:变声/美声仅按键+灯,tile0 保存状态供下发橙色 mode 区;AI 降噪无灯仅本地翻转供后续扩展。 + unsigned c1_mic_voice_fx = 0; + unsigned c1_mic_ai_nr = 0; + // 改动原因:mic mute红灯通过interface下发到tile1,仅在状态变化时发送,减少无意义跨tile调用。 + unsigned last_mute_switch_for_led = 0xFFFFFFFF; + unsigned host_os = 0; + tmr :> time; /* Input time */ + time += TIMER_PERIOD; /* Add time */ + se_tmr :> se_time; + se_time += SE_DELAY; + eq_mode_timer :> eq_mode_time; + eq_mode_time += EQ_MODE_DELAY; + eq_sync_timer :> eq_sync_time; + eq_sync_time += EQ_SYNC_DELAY; + unsigned c1_mode = load_value(C1_MODE_INFO_PATH); - static int uac_vol=0, last_uac_vol=0; -#if EQ_EN - - static unsigned eq_sync_counter = 0; // EQ参数存储计数器(每100ms递增,5次后保存) -#endif - // port_t p_ctrl_keys = XS1_PORT_8C; - - uint32_t port_ctrl_keys = 0, curr_ctrl_keys = 0, last_ctrl_keys = 0, keys_changed = 0; - uint32_t port_ctrl_keys2 = 0, curr_ctrl_keys2 = 0, last_ctrl_keys2 = 0, keys_changed2 = 0; - - int debounce_cnt = 0; - static unsigned isMute = 0; - uint8_t tmp = 0; - - // port_t p_button_music_mode = PORT_BUTTON_MUSIC_MODE; - // port_t p_button_game_mode = PORT_BUTTON_GAME_MODE; - // port_t p_button_ai71_onoff = PORT_BUTTON_AI71_ONOFF; - - //port_enable(p_button_music_mode); - - // 改动原因:麦克风默认值改为49级中的44级(约22dB),上限受24dB约束。 - // 改动原因:本变量改为保存“49级HID音量等级”(0~48),便于旋钮/HID统一一套等级语义。 - int codec_adc_pga_gain_reg_value = MIC_HID_LEVEL_DEFAULT; - - // 改动原因:默认监听音量从旧30级体系迁移到49级体系,保持中高音量默认值。 - int dac_level = DAC_HID_LEVEL_DEFAULT; - - // mic endcoder 变量 - uint8_t prev_encode_input1 = 0; - uint8_t rotation_active = 0; - uint8_t sample_count = 0; - uint8_t last_valid_direction = 0; - uint8_t fast_rotation_mode = 0; // 快速旋转模式 - uint8_t consecutive_same_dir = 0; // 连续相同方向计数 - - // hp endcoder 变量 - uint8_t hp_prev_encode_input1 = 0; - uint8_t hp_rotation_active = 0; - uint8_t hp_sample_count = 0; - uint8_t hp_last_valid_direction = 0; - uint8_t hp_fast_rotation_mode = 0; // 快速旋转模式 - uint8_t hp_consecutive_same_dir = 0; // 连续相同方向计数 - - - - // active_mode: 0=off, 1=music (LED_MUSIC, no algorithm), - // 2=game (LED_GAME_MODE, IR_GAME), 3=AI7.1 (LED_AI7_1, IR_7_1_GAME) - unsigned active_mode = 0; - // 脚步增强3档状态: 0=关(0dB), 1=中亮/6dB, 2=高亮/12dB;出厂默认开启(12dB) - unsigned flag_footsteps_enhancement = 2; - // 出厂默认:AI降噪开启 - unsigned flag_aidenoise_onoff = 1; - unsigned dnr_strength_saved = 100; // AI降噪重新开启时恢复的强度(0x85可更新) - unsigned last_footstep_expand = 0xFF; // 上次已上报的脚步增强增益值,0xFF表示初始化未完成 - - // Buttons state - unsigned push_button_music_mode_state_old = 1; // Active low - unsigned push_button_ai71_onoff_state_old = 1; // Active low - unsigned push_button_game_mode_state_old = 1; // Active low - unsigned push_button_footsteps_enhancement_state_old = 0; // Active low - unsigned push_button_aidenoise_onoff_state_old = 1; // Active low - unsigned char saved_footstep = 0; - - - - unsigned flag_mic_mute = 0; - unsigned flag_hp_mute = 0; - unsigned mic_det_muted = 0; // mic检测导致的mute(不影响LED和g_mic_volume_level) - unsigned dac_det_muted = 0; // mic插入时临时mute DAC防pop(不影响LED) - - unsigned push_button_mic_mute_state_old = 1; // Active low - unsigned push_button_hp_mute_state_old = 1; // Active low - - // 出厂恢复长按状态机:音乐+游戏同时长按3秒 - unsigned factory_reset_hold_count = 0; // 两键同时按住计数(×1ms) - unsigned factory_reset_blink_state = 0; // 0=空闲,1-6=闪烁相位 - unsigned factory_reset_blink_tick = 0; // 当前相位内计数 - unsigned mic_mute_blink_tick = 0; - unsigned hp_mute_blink_tick = 0; - // 组合键去抖:单键动作延迟 BTN_COMBO_DELAY_TICKS 后触发,期间若另一键也按下则切换为组合模式 - unsigned btn_music_hold_ticks = 0; // music键连续按住计数 - unsigned btn_game_hold_ticks = 0; // game键连续按住计数 - unsigned btn_combo_active = 0; // 1=处于组合键模式(单键动作已抑制) - unsigned fr_inhibit = 0; // 1=出厂恢复重启后抑制状态,必须松键后才允许重新触发 - - int current_mic_led_pos = 0; - - htr3236_t htr3236_dev; - - // LED控制上下文 - led_control_t led_ctx; - - - // saved_mode / active_mode: 0=off, 1=music, 2=game (IR_GAME), 3=AI7.1 (IR_7_1_GAME) - unsigned /* char */ saved_mode; - unsigned char saved_uac1_mode = 0; - unsigned char path[] = "game_mode"; - unsigned char mic_vol_path[] = "mic_vol"; - unsigned char dac_vol_path[] = "dac_vol"; - unsigned char mic_mute_path[] = "mic_mute"; - unsigned char hp_mute_path[] = "hp_mute"; - unsigned char monitor_sw_path[] = "monitor_sw"; - unsigned char dnr_strength_path[] = "dnr_strength"; - // 改动原因:断电记忆AI降噪开关与强度分离存储(旧固件仅用dnr_strength=0表示关,启动时迁移) - unsigned char dnr_on_path[] = "dnr_on"; - unsigned host_os = OS_OTHERS; -#if DNR_ENABLE - unsigned dnr_init_flag = 0; - while (dnr_init_flag == 0) - { - GET_SHARED_GLOBAL(dnr_init_flag, g_dnr_init_flag); - asm("nop"); - } -#endif -#if USE_EX3D == 1 - unsigned ex3d_key_verified = 0; - while (ex3d_key_verified == 0) - { - GET_SHARED_GLOBAL(ex3d_key_verified, g_ex3d_key_verified); - asm("nop"); - } +#if HID_DFU_EN + firmware_upgrade_init(); #endif - delay_milliseconds(10); - saved_mode = load_value(path); - debug_printf("Loaded game_mode from flash: %d\n", saved_mode); - -#if USE_EX3D == 1 - // 加载脚步增强状态(保存值为expand_gain: 0/6/12) + if (c1_mode > C1_MODE_VALUE_MAX || c1_mode < C1_MODE_VALUE_MIN) { - unsigned char footstep_path[] = "footstep"; - saved_footstep = load_value(footstep_path); - debug_printf("Loaded footstep gain from flash: %d\n", saved_footstep); - if (saved_footstep == 0) { - flag_footsteps_enhancement = 0; - } else if (saved_footstep <= 6) { - flag_footsteps_enhancement = 1; - } else if (saved_footstep <= 20) { - flag_footsteps_enhancement = 2; - } else { - // 未初始化(255)或异常值:出厂默认脚步增强开启(12dB),写入flash - saved_footstep = 12; - flag_footsteps_enhancement = 2; - save_value(footstep_path, (unsigned char)12); - debug_printf("Saved footstep gain to flash: %d\n", saved_footstep); - } - debug_printf("Loaded footstep gain from flash: %d, state=%d\n", saved_footstep, flag_footsteps_enhancement); + c1_mode = C1_MODE_VALUE_DEFAULT; + save_value(C1_MODE_INFO_PATH, c1_mode); } - // 加载EX3D角度,未初始化时写入默认值 - { - unsigned ex3d_angles[EX3D_ANGLE_CHANNELS]; - ex3d_angle_load_defaults(ex3d_angles); - for (int i = 0; i < EX3D_ANGLE_CHANNELS; ++i) { - g_hid_angle_values[i] = ex3d_angle_load_channel(i, ex3d_angles[i]); - // 改动原因: - // - g_hid_angle_values_old 用于后续“变更检测后再写flash”; - // - 开机从flash加载角度后,旧值必须与当前值对齐,否则首次保存请求会把未变化通道也误判为变化。 - g_hid_angle_values_old[i] = g_hid_angle_values[i]; - } - } -#endif -#if defined(UAC1_MODE) +#if defined(WIN_OS_DETECTION) for(int i = 0; i < 500; i++) { GET_SHARED_GLOBAL(host_os, g_host_os); if (host_os == OS_WIN) { + debug_printf("Detected Windows OS (OS_WIN) host_os: %d\n", host_os); break; } delay_milliseconds(1); } if (host_os == OS_WIN) { - debug_printf("Detected Windows OS (OS_WIN) saved_mode: %d\n", saved_mode); - unsigned flag = (saved_mode <= 1) ? MODE_F1_MUSIC_UAC2 : MODE_F3_F4_FPS_UAC2; - SetRoleSwitchFlag(flag); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif + debug_printf("Detected Windows OS (OS_WIN) c1_mode: %d\n", c1_mode); + switch_mode_by_c1_mode(c1_mode, 1); } else { -#if F5_MUSIC_UAC1 - if (saved_mode >= 2) { - SetRoleSwitchFlag(MODE_F6_F7_FPS_UAC1); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } -#elif F6_F7_FPS_UAC1 - if (saved_mode <= 1) { - SetRoleSwitchFlag(MODE_F5_MUSIC_UAC1); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } -#endif + switch_mode_by_c1_mode(c1_mode, 0); } #endif -#if defined(UAC1_MODE) - if (saved_mode == 255) { -#if defined(F5_MUSIC_UAC1) - saved_mode = 1; // f5: default music mode -#elif defined(F6_F7_FPS_UAC1) - saved_mode = 2; // f6/f7: default game mode -#else - saved_mode = 1; // default off -#endif - save_value(path, saved_mode); - debug_printf("Saved game_mode to flash: %d\n", saved_mode); - } -#else - if (saved_mode == 255) { - // 出厂默认:AI7.1开启(mode=3) - saved_mode = 3; - save_value(path, saved_mode); - debug_printf("Saved game_mode to flash: %d\n", saved_mode); - } -#endif - - - active_mode = (saved_mode <= 3) ? saved_mode : 0; + // 改动原因:开机从 LittleFS 恢复 DAC 音量寄存器码;无效或未写过时用最大音量 C1_DAC_VOL_MAX,避免误用默认值或垃圾数据。 { - SET_SHARED_GLOBAL(g_game_mode, active_mode); - debug_printf("active_mode=%d\n", active_mode); - } - - - - // 初始化硬件 - htr3236_init(&htr3236_dev, HTR3236_ADDR_GND); - htr3236_hw_enable(&htr3236_dev); - //p_htr3235_sdb <: 1; - - unsafe - { - while(htr3236_software_wake(&htr3236_dev, (client interface i2c_master_if)i_i2c_client) != 0) { - // 错误处理 - debug_printf("HTR3236 LED driver wake failed\n"); - //return; - } - } - debug_printf("HTR3236 LED driver wake success 9\n"); - - // 设置PWM频率为22kHz (避免可闻噪声) - //htr3236_set_frequency(i2c, HTR3236_FREQ_22KHZ); - unsafe - { - while(htr3236_set_frequency(&htr3236_dev, (client interface i2c_master_if)i_i2c_client, HTR3236_FREQ_22KHZ) != 0) - { - debug_printf("HTR3236 set frequency failed\n"); - } - } - debug_printf("HTR3236 set frequency success 9\n"); - - // 初始化LED控制 - unsafe{led_control_init(&led_ctx, &htr3236_dev, (client interface i2c_master_if)i_i2c_client);} - - // led_on(&led_ctx, led_l_physical_map[0]); - // delay_milliseconds(100); - // led_update_all(&led_ctx); - - // led_on(&led_ctx, led_l_physical_map[1]); - // delay_milliseconds(100); - // led_update_all(&led_ctx); - - // led_on(&led_ctx, led_l_physical_map[2]); - // delay_milliseconds(100); - // led_update_all(&led_ctx); - - //led_waterfall(&led_ctx, 50); - - - // 从 Flash 恢复 mic/dac 音量 - { - unsigned char saved_mic = load_value(mic_vol_path); - if(saved_mic >= MIC_HID_LEVEL_MIN && saved_mic <= MIC_HID_LEVEL_MAX) - codec_adc_pga_gain_reg_value = saved_mic; + unsigned char loaded_dac_vol = load_value(C1_DAC_VOL_INFO_PATH); + unsigned init_dac_vol; + if (c1_saved_dac_vol_is_valid(loaded_dac_vol) == 0) + init_dac_vol = C1_DAC_VOL_MAX; else - save_value(mic_vol_path, (unsigned char)codec_adc_pga_gain_reg_value); // 出厂默认44级(约22dB) - - unsigned char saved_dac = load_value(dac_vol_path); - if(saved_dac <= DAC_LEVEL_MAX) - dac_level = saved_dac; - else - save_value(dac_vol_path, (unsigned char)dac_level); // 出厂默认15(-14dB) - - // 从Flash恢复耳返开关(默认关闭) - unsigned char saved_monitor_sw = load_value(monitor_sw_path); - if(saved_monitor_sw == 1) - g_monitor_switch = 1; - else if(saved_monitor_sw == 255) { - // 未初始化:出厂默认关闭 - g_monitor_switch = 0; - save_value(monitor_sw_path, (unsigned char)0); - } else { - g_monitor_switch = 0; - } - debug_printf("Loaded monitor_switch from flash: %d\n", g_monitor_switch); - - { - unsigned char saved_dnr = load_value(dnr_strength_path); - unsigned char saved_on = load_value(dnr_on_path); - // 改动原因:强度文件只存2–100偶数档位;开关存dnr_on;兼容旧数据saved_dnr==0表示关且未单独存开关 - if (saved_dnr == 255) { - g_dnr_strength = 100; - dnr_strength_saved = 100; - g_dnr_on = 1; - flag_aidenoise_onoff = 1; - save_value(dnr_strength_path, (unsigned char)100); - if (saved_on == 255) - save_value(dnr_on_path, (unsigned char)1); - } else if (saved_dnr == 0) { - g_dnr_strength = 100; - dnr_strength_saved = 100; - g_dnr_on = 0; - flag_aidenoise_onoff = 0; - save_value(dnr_strength_path, (unsigned char)100); - save_value(dnr_on_path, (unsigned char)0); - } else if (saved_dnr <= 100) { - g_dnr_strength = saved_dnr; - dnr_strength_saved = saved_dnr; - if (saved_on == 0) { - g_dnr_on = 0; - flag_aidenoise_onoff = 0; - } else { - g_dnr_on = 1; - flag_aidenoise_onoff = 1; - if (saved_on == 255) - save_value(dnr_on_path, (unsigned char)1); - } - } else { - g_dnr_strength = 100; - dnr_strength_saved = 100; - g_dnr_on = 1; - flag_aidenoise_onoff = 1; - save_value(dnr_strength_path, (unsigned char)100); - save_value(dnr_on_path, (unsigned char)1); - } - debug_printf("Loaded dnr from flash: strength=%d saved=%d on=%d key_onoff=%d\n", - g_dnr_strength, dnr_strength_saved, g_dnr_on, flag_aidenoise_onoff); - } - - // 从Flash恢复mic_mute状态(默认关闭=未静音) - unsigned char saved_mic_mute = load_value(mic_mute_path); - if(saved_mic_mute == 1) - flag_mic_mute = 1; - else { - flag_mic_mute = 0; - if(saved_mic_mute == 255) - save_value(mic_mute_path, (unsigned char)0); - } - debug_printf("Loaded mic_mute from flash: %d\n", flag_mic_mute); - - // 从Flash恢复hp_mute状态(默认关闭=未静音) - unsigned char saved_hp_mute = load_value(hp_mute_path); - if(saved_hp_mute == 1) - flag_hp_mute = 1; - else { - flag_hp_mute = 0; - if(saved_hp_mute == 255) - save_value(hp_mute_path, (unsigned char)0); - } - debug_printf("Loaded hp_mute from flash: %d\n", flag_hp_mute); + init_dac_vol = loaded_dac_vol; + SET_SHARED_GLOBAL(g_dac_vol, init_dac_vol); + // 改动原因:强制首轮定时器路径执行 NAU88C22 写音量(含 mute=0 时 old_dac_vol 初值也为 0 的情况)。 + old_dac_vol = ~init_dac_vol; + dac_vol_persist_snapshot = init_dac_vol; + dac_vol_persist_deadline = 0; } - codec_init(); - // 同步全局音量变量与从Flash恢复的dac_level / codec_adc_pga_gain_reg_value - g_volume_level = dac_level; - // 改动原因:g_mic_volume_level 直接使用49级HID等级,避免旧版37级上限截断。 - g_mic_volume_level = (codec_adc_pga_gain_reg_value <= MIC_HID_LEVEL_MAX) ? codec_adc_pga_gain_reg_value : MIC_HID_LEVEL_MAX; + // 改动原因:tile1 上电已硬件全灭;先下发当前 g_mute_switch 再下发 Flash 中的 c1_mode,使首帧 apply 时 mic 已正确,避免仅 set_mode 时用占位 mic 闪错 mute 灯。 + unsigned init_mute_for_led; + GET_SHARED_GLOBAL(init_mute_for_led, g_mute_switch); + i_c1_led_ctrl.set_mic_mute_state(init_mute_for_led); + i_c1_led_ctrl.set_mode_led_color(c1_mode_to_tile_mode_led_code(c1_mode)); + // 改动原因:上电默认关闭变声灯效覆盖,避免未初始化随机亮橙。 + i_c1_led_ctrl.set_mic_voice_fx(0); + last_mute_switch_for_led = init_mute_for_led; - // ADCL PGA default setting(mic_volume内部已根据g_monitor_switch决定是否启用耳返通路) - // 若mic_mute已从flash恢复为1,则此处先以正常gain调用,再用mute覆盖 - mic_volume(mic_hid_level_to_codec_gain(codec_adc_pga_gain_reg_value)); + while(1) { - int mic_led_count = flag_mic_mute ? 15 : mic_gain_to_led[codec_adc_pga_gain_reg_value]; - for(int i = 0; i < 15; i++) - { - if (i < mic_led_count) - led_on(&led_ctx, led_l_physical_map[i]); - else - led_off(&led_ctx, led_l_physical_map[i]); - } - } - // 应用从flash恢复的mic_mute状态 - if(flag_mic_mute) { - mic_volume(0); - g_mic_volume_level = 0; - mic_mute_blink_tick = 1; - } - - // 硬件耳返通路已禁用,改为数字监听(在tile1 UserBufferManagement中实现) - // 初始化同步在上方已通过 cc_mic_level <: 0xFE 完成 - - // DAC 默认音量(mute 时写 0x0000) - if(dac_level == DAC_LEVEL_MIN) - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - else - dac_volume(dac_level); - { - int dac_led_count = flag_hp_mute ? 15 : dac_gain_to_led[dac_level]; - for(int i = 0; i < 15; i++) - { - if (i < dac_led_count) - led_on(&led_ctx, led_d_physical_map[i]); - else - led_off(&led_ctx, led_d_physical_map[i]); - } - } - // 应用从flash恢复的hp_mute状态 - if(flag_hp_mute) { - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - g_volume_level = 0; - hp_mute_blink_tick = 1; - } - // Initialize mode button LEDs: at most one may be lit at a time - led_off(&led_ctx, LED_MUSIC); - led_off(&led_ctx, LED_GAME_MODE); - led_off(&led_ctx, LED_AI7_1); - switch (active_mode) { - case 1: led_on(&led_ctx, LED_MUSIC); break; - case 2: led_on(&led_ctx, LED_GAME_MODE); break; - case 3: led_on(&led_ctx, LED_AI7_1); break; - default: break; - } - led_update_all(&led_ctx); - - - unsigned hidData0; - delay_milliseconds(200); - - debug_printf("button task start\n"); - - - { - cc_mic_level <: 0xFC; - cc_mic_level <: active_mode; - debug_printf("Sent sound_effect_mode %d to hid_button_task\n", active_mode); - } - -#if USE_EX3D == 1 - // 发送初始脚步增强expand_gain到tile1 - { - cc_mic_level <: 0xFD; - cc_mic_level <: (unsigned) saved_footstep; - debug_printf("set init expand_gain %d to hid_button_task\n", saved_footstep); - } - - // 加载枪声阈值并同步到tile1 - // 存储格式: -threshold (0~35, 0=threshold=0dB), 255=未初始化 - { - unsigned char lmt_thresh_path[] = "lmt_thresh"; - unsigned char raw = load_value(lmt_thresh_path); - int init_threshold; - if (raw == 255) { - // 未初始化,使用默认值-15 - init_threshold = -15; - save_value(lmt_thresh_path, (unsigned char)15); - } else if (raw <= 36) { - // raw=0~35 全部有效: 0=threshold=0dB(不限幅), 35=threshold=-35dB(最大限幅) - init_threshold = -(int)(raw - 1); - } else { - init_threshold = -15; - } - cc_mic_level <: 0xFA; - cc_mic_level <: (unsigned)init_threshold; - debug_printf("Loaded lmt_threshold=%d from flash (raw=%d), sent to tile1\n", init_threshold, raw); - } - - // 同步EX3D角度到tile1 - { - cc_mic_level <: 0xF9; - for (int i = 0; i < EX3D_ANGLE_CHANNELS; ++i) { - cc_mic_level <: g_hid_angle_values[i]; - debug_printf("angle[%d] = %d\n", i, g_hid_angle_values[i]); - } - } - - // 恢复脚步增强LED初始状态 - if (flag_footsteps_enhancement == 1) { - led_on(&led_ctx, LED_FOOTSTEP_MODE); - led_update_all(&led_ctx); - } else if (flag_footsteps_enhancement == 2) { - led_set_brightness(&led_ctx, LED_FOOTSTEP_MODE, 128); - led_update_all(&led_ctx); - } -#endif - - // 初始化数字监听开关同步到tile1 - cc_mic_level <: 0xFE; - cc_mic_level <: (unsigned)g_monitor_switch; - debug_printf("Init monitor sync: sw=%d\n", g_monitor_switch); - - // 出厂默认:AI降噪由g_dnr_on决定,关时强度变量仍保留供再次开启 -#if DNR_ENABLE == 1 - if (g_dnr_on) { - led_on(&led_ctx, LED_ANC); - led_update_all(&led_ctx); - dnr_set_mode(1); - dnr_set_strength_level((unsigned char)g_dnr_strength); - } else { - led_off(&led_ctx, LED_ANC); - led_update_all(&led_ctx); - dnr_set_mode(1); - dnr_set_strength_level(DNR_STRENGTH_off); - } -#endif - - // port_enable(p_ctrl_keys); - port_ctrl_keys = 0;//port_in(p_ctrl_keys); - if ((port_ctrl_keys & KEY_MUTE) == 0) { - // mute switch off (unmuted) - debug_printf("unmuted\n"); - isMute = 0; - SET_SHARED_GLOBAL(g_mute_on_off_t0, MUTE_OFF); // 初始化tile0静音状态 - } else { - // mute switch on (muted) - debug_printf("muted\n"); - isMute = 1; - SET_SHARED_GLOBAL(g_mute_on_off_t0, MUTE_ON); // 初始化tile0静音状态 - } - - last_ctrl_keys = ((port_ctrl_keys) & KEY_BITS); - last_ctrl_keys ^= KEY_MUTE; - - - // 启动时若两键同时按住,设置抑制标志,必须松开后才允许触发出厂恢复 - { - unsigned music_init, game_init; - p_button_music_mode :> music_init; - p_button_game_mode :> game_init; - if (music_init == 0 && game_init == 0) { - fr_inhibit = 1; - btn_combo_active = 1; - debug_printf("Boot: both keys held, FR inhibited until release\n"); - } - } - - //hwtimer_set_trigger_time(timer, hwtimer_get_time(timer) + KEY_POLLING_INTERVAL); - tmr :> time; /* Input the time */ - time += TIMER_PERIOD; /* Increment the time */ - - g_windows_detect_done = 1; - while (1) { select { - case c_hidSendData :> hidData0: - { - if (hidData0 == 0xffffffff) { - debug_printf("receive end data\n"); - - // 注意:UAC1模式下不会收到此命令(hid_button_task不发送) - // 读取当前g_game_mode值 - unsigned current_mode;// = chan_in_word(c_hidSendData); - c_hidSendData :> current_mode; - - - // 循环切换模式:0(STEREO_2K) -> 1(SPATIAL_GAME) -> 2(SPATIAL_MOVIE) -> 3(无音效) -> 0 - unsigned new_mode; - unsigned mode_flag; - debug_printf("current_mode: %d\n", current_mode); - if (current_mode == 0) { - // 当前是STEREO_2K,切换到STEREO_2K - new_mode = 1; -#if IR_SWITCHING_MODE - mode_flag = IR_GAME; -#else - // mode_flag = MODE_STEREO_2K; -#endif - debug_printf("Switching from STEREO_2K (0) to STEREO_2K (1)\n"); - } else if (current_mode == 1) { - // 当前是STEREO_2K,切换到SPATIAL_GAME - new_mode = 2; -#if IR_SWITCHING_MODE - mode_flag = IR_7_1_GAME; -#else - // mode_flag = MODE_SPATIAL_GAME; -#endif - debug_printf("Switching from STEREO_2K (1) to SPATIAL_GAME (2)\n"); - } else if (current_mode == 2) { - // 当前是SPATIAL_GAME,切换到SPATIAL_MOVIE - new_mode = 3; -#if IR_SWITCHING_MODE - mode_flag = IR_7_1_MOVIE; -#else - // mode_flag = MODE_SPATIAL_MOVIE; // SPATIAL_MOVIE模式使用SPATIAL_MOVIE固件 -#endif - debug_printf("Switching from SPATIAL_GAME (2) to SPATIAL_MOVIE (3)\n"); - } // 更新g_game_mode - else if(current_mode == 3) { - new_mode = 0; -#if IR_SWITCHING_MODE - mode_flag = IR_OFF; -#else - // mode_flag = MODE_STEREO_2K; -#endif - debug_printf("Switching from SPATIAL_MOVIE (3) to STEREO_2K (0)\n"); - } - - - unsigned char path[] = "game_mode"; - save_value(path, (unsigned char)new_mode); - debug_printf("Saved game_mode %d to flash\n", new_mode); - delay_milliseconds(20); - - - // 只有在需要切换固件时才reboot,同一固件内的模式切换(如0<->1)只更新模式和算法状态 -#if !UAC1_MODE - -#if IR_SWITCHING_MODE - debug_printf("Same firmware mode (0x%04X), updating mode and algorithm state without reboot\n", mode_flag); - SET_SHARED_GLOBAL(g_game_mode, new_mode); - //chan_out_byte(cc_mic_level, 0xFC); // 音频模式传输命令 - //chan_out_byte(cc_mic_level, new_mode); // 音频模式值 - cc_mic_level <: 0xFC; - cc_mic_level <: new_mode; - debug_printf("Sent audio_mode %d to hid_button_task via cc_mic_level channel\n", new_mode); -#else - if (new_mode != 1) { - - debug_printf("Set role switch flag: 0x%04X, switching firmware, rebooting...\n", mode_flag); - SetRoleSwitchFlag(mode_flag); - delay_milliseconds(20); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } else { - - debug_printf("Same firmware mode (0x%04X), updating mode and algorithm state without reboot\n", mode_flag); - SET_SHARED_GLOBAL(g_game_mode, new_mode); - - // chan_out_byte(cc_mic_level, 0xFC); // 音频模式传输命令 - // chan_out_byte(cc_mic_level, new_mode); // 音频模式值 - cc_mic_level <: 0xFC; - cc_mic_level <: new_mode; - debug_printf("Sent audio_mode %d to hid_button_task via cc_mic_level channel\n", new_mode); - } -#endif -#endif - break; - } - -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif + case c :> cmd: + if(cmd == AUDIOHW_CMD_REGRD) { -#if (HID_CONTROLS == 1) - unsigned *reportData = hidSendData; - reportData[0] = hidData0; - for (int i=1; i<(HID_MAX_DATA_BYTES/4); i++) { - c_hidSendData :> reportData[i]; + unsigned device; + unsigned regAddr; + unsigned regVal; + c :> device; + c :> regAddr; + if (device == NAU88_I2C_DEVICE_ADDR) + { + NAU88C22_REGREAD(regAddr, regVal, i2c); } - hidSetChangePending(1); -#endif + c <: regVal; } - break; - } - - case c_audiohw_rx :> unsigned new_samfreq: - { - // 采样率变化通知,来自AudioHwConfig (tile[1]),通过uc_audiohw专用通道传递 - unsigned new_dsd_mode; - c_audiohw_rx :> new_dsd_mode; - debug_printf("SampRate->tile0: %uHz dsd=%u\n", new_samfreq, new_dsd_mode); - - unsafe { -#if !UAC1_MODE - switch (new_samfreq) { - case 192000: - case 176400: - NAU88C22_REGWRITE(0x0003, 0x00D0, (client interface i2c_master_if)i_i2c_client); - NAU88C22_REGWRITE(0x002B, 0x4000, (client interface i2c_master_if)i_i2c_client); - - NAU88C22_REGWRITE(0x002C, 0x0082, (client interface i2c_master_if)i_i2c_client); - break; - case 96000: - case 88200: - NAU88C22_REGWRITE(0x0003, 0x0092, (client interface i2c_master_if)i_i2c_client); - NAU88C22_REGWRITE(0x002B, 0x4001, (client interface i2c_master_if)i_i2c_client); - NAU88C22_REGWRITE(0x002C, 0x0082, (client interface i2c_master_if)i_i2c_client); - break; - case 44100: - case 48000: - default: - NAU88C22_REGWRITE(0x0003, 0x0053, (client interface i2c_master_if)i_i2c_client); - NAU88C22_REGWRITE(0x002B, 0x4002, (client interface i2c_master_if)i_i2c_client); - NAU88C22_REGWRITE(0x002C, 0x0082, (client interface i2c_master_if)i_i2c_client); - break; - } -#endif -#if 0 - unsigned val; - - NAU88C22_REGREAD(0x0003, val, (client interface i2c_master_if)i_i2c_client); - debug_printf("NAU88C22_REGREAD(0x0003): 0x%08x\n", val); - NAU88C22_REGREAD(0x002B, val, (client interface i2c_master_if)i_i2c_client); - debug_printf("NAU88C22_REGREAD(0x002B): 0x%08x\n", val); - NAU88C22_REGREAD(0x002C, val, (client interface i2c_master_if)i_i2c_client); - debug_printf("NAU88C22_REGREAD(0x002C): 0x%08x\n", val); -#endif - } - c_audiohw_rx <: 0xff; - -#if HID_CONTROLS > 0 -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif + else { - unsafe { - unsigned char * unsafe ptr = (unsigned char * unsafe)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; - ptr[2] = 0x9F; - ptr[3] = (unsigned char)(new_samfreq & 0xFF); - ptr[4] = (unsigned char)((new_samfreq >> 8) & 0xFF); - ptr[5] = (unsigned char)((new_samfreq >> 16) & 0xFF); - ptr[6] = (unsigned char)((new_samfreq >> 24) & 0xFF); - ptr[7] = (unsigned char)new_dsd_mode; - for (int i = 8; i < HID_MAX_DATA_BYTES; i++) - ptr[i] = 0x00; - } - hidSetChangePending(0x1); - } -#endif - break; - } - -#if HID_DFU_EN - case c_dfu_rx :> unsigned dfu_first_word: - { - // 接收来自tile[1] hid_button_task转发的固件升级START命令(16个word) - unsigned dfu_words[16]; - dfu_words[0] = dfu_first_word; - for (int i = 1; i < 16; i++) - c_dfu_rx :> dfu_words[i]; - unsigned char cmd_buf[63]; - for (int i = 0; i < 63; i++) - cmd_buf[i] = (dfu_words[i / 4] >> ((i % 4) * 8)) & 0xFF; - if (cmd_buf[1] == FIRMWARE_UPGRADE_START) - handle_firmware_upgrade_start(cmd_buf, 63); - break; - } -#endif - - case c_mic_det :> unsigned mic_det_cmd: - { - if (mic_det_cmd == MIC_DET_MUTE) { - mic_det_muted = 1; - // 仅mute硬件,不改变g_mic_volume_level和LED - mic_volume(0); - debug_printf("mic_det: mute (det)\n"); - } else if (mic_det_cmd == MIC_DET_UNMUTE) { - mic_det_muted = 0; - // 恢复音量,但如果用户手动mute了则不恢复 - if (!flag_mic_mute) { - // 改动原因(关键修复): - // codec_adc_pga_gain_reg_value 在当前版本保存的是 49级HID音量等级(0~48),不是Codec寄存器原始值。 - // 这里之前直接写 mic_volume(codec_adc_pga_gain_reg_value) 会绕过统一映射逻辑, - // 造成“插拔后恢复增益”与“旋钮/HID设置增益”不一致,表现为录音音量异常(偏小/不稳定)。 - // 必须与其它路径保持一致,先做 HID->Codec PGA 映射再写寄存器。 - unsigned codec_gain = mic_hid_level_to_codec_gain(codec_adc_pga_gain_reg_value); - mic_volume(codec_gain); - debug_printf("mic_det: unmute -> hid=%d codec_pga=%d\n", - codec_adc_pga_gain_reg_value, codec_gain); - } - } else if (mic_det_cmd == MIC_DET_DAC_MUTE) { - dac_det_muted = 1; - // mute DAC硬件,不改变dac_level/g_volume_level和LED - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - debug_printf("mic_det: dac mute\n"); - } else if (mic_det_cmd == MIC_DET_DAC_UNMUTE) { - dac_det_muted = 0; - // 恢复DAC音量,但如果用户手动hp_mute或dac_level==0则不恢复 - if (!flag_hp_mute && dac_level > DAC_LEVEL_MIN) { - dac_volume(dac_level); - debug_printf("mic_det: dac unmute -> level=%d\n", dac_level); + unsigned device, regAddr, regValue; + c :> device; + c :> regAddr; + c :> regValue; + if (device == NAU88_I2C_DEVICE_ADDR) + { + NAU88C22_REGWRITE(regAddr, regValue, i2c); } } break; - } case tmr when timerafter(time) :> void : - { - //hwtimer_change_trigger_time(timer, hwtimer_get_time(timer) + KEY_POLLING_INTERVAL); + uint32_t now, old_time; time += TIMER_PERIOD; + unsigned dac_vol, adc_vol, dac_mode, new_dac_mode; + now = get_reference_time(); - //hidData0 = 0; - -// port_t p_button_music_mode = PORT_BUTTON_MUSIC_MODE; -// port_t p_button_game_mode = PORT_BUTTON_GAME_MODE; -// port_t p_button_ai71_onoff = PORT_BUTTON_AI71_ONOFF; - -//p_button_music_mode :> button_music_mode; // 1A - - unsigned mic_encoder1, mic_encoder2, hp_encoder; - unsigned button_mic_mute, button_hp_mute; - unsigned button_music_mode, button_ai71_onoff, button_game_mode, button_footsteps_enhancement, button_aidenoise_onoff; - unsigned mode_change = 0; - - //button_music_mode = port_in(p_button_music_mode); - p_button_music_mode :> button_music_mode; // 1A - p_button_game_mode :> button_game_mode; // 1L - p_button_ai71_onoff :> button_ai71_onoff; // 1M - - p_mic_gain_encoder1 :> mic_encoder1; // 4F2 - p_mic_gain_encoder2 :> mic_encoder2; // 4E2 - - button_mic_mute = ((mic_encoder1 & 0b1000) != 0); // 4F3 - //button_hp_mute = ((hp_encoder & 0b01000000) != 0); // 8D6 - - button_footsteps_enhancement = ((mic_encoder1 & 0b0010) != 0); // 4F1 - button_aidenoise_onoff = ((mic_encoder2 & 0b1000) != 0); // 4E3 - - // --- Mode button handling --- - // active_mode: 0=off, 1=music, 2=game (IR_GAME), 3=AI7.1 (IR_7_1_GAME) - // - // Boot chain: power-on → F5 → OS detect → route to F1/F3/F4/F5/F6/F7 - // - // Music-only firmware (F1, F5): USE_EX3D not set - // Music btn: toggle LED locally (no reboot) - // Game/AI7.1 btn: save mode + reboot (F5 will route to FPS firmware) - // - // FPS firmware (F3/F4, F6/F7): USE_EX3D set - // Music btn: save mode=1 + reboot (F5 will route to music firmware) - // Game/AI7.1 btn: switch IR algorithm locally (no reboot) - - unsigned mode_btn_change = 0; - unsigned need_reboot = 0; - - // --- Music + Game 按键:组合检测 + 去抖 --- - // 两键同时按住3秒 → 出厂恢复;单键需持续 BTN_COMBO_DELAY_TICKS 后生效 - // (50ms 窗口内若另一键也按下则进入组合模式,单键动作取消) + GET_SHARED_GLOBAL(unmute_dac_state, g_unmute_dac_state); + if (unmute_dac_state == 1) { - int music_is_down = (button_music_mode == 0); - int game_is_down = (button_game_mode == 0); - int factory_combo_is_down = ( music_is_down && game_is_down); - - // 更新各键连续按住计数(断开则清零,用于去抖和窗口判断) - if (music_is_down && !factory_combo_is_down) + GET_SHARED_GLOBAL(old_time, g_unmute_time); + if (timeafter(now, old_time + UMUTE_DELAY)) { - if (btn_music_hold_ticks < 0xFFFFu) btn_music_hold_ticks++; - debug_printf("btn_music_hold_ticks=%d\n", btn_music_hold_ticks); - } - else - { - btn_music_hold_ticks = 0; - } - if (game_is_down && !factory_combo_is_down) - { - if (btn_game_hold_ticks < 0xFFFFu) + unsigned t; + GET_SHARED_GLOBAL(t, g_samfreq); + if (samp_support(t) == 1) { - btn_game_hold_ticks++; + debug_printf("unmute_dac from different freq\n"); + unmute_dac(); + SET_SHARED_GLOBAL(g_unmute_dac_state, 0); } - debug_printf("btn_game_hold_ticks=%d\n", btn_game_hold_ticks); - } - else - { - btn_game_hold_ticks = 0; - } - - // 场景1:两键同时按住(参照 fosi_ds1 else-if 结构) - if (factory_combo_is_down) { - btn_combo_active = 1; // 粘性锁定 - // fr_inhibit=1 时(出厂恢复重启后):不计时,必须松键后重新按下才触发 - if (factory_reset_blink_state == 0 && !fr_inhibit) { - factory_reset_hold_count++; - if (factory_reset_hold_count >= FACTORY_RESET_HOLD_TICKS) { - factory_reset_hold_count = 0; - factory_reset_blink_state = 1; - factory_reset_blink_tick = 0; - // 清除所有Flash设置并重启 - debug_printf("Factory reset: clearing flash " - "and rebooting\n"); - unsafe { - lfs_format_all(); - } - - led_on(&led_ctx, LED_MUSIC); - led_on(&led_ctx, LED_ANC); - led_on(&led_ctx, LED_FOOTSTEP_MODE); - led_on(&led_ctx, LED_AI7_1); - led_on(&led_ctx, LED_GAME_MODE); - led_update_all(&led_ctx); - debug_printf("Factory reset: 3s hold detected, starting blink\n"); - } + else + { + mute_dac(); + SET_SHARED_GLOBAL(g_unmute_dac_state, 0); } } - // 场景2:仅 Music 按住 - else if (music_is_down) { - factory_reset_hold_count = 0; - if (!btn_combo_active) { - if (btn_music_hold_ticks == BTN_COMBO_DELAY_TICKS) { - debug_printf("Music button pressed for %d ticks\n", BTN_COMBO_DELAY_TICKS); -#if (F3_F4_FPS_UAC2 == 1) - active_mode = 1; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F1_MUSIC_UAC2); -#elif (F6_F7_FPS_UAC1 == 1) - // UAC1 FPS firmware: music needs F5, reboot if not already music - if (active_mode != 1) { - active_mode = 1; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F5_MUSIC_UAC1); - } -#elif (F5_MUSIC_UAC1 == 1) - // UAC1 Music firmware: already on music FW, toggle locally - if (active_mode != 1) { - active_mode = 1; - mode_btn_change = 1; - } -#else - if (active_mode != 1) { - active_mode = 1; - mode_btn_change = 1; - } -#endif - } - } - } - // 场景3:仅 Game 按住 - else if (game_is_down) { - factory_reset_hold_count = 0; - if (!btn_combo_active) { - if (btn_game_hold_ticks == BTN_COMBO_DELAY_TICKS) { - debug_printf("Game button pressed for %d ticks\n", BTN_COMBO_DELAY_TICKS); -#if F1_MUSIC_UAC2 == 1 - active_mode = 2; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F3_F4_FPS_UAC2); -#elif (F5_MUSIC_UAC1 == 1) - // UAC1 Music firmware: game needs F6/F7, reboot if not already game - if (active_mode != 2) { - active_mode = 2; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F6_F7_FPS_UAC1); - } -#elif (F6_F7_FPS_UAC1 == 1) - // UAC1 FPS firmware: already on FPS FW, switch locally (IR_OFF) - if (active_mode != 2) { - active_mode = 2; - mode_btn_change = 1; - } -#else - if (active_mode != 2) { - active_mode = 2; - mode_btn_change = 1; - } -#endif - } - } - } - // 场景4:两键全松开 → 解除组合锁定及抑制标志 - else { - factory_reset_hold_count = 0; - btn_combo_active = 0; - fr_inhibit = 0; // 松键后允许下次同时按下重新触发出厂恢复 - } } - if (button_ai71_onoff == 0) { - if (push_button_ai71_onoff_state_old == 1) { -#if (F1_MUSIC_UAC2 == 1) - // Music-only firmware: AI7.1 needs FPS firmware - active_mode = 3; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F3_F4_FPS_UAC2); -#elif (F5_MUSIC_UAC1 == 1) - // UAC1 Music firmware: AI71 needs F6/F7 FPS, reboot if not already AI71 - if (active_mode != 3) { - active_mode = 3; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F6_F7_FPS_UAC1); - } -#elif (F6_F7_FPS_UAC1 == 1) - // UAC1 FPS firmware: already on FPS FW, switch locally (IR_GAME) - if (active_mode != 3) { - active_mode = 3; - mode_btn_change = 1; - } -#else - // FPS firmware: switch algorithm locally (activate if not already) - if (active_mode != 3) { - active_mode = 3; - mode_btn_change = 1; - } -#endif - } + unsigned audio_type; + unsigned old_type; + GET_SHARED_GLOBAL(old_type, g_old_audio_type); + GET_SHARED_GLOBAL(audio_type, g_new_audio_type); + GET_SHARED_GLOBAL(old_time, g_format_time); + #if !OPT && !COAX + if (timeafter(now, old_time + FORMAT_DELAY)) + #endif + { + unsigned tmp_format; + GET_SHARED_GLOBAL(tmp_format, g_new_playback_format); + if ((tmp_format != AUDIO_PCM_1536000) && (tmp_format != AUDIO_PCM_1441200)) + { + unsigned update_led; + unsigned led_mode; + GET_SHARED_GLOBAL(led_mode, g_led_mode); + GET_SHARED_GLOBAL(update_led, g_update_led); + #if OPT || COAX + if (timeafter(now, old_time + FORMAT_DELAY)) + #endif + { + SET_SHARED_GLOBAL(g_playback_format, tmp_format); + SET_SHARED_GLOBAL(g_audio_type, audio_type); + } + } } - push_button_ai71_onoff_state_old = button_ai71_onoff; - - // 处理HID SET_SOUND_EFFECT_MODE (0xA4) 请求,等同于按键效果 - if (!mode_btn_change && !need_reboot) { - unsigned hid_req_mode; - GET_SHARED_GLOBAL(hid_req_mode, g_request_game_mode); - if (hid_req_mode != (unsigned)-1) { - SET_SHARED_GLOBAL(g_request_game_mode, (unsigned)-1); - unsigned target = (hid_req_mode <= 3) ? hid_req_mode : 0; -#if (F3_F4_FPS_UAC2 == 1) - if (target == 1) { - active_mode = target; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F1_MUSIC_UAC2); + // 改动原因:耳机/MIC 插拔检测——写 NAU88C22(0x0034 / mic_volume);不修改 g_dac_vol、g_mute_switch;MIC 插/拔均对 DAC 做瞬时静音+500ms 恢复防 pop。 + { + unsigned raw_det; + p_mic_phone_detect :> raw_det; + unsigned hp_now = ((raw_det & C1_HP_DETECT_MASK) != 0) ? 1u : 0u; + unsigned mic_now = ((raw_det & C1_MIC_DETECT_MASK) == 0) ? 1u : 0u; + if (hp_cand == 0xFFFFFFFFu) { + hp_cand = hp_now; + hp_stable = hp_now; + hp_db_cnt = 0; + } else if (hp_now == hp_cand) { + hp_db_cnt++; + if (hp_db_cnt >= C1_JACK_DEBOUNCE_SAMPLES) { + hp_stable = hp_cand; + } + } else { + hp_cand = hp_now; + hp_db_cnt = 1; + } + if (mic_cand == 0xFFFFFFFFu) { + mic_cand = mic_now; + mic_stable = mic_now; + mic_db_cnt = 0; + } else if (mic_now == mic_cand) { + mic_db_cnt++; + if (mic_db_cnt >= C1_JACK_DEBOUNCE_SAMPLES) { + mic_stable = mic_cand; + } + } else { + mic_cand = mic_now; + mic_db_cnt = 1; + } + if (hp_stable_prev == 0xFFFFFFFFu) { + hp_stable_prev = hp_stable; + mic_stable_prev = mic_stable; + } else { + if (!hp_stable) { + hp_jack_dac_mute = 1; + hp_restore_deadline = 0; } else { - active_mode = target; - mode_btn_change = 1; - } -#elif (F1_MUSIC_UAC2 == 1) - if (target >= 2) { - active_mode = target; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F3_F4_FPS_UAC2); - } else { - active_mode = target; - mode_btn_change = 1; - } -#elif (F5_MUSIC_UAC1 == 1) - // UAC1 Music FW: mode 1 local, mode 2/3 need F6/F7 reboot - if (target >= 2) { - active_mode = target; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F6_F7_FPS_UAC1); - } else if (target != active_mode) { - active_mode = target; - mode_btn_change = 1; - } -#elif (F6_F7_FPS_UAC1 == 1) - // UAC1 FPS FW: mode 2/3 local, mode 1 needs F5 reboot - if (target <= 1) { - active_mode = target; - need_reboot = 1; - SetRoleSwitchFlag(MODE_F5_MUSIC_UAC1); - } else if (target != active_mode) { - active_mode = target; - mode_btn_change = 1; - } -#else - active_mode = target; - mode_btn_change = 1; -#endif - } - } - - if (mode_btn_change || need_reboot) { - // Always persist mode to flash so boot chain restores it - { - unsigned char save_path[] = "game_mode"; - save_value(save_path, (unsigned char)active_mode); - } - - if (need_reboot) { - // Reboot: F5 will re-detect OS and route to correct firmware - debug_printf("Mode %d requires firmware switch, rebooting\n", active_mode); - delay_milliseconds(200); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } - - // Local update path (no reboot): update LEDs and DSP algorithm - led_off(&led_ctx, LED_MUSIC); - led_off(&led_ctx, LED_GAME_MODE); - led_off(&led_ctx, LED_AI7_1); - switch (active_mode) { - case 1: led_on(&led_ctx, LED_MUSIC); break; - case 2: led_on(&led_ctx, LED_GAME_MODE); break; - case 3: led_on(&led_ctx, LED_AI7_1); break; - default: break; - } - led_update_all(&led_ctx); - - // Always update g_game_mode so 0xA5 reads correctly - SET_SHARED_GLOBAL(g_game_mode, active_mode); -#if USE_EX3D == 1 - { - // sound_effect_mode: 0=无音效, 1=音乐, 2=游戏, 3=AI7.1 - cc_mic_level <: 0xFC; - cc_mic_level <: active_mode; - debug_printf("Mode changed: active_mode=%d\n", active_mode); - } -#endif - } - - // 出厂恢复闪烁状态机:5个按键LED闪3次后清除Flash并重启 - if (factory_reset_blink_state > 0) { - factory_reset_blink_tick++; - if (factory_reset_blink_tick >= FACTORY_RESET_BLINK_TICKS) { - factory_reset_blink_tick = 0; - factory_reset_blink_state++; - if (factory_reset_blink_state > 6) { -#if 1 - // 3次闪烁完成:恢复原始LED显示 - factory_reset_blink_state = 0; - led_off(&led_ctx, LED_MUSIC); - led_off(&led_ctx, LED_ANC); - led_off(&led_ctx, LED_FOOTSTEP_MODE); - led_off(&led_ctx, LED_AI7_1); - led_off(&led_ctx, LED_GAME_MODE); - switch (active_mode) { - case 1: led_on(&led_ctx, LED_MUSIC); break; - case 2: led_on(&led_ctx, LED_GAME_MODE); break; - case 3: led_on(&led_ctx, LED_AI7_1); break; - default: break; + if (hp_stable && !hp_stable_prev) { + hp_restore_deadline = now + C1_JACK_RESTORE_DELAY; } - if (flag_footsteps_enhancement == 1) led_on(&led_ctx, LED_FOOTSTEP_MODE); - else if (flag_footsteps_enhancement == 2) led_set_brightness(&led_ctx, LED_FOOTSTEP_MODE, 128); - if (flag_aidenoise_onoff) led_on(&led_ctx, LED_ANC); - led_update_all(&led_ctx); - // 等待松键,防止重启后再次触发出厂恢复循环 + if (hp_jack_dac_mute && hp_restore_deadline != 0 && timeafter(now, hp_restore_deadline)) { + hp_jack_dac_mute = 0; + } + } + if (!mic_stable) { + mic_jack_adc_mute = 1; + mic_restore_deadline = 0; + mic_insert_dac_mute = 0; + mic_insert_dac_deadline = 0; + // 改动原因:MIC 拔出边沿立即拉 DAC 寄存器静音,减轻瞬态 pop;满 500ms(相对拔出时刻)后 mic_pull_dac_mute 清零恢复 g_dac_vol 对应音量。 + if (mic_stable_prev) { + mic_pull_dac_mute = 1; + mic_pull_dac_deadline = now + C1_JACK_RESTORE_DELAY; + } + if (mic_pull_dac_deadline != 0 && timeafter(now, mic_pull_dac_deadline)) { + mic_pull_dac_mute = 0; + mic_pull_dac_deadline = 0; + } + } else { + mic_pull_dac_mute = 0; + mic_pull_dac_deadline = 0; + // 改动原因:去抖后由拔出→插入的边沿:立刻 mic_insert_dac_mute 哑 DAC;自该稳定插入时刻起 500ms 后清除以恢复 g_dac_vol(与 ADC 的 mic_restore 同源边沿,时间基准一致)。 + if (mic_stable && !mic_stable_prev) { + mic_restore_deadline = now + C1_JACK_RESTORE_DELAY; + mic_insert_dac_mute = 1; + mic_insert_dac_deadline = now + C1_JACK_RESTORE_DELAY; + } + if (mic_jack_adc_mute && mic_restore_deadline != 0 && timeafter(now, mic_restore_deadline)) { + mic_jack_adc_mute = 0; + } + if (mic_insert_dac_mute && mic_insert_dac_deadline != 0 && timeafter(now, mic_insert_dac_deadline)) { + mic_insert_dac_mute = 0; + mic_insert_dac_deadline = 0; + } + } + hp_stable_prev = hp_stable; + mic_stable_prev = mic_stable; + } + } + GET_SHARED_GLOBAL(dac_vol, g_dac_vol); + GET_SHARED_GLOBAL(adc_vol, g_adc_vol); + unsigned mute_switch; + GET_SHARED_GLOBAL(mute_switch, g_mute_switch); + if (last_mute_switch_for_led != mute_switch) + { + // 改动原因:需求规定mic mute=0亮红灯,否则灭灯;LED端口在tile1,因此在tile0检测状态变化后用interface同步。 + i_c1_led_ctrl.set_mic_mute_state(mute_switch); + last_mute_switch_for_led = mute_switch; + } + // 改动原因:MIC 物理拔出时 mic_jack_adc_mute 强制 ADC 静音;插入 500ms 内仍保持静音,之后恢复 g_mute_switch 与 g_adc_vol 决定的电平(不触碰 LED 条件 mute_switch)。 + unsigned effective_adc_vol = mic_jack_adc_mute ? 0 : ((mute_switch != 0) ? 0 : adc_vol); + + // 改动原因:耳机拔出或 MIC 插/拔防 pop 时写 C1_DAC_MUTE(不改 g_dac_vol);各事件满 500ms 或互斥清除后按 g_dac_vol 写回 0x0034。 + { + unsigned dac_jack_force_mute = hp_jack_dac_mute | mic_pull_dac_mute | mic_insert_dac_mute; + unsigned dac_reg = dac_jack_force_mute ? C1_DAC_MUTE : (dac_vol & 0xff); + if (old_dac_vol != dac_vol || old_type != audio_type || old_dac_jack_force_mute != dac_jack_force_mute) { + old_dac_vol = dac_vol; + old_dac_jack_force_mute = dac_jack_force_mute; + NAU88C22_REGWRITE(0x0034, ((dac_reg & 0xff) << 8) | (dac_reg & 0xff), i2c); + SET_SHARED_GLOBAL(g_old_audio_type, audio_type); + debug_printf("set dac_reg 0x%x (hp=%d mic_pull=%d mic_ins=%d) audio_type %d \n", dac_reg, hp_jack_dac_mute, mic_pull_dac_mute, mic_insert_dac_mute, audio_type); + } + } + + // 改动原因:音量键/HID/UART 任一修改 g_dac_vol 后不立即写 Flash;仅当读回值相对 persist_snapshot 稳定满 300ms 再 save_value,满足防抖与关机保存。 + { + if (dac_vol != dac_vol_persist_snapshot) + { + dac_vol_persist_snapshot = dac_vol; + dac_vol_persist_deadline = now + C1_DAC_VOL_SAVE_DELAY; + } + else if (dac_vol_persist_deadline != 0 && timeafter(now, dac_vol_persist_deadline)) + { + save_value(C1_DAC_VOL_INFO_PATH, (unsigned char)(dac_vol & 0xff)); + dac_vol_persist_deadline = 0; + } + } + + if (old_adc_vol != effective_adc_vol) + { + if ((effective_adc_vol <= 0xff) && (effective_adc_vol >= 0)) + { + old_adc_vol = effective_adc_vol; + // 改动原因:mic mute按键会改变g_mute_switch并影响effective_adc_vol;这里复用现有mic_volume接口让静音立即作用到ADC通路。 + mic_volume(effective_adc_vol, i2c); + } + } + + GET_SHARED_GLOBAL(dac_mode, g_dac_mode); + GET_SHARED_GLOBAL(new_dac_mode, g_new_dac_mode); + + // --- C1实体按键逻辑处理 --- + // 改动原因:参考DS1按键处理模型,在主定时循环中读取端口、按低电平有效判断按下;mode/mic 用计数器区分短按窗口,音量键仅在释放时步进一档(无长按连调)。 + { + unsigned button_state; + unsigned mode_pressed; + unsigned vol_down_pressed; + unsigned mic_mute_pressed; + unsigned vol_up_pressed; + unsigned pressed_count; + + p_button :> button_state; + mode_pressed = ((button_state & C1_KEY_MODE_MASK) == 0); + vol_down_pressed = ((button_state & C1_KEY_VOL_DOWN_MASK) == 0); + mic_mute_pressed = ((button_state & C1_KEY_MIC_MUTE_MASK) == 0); + vol_up_pressed = ((button_state & C1_KEY_VOL_UP_MASK) == 0); + pressed_count = mode_pressed + vol_down_pressed + mic_mute_pressed + vol_up_pressed; + + // 改动原因:mic 首击短按后延迟 500ms 再静音,以便识别双击;仅 mic 松开时递减 mic_defer_left,到 0 执行单击静音。 + if (mic_dbl_stage == 1 && mic_defer_left > 0) + { + unsigned mic_released_now = ((button_state & C1_KEY_MIC_MUTE_MASK) != 0); + if (mic_released_now) + { + mic_defer_left--; + if (mic_defer_left == 0) { - unsigned mw, gw; - do { - delay_milliseconds(10); - p_button_music_mode :> mw; - p_button_game_mode :> gw; - } while (mw == 0 || gw == 0); - delay_milliseconds(100); + unsigned current_mute_switch; + unsigned effective_adc_vol; + GET_SHARED_GLOBAL(effective_adc_vol, g_adc_vol); + GET_SHARED_GLOBAL(current_mute_switch, g_mute_switch); + current_mute_switch = (current_mute_switch == 0) ? 1 : 0; + + if (current_mute_switch == 0) + { + mic_volume(0, i2c); + } + else + { + mic_volume(effective_adc_vol, i2c); + } + SET_SHARED_GLOBAL(g_mute_switch, current_mute_switch); + i_c1_led_ctrl.set_mic_mute_state(current_mute_switch); + last_mute_switch_for_led = current_mute_switch; + debug_printf("C1 key mic mute toggle (deferred single): %d\n", current_mute_switch); + mic_dbl_stage = 0; } -#endif - // 出厂恢复默认AI7.1模式(mode=3),需要F3/F4固件 - SetRoleSwitchFlag(MODE_F3_F4_FPS_UAC2); - delay_milliseconds(20); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } else if (factory_reset_blink_state % 2 == 0) { - // 偶数相:全灭 - led_off(&led_ctx, LED_MUSIC); - led_off(&led_ctx, LED_ANC); - led_off(&led_ctx, LED_FOOTSTEP_MODE); - led_off(&led_ctx, LED_AI7_1); - led_off(&led_ctx, LED_GAME_MODE); - led_update_all(&led_ctx); - delay_milliseconds(200); - } else { - // 奇数相:全亮 - led_on(&led_ctx, LED_MUSIC); - led_on(&led_ctx, LED_ANC); - led_on(&led_ctx, LED_FOOTSTEP_MODE); - led_on(&led_ctx, LED_AI7_1); - led_on(&led_ctx, LED_GAME_MODE); - led_update_all(&led_ctx); - delay_milliseconds(200); } } - } -#if USE_EX3D == 1 - mode_change = 0; - if(button_footsteps_enhancement == 0) - { - if(push_button_footsteps_enhancement_state_old == 1) + if (pressed_count == 1) { - // 3档循环: 0(关/0dB) → 1(中亮/6dB) → 2(高亮/12dB) → 0 - flag_footsteps_enhancement = (flag_footsteps_enhancement + 1) % 3; - mode_change = 1; - debug_printf("Footstep mode changed: %d -> %d\n", flag_footsteps_enhancement, flag_footsteps_enhancement + 1); - } - } - push_button_footsteps_enhancement_state_old = button_footsteps_enhancement; - if(mode_change) - { - if(flag_footsteps_enhancement == 0) - { - saved_footstep = 0; - led_off(&led_ctx, LED_FOOTSTEP_MODE); - } - else if(flag_footsteps_enhancement == 1) - { - saved_footstep = 6; - led_on(&led_ctx, LED_FOOTSTEP_MODE); - } - else - { - saved_footstep = 12; - led_set_brightness(&led_ctx, LED_FOOTSTEP_MODE, 128); - } - led_update_all(&led_ctx); - // 发送expand_gain到tile1执行 - cc_mic_level <: 0xFD; - cc_mic_level <: (unsigned)saved_footstep; - // 掉电保存 - unsigned char footstep_path[] = "footstep"; - save_value(footstep_path, (unsigned char)saved_footstep); - debug_printf("Footstep state=%d, expand_gain=%d\n", flag_footsteps_enhancement, saved_footstep); - } - - // HID 0xB0 CMD_EXPAND_GAIN请求:同步footstep LED状态 - { - unsigned hid_gain_req; - GET_SHARED_GLOBAL(hid_gain_req, g_hid_expand_gain_request); - if (hid_gain_req != (unsigned)-1) { - SET_SHARED_GLOBAL(g_hid_expand_gain_request, (unsigned)-1); - // 将增益值映射到footstep档位 - unsigned new_state; - if (hid_gain_req == 0) { - new_state = 0; - } else if (hid_gain_req <= 6) { - new_state = 1; - } else { - new_state = 2; + // 改动原因:mic 双击等待期间若用户去按 mode/音量键,应取消延迟单击静音,避免误切 g_mute_switch。 + if (!mic_mute_pressed) + { + mic_dbl_stage = 0; + mic_defer_left = 0; } - if (new_state != (unsigned)flag_footsteps_enhancement) { - flag_footsteps_enhancement = (int)new_state; - if (flag_footsteps_enhancement == 0) { - led_off(&led_ctx, LED_FOOTSTEP_MODE); - } else if (flag_footsteps_enhancement == 1) { - led_on(&led_ctx, LED_FOOTSTEP_MODE); - } else { - led_set_brightness(&led_ctx, LED_FOOTSTEP_MODE, 128); + if (mode_pressed) + { + mode_press_ticks++; + // 改动原因:同一时刻只允许一个实体键生效,切到mode键时清除其它键计时,避免滑键后释放误触发。 + vol_down_press_ticks = 0; + mic_mute_press_ticks = 0; + vol_up_press_ticks = 0; + } + else if (vol_down_pressed) + { + vol_down_press_ticks++; + // 改动原因:同一时刻只允许音量-键生效,清除其它键状态以匹配DS1单键状态机处理方式。 + mode_press_ticks = 0; + mic_mute_press_ticks = 0; + vol_up_press_ticks = 0; + } + else if (mic_mute_pressed) + { + // 改动原因:双击窗口内第二下按下,取消延迟单击静音,改为等待释放后判双击变声。 + if (mic_dbl_stage == 1) + { + mic_defer_left = 0; + mic_dbl_stage = 2; } - led_update_all(&led_ctx); + mic_mute_press_ticks++; + // 改动原因:同一时刻只允许mic mute键生效,清除其它键状态,避免释放时误执行音量或mode短按。 + mode_press_ticks = 0; + vol_down_press_ticks = 0; + vol_up_press_ticks = 0; } - - unsigned char fp[] = "footstep"; - save_value(fp, (unsigned char)hid_gain_req); - saved_footstep = hid_gain_req; - debug_printf("HID set footstep gain=%d, state=%d\n", hid_gain_req, flag_footsteps_enhancement); - } - } - - // HID 0xB0 CMD_LMT_THRESHOLD请求:保存阈值到flash - // eq.c以(-threshold+1)编码存入shared global,范围1~36;此处解码后存flash (0~35) - { - unsigned hid_thresh_req; - GET_SHARED_GLOBAL(hid_thresh_req, g_hid_lmt_threshold_request); - if (hid_thresh_req != (unsigned)-1) { - SET_SHARED_GLOBAL(g_hid_lmt_threshold_request, (unsigned)-1); - if (hid_thresh_req >= 1 && hid_thresh_req <= 36) { - unsigned char lmt_thresh_path[] = "lmt_thresh"; - unsigned char flash_raw = (unsigned char)(hid_thresh_req - 1); - save_value(lmt_thresh_path, flash_raw); - debug_printf("HID set lmt_threshold=-%d, saved to flash\n", (int)(hid_thresh_req - 1)); - } - } - } - - // HID 0xB0 CMD_ANGLE请求:保存角度到flash - { - for (int i = 0; i < EX3D_ANGLE_CHANNELS; ++i) - { - // 改动原因:按用户要求去掉normalize,直接比较并保存原始角度值,减少计算分支。 - unsigned angle = g_hid_angle_values[i]; - if (angle != g_hid_angle_values_old[i]) + else if (vol_up_pressed) { - ex3d_angle_save_channel(i, angle); - g_hid_angle_values_old[i] = angle; + vol_up_press_ticks++; + // 改动原因:同一时刻只允许音量+键生效,清除其它键状态以匹配DS1单键状态机处理方式。 + mode_press_ticks = 0; + vol_down_press_ticks = 0; + mic_mute_press_ticks = 0; } } - } -#endif - - mode_change = 0; - if(button_aidenoise_onoff == 0) - { - if(push_button_aidenoise_onoff_state_old == 1) - { - flag_aidenoise_onoff ^= 1; - mode_change = 1; - } - } - push_button_aidenoise_onoff_state_old = button_aidenoise_onoff; -#if DNR_ENABLE == 1 - if(mode_change) { - if(flag_aidenoise_onoff) - { - // 改动原因:开时应用当前保存的档位g_dnr_strength,不把强度全局量写成0 - unsigned gs_on; - GET_SHARED_GLOBAL(gs_on, g_dnr_strength); - led_on(&led_ctx, LED_ANC); - dnr_set_strength_level((unsigned char)gs_on); - SET_SHARED_GLOBAL(g_dnr_on, 1); - dnr_strength_saved = gs_on; - } else { - // 改动原因:关时只清开关与算法档位,保留g_dnr_strength供HID 0x86与再次开启 - led_off(&led_ctx, LED_ANC); - dnr_set_strength_level(DNR_STRENGTH_off); - SET_SHARED_GLOBAL(g_dnr_on, 0); - } - save_value(dnr_on_path, (unsigned char)flag_aidenoise_onoff); - { - unsigned gs_sv; - GET_SHARED_GLOBAL(gs_sv, g_dnr_strength); - save_value(dnr_strength_path, (unsigned char)gs_sv); - } - g_dnr_on = flag_aidenoise_onoff; - led_update_all(&led_ctx); - } -#endif - - // 检查HID 0x84 FACTORY_RESET请求 - { - unsigned factory_reset_req; - GET_SHARED_GLOBAL(factory_reset_req, g_request_factory_reset); - if (factory_reset_req) { - SET_SHARED_GLOBAL(g_request_factory_reset, 0); - debug_printf("Factory reset: rebooting...\n"); - unsafe { - lfs_format_all(); - } - delay_milliseconds(500); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } - } - - mode_change = 0; - if(button_mic_mute == 0) - { - if(push_button_mic_mute_state_old == 1) - { - flag_mic_mute ^= 1; - mode_change = 1; - } - } - push_button_mic_mute_state_old = button_mic_mute; - if(mode_change) - { - save_value(mic_mute_path, (unsigned char)flag_mic_mute); - debug_printf("mic_mute changed: %d, saved to flash\n", flag_mic_mute); - } - if(mode_change) - if(flag_mic_mute) - { - mic_volume(0); - g_mic_volume_level = 0; - for(int i = 0; i < 15; i++) - led_on(&led_ctx, led_l_physical_map[i]); - mic_mute_blink_tick = 1; - } - else - { - if (!mic_det_muted) - mic_volume(mic_hid_level_to_codec_gain(codec_adc_pga_gain_reg_value)); - g_mic_volume_level = (codec_adc_pga_gain_reg_value <= MIC_HID_LEVEL_MAX) ? codec_adc_pga_gain_reg_value : MIC_HID_LEVEL_MAX; - mic_mute_blink_tick = 0; - for(int i = 0; i < 15; i++) - led_off(&led_ctx, led_l_physical_map[i]); - current_mic_led_pos = mic_gain_to_led[codec_adc_pga_gain_reg_value] - 1; - for(int i = 0; i <= current_mic_led_pos; i++) + if (pressed_count == 0) { - if ((i < 15) && (i >= 0)) - led_on(&led_ctx, led_l_physical_map[i]); + // 改动原因:mode 短按在 c1_mode 1~5 间循环,灯索引与 mode 同值;持久化后切角色并 set_mode_led_color(c1_mode) 下发 tile1(无重启路径必须调用否则灯不更新)。 + if ((mode_press_ticks >= C1_KEY_SHORT_TICKS) && (mode_press_ticks < C1_KEY_LONG_TICKS)) + { + c1_mode ++; + if (c1_mode > C1_MODE_VALUE_MAX) + { + c1_mode = C1_MODE_VALUE_MIN; + } + save_value(C1_MODE_INFO_PATH, c1_mode); + + switch_mode_by_c1_mode(c1_mode, 0); + i_c1_led_ctrl.set_mode_led_color(c1_mode_to_tile_mode_led_code(c1_mode)); + } + + // 改动原因:音量键仅短按——释放时若已满足去抖时长则步进一档,与按住时长无关(已取消长按连调)。 + if (vol_down_press_ticks >= C1_KEY_SHORT_TICKS) + { + unsigned current_dac_vol; + GET_SHARED_GLOBAL(current_dac_vol, g_dac_vol); + // 改动原因:短按执行“最小值再按一次直达mute(0x00)”规则。 + if (current_dac_vol == C1_DAC_VOL_MIN) + { + current_dac_vol = C1_DAC_MUTE; + SET_SHARED_GLOBAL(g_dac_vol, current_dac_vol); + debug_printf("C1 key volume down short to mute: %d\n", current_dac_vol); + } + // 改动原因:短按按步进2减小(1dB);并钳位到0x4B,避免进入最小值以下的无效区间。 + else if (current_dac_vol > C1_DAC_VOL_MIN) + { + if (current_dac_vol <= (C1_DAC_VOL_MIN + C1_DAC_VOL_STEP)) + current_dac_vol = C1_DAC_VOL_MIN; + else + current_dac_vol -= C1_DAC_VOL_STEP; + SET_SHARED_GLOBAL(g_dac_vol, current_dac_vol); + debug_printf("C1 key volume down short: %d\n", current_dac_vol); + } + } + + // 改动原因:mic:短按静音改为延迟单击(防双击);双击短按切变声灯(橙R+G);按住满1.5s仅切 AI 状态变量无灯;长按与短/双互斥。 + { + unsigned mic_snap = mic_mute_press_ticks; + if (mic_snap > 0) + { + if ((mic_snap >= C1_KEY_MIC_AI_NR_TICKS) || mic_ai_long_fired) + { + if (mic_dbl_stage == 2) + mic_dbl_stage = 0; + } + else if ((mic_snap >= C1_KEY_SHORT_TICKS) && (mic_snap < C1_KEY_MIC_AI_NR_TICKS)) + { + if (mic_dbl_stage == 2) + { + c1_mic_voice_fx = (c1_mic_voice_fx ? 0 : 1); + i_c1_led_ctrl.set_mic_voice_fx(c1_mic_voice_fx); + mic_dbl_stage = 0; + mic_defer_left = 0; + debug_printf("C1 mic voice/beautifier toggle: %d\n", c1_mic_voice_fx); + } + else + { + mic_dbl_stage = 1; + mic_defer_left = C1_MIC_DOUBLE_DEFER_TICKS; + } + } + mic_ai_long_fired = 0; + } + } + + // 改动原因:音量键仅短按——释放时若已满足去抖时长则步进一档(已取消长按连调)。 + if (vol_up_press_ticks >= C1_KEY_SHORT_TICKS) + { + unsigned current_dac_vol; + GET_SHARED_GLOBAL(current_dac_vol, g_dac_vol); + // 改动原因:短按从mute恢复时先到0x4B,保证UI和听感从可听最小档开始。 + if (current_dac_vol < C1_DAC_VOL_MIN) + { + current_dac_vol = C1_DAC_VOL_MIN; + SET_SHARED_GLOBAL(g_dac_vol, current_dac_vol); + debug_printf("C1 key volume up short from mute: %d\n", current_dac_vol); + } + // 改动原因:短按按步进2增加(1dB);并钳位到0xCF,不越界。 + else if (current_dac_vol < C1_DAC_VOL_MAX) + { + if (current_dac_vol >= (C1_DAC_VOL_MAX - C1_DAC_VOL_STEP)) + current_dac_vol = C1_DAC_VOL_MAX; + else + current_dac_vol += C1_DAC_VOL_STEP; + SET_SHARED_GLOBAL(g_dac_vol, current_dac_vol); + debug_printf("C1 key volume up short: %d\n", current_dac_vol); + } + } + } + else if (pressed_count > 1) + { + // 改动原因:多键同按时取消 mic 双击等待,避免组合键松手后误触发延迟静音。 + mic_dbl_stage = 0; + mic_defer_left = 0; + } + + // 改动原因:多键同时按下不映射功能,立即清除本轮计时,避免组合键抖动误触发单键动作。 + mode_press_ticks = 0; + vol_down_press_ticks = 0; + mic_mute_press_ticks = 0; + vol_up_press_ticks = 0; + } + } + +#if 0// UAC1 + unsigned p_8ch_in_val; + p_8ch_in :> p_8ch_in_val; + if ((p_8ch_in_val & 0x40) == 0x40) + { + g_dnr_enable = 0; + } + else + { + g_dnr_enable = 1; + } + + if ((p_8ch_in_val & 0xa0) == 0xa0) + { + g_fps_enable = 1; + g_3d_enable = 0; + } + else if ((p_8ch_in_val & 0xa0) == 0x20) + { + g_3d_enable = 1; + g_fps_enable = 0; + } + else + { + g_3d_enable = 0; + g_fps_enable = 0; + } +#endif + +#if ((HID_CONTROLS == 1) && (EQ_EN == 1)) + + // 改动原因:检测增益模式变化请求,当g_request_gain_mode != -1且与当前模式不同时应用 + { + unsigned request_gain_mode, gain_mode; + GET_SHARED_GLOBAL(request_gain_mode, g_request_gain_mode); + GET_SHARED_GLOBAL(gain_mode, g_gain_mode); + if (request_gain_mode != -1 && request_gain_mode != gain_mode) + { + debug_printf("Gain mode changing: %d -> %d\n", gain_mode, request_gain_mode); + SET_SHARED_GLOBAL(g_gain_mode, request_gain_mode); + + // 更新音量以应用新的增益模式 + unsigned volume_level; + GET_SHARED_GLOBAL(volume_level, g_volume_level); + //update_volume(request_gain_mode, volume_level, i2c); + + // 清除请求标志 + SET_SHARED_GLOBAL(g_request_gain_mode, -1); + debug_printf("Gain mode switched to: %d\n", request_gain_mode); + } + } + + // 改动原因:检测滤波器模式变化请求,当g_request_filter_mode != -1且与当前模式不同时应用 + { + unsigned request_filter_mode, filter_mode; + GET_SHARED_GLOBAL(filter_mode, g_filter_mode); + GET_SHARED_GLOBAL(request_filter_mode, g_request_filter_mode); + if (request_filter_mode != -1 && request_filter_mode != filter_mode) + { + debug_printf("Filter mode changing: %d -> %d\n", filter_mode, request_filter_mode); + SET_SHARED_GLOBAL(g_filter_mode, request_filter_mode); + + // 清除请求标志 + SET_SHARED_GLOBAL(g_request_filter_mode, -1); + } + } + + // 改动原因:检测g_dac_vol的变化,如果变化则通过HID上报 + // 参考hid_ret_process和UserReadHIDLog方式,使用指针访问全局数组 + { + // 改动原因:检测g_dac_vol的变化,而不是g_volume_level + unsigned current_dac_vol; + GET_SHARED_GLOBAL(current_dac_vol, g_dac_vol); + + // 如果g_dac_vol发生变化,构建0x94 GET_VOLUME响应数据包并上报 + if (g_last_dac_vol != current_dac_vol && g_last_dac_vol != 0xFF) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; + + // 构建0x94 GET_VOLUME响应数据包格式(参考eq_hid_protocol.md) + // 字节位置 | 长度 | 内容 | 描述 + // 0 | 1 | 0x77 | 同步头1 + // 1 | 1 | 0x94 | 同步头2 + // 2 | 1 | uint8 | 当前音量级别 (0-255) + // 3-62 | 60 | 0x00 | 保留字节 + reportPtr[0] = 0x77; // 同步头1 + reportPtr[1] = 0x94; // 同步头2(GET_VOLUME命令) + reportPtr[2] = (unsigned char)current_dac_vol; // 当前音量级别(0-255) + + // 其余字节填充为0 + for (int i = 3; i < 63; i++) + { + reportPtr[i] = 0x00; + } + + // 通知HID系统有数据变化 + hidSetChangePending(0x1); + + debug_printf("DAC volume changed: %d -> %d, HID report prepared\n", + g_last_dac_vol, current_dac_vol); } } - uint8_t rotating = (mic_encoder2 & 0b0100) == 0; // 4E2 - uint8_t encode_input1 = ((mic_encoder1 & 0b0100) != 0); // 4F2 - if(rotating) { - if(!rotation_active) { - // 旋转开始 - prev_encode_input1 = encode_input1; - sample_count = 1; - rotation_active = 1; + g_last_dac_vol = current_dac_vol; - // 根据上次方向预判 - if(fast_rotation_mode) { - // 快速模式只需要2次采样 - sample_count = 2; + // 改动原因:检测静音开关状态变化,如果变化则通过HID上报0xB2(格式参考eq_hid_protocol.md),与g_adc_loop一致直接读g_mute_switch + { + unsigned current_mute; + GET_SHARED_GLOBAL(current_mute, g_mute_switch); + if (g_last_mute_switch != current_mute && g_last_mute_switch != 0xFF) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; + reportPtr[0] = 0x77; + reportPtr[1] = 0xB2; // GET_MUTE_SWITCH + reportPtr[2] = (unsigned char)current_mute; + for (int i = 3; i < 63; i++) reportPtr[i] = 0x00; + hidSetChangePending(0x1); + } + debug_printf("Mute switch changed: %d -> %d, HID 0xB2 report prepared\n", g_last_mute_switch, current_mute); } + g_last_mute_switch = current_mute; + } + + // 改动原因:检测监听开关(g_adc_loop)状态变化,如果变化则通过HID上报0xB4(格式参考eq_hid_protocol.md) + { + unsigned current_adc_loop; + GET_SHARED_GLOBAL(current_adc_loop, g_adc_loop); + if (g_last_adc_loop != current_adc_loop && g_last_adc_loop != 0xFF) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; + reportPtr[0] = 0x77; + reportPtr[1] = 0xB4; // GET_LISTEN_SWITCH + reportPtr[2] = (unsigned char)(current_adc_loop & 0xFF); + for (int i = 3; i < 63; i++) reportPtr[i] = 0x00; + hidSetChangePending(0x1); + } + debug_printf("Listen switch (g_adc_loop) changed: %d -> %d, HID 0xB4 report prepared\n", g_last_adc_loop, current_adc_loop); + } + g_last_adc_loop = current_adc_loop; + } + + // 改动原因:检测LED状态变化,根据音频格式判断颜色:PCM=绿灯,DOP/DSD=蓝灯 + // 读取音频类型和LED模式 + unsigned current_audio_type = g_audio_type; + unsigned led_mode; + GET_SHARED_GLOBAL(led_mode, g_led_mode); + + // 根据音频格式计算LED颜色RGB值 + // PCM (audio_type=0): 绿灯 RGB(0, 255, 0) + // DOP (audio_type=1): 蓝灯 RGB(0, 0, 255) + // DSD (audio_type=5): 蓝灯 RGB(0, 0, 255) + unsigned current_r = 0, current_g = 0, current_b = 0; + if (current_audio_type == 0) { + // PCM: 绿灯 + current_g = 255; + current_b = 0; + } else if (current_audio_type == 1 || current_audio_type == 5) { + // DOP (1) 或 DSD (5): 蓝灯 + current_g = 0; + current_b = 255; } else { - sample_count++; + // 其他格式:默认关闭 + current_g = 255; + current_b = 0; + } - // 动态调整采样次数:快速模式用2次,普通模式用3次 - uint8_t required_samples = fast_rotation_mode ? 2 : 3; + // 计算当前LED状态:根据g_led_mode,0=关闭,1=开启(常亮) + unsigned calculated_led_status = (led_mode == 0) ? 0 : 1; // 0=LED_STATUS_OFF, 1=LED_STATUS_SOLID - if(sample_count >= required_samples) { - if(encode_input1 != prev_encode_input1) { - uint8_t current_dir = encode_input1 ? 1 : 2; + // 如果LED颜色或状态发生变化,构建0x98 GET_LED_STATUS响应数据包并上报 + // 改动原因:检测audio_type和led_mode的变化,而不是g_led_color + if ((g_last_audio_type != current_audio_type || g_last_led_status != calculated_led_status) + && g_last_audio_type != 0xFF) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; - // 执行音量调节 - if(current_dir == 1) { // 顺时针 - if((codec_adc_pga_gain_reg_value < MIC_HID_LEVEL_MAX) && (flag_mic_mute == 0)) { - uint8_t old_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value]; + // 构建0x98 GET_LED_STATUS响应数据包格式(参考eq_hid_protocol.md) + // 字节位置 | 长度 | 内容 | 描述 + // 0 | 1 | 0x77 | 同步头1 + // 1 | 1 | 0x98 | 同步头2 + // 2 | 1 | uint8 | LED索引 (0-7) + // 3 | 1 | uint8 | R颜色值 (0-255) + // 4 | 1 | uint8 | G颜色值 (0-255) + // 5 | 1 | uint8 | B颜色值 (0-255) + // 6 | 1 | uint8 | LED状态 (0=熄灭, 1=常亮, 2=慢闪, 3=快闪, 4=呼吸) + // 7-62 | 56 | 0x00 | 保留字节 + reportPtr[0] = 0x77; // 同步头1 + reportPtr[1] = 0x98; // 同步头2(GET_LED_STATUS命令) + reportPtr[2] = 0; // LED索引(当前设备只有1个LED,索引为0) - codec_adc_pga_gain_reg_value = codec_adc_pga_gain_reg_value + 2; - if (codec_adc_pga_gain_reg_value > MIC_HID_LEVEL_MAX) { - codec_adc_pga_gain_reg_value = MIC_HID_LEVEL_MAX; - } + // 改动原因:根据音频格式判断LED颜色,PCM=绿灯,DOP/DSD=蓝灯 + reportPtr[3] = (unsigned char)current_r; // R颜色值 + reportPtr[4] = (unsigned char)current_g; // G颜色值 + reportPtr[5] = (unsigned char)current_b; // B颜色值 + reportPtr[6] = (unsigned char)calculated_led_status; // LED状态 - if (!mic_det_muted) - mic_volume(mic_hid_level_to_codec_gain(codec_adc_pga_gain_reg_value)); - g_mic_volume_level = (codec_adc_pga_gain_reg_value <= MIC_HID_LEVEL_MAX) ? codec_adc_pga_gain_reg_value : MIC_HID_LEVEL_MAX; - debug_printf("volume up %d\n", codec_adc_pga_gain_reg_value); - save_value(mic_vol_path, codec_adc_pga_gain_reg_value); - uint8_t new_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value]; + // 其余字节填充为0 + for (int i = 7; i < 63; i++) + { + reportPtr[i] = 0x00; + } - // 如果LED数增加,点亮新增的那个LED - if(new_led_count > old_led_count) { - // 新点亮的LED索引 = new_led_count - 1 - led_on(&led_ctx, led_l_physical_map[new_led_count - 1]); - led_update_all(&led_ctx); - } - } - } else { // 逆时针 - if((codec_adc_pga_gain_reg_value > 0) && (flag_mic_mute == 0)) { - uint8_t old_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value]; + // 通知HID系统有数据变化 + hidSetChangePending(0x1); + } - codec_adc_pga_gain_reg_value = codec_adc_pga_gain_reg_value - 2; - if (codec_adc_pga_gain_reg_value < 0) { - codec_adc_pga_gain_reg_value = 0; - } + debug_printf("LED status changed: audio_type %d -> %d, RGB (%d,%d,%d), status %d -> %d, HID report prepared\n", + g_last_audio_type, current_audio_type, current_r, current_g, current_b, g_last_led_status, calculated_led_status); + } - if (!mic_det_muted) { - if (codec_adc_pga_gain_reg_value == 0) - mic_volume(0); - else - mic_volume(mic_hid_level_to_codec_gain(codec_adc_pga_gain_reg_value)); - } - g_mic_volume_level = (codec_adc_pga_gain_reg_value <= MIC_HID_LEVEL_MAX) ? codec_adc_pga_gain_reg_value : MIC_HID_LEVEL_MAX; - debug_printf("volume down %d\n", codec_adc_pga_gain_reg_value); - save_value(mic_vol_path, codec_adc_pga_gain_reg_value); + g_last_audio_type = current_audio_type; + g_last_led_status = calculated_led_status; - uint8_t new_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value]; + // 改动原因:检测采样率和DSD模式变化,如果变化则通过HID上报0x9F命令(已去掉DAC采样分辨率) + unsigned current_samfreq; + unsigned current_dsd_mode; + unsigned last_samfreq; + unsigned last_dsd_mode; + GET_SHARED_GLOBAL(last_samfreq, g_last_samfreq); + GET_SHARED_GLOBAL(last_dsd_mode, g_last_dsd_mode); + GET_SHARED_GLOBAL(current_samfreq, g_samfreq); + GET_SHARED_GLOBAL(current_dsd_mode, g_dsd_mode); - // 如果LED数减少,关闭减少的那个LED - if(new_led_count < old_led_count) { - // 关闭的LED索引 = old_led_count - 1 - led_off(&led_ctx, led_l_physical_map[old_led_count - 1]); - led_update_all(&led_ctx); - } - } + // 改动原因:修复上报逻辑,只要采样率或DSD模式发生变化就上报,且只在初始化完成后才检查变化 + // 如果采样率或DSD模式发生变化,构建0x9F GET_SAMPLE_FORMAT响应数据包并上报 + if (last_samfreq != 0xFFFFFFFF && last_dsd_mode != 0xFF) + { + // 初始化完成后,检查是否有变化 + if (last_samfreq != current_samfreq || last_dsd_mode != current_dsd_mode) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; + + // 构建0x9F GET_SAMPLE_FORMAT响应数据包格式 + // 字节位置 | 长度 | 内容 | 描述 + // 0 | 1 | 0x77 | 同步头1 + // 1 | 1 | 0x9F | 同步头2(GET_SAMPLE_FORMAT命令) + // 2-5 | 4 | uint32 | 采样率 (samFreq) + // 6 | 1 | uint8 | DSD模式 (dsdMode: 0=PCM, >0=DSD) + // 7-62 | 56 | 0x00 | 保留字节 + reportPtr[0] = 0x77; // 同步头1 + reportPtr[1] = 0x9F; // 同步头2(GET_SAMPLE_FORMAT命令) + + // 采样率(32位,小端序) + reportPtr[2] = (unsigned char)(current_samfreq & 0xFF); + reportPtr[3] = (unsigned char)((current_samfreq >> 8) & 0xFF); + reportPtr[4] = (unsigned char)((current_samfreq >> 16) & 0xFF); + reportPtr[5] = (unsigned char)((current_samfreq >> 24) & 0xFF); + + // DSD模式 + reportPtr[6] = (unsigned char)current_dsd_mode; + + debug_printf("Sample format changed: samFreq %d -> %d, dsdMode %d -> %d\n", + last_samfreq, current_samfreq, last_dsd_mode, current_dsd_mode); + + // 其余字节填充为0 + for (int i = 7; i < 63; i++) + { + reportPtr[i] = 0x00; } - // 检测是否快速旋转 - if(current_dir == last_valid_direction) { - consecutive_same_dir++; - if(consecutive_same_dir >= 3) { - fast_rotation_mode = 1; // 进入快速模式 - } - } else { - consecutive_same_dir = 0; - fast_rotation_mode = 0; // 方向变化,退出快速模式 - } + // 改动原因:更新全局变量,使用SHARED_GLOBAL宏确保线程安全 + SET_SHARED_GLOBAL(g_last_samfreq, current_samfreq); + SET_SHARED_GLOBAL(g_last_dsd_mode, current_dsd_mode); - last_valid_direction = current_dir; - rotation_active = 0; - sample_count = 0; + // 通知HID系统有数据变化 + hidSetChangePending(0x1); + + debug_printf("Sample format changed, HID report prepared\n"); } } } - } else { - rotation_active = 0; - sample_count = 0; - // 停止旋转一段时间后退出快速模式 - static uint16_t idle_count = 0; - idle_count++; - if(idle_count > 50) { // 50ms无旋转 - fast_rotation_mode = 0; - consecutive_same_dir = 0; - idle_count = 0; - } - } - -#if 1 - // HP Encoder - p_hp_gain_encoder :> hp_encoder; // 8D4, 8D5 - - uint8_t hp_rotating = ((hp_encoder & 0b00100000) == 0); // 8D5 - uint8_t hp_encode_input1 = ((hp_encoder & 0b00010000) != 0); // 8D4 - - if(hp_rotating) { - if(!hp_rotation_active) { - // 旋转开始 - hp_prev_encode_input1 = hp_encode_input1; - hp_sample_count = 1; - hp_rotation_active = 1; - - // 根据上次方向预判 - if(hp_fast_rotation_mode) { - // 快速模式只需要2次采样 - hp_sample_count = 2; - } - } else { - hp_sample_count++; - - // 动态调整采样次数:快速模式用2次,普通模式用3次 - uint8_t hp_required_samples = hp_fast_rotation_mode ? 2 : 3; - - if(hp_sample_count >= hp_required_samples) { - if(hp_encode_input1 != hp_prev_encode_input1) { - uint8_t hp_current_dir = hp_encode_input1 ? 1 : 2; - - // 执行音量调节 - if(hp_current_dir == 1) { // 顺时针 - if(dac_level < DAC_LEVEL_MAX && flag_hp_mute == 0) { - uint8_t old_led_count = dac_gain_to_led[dac_level]; - - // 增加音量 - dac_level = dac_level + 2; - if (dac_level > DAC_LEVEL_MAX) { - dac_level = DAC_LEVEL_MAX; - } - g_volume_level = dac_level; - if (!dac_det_muted) - dac_volume(dac_level); - save_value(dac_vol_path, dac_level); - - uint8_t new_led_count = dac_gain_to_led[dac_level]; - - // 如果LED数增加,点亮新增的那个LED - if(new_led_count > old_led_count) { - // 新点亮的LED索引 = new_led_count - 1 - led_on(&led_ctx, led_d_physical_map[new_led_count - 1]); - led_update_all(&led_ctx); - } - } - } else { // 逆时针 - if(dac_level > DAC_LEVEL_MIN && flag_hp_mute == 0) { - uint8_t old_led_count = dac_gain_to_led[dac_level]; - - // 减小音量 - dac_level = dac_level - 2; - if (dac_level < DAC_LEVEL_MIN) { - dac_level = DAC_LEVEL_MIN; - } - g_volume_level = dac_level; - if (!dac_det_muted) { - if(dac_level == DAC_LEVEL_MIN) - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - else - dac_volume(dac_level); - } - save_value(dac_vol_path, dac_level); - - uint8_t new_led_count = dac_gain_to_led[dac_level]; - - // 如果LED数减少,关闭减少的那个LED - if(new_led_count < old_led_count) { - // 关闭的LED索引 = old_led_count - 1 - led_off(&led_ctx, led_d_physical_map[old_led_count - 1]); - led_update_all(&led_ctx); - } - } - } - - // 检测是否快速旋转 - if(hp_current_dir == hp_last_valid_direction) { - hp_consecutive_same_dir++; - if(hp_consecutive_same_dir >= 3) { - hp_fast_rotation_mode = 1; // 进入快速模式 - } - } else { - hp_consecutive_same_dir = 0; - hp_fast_rotation_mode = 0; // 方向变化,退出快速模式 - } - - hp_last_valid_direction = hp_current_dir; - hp_rotation_active = 0; - hp_sample_count = 0; - } - } - } - } else { - hp_rotation_active = 0; - hp_sample_count = 0; - // 停止旋转一段时间后退出快速模式 - static uint16_t hp_idle_count = 0; - hp_idle_count++; - if(hp_idle_count > 50) { // 50ms无旋转 - hp_fast_rotation_mode = 0; - hp_consecutive_same_dir = 0; - hp_idle_count = 0; - } - } - - button_hp_mute = ((hp_encoder & 0b01000000) != 0); // 8D6 - - mode_change = 0; - if(button_hp_mute == 0) - { - if(push_button_hp_mute_state_old == 1) - { - flag_hp_mute ^= 1; - mode_change = 1; - } - } - push_button_hp_mute_state_old = button_hp_mute; - if(mode_change) - { - save_value(hp_mute_path, (unsigned char)flag_hp_mute); - debug_printf("hp_mute changed: %d, saved to flash\n", flag_hp_mute); - } - if(mode_change) - if(flag_hp_mute) - { - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - g_volume_level = 0; - for(int i = 0; i < 15; i++) - led_on(&led_ctx, led_d_physical_map[i]); - hp_mute_blink_tick = 1; - } else { - if (!dac_det_muted) { - if(dac_level == DAC_LEVEL_MIN) - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - else - dac_volume(dac_level); - } - g_volume_level = dac_level; - hp_mute_blink_tick = 0; - for(int i = 0; i < 15; i++) - led_off(&led_ctx, led_d_physical_map[i]); - current_mic_led_pos = dac_gain_to_led[dac_level] - 1; - for(int i = 0; i <= current_mic_led_pos; i++) + // 改动原因:首次初始化时,直接设置last值,不触发上报,等待下次变化时再上报 + SET_SHARED_GLOBAL(g_last_samfreq, current_samfreq); + SET_SHARED_GLOBAL(g_last_dsd_mode, current_dsd_mode); + debug_printf("Sample format initialized: samFreq %d, dsdMode %d\n", current_samfreq, current_dsd_mode); + } + + // 改动原因:检测增益模式变化,如果变化则通过HID上报0xA1 GET_GAIN_MODE命令 + unsigned current_gain_mode; + GET_SHARED_GLOBAL(current_gain_mode, g_gain_mode); + + // 如果增益模式发生变化,构建0xA1 GET_GAIN_MODE响应数据包并上报 + if (g_last_gain_mode != current_gain_mode && g_last_gain_mode != 0xFF) + { + unsafe { - if ((i < 15) && (i >= 0)) - led_on(&led_ctx, led_d_physical_map[i]); + unsigned char * unsafe reportPtr = g_hid_pass_data; + + // 构建0xA1 GET_GAIN_MODE响应数据包格式(参考eq_hid_protocol.md) + // 字节位置 | 长度 | 内容 | 描述 + // 0 | 1 | 0x77 | 同步头1 + // 1 | 1 | 0xA1 | 同步头2(GET_GAIN_MODE命令) + // 2 | 1 | uint8 | 当前增益模式 (0=低阻, 1=高阻) + // 3-62 | 60 | 0x00 | 保留字节 + reportPtr[0] = 0x77; // 同步头1 + reportPtr[1] = 0xA1; // 同步头2(GET_GAIN_MODE命令) + reportPtr[2] = (unsigned char)current_gain_mode; // 当前增益模式 + + // 其余字节填充为0 + for (int i = 3; i < 63; i++) + { + reportPtr[i] = 0x00; + } + + // 通知HID系统有数据变化 + hidSetChangePending(0x1); + + debug_printf("Gain mode changed: %d -> %d, HID report prepared\n", + g_last_gain_mode, current_gain_mode); } } - // mute blink: 250ms on / 250ms off - if(mic_mute_blink_tick > 0) - { - mic_mute_blink_tick++; - if(mic_mute_blink_tick >= MUTE_BLINK_HALF_PERIOD * 2) - mic_mute_blink_tick = 1; - if(mic_mute_blink_tick == 1) - for(int i = 0; i < 15; i++) led_on(&led_ctx, led_l_physical_map[i]); - else if(mic_mute_blink_tick == MUTE_BLINK_HALF_PERIOD + 1) - for(int i = 0; i < 15; i++) led_off(&led_ctx, led_l_physical_map[i]); - } - if(hp_mute_blink_tick > 0) - { - hp_mute_blink_tick++; - if(hp_mute_blink_tick >= MUTE_BLINK_HALF_PERIOD * 2) - hp_mute_blink_tick = 1; - if(hp_mute_blink_tick == 1) - for(int i = 0; i < 15; i++) led_on(&led_ctx, led_d_physical_map[i]); - else if(hp_mute_blink_tick == MUTE_BLINK_HALF_PERIOD + 1) - for(int i = 0; i < 15; i++) led_off(&led_ctx, led_d_physical_map[i]); - } - led_update_all(&led_ctx); -#endif + g_last_gain_mode = current_gain_mode; - GET_SHARED_GLOBAL(uac_vol, g_uac_vol); - if (uac_vol != last_uac_vol) { - unsigned conv_vol = (0xffffffff - uac_vol + 1) >> 8; - //debug_printf("vol: - %d\n", conv_vol); - //chan_out_word(c_uac_vol, conv_vol); - c_uac_vol <: conv_vol; - last_uac_vol = uac_vol; - } + // 改动原因:检测滤波器模式变化,如果变化则通过HID上报0xA3 GET_FILTER_MODE命令 + unsigned current_filter_mode; + GET_SHARED_GLOBAL(current_filter_mode, g_filter_mode); - // 处理HID SET_VOLUME (0x93) 请求:应用新音量到DAC和LED - if (g_request_volume_set) { - g_request_volume_set = 0; - unsigned new_level = g_volume_level; - if (new_level <= DAC_LEVEL_MAX) { - uint8_t new_led_count; - dac_level = new_level; - if (!dac_det_muted) { - if (dac_level == DAC_LEVEL_MIN) - unsafe { NAU88C22_REGWRITE(0x0034, 0x0000, (client interface i2c_master_if)i_i2c_client); } - else - dac_volume(dac_level); + // 如果滤波器模式发生变化,构建0xA3 GET_FILTER_MODE响应数据包并上报 + if ((g_last_filter_mode != current_filter_mode) && (g_last_filter_mode != 0xFF)) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; + + // 构建0xA3 GET_FILTER_MODE响应数据包格式(参考eq_hid_protocol.md) + // 字节位置 | 长度 | 内容 | 描述 + // 0 | 1 | 0x77 | 同步头1 + // 1 | 1 | 0xA3 | 同步头2(GET_FILTER_MODE命令) + // 2 | 1 | uint8 | 当前滤波器模式 (0-6) + // 3-62 | 60 | 0x00 | 保留字节 + reportPtr[0] = 0x77; // 同步头1 + reportPtr[1] = 0xA3; // 同步头2(GET_FILTER_MODE命令) + reportPtr[2] = (unsigned char)current_filter_mode; // 当前滤波器模式 + + // 其余字节填充为0 + for (int i = 3; i < 63; i++) + { + reportPtr[i] = 0x00; + } + + // 通知HID系统有数据变化 + hidSetChangePending(0x1); + + debug_printf("Filter mode changed: %d -> %d, HID report prepared\n", + g_last_filter_mode, current_filter_mode); } - save_value(dac_vol_path, (unsigned char)dac_level); - // 更新DAC音量指示LED - new_led_count = dac_gain_to_led[dac_level]; - for (int i = 0; i < 15; i++) { - if (i < new_led_count) - led_on(&led_ctx, led_d_physical_map[i]); - else - led_off(&led_ctx, led_d_physical_map[i]); - } - led_update_all(&led_ctx); - debug_printf("HID SET_VOLUME: dac_level=%d\n", dac_level); } - } - // 处理HID SET_MIC_VOLUME (0x82) 请求:应用新麦克风增益到硬件和LED - if (g_request_mic_volume_set) { - g_request_mic_volume_set = 0; - unsigned new_mic_level = g_mic_volume_level; - if (new_mic_level <= MIC_HID_LEVEL_MAX) { // 0=mute, 1~48=0~24dB(0.5dB/级) - uint8_t new_led_count; - if (new_mic_level == 0) { - // mute: 静音硬件,codec_adc_pga_gain_reg_value设为0(与编码器静音一致) - mic_volume(0); - codec_adc_pga_gain_reg_value = 0; - new_led_count = 0; - } else { - codec_adc_pga_gain_reg_value = new_mic_level; - if (!mic_det_muted) - mic_volume(mic_hid_level_to_codec_gain(codec_adc_pga_gain_reg_value)); - new_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value]; - } - save_value(mic_vol_path, (unsigned char)codec_adc_pga_gain_reg_value); - // 更新麦克风增益指示LED(L系列) - for (int i = 0; i < 15; i++) { - if (i < new_led_count) - led_on(&led_ctx, led_l_physical_map[i]); - else - led_off(&led_ctx, led_l_physical_map[i]); - } - led_update_all(&led_ctx); - debug_printf("HID SET_MIC_VOLUME: level=%d pga=%d\n", new_mic_level, codec_adc_pga_gain_reg_value); - } - } + g_last_filter_mode = current_filter_mode; - // 处理HID SET_MONITOR_SWITCH (0x87) 请求:设置耳返开关 - if (g_request_monitor_switch_set) { - g_request_monitor_switch_set = 0; - unsigned new_mon = g_monitor_switch; - // 同步数字监听开关到tile1 - cc_mic_level <: 0xFE; - cc_mic_level <: (unsigned)new_mon; - debug_printf("HID monitor sync: sw=%d\n", new_mon); - save_value(monitor_sw_path, (unsigned char)new_mon); - debug_printf("HID SET_MONITOR_SWITCH: %d\n", new_mon); - } - - // 处理HID SET_AI_NOISE_STRENGTH (0x85) 请求 - // 改动原因:0x85的0仅关开关与灯并停算法,g_dnr_strength由eq.c保持原档位;非0更新强度并打开 - { - unsigned dnr_req; - GET_SHARED_GLOBAL(dnr_req, g_request_dnr_strength_set); - if (dnr_req) { - SET_SHARED_GLOBAL(g_request_dnr_strength_set, 0); - unsigned new_strength; - unsigned dnr_on_sw; - GET_SHARED_GLOBAL(new_strength, g_dnr_strength); - GET_SHARED_GLOBAL(dnr_on_sw, g_dnr_on); -#if DNR_ENABLE == 1 - if (dnr_on_sw) { - dnr_set_strength_level((unsigned char)new_strength); - flag_aidenoise_onoff = 1; - dnr_strength_saved = new_strength; - led_on(&led_ctx, LED_ANC); - } else { - dnr_set_strength_level(DNR_STRENGTH_off); - flag_aidenoise_onoff = 0; - led_off(&led_ctx, LED_ANC); - } -#endif - save_value(dnr_on_path, (unsigned char)dnr_on_sw); - save_value(dnr_strength_path, (unsigned char)new_strength); - g_dnr_on = dnr_on_sw; - led_update_all(&led_ctx); - debug_printf("HID SET_AI_NOISE_STRENGTH: strength=%d on=%d flash saved\n", - new_strength, dnr_on_sw); - } - } - -#if HID_CONTROLS == 1 - // HID监听音量变化主动上报(编码器旋转或HID命令导致的音量变化) - { - unsigned current_volume_level = g_volume_level; -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif - if (g_last_volume_level != current_volume_level && g_last_volume_level != 0xFF) { - unsafe { - unsigned char * unsafe ptr = (unsigned char * unsafe)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; - ptr[2] = 0x94; - ptr[3] = (unsigned char)current_volume_level; - for (int i = 4; i < HID_MAX_DATA_BYTES; i++) - ptr[i] = 0x00; - } - hidSetChangePending(0x1); - debug_printf("Volume changed: %d -> %d, HID report sent\n", - g_last_volume_level, current_volume_level); - } - g_last_volume_level = current_volume_level; - } - - // HID麦克风增益变化主动上报 - { - unsigned current_mic_level = g_mic_volume_level; -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif - if (g_last_mic_volume_level != current_mic_level && g_last_mic_volume_level != 0xFF) { - unsafe { - unsigned char * unsafe ptr = (unsigned char * unsafe)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; - ptr[2] = 0x83; - ptr[3] = (unsigned char)current_mic_level; - for (int i = 4; i < HID_MAX_DATA_BYTES; i++) - ptr[i] = 0x00; - } - hidSetChangePending(0x1); - // debug_printf("Mic volume changed: %d -> %d, HID report sent\n", - // g_last_mic_volume_level, current_mic_level); - } - g_last_mic_volume_level = current_mic_level; - } - - // HID AI降噪强度变化主动上报(含首次开机上报:g_last_dnr_strength初始为0xFF) - // 改动原因:按键关闭AI降噪时,协议要求上报0;开启时上报当前g_dnr_strength -#if DNR_ENABLE == 1 - { - unsigned current_dnr_strength; - unsigned current_dnr_on; - GET_SHARED_GLOBAL(current_dnr_on, g_dnr_on); - GET_SHARED_GLOBAL(current_dnr_strength, g_dnr_strength); - if (!current_dnr_on) { - current_dnr_strength = 0; - } -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif - if (g_last_dnr_strength != current_dnr_strength) { - unsafe { - unsigned char * unsafe ptr = (unsigned char * unsafe)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; - ptr[2] = 0x86; - ptr[3] = (unsigned char)current_dnr_strength; - for (int i = 4; i < HID_MAX_DATA_BYTES; i++) - ptr[i] = 0x00; - } - hidSetChangePending(0x1); - debug_printf("DNR strength changed: %d -> %d, HID report sent\n", - g_last_dnr_strength, current_dnr_strength); - } - g_last_dnr_strength = current_dnr_strength; - } -#endif - - // HID音效模式变化主动上报(按键切换或0xA4命令导致的模式变化,含首次开机上报) - { + // 改动原因:检测游戏模式变化,如果变化则通过HID上报0xA5 GET_GAME_MODE命令 unsigned current_game_mode; - GET_SHARED_GLOBAL(current_game_mode, g_game_mode); -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif - if (g_last_game_mode != current_game_mode) { - unsafe { - unsigned char * unsafe ptr = (unsigned char * unsafe)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; - ptr[2] = 0xA5; - ptr[3] = (unsigned char)current_game_mode; - for (int i = 4; i < HID_MAX_DATA_BYTES; i++) - ptr[i] = 0x00; + GET_SHARED_GLOBAL(current_game_mode, g_3d_fps); + + // 如果游戏模式发生变化,构建0xA5 GET_GAME_MODE响应数据包并上报 + if ((g_last_game_mode != current_game_mode) && (g_last_game_mode != 0xFF)) + { + unsafe + { + unsigned char * unsafe reportPtr = g_hid_pass_data; + + // 构建0xA5 GET_GAME_MODE响应数据包格式(参考eq_hid_protocol.md) + // 字节位置 | 长度 | 内容 | 描述 + // 0 | 1 | 0x77 | 同步头1 + // 1 | 1 | 0xA5 | 同步头2(GET_GAME_MODE命令) + // 2 | 1 | uint8 | 当前游戏模式 (0=无音效, 1=FPS, 2=虚拟7.1) + // 3-62 | 60 | 0x00 | 保留字节 + reportPtr[0] = 0x77; // 同步头1 + reportPtr[1] = 0xA5; // 同步头2(GET_GAME_MODE命令) + reportPtr[2] = (unsigned char)current_game_mode; // 当前游戏模式 + + // 其余字节填充为0 + for (int i = 3; i < 63; i++) + { + reportPtr[i] = 0x00; + } + + // 通知HID系统有数据变化 + hidSetChangePending(0x1); + + debug_printf("Game mode changed: %d -> %d, HID report prepared\n", + g_last_game_mode, current_game_mode); } - hidSetChangePending(0x1); - debug_printf("Game mode changed: %d -> %d, HID report sent\n", - g_last_game_mode, current_game_mode); } + g_last_game_mode = current_game_mode; - } -#if USE_EX3D == 1 - // HID脚步增强状态变化主动上报(按键切换或HID 0xB0命令导致的变化,含首次开机上报) - { -#if HID_DFU_EN - if (!g_in_fw_upgrade) -#endif - if (last_footstep_expand != saved_footstep ) { - unsafe { - unsigned char * unsafe ptr = (unsigned char * unsafe)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; - ptr[2] = 0xB1; - // EX3D GET CMD_EXPAND_GAIN = 0x193 (little-endian) - ptr[3] = 0x93; ptr[4] = 0x01; ptr[5] = 0x00; ptr[6] = 0x00; - // 返回值: expand_gain (uint32, little-endian) - ptr[7] = (unsigned char)saved_footstep; - ptr[8] = 0x00; ptr[9] = 0x00; ptr[10] = 0x00; - for (int i = 11; i < HID_MAX_DATA_BYTES; i++) ptr[i] = 0x00; - } - hidSetChangePending(0x1); - debug_printf("Footstep expand_gain changed: %d -> %d, HID 0xB1 report sent\n", - last_footstep_expand, saved_footstep); - } - last_footstep_expand = saved_footstep; - } -#endif -#endif - -#if EQ_EN - - { - unsigned request_eq_mode, new_eq_mode; - unsigned force_request_mode_change; - GET_SHARED_GLOBAL(request_eq_mode, g_request_eq_mode); - GET_SHARED_GLOBAL(new_eq_mode, g_new_eq_mode); - GET_SHARED_GLOBAL(force_request_mode_change, g_force_request_eq_mode_change); - if (new_eq_mode != request_eq_mode) - { - // debug_printf("new eq mode != request eq mode\n"); - SET_SHARED_GLOBAL(g_new_eq_mode, request_eq_mode); - } - - if (force_request_mode_change == 1) - { - debug_printf("force request mode change\n"); - SET_SHARED_GLOBAL(g_force_eq_mode_change, 1); - SET_SHARED_GLOBAL(g_force_request_eq_mode_change, 0); - } - } - - - eq_sync_counter++; - if (eq_sync_counter >= 5) { // 5 * 100ms = 500ms - eq_sync_counter = 0; - - // 使用单参数存储系统保存脏参数(独立保存EQ参数) - if (eq_save_dirty_params() == 0) { - //debug_printf("Single EQ parameters synced to Flash successfully\n"); - } else { - //debug_printf("Failed to sync single EQ parameters to Flash\n"); - } - - // 独立保存脏的增益 - if (eq_save_dirty_gain() == 0) { - // debug_printf("Gain synced to Flash successfully\n"); - } else { - //debug_printf("Failed to sync gain to Flash\n"); - } - - // 独立保存脏的模式名称 - if (eq_save_dirty_names() == 0) { - // debug_printf("Mode names synced to Flash successfully\n"); - } else { - //debug_printf("Failed to sync mode names to Flash\n"); - } } #endif -#if UAC1_MODE == 1 - GET_SHARED_GLOBAL(host_os, g_host_os); - if (host_os == OS_WIN) { - unsigned flag = (saved_mode <= 1) ? MODE_F1_MUSIC_UAC2 : MODE_F3_F4_FPS_UAC2; - SetRoleSwitchFlag(flag); -#ifndef DISABLE_REBOOT - device_reboot(); - while (1); -#endif - } -#endif break; - } + case se_tmr when timerafter(se_time) :> void : + se_time += SE_DELAY; + se_count ++; + if ((se_count % 90) == 0) + { + + unsigned key = GetKeyFlag(); + if (key != 0x20241224) + { + debug_printf("se reboot\n"); + device_reboot(); + while(1); + } + else + debug_printf("no se reboot\n"); + } + break; +#if HID_DFU_EN + case c_dfu :> unsigned first_word: + { + unsigned dfu_words[16]; + dfu_words[0] = first_word; + for (int i = 1; i < 16; i++) + c_dfu :> dfu_words[i]; + unsigned char cmd_buf[63]; + for (int i = 0; i < 63; i++) + cmd_buf[i] = (dfu_words[i / 4] >> ((i % 4) * 8)) & 0xFF; + if (cmd_buf[1] == FIRMWARE_UPGRADE_START) + handle_firmware_upgrade_start(cmd_buf, 63); + } + break; +#endif +#if EQ_EN + case eq_mode_timer when timerafter(eq_mode_time) :> void : + eq_mode_time += EQ_MODE_DELAY; + unsigned request_eq_mode, new_eq_mode; + unsigned force_request_mode_change; + GET_SHARED_GLOBAL(request_eq_mode, g_request_eq_mode); + GET_SHARED_GLOBAL(new_eq_mode, g_new_eq_mode); + GET_SHARED_GLOBAL(force_request_mode_change, g_force_request_eq_mode_change); + if (new_eq_mode != request_eq_mode) + { + SET_SHARED_GLOBAL(g_new_eq_mode, request_eq_mode); + } + + if (force_request_mode_change == 1) + { + debug_printf("force request mode change\n"); + SET_SHARED_GLOBAL(g_force_eq_mode_change, 1); + SET_SHARED_GLOBAL(g_force_request_eq_mode_change, 0); + } + break; + + case eq_sync_timer when timerafter(eq_sync_time) :> void : + eq_sync_time += EQ_SYNC_DELAY; + + // 使用单参数存储系统保存脏参数(独立保存EQ参数) + if (eq_save_dirty_params() == 0) { + // debug_printf("Single EQ parameters synced to Flash successfully\n"); + } else { + //debug_printf("Failed to sync single EQ parameters to Flash\n"); + } + + // 独立保存脏的增益 + if (eq_save_dirty_gain() == 0) { + // debug_printf("Gain synced to Flash successfully\n"); + } else { + //debug_printf("Failed to sync gain to Flash\n"); + } + + // 独立保存脏的模式名称 + if (eq_save_dirty_names() == 0) { + // debug_printf("Mode names synced to Flash successfully\n"); + } else { + //debug_printf("Failed to sync mode names to Flash\n"); + } + break; +#endif } + } } -void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx +extern void SetKeyFlag(unsigned x); + + + +/* 改动原因:与 AudioHwRemote2 一致——HID_DFU_EN=0 时不声明 c_dfu,避免 main 必须挂接无发送端的 streaming chan。 */ #if HID_DFU_EN - , streaming chanend c_dfu_rx -#endif - , chanend c_mic_det - ) +void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu) { - i2c_master_if i2c[1]; - board_setup(); - par { - i2c_master(i2c, 1, p_scl, p_sda, 300); - { - unsafe {i_i2c_client = i2c[0];} - button_task(c_hidSendData, cc_mic_level, c_uac_vol, c_audiohw_rx -#if HID_DFU_EN - , c_dfu_rx -#endif - , c_mic_det - ); - } - } + i2c_master_if i2c[1]; + + par + { + i2c_master(i2c, 1, p_scl, p_sda, 100); + AudioHwRemote2(c, i2c[0], i_c1_led_ctrl, c_dfu); + } } +#else +void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl) +{ + i2c_master_if i2c[1]; + par + { + i2c_master(i2c, 1, p_scl, p_sda, 100); + AudioHwRemote2(c, i2c[0], i_c1_led_ctrl); + } +} +#endif -/* Configures the external audio hardware at startup */ +/* Note this is called from tile[0] but the I2C lines to the CODEC are on tile[0] + * use a channel to communicate CODEC reg read/writes to a remote core */ void AudioHwInit() { - // p_ctl_mute <: 0; - int result=0; + debug_printf("AudioHwInit\n"); + /* 改动原因:等待 main 中 tile[0] 完成对 uc_audiohw 的绑定;与 usb_audio_io 无固定启动顺序,仅靠“先 unsafe 再 par”不足。 */ + { + unsigned spin = 0; + while (g_uc_audiohw_chan_bound == 0 && spin < 20000) { + delay_microseconds(50); + spin++; + } + } + delay_milliseconds(100); - sw_pll_fixed_clock(MCLK_48); + if((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL) + { + /* Do nothing - SW_PLL configures AppPLL */ + } + else + { + if (DEFAULT_FREQ % 22050 == 0) + { + sw_pll_fixed_clock(MCLK_441); + } + else + { + sw_pll_fixed_clock(MCLK_48); + } + } + set_gpio(P_GPIO_MUTE, MUTE); + debug_printf("mute_dac ======== \n"); + delay_milliseconds(10); - // Wait for power supply to come up. - delay_milliseconds(200); + codec_init(); + + debug_printf("AudioHwInit completed\n"); + + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x0003, 0x0053); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002B, 0x4002); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002C, 0x0082); } -/* Configures the external audio hardware for the required sample frequency */ -void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) +void unmute_dac(void) { -#if UAC1_MODE == 1 - static unsigned count = 1; -#else - static unsigned count = 0; -#endif - // p_ctl_mute <: 0; - g_samfreq = samFreq; - delay_milliseconds(2); - { - sw_pll_fixed_clock(mClk); - } - // 通知tile0 (button_task) 采样率已变化,用于配置NAU88C22寄存器 - unsafe {uc_audiohw <: samFreq; } - unsafe {uc_audiohw <: dsdMode; } + unsigned samFreq; + GET_SHARED_GLOBAL(samFreq, g_samfreq); + set_gpio(P_GPIO_MUTE, UNMUTE); + debug_printf("unmute_dac ======== \n"); +} +void unmute_spdif_led(void) +{ + unsigned led_mode; + GET_SHARED_GLOBAL(led_mode, g_led_mode); + if (led_mode == 1) + { + SET_SHARED_GLOBAL(g_update_led, 1); + } +} + +void mute_dac(void) +{ + unsigned samFreq; + GET_SHARED_GLOBAL(samFreq, g_samfreq); +#if UAC1 + unsigned adc_loop; + GET_SHARED_GLOBAL(adc_loop, g_adc_loop); + + set_gpio(P_GPIO_MUTE, MUTE); + debug_printf("mute_dac %d======== \n", samFreq); +#if 0 + if (adc_loop == 0) + { + set_gpio(P_GPIO_MUTE, MUTE); + debug_printf("mute_dac %d======== \n", samFreq); + } + else + { + set_gpio(P_GPIO_MUTE, UNMUTE); + debug_printf("mute_dac %d======== \n", samFreq); + } +#endif +#else + set_gpio(P_GPIO_MUTE, MUTE); + debug_printf("mute_dac %d======== \n", samFreq); +#endif +} + + +void update_play_rate(unsigned samFreq, unsigned audiotype, unsigned sample_code) +{ + unsigned time = get_reference_time(); + audio_sampling format; + + if (samFreq > 0) + { + switch (samFreq) + { + case 32000: + format = AUDIO_PCM_32000; + break; + case 64000: + format = AUDIO_PCM_64000; + break; + case 128000: + format = AUDIO_PCM_128000; + break; + case 256000: + format = AUDIO_PCM_256000; + break; + case 512000: + format = AUDIO_PCM_512000; + break; + case 44100: + format = AUDIO_PCM_44100; + break; + case 48000: + format = AUDIO_PCM_48000; + break; + case 88200: + format = AUDIO_PCM_88200; + break; + case 96000: + format = AUDIO_PCM_96000; + break; + case 176400: + format = AUDIO_PCM_176400; + break; + case 192000: + format = AUDIO_PCM_192000; + break; + case 352800: + format = AUDIO_PCM_352800; + break; + case 384000: + format = AUDIO_PCM_384000; + break; + case 705600: + format = AUDIO_PCM_705600; + break; + case 768000: + format = AUDIO_PCM_768000; + break; + case 1411200: + format = AUDIO_PCM_1441200; + break; + case 1536000: + format = AUDIO_PCM_1536000; + break; + case 2822400: + format = AUDIO_DSD_64; + break; + case 5644800: + format = AUDIO_DSD_128; + break; + case 11289600: + format = AUDIO_DSD_256; + break; + case 22579200: + format = AUDIO_DSD_512; + break; + default: + format = AUDIO_PCM_44100; + break; + } + + } + else + { + if (audiotype == 0) + { + if (sample_code < 8) + format = sample_code * 2; + else if (sample_code > 15) + format = sample_code - 5; + else if (sample_code < 15) + format = (sample_code - 8) * 2 + 1; + } +#if MQA_EN + if ((audiotype >= 2) && (audiotype <= 4)) + { + switch (sample_code) + { + case MQAFS44100 : + format = AUDIO_PCM_44100; + break; + case MQAFS88200 : + format = AUDIO_PCM_88200; + break; + case MQAFS176400 : + format = AUDIO_PCM_176400; + break; + case MQAFS352800 : + format = AUDIO_PCM_352800; + break; + case MQAFS705600 : + format = AUDIO_PCM_705600; + break; + case MQAFS1411200: + format = AUDIO_PCM_1441200; + break; + case MQAFS1536000: + format = AUDIO_PCM_1536000; + break; + case MQAFS48000 : + format = AUDIO_PCM_48000; + break; + case MQAFS96000 : + format = AUDIO_PCM_96000; + break; + case MQAFS192000 : + format = AUDIO_PCM_192000; + break; + case MQAFS384000 : + format = AUDIO_PCM_384000; + break; + case MQAFS768000 : + format = AUDIO_PCM_768000; + break; + + case MQAFS64000 : + format = AUDIO_PCM_64000; + break; + case MQAFS128000 : + format = AUDIO_PCM_128000; + break; + case MQAFS256000 : + format = AUDIO_PCM_256000; + break; + case MQAFS512000 : + format = AUDIO_PCM_512000; + break; + default: + format = AUDIO_PCM_44100; + break; + } + + } +#endif + if (audiotype == 1 || audiotype == 5) + { + format = sample_code + AUDIO_DSD_64; + } + } + +// if (sample_code != 0) +// debug_printf("samFreq %d, audiotype %d code %d format %d\n", samFreq, audiotype, sample_code, format); + + SET_SHARED_GLOBAL(g_new_playback_format, format); + SET_SHARED_GLOBAL(g_new_audio_type, audiotype); + //debug_printf("audiotype %d code %d \n", audiotype, sample_code); + SET_SHARED_GLOBAL(g_format_time, time); +} + +/* Configures the external audio hardware for the required sample frequency. + * See gpio.h for I2C helper functions and gpio access + */ +void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, + unsigned sampRes_DAC, unsigned sampRes_ADC) +{ + debug_printf(" samFreq %d, mClk %d dsdMode %d\n", samFreq, mClk, dsdMode); + + static unsigned current_sample_rate = DEFAULT_FREQ; + static unsigned led_count = 0; + SET_SHARED_GLOBAL(g_samfreq, samFreq); + SET_SHARED_GLOBAL(g_dsd_mode, dsdMode); + + set_gpio(P_GPIO_MUTE, MUTE); + debug_printf("mute_dac %d======== \n", samFreq); + delay_milliseconds(1); + + if((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL) + { + /* Do nothing - the SW_PLL configures the AppPLL */ + } + else + { + if (samFreq % 22050 == 0) + { + sw_pll_fixed_clock(MCLK_441); + } + else + { + sw_pll_fixed_clock(MCLK_48); + } + } + + switch (samFreq) + { + case 192000: + case 176400: + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x0003, 0x00D0); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002B, 0x4000); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002C, 0x0082); + break; + case 96000: + case 88200: + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x0003, 0x0092); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002B, 0x4001); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002C, 0x0082); + break; + case 44100: + case 48000: + default: + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x0003, 0x0053); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002B, 0x4002); + CODEC_REGWRITE(NAU88_I2C_DEVICE_ADDR, 0x002C, 0x0082); + break; + } + + if (led_count == 0) + { + led_count = 1; + } + else if (led_count == 1) + { + led_count = 2; + // SET_SHARED_GLOBAL(g_update_led, 1); + } +} + +void AudioHwConfig_UnMute(void) +{ + static unsigned count = 1; if (count++ > 0) { - // p_ctl_mute <: 1; + unsigned long time = get_reference_time(); + debug_printf(" AudioHwConfig_UnMute %d\n", time); + SET_SHARED_GLOBAL(g_unmute_dac_state, 1); + SET_SHARED_GLOBAL(g_unmute_time, time); } else { debug_printf("don't unmute at boot\n"); } - - unsafe {uc_audiohw :> dsdMode; } } - -void mute_handler(chanend c_mic_det) +// 改动原因:tile1 上电瞬间尚未收到 tile0 的 mode/mic,先把 mode 红脚与 PORT_4D 各 bit 拉到熄灭电平(低有效灯:输出 1 为灭),与 apply 中无混色时 mode 红通道熄灭写法一致。 +static inline void c1_panel_leds_force_all_off_hw(void) { - // 开机mute sequence - p_ctl_mute <: 0; -#if UAC1_MODE == 1 - delay_milliseconds(3000); -#else - delay_milliseconds(1000); -#endif - p_ctl_mute <: 0xf; + p_mode_led_red <: 1; + p_leds <: 0xF; + p_mic_mute_led_blue <: 1; +} - // mic detect: bit1=mic1 (插入=高, 拔出=低), bit2=mic2 (插入=低, 拔出=高) - c_mic_det <: (unsigned)MIC_DET_MUTE; - unsigned det_val; - p_ctl_det :> det_val; - unsigned mic1_in = (det_val >> 1) & 1; // bit1: 1=inserted - unsigned mic2_in = ((det_val >> 2) & 1) ^ 1; // bit2: 0=inserted, invert - unsigned phone_in = ((det_val >> 3) & 1) ^ 1; // bit3: 0=inserted, invert - unsigned any_mic_in = mic1_in || mic2_in; - unsigned prev_mic1_in = mic1_in; - unsigned prev_mic2_in = mic2_in; - unsigned prev_any_mic_in = any_mic_in; - unsigned prev_phone_in = phone_in; - - // 如果开机时全拔出,发送mute - - if (((det_val & 0b1110) == 0b1110) || ((det_val & 0b1110) == 0b1010) || ((det_val & 0b1110) == 0b0010) || ((det_val & 0b1110) == 0b1000)) { - // 有mic插入,恢复mic音量状态 - c_mic_det <: (unsigned)MIC_DET_UNMUTE; - debug_printf("mic stable -> unmute\n"); +// 改动原因:c1_mode 与灯索引一致:1=灭 2=蓝 3=绿 4=橙(R+G) 5=紫(R+B);仅驱动 mode 区(p_mode_led_red + p_leds bit0/1),不受 mic 变声影响。 +// mic_voice_fx_on:规格变声/美声橙灯在 mic 区——p_leds bit2 红 + bit3 绿同时点亮;关变声时 mic 区仅由静音决定 bit2,bit3 熄灭。 +static inline void apply_c1_panel_leds(unsigned mode_led_color_idx, unsigned mic_mute_switch, unsigned mic_voice_fx_on, unsigned &led_shadow) +{ + unsigned mode_red = 0; + unsigned mode_green = 0; + unsigned mode_blue = 0; + // 改动原因:与 user_main.h 约定一致——mic_mute_switch 存的是“非静音=1、静音=0”,静音时 mic 红灯(bit2)亮。 + unsigned mic_red = 0; + unsigned mic_green = 0; + if (mic_voice_fx_on) { + // 改动原因:变声开为橙=R+G,映射到 XS1_PORT_4D 的 mic 专用 bit2/bit3,不占用 mode 的 bit0/bit1。 + mic_red = 1; + mic_green = 1; + } else { + mic_red = (mic_mute_switch == 0) ? 1 : 0; + mic_green = 0; } - timer tmr; - unsigned time; - tmr :> time; - #define MIC_DET_POLL_MS 10 - time += MIC_DET_POLL_MS * 100000; // 10ms in 100MHz ticks + if (mode_led_color_idx == 1) { + mode_red = 0; + mode_green = 0; + mode_blue = 0; + } else if (mode_led_color_idx == 2) { + mode_blue = 1; + } else if (mode_led_color_idx == 3) { + mode_green = 1; + } else if (mode_led_color_idx == 4) { + mode_red = 1; + mode_green = 1; + } else if (mode_led_color_idx == 5) { + mode_red = 1; + mode_blue = 1; + } else { + mode_red = 0; + mode_green = 0; + mode_blue = 0; + } - while (1) { - select { - case tmr when timerafter(time) :> void: - { - time += MIC_DET_POLL_MS * 100000; + // 改动原因:硬件LED为低电平点亮(1灭/0亮);低四位 bit0~3 分别为 mode绿、mode蓝、mic红、mic绿,统一刷新避免旧代码固定 |=0x8 导致 bit3 永灭。 + p_mode_led_red <: (mode_red ? 0 : 1); + led_shadow &= ~0xF; + led_shadow |= (mode_green ? 0x0 : 0x1); + led_shadow |= (mode_blue ? 0x0 : 0x2); + led_shadow |= (mic_red ? 0x0 : 0x4); + led_shadow |= (mic_green ? 0x0 : 0x8); + p_leds <: led_shadow; + // 改动原因:该蓝灯当前不参与功能,保持熄灭(低电平有效下输出1表示灭)。 + p_mic_mute_led_blue <: 1; +} - p_ctl_det :> det_val; - mic1_in = (det_val >> 1) & 1; - mic2_in = ((det_val >> 2) & 1) ^ 1; - phone_in = ((det_val >> 3) & 1) ^ 1; - any_mic_in = mic1_in || mic2_in; +void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl) +{ + // 改动原因:tile1 先于 tile0 运行,上电先把硬件灯全灭且不调用 apply,避免用占位 mic/mode 组合误亮;shadow 置为全灭电平便于首包 set_* 时 apply 与端口一致。 + unsigned led_shadow = 0xF; + unsigned mode_led_color_idx = 1; + unsigned mic_mute_switch = 1; + // 改动原因:变声/美声开时仅 p_leds bit2/bit3 显橙,与 set_mode_led_color 下发的 mode 灯独立;此处状态与 tile0 set_mic_voice_fx 同步。 + unsigned mic_voice_fx_on = 0; + c1_panel_leds_force_all_off_hw(); - // 检测单个mic插拔事件 - unsigned mic1_changed = (mic1_in != prev_mic1_in); - unsigned mic2_changed = (mic2_in != prev_mic2_in); - unsigned any_changed = mic1_changed || mic2_changed; - unsigned phone_changed = (phone_in != prev_phone_in); + unsigned eq_mode_time = 0; + timer eq_mode_timer; + eq_mode_timer :> eq_mode_time; + eq_mode_time += EQ_MODE_DELAY; - if (any_changed || phone_changed) { - // 状态变化:立即mute mic和DAC防止pop音 - p_ctl_mute <: 0; - c_mic_det <: (unsigned)MIC_DET_MUTE; - // c_mic_det <: (unsigned)MIC_DET_DAC_MUTE; - // 配置ADC - //c_mic_det <: (unsigned)MIC_DET_REINIT_CODEC; - p_ctl_det <: 0; - delay_milliseconds(100); - //debug_printf("mic det change: mic1=%d mic2=%d -> mute all & reconfig\n", mic1_in, mic2_in); - p_ctl_det :> det_val; + delay_milliseconds(100); - // 等1s让插拔稳定 - delay_milliseconds(900); - p_ctl_mute <: 0xf; - // 重新读取稳定状态 - p_ctl_det :> det_val; - mic1_in = (det_val >> 1) & 1; - mic2_in = ((det_val >> 2) & 1) ^ 1; - phone_in = ((det_val >> 3) & 1) ^ 1; - any_mic_in = mic1_in || mic2_in; - - // 恢复DAC状态 - c_mic_det <: (unsigned)MIC_DET_DAC_UNMUTE; - -#if 0 - if ((any_mic_in && !phone_in) || (phone_in && mic2_in)) { - // 有mic插入,恢复mic音量状态 - c_mic_det <: (unsigned)MIC_DET_UNMUTE; - debug_printf("mic stable -> unmute\n"); - } - // 全拔出则保持mic mute - - delay_milliseconds(200); - -#endif - - if (((det_val & 0b1110) == 0b1110) || ((det_val & 0b1110) == 0b1010) || ((det_val & 0b1110) == 0b0010) || ((det_val & 0b1110) == 0b1000)) { - // 有mic插入,恢复mic音量状态 - c_mic_det <: (unsigned)MIC_DET_UNMUTE; - debug_printf("mic stable -> unmute\n"); - } - // 全拔出则保持mic mute - - prev_mic1_in = mic1_in; - prev_mic2_in = mic2_in; - prev_any_mic_in = any_mic_in; - prev_phone_in = phone_in; - // 重新同步timer - tmr :> time; - time += MIC_DET_POLL_MS * 100000; - } - break; + while(1) + { + unsafe { + select{ + case i_c1_led_ctrl.set_mode_led_color(unsigned color_idx): + // 改动原因:color_idx 与 c1_mode 同值 1~5;越界时钳位为默认灯码,避免未定义索引。 + mode_led_color_idx = color_idx; + if (mode_led_color_idx > 5 || mode_led_color_idx < 1) + mode_led_color_idx = C1_MODE_VALUE_DEFAULT; + apply_c1_panel_leds(mode_led_color_idx, mic_mute_switch, mic_voice_fx_on, led_shadow); + break; + case i_c1_led_ctrl.set_mic_mute_state(unsigned mute_state): + mic_mute_switch = (mute_state != 0) ? 1 : 0; + apply_c1_panel_leds(mode_led_color_idx, mic_mute_switch, mic_voice_fx_on, led_shadow); + break; + case i_c1_led_ctrl.set_mic_voice_fx(unsigned voice_fx_enabled): + mic_voice_fx_on = (voice_fx_enabled != 0) ? 1 : 0; + apply_c1_panel_leds(mode_led_color_idx, mic_mute_switch, mic_voice_fx_on, led_shadow); + break; } } } diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiostream.xc b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiostream.xc index a8bae3d..eb09535 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiostream.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/audiostream.xc @@ -1,16 +1,27 @@ +#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED +#define DEBUG_PRINT_ENABLE 1 +#endif #include +#include "gpio_access.h" +#include "xc_ptr.h" +#include "debug_print.h" -//on tile[0]: out port p_leds = XS1_PORT_4F; - +extern unsigned g_mute_enable, g_unmute_time; +extern unsigned g_unmute_dac_state; +unsigned long get_reference_time(); void UserAudioStreamStart(void) { - /* Turn all LEDs on */ -// p_leds <: 0xF; + unsigned long time = get_reference_time(); + SET_SHARED_GLOBAL(g_unmute_dac_state, 1); + SET_SHARED_GLOBAL(g_unmute_time, time); + debug_printf("UserAudioStreamStart\n"); } void UserAudioStreamStop(void) { - /* Turn all LEDs off */ -// p_leds <: 0x0; + unsigned enable_mute; + debug_printf("UserAudioStreamStop\n"); + //SET_SHARED_GLOBAL(g_unmute_dac_state, 0); + //set_gpio(P_GPIO_MUTE, MUTE); + delay_milliseconds(10); } - diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/codec_ti3204.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/codec_ti3204.h deleted file mode 100644 index 3f4781f..0000000 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/codec_ti3204.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2020-2023 XMOS LIMITED. -// This Software is subject to the terms of the XMOS Public Licence: Version 1. - -#ifndef AIC3204_H_ -#define AIC3204_H_ - -// TLV320AIC3204 Device I2C Address -#define AIC3204_I2C_DEVICE_ADDR 0x18 - -#define CODEC_I2C_DEVICE_ADDR AIC3204_I2C_DEVICE_ADDR - -// TLV320AIC3204 Register Addresses -// Page 0 -#define AIC3204_PAGE_CTRL 0x00 // Register 0 - Page Control -#define AIC3204_SW_RST 0x01 // Register 1 - Software Reset -#define AIC3204_NDAC 0x0B // Register 11 - NDAC Divider Value -#define AIC3204_MDAC 0x0C // Register 12 - MDAC Divider Value -#define AIC3204_DOSR_MSB 0x0d // Register 14 - DOSR Divider Value (MS Byte) -#define AIC3204_DOSR_LSB 0x0e // Register 14 - DOSR Divider Value (LS Byte) -#define AIC3204_NADC 0x12 // Register 18 - NADC Divider Value -#define AIC3204_MADC 0x13 // Register 19 - MADC Divider Value -#define AIC3204_AOSR 0x14 // Register 20 - AOSR Divider Value -#define AIC3204_CLK_MUL 0x19 // Register 25 -#define AIC3204_CLK_DIV 0x1A // Register 26 -#define AIC3204_CODEC_IF 0x1B // Register 27 - CODEC Interface Control -#define AIC3204_D_OFFSET 0x1C // Register 28 - -#define AIC3204_LOOPBACK 0x1D // Register 29 - -#define AIC3204_BCLK_DIV 0x1E // Register 30 - -------- -#define AIC3204_CLK_MUL 0x1F // Register 31 - -#define AIC3204_BCLK_SEL 0x20 // Register 32 - 0:Primary; 1:Second -#define AIC3204_DAC_SIG_PROC 0x3C // Register 60 - DAC Sig Processing Block Control -#define AIC3204_ADC_SIG_PROC 0x3D // Register 61 - ADC Sig Processing Block Control -#define AIC3204_DAC_CH_SET1 0x3F // Register 63 - DAC Channel Setup 1 -#define AIC3204_DAC_CH_SET2 0x40 // Register 64 - DAC Channel Setup 2 -#define AIC3204_DACL_VOL_D 0x41 // Register 65 - DAC Left Digital Vol Control -#define AIC3204_DACR_VOL_D 0x42 // Register 66 - DAC Right Digital Vol Control -#define AIC3204_HEADSET_DET 0x43 // Register 67 - Headset Detection configuration -#define AIC3204_DRC_CON1 0x44 // Register 68 - DRC control reg1 -#define AIC3204_DRC_CON2 0x45 // Register 69 - DRC control reg2 -#define AIC3204_DRC_CON3 0x46 // Register 70 - DRC control reg3 -#define AIC3204_ADC_CH_SET 0x51 // Register 81 - ADC Channel Setup -#define AIC3204_ADC_FGA_MUTE 0x52 // Register 82 - ADC Fine Gain Adjust/Mute -#define AIC3204_ADC_CH1_SET 0x53 // Register 83 - ADC L_CH vol -#define AIC3204_ADC_CH2_SET 0x54 // Register 84 - ADC R_CH vol -#define AIC3204_ADC_PHA_SET 0x55 // Register 84 - ADC Phase Adjust Reg -//0x56~0x5c: L-CH agc control regs -//0x5e~0x65: R-CH agc control regs -///0x66~0x67: DC measurement regs -//0x68~0x6d: DC Measurement output regs - -// Page 1 -#define AIC3204_PAGE_SEL1 0x00 // Register 0 - Page Select Reg -#define AIC3204_PWR_CFG 0x01 // Register 1 - Power Config -#define AIC3204_LDO_CTRL 0x02 // Register 2 - LDO Control -#define AIC3204_PLAY_CFG1 0x03 // Register 3 - Playback Config 1 -#define AIC3204_PLAY_CFG2 0x04 // Register 4 - Playback Config 2 -#define AIC3204_OP_PWR_CTRL 0x09 // Register 9 - Output Driver Power Control -#define AIC3204_CM_CTRL 0x0A // Register 10 - Common Mode Control -#define AIC3204_HPL_ROUTE 0x0C // Register 12 - HPL Routing Select -#define AIC3204_HPR_ROUTE 0x0D // Register 13 - HPR Routing Select -#define AIC3204_HPL_GAIN 0x10 // Register 16 - HPL Driver Gain -#define AIC3204_HPR_GAIN 0x11 // Register 17 - HPR Driver Gain -#define AIC3204_HP_START 0x14 // Register 20 - Headphone Driver Startup -#define AIC3204_LPGA_P_ROUTE 0x34 // Register 52 - Left PGA Positive Input Route -#define AIC3204_LPGA_N_ROUTE 0x36 // Register 54 - Left PGA Negative Input Route -#define AIC3204_RPGA_P_ROUTE 0x37 // Register 55 - Right PGA Positive Input Route -#define AIC3204_RPGA_N_ROUTE 0x39 // Register 57 - Right PGA Negative Input Route -#define AIC3204_LPGA_VOL 0x3B // Register 59 - Left PGA Volume -#define AIC3204_RPGA_VOL 0x3C // Register 60 - Right PGA Volume -#define AIC3204_ADC_PTM 0x3D // Register 61 - ADC Power Tune Config -#define AIC3204_ADC_VOL 0x3E // Register 62 - ADC Analog Gain Control Flag -#define AIC3204_AN_IN_CHRG 0x47 // Register 71 - Analog Input Quick Charging Config -#define AIC3204_REF_STARTUP 0x7B // Register 123 - Reference Power Up Config - -int aic3204_init(void); - -#endif /* AIC3204_H_ */ \ No newline at end of file diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dfu_upgrade.c b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dfu_upgrade.c index 9c8cfb4..c239f4d 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dfu_upgrade.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dfu_upgrade.c @@ -18,11 +18,11 @@ extern swlock_t flash_lock; extern void hidSetChangePending(unsigned int id); extern unsigned char check_sum(unsigned char *pbuf, unsigned len); extern void device_reboot(void); -extern unsigned hidSendData[]; -// 固件升级通知MCU的标志(phaten无UART MCU,保留为静态变量供内部使用) -static unsigned g_firmware_upgrade_mcu_notify = 0; -unsigned g_in_fw_upgrade = 0; // 升级进行中标志,供其他模块检查以阻止非升级HID上报 +// 全局变量 +extern unsigned char g_hid_pass_data[64]; // HID主动上报数据缓冲区 +extern unsigned g_firmware_upgrade_mcu_notify; // 固件升级状态通知 MCU:1=开始 2=结束成功 3=结束(中止/失败) +extern unsigned g_in_fw_upgrade; // 是否处于固件升级中,START=1 END/ABORT=0 // 升级状态(静态全局变量) static upgrade_status_t g_upgrade_status; @@ -59,24 +59,42 @@ void firmware_upgrade_reset(void) } // 发送固件升级响应(主动上报) -// 填充hidSendData,通过UserHIDGetData上报给host +// 改动原因:通过HID主动上报机制发送响应,参考audiohw.xc中的音量上报实现 +// 使用g_hid_pass_data全局数组存储响应数据,然后调用hidSetChangePending触发主动上报 void send_firmware_upgrade_response(uint8_t cmd, uint8_t *response_data, uint16_t data_len) { - unsigned char *ptr = (unsigned char *)hidSendData; - ptr[0] = 1; - ptr[1] = 0x77; // 同步头 - ptr[2] = cmd; // 命令码 - + // 构建响应数据包 + g_hid_pass_data[0] = 0x77; // 同步头 + g_hid_pass_data[1] = cmd; // 命令码 + + // 复制响应数据 if (response_data != NULL && data_len > 0) { uint16_t copy_len = (data_len < 61) ? data_len : 61; - memcpy(&ptr[3], response_data, copy_len); + memcpy(&g_hid_pass_data[2], response_data, copy_len); } - - for (int i = 3 + (int)data_len; i < 64; i++) { - ptr[i] = 0x00; + + // 其余字节填充为0 + for (int i = 2 + data_len; i < 63; i++) { + g_hid_pass_data[i] = 0x00; } - + + // 改动原因:先触发主动上报,再打印调试信息,确保响应及时发送 + // 通知HID系统有数据变化,触发主动上报(优先执行,减少延迟) hidSetChangePending(0x1); + + // 改动原因:添加调试打印,显示上报的响应数据(16进制格式) + // 注意:g_hid_pass_data是63字节(不包括Report ID),但HID实际发送的是64字节(包括Report ID 0x01) + // 为了完整显示,我们需要构建完整的64字节数据包 + // 注意:打印操作移到hidSetChangePending之后,避免打印延迟影响响应发送 + uint8_t full_packet[64]; + full_packet[0] = 0x01; // Report ID + memcpy(&full_packet[1], g_hid_pass_data, 63); // 复制63字节数据 + + char prefix[64]; + //debug_printf(prefix, sizeof(prefix), "[Device Report] Response (0x%02X)", cmd); + //debug_print_hex(prefix, full_packet, 64, 64); + + //debug_printf("Firmware upgrade response sent: cmd=0x%02x\n", cmd); } // 处理START命令 diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dnr_dsp_buf.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dnr_dsp_buf.h index 333973f..d2f57cb 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dnr_dsp_buf.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dnr_dsp_buf.h @@ -48,12 +48,6 @@ void start_dsp_processing(unsigned samFreq); #define KEY_PLAY_VOL_UP 0x80 #define KEY_BITS (KEY_MIC_VOL_DN | KEY_MUTE | KEY_MIC_VOL_UP | KEY_PLAY_VOL_DN | KEY_PLAY_VOL_UP) -#if defined (PHATEN_GSV2) -#define DEBOUNCE_TIMEOUT 10 // in units of 2.6ms; 128 samples/frame -#else -#error "Please define DEBOUNCE_TIMEOUT" -#endif - #define MUTED_MIC 0x5A #define UNMUTED_MIC 0xA5 @@ -66,4 +60,3 @@ void start_dsp_processing(unsigned samFreq); #define HID_CONTROL_MUTE 0x20 #endif //RINGBUFFER_H - diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp.c b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp.c index 14c3c62..8326503 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp.c +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp.c @@ -120,6 +120,9 @@ chanend_t uc_dsp_to_dnr_t1; chanend_t uc_key_to_ubm_t0; volatile EXTERN DS_BOOL m_hThread; extern unsigned g_dnr_init_flag; +void SetEx3dToUbmChan (chanend_t c) { + uc_ex3d_to_ubm = c; +} void SetEqDataChan (chanend_t c) { uc_eq_data = c; } @@ -161,7 +164,7 @@ void key_sender(chanend_t c) void UserBufferManagementInit(unsigned sampFreq) { ubm_sample_freq = sampFreq; -#if USE_EX3D == 1 +#if 0// USE_EX3D == 1 memset(ubm_ingress, 0, sizeof(ubm_ingress)); memset(ubm_egress, 0, sizeof(ubm_egress)); frame_index = 0; @@ -885,12 +888,10 @@ void update_button(unsigned char b) #endif -#if defined (PHATEN_GSV2) #define KEY_POLLING_INTERVAL 10000000L // 100ms polling interval #define HOLD_THRESHOLD 20 // time = HOLD_THRESHOLD * KEY_POLLING_INTERVAL = 2000ms // 改动原因:添加LED闪烁相关宏定义,用于长按时直接循环闪烁3次 #define BLINK_COUNT 3 // LED闪烁次数:3次 -#endif @@ -1153,10 +1154,8 @@ void hid_button_task(chanend_t cc_mic_level, chanend_t c_hidRcvData, chanend_t c chanend_t uc_dsp_to_ex3d[DSP_WORKER_COUNT]; extern int OnProcessing(); -void ex3d_task(){ - channel_t c = chan_alloc(); - chanend_t c_ex3d_to_ubm = c.end_a; - uc_ex3d_to_ubm = c.end_b; +void ex3d_task(chanend_t c_ex3d_to_ubm){ + // set_core_high_priority_on(); delay_milliseconds(500); @@ -1164,7 +1163,10 @@ void ex3d_task(){ if(ret != 0) { debug_printf("audio_ex3d_init() error:%d\n\r", ret); } - + memset(ubm_ingress, 0, sizeof(ubm_ingress)); + memset(ubm_egress, 0, sizeof(ubm_egress)); + audio_ex3d_onoff(1); + #if !UAC1_MODE Ex3dOffGain = -5; Ex3dOnGain = -5; diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp_core0.xc b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp_core0.xc index 0debd98..b1046e5 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp_core0.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/dsp_core0.xc @@ -35,7 +35,7 @@ extern void debug_print_eq_params(unsigned sample_freq); extern uint32_t get_reference_time(void); extern void update_eq_post_gain(void); extern unsigned int g_eq_sample_rate; -extern unsigned g_windows_detect_done; +unsigned g_windows_detect_done = 1; extern unsigned g_dnr_init_flag; extern unsigned g_ex3d_key_verified; diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.c b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.c new file mode 100644 index 0000000..573152e --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.c @@ -0,0 +1,50 @@ +#include "gpio_access.h" +#include "swlock.h" +#include + +swlock_t gpo_swlock = SWLOCK_INITIAL_VALUE; + +void p_gpio_lock() +{ + swlock_acquire(&gpo_swlock); +} + +void p_gpio_unlock() +{ + swlock_release(&gpo_swlock); +} + +unsigned p_gpio_peek() +{ + unsigned portId, x; + + // Wrapped in lock to ensure it's safe from multiple logical cores + swlock_acquire(&gpo_swlock); + + asm("ldw %0, dp[p_gpio]":"=r"(portId)); + asm volatile("peek %0, res[%1]":"=r"(x):"r"(portId)); + + return x; +} + +void p_gpio_out(unsigned x) +{ + unsigned portId; + + asm("ldw %0, dp[p_gpio]":"=r"(portId)); + asm volatile("out res[%0], %1"::"r"(portId),"r"(x)); + + // Wrapped in lock to ensure it's safe from multiple logical cores + swlock_release(&gpo_swlock); +} + +void set_gpio(unsigned bit, unsigned value) +{ + unsigned port_shadow; + port_shadow = p_gpio_peek(); // Read port pin value + if (value == 0) port_shadow &= ~bit; // If writing a 0, generate mask and AND with current val + else port_shadow |= bit; // Else use mask and OR to set bit + p_gpio_out(port_shadow); // Write back to port. Will make port an output if not already +} + + diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.h new file mode 100644 index 0000000..59f9ae1 --- /dev/null +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/gpio_access.h @@ -0,0 +1,17 @@ +#ifndef _GPIO_ACCESS_H_ +#define _GPIO_ACCESS_H_ + +/* General output port bit definitions */ +#define P_GPIO_DAC_RST_N (1 << 1) +#define P_GPIO_MUTE (1 << 3) +#define P_GPIO_SET (1 << 2) +#define MUTE (0) +#define UNMUTE (1) + +void set_gpio(unsigned bit, unsigned value); +void p_gpio_lock(); +void p_gpio_unlock(); +unsigned p_gpio_peek(); +void p_gpio_out(unsigned x); + +#endif diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/htr3236.xc b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/htr3236.xc deleted file mode 100644 index 3af71b4..0000000 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/htr3236.xc +++ /dev/null @@ -1,252 +0,0 @@ -/** - * @file htr3236.c - * @brief HTR3236 36-Channel LED PWM Driver Implementation for XMOS - * @version 1.1 - */ - -#include "htr3236.h" -#include - -#include - -out port p_htr3235_sdb = PORT_HTR3236_SDB; /* 连接到HTR3236的SDB引脚,用于控制其电源状态 */ - -/*========================================================================= - Gamma 校正查找表 - -----------------------------------------------------------------------*/ - -static const uint8_t gamma_table_32[32] = { - 0, 1, 2, 4, 6, 10, 13, 18, - 22, 28, 33, 39, 46, 53, 61, 69, - 78, 86, 96, 106, 116, 126, 138, 149, - 161, 173, 186, 199, 212, 226, 240, 255 -}; - -static const uint8_t gamma_table_64[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 10, 12, 14, 16, 18, 20, 22, - 24, 26, 29, 32, 35, 38, 41, 44, - 47, 50, 53, 57, 61, 65, 69, 73, - 77, 81, 85, 89, 94, 99, 104, 109, - 114, 119, 124, 129, 134, 140, 146, 152, - 158, 164, 170, 176, 182, 188, 195, 202, - 209, 216, 223, 230, 237, 244, 251, 255 -}; - -/*========================================================================= - 内部函数 - -----------------------------------------------------------------------*/ - -/** - * @brief 写单字节到寄存器 - */ -static int write_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, uint8_t data) -{ - uint8_t buf[2] = {reg, data}; - size_t n; - - i2c.write(dev->i2c_addr, buf, 2, n, 1); - - if (n == 0) - { - return I2C_REGOP_DEVICE_NACK; - } - if (n < 2) - { - return I2C_REGOP_INCOMPLETE; - } - - return I2C_REGOP_SUCCESS; -} - -/** - * @brief 写多字节到寄存器 (支持自动地址递增) - */ -static int write_reg_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_reg, - const uint8_t *data, uint8_t len) -{ - uint8_t buf[36 + 1]; - size_t n; - - buf[0] = start_reg; - - for (int i = 0; i < len; i++) { - buf[i + 1] = data[i]; - } - - i2c.write(dev->i2c_addr, buf, len + 1, n, 1); - - if (n == 0) - { - return I2C_REGOP_DEVICE_NACK; - } - if (n < 2) - { - return I2C_REGOP_INCOMPLETE; - } - - return I2C_REGOP_SUCCESS; -} - -/** - * @brief 读取寄存器值 - */ -static int read_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, i2c_regop_res_t &result) -{ - uint8_t a_reg[1] = {reg}; - uint8_t data[1] = {0}; - size_t n; - i2c_res_t res; - - unsafe - { - res = i2c.write(dev->i2c_addr, a_reg, 1, n, 0); - - if (n != 1) - { - result = I2C_REGOP_DEVICE_NACK; - i2c.send_stop_bit(); - return 0; - } - - res = i2c.read(dev->i2c_addr, data, 1, 1); - } - - if (res == I2C_ACK) - { - result = I2C_REGOP_SUCCESS; - } - else - { - result = I2C_REGOP_DEVICE_NACK; - } - return data[0]; -} - - - -/*========================================================================= - API 函数实现 - -----------------------------------------------------------------------*/ - -void htr3236_init(htr3236_t *dev, uint8_t addr) -{ - dev->i2c_addr = addr; - - // 默认 SDB 拉高,使能芯片 - //htr3236_hw_enable(dev); -} - -void htr3236_hw_enable(htr3236_t *dev) -{ - p_htr3235_sdb <: 1; -} - -void htr3236_hw_disable(htr3236_t *dev) -{ - p_htr3235_sdb <: 0; -} - -int htr3236_software_wake(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c)) -{ - return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_NORMAL_OP); -} - -int htr3236_software_shutdown(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c)) -{ - return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_SHUTDOWN_SOFT); -} - -int htr3236_software_reset(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c)) -{ - return write_reg(dev, i2c, HTR3236_REG_RESET, 0x00); -} - -int htr3236_set_pwm(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel, uint8_t brightness) -{ - if (channel < 1 || channel > 36) { - return -1; - } - - uint8_t reg = HTR3236_REG_PWM_START + (channel - 1); - return write_reg(dev, i2c, reg, brightness); -} - -int htr3236_set_pwm_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch, - const uint8_t *values, uint8_t len) -{ - if (start_ch < 1 || start_ch > 36 || len == 0) { - return -1; - } - - // 检查是否会超出寄存器范围 - if (start_ch + len - 1 > 36) { - return -1; - } - - uint8_t start_reg = HTR3236_REG_PWM_START + (start_ch - 1); - return write_reg_bulk(dev, i2c, start_reg, values, len); -} - -int htr3236_set_led_config(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel, - htr3236_current_t current, uint8_t enable) -{ - if (channel < 1 || channel > 36) { - return -1; - } - - uint8_t reg = HTR3236_REG_LED_CTRL_START + (channel - 1); - uint8_t data = (enable ? 1 : 0) | (current << 1); - - return write_reg(dev, i2c, reg, data); -} - -int htr3236_set_led_config_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch, - const uint8_t *configs, uint8_t len) -{ - if (start_ch < 1 || start_ch > 36 || len == 0) { - return -1; - } - - // 检查是否会超出寄存器范围 - if (start_ch + len - 1 > 36) { - return -1; - } - - uint8_t start_reg = HTR3236_REG_LED_CTRL_START + (start_ch - 1); - return write_reg_bulk(dev, i2c, start_reg, configs, len); -} - -int htr3236_update(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c)) -{ - // 写入任意值到更新寄存器使配置生效 - return write_reg(dev, i2c, HTR3236_REG_PWM_UPDATE, 0x00); -} - -int htr3236_global_enable(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t enable) -{ - uint8_t data = enable ? 1 : 0; - return write_reg(dev, i2c, HTR3236_REG_GLOBAL_CTRL, data); -} - -int htr3236_set_frequency(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), htr3236_freq_t freq) -{ - uint8_t data = (freq == HTR3236_FREQ_22KHZ) ? 1 : 0; - return write_reg(dev, i2c, HTR3236_REG_FREQ_SET, data); -} - -uint8_t htr3236_gamma_32(uint8_t index) -{ - if (index >= 32) { - index = 31; - } - return gamma_table_32[index]; -} - -uint8_t htr3236_gamma_64(uint8_t index) -{ - if (index >= 64) { - index = 63; - } - return gamma_table_64[index]; -} \ No newline at end of file diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/led_control.c b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/led_control.c deleted file mode 100644 index 39a4182..0000000 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/led_control.c +++ /dev/null @@ -1,331 +0,0 @@ -/** - * @file led_control.c - * @brief LED控制API实现 (基于HTR3236) - * @version 1.0 - */ - -#include "led_control.h" -#include -#include -#include - -/*========================================================================= - 内部函数 - -----------------------------------------------------------------------*/ - -/** - * @brief 检查LED ID是否有效 - */ -static int is_valid_led(led_id_t led) -{ - return (led >= 1 && led <= 36 && led != 36); // OUT36未使用 -} - -/** - * @brief 获取LED组起始和结束索引 - */ -static void get_group_range(led_group_t group, uint8_t *start, uint8_t *end) -{ - switch (group) { - case LED_GROUP_L_SERIES: - *start = LED_L1; - *end = LED_L15; - break; - case LED_GROUP_D_SERIES: - *start = LED_D1; - *end = LED_D15; - break; - // case LED_GROUP_FUNCTION: - // *start = LED_ANC; - // *end = LED_GAME_MODE; - // break; - case LED_GROUP_ALL: - default: - *start = 1; - *end = 35; // 排除OUT36 - break; - } -} - -/*========================================================================= - LED物理映射表 - -----------------------------------------------------------------------*/ -// 根据测试结果:LED_L1-L15的实际OUT口 -const uint8_t led_l_physical_map[15] = { - 15, // LED_L1 -> OUT15 - 14, // LED_L2 -> OUT14 - 13, // LED_L3 -> OUT13 - 11, // LED_L4 -> OUT11 - 10, // LED_L5 -> OUT10 - 9, // LED_L6 -> OUT9 - 8, // LED_L7 -> OUT8 - 7, // LED_L8 -> OUT7 - 6, // LED_L9 -> OUT6 - 5, // LED_L10 -> OUT5 - 4, // LED_L11 -> OUT4 - 12, // LED_L12 -> OUT12 * - 18, // LED_L13 -> OUT18 * - 17, // LED_L14 -> OUT17 - 16, // LED_L15 -> OUT16 -}; -// 根据测试结果:LED_D1-D15的实际OUT口 -const uint8_t led_d_physical_map[15] = { - 21, // LED_D1 -> OUT21 - 20, // LED_D2 -> OUT20 - 19, // LED_D3 -> OUT19 - 26, // LED_D4 -> OUT26 * - 33, // LED_D5 -> OUT33 * - 32, // LED_D6 -> OUT32 - 31, // LED_D7 -> OUT31 - 30, // LED_D8 -> OUT30 - 29, // LED_D9 -> OUT29 - 28, // LED_D10 -> OUT28 - 27, // LED_D11 -> OUT27 - 25, // LED_D12 -> OUT25 - 24, // LED_D13 -> OUT24 - 23, // LED_D14 -> OUT23 - 22, // LED_D15 -> OUT22 -}; - -// 改动原因:按 SY102mic音量对应表.csv,将麦克风音量等级改为 49 级(0~48),最大增益改为 24dB, -// LED档位按表中“旋钮刻度49级 + LED灯15个”的分段阈值重建。 -const uint8_t mic_gain_to_led[49] = { - 0, // [0] mute - 1, // [1] - 1, // [2] - 1, // [3] - 2, // [4] - 2, // [5] - 2, // [6] - 3, // [7] - 3, // [8] - 3, // [9] - 4, // [10] - 4, // [11] - 4, // [12] - 5, // [13] - 5, // [14] - 5, // [15] - 6, // [16] - 6, // [17] - 6, // [18] - 7, // [19] - 7, // [20] - 7, // [21] - 8, // [22] - 8, // [23] - 8, // [24] - 9, // [25] - 9, // [26] - 9, // [27] - 10, // [28] - 10, // [29] - 10, // [30] - 11, // [31] - 11, // [32] - 11, // [33] - 12, // [34] - 12, // [35] - 12, // [36] - 13, // [37] - 13, // [38] - 13, // [39] - 13, // [40] - 14, // [41] - 14, // [42] - 14, // [43] - 14, // [44] - 15, // [45] - 15, // [46] - 15, // [47] - 15 // [48] max 24dB -}; - -// 改动原因:按 SY102dac对应表.csv,将DAC音量等级改为 49 级(0~48), -// LED分段阈值按“旋钮48格 + 15灯”映射重建,确保HID 0x93新范围显示一致。 -const uint8_t dac_gain_to_led[49] = { - 0, // [0] mute - 1, // [1] - 1, // [2] - 1, // [3] - 2, // [4] - 2, // [5] - 2, // [6] - 3, // [7] - 3, // [8] - 3, // [9] - 4, // [10] - 4, // [11] - 4, // [12] - 5, // [13] - 5, // [14] - 5, // [15] - 6, // [16] - 6, // [17] - 6, // [18] - 7, // [19] - 7, // [20] - 7, // [21] - 8, // [22] - 8, // [23] - 8, // [24] - 9, // [25] - 9, // [26] - 9, // [27] - 10, // [28] - 10, // [29] - 10, // [30] - 11, // [31] - 11, // [32] - 11, // [33] - 12, // [34] - 12, // [35] - 12, // [36] - 13, // [37] - 13, // [38] - 13, // [39] - 13, // [40] - 14, // [41] - 14, // [42] - 14, // [43] - 14, // [44] - 15, // [45] - 15, // [46] - 15, // [47] - 15, // [48] -}; - -/*========================================================================= - 内部函数 - 获取实际OUT口 - -----------------------------------------------------------------------*/ -static uint8_t get_physical_out(led_id_t led) -{ - // 如果是L系列LED - if (led >= LED_L1 && led <= LED_L15) { - uint8_t index = led - LED_L1; - return led_l_physical_map[index]; - } - else if (led >= LED_D1 && led <= LED_D15) { - uint8_t index = led - LED_D1; - return led_d_physical_map[index]; - } - - // 其他LED直接返回原值 - return (uint8_t)led; -} - -/*========================================================================= - 基础控制API实现 - -----------------------------------------------------------------------*/ - -void led_control_init(led_control_t *ctx, - htr3236_t *dev, - CLIENT_INTERFACE(i2c_master_if,i2c)) -{ - ctx->htr3236_dev = dev; - ctx->i2c = i2c; - - // 初始化亮度缓存 - memset(ctx->brightness, 0, sizeof(ctx->brightness)); - - // 配置所有LED通道的电流 (使用IMAX/2) - for (int led = 1; led <= 35; led++) { // 跳过OUT36 - htr3236_set_led_config(ctx->htr3236_dev, ctx->i2c, - led, HTR3236_CURRENT_HALF, 1); - } - - // 初始关闭所有LED - for (int led = 1; led <= 35; led++) { - htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, 0); - } - - htr3236_update(ctx->htr3236_dev, ctx->i2c); -} - -int led_set_brightness(led_control_t *ctx, - led_id_t led, - uint8_t brightness) -{ - if (!is_valid_led(led)) { - return -1; - } - - ctx->brightness[led - 1] = brightness; - return htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness); -} - -int led_on(led_control_t *ctx, led_id_t led) -{ - return led_set_brightness(ctx, led, 30/*255*/); -} - -int led_off(led_control_t *ctx, led_id_t led) -{ - return led_set_brightness(ctx, led, 0); -} - -int led_toggle(led_control_t *ctx, led_id_t led) -{ - if (!is_valid_led(led)) { - return -1; - } - - uint8_t new_brightness = (ctx->brightness[led - 1] == 0) ? 255 : 0; - return led_set_brightness(ctx, led, new_brightness); -} - -int led_update_all(led_control_t *ctx) -{ - return htr3236_update(ctx->htr3236_dev, ctx->i2c); -} - -/*========================================================================= - 组控制API实现 - -----------------------------------------------------------------------*/ - -int led_group_set_brightness(led_control_t *ctx, - led_group_t group, - uint8_t brightness) -{ - uint8_t start, end; - get_group_range(group, &start, &end); - - if (group == LED_GROUP_FUNCTION) { - // 功能LED需要单独处理每个LED - led_id_t function_leds[] = { - LED_MUSIC, LED_ANC, LED_FOOTSTEP_MODE, LED_AI7_1, LED_GAME_MODE - }; - - for (int i = 0; i < 5; i++) { - led_id_t led = function_leds[i]; - uint8_t physical_out = get_physical_out(led); // 如果有映射 - ctx->brightness[physical_out - 1] = brightness; - htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness); - } - } - else - { - for (uint8_t led = start; led <= end; led++) { - if (led == 36) continue; // 跳过未使用的OUT36 - if((group == LED_GROUP_L_SERIES) || (group == LED_GROUP_D_SERIES)) - { - uint8_t physical_out = get_physical_out(led); - ctx->brightness[physical_out - 1] = brightness; - } - else ctx->brightness[led - 1] = brightness; - htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness); - } - } - - return htr3236_update(ctx->htr3236_dev, ctx->i2c); -} - -int led_group_on(led_control_t *ctx, led_group_t group) -{ - return led_group_set_brightness(ctx, group, 255); -} - -int led_group_off(led_control_t *ctx, led_group_t group) -{ - return led_group_set_brightness(ctx, group, 0); -} \ No newline at end of file diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/main.xc b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/main.xc index 7f21fbc..487ddba 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/main.xc +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/main.xc @@ -24,6 +24,8 @@ #endif #include "uac_hwresources.h" +/* 改动原因:引入 C1 面板 LED 控制 interface 声明(user_main.h),供 main 中声明 interface 实例并连接 AudioHwRemote / app_control_slave。 */ +#include "user_main.h" #ifdef IAP #include "i2c_shared.h" @@ -429,26 +431,31 @@ extern void SetEx3dHidChan (chanend c); extern int dsp_worker_tile(chanend c_dsp_to_ex3d, int worker_id); //extern int dsp_worker_tile_1(chanend c_dsp_to_ex3d, int worker_id); -extern void ex3d_task(); +extern void ex3d_task(chanend c_ex3d_to_ubm); extern void hid_button_task(chanend cc_mic_level, chanend c_hid, chanend c_hidSendData, chanend c_uac_vol, chanend c_ex3d_hid_cmd); +/* 改动原因:与 audiohw.xc 中 AudioHwRemote 一致。HID/音量/MIC 检测等已迁到 tile1 hid_button_task 与 AudioHwRemote2 内物理口; + * codec 仅经 streaming c_audiohw;DFU 命令经 c_dfu(仅 HID_DFU_EN=1)。 */ #if HID_DFU_EN -extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, streaming chanend c_dfu_rx, chanend c_mic_det); +extern void AudioHwRemote(streaming chanend c_audiohw_rx, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu_rx); #else -extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, chanend c_mic_det); +extern void AudioHwRemote(streaming chanend c_audiohw_rx, client interface c1_led_ctrl_if i_c1_led_ctrl); #endif extern void dnr_dsp_proc_task(void); extern unsafe chanend uc_dsp_to_ex3d[DSP_WORKER_COUNT]; extern unsafe chanend uc_dsp_to_dnr_t1; extern unsafe chanend uc_key_to_ubm_t0; -extern unsafe chanend uc_audiohw; +extern streaming unsafe chanend uc_audiohw; #if HID_DFU_EN extern unsafe streaming chanend uc_dfu; #endif extern void key_sender(chanend c_key); extern void key_receiver(chanend c_key); -extern void mute_handler(chanend c_mic_det); +extern void SetEx3dToUbmChan (chanend c); + +/* 改动原因:main 绑定 uc_audiohw 后写 1,供 AudioHwInit 自旋等待(定义在 audiohw.xc),消除与 usb_audio_io 的启动竞态。 */ +extern unsigned g_uc_audiohw_chan_bound; /* Main for USB Audio Applications */ int main() @@ -541,8 +548,8 @@ int main() USER_MAIN_DECLARATIONS chan c_dsp_to_ex3d[DSP_WORKER_COUNT]; - chan cc_mic_level; - chan c_audiohw; + // chan cc_mic_level; + streaming chan c_audiohw; #if HID_DFU_EN streaming chan c_dfu; #endif @@ -551,7 +558,10 @@ int main() chan c_eq_data; chan c_uac_vol; chan c_ex3d_hid_cmd; - chan c_mic_det; + chan c_ex3d_to_ubm; + /* 改动原因:MIC 插拔检测已并入 audiohw.xc(p_mic_phone_detect / AudioHwRemote2),删除未使用 c_mic_det。 + * C1 面板灯:tile0 AudioHwRemote 为 c1_led_ctrl_if client,tile1 app_control_slave 为 server。 */ + interface c1_led_ctrl_if i_c1_led_ctrl; par { @@ -559,42 +569,54 @@ int main() on tile[1] : { par { unsafe { - uc_audiohw = (chanend)c_audiohw; #if EQ_EN == 1 && USE_EX3D == 0 - SetEqDataChan(c_eq_data); #endif - hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol, c_ex3d_hid_cmd); + // hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol, c_ex3d_hid_cmd); } #if USE_EX3D == 1 par(int i = 0; i < DSP_WORKER_COUNT; i++) dsp_worker_tile(c_dsp_to_ex3d[i], i); unsafe { - SetEqDataChan(c_eq_data); delay_milliseconds(200); key_sender(c_key); for (int i = 0; i < DSP_WORKER_COUNT; i++) uc_dsp_to_ex3d[i] = (chanend)c_dsp_to_ex3d[i]; - ex3d_task(); + ex3d_task(c_ex3d_to_ubm); } #endif } } - on tile[1]: mute_handler(c_mic_det); + /* 改动原因:C1 硬件插拔检测与 DAC/MIC 哑音逻辑已并入 tile0 button_task(见 audiohw.xc),不再使用原 mute_handler + p_ctl_det 方案。 */ + on tile[1]: app_control_slave(i_c1_led_ctrl); + /* 改动原因:XUA_AudioHub 与 AudioHwRemote/dsp 并行启动;AudioHwInit→codec_init 经 CODEC_REGWRITE 使用 uc_audiohw。 + * 若仅在 dsp_main 内赋值,AudioHub 先跑到 codec_init 时 uc_audiohw 未绑定会 ET_ILLEGAL_RESOURCE。 + * 与 fosi_c1 user_main.h 一致:在 tile[0]、启动 AudioHwRemote 之前绑定 streaming chan 发送端句柄。 */ on tile[0] : { + unsafe { + uc_audiohw = (streaming chanend)c_audiohw; + g_uc_audiohw_chan_bound = 1; + } par { { + /* 改动原因:参数顺序与类型对齐 audiohw.xc 的 AudioHwRemote,修复链接阶段符号类型不一致。 */ + { + unsafe { + SetEqDataChan(c_eq_data); + SetEx3dToUbmChan(c_ex3d_to_ubm); + } #if USE_EX3D == 1 unsafe { key_receiver(c_key); } #endif - AudioHwRemote(c_hidSendData, cc_mic_level, c_uac_vol, c_audiohw + #if HID_DFU_EN - , c_dfu + AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_dfu); +#else + AudioHwRemote(c_audiohw, i_c1_led_ctrl); #endif - , c_mic_det - ); + } } } } @@ -611,6 +633,7 @@ int main() dsp_core0(); } } + /* 改动原因:uc_audiohw 已在上文 tile[0] AudioHwRemote 父块入口绑定,此处删除重复赋值,避免误读为唯一初始化点。 */ on tile[0] : { dsp_main(c_eq_data); } #endif 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 1261425..60eb87f 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 @@ -263,3 +263,35 @@ void save_userconfig_info(unsigned char *buffer) { memcpy((unsigned char *)&appUserConf, buffer, sizeof(appUserConf)); } +unsigned char g_hid_pass_data[64]; +/* 改动原因:固件升级开始/结束时通知 MCU;0=无,1=升级开始,2=升级结束成功,3=升级结束(中止/失败)。 + * 由 dfu_upgrade.c 在 handle_firmware_upgrade_start/end/abort 中设置,uart_handler 在 se_tmr 中读取并发送 0x62 串口包后清零。 */ +unsigned g_firmware_upgrade_mcu_notify = 0; +/* 改动原因:标记是否处于固件升级中,供 uart_handler 跳过 heatTick 等;START 时置 1,END/ABORT 时置 0。由 dfu_upgrade.c 设置。 */ +unsigned g_in_fw_upgrade = 0; +extern void hidSetChangePending(unsigned int); + +void user_read_hidpass(unsigned char * hidPassData) +{ + int i = 0; + for (i = 0; i < 64; i++) + { + hidPassData[i] = g_hid_pass_data[i]; + debug_printf("hidPassData[%d] = %02x\n", i, hidPassData[i]); + g_hid_pass_data[i] = 0; + } +} + +void user_set_hidpass(unsigned char *data) +{ +#if HID_CONTROLS + + for (int i = 0; i < 63; i++) + { + g_hid_pass_data[i] = data[i]; + debug_printf("g_hid_pass_data[%d] = %02x\n", i, g_hid_pass_data[i]); + } + + hidSetChangePending(0x1); +#endif +} diff --git a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_main.h b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_main.h index 3acbb07..a311baa 100644 --- a/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_main.h +++ b/sw_usb_audio/app_usb_aud_fosi_c1_v71/src/extensions/user_main.h @@ -10,9 +10,17 @@ #include #include "DSBuild.h" +/* 改动原因:与 fosi_c1 一致,mode/mic 物理灯在 tile[1],tile[0] 的 button_task 通过 client interface 下发状态,由 app_control_slave 统一驱动 GPIO。 */ +interface c1_led_ctrl_if { + void set_mode_led_color(unsigned color_idx); + void set_mic_mute_state(unsigned mute_switch); + void set_mic_voice_fx(unsigned voice_fx_enabled); +}; -#define USER_MAIN_DECLARATIONS \ +void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl); +/* 改动原因:v71 main.xc 自行展开任务拓扑,此处不注入额外 chan/interface 声明,避免宏续行空定义导致预处理异常。 */ +#define USER_MAIN_DECLARATIONS #endif // __XC__