From a15bfeb615eff7546ae5a0036c0faf970d33d218 Mon Sep 17 00:00:00 2001 From: Steven Dan Date: Sat, 28 Mar 2026 12:27:05 +0800 Subject: [PATCH] update hid commands --- .../src/extensions/audiohw.xc | 118 +++++++++++++----- .../src/extensions/eq.c | 37 ++++++ .../src/extensions/eq_designer_new.py | 115 +++++++++++++++++ .../src/extensions/eq_hid_protocol.md | 70 +++++++++++ .../src/extensions/sy102_hid_protocol.md | 79 ++++++++++++ 5 files changed, 385 insertions(+), 34 deletions(-) diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc index d4e8aca..947940a 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc @@ -88,6 +88,8 @@ unsigned g_last_mic_volume_level = 0xFF; // 上次已上报的麦克风增益 unsigned g_dnr_strength = 100; // AI降噪强度HID值(0=关,2-100=开,步进2;100→-200dB最强) unsigned g_last_dnr_strength = 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; @@ -421,6 +423,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, 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 host_os; delay_milliseconds(10); @@ -555,6 +560,41 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, 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); + + // 从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); } codec_init(); @@ -563,10 +603,11 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, // 麦克风HID范围上限37 (register=38的+1.5dB仅firmware内部使用) g_mic_volume_level = (codec_adc_pga_gain_reg_value <= 37) ? codec_adc_pga_gain_reg_value : 37; - // ADCL PGA default setting - mic_volume(codec_adc_pga_gain_reg_value); // make sure to write adc reg after initialize the codec, otherwise it does not take effect because of the hardware reset in the initial code + // ADCL PGA default setting(mic_volume内部已根据g_monitor_switch决定是否启用耳返通路) + // 若mic_mute已从flash恢复为1,则此处先以正常gain调用,再用mute覆盖 + mic_volume(codec_adc_pga_gain_reg_value); { - int mic_led_count = mic_gain_to_led[codec_adc_pga_gain_reg_value]; + int mic_led_count = flag_mic_mute ? 0 : mic_gain_to_led[codec_adc_pga_gain_reg_value]; for(int i = 0; i < 15; i++) { if (i < mic_led_count) @@ -575,6 +616,11 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, led_off(&led_ctx, led_l_physical_map[i]); } } + // 应用从flash恢复的mic_mute状态 + if(flag_mic_mute) { + mic_volume(0); + g_mic_volume_level = 0; + } // DAC 默认音量(mute 时写 0x0000) if(dac_level == DAC_LEVEL_MIN) @@ -582,7 +628,7 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, else dac_volume(dac_level - DAC_LEVEL_MAX); { - int dac_led_count = dac_gain_to_led[dac_level]; + int dac_led_count = flag_hp_mute ? 0 : dac_gain_to_led[dac_level]; for(int i = 0; i < 15; i++) { if (i < dac_led_count) @@ -591,6 +637,11 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, 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; + } // 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); @@ -976,6 +1027,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, lfs_remove_file("mic_vol"); lfs_remove_file("dac_vol"); lfs_remove_file("footstep"); + lfs_remove_file("monitor_sw"); + lfs_remove_file("mic_mute"); + lfs_remove_file("hp_mute"); } led_on(&led_ctx, LED_MUSIC); @@ -1305,6 +1359,11 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } } 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) { @@ -1328,34 +1387,6 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, led_on(&led_ctx, led_l_physical_map[i]); } } - - - - // mic_gain = 0; - - // if((mic_encoder1 & 0b0100) != 0) mic_gain |= 0b0010; - // if((mic_encoder2 & 0b0100) != 0) mic_gain |= 0b1000; - - //mic_gain >>= 4; - - // if((mic_gain & 0b0100) == 0) - // { - // if(mute_down) - // { - // SET_SHARED_GLOBAL(g_reduct_dep, ++mic_mute % 4); - // } - // // if ((mic_mute % 4) == 0) - // // set_gpio(P_GPIO_LED, 0); - // // else - // // set_gpio(P_GPIO_LED, 1); - - // mute_down = 0; - // } - // else - // { - // mute_down = 1; - // } - uint8_t rotating = (mic_encoder2 & 0b0100) == 0; // 4E2 uint8_t encode_input1 = ((mic_encoder1 & 0b0100) != 0); // 4F2 @@ -1566,6 +1597,11 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } } 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) { @@ -1659,8 +1695,21 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, } } + // 处理HID SET_MONITOR_SWITCH (0x87) 请求:设置耳返开关 + if (g_request_monitor_switch_set) { + g_request_monitor_switch_set = 0; + unsigned new_mon = g_monitor_switch; + // 根据当前mic状态和新的耳返开关值更新reg 0x30 + if (new_mon && !flag_mic_mute && codec_adc_pga_gain_reg_value >= 2) { + unsafe { NAU88C22_REGWRITE(0x0030, 0xff00, (client interface i2c_master_if)i_i2c_client); } + } else { + unsafe { NAU88C22_REGWRITE(0x0030, 0x0000, (client interface i2c_master_if)i_i2c_client); } + } + 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) 请求 -#if DNR_ENABLE == 1 { unsigned dnr_req; GET_SHARED_GLOBAL(dnr_req, g_request_dnr_strength_set); @@ -1668,7 +1717,9 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, SET_SHARED_GLOBAL(g_request_dnr_strength_set, 0); unsigned new_strength; GET_SHARED_GLOBAL(new_strength, g_dnr_strength); +#if DNR_ENABLE == 1 dnr_set_strength_level((unsigned char)new_strength); +#endif if (new_strength == 0) { flag_aidenoise_onoff = 0; led_off(&led_ctx, LED_ANC); @@ -1681,7 +1732,6 @@ void button_task(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, debug_printf("HID SET_AI_NOISE_STRENGTH: strength=%d\n", new_strength); } } -#endif #if HID_CONTROLS == 1 // HID监听音量变化主动上报(编码器旋转或HID命令导致的音量变化) diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c index 3a56009..aae4adf 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c @@ -638,6 +638,7 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { extern unsigned g_request_mic_volume_set; g_mic_volume_level = mic_level; g_request_mic_volume_set = 1; + read_request.pending_cmd = 0x83; // 设置后用0x83格式回报当前增益 return true; } @@ -669,6 +670,27 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { return true; } + // 处理设置耳返开关命令 (0x87) - SET_MONITOR_SWITCH + // 0=关闭耳返(ADC不路由到耳机输出),1=开启耳返 + if (data[1] == 0x87) { + uint8_t mon_sw = data[2]; + if (mon_sw > 1) { + return false; + } + extern unsigned g_monitor_switch; + extern unsigned g_request_monitor_switch_set; + g_monitor_switch = mon_sw; + g_request_monitor_switch_set = 1; + read_request.pending_cmd = 0x88; // 设置后用0x88格式回报当前状态 + return true; + } + + // 处理读取耳返开关命令 (0x88) - GET_MONITOR_SWITCH + if (data[1] == 0x88) { + read_request.pending_cmd = 0x88; + return true; + } + // 处理设置音量命令 (0x93) - SET_VOLUME // 范围: 0-15 (0=静音, 1-15=-28dB~0dB, 2dB/步) if (data[1] == 0x93) { @@ -758,6 +780,9 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) { lfs_remove_file("mic_vol"); lfs_remove_file("dac_vol"); lfs_remove_file("footstep"); + lfs_remove_file("monitor_sw"); + lfs_remove_file("mic_mute"); + lfs_remove_file("hp_mute"); // 删除EQ flash数据 eq_flash_clear_all(); // 通知button_task在合适时机重启(避免在USB上下文中直接reboot) @@ -1061,6 +1086,18 @@ unsigned char process_read_params(uint8_t response[]) { read_request.pending_cmd = 0; return true; } + + // 处理耳返开关请求/响应 (0x88) - GET_MONITOR_SWITCH + if (read_request.pending_cmd == 0x88) { + RSP_HDR(response, 0x88); + + extern unsigned g_monitor_switch; + response[2] = (uint8_t)g_monitor_switch; + + read_request.pending_cmd = 0; + return true; + } + // 处理读取音量请求 (0x94) - GET_VOLUME if (read_request.pending_cmd == 0x94) { RSP_HDR(response, 0x94); diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_designer_new.py b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_designer_new.py index 5774f72..577a6d3 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_designer_new.py +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_designer_new.py @@ -674,6 +674,25 @@ class EQDesigner(QMainWindow): noise_btn_layout.addWidget(self.get_noise_strength_btn) volume_layout.addRow(noise_btn_layout) + # 耳返开关控制 + monitor_switch_layout = QHBoxLayout() + self.monitor_switch_label = QLabel("耳返开关 (0x87/0x88):") + self.monitor_switch_combo = QComboBox() + self.monitor_switch_combo.addItems(["关闭 (0)", "开启 (1)"]) + self.monitor_switch_combo.setCurrentIndex(0) # 默认关闭 + monitor_switch_layout.addWidget(self.monitor_switch_label) + monitor_switch_layout.addWidget(self.monitor_switch_combo) + volume_layout.addRow(monitor_switch_layout) + + monitor_btn_layout = QHBoxLayout() + self.set_monitor_switch_btn = QPushButton("设置耳返开关") + self.set_monitor_switch_btn.clicked.connect(self.on_set_monitor_switch) + self.get_monitor_switch_btn = QPushButton("读取耳返开关") + self.get_monitor_switch_btn.clicked.connect(self.on_get_monitor_switch) + monitor_btn_layout.addWidget(self.set_monitor_switch_btn) + monitor_btn_layout.addWidget(self.get_monitor_switch_btn) + volume_layout.addRow(monitor_btn_layout) + # 读取采样率和格式按钮 self.get_sample_format_btn = QPushButton("读取采样率和格式") self.get_sample_format_btn.clicked.connect(self.on_get_sample_format) @@ -2511,6 +2530,102 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{ except Exception as e: log_message(LOG_LEVEL_ERROR, f"读取AI降噪强度时出错: {str(e)}", self.log_level) + def on_set_monitor_switch(self): + """设置耳返开关(发送0x87命令,0=关闭,1=开启)""" + if self.device_combo.currentData() is None: + log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level) + return + + mon_sw = self.monitor_switch_combo.currentIndex() # 0=关闭, 1=开启 + desc = "关闭耳返" if mon_sw == 0 else "开启耳返(ADC路由到耳机输出)" + reply = QMessageBox.question( + self, + "确认设置耳返开关", + f"将要设置耳返开关为: {'开启' if mon_sw else '关闭'}\n{desc}\n\n是否继续?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No + ) + + if reply == QMessageBox.Yes: + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + + data = bytearray(63) + data[0] = 0x77 + data[1] = 0x87 # SET_MONITOR_SWITCH + data[2] = mon_sw + + log_message(LOG_LEVEL_INFO, f"正在设置耳返开关为 {'开启' if mon_sw else '关闭'}...", self.log_level) + h.write([0x01] + list(data)) + + import time + time.sleep(0.05) + reply_data = h.get_input_report(0x1, 64) + if reply_data and len(reply_data) == 64: + if reply_data[0] == 0x01 and reply_data[1] == 0x77 and reply_data[2] == 0x88: + cur_val = reply_data[3] + self.monitor_switch_combo.setCurrentIndex(cur_val) + log_message(LOG_LEVEL_INFO, f"耳返开关已设置为: {'开启' if cur_val else '关闭'}", self.log_level) + QMessageBox.information(self, "成功", f"耳返开关已设置为: {'开启' if cur_val else '关闭'}") + else: + log_message(LOG_LEVEL_INFO, f"耳返开关设置成功(无响应确认)", self.log_level) + QMessageBox.information(self, "成功", f"耳返开关已设置为: {'开启' if mon_sw else '关闭'}") + else: + log_message(LOG_LEVEL_INFO, f"耳返开关设置命令已发送", self.log_level) + QMessageBox.information(self, "成功", f"耳返开关已设置为: {'开启' if mon_sw else '关闭'}") + + h.close() + + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"设置耳返开关时出错: {str(e)}", self.log_level) + + def on_get_monitor_switch(self): + """读取耳返开关状态(发送0x88命令)""" + if self.device_combo.currentData() is None: + log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level) + return + + try: + device_info = self.device_combo.currentData() + h = hid.device() + h.open(device_info['vendor_id'], device_info['product_id']) + h.set_nonblocking(1) + + data = bytearray(63) + data[0] = 0x77 + data[1] = 0x88 # GET_MONITOR_SWITCH + + log_message(LOG_LEVEL_INFO, "正在读取耳返开关状态...", self.log_level) + h.write([0x01] + list(data)) + + import time + time.sleep(0.05) + reply = h.get_input_report(0x1, 64) + if reply and len(reply) == 64: + if reply[0] == 0x01 and reply[1] == 0x77 and reply[2] == 0x88: + mon_sw = reply[3] + # 更新UI下拉框(index直接等于值:0=关闭, 1=开启) + if mon_sw <= 1: + self.monitor_switch_combo.setCurrentIndex(mon_sw) + log_message(LOG_LEVEL_INFO, f"当前耳返开关状态: {'开启' if mon_sw else '关闭'}", self.log_level) + QMessageBox.information( + self, "耳返开关状态", + f"当前耳返开关: {'开启 (1)' if mon_sw else '关闭 (0)'}\n\n" + f"说明: 开启时ADC数据实时路由到耳机输出(需麦克风未静音)" + ) + else: + log_message(LOG_LEVEL_ERROR, f"无效的0x88响应同步头: 0x{reply[1]:02x} 0x{reply[2]:02x}", self.log_level) + else: + log_message(LOG_LEVEL_ERROR, "未收到0x88响应数据", self.log_level) + + h.close() + + except Exception as e: + log_message(LOG_LEVEL_ERROR, f"读取耳返开关状态时出错: {str(e)}", self.log_level) + def on_get_sample_format(self): """读取采样率和格式信息(发送0x9F命令)""" if self.device_combo.currentData() is None: diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_hid_protocol.md b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_hid_protocol.md index bfccfac..90b3a66 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_hid_protocol.md +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq_hid_protocol.md @@ -13,6 +13,8 @@ | 0x84 | FACTORY_RESET | 恢复出厂默认设置 | 主机→设备 | 删除Flash中所有已保存参数,设备重启后自动恢复出厂默认值 | | 0x85 | SET_AI_NOISE_STRENGTH | 设置AI降噪强度 | 主机→设备 | 设置AI降噪强度(0=关闭,2-100偶数=强度级别,步进2;100对应最强-200dB) | | 0x86 | GET_AI_NOISE_STRENGTH | 获取AI降噪强度 | 主机→设备 | 读取当前AI降噪强度;强度变化(含按键切换、开机初始值)时设备主动上报 | +| 0x87 | SET_MONITOR_SWITCH | 设置耳返开关 | 主机→设备 | 设置耳返(ADC→耳机监听)开关(0=关闭,1=开启),保存到Flash | +| 0x88 | GET_MONITOR_SWITCH | 获取耳返开关状态 | 主机→设备 | 读取当前耳返开关状态(0=关闭,1=开启) | | 0x8A | SET_EQ_MODE | 切换EQ模式 | 主机→设备 | 切换EQ模式 | | 0x8B | GET_EQ_MODE | 获取当前EQ模式信息 | 主机→设备 | 读取设备当前EQ模式和名称 | | 0x8C | SET_MODE_GAIN_AND_NAME | 设置模式整体增益和名称 | 主机→设备 | 设置模式整体增益和名称 | @@ -122,6 +124,9 @@ | 监听音量 | 15 (-14dB) | DAC level 15 = 0dB - 14 = -14dB | | EQ参数 | 头文件预设 | 删除所有用户EQ参数,恢复固件内置预设 | | AI降噪 | 开启 | 每次上电默认开启(不保存到Flash) | +| 耳返开关 | 0 (关闭) | ADC→耳机监听通路默认关闭 | +| 麦克风静音 | 0 (未静音) | 麦克风静音状态默认关闭 | +| 监听静音 | 0 (未静音) | 耳机输出静音状态默认关闭 | **设备端处理**: 1. 删除Flash中保存的以下参数文件: @@ -129,6 +134,9 @@ - `mic_vol`(麦克风音量) - `dac_vol`(监听音量) - `footstep`(脚步增强状态) + - `monitor_sw`(耳返开关) + - `mic_mute`(麦克风静音状态) + - `hp_mute`(耳机静音状态) - 所有EQ参数文件(调用eq_flash_clear_all) 2. 设置重启标志,约500ms后设备自动重启 3. 重启后自动加载出厂默认参数 @@ -208,6 +216,68 @@ - **按键切换**:用户按下AI降噪按键时,设备主动上报新强度(关闭时上报0,开启时上报恢复的强度) - **HID SET_AI_NOISE_STRENGTH(0x85)命令成功执行后**,设备主动上报新强度 +### 2.0f 0x87 - SET_MONITOR_SWITCH (设置耳返开关) +**功能**: 设置耳返(ADC→耳机监听)开关,控制是否将麦克风输入实时路由到耳机输出 +**方向**: 主机→设备 +**数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0x87 | 命令码 +2 | 1 | uint8 | 开关值 (0=关闭, 1=开启) +3-62 | 60 | 0x00 | 保留字节 +``` + +**参数说明**: +- **0**: 关闭耳返,ADC数据不路由到耳机输出(NAU88L21 reg 0x0035 = 0x0000) +- **1**: 开启耳返,ADC数据路由到耳机输出(NAU88L21 reg 0x0035 = 0xCFCF,0dB监听音量) +- **注意**: 耳返路由需要麦克风未静音(mic_mute=0)且麦克风增益有效(level≥2)方才生效 + +**设备端处理**: +- 立即更新 NAU88L21 reg 0x0035(耳返音量寄存器) +- 若麦克风当前处于静音状态,则无论耳返开关为何值,reg 0x0035保持0x0000 +- 保存到Flash(`monitor_sw`路径),断电重启后自动恢复 +- 设置成功后用0x88格式响应当前状态 +- 出厂默认:关闭(0) + +**返回值**: +设置成功后设备回复0x88格式响应。 + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0x88 | 同步头2 +3 | 1 | uint8 | 当前耳返开关状态 (0=关闭, 1=开启) +4-62 | 59 | 0x00 | 保留字节 +``` + +### 2.0g 0x88 - GET_MONITOR_SWITCH (获取耳返开关状态) +**功能**: 读取当前耳返开关状态 +**方向**: 主机→设备(请求),设备→主机(响应) +**请求数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0x88 | 命令码 +2-62 | 61 | 0x00 | 保留字节 +``` + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0x88 | 同步头2 +3 | 1 | uint8 | 当前耳返开关状态 (0=关闭, 1=开启) +4-62 | 59 | 0x00 | 保留字节 +``` + ### 2.1 0x8A - SET_EQ_MODE (切换EQ模式) **功能**: 切换当前EQ模式 **方向**: 主机→设备 diff --git a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/sy102_hid_protocol.md b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/sy102_hid_protocol.md index 2a505a0..dbbb83c 100644 --- a/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/sy102_hid_protocol.md +++ b/sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/sy102_hid_protocol.md @@ -11,6 +11,8 @@ | 0x82 | SET_MIC_VOLUME | 设置麦克风增益级别 | 主机→设备 | 设置麦克风PGA增益(0=静音, 1-37=0dB~36dB, 1dB/步) | | 0x83 | GET_MIC_VOLUME | 获取麦克风增益级别 | 主机→设备 | 读取当前麦克风PGA增益级别(0=静音, 1-37=0dB~36dB) | | 0x84 | FACTORY_RESET | 恢复出厂默认设置 | 主机→设备 | 删除Flash中所有已保存参数,设备重启后自动恢复出厂默认值 | +| 0x87 | SET_MONITOR_SWITCH | 设置耳返开关 | 主机→设备 | 设置耳返(ADC→耳机监听)开关(0=关闭,1=开启),保存到Flash | +| 0x88 | GET_MONITOR_SWITCH | 获取耳返开关状态 | 主机→设备 | 读取当前耳返开关状态(0=关闭,1=开启) | | 0x8A | SET_EQ_MODE | 切换EQ模式 | 主机→设备 | 切换EQ模式 | | 0x8B | GET_EQ_MODE | 获取当前EQ模式信息 | 主机→设备 | 读取设备当前EQ模式和名称 | | 0x8C | SET_MODE_GAIN_AND_NAME | 设置模式整体增益和名称 | 主机→设备 | 设置模式整体增益和名称 | @@ -114,6 +116,22 @@ | 监听音量 | 15 (-14dB) | DAC level 15 = 0dB - 14 = -14dB | | EQ参数 | 头文件预设 | 删除所有用户EQ参数,恢复固件内置预设 | | AI降噪 | 开启 | 每次上电默认开启(不保存到Flash) | +| 耳返开关 | 0 (关闭) | ADC→耳机监听通路默认关闭 | +| 麦克风静音 | 0 (未静音) | 麦克风静音状态默认关闭 | +| 监听静音 | 0 (未静音) | 耳机输出静音状态默认关闭 | + +**设备端处理**: +1. 删除Flash中保存的以下参数文件: + - `game_mode`(音效模式) + - `mic_vol`(麦克风音量) + - `dac_vol`(监听音量) + - `footstep`(脚步增强状态) + - `monitor_sw`(耳返开关) + - `mic_mute`(麦克风静音状态) + - `hp_mute`(耳机静音状态) + - 所有EQ参数文件(调用eq_flash_clear_all) +2. 设置重启标志,约500ms后设备自动重启 +3. 重启后自动加载出厂默认参数 **响应数据包格式**: ``` @@ -131,6 +149,67 @@ - 重启后所有参数将恢复为出厂默认值 - 此操作不可撤销 +### 2.0d 0x87 - SET_MONITOR_SWITCH (设置耳返开关) +**功能**: 设置耳返(ADC→耳机监听)开关,控制是否将麦克风输入实时路由到耳机输出 +**方向**: 主机→设备 +**数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0x87 | 命令码 +2 | 1 | uint8 | 开关值 (0=关闭, 1=开启) +3-62 | 60 | 0x00 | 保留字节 +``` + +**参数说明**: +- **0**: 关闭耳返,ADC数据不路由到耳机输出(NAU88L21 reg 0x0035 = 0x0000) +- **1**: 开启耳返,ADC数据路由到耳机输出(NAU88L21 reg 0x0035 = 0xCFCF,0dB监听音量) +- **注意**: 耳返路由需要麦克风未静音(mic_mute=0)且麦克风增益有效(level≥2)方才生效 + +**设备端处理**: +- 立即更新 NAU88L21 reg 0x0035(耳返音量寄存器) +- 若麦克风当前处于静音状态,则无论耳返开关为何值,reg 0x0035保持0x0000 +- 保存到Flash(`monitor_sw`路径),断电重启后自动恢复 +- 设置成功后用0x88格式响应当前状态 + +**返回值**: +设置成功后设备回复0x88格式响应。 + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0x88 | 同步头2 +3 | 1 | uint8 | 当前耳返开关状态 (0=关闭, 1=开启) +4-62 | 59 | 0x00 | 保留字节 +``` + +### 2.0e 0x88 - GET_MONITOR_SWITCH (获取耳返开关状态) +**功能**: 读取当前耳返开关状态 +**方向**: 主机→设备(请求),设备→主机(响应) +**请求数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x77 | 同步头1 +1 | 1 | 0x88 | 命令码 +2-62 | 61 | 0x00 | 保留字节 +``` + +**响应数据包格式**: +``` +字节位置 | 长度 | 内容 | 描述 +---------|------|------|------ +0 | 1 | 0x01 | Report ID +1 | 1 | 0x77 | 同步头1 +2 | 1 | 0x88 | 同步头2 +3 | 1 | uint8 | 当前耳返开关状态 (0=关闭, 1=开启) +4-62 | 59 | 0x00 | 保留字节 +``` + ### 2.1 0x8A - SET_EQ_MODE (切换EQ模式) **功能**: 切换当前EQ模式 **方向**: 主机→设备