sync fps with C3
This commit is contained in:
@@ -21,13 +21,37 @@
|
||||
#include "xua_hid_report.h"
|
||||
#include "nau88c21.h"
|
||||
#include "tile1_clk.h"
|
||||
#include "dfu_upgrade.h"
|
||||
#if MQA_EN
|
||||
#include "MQA_XMOS.h"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "sw_pll.h"
|
||||
#include "dfu_upgrade.h"
|
||||
extern unsigned g_sync_t0_to_t1_cmd;
|
||||
extern unsigned g_sync_t0_to_t1_data;
|
||||
/* 改动原因:tile0/tile1 内存不共享,sync 第二数据字用于上电经 0x03 传递 FPS 三模块使能 */
|
||||
extern unsigned g_sync_t0_to_t1_data2;
|
||||
extern unsigned g_fps_game_select;
|
||||
extern unsigned g_fps_level_select;
|
||||
extern unsigned g_fps_drc_enable;
|
||||
extern unsigned g_fps_sub_enable;
|
||||
extern unsigned g_fps_eq_enable;
|
||||
extern unsigned g_fps_drc_mode;
|
||||
#if XMOS_FPS_EN
|
||||
#include "fps_eq_sync.h"
|
||||
/* 改动原因:HID 0xBF/0xB5/0xBD/0xB7/0xB9经tile同步后调用FPS库接口,不在DSP任务内轮询 */
|
||||
void fps_apply_game_level_select(void);
|
||||
void fps_apply_module_enable(void);
|
||||
void fps_apply_drc_mode(void);
|
||||
void fps_apply_eq_mode(void);
|
||||
void fps_apply_eq_band_gain(unsigned band, int16_t gain);
|
||||
void fps_eq_boot_publish_to_tile1(void);
|
||||
void fps_drc_boot_sync_to_tile1(void);
|
||||
void fps_boot_load_from_flash(void);
|
||||
void sync_t0_promote_pending_to_tile1(void);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#define TIMER_PERIOD 2000000
|
||||
@@ -529,8 +553,52 @@ static void codec_init_on_i2c(client interface i2c_master_if i2c)
|
||||
void save_value(unsigned char * unsafe path, unsigned char value);
|
||||
unsigned char load_value(unsigned char * unsafe path);
|
||||
#define C1_MODE_INFO_PATH "c1_mode"
|
||||
|
||||
#if XMOS_FPS_EN
|
||||
/* 改动原因:将 g_sync_t0_to_t1_cmd 经 c_app_sync 发到 tile1;供定时器与上电 flush 复用 */
|
||||
static int tile0_send_one_sync_to_tile1(chanend c_app_sync)
|
||||
{
|
||||
unsigned sync_cmd = 0;
|
||||
|
||||
GET_SHARED_GLOBAL(sync_cmd, g_sync_t0_to_t1_cmd);
|
||||
if (sync_cmd == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned sync_data = 0;
|
||||
unsigned sync_data2 = 0;
|
||||
GET_SHARED_GLOBAL(sync_data, g_sync_t0_to_t1_data);
|
||||
GET_SHARED_GLOBAL(sync_data2, g_sync_t0_to_t1_data2);
|
||||
|
||||
c_app_sync <: (unsigned)(0x80 | sync_cmd);
|
||||
c_app_sync <: sync_data;
|
||||
c_app_sync <: sync_data2;
|
||||
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, 0);
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, 0);
|
||||
sync_t0_promote_pending_to_tile1();
|
||||
debug_printf("tile0: Sent sync 0x%02X to tile1, data=%u data2=%u\n",
|
||||
sync_cmd, sync_data, sync_data2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 改动原因:上电 fps_boot_load 会排队 0x03+0x0C+0x09+五包0x0B,须立即 drain 而非等 20ms 定时器 */
|
||||
static void tile0_flush_sync_queue_to_tile1(chanend c_app_sync)
|
||||
{
|
||||
unsigned sync_cmd = 0;
|
||||
|
||||
do {
|
||||
while (tile0_send_one_sync_to_tile1(c_app_sync) != 0) {}
|
||||
sync_t0_promote_pending_to_tile1();
|
||||
GET_SHARED_GLOBAL(sync_cmd, g_sync_t0_to_t1_cmd);
|
||||
} while (sync_cmd != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 改动原因:c_dfu 仅接收 FIRMWARE_UPGRADE_START,在此线程执行 handle_firmware_upgrade_start */
|
||||
void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, client interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_erase, streaming chanend c_dfu)
|
||||
void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu, chanend c_app_sync)
|
||||
{
|
||||
unsigned cmd;
|
||||
int value;
|
||||
@@ -683,6 +751,14 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
|
||||
old_adc_vol = boot_effective_adc_vol;
|
||||
}
|
||||
|
||||
#if XMOS_FPS_EN
|
||||
/* 改动原因:C1 无 UART/MCU,不经过 c_uart_sync;上电直接在 tile0 从 Flash 恢复 FPS 并 sync 到 tile1 */
|
||||
/* 改动原因:tile1 app_control_slave 有约 100ms 延时,此处再等 50ms 确保 c_sync 已进 select */
|
||||
delay_milliseconds(50);
|
||||
fps_boot_load_from_flash();
|
||||
tile0_flush_sync_queue_to_tile1(c_app_sync);
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
{
|
||||
select
|
||||
@@ -1091,6 +1167,10 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
|
||||
|
||||
#if ((HID_CONTROLS == 1) && (EQ_EN == 1))
|
||||
|
||||
// 改动原因:检测tile0到tile1的同步命令,如果有命令则通过channel发送到tile1
|
||||
#if XMOS_FPS_EN
|
||||
(void)tile0_send_one_sync_to_tile1(c_app_sync);
|
||||
#endif
|
||||
// 改动原因:检测增益模式变化请求,当g_request_gain_mode != -1且与当前模式不同时应用
|
||||
{
|
||||
unsigned request_gain_mode, gain_mode;
|
||||
@@ -1187,7 +1267,8 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
|
||||
g_last_mute_switch = current_mute;
|
||||
}
|
||||
|
||||
// 改动原因:规格DNR无指示灯,按键长按切换后通过HID 0xB5主动上报APP(与0xB4监听开关上报方式一致)。
|
||||
// 改动原因:规格DNR无指示灯,按键长按切换后通过HID主动上报APP
|
||||
// 改动原因:XMOS_FPS_EN 时 0xB5 为 SET_FPS_MODULE_ENABLE,DNR 上报改用 0xC5
|
||||
{
|
||||
unsigned current_dnr;
|
||||
GET_SHARED_GLOBAL(current_dnr, g_dnr_enable);
|
||||
@@ -1197,12 +1278,16 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
|
||||
{
|
||||
unsigned char * unsafe reportPtr = g_hid_pass_data;
|
||||
reportPtr[0] = 0x77;
|
||||
#if XMOS_FPS_EN
|
||||
reportPtr[1] = 0xC5; // GET_DNR_ENABLE(FPS 构建下与 0xB5 区分)
|
||||
#else
|
||||
reportPtr[1] = 0xB5; // GET_DNR_ENABLE
|
||||
#endif
|
||||
reportPtr[2] = (unsigned char)current_dnr;
|
||||
for (int i = 3; i < 63; i++) reportPtr[i] = 0x00;
|
||||
hidSetChangePending(0x1);
|
||||
}
|
||||
debug_printf("DNR enable changed: %d -> %d, HID 0xB5 report prepared\n", g_last_dnr_enable, current_dnr);
|
||||
debug_printf("DNR enable changed: %d -> %d, HID report prepared\n", g_last_dnr_enable, current_dnr);
|
||||
}
|
||||
g_last_dnr_enable = current_dnr;
|
||||
}
|
||||
@@ -1570,6 +1655,11 @@ void AudioHwRemote2(streaming chanend c, client interface i2c_master_if i2c, cli
|
||||
}
|
||||
}
|
||||
|
||||
// 改动原因:用于tile0到tile1同步命令的共享变量
|
||||
unsigned g_sync_t0_to_t1_cmd = 0; // 0=无命令,0x01=SET_GAME_MODE
|
||||
unsigned g_sync_t0_to_t1_data = 0; // 命令数据
|
||||
unsigned g_sync_t0_to_t1_data2 = 0; // 改动原因:sync 第二数据字,上电 0x03 携带 FPS 模块使能
|
||||
|
||||
extern void SetKeyFlag(unsigned x);
|
||||
void flag_handler()
|
||||
{
|
||||
@@ -1588,14 +1678,14 @@ void flag_handler()
|
||||
}
|
||||
|
||||
|
||||
void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_erase, streaming chanend c_dfu)
|
||||
void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu, chanend c_app_sync)
|
||||
{
|
||||
i2c_master_if i2c[1];
|
||||
|
||||
par
|
||||
{
|
||||
i2c_master(i2c, 1, p_scl, p_sda, 100);
|
||||
AudioHwRemote2(c, i2c[0], i_c1_led_ctrl, c_erase, c_dfu);
|
||||
AudioHwRemote2(c, i2c[0], i_c1_led_ctrl, c_dfu, c_app_sync);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1985,7 +2075,7 @@ static inline void apply_c1_panel_leds(unsigned mode_led_color_idx, unsigned mic
|
||||
p_mode_led_blue <: (mode_blue ? 0 : 1);
|
||||
}
|
||||
|
||||
void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl)
|
||||
void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_sync)
|
||||
{
|
||||
// 改动原因:tile1 先于 tile0 运行,上电先把硬件灯全灯且不调用 apply,避免用占位 mic/mode 组合误亮;shadow 置为全灯灯电平便于首包 set_* 时 apply 与端口一致。
|
||||
unsigned led_shadow = 0xF;
|
||||
@@ -2022,6 +2112,154 @@ void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl)
|
||||
mic_mute_switch = (mute_state != 0) ? 1 : 0;
|
||||
apply_c1_panel_leds(mode_led_color_idx, mic_mute_switch, led_shadow);
|
||||
break;
|
||||
// 改动原因:接收从tile0通过channel发送的同步命令(命令码 >= 0x80表示tile0到tile1的命令)
|
||||
case c_sync :> unsigned sync_cmd:
|
||||
if ((sync_cmd & 0x80) != 0) {
|
||||
// 这是从tile0发送的命令
|
||||
unsigned sync_data1, sync_data2;
|
||||
c_sync :> sync_data1;
|
||||
c_sync :> sync_data2;
|
||||
|
||||
unsigned actual_cmd = sync_cmd & 0x7F; // 去掉0x80标志
|
||||
|
||||
if (actual_cmd == 0x01) { // SYNC_CMD_T0_TO_T1_SET_GAME_MODE
|
||||
debug_printf("tile1: Received SET_GAME_MODE command from tile0 via channel, game_mode=%d\n", sync_data1);
|
||||
// 改动原因:调用UART 0x5A命令处理函数,将命令透传给MCU
|
||||
#if EQ_EN
|
||||
process_uart_set_game_mode((uint8_t)sync_data1);
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x02) { // SYNC_CMD_T0_TO_T1_SET_UAC_MODE
|
||||
debug_printf("tile1: Received SET_UAC_MODE command from tile0 via channel, uac_mode=%d\n", sync_data1);
|
||||
// 改动原因:调用UART 0x51命令处理函数,将命令透传给MCU
|
||||
#if EQ_EN
|
||||
process_uart_set_uac_mode((uint8_t)sync_data1);
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x03) { // SYNC_CMD_T0_TO_T1_SET_FPS_XMOS_GAME_SELECT
|
||||
// 改动原因:sync_data1中同时打包了game和level,低8位为game,高8位为level
|
||||
unsigned game_select = (sync_data1 & 0xFF);
|
||||
unsigned level_select = ((sync_data1 >> 8) & 0xFF);
|
||||
if (game_select > 2) {
|
||||
game_select = 0;
|
||||
}
|
||||
// 改动原因:tile1 与 tile0/协议一致,level 有效 0-4;无效时回默认 2(与 0xBF 一致)
|
||||
if (level_select > 4) {
|
||||
level_select = 2;
|
||||
}
|
||||
debug_printf("tile1: Received SET_FPS_XMOS_GAME_SELECT command from tile0 via channel, game=%u level=%u\n",
|
||||
game_select, level_select);
|
||||
// 改动原因:更新全局变量后由fps_apply_game_level_select调用fps_xmos_xc_game_select,DSP任务内不再轮询
|
||||
SET_SHARED_GLOBAL(g_fps_game_select, game_select);
|
||||
SET_SHARED_GLOBAL(g_fps_level_select, level_select);
|
||||
#if XMOS_FPS_EN
|
||||
fps_apply_game_level_select();
|
||||
/* 改动原因:tile0/tile1 内存不共享,上电使能经 sync data2(bit31) 下发后再 apply */
|
||||
if ((sync_data2 & (1u << 31)) != 0) {
|
||||
unsigned drc_enable = (sync_data2 & 0xFF);
|
||||
unsigned fps_sub_enable = ((sync_data2 >> 8) & 0xFF);
|
||||
unsigned eq_enable = ((sync_data2 >> 16) & 0xFF);
|
||||
if (drc_enable > 1) { drc_enable = 0; }
|
||||
if (fps_sub_enable > 1) { fps_sub_enable = 1; }
|
||||
if (eq_enable > 1) { eq_enable = 0; }
|
||||
debug_printf("tile1: boot FPS module enable from sync drc=%u fps=%u eq=%u\n",
|
||||
drc_enable, fps_sub_enable, eq_enable);
|
||||
SET_SHARED_GLOBAL(g_fps_drc_enable, drc_enable);
|
||||
SET_SHARED_GLOBAL(g_fps_sub_enable, fps_sub_enable);
|
||||
SET_SHARED_GLOBAL(g_fps_eq_enable, eq_enable);
|
||||
}
|
||||
fps_apply_module_enable();
|
||||
/* 改动原因:fps_eq 由后续排队 sync 0x09+0x0B 应用,此处不读 tile1 默认 pack */
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x09) { // SYNC_CMD_T0_TO_T1_SET_FPS_EQ_MODE
|
||||
unsigned mode = (sync_data1 & 0xFF);
|
||||
if (mode >= 5) {
|
||||
mode = 0;
|
||||
}
|
||||
debug_printf("tile1: SET_FPS_EQ_MODE %u\n", mode);
|
||||
SET_SHARED_GLOBAL(g_fps_eq_mode, mode);
|
||||
/* 改动原因:增益由紧随的 0x0B 包同步,末包 apply 时再 fps_apply_eq_mode */
|
||||
}
|
||||
else if (actual_cmd == 0x0B) { // SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK
|
||||
unsigned pack_idx = (sync_data1 & 0xFF);
|
||||
unsigned apply_eq = ((sync_data1 >> 8) & 0xFF);
|
||||
int32_t pack_val = (int32_t)sync_data2;
|
||||
|
||||
if (pack_idx < 5) {
|
||||
debug_printf("tile1: SET_FPS_EQ_PACK idx=%u apply=%u\n", pack_idx, apply_eq);
|
||||
switch (pack_idx) {
|
||||
case 0: SET_SHARED_GLOBAL(g_fps_eq_pack0, pack_val); break;
|
||||
case 1: SET_SHARED_GLOBAL(g_fps_eq_pack1, pack_val); break;
|
||||
case 2: SET_SHARED_GLOBAL(g_fps_eq_pack2, pack_val); break;
|
||||
case 3: SET_SHARED_GLOBAL(g_fps_eq_pack3, pack_val); break;
|
||||
case 4: SET_SHARED_GLOBAL(g_fps_eq_pack4, pack_val); break;
|
||||
default: break;
|
||||
}
|
||||
#if XMOS_FPS_EN
|
||||
if (apply_eq != 0) {
|
||||
fps_apply_eq_mode();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (actual_cmd == 0x0A) { // SYNC_CMD_T0_TO_T1_SET_FPS_EQ_BAND_GAIN
|
||||
unsigned band = (sync_data1 & 0xFF);
|
||||
int16_t gain = (int16_t)((sync_data1 >> 8) & 0xFFFF);
|
||||
debug_printf("tile1: SET_FPS_EQ_BAND band=%u gain=%d\n", band, (int)gain);
|
||||
#if XMOS_FPS_EN
|
||||
fps_apply_eq_band_gain(band, gain);
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x08) { // SYNC_CMD_T0_TO_T1_SET_FPS_MODULE_ENABLE
|
||||
unsigned drc_enable = (sync_data1 & 0xFF);
|
||||
unsigned fps_sub_enable = ((sync_data1 >> 8) & 0xFF);
|
||||
unsigned eq_enable = ((sync_data1 >> 16) & 0xFF);
|
||||
/* 改动原因:sync 包无效字节时与上电默认一致:DRC/fps_eq 关,FPS 开 */
|
||||
if (drc_enable > 1) { drc_enable = 0; }
|
||||
if (fps_sub_enable > 1) { fps_sub_enable = 1; }
|
||||
if (eq_enable > 1) { eq_enable = 0; }
|
||||
debug_printf("tile1: SET_FPS_MODULE_ENABLE drc=%u fps=%u eq=%u\n",
|
||||
drc_enable, fps_sub_enable, eq_enable);
|
||||
SET_SHARED_GLOBAL(g_fps_drc_enable, drc_enable);
|
||||
SET_SHARED_GLOBAL(g_fps_sub_enable, fps_sub_enable);
|
||||
SET_SHARED_GLOBAL(g_fps_eq_enable, eq_enable);
|
||||
#if XMOS_FPS_EN
|
||||
fps_apply_module_enable();
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x0C) { // SYNC_CMD_T0_TO_T1_SET_FPS_DRC_MODE
|
||||
unsigned drc_mode = (sync_data1 & 0xFF);
|
||||
/* 改动原因:mode仅0=low、1=high,无效时回默认0 */
|
||||
if (drc_mode > 1) {
|
||||
drc_mode = 0;
|
||||
}
|
||||
debug_printf("tile1: SET_FPS_DRC_MODE mode=%u\n", drc_mode);
|
||||
SET_SHARED_GLOBAL(g_fps_drc_mode, drc_mode);
|
||||
#if XMOS_FPS_EN
|
||||
fps_apply_drc_mode();
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x04) { // SYNC_CMD_T0_TO_T1_SET_INPUT_SOURCE
|
||||
debug_printf("tile1: Received SET_INPUT_SOURCE command from tile0 via channel, input_source=%d\n", sync_data1);
|
||||
#if EQ_EN
|
||||
process_uart_set_input_source((uint8_t)sync_data1);
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x05) { // SYNC_CMD_T0_TO_T1_SET_MUTE_SWITCH
|
||||
debug_printf("tile1: Received SET_MUTE_SWITCH command from tile0 via channel, mute=%d\n", sync_data1);
|
||||
#if EQ_EN
|
||||
process_uart_set_mute_switch((uint8_t)sync_data1);
|
||||
#endif
|
||||
}
|
||||
else if (actual_cmd == 0x07) { // SYNC_CMD_T0_TO_T1_SET_LISTEN_SWITCH
|
||||
debug_printf("tile1: Received SET_LISTEN_SWITCH command from tile0 via channel, listen=%d\n", sync_data1);
|
||||
#if EQ_EN
|
||||
process_uart_set_listen_switch((uint8_t)sync_data1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,59 +100,4 @@ void dsp_main (chanend_t c_data , chanend_t cc_br_eof) {
|
||||
#endif
|
||||
}
|
||||
|
||||
extern uint8_t opt_key_read(uint8_t key[], unsigned offset);
|
||||
extern unsigned dnr_init_flag;
|
||||
void validate_algo(chanend_t c_validate)
|
||||
{
|
||||
#if BR_ALGO
|
||||
uint8_t uid[20] = {0};
|
||||
char hex_string[41] = {0};
|
||||
while (!dnr_init_flag) {
|
||||
delay_milliseconds(1);
|
||||
}
|
||||
opt_key_read(uid, 2);
|
||||
delay_milliseconds(10);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
sprintf(hex_string + i * 2, "%02x", uid[i]);
|
||||
}
|
||||
hex_string[40] = '\0';
|
||||
flash_cmd_init();
|
||||
int res = br_validate(c_validate, hex_string);
|
||||
flash_cmd_deinit();
|
||||
debug_printf("Validate status: %d\n", res); // check validate status
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void set_core_high_priority_on(void);
|
||||
void br_dsp_proc_task(chanend_t c_validate, chanend_t cc_br_eof)
|
||||
{
|
||||
#if BR_ALGO
|
||||
set_core_high_priority_on();
|
||||
int channel_flag = 4;
|
||||
int is_br_on = 1;
|
||||
|
||||
int cnt = 0;
|
||||
|
||||
br_init(c_validate);
|
||||
int validate = br_get_validate_status();
|
||||
debug_printf("After Validate status: %d\n", validate); // check validate status
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
int tmp;
|
||||
int cur_pos;
|
||||
chan_in_buf_word (cc_br_eof, &tmp, 1);
|
||||
cur_pos = pos == 0 ? 1 : 0;
|
||||
|
||||
if (channel_flag <= 2) {
|
||||
is_br_on = 0;
|
||||
}
|
||||
else {
|
||||
is_br_on = 1;
|
||||
}
|
||||
br_apply(dsp_br_input_buf[cur_pos], dsp_br_out_buf[cur_pos], is_br_on);
|
||||
channel_flag = br_get_channel_flag();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -590,6 +590,17 @@ unsigned char handle_firmware_upgrade_erase(uint8_t data[], uint16_t len)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// 改动原因:HID 0xAE 设备重启;补全缺失的 handle_device_reboot,调用 eq.c 中已有的 device_reboot() 避免链接错误
|
||||
unsigned char handle_device_reboot(uint8_t data[], uint16_t len)
|
||||
{
|
||||
(void)data;
|
||||
(void)len;
|
||||
debug_printf("Firmware upgrade DEVICE_REBOOT (0xAE)\n");
|
||||
device_reboot();
|
||||
while (1);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// 固件升级主处理函数
|
||||
// 改动原因:处理所有HID固件升级命令,分发到相应的处理函数
|
||||
// 参数:
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -7,15 +7,15 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NUM_EQ_MODES 10
|
||||
#define NUM_EQ_MODES 15
|
||||
#define NUM_EQ_CHANS 2
|
||||
#define MAX_EQ_BANDS 8
|
||||
#define EQ_DISABLED_MODE 10 // 禁用EQ的模式编号
|
||||
#define EQ_PRESET_MODE_MIN 0 // 预设模式最小编号
|
||||
#define EQ_PRESET_MODE_MAX 6 // 预设模式最大编号(preset1-preset6)
|
||||
#define EQ_USER_MODE_MIN 7 // 用户模式最小编号
|
||||
#define EQ_USER_MODE_MAX 9 // 用户模式最大编号(user 1-4)
|
||||
#define EQ_MODE_MAX (NUM_EQ_MODES) // 模式最大编号(user 1-4)
|
||||
#define EQ_DISABLED_MODE 15 // 禁用EQ的模式编号(改动原因:模式扩展至15后,禁用模式编号同步改为15)
|
||||
#define EQ_PRESET_MODE_MIN 0 // 预设模式最小编号
|
||||
#define EQ_PRESET_MODE_MAX 12 // 预设模式最大编号(0-12共13个预设,含音乐与游戏曲线)
|
||||
#define EQ_USER_MODE_MIN 13 // 用户模式最小编号(改动原因:仅保留2个用户自定义模式)
|
||||
#define EQ_USER_MODE_MAX 14 // 用户模式最大编号(user 1-2)
|
||||
#define EQ_MODE_MAX (NUM_EQ_MODES) // 有效模式上界(0-14为可用模式,15为禁用)
|
||||
|
||||
|
||||
// Filter type definition
|
||||
@@ -130,10 +130,6 @@ uint8_t process_uart_get_led_status(uint8_t led_index, uint8_t * unsafe response
|
||||
uint8_t process_uart_get_led_count(uint8_t * unsafe response, uint8_t response_size);
|
||||
uint8_t process_uart_get_uac_mode_info(uint8_t * unsafe response, uint8_t response_size);
|
||||
void process_uart_set_uac_mode(uint8_t uac_mode);
|
||||
void process_uart_set_input_source(uint8_t input_source); // 设置输入源(0=USB,1=OPT,2=COAX),HID 0xB0透传MCU
|
||||
void process_uart_set_mute_switch(uint8_t mute); // 设置静音开关(0=关,1=开),HID 0xB1透传MCU
|
||||
void process_uart_set_listen_switch(uint8_t listen); // 设置监听开关(0=关,1=开),HID 0xB3透传MCU
|
||||
void process_uart_send_get_mute_request(void); // 向MCU发送0x5F获取静音请求
|
||||
uint8_t process_uart_get_current_uac_mode(uint8_t * unsafe response, uint8_t response_size);
|
||||
uint8_t process_uart_set_eq_enable(uint8_t enable);
|
||||
uint8_t process_uart_get_eq_enable_response(uint8_t result, uint8_t enable, uint8_t * unsafe response, uint8_t response_size);
|
||||
@@ -146,6 +142,11 @@ uint8_t process_uart_get_filter_mode(uint8_t * unsafe response, uint8_t response
|
||||
void process_uart_set_game_mode(uint8_t game_mode);
|
||||
uint8_t process_uart_get_game_mode(uint8_t * unsafe response, uint8_t response_size);
|
||||
uint8_t process_uart_get_firmware_version(uint8_t * unsafe response, uint8_t response_size);
|
||||
/* 改动原因:添加 0xB0-0xB4 相关 UART 处理与静音值回传(XC 侧声明),HID 在 tile0、UART 在 tile1 时由 tile1 调用 */
|
||||
void process_uart_set_input_source(uint8_t input_source);
|
||||
void process_uart_set_mute_switch(uint8_t mute);
|
||||
void process_uart_send_get_mute_request(void);
|
||||
void process_uart_set_listen_switch(uint8_t listen);
|
||||
|
||||
#else
|
||||
// 独立的增益和名称设置/获取函数
|
||||
@@ -171,10 +172,6 @@ uint8_t process_uart_get_led_status(uint8_t led_index, uint8_t *response, uint8_
|
||||
uint8_t process_uart_get_led_count(uint8_t *response, uint8_t response_size);
|
||||
uint8_t process_uart_get_uac_mode_info(uint8_t *response, uint8_t response_size);
|
||||
void process_uart_set_uac_mode(uint8_t uac_mode);
|
||||
void process_uart_set_input_source(uint8_t input_source); // 设置输入源(0=USB,1=OPT,2=COAX),HID 0xB0透传MCU
|
||||
void process_uart_set_mute_switch(uint8_t mute); // 设置静音开关(0=关,1=开),HID 0xB1透传MCU
|
||||
void process_uart_set_listen_switch(uint8_t listen); // 设置监听开关(0=关,1=开),HID 0xB3透传MCU
|
||||
void process_uart_send_get_mute_request(void); // 向MCU发送0x5F获取静音请求
|
||||
uint8_t process_uart_get_current_uac_mode(uint8_t *response, uint8_t response_size);
|
||||
uint8_t process_uart_set_eq_enable(uint8_t enable);
|
||||
uint8_t process_uart_get_eq_enable_response(uint8_t result, uint8_t enable, uint8_t *response, uint8_t response_size);
|
||||
@@ -187,7 +184,11 @@ uint8_t process_uart_get_filter_mode(uint8_t *response, uint8_t response_size);
|
||||
void process_uart_set_game_mode(uint8_t game_mode);
|
||||
uint8_t process_uart_get_game_mode(uint8_t *response, uint8_t response_size);
|
||||
uint8_t process_uart_get_firmware_version(uint8_t *response, uint8_t response_size);
|
||||
|
||||
/* 改动原因:添加 0xB0-0xB4 相关 UART 处理与静音值回传(C 侧声明) */
|
||||
void process_uart_set_input_source(uint8_t input_source);
|
||||
void process_uart_set_mute_switch(uint8_t mute);
|
||||
void process_uart_send_get_mute_request(void);
|
||||
void process_uart_set_listen_switch(uint8_t listen);
|
||||
|
||||
#endif
|
||||
void init_mode_info(void);
|
||||
|
||||
@@ -53,10 +53,23 @@ from filter_utils import (BiquadFilterCalculator, make_biquad_bypass, make_biqua
|
||||
|
||||
# 常量定义
|
||||
MAX_EQ_BANDS = 8 # 最大EQ滤波器数量 (0-7)
|
||||
NUM_EQ_MODES = 10 # EQ模式数量
|
||||
EQ_DISABLED_MODE = 10 # 禁用EQ的模式编号
|
||||
NUM_EQ_MODES = 15 # EQ模式数量(改动原因:13预设+2用户,共15模式)
|
||||
EQ_DISABLED_MODE = 15 # 禁用EQ的模式编号(改动原因:与NUM_EQ_MODES对齐)
|
||||
# 预设模式0-12,用户模式13-14
|
||||
EQ_PRESET_MODE_MAX = 12
|
||||
EQ_USER_MODE_MIN = 13
|
||||
EQ_USER_MODE_MAX = 14
|
||||
|
||||
# HID 固件升级命令码(使用命令名代替裸命令码)
|
||||
# 模式下拉列表显示名称(改动原因:与固件default_names及新增游戏曲线一致)
|
||||
MODE_COMBO_ITEMS = [
|
||||
"JAZZ(0)", "POP(1)", "ROCK(2)", "CLASIC(3)",
|
||||
"暗区突围(4)", "3A Game(5)", "战地6(6)",
|
||||
"APEX(7)", "和平精英(8)", "逃离塔科夫(9)",
|
||||
"穿越火线(10)", "守望先锋(11)", "永劫无望(12)",
|
||||
"用户模式1(13)", "用户模式2(14)", "禁用EQ"
|
||||
]
|
||||
|
||||
# HID 固件升级命令码(与 eq_hid_protocol_ds1 一致,0xA7-0xAE)
|
||||
FIRMWARE_UPGRADE_START = 0xA7 # 开始固件升级
|
||||
FIRMWARE_UPGRADE_DATA = 0xA8 # 传输固件数据块
|
||||
FIRMWARE_UPGRADE_END = 0xA9 # 结束固件升级
|
||||
@@ -65,6 +78,20 @@ FIRMWARE_UPGRADE_ABORT = 0xAB # 中止固件升级
|
||||
FIRMWARE_UPGRADE_ERASE = 0xAC # 擦除现有升级镜像
|
||||
DEVICE_REBOOT = 0xAE # 设备重启(通用命令)
|
||||
|
||||
# FPS XMOS 命令(改动原因:0xA7/0xA8 保留固件升级;game/level 放在 DRC 0xBD/0xBE 之后为 0xBF/0xC0)
|
||||
SET_FPS_XMOS_GAME_SELECT = 0xBF
|
||||
GET_FPS_XMOS_GAME_SELECT = 0xC0
|
||||
SET_FPS_MODULE_ENABLE = 0xB5
|
||||
GET_FPS_MODULE_ENABLE = 0xB6
|
||||
SET_FPS_EQ_MODE = 0xB7
|
||||
GET_FPS_EQ_MODE = 0xB8
|
||||
SET_FPS_EQ_BAND_GAIN = 0xB9
|
||||
GET_FPS_EQ_BAND_GAIN = 0xBA
|
||||
SET_FPS_EQ_MODE_NAME = 0xBB
|
||||
GET_FPS_EQ_MODE_NAME = 0xBC
|
||||
SET_FPS_DRC_MODE = 0xBD
|
||||
GET_FPS_DRC_MODE = 0xBE
|
||||
|
||||
class BandFilter(QGroupBox):
|
||||
"""单个滤波器带控件"""
|
||||
def __init__(self, band_id, parent=None):
|
||||
@@ -536,7 +563,7 @@ class EQDesigner(QMainWindow):
|
||||
mode_layout = QFormLayout(mode_group)
|
||||
self.mode_label = QLabel("音效模式:")
|
||||
self.mode_combo = QComboBox()
|
||||
self.mode_combo.addItems(["预设模式1", "预设模式2", "预设模式3", "预设模式4", "预设模式5", "预设模式6", "用户模式1", "用户模式2", "用户模式3", "bypass", "禁用EQ"])
|
||||
self.mode_combo.addItems(MODE_COMBO_ITEMS)
|
||||
self.mode_combo.currentIndexChanged.connect(self.on_mode_changed)
|
||||
mode_layout.addRow(self.mode_label, self.mode_combo)
|
||||
|
||||
@@ -912,6 +939,129 @@ class EQDesigner(QMainWindow):
|
||||
listen_switch_layout.addRow(listen_switch_btn_layout)
|
||||
left_content_layout.addWidget(listen_switch_group)
|
||||
|
||||
# FPS XMOS 算法控制(HID 0xBF/0xC0 游戏档位,0xB5/0xB6 三子模块使能)
|
||||
fps_xmos_group = QGroupBox("FPS算法控制")
|
||||
self.ui_groups['fps_xmos'] = fps_xmos_group
|
||||
fps_xmos_layout = QFormLayout(fps_xmos_group)
|
||||
|
||||
fps_game_layout = QHBoxLayout()
|
||||
self.fps_xmos_game_combo = QComboBox()
|
||||
self.fps_xmos_game_combo.addItem("CS2 (0)", 0)
|
||||
self.fps_xmos_game_combo.addItem("PUBG (1)", 1)
|
||||
self.fps_xmos_game_combo.addItem("DELTA (2)", 2)
|
||||
fps_game_layout.addWidget(QLabel("游戏类型:"))
|
||||
fps_game_layout.addWidget(self.fps_xmos_game_combo)
|
||||
fps_xmos_layout.addRow(fps_game_layout)
|
||||
|
||||
fps_level_layout = QHBoxLayout()
|
||||
# 改动原因:与固件默认增益档位一致,默认 level=2
|
||||
self.fps_xmos_level_spin = QSpinBox()
|
||||
self.fps_xmos_level_spin.setRange(0, 4)
|
||||
self.fps_xmos_level_spin.setValue(2)
|
||||
fps_level_layout.addWidget(QLabel("增益档位(0-4):"))
|
||||
fps_level_layout.addWidget(self.fps_xmos_level_spin)
|
||||
fps_xmos_layout.addRow(fps_level_layout)
|
||||
|
||||
fps_game_btn_layout = QHBoxLayout()
|
||||
self.set_fps_xmos_game_btn = QPushButton("设置游戏/档位 (0xBF)")
|
||||
self.set_fps_xmos_game_btn.clicked.connect(self.on_set_fps_xmos_game_select)
|
||||
self.get_fps_xmos_game_btn = QPushButton("查询档位 (0xC0)")
|
||||
self.get_fps_xmos_game_btn.clicked.connect(self.on_get_fps_xmos_game_select)
|
||||
fps_game_btn_layout.addWidget(self.set_fps_xmos_game_btn)
|
||||
fps_game_btn_layout.addWidget(self.get_fps_xmos_game_btn)
|
||||
fps_xmos_layout.addRow(fps_game_btn_layout)
|
||||
|
||||
self.fps_xmos_game_status_label = QLabel("游戏档位: 未查询")
|
||||
fps_xmos_layout.addRow("状态:", self.fps_xmos_game_status_label)
|
||||
|
||||
# 改动原因:与固件默认一致——FPS 主处理开,DRC/fps_eq 关
|
||||
self.fps_drc_enable_combo = QComboBox()
|
||||
self.fps_drc_enable_combo.addItems(["关 (0)", "开 (1)"])
|
||||
self.fps_drc_enable_combo.setCurrentIndex(0)
|
||||
fps_xmos_layout.addRow("DRC:", self.fps_drc_enable_combo)
|
||||
|
||||
self.fps_sub_enable_combo = QComboBox()
|
||||
self.fps_sub_enable_combo.addItems(["关 (0)", "开 (1)"])
|
||||
self.fps_sub_enable_combo.setCurrentIndex(1)
|
||||
fps_xmos_layout.addRow("FPS主处理:", self.fps_sub_enable_combo)
|
||||
|
||||
self.fps_eq_enable_combo = QComboBox()
|
||||
self.fps_eq_enable_combo.addItems(["关 (0)", "开 (1)"])
|
||||
self.fps_eq_enable_combo.setCurrentIndex(0)
|
||||
fps_xmos_layout.addRow("fps_eq:", self.fps_eq_enable_combo)
|
||||
|
||||
fps_module_btn_layout = QHBoxLayout()
|
||||
self.set_fps_module_enable_btn = QPushButton("设置使能 (0xB5)")
|
||||
self.set_fps_module_enable_btn.clicked.connect(self.on_set_fps_module_enable)
|
||||
self.get_fps_module_enable_btn = QPushButton("读取使能 (0xB6)")
|
||||
self.get_fps_module_enable_btn.clicked.connect(self.on_get_fps_module_enable)
|
||||
fps_module_btn_layout.addWidget(self.set_fps_module_enable_btn)
|
||||
fps_module_btn_layout.addWidget(self.get_fps_module_enable_btn)
|
||||
fps_xmos_layout.addRow(fps_module_btn_layout)
|
||||
|
||||
# 改动原因:DRC压缩模式与DRC使能独立,HID 0xBD/0xBE,默认0=low柔和压缩
|
||||
self.fps_drc_mode_combo = QComboBox()
|
||||
self.fps_drc_mode_combo.addItem("low 柔和压缩 (0)", 0)
|
||||
self.fps_drc_mode_combo.addItem("high 强力压缩 (1)", 1)
|
||||
self.fps_drc_mode_combo.setCurrentIndex(0)
|
||||
fps_xmos_layout.addRow("DRC压缩模式:", self.fps_drc_mode_combo)
|
||||
fps_drc_mode_btn_layout = QHBoxLayout()
|
||||
self.set_fps_drc_mode_btn = QPushButton("设置DRC模式 (0xBD)")
|
||||
self.set_fps_drc_mode_btn.clicked.connect(self.on_set_fps_drc_mode)
|
||||
self.get_fps_drc_mode_btn = QPushButton("读取DRC模式 (0xBE)")
|
||||
self.get_fps_drc_mode_btn.clicked.connect(self.on_get_fps_drc_mode)
|
||||
fps_drc_mode_btn_layout.addWidget(self.set_fps_drc_mode_btn)
|
||||
fps_drc_mode_btn_layout.addWidget(self.get_fps_drc_mode_btn)
|
||||
fps_xmos_layout.addRow(fps_drc_mode_btn_layout)
|
||||
|
||||
self.fps_eq_mode_spin = QSpinBox()
|
||||
self.fps_eq_mode_spin.setRange(0, 4)
|
||||
self.fps_eq_mode_spin.setValue(0)
|
||||
fps_xmos_layout.addRow("fps_eq模式(0-4):", self.fps_eq_mode_spin)
|
||||
fps_eq_mode_btn = QHBoxLayout()
|
||||
self.set_fps_eq_mode_btn = QPushButton("设置模式 (0xB7)")
|
||||
self.set_fps_eq_mode_btn.clicked.connect(self.on_set_fps_eq_mode)
|
||||
self.get_fps_eq_mode_btn = QPushButton("读取模式 (0xB8)")
|
||||
self.get_fps_eq_mode_btn.clicked.connect(self.on_get_fps_eq_mode)
|
||||
fps_eq_mode_btn.addWidget(self.set_fps_eq_mode_btn)
|
||||
fps_eq_mode_btn.addWidget(self.get_fps_eq_mode_btn)
|
||||
fps_xmos_layout.addRow(fps_eq_mode_btn)
|
||||
|
||||
fps_name_layout = QHBoxLayout()
|
||||
self.fps_eq_mode_name_edit = QLineEdit()
|
||||
self.fps_eq_mode_name_edit.setPlaceholderText("模式名称(最多15字符)")
|
||||
fps_name_layout.addWidget(self.fps_eq_mode_name_edit)
|
||||
self.set_fps_eq_mode_name_btn = QPushButton("设置名称 (0xBB)")
|
||||
self.set_fps_eq_mode_name_btn.clicked.connect(self.on_set_fps_eq_mode_name)
|
||||
self.get_fps_eq_mode_name_btn = QPushButton("读取名称 (0xBC)")
|
||||
self.get_fps_eq_mode_name_btn.clicked.connect(self.on_get_fps_eq_mode_name)
|
||||
fps_name_layout.addWidget(self.set_fps_eq_mode_name_btn)
|
||||
fps_name_layout.addWidget(self.get_fps_eq_mode_name_btn)
|
||||
fps_xmos_layout.addRow("fps_eq模式名:", fps_name_layout)
|
||||
|
||||
fps_band_layout = QHBoxLayout()
|
||||
self.fps_eq_band_spin = QSpinBox()
|
||||
self.fps_eq_band_spin.setRange(0, 9)
|
||||
self.fps_eq_gain_spin = QSpinBox()
|
||||
self.fps_eq_gain_spin.setRange(-600, 600)
|
||||
self.fps_eq_gain_spin.setValue(1)
|
||||
fps_band_layout.addWidget(QLabel("频段:"))
|
||||
fps_band_layout.addWidget(self.fps_eq_band_spin)
|
||||
fps_band_layout.addWidget(QLabel("增益(0.01dB):"))
|
||||
fps_band_layout.addWidget(self.fps_eq_gain_spin)
|
||||
fps_xmos_layout.addRow(fps_band_layout)
|
||||
|
||||
fps_band_btn = QHBoxLayout()
|
||||
self.set_fps_eq_band_btn = QPushButton("设置频段 (0xB9)")
|
||||
self.set_fps_eq_band_btn.clicked.connect(self.on_set_fps_eq_band_gain)
|
||||
self.get_fps_eq_band_btn = QPushButton("读取频段 (0xBA)")
|
||||
self.get_fps_eq_band_btn.clicked.connect(self.on_get_fps_eq_band_gain)
|
||||
fps_band_btn.addWidget(self.set_fps_eq_band_btn)
|
||||
fps_band_btn.addWidget(self.get_fps_eq_band_btn)
|
||||
fps_xmos_layout.addRow(fps_band_btn)
|
||||
|
||||
left_content_layout.addWidget(fps_xmos_group)
|
||||
|
||||
# 添加EQ使能控制组
|
||||
eq_enable_group = QGroupBox("EQ使能控制")
|
||||
self.ui_groups['eq_enable'] = eq_enable_group # 保存引用
|
||||
@@ -1097,6 +1247,7 @@ class EQDesigner(QMainWindow):
|
||||
'input_source': '输入源控制',
|
||||
'mute_switch': '静音开关',
|
||||
'listen_switch': '监听开关',
|
||||
'fps_xmos': 'FPS算法控制',
|
||||
'eq_enable': 'EQ使能控制',
|
||||
'firmware': '固件升级',
|
||||
'dfs': '动态降频'
|
||||
@@ -1131,6 +1282,7 @@ class EQDesigner(QMainWindow):
|
||||
'input_source': '输入源控制',
|
||||
'mute_switch': '静音开关',
|
||||
'listen_switch': '监听开关',
|
||||
'fps_xmos': 'FPS算法控制',
|
||||
'eq_enable': 'EQ使能控制',
|
||||
'firmware': '固件升级'
|
||||
}
|
||||
@@ -1804,7 +1956,11 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
|
||||
fs = 48000
|
||||
log_message(LOG_LEVEL_DEBUG, f" 图像显示采样率: {fs} Hz", self.log_level)
|
||||
|
||||
mode = self.current_mode
|
||||
# 改动原因:读取参数时以UI当前选择模式为准,避免self.current_mode被异步查询结果覆盖后读取到错误模式。
|
||||
requested_mode = self.mode_combo.currentIndex()
|
||||
if requested_mode == NUM_EQ_MODES:
|
||||
requested_mode = EQ_DISABLED_MODE
|
||||
mode = requested_mode
|
||||
|
||||
# 读取所有MAX_EQ_BANDS个EQ参数
|
||||
for eq_index in range(MAX_EQ_BANDS):
|
||||
@@ -1839,9 +1995,15 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
|
||||
log_message(LOG_LEVEL_ERROR, f"错误: 无效的响应同步头: 0x{reply[1]:02x} 0x{reply[2]:02x}", self.log_level)
|
||||
continue
|
||||
|
||||
# 模式值
|
||||
mode = reply[3]
|
||||
log_message(LOG_LEVEL_DEBUG, f" 模式值: {mode}", self.log_level)
|
||||
# 模式值(设备回包)
|
||||
resp_mode = reply[3]
|
||||
log_message(LOG_LEVEL_DEBUG, f" 模式值: {resp_mode}", self.log_level)
|
||||
if resp_mode != requested_mode:
|
||||
log_message(
|
||||
LOG_LEVEL_WARN,
|
||||
f" 警告: 请求模式={requested_mode}, 回包模式={resp_mode},后续仍按请求模式继续读取",
|
||||
self.log_level
|
||||
)
|
||||
|
||||
# EQ索引
|
||||
eq_idx = reply[4]
|
||||
@@ -1882,7 +2044,9 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
|
||||
log_message(LOG_LEVEL_DEBUG, f" 带宽: {bw:.2f} Hz", self.log_level)
|
||||
|
||||
# 增益 (4字节) - 位置18-21
|
||||
gain = struct.unpack('<f', bytes(reply[18:22]))[0]
|
||||
gain_bytes = bytes(reply[18:22])
|
||||
gain = struct.unpack('<f', gain_bytes)[0]
|
||||
log_message(LOG_LEVEL_DEBUG, f" gain bytes: {gain_bytes.hex()}", self.log_level)
|
||||
log_message(LOG_LEVEL_DEBUG, f" 增益: {gain:.2f} dB", self.log_level)
|
||||
|
||||
# 更新UI显示
|
||||
@@ -1896,7 +2060,7 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
|
||||
|
||||
# 打印读取到的参数
|
||||
log_message(LOG_LEVEL_INFO, f"成功读取EQ {eq_index} 的参数:", self.log_level)
|
||||
log_message(LOG_LEVEL_INFO, f" 模式值: {mode}", self.log_level)
|
||||
log_message(LOG_LEVEL_INFO, f" 模式值: {resp_mode}", self.log_level)
|
||||
log_message(LOG_LEVEL_INFO, f" 类型: {filter_type}", self.log_level)
|
||||
log_message(LOG_LEVEL_INFO, f" 频率: {fc} Hz", self.log_level)
|
||||
log_message(LOG_LEVEL_INFO, f" Q值: {q:.2f}", self.log_level)
|
||||
@@ -2295,7 +2459,7 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
|
||||
self,
|
||||
"错误",
|
||||
f"无效的模式值: {mode}\n\n"
|
||||
f"有效范围: 0-9 (0-5预设模式, 6-8用户模式, 9: bypass)"
|
||||
f"有效范围: 0-14 (0-12预设模式, 13-14用户模式, 15=禁用EQ)"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -3670,6 +3834,357 @@ 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"读取固件版本时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_set_fps_xmos_game_select(self):
|
||||
"""设置 FPS XMOS 游戏类型与档位(HID 0xBF,tile0→tile1)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
|
||||
return
|
||||
game = self.fps_xmos_game_combo.currentData()
|
||||
level = self.fps_xmos_level_spin.value()
|
||||
game_name = self.fps_xmos_game_combo.currentText()
|
||||
try:
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = SET_FPS_XMOS_GAME_SELECT
|
||||
data[2] = game
|
||||
data[3] = level
|
||||
log_message(LOG_LEVEL_INFO,
|
||||
f"设置 FPS 游戏/档位: {game_name}, level={level} (HID 0xBF)...",
|
||||
self.log_level)
|
||||
h.write([0x01] + list(data))
|
||||
self.fps_xmos_game_status_label.setText(f"游戏档位: game={game}, level={level} (已发送)")
|
||||
QMessageBox.information(self, "已发送",
|
||||
f"已设置 FPS 游戏/档位:\n{game_name}\n档位: {level}")
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"设置 FPS 游戏/档位时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_get_fps_xmos_game_select(self):
|
||||
"""查询指定 game 的档位(HID 0xC0)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
|
||||
return
|
||||
game = self.fps_xmos_game_combo.currentData()
|
||||
try:
|
||||
import time
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = GET_FPS_XMOS_GAME_SELECT
|
||||
data[2] = game
|
||||
log_message(LOG_LEVEL_INFO,
|
||||
f"查询 FPS game={game} 的档位 (HID 0xC0)...",
|
||||
self.log_level)
|
||||
h.write([0x01] + list(data))
|
||||
time.sleep(0.05)
|
||||
reply = h.get_input_report(0x01, 64)
|
||||
if (reply and len(reply) == 64 and reply[0] == 0x01
|
||||
and reply[1] == 0x77 and reply[2] == GET_FPS_XMOS_GAME_SELECT):
|
||||
resp_game = reply[3]
|
||||
resp_level = reply[4]
|
||||
self.fps_xmos_game_status_label.setText(
|
||||
f"游戏档位: game={resp_game}, level={resp_level}")
|
||||
if resp_game <= 2:
|
||||
idx = self.fps_xmos_game_combo.findData(resp_game)
|
||||
if idx >= 0:
|
||||
self.fps_xmos_game_combo.setCurrentIndex(idx)
|
||||
if resp_level <= 4:
|
||||
self.fps_xmos_level_spin.setValue(resp_level)
|
||||
QMessageBox.information(self, "FPS 游戏档位",
|
||||
f"game={resp_game}, level={resp_level}")
|
||||
else:
|
||||
log_message(LOG_LEVEL_ERROR, "未收到有效的 0xC0 响应", self.log_level)
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"查询 FPS 游戏档位时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_set_fps_module_enable(self):
|
||||
"""设置 FPS 库 DRC / FPS主处理 / fps_eq 使能(HID 0xB5)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
|
||||
return
|
||||
drc = self.fps_drc_enable_combo.currentIndex()
|
||||
fps_sub = self.fps_sub_enable_combo.currentIndex()
|
||||
eq_en = self.fps_eq_enable_combo.currentIndex()
|
||||
try:
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = SET_FPS_MODULE_ENABLE
|
||||
data[2] = drc
|
||||
data[3] = fps_sub
|
||||
data[4] = eq_en
|
||||
log_message(LOG_LEVEL_INFO,
|
||||
f"设置 FPS 模块使能: DRC={drc}, FPS={fps_sub}, EQ={eq_en} (HID 0xB5)...",
|
||||
self.log_level)
|
||||
h.write([0x01] + list(data))
|
||||
|
||||
log_message(LOG_LEVEL_DEBUG, "发送的数据:", self.log_level)
|
||||
log_message(LOG_LEVEL_DEBUG, " ".join(f"0x{byte:02x}" for byte in ([0x01] + list[int](data))), self.log_level)
|
||||
QMessageBox.information(self, "已发送",
|
||||
f"DRC={drc}, FPS主处理={fps_sub}, fps_eq={eq_en}\n(0=关, 1=开)")
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"设置 FPS 模块使能时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_get_fps_module_enable(self):
|
||||
"""读取 FPS 库三模块使能(HID 0xB6)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
|
||||
return
|
||||
try:
|
||||
import time
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = GET_FPS_MODULE_ENABLE
|
||||
log_message(LOG_LEVEL_INFO, "读取 FPS 模块使能 (HID 0xB6)...", self.log_level)
|
||||
h.write([0x01] + list(data))
|
||||
time.sleep(0.05)
|
||||
reply = h.get_input_report(0x01, 64)
|
||||
if (reply and len(reply) == 64 and reply[0] == 0x01
|
||||
and reply[1] == 0x77 and reply[2] == GET_FPS_MODULE_ENABLE):
|
||||
drc = reply[3]
|
||||
fps_sub = reply[4]
|
||||
eq_en = reply[5]
|
||||
self.fps_drc_enable_combo.setCurrentIndex(1 if drc else 0)
|
||||
self.fps_sub_enable_combo.setCurrentIndex(1 if fps_sub else 0)
|
||||
self.fps_eq_enable_combo.setCurrentIndex(1 if eq_en else 0)
|
||||
log_message(LOG_LEVEL_DEBUG, "读取到的响应数据:", self.log_level)
|
||||
log_message(LOG_LEVEL_DEBUG, " ".join(f"0x{byte:02x}" for byte in reply), self.log_level)
|
||||
log_message(LOG_LEVEL_INFO,
|
||||
f"FPS 模块使能: DRC={drc}, FPS={fps_sub}, EQ={eq_en}",
|
||||
self.log_level)
|
||||
QMessageBox.information(self, "FPS 模块使能",
|
||||
f"DRC={drc}\nFPS主处理={fps_sub}\nfps_eq={eq_en}\n(0=关, 1=开)")
|
||||
else:
|
||||
log_message(LOG_LEVEL_ERROR, "未收到有效的 0xB6 响应", self.log_level)
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"读取 FPS 模块使能时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_set_fps_drc_mode(self):
|
||||
"""设置 DRC 压缩模式(HID 0xBD):0=low柔和,1=high强力"""
|
||||
if self.device_combo.currentData() is None:
|
||||
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
|
||||
return
|
||||
mode = self.fps_drc_mode_combo.currentData()
|
||||
try:
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = SET_FPS_DRC_MODE
|
||||
data[2] = mode
|
||||
mode_name = self.fps_drc_mode_combo.currentText()
|
||||
log_message(LOG_LEVEL_INFO,
|
||||
f"设置 DRC 压缩模式: {mode_name} (HID 0xBD)...",
|
||||
self.log_level)
|
||||
h.write([0x01] + list(data))
|
||||
QMessageBox.information(self, "已发送", f"DRC模式={mode}\n(0=low, 1=high)")
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"设置 DRC 压缩模式时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_get_fps_drc_mode(self):
|
||||
"""读取 DRC 压缩模式(HID 0xBE)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
|
||||
return
|
||||
try:
|
||||
import time
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = GET_FPS_DRC_MODE
|
||||
log_message(LOG_LEVEL_INFO, "读取 DRC 压缩模式 (HID 0xBE)...", self.log_level)
|
||||
h.write([0x01] + list(data))
|
||||
time.sleep(0.05)
|
||||
reply = h.get_input_report(0x01, 64)
|
||||
if (reply and len(reply) == 64 and reply[0] == 0x01
|
||||
and reply[1] == 0x77 and reply[2] == GET_FPS_DRC_MODE):
|
||||
mode = reply[3]
|
||||
idx = self.fps_drc_mode_combo.findData(mode)
|
||||
if idx >= 0:
|
||||
self.fps_drc_mode_combo.setCurrentIndex(idx)
|
||||
log_message(LOG_LEVEL_INFO, f"DRC 压缩模式: {mode} (0=low, 1=high)", self.log_level)
|
||||
QMessageBox.information(self, "DRC 压缩模式", f"mode={mode}\n(0=low, 1=high)")
|
||||
else:
|
||||
log_message(LOG_LEVEL_ERROR, "未收到有效的 0xBE 响应", self.log_level)
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"读取 DRC 压缩模式时出错: {str(e)}", self.log_level)
|
||||
|
||||
def on_set_fps_eq_mode(self):
|
||||
"""设置 fps_eq 预设模式 0-4(HID 0xB7)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
return
|
||||
mode = self.fps_eq_mode_spin.value()
|
||||
try:
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = SET_FPS_EQ_MODE
|
||||
data[2] = mode
|
||||
h.write([0x01] + list(data))
|
||||
h.close()
|
||||
QMessageBox.information(self, "已发送", f"fps_eq 模式已设为 {mode}")
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"设置 fps_eq 模式失败: {e}", self.log_level)
|
||||
|
||||
def on_get_fps_eq_mode(self):
|
||||
"""读取 fps_eq 当前模式(HID 0xB8)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
return
|
||||
try:
|
||||
import time
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = GET_FPS_EQ_MODE
|
||||
h.write([0x01] + list(data))
|
||||
time.sleep(0.05)
|
||||
reply = h.get_input_report(0x01, 64)
|
||||
if (reply and len(reply) >= 4 and reply[0] == 0x01
|
||||
and reply[1] == 0x77 and reply[2] == GET_FPS_EQ_MODE):
|
||||
mode = reply[3]
|
||||
self.fps_eq_mode_spin.setValue(mode)
|
||||
QMessageBox.information(self, "fps_eq 模式", f"当前模式: {mode}")
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"读取 fps_eq 模式失败: {e}", self.log_level)
|
||||
|
||||
def on_set_fps_eq_mode_name(self):
|
||||
"""设置 fps_eq 模式名称(HID 0xBB)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
return
|
||||
mode = self.fps_eq_mode_spin.value()
|
||||
mode_name = self.fps_eq_mode_name_edit.text().strip()
|
||||
try:
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = SET_FPS_EQ_MODE_NAME
|
||||
data[2] = mode
|
||||
encoded = mode_name.encode('utf-8', errors='ignore')[:15]
|
||||
data[3:3 + len(encoded)] = encoded
|
||||
data[3 + len(encoded)] = 0x00
|
||||
h.write([0x01] + list(data))
|
||||
h.close()
|
||||
QMessageBox.information(self, "已发送", f"模式{mode} 名称已设置为: {mode_name}")
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"设置 fps_eq 模式名失败: {e}", self.log_level)
|
||||
|
||||
def on_get_fps_eq_mode_name(self):
|
||||
"""读取 fps_eq 模式名称(HID 0xBC)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
return
|
||||
mode = self.fps_eq_mode_spin.value()
|
||||
try:
|
||||
import time
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = GET_FPS_EQ_MODE_NAME
|
||||
data[2] = mode
|
||||
h.write([0x01] + list(data))
|
||||
time.sleep(0.05)
|
||||
reply = h.get_input_report(0x01, 64)
|
||||
log_message(LOG_LEVEL_DEBUG, f"0xBC响应原始数据: {' '.join(f'0x{byte:02x}' for byte in reply[:16])}", self.log_level)
|
||||
if (reply and len(reply) >= 20 and reply[0] == 0x01
|
||||
and reply[1] == 0x77 and reply[2] == GET_FPS_EQ_MODE_NAME):
|
||||
resp_mode = reply[3]
|
||||
raw_name = bytes(reply[4:20]).split(b'\x00', 1)[0]
|
||||
log_message(LOG_LEVEL_DEBUG, f"raw_name: {raw_name}", self.log_level)
|
||||
mode_name = raw_name.decode('utf-8', errors='ignore')
|
||||
self.fps_eq_mode_spin.setValue(resp_mode if resp_mode <= 4 else 0)
|
||||
self.fps_eq_mode_name_edit.setText(mode_name)
|
||||
QMessageBox.information(self, "fps_eq 模式名", f"模式{resp_mode} 名称: {mode_name}")
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"读取 fps_eq 模式名失败: {e}", self.log_level)
|
||||
|
||||
def on_set_fps_eq_band_gain(self):
|
||||
"""设置当前模式单段增益(HID 0xB9)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
return
|
||||
band = self.fps_eq_band_spin.value()
|
||||
gain = self.fps_eq_gain_spin.value()
|
||||
try:
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = SET_FPS_EQ_BAND_GAIN
|
||||
data[2] = band
|
||||
data[3] = gain & 0xFF
|
||||
data[4] = (gain >> 8) & 0xFF
|
||||
h.write([0x01] + list(data))
|
||||
h.close()
|
||||
QMessageBox.information(self, "已发送", f"band={band}, gain={gain} (0.01dB)")
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"设置 fps_eq 频段失败: {e}", self.log_level)
|
||||
|
||||
def on_get_fps_eq_band_gain(self):
|
||||
"""读取当前模式单段增益(HID 0xBA)"""
|
||||
if self.device_combo.currentData() is None:
|
||||
return
|
||||
band = self.fps_eq_band_spin.value()
|
||||
try:
|
||||
import time
|
||||
device_info = self.device_combo.currentData()
|
||||
h = hid.device()
|
||||
h.open(device_info['vendor_id'], device_info['product_id'])
|
||||
h.set_nonblocking(1)
|
||||
data = bytearray(63)
|
||||
data[0] = 0x77
|
||||
data[1] = GET_FPS_EQ_BAND_GAIN
|
||||
data[2] = band
|
||||
h.write([0x01] + list(data))
|
||||
time.sleep(0.05)
|
||||
reply = h.get_input_report(0x01, 64)
|
||||
# 改动原因:64字节含ReportID[0]=0x01,协议载荷从[1]起:77 BA band gain_lo gain_hi
|
||||
if (reply and len(reply) >= 6 and reply[0] == 0x01
|
||||
and reply[1] == 0x77 and reply[2] == GET_FPS_EQ_BAND_GAIN):
|
||||
resp_band = reply[3]
|
||||
gain = struct.unpack('<h', bytes(reply[4:6]))[0]
|
||||
self.fps_eq_gain_spin.setValue(gain)
|
||||
QMessageBox.information(
|
||||
self, "fps_eq 增益",
|
||||
f"band={resp_band}, gain={gain} (0.01dB)")
|
||||
h.close()
|
||||
except Exception as e:
|
||||
log_message(LOG_LEVEL_ERROR, f"读取 fps_eq 频段失败: {e}", self.log_level)
|
||||
|
||||
def on_browse_firmware(self):
|
||||
"""浏览选择固件文件"""
|
||||
# 改动原因:打开文件对话框选择固件文件
|
||||
@@ -3720,7 +4235,7 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
|
||||
改动原因:实现可靠的响应等待机制,确保每个命令发送后都等待设备响应后再继续
|
||||
参数:
|
||||
h: HID设备对象
|
||||
expected_cmd: 期望的命令码(如0xA7, 0xA8等)
|
||||
expected_cmd: 期望的命令码(如0xBF, 0xC0等)
|
||||
timeout: 超时时间(秒)
|
||||
max_retries: 最大重试次数
|
||||
返回:
|
||||
|
||||
@@ -94,11 +94,7 @@ static int get_sample_rate_index(uint32_t sample_rate) {
|
||||
*/
|
||||
static eq_mode_data_t (*get_eq_array_ptr(uint32_t sample_rate))[NUM_EQ_MODES][NUM_EQ_CHANS] {
|
||||
// 改动原因:所有采样率共用44100Hz数组
|
||||
#if !UAC1
|
||||
return &sEQ_data_44100HZ;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,6 +166,7 @@ int eq_flash_init(void) {
|
||||
while (retry_count < 3 && lfs_init_result != 0) {
|
||||
lfs_init_result = lfs_init();
|
||||
if (lfs_init_result != 0) {
|
||||
lfs_deinit(); // 释放session锁,避免下次循环自死锁
|
||||
retry_count++;
|
||||
DPRINTF("Failed to initialize LFS, retry %d/3\n", retry_count);
|
||||
if (retry_count < 3) {
|
||||
@@ -233,6 +230,13 @@ int eq_flash_load_mode(uint8_t mode) {
|
||||
DPRINTF(" Error: Invalid mode %d (max: %d)\n", mode, NUM_EQ_MODES - 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 改动原因:模式扩展后,0-12为固化预设曲线,不允许被Flash历史数据覆盖。
|
||||
// 仅用户模式(13-14)从Flash加载,避免旧版本遗留mode7/8/9文件覆盖新预设,导致读回曲线异常(如32Hz/0dB直线)。
|
||||
if (mode < EQ_USER_MODE_MIN) {
|
||||
DPRINTF(" Mode %d is preset mode, skip Flash override and keep built-in preset parameters\n", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取当前采样率的EQ数组指针
|
||||
eq_mode_data_t (*eq_array)[NUM_EQ_MODES][NUM_EQ_CHANS] = get_eq_array_ptr(g_eq_sample_rate);
|
||||
@@ -240,7 +244,14 @@ int eq_flash_load_mode(uint8_t mode) {
|
||||
DPRINTF(" Error: Failed to get EQ array for current sample rate %lu\n", (unsigned long)g_eq_sample_rate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// user_func.c通过load_eq_mode_from_flash()调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_flash_load_mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 加载左右两个声道的数据
|
||||
for (int ch = 0; ch < NUM_EQ_CHANS; ch++) {
|
||||
// 构建文件路径
|
||||
@@ -434,7 +445,8 @@ int eq_flash_load_mode(uint8_t mode) {
|
||||
|
||||
DPRINTF(" Successfully loaded EQ parameters for mode %d, channel %d\n", mode, ch);
|
||||
}
|
||||
|
||||
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -818,7 +830,14 @@ int eq_save_dirty_params(void) {
|
||||
DPRINTF(" Error: Flash storage not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// audiohw.xc直接调用此函数,但之前没有会话保护,可能与其他core的Flash操作冲突。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_save_dirty_params\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//DPRINTF(" Single param database count: %d\n", single_param_database.param_count);
|
||||
|
||||
int saved_count = 0;
|
||||
@@ -859,6 +878,7 @@ int eq_save_dirty_params(void) {
|
||||
if (saved_count > 0) {
|
||||
DPRINTF(" Saved %d dirty single parameters\n", saved_count);
|
||||
}
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
@@ -877,14 +897,23 @@ int eq_save_dirty_gain(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// audiohw.xc直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_save_dirty_gain\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DPRINTF(" Saving dirty gain\n");
|
||||
// 使用新的独立保存函数
|
||||
if (eq_save_gain() == 0) {
|
||||
gain_dirty = 0; // 只清除增益脏标志
|
||||
DPRINTF(" Successfully saved gain\n");
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
} else {
|
||||
DPRINTF(" Error: Failed to save gain\n");
|
||||
lfs_deinit();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -904,6 +933,13 @@ int eq_save_dirty_names(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// audiohw.xc直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_save_dirty_names\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DPRINTF(" Saving dirty mode names\n");
|
||||
// 使用新的独立保存函数,逐个保存每个用户模式的name
|
||||
int saved_count = 0;
|
||||
@@ -923,12 +959,15 @@ int eq_save_dirty_names(void) {
|
||||
|
||||
if (saved_count > 0) {
|
||||
DPRINTF(" Successfully saved %d mode name(s), skipped %d\n", saved_count, skipped_count);
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
} else if (skipped_count > 0) {
|
||||
DPRINTF(" All mode names skipped (same as default or empty), %d skipped\n", skipped_count);
|
||||
lfs_deinit();
|
||||
return 0; // 跳过是正常的,不算错误
|
||||
} else {
|
||||
DPRINTF(" Error: Failed to save mode names\n");
|
||||
lfs_deinit();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1081,6 +1120,13 @@ int eq_save_name(uint8_t mode) {
|
||||
int eq_save_gain_and_names(void) {
|
||||
int ret = 0;
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// 此函数为公共API,调用了eq_save_gain和eq_save_name(均直接操作Flash),必须提供会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_save_gain_and_names\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 保存gain
|
||||
if (eq_save_gain() != 0) {
|
||||
ret = -1;
|
||||
@@ -1095,6 +1141,7 @@ int eq_save_gain_and_names(void) {
|
||||
// result == 1 表示跳过,这是正常的
|
||||
}
|
||||
|
||||
lfs_deinit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1260,6 +1307,13 @@ int eq_load_name(uint8_t mode) {
|
||||
int eq_load_gain_and_names(void) {
|
||||
int ret = 0;
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// dsp_core0.xc在eq_flash_init()完成(释放锁)后直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_load_gain_and_names\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 加载gain
|
||||
if (eq_load_gain() != 0) {
|
||||
ret = -1; // 文件不存在是正常的,使用默认值
|
||||
@@ -1273,6 +1327,7 @@ int eq_load_gain_and_names(void) {
|
||||
}
|
||||
|
||||
DPRINTF("Successfully loaded gain and mode names\n");
|
||||
lfs_deinit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1300,7 +1355,14 @@ int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t
|
||||
DPRINTF(" Error: Failed to get EQ array for sample rate %u\n", sample_rate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// dsp_core0.xc在eq_flash_init()完成后直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_load_all_params_and_calculate_coefficients\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int loaded_count = 0;
|
||||
|
||||
// 简化加载逻辑:只从44100Hz channel 0加载参数,然后应用到所有采样率和通道
|
||||
@@ -1313,7 +1375,8 @@ int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t
|
||||
|
||||
//DPRINTF(" Loaded %d single parameters and calculated coefficients for mode %d\n",
|
||||
// loaded_count, mode);
|
||||
|
||||
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1367,7 +1430,14 @@ int eq_flash_save_mode(uint8_t mode) {
|
||||
DPRINTF(" Error: Failed to get EQ array for current sample rate %lu\n", (unsigned long)g_eq_sample_rate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// 此前该函数直接调用lfs_write_config而无会话保护,多core同时访问会导致数据损坏。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_flash_save_mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 保存左右两个声道的数据
|
||||
for (int ch = 0; ch < NUM_EQ_CHANS; ch++) {
|
||||
// 构建文件路径
|
||||
@@ -1421,7 +1491,8 @@ int eq_flash_save_mode(uint8_t mode) {
|
||||
#endif
|
||||
DPRINTF(" Successfully saved EQ parameters for mode %d, channel %d\n", mode, ch);
|
||||
}
|
||||
|
||||
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1604,7 +1675,14 @@ int delete_flash_eq_params(uint8_t mode) {
|
||||
DPRINTF(" Error: Flash storage not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// eq.c的reset_eq_params()直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in delete_flash_eq_params\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int deleted_count = 0;
|
||||
|
||||
if (mode == 0xFF) {
|
||||
@@ -1646,6 +1724,7 @@ int delete_flash_eq_params(uint8_t mode) {
|
||||
}
|
||||
|
||||
DPRINTF(" Deleted %d parameter files\n", deleted_count);
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1656,7 +1735,7 @@ int delete_flash_eq_params(uint8_t mode) {
|
||||
*
|
||||
* 改动原因:修改为按模式删除,只删除指定模式的增益和名称,而不是删除所有文件
|
||||
* - 如果mode == 0xFF,删除所有用户模式的增益和名称文件
|
||||
* - 如果mode是用户模式(6-8),只删除该模式的名称文件,并将该模式的增益恢复为默认值(0)
|
||||
* - 如果mode是用户模式(13-14),只删除该模式的名称文件,并将该模式的增益恢复为默认值(0)
|
||||
* - 如果mode是预设模式(0-5),不需要删除(预设模式的增益和名称不存储在Flash中)
|
||||
*/
|
||||
int delete_flash_gain_and_names(uint8_t mode) {
|
||||
@@ -1666,7 +1745,14 @@ int delete_flash_gain_and_names(uint8_t mode) {
|
||||
DPRINTF(" Error: Flash storage not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// eq.c的reset_eq_params()直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in delete_flash_gain_and_names\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 处理删除所有模式的情况
|
||||
if (mode == 0xFF) {
|
||||
DPRINTF(" Deleting all user mode gains and names\n");
|
||||
@@ -1693,23 +1779,26 @@ int delete_flash_gain_and_names(uint8_t mode) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 检查模式有效性
|
||||
if (mode >= NUM_EQ_MODES) {
|
||||
DPRINTF(" Error: Invalid mode %d\n", mode);
|
||||
lfs_deinit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 预设模式(0-5)的增益和名称不存储在Flash中,不需要删除
|
||||
if (mode < EQ_USER_MODE_MIN) {
|
||||
DPRINTF(" Mode %d is a preset mode, no Flash data to delete\n", mode);
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 只处理用户模式(6-8)
|
||||
// 只处理用户模式(13-14)
|
||||
if (mode >= EQ_USER_MODE_MIN && mode <= EQ_USER_MODE_MAX) {
|
||||
// 删除该模式的名称文件
|
||||
char file_path[FILE_PATH_MAX_LENGTH];
|
||||
@@ -1763,12 +1852,14 @@ int delete_flash_gain_and_names(uint8_t mode) {
|
||||
} else {
|
||||
DPRINTF(" Gains file does not exist: %s\n", file_path);
|
||||
}
|
||||
|
||||
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 其他模式(如模式9)不需要处理
|
||||
DPRINTF(" Mode %d does not require Flash data deletion\n", mode);
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1864,7 +1955,14 @@ int eq_flash_save_eq_enable(uint8_t enable)
|
||||
DPRINTF(" Error: Invalid EQ enable value %d (valid range: 0-1)\n", enable);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// 此前该函数直接调用lfs_write_config而无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_flash_save_eq_enable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 构建独立文件路径
|
||||
// 改动原因:使用独立的文件名存储eq_enable,与模式存储完全分离
|
||||
char file_path[FILE_PATH_MAX_LENGTH];
|
||||
@@ -1891,6 +1989,7 @@ int eq_flash_save_eq_enable(uint8_t enable)
|
||||
// 写入文件
|
||||
lfs_write_config(file_path, file_data, sizeof(file_data));
|
||||
DPRINTF(" Successfully saved EQ enable %d to Flash (independent file: %s)\n", enable, file_path);
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1911,11 +2010,19 @@ int eq_flash_save_current_mode(uint8_t mode)
|
||||
}
|
||||
|
||||
// 验证模式值范围
|
||||
if (mode > 9) {
|
||||
DPRINTF(" Error: Invalid mode %d (valid range: 0-9)\n", mode);
|
||||
// 改动原因:EQ模式数量扩展到15,允许保存模式范围0-14。
|
||||
if (mode >= NUM_EQ_MODES) {
|
||||
DPRINTF(" Error: Invalid mode %d (valid range: 0-%d)\n", mode, NUM_EQ_MODES - 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥,
|
||||
// 防止多core并发访问导致数据损坏。此前该函数直接调用lfs_write_config而无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_flash_save_current_mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 构建独立文件路径
|
||||
// 改动原因:使用独立的文件名存储模式,与eq_enable存储完全分离
|
||||
char file_path[FILE_PATH_MAX_LENGTH];
|
||||
@@ -1942,6 +2049,7 @@ int eq_flash_save_current_mode(uint8_t mode)
|
||||
// 写入文件
|
||||
lfs_write_config(file_path, file_data, sizeof(file_data));
|
||||
DPRINTF(" Successfully saved EQ mode %d to Flash (independent file: %s)\n", mode, file_path);
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1961,10 +2069,17 @@ int eq_flash_load_current_mode(void)
|
||||
DPRINTF(" Error: Flash storage not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// dsp_core0.xc在eq_flash_init()完成后直接调用此函数,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_flash_load_current_mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 加载模式(从独立文件)
|
||||
char mode_file_path[FILE_PATH_MAX_LENGTH];
|
||||
snprintf(mode_file_path, sizeof(mode_file_path), "%s", g_eq_flash_mode_file);
|
||||
snprintf(mode_file_path, sizeof(mode_file_path), "%s/%s", g_eq_flash_base_dir, g_eq_flash_mode_file);
|
||||
|
||||
if (lfs_file_exists(mode_file_path)) {
|
||||
eq_file_header_t header;
|
||||
@@ -1976,7 +2091,8 @@ int eq_flash_load_current_mode(void)
|
||||
mode = file_header_data[sizeof(header)];
|
||||
|
||||
// 验证模式值范围
|
||||
if (mode > 9) {
|
||||
// 改动原因:EQ模式数量扩展到15,加载时按NUM_EQ_MODES校验范围(0-14)。
|
||||
if (mode >= NUM_EQ_MODES) {
|
||||
DPRINTF(" Error: Invalid mode value %d in file\n", mode);
|
||||
mode = 0; // 使用默认值
|
||||
} else {
|
||||
@@ -2001,7 +2117,7 @@ int eq_flash_load_current_mode(void)
|
||||
|
||||
// 加载使能状态(从独立文件)
|
||||
char enable_file_path[FILE_PATH_MAX_LENGTH];
|
||||
snprintf(enable_file_path, sizeof(enable_file_path), "%s", g_eq_flash_enable_file);
|
||||
snprintf(enable_file_path, sizeof(enable_file_path), "%s/%s", g_eq_flash_base_dir, g_eq_flash_enable_file);
|
||||
|
||||
if (lfs_file_exists(enable_file_path)) {
|
||||
eq_file_header_t header;
|
||||
@@ -2041,6 +2157,7 @@ int eq_flash_load_current_mode(void)
|
||||
g_eq_enable = eq_enable;
|
||||
|
||||
DPRINTF(" Successfully loaded mode %d and EQ enable %d from Flash (independent files)\n", mode, eq_enable);
|
||||
lfs_deinit();
|
||||
return mode;
|
||||
}
|
||||
|
||||
@@ -2059,7 +2176,14 @@ int eq_flash_load_eq_enable(void)
|
||||
DPRINTF(" Error: Flash storage not initialized\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// 改动原因:所有Flash I/O必须在lfs_init()/lfs_deinit()会话内执行,确保QSPI Flash访问互斥。
|
||||
// 此函数为公共API,直接进行Flash读操作,此前无会话保护。
|
||||
if (lfs_init() != 0) {
|
||||
DPRINTF(" Error: Failed to open flash session in eq_flash_load_eq_enable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 加载使能状态(从独立文件)
|
||||
char enable_file_path[FILE_PATH_MAX_LENGTH];
|
||||
snprintf(enable_file_path, sizeof(enable_file_path), "%s", g_eq_flash_enable_file);
|
||||
@@ -2102,6 +2226,7 @@ int eq_flash_load_eq_enable(void)
|
||||
g_eq_enable = eq_enable;
|
||||
|
||||
DPRINTF(" Successfully loaded EQ enable %d from Flash (independent file)\n", eq_enable);
|
||||
lfs_deinit();
|
||||
return eq_enable;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#define EQ_FLASH_MAGIC_PARAMS 0x45515041 // "EQPA" - EQ参数文件魔数
|
||||
#define EQ_FLASH_VERSION 0x00020000 // 版本2.0.0 - 优化存储格式
|
||||
#define EQ_FLASH_MAX_SAMPLE_RATES 6 // 支持的采样率数量
|
||||
#define EQ_FLASH_MAX_MODES 10 // 最大模式数量
|
||||
#define EQ_FLASH_MAX_MODES 15 // 最大模式数量(改动原因:EQ模式扩展至15)
|
||||
#define EQ_FLASH_MAX_CHANNELS 2 // 最大通道数量
|
||||
|
||||
// 支持的采样率列表
|
||||
@@ -46,9 +46,9 @@ typedef struct {
|
||||
uint32_t crc32; // CRC32校验
|
||||
} __attribute__((packed)) eq_gain_header_t;
|
||||
|
||||
// 模式增益数据(只存储用户模式6-8)
|
||||
// 模式增益数据(只存储用户模式13-14)
|
||||
typedef struct {
|
||||
int32_t mode_gains[3]; // 用户模式增益数组:mode 6, 7, 8,每个4字节
|
||||
int32_t mode_gains[2]; // 用户模式增益数组:mode 13, 14,每个4字节(改动原因:用户模式由3个减为2个)
|
||||
} __attribute__((packed)) eq_gain_data_t;
|
||||
|
||||
// 单个模式名称存储结构
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
| 0x8F | GET_DEVICE_INFO | 获取设备信息 | 主机→设备 | 读取设备PID、VID、产品字符串等信息 |
|
||||
| 0x90 | RESET_EQ_PARAMS | 复位EQ参数 | 主机→设备 | 删除Flash中的EQ参数并恢复头文件预设参数 |
|
||||
| 0x91 | GET_EQ_MODE_COUNT | 获取EQ模式总数 | 主机→设备 | 返回预定义加用户模式的总数(不包含禁用模式) |
|
||||
| 0x92 | SET_AND_SAVE_EQ_MODE | 设置并保存EQ模式 | 主机→设备 | 设置当前EQ模式(0-9)并保存到Flash,开机时自动恢复 |
|
||||
| 0x92 | SET_AND_SAVE_EQ_MODE | 设置并保存EQ模式 | 主机→设备 | 设置当前EQ模式(0-14)并保存到Flash,开机时自动恢复 |
|
||||
| 0x93 | SET_VOLUME | 设置音量级别 | 主机→设备 | 设置设备音量级别(0-255) |
|
||||
| 0x94 | GET_VOLUME | 获取音量级别 | 主机→设备 | 读取设备当前音量级别(0-255) |
|
||||
| 0x95 | GET_LED_INFO | 获取LED信息 | 主机→设备 | 读取LED索引和LED名称 |
|
||||
@@ -37,13 +37,30 @@
|
||||
| 0xA4 | SET_GAME_MODE | 设置游戏模式 | 主机→设备 | 设置游戏模式(0=无音效,1=FPS,2=虚拟7.1) |
|
||||
| 0xA5 | GET_GAME_MODE | 获取游戏模式 | 主机→设备 | 读取当前游戏模式(0-2) |
|
||||
| 0xA6 | GET_FIRMWARE_VERSION | 获取固件版本 | 主机→设备 | 读取设备固件版本号(BCD格式:主版本.次版本.修订版本) |
|
||||
| 0xB0 | SET_INPUT_SOURCE | 设置输入源模式 | 主机→设备 | 设置输入源模式(0=USB, 1=OPT, 2=COAX),通过UART 0x5D透传给MCU |
|
||||
| 0xB1 | SET_MUTE_SWITCH | 设置静音开关 | 主机→设备 | 设置静音开关(0=关,1=开),通过UART 0x5E透传给MCU |
|
||||
| 0xB2 | GET_MUTE_SWITCH | 获取静音开关状态 | 主机→设备 | 读取静音开关状态(0=关,1=开),设备通过串口向MCU请求后返回 |
|
||||
| 0xB3 | SET_LISTEN_SWITCH | 设置监听开关 | 主机→设备 | 设置监听开关(0=关,1=开),通过UART 0x60透传给MCU |
|
||||
| 0xB4 | GET_LISTEN_SWITCH | 获取监听开关状态 | 主机→设备 | 读取监听开关状态(0=关,1=开),直接返回 g_adc_loop 的值,不经过串口 |
|
||||
| 0xB6 | SET_TILE1_DIV | 设置tile1动态降频分频值 | 主机→设备 | 设置tile1低功耗分频值N(core clock=600MHz/N),仅FPS镜像(C1_DFS_EN)生效,tile1空闲时降频 |
|
||||
| 0xB7 | GET_TILE1_DIV | 获取tile1动态降频分频值 | 主机→设备 | 读取当前tile1低功耗分频值N(动态降频),仅FPS镜像(C1_DFS_EN)生效 |
|
||||
| 0xA7 | FIRMWARE_UPGRADE_START | 开始固件升级 | 主机→设备 | 初始化升级流程,设置固件大小(与 eq_hid_protocol_ds1 一致) |
|
||||
| 0xA8 | FIRMWARE_UPGRADE_DATA | 传输固件数据块 | 主机→设备 | 固定57字节数据块 |
|
||||
| 0xA9 | FIRMWARE_UPGRADE_END | 结束固件升级 | 主机→设备 | 验证镜像 |
|
||||
| 0xAA | FIRMWARE_UPGRADE_STATUS | 获取升级状态 | 主机→设备 | 进度与状态 |
|
||||
| 0xAB | FIRMWARE_UPGRADE_ABORT | 中止固件升级 | 主机→设备 | 中止并清理 |
|
||||
| 0xAC | FIRMWARE_UPGRADE_ERASE | 擦除升级镜像 | 主机→设备 | 擦除 Flash 升级区 |
|
||||
| 0xAE | DEVICE_REBOOT | 设备重启 | 主机→设备 | 通用重启命令 |
|
||||
| 0xB0 | SET_INPUT_SOURCE | 设置输入源模式 | 主机→设备 | 设置输入源模式(0=USB, 1=OPT, 2=COAX),tile0 经 sync 0x04 到 tile1 发 UART 0x5D 透传 MCU |
|
||||
| 0xB1 | SET_MUTE_SWITCH | 设置静音开关 | 主机→设备 | 设置静音开关(0=关,1=开),tile0 经 sync 0x05 到 tile1 发 UART 0x5E 透传 MCU |
|
||||
| 0xB2 | GET_MUTE_SWITCH | 获取静音开关状态 | 主机→设备 | 读取静音开关状态(0=关,1=开),tile0 经 sync 0x06 让 tile1 向 MCU 发 0x5F,MCU 返回后 tile1 经 sync 0x0E 回传静音值 |
|
||||
| 0xB3 | SET_LISTEN_SWITCH | 设置监听开关 | 主机→设备 | 设置监听开关(0=关,1=开),tile0 经 sync 0x07 到 tile1 发 UART 0x60 透传 MCU |
|
||||
| 0xB4 | GET_LISTEN_SWITCH | 获取监听开关状态 | 主机→设备 | 读取监听开关状态(0=关,1=开),直接返回 tile0 的 g_adc_loop 值(由 tile1 经 sync 0x0D 同步),不经过串口 |
|
||||
| 0xB5 | SET_FPS_MODULE_ENABLE | 设置FPS库子模块使能 | 主机→设备 | 设置DRC/FPS主处理/fps_eq使能(0=旁路,1=开启);tile0存Flash后经sync 0x08同步tile1 |
|
||||
| 0xB6 | GET_FPS_MODULE_ENABLE | 获取FPS库子模块使能 | 主机→设备 | 从Flash读取三模块使能状态(0/1) |
|
||||
| 0xB7 | SET_FPS_EQ_MODE | 设置fps_eq预设模式 | 主机→设备 | 模式0-4(共5套),默认0;tile0写Flash后sync 0x09到tile1加载该模式10段增益 |
|
||||
| 0xB8 | GET_FPS_EQ_MODE | 获取fps_eq当前模式 | 主机→设备 | 返回当前模式0-4 |
|
||||
| 0xB9 | SET_FPS_EQ_BAND_GAIN | 设置当前模式单段增益 | 主机→设备 | band(0-9)+gain int16 LE(0.01dB,-600~600);tile0存Flash,sync 0x0A到tile1调用eq_set_band_gain |
|
||||
| 0xBA | GET_FPS_EQ_BAND_GAIN | 获取当前模式单段增益 | 主机→设备 | 请求band(0-9),返回gain int16 LE |
|
||||
| 0xBB | SET_FPS_EQ_MODE_NAME | 设置fps_eq模式名称 | 主机→设备 | 设置模式0-4的名称(16字节,含\0截断);tile0写Flash断电保存 |
|
||||
| 0xBC | GET_FPS_EQ_MODE_NAME | 获取fps_eq模式名称 | 主机→设备 | 请求模式0-4,返回该模式16字节名称 |
|
||||
| 0xBD | SET_FPS_DRC_MODE | 设置DRC压缩模式 | 主机→设备 | mode 0=low柔和压缩、1=high强力压缩,默认0;tile0存Flash后经sync 0x0C同步tile1 |
|
||||
| 0xBE | GET_FPS_DRC_MODE | 获取DRC压缩模式 | 主机→设备 | 返回当前DRC压缩模式(0/1) |
|
||||
| 0xBF | SET_FPS_XMOS_GAME_SELECT | 设置FPS XMOS游戏与增益 | 主机→设备 | 设置game(0-2)及该game绑定的level(0-4);每种game单独存level(fps_level_g0/g1/g2),默认level为2 |
|
||||
| 0xC0 | GET_FPS_XMOS_GAME_SELECT | 获取指定game的level | 主机→设备 | 请求字节2指定game(0-2),返回该game及其在Flash中保存的level(0-4) |
|
||||
|
||||
### 1.3 数据包格式
|
||||
- **Report ID**: 0x01 (HID报告ID)
|
||||
@@ -62,7 +79,7 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x8A | 命令码
|
||||
2 | 1 | uint8 | 模式值 (0-5: 预设模式, 6-8: 用户模式, 9: bypass)
|
||||
2 | 1 | uint8 | 模式值 (0-12: 预设模式, 13-14: 用户模式, 15: 禁用EQ)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
@@ -76,13 +93,13 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x8B | 命令码
|
||||
2 | 1 | uint8 | 模式值 (0-9: 有效模式值, 0xFF: 获取当前模式信息)
|
||||
2 | 1 | uint8 | 模式值 (0-14: 有效模式值, 0xFF: 获取当前模式信息)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**设备端处理**:
|
||||
- 如果mode值为0xFF,返回当前模式值、整体增益和模式名称
|
||||
- 如果mode值为有效模式值(0-9),返回指定模式值、整体增益和模式名称
|
||||
- 如果mode值为有效模式值(0-14),返回指定模式值、整体增益和模式名称
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +118,7 @@
|
||||
|
||||
**使用说明**:
|
||||
- 发送mode=0xFF时,返回当前激活的EQ模式信息
|
||||
- 发送mode=0-9时,返回指定模式的增益和名称信息(不切换当前模式)
|
||||
- 发送mode=0-14时,返回指定模式的增益和名称信息(不切换当前模式)
|
||||
|
||||
### 2.3 0x8C - SET_MODE_GAIN_AND_NAME (设置模式整体增益和名称)
|
||||
**功能**: 设置EQ模式整体增益和名称
|
||||
@@ -112,7 +129,7 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x8C | 命令码
|
||||
2 | 1 | uint8 | 模式值 (0-9)
|
||||
2 | 1 | uint8 | 模式值 (0-14)
|
||||
3-6 | 4 | int32 | 增益值 (范围0到-50dB,有符号整数)
|
||||
7-22 | 16 | char | 模式名称 (UTF-8编码,16字节)
|
||||
23-62 | 40 | 0x00 | 保留字节
|
||||
@@ -132,7 +149,7 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x8D | 命令码
|
||||
2 | 1 | uint8 | 模式值 (0-9)
|
||||
2 | 1 | uint8 | 模式值 (0-14)
|
||||
3 | 1 | uint8 | 滤波器Band索引 (0-7)
|
||||
4 | 1 | uint8 | 滤波器类型
|
||||
5-8 | 4 | float | 中心频率 (Hz)
|
||||
@@ -166,7 +183,7 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x8E | 命令码
|
||||
2 | 1 | uint8 | 模式值 (0-9)
|
||||
2 | 1 | uint8 | 模式值 (0-14)
|
||||
3 | 1 | uint8 | EQ索引 (0-7)
|
||||
4-62 | 59 | 0x00 | 保留字节
|
||||
```
|
||||
@@ -178,7 +195,7 @@
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0x8E | 同步头2
|
||||
3 | 1 | uint8 | 模式值 (0-9)
|
||||
3 | 1 | uint8 | 模式值 (0-14)
|
||||
4 | 1 | uint8 | 滤波器Band索引 (0-7)
|
||||
5 | 1 | uint8 | 滤波器类型
|
||||
6-9 | 4 | float | 中心频率 (Hz)
|
||||
@@ -224,7 +241,7 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x90 | 命令码
|
||||
2 | 1 | uint8 | 模式号 (0-9, 0xFF表示恢复所有包括EQ参数,总体增益,模式名称 )
|
||||
2 | 1 | uint8 | 模式号 (0-14, 0xFF表示恢复所有包括EQ参数,总体增益,模式名称 )
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
@@ -258,8 +275,8 @@
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0x91 | 同步头2
|
||||
3 | 1 | uint8 | 模式总数 (当前为9,包含0-8共9个模式,不包含禁用模式)
|
||||
4 | 1 | uint8 | 预定义模式数量 (当前为6,包含0-5共6个预设模式)
|
||||
3 | 1 | uint8 | 模式总数 (当前为15,包含0-14共15个模式,不包含禁用模式15)
|
||||
4 | 1 | uint8 | 预定义模式数量 (当前为13,包含0-12共13个预设模式)
|
||||
5-62 | 58 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
@@ -272,7 +289,7 @@
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0x92 | 命令码
|
||||
2 | 1 | uint8 | 模式值 (0-9: 0-5预设模式, 6-8用户模式, 9: bypass)
|
||||
2 | 1 | uint8 | 模式值 (0-14: 0-12预设模式, 13-14用户模式, 15=禁用EQ)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
@@ -665,7 +682,7 @@
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0x9E | 同步头2
|
||||
3 | 1 | uint8 | EQ使能开关状态 (0=OFF禁用, 1=ON启用)
|
||||
4 | 1 | uint8 | 保存的模式值 (0-9,如果之前有保存,0xFF表示未保存)
|
||||
4 | 1 | uint8 | 保存的模式值 (0-14,如果之前有保存,0xFF表示未保存)
|
||||
5-62 | 58 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
@@ -863,9 +880,221 @@
|
||||
- 3个字节分别表示:主版本号、次版本号、修订版本号
|
||||
- 例如:0x01 0x00 0x0C 表示版本 1.0.12
|
||||
|
||||
### 2.30 0xB0 - SET_INPUT_SOURCE (设置输入源模式)
|
||||
**功能**: 设置输入源模式(USB/OPT/COAX),通过UART 0x5D命令透传给MCU处理
|
||||
**方向**: 主机→设备(XMOS)→MCU
|
||||
### 2.30 0xB5 - SET_FPS_MODULE_ENABLE (设置FPS库 DRC / FPS主处理 / fps_eq 使能)
|
||||
**功能**: 设置 FPS 算法库三个子模块的运行时开关,对应 `fps_xmos_xc_set_module_enable(drc_enable, fps_enable, eq_enable)`。0=旁路,非0=开启。
|
||||
**方向**: 主机→设备(tile0)→tile1
|
||||
**数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB5 | 命令码
|
||||
2 | 1 | uint8 | drc_enable (0/1)
|
||||
3 | 1 | uint8 | fps_enable,FPS主处理子模块 (0/1)
|
||||
4 | 1 | uint8 | eq_enable,fps_eq子模块 (0/1)
|
||||
5-62 | 58 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**Flash 存储**:
|
||||
- `fps_drc_enable` / `fps_sub_enable` / `fps_eq_enable`:各 0 或 1,未存或无效(>1) 时默认 DRC=0、FPS主处理=1、fps_eq=0。
|
||||
|
||||
**设备端处理**:
|
||||
- tile0:写 Flash 与共享全局 `g_fps_drc_enable`、`g_fps_sub_enable`、`g_fps_eq_enable`。
|
||||
- 打包 `packed = drc | (fps_sub<<8) | (eq<<16)`,`g_sync_t0_to_t1_cmd=0x08`,`g_sync_t0_to_t1_data=packed`。
|
||||
- tile1:解包后调用 `fps_apply_module_enable()` → `fps_xmos_xc_set_module_enable()`。
|
||||
|
||||
**上电恢复**: `SYNC_CMD_LOAD_CONFIGS` 中从 Flash 读取三键并触发 sync 0x08。
|
||||
|
||||
### 2.31 0xB6 - GET_FPS_MODULE_ENABLE (获取FPS库子模块使能)
|
||||
**功能**: 读取 DRC / FPS主处理 / fps_eq 当前使能状态(来自 tile0 运行时全局 `g_fps_*`,与 0xB5 写入一致,避免紧接读 Flash 滞后)。
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB6 | 命令码
|
||||
2-62 | 61 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0xB6 | 同步头2
|
||||
3 | 1 | uint8 | drc_enable (0/1)
|
||||
4 | 1 | uint8 | fps_enable (0/1)
|
||||
5 | 1 | uint8 | eq_enable (0/1)
|
||||
6-62 | 57 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
### 2.32 0xBD - SET_FPS_DRC_MODE (设置 DRC 压缩模式)
|
||||
**功能**: 设置 FPS 算法库 DRC 压缩强度,对应 `fps_xmos_xc_drc_set_mode(mode)`。0=low(柔和压缩),1=high(强力压缩)。
|
||||
**方向**: 主机→设备(tile0)→tile1
|
||||
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xBD | 命令码
|
||||
2 | 1 | uint8 | drc_mode (0=low, 1=high)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**Flash 键**: `fps_drc_mode`,未存或无效(>1) 时默认 **0**(low)。
|
||||
|
||||
|
||||
### 2.33 0xBE - GET_FPS_DRC_MODE (获取 DRC 压缩模式)
|
||||
**功能**: 读取当前 DRC 压缩模式(来自 tile0 运行时全局 `g_fps_drc_mode`,与 0xBD 写入一致)。
|
||||
**方向**: 主机→设备
|
||||
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xBE | 命令码
|
||||
2-62 | 61 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0xBE | 同步头2
|
||||
3 | 1 | uint8 | drc_mode (0=low, 1=high)
|
||||
4-62 | 59 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
### 2.34 0xBF - SET_FPS_XMOS_GAME_SELECT (设置FPS XMOS游戏类型与增益等级)
|
||||
**功能**: 设置当前FPS游戏类型(game)及**该game绑定的**增益等级(level),用于 `fps_xmos_game_select(game, level)`。game 与 level 绑定:三种 game(0/1/2) 各有各自保存的 level(0/1/2/3/4),选择某 game 时使用该 game 对应的 level;默认 level 为 2。
|
||||
**方向**: 主机→设备(XMOS tile0)→tile1
|
||||
**数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xBF | 命令码
|
||||
2 | 1 | uint8 | 游戏类型 game (0/1/2)
|
||||
3 | 1 | uint8 | 该 game 的增益等级 level (0/1/2/3/4),默认 2
|
||||
4-62 | 59 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**参数说明**:
|
||||
- **game(字节2):** 游戏类型,0/1/2;对应 `fps_xmos_game_select` 的第一个参数。
|
||||
- **level(字节3):** 当前选中的 game 的增益等级,0/1/2/3/4;对应 `fps_xmos_game_select` 的第二个参数。若主机未发或无效(>4),设备按默认 2 处理。
|
||||
- **绑定关系:** 设置 (game, level) 后,仅该 game 的 level 被更新;切换 game 时(含上电恢复)会查该 game 对应的已保存 level。
|
||||
|
||||
**Flash 存储(按 game 分别存 level)**:
|
||||
- `fps_game_select`:当前选中的 game (0/1/2)。
|
||||
- `fps_level_g0` / `fps_level_g1` / `fps_level_g2`:分别表示 game 0、1、2 的 level (0/1/2/3/4),默认 2。
|
||||
- 0xBF 设置 (game, level) 时:写入 `fps_game_select=game`,并将 level 写入对应键(game 0→fps_level_g0,game 1→fps_level_g1,game 2→fps_level_g2)。
|
||||
- 上电恢复:在 `fps_boot_load_from_flash` 中读 `fps_game_select`,再根据 game 查对应 level(读 fps_level_g0/g1/g2),得到当前 (game, level) 后同步到 tile1。
|
||||
|
||||
**设备端处理**:
|
||||
- tile0 解析 data[2]=game、data[3]=level;level 无效(>4) 时按 2。
|
||||
- 保存:`save_value("fps_game_select", game)`,并按 game 写 `save_value("fps_level_g0"/"fps_level_g1"/"fps_level_g2", level)`。
|
||||
- 打包 `packed_fps = (game<<0) | (level<<8)`,设置 g_sync_t0_to_t1_cmd=0x03、g_sync_t0_to_t1_data=packed_fps,更新 g_fps_game_select、g_fps_level_select。
|
||||
- tile1 解包后设置 g_fps_game_select、g_fps_level_select,fps1_dsp_proc_task 调用 fps_xmos_game_select(game, level)。
|
||||
|
||||
**同步机制**:
|
||||
- HID 0xBF 在 tile0 接收 → 按 game 写入对应 level 键 → 设置 sync 0x03 + packed_fps → tile1 解包并设置 g_fps_game_select、g_fps_level_select → fps1_dsp_proc_task 调用 fps_xmos_game_select(game, level)。
|
||||
|
||||
**返回值**:
|
||||
无直接返回值。当前 game 及该 game 的 level 可用 GET_FPS_XMOS_GAME_SELECT (0xC0) 读取。
|
||||
|
||||
### 2.35 0xC0 - GET_FPS_XMOS_GAME_SELECT (获取指定 game 的 level)
|
||||
**功能**: 按主机指定的 game(0/1/2) 查询该 game 绑定的 level(0/1/2/3/4),返回**指定 game** 及其在 Flash 中保存的 level(非当前选中的 game)。
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xC0 | 命令码
|
||||
2 | 1 | uint8 | 要查询的 game (0/1/2),不传或无效时设备按 0 处理
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0xC0 | 同步头2
|
||||
3 | 1 | uint8 | 请求的 game (0/1/2)
|
||||
4 | 1 | uint8 | 该 game 绑定的 level (0/1/2/3/4),来自 Flash fps_level_g0/g1/g2
|
||||
5-62 | 58 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- 请求字节2:指定要查询的 game;未传或 >2 时设备按 game=0 查询。
|
||||
|
||||
### 2.36 0xB7 - SET_FPS_EQ_MODE (设置 fps_eq 预设模式)
|
||||
**功能**: 选择 5 套 fps_eq 增益预设之一(模式 **0–4**,默认 **0**)。切换后 tile1 对该模式全部 10 段调用 `fps_xmos_xc_eq_set_all_gains`。
|
||||
**数据包**: `[0x77][0xB7][mode]`,mode 无效(>4) 拒绝。
|
||||
|
||||
**Flash**: 文件 `fps_eq_store`,含 `current_mode` 与 `gains[5][10]`,每段默认 **1** (0.01dB)。
|
||||
|
||||
**同步**: tile0 写 Flash → 发布共享 pack 字 → `g_sync_t0_to_t1_cmd=0x09`。
|
||||
|
||||
### 2.35 0xB8 - GET_FPS_EQ_MODE
|
||||
**响应**: `[0x77][0xB8][mode]`,mode 为当前选中模式 0–4。
|
||||
|
||||
### 2.36 0xB9 - SET_FPS_EQ_BAND_GAIN (设置当前模式单段增益)
|
||||
**功能**: 调节**当前模式**下某一频段增益,tile1 调用 `fps_xmos_xc_eq_set_band_gain(band, gain)`。
|
||||
**数据包**:
|
||||
```
|
||||
0: 0x77 1: 0xB9 2: band(0-9) 3-4: gain int16 LE (0.01dB, -600~600)
|
||||
```
|
||||
tile0 更新 Flash 中 `gains[current_mode][band]`,sync **0x0A**。
|
||||
|
||||
### 2.37 0xBA - GET_FPS_EQ_BAND_GAIN
|
||||
**请求**: `[0x77][0xBA][band]`
|
||||
**响应(含 Report ID 的 64 字节 HID 报告)**:
|
||||
```
|
||||
字节 | 内容
|
||||
-----|------
|
||||
0 | 0x01 Report ID
|
||||
1 | 0x77
|
||||
2 | 0xBA
|
||||
3 | band (0-9)
|
||||
4-5 | gain int16 小端 (0.01dB, -600~600)
|
||||
```
|
||||
主机解析增益应使用 **字节 4–5**,勿与字节 3(band)拼接。
|
||||
|
||||
### 2.38 0xBB - SET_FPS_EQ_MODE_NAME (设置 fps_eq 模式名称)
|
||||
**功能**: 设置 fps_eq 预设模式名称(模式 0~4,对应 5 套增益)。
|
||||
**请求格式**:
|
||||
```
|
||||
0:0x77 1:0xBB 2:mode(0-4) 3..18:name[16]
|
||||
```
|
||||
**说明**:
|
||||
- 名称最大 15 个可见字符,第 16 字节用于 `\0` 结尾(设备侧强制截断)。
|
||||
- 名称写入 tile0 Flash (`fps_eq_store`),支持断电保存。
|
||||
|
||||
### 2.39 0xBC - GET_FPS_EQ_MODE_NAME (读取 fps_eq 模式名称)
|
||||
**请求**: `[0x77][0xBC][mode]`
|
||||
**响应(含 Report ID 的 64 字节 HID 报告)**:
|
||||
```
|
||||
字节 | 内容
|
||||
-----|------
|
||||
0 | 0x01 Report ID
|
||||
1 | 0x77
|
||||
2 | 0xBC
|
||||
3 | mode(0-4)
|
||||
4..19| name[16](\0 结尾,不足补0)
|
||||
```
|
||||
|
||||
### 2.40 0xB0 - SET_INPUT_SOURCE (设置输入源模式)
|
||||
**功能**: 设置输入源模式(0=USB, 1=OPT, 2=COAX)
|
||||
**方向**: 主机→设备
|
||||
**数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
@@ -875,161 +1104,61 @@
|
||||
2 | 1 | uint8 | 输入源模式值 (0=USB, 1=OPT, 2=COAX)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
**设备端处理(c3_fps 双 tile)**:
|
||||
- tile0(HID)收到 0xB0 后设置 g_sync_t0_to_t1_cmd=0x04、g_sync_t0_to_t1_data=输入源
|
||||
- tile1 的 app_control_slave 收到 sync 后调用 process_uart_set_input_source,构建 UART 0x5D 包透传 MCU
|
||||
|
||||
**设备端处理**:
|
||||
- XMOS设备接收到HID 0xB0命令后,将其转换为UART 0x5D命令格式
|
||||
- 通过UART接口将完整的0x5D数据包透传给MCU
|
||||
- MCU负责处理输入源切换(USB/OPT/COAX)
|
||||
- 本命令不返回HID响应
|
||||
|
||||
**透传机制**:
|
||||
- HID 0xB0命令 → XMOS设备转换为UART 0x5D命令 → 透传给MCU
|
||||
- UART 0x5D数据包格式:0x55 0xAA 0x00 0x5D [长度] [输入源模式值] [校验和]
|
||||
- MCU根据输入源模式值执行相应的输入切换操作
|
||||
|
||||
### 2.31 0xB1 - SET_MUTE_SWITCH (设置静音开关)
|
||||
**功能**: 设置静音开关(0=关,1=开),通过UART 0x5E命令透传给MCU处理
|
||||
**方向**: 主机→设备(XMOS)→MCU
|
||||
### 2.33 0xB1 - SET_MUTE_SWITCH (设置静音开关)
|
||||
**功能**: 设置静音开关(0=关,1=开)
|
||||
**方向**: 主机→设备
|
||||
**数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB1 | 命令码
|
||||
2 | 1 | uint8 | 静音开关值 (0=关,1=开)
|
||||
2 | 1 | uint8 | 静音开关值 (0=关, 1=开)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
**设备端处理(c3_fps 双 tile)**:
|
||||
- tile0 收到 0xB1 后设置 sync 0x05 及数据,tile1 调用 process_uart_set_mute_switch,发 UART 0x5E 透传 MCU
|
||||
|
||||
**设备端处理**:
|
||||
- XMOS设备接收到HID 0xB1命令后,将其转换为UART 0x5E命令格式并透传给MCU
|
||||
- MCU负责处理静音开关状态
|
||||
- 本命令不返回HID响应
|
||||
### 2.34 0xB2 - GET_MUTE_SWITCH (获取静音开关状态)
|
||||
**功能**: 读取静音开关状态(0=关,1=开),设备向 MCU 请求后返回
|
||||
**方向**: 主机→设备
|
||||
**请求**: 同步头 0x77 + 0xB2 + 保留字节
|
||||
**响应**: 0x01 0x77 0xB2 + 1 字节静音值 (0=关, 1=开)
|
||||
**设备端处理(c3_fps 双 tile)**:
|
||||
- tile0 收到 0xB2 后置 is_get_mute_switch_request,并设置 sync 0x06,tile1 调用 process_uart_send_get_mute_request 向 MCU 发 UART 0x5F
|
||||
- MCU 返回 0x5F+1 字节后,tile1 的 user_uart 调用 sync_to_tile0(0x0E, mute_value, 0);tile0 的 audiohw 收到 0x0E 后设置 g_mute_switch
|
||||
- 主机执行 HID 读时,process_read_params 直接读 g_mute_switch 返回。建议发送 0xB2 后延时约 50ms 再执行 HID 读
|
||||
|
||||
### 2.32 0xB2 - GET_MUTE_SWITCH (获取静音开关状态)
|
||||
**功能**: 读取静音开关状态(0=关,1=开);设备通过串口向MCU发送0x5F请求,MCU返回状态后设备再通过HID响应返回给主机
|
||||
**方向**: 主机→设备→MCU→设备→主机
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB2 | 命令码
|
||||
2-62 | 61 | 0x00 | 保留字节
|
||||
```
|
||||
**状态变化上报**: 当静音开关状态发生变化(如 MCU 通过 0x5F 返回、tile1 经 sync 0x0E 回传)时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB2 + 1 字节静音值),与音量变化上报(0x94)方式相同。
|
||||
|
||||
**设备端处理**:
|
||||
- 主机发送0xB2后,XMOS向MCU发送UART 0x5F(GET请求)
|
||||
- MCU返回UART 0x5F响应(含静音开关值)
|
||||
- 主机随后通过HID读报告获取响应
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0xB2 | 同步头2
|
||||
3 | 1 | uint8 | 静音开关状态 (0=关,1=开)
|
||||
4-62 | 59 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**说明**: 主机发送0xB2后建议稍作延时(如50ms)再执行HID读,以确保MCU已返回数据。
|
||||
|
||||
**状态变化上报**: 当静音开关状态发生变化(如 MCU 通过 0x5F 返回新值)时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB2 + 1 字节静音值),与音量变化上报(0x94)方式相同,主机可通过 HID 读或中断 IN 获取。
|
||||
|
||||
### 2.33 0xB3 - SET_LISTEN_SWITCH (设置监听开关)
|
||||
**功能**: 设置监听开关(0=关,1=开),通过UART 0x60命令透传给MCU处理
|
||||
**方向**: 主机→设备(XMOS)→MCU
|
||||
### 2.35 0xB3 - SET_LISTEN_SWITCH (设置监听开关)
|
||||
**功能**: 设置监听开关(0=关,1=开)
|
||||
**方向**: 主机→设备
|
||||
**数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB3 | 命令码
|
||||
2 | 1 | uint8 | 监听开关值 (0=关,1=开)
|
||||
2 | 1 | uint8 | 监听开关值 (0=关, 1=开)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
**设备端处理(c3_fps 双 tile)**:
|
||||
- tile0 收到 0xB3 后设置 sync 0x07 及数据,tile1 调用 process_uart_set_listen_switch,发 UART 0x60 透传 MCU(对应 g_adc_loop 语义)
|
||||
|
||||
**设备端处理**:
|
||||
- XMOS设备接收到HID 0xB3命令后,将其转换为UART 0x60命令格式并透传给MCU
|
||||
- MCU负责处理监听开关(对应 g_adc_loop 语义)
|
||||
- 本命令不返回HID响应
|
||||
|
||||
### 2.34 0xB4 - GET_LISTEN_SWITCH (获取监听开关状态)
|
||||
**功能**: 读取监听开关状态(0=关,1=开),设备直接返回 g_adc_loop 的值,不经过串口
|
||||
### 2.36 0xB4 - GET_LISTEN_SWITCH (获取监听开关状态)
|
||||
**功能**: 读取监听开关状态(0=关,1=开),直接返回 g_adc_loop 的值,不经过串口
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB4 | 命令码
|
||||
2-62 | 61 | 0x00 | 保留字节
|
||||
```
|
||||
**请求**: 同步头 0x77 + 0xB4 + 保留字节
|
||||
**响应**: 0x01 0x77 0xB4 + 1 字节监听开关状态 (0=关, 1=开)
|
||||
**设备端处理(c3_fps 双 tile)**:
|
||||
- tile0 收到 0xB4 后置 is_get_listen_switch_request;HID 读时 process_read_params 直接读取 tile0 的 g_adc_loop(由 tile1 经 sync 0x0D 同步)填入响应字节 3
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0xB4 | 同步头2
|
||||
3 | 1 | uint8 | 监听开关状态 (0=关,1=开),即 g_adc_loop 的值
|
||||
4-62 | 59 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**设备端处理**:
|
||||
- 设备直接读取 g_adc_loop,填入响应字节 3,无需向 MCU 请求
|
||||
|
||||
**状态变化上报**: 当监听开关状态(g_adc_loop)发生变化时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB4 + 1 字节监听状态),与音量变化上报(0x94)方式相同,主机可通过 HID 读或中断 IN 获取。
|
||||
|
||||
### 2.35 0xB6 - SET_TILE1_DIV (设置tile1动态降频分频值)
|
||||
**功能**: 设置 tile[1] 动态降频(动态降频)的低功耗分频值 N。tile[1] core clock = 600 MHz / N。
|
||||
**方向**: 主机→设备
|
||||
**数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB6 | 命令码
|
||||
2 | 1 | uint8 | 分频值 N (1-255,0视为1;N=1为全速600MHz,N=40约15MHz)
|
||||
3-62 | 60 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**设备端处理**:
|
||||
- 仅在 FPS 镜像(编译宏 `C1_DFS_EN=1`,默认等于 `XMOS_FPS_EN`)生效;其它镜像(如 factory)忽略此命令。
|
||||
- 写入全局 `g_tile1_lp_div`。tile[1] 电源状态机下次进入 CLOCKED_DOWN(FPS 关闭或音频流停止、grace 超时后)时按此分频值降频;若当前已处于 CLOCKED_DOWN,则下次状态机 tick 立即按新值重写分频寄存器。
|
||||
- 全速运行(FPS 开启且音频流活跃)时不影响 tile[1] 实时时钟,仅更新待用分频值。
|
||||
|
||||
**返回值**:
|
||||
无直接返回值。如需确认,请使用 GET_TILE1_DIV (0xB7) 读取当前分频值。
|
||||
|
||||
### 2.36 0xB7 - GET_TILE1_DIV (获取tile1动态降频分频值)
|
||||
**功能**: 读取 tile[1] 动态降频当前的低功耗分频值 N。
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x77 | 同步头1
|
||||
1 | 1 | 0xB7 | 命令码
|
||||
2-62 | 61 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1 | 1 | 0x77 | 同步头1
|
||||
2 | 1 | 0xB7 | 同步头2
|
||||
3 | 1 | uint8 | 当前分频值 N (1-255)
|
||||
4-62 | 59 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**设备端处理**:
|
||||
- 仅在 FPS 镜像(`C1_DFS_EN=1`)生效,返回 `g_tile1_lp_div`。
|
||||
- 注意:返回的 N 为"待用/当前低功耗分频值",并非实时核心频率读数;tile[1] 是否实际处于降频状态取决于 FPS 开关与音频流状态(FPS 关闭或音频停止后才会真正降频)。
|
||||
**状态变化上报**: 当监听开关状态(g_adc_loop)发生变化时,设备会主动通过 HID 上报,数据格式与上述响应一致(0x77 0xB4 + 1 字节监听状态),与音量变化上报(0x94)方式相同。
|
||||
|
||||
## 5. 关键特性
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
47
sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_api.h
Normal file
47
sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_api.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef __FPS_API_H__
|
||||
#define __FPS_API_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 初始化 FPS 处理链及默认运行状态。 */
|
||||
void fps_xmos_xc_init(void);
|
||||
|
||||
/* 选择游戏配置和档位。game: 0~2(0=cs2,1=pubg,2=delta),level: 0~4。 */
|
||||
void fps_xmos_xc_game_select(int game, int level);
|
||||
|
||||
/* DRC 模式切换。mode: 0=low(柔和压缩),1=high(强力压缩)。 */
|
||||
void fps_xmos_xc_drc_set_mode(int mode);
|
||||
|
||||
/*
|
||||
* 设置运行时三个子模块的开关。
|
||||
* drc_enable: 0 表示旁路,非 0 表示开启 DRC
|
||||
* fps_enable: 0 表示旁路 FPS 主处理,非 0 表示开启
|
||||
* eq_enable: 0 表示在 FPS 阶段旁路 EQ,非 0 表示开启
|
||||
*/
|
||||
void fps_xmos_xc_set_module_enable(int drc_enable, int fps_enable, int eq_enable);
|
||||
|
||||
/* 初始化运行,调节过程中不运行。 */
|
||||
/* 设置 10 段 EQ 的全部增益,单位为 0.01 dB,范围 -600 ~ 600。 */
|
||||
void fps_xmos_xc_eq_set_all_gains(int16_t *gains);
|
||||
|
||||
/* 初始化不运行,调节过程中运行。 */
|
||||
/* 设置单个 EQ 频段增益,单位为 0.01 dB,范围 -600 ~ 600。 */
|
||||
void fps_xmos_xc_eq_set_band_gain(int band, int16_t gain);
|
||||
|
||||
/*
|
||||
* 处理一个双声道块。
|
||||
* input/output 数据格式为解交织的平面双声道:
|
||||
* input[0..511] : 左声道
|
||||
* input[512..1023] : 右声道
|
||||
*/
|
||||
void fps_xmos_xc_process(int16_t *input, int16_t *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
173
sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.c
Normal file
173
sw_usb_audio/app_usb_aud_fosi_c1/src/extensions/fps_eq_flash.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/* 改动原因:FPS fps_eq 五模式增益在tile0侧LittleFS持久化 */
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "fps_eq_flash.h"
|
||||
#include "lfs_io.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
#define FPS_EQ_FLASH_PATH "fps_eq_store"
|
||||
#define FPS_EQ_FLASH_VERSION 0x01u
|
||||
|
||||
static void fps_eq_default_name(uint8_t mode, char out_name[FPS_EQ_NAME_LEN])
|
||||
{
|
||||
/* 改动原因:按协议约定提供小写默认模式名 fps_eq_0 ~ fps_eq_4 */
|
||||
snprintf(out_name, FPS_EQ_NAME_LEN, "fps_eq_%u", (unsigned)mode);
|
||||
}
|
||||
|
||||
/* 改动原因:仅判断“是否历史已存名称”,不做ASCII限制,兼容中文/多语言UTF-8 */
|
||||
static int fps_eq_name_has_saved_value(const char name[FPS_EQ_NAME_LEN])
|
||||
{
|
||||
int i;
|
||||
int all_zero = 1;
|
||||
int all_ff = 1;
|
||||
int has_terminator = 0;
|
||||
unsigned char first = (unsigned char)name[0];
|
||||
|
||||
for (i = 0; i < FPS_EQ_NAME_LEN; i++) {
|
||||
unsigned char c = (unsigned char)name[i];
|
||||
if (c != 0x00) {
|
||||
all_zero = 0;
|
||||
}
|
||||
if (c != 0xFF) {
|
||||
all_ff = 0;
|
||||
}
|
||||
if (c == '\0') {
|
||||
has_terminator = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 旧数据或未初始化:全0或全0xFF,视为“未存名称” */
|
||||
if (all_zero || all_ff) {
|
||||
return 0;
|
||||
}
|
||||
/* 改动原因:旧布局中常见 0x01 0x00...(增益=1)会误判为“有名称”,首字节为控制字节时视为未存 */
|
||||
if (first < 0x20) {
|
||||
return 0;
|
||||
}
|
||||
/* 有数据但无\0终止,视为旧布局残留,回退默认名 */
|
||||
if (!has_terminator) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fps_eq_flash_set_defaults(fps_eq_flash_store_t *store)
|
||||
{
|
||||
int m, b;
|
||||
|
||||
memset(store, 0, sizeof(*store));
|
||||
store->magic = FPS_EQ_FLASH_MAGIC;
|
||||
store->version = FPS_EQ_FLASH_VERSION;
|
||||
store->current_mode = 0;
|
||||
for (m = 0; m < FPS_EQ_MODE_COUNT; m++) {
|
||||
fps_eq_default_name((uint8_t)m, store->mode_names[m]);
|
||||
for (b = 0; b < FPS_EQ_BAND_COUNT; b++) {
|
||||
store->gains[m][b] = FPS_EQ_GAIN_DEFAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t fps_eq_clamp_gain(int16_t gain)
|
||||
{
|
||||
if (gain < FPS_EQ_GAIN_MIN) {
|
||||
return FPS_EQ_GAIN_MIN;
|
||||
}
|
||||
if (gain > FPS_EQ_GAIN_MAX) {
|
||||
return FPS_EQ_GAIN_MAX;
|
||||
}
|
||||
return gain;
|
||||
}
|
||||
|
||||
int fps_eq_flash_load(fps_eq_flash_store_t *out)
|
||||
{
|
||||
fps_eq_flash_store_t tmp;
|
||||
int m;
|
||||
int need_repair = 0;
|
||||
|
||||
fps_eq_flash_set_defaults(out);
|
||||
|
||||
if (lfs_init() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lfs_read_config((unsigned char *)FPS_EQ_FLASH_PATH,
|
||||
(unsigned char *)&tmp,
|
||||
sizeof(tmp));
|
||||
lfs_deinit();
|
||||
|
||||
if (tmp.magic != FPS_EQ_FLASH_MAGIC) {
|
||||
debug_printf("fps_eq_flash: invalid magic, use defaults\n");
|
||||
return -1;
|
||||
}
|
||||
if (tmp.version != FPS_EQ_FLASH_VERSION) {
|
||||
debug_printf("fps_eq_flash: version mismatch, reset defaults\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tmp.current_mode >= FPS_EQ_MODE_COUNT) {
|
||||
tmp.current_mode = 0;
|
||||
need_repair = 1;
|
||||
}
|
||||
for (m = 0; m < FPS_EQ_MODE_COUNT; m++) {
|
||||
tmp.mode_names[m][FPS_EQ_NAME_LEN - 1] = '\0';
|
||||
if (!fps_eq_name_has_saved_value(tmp.mode_names[m])) {
|
||||
fps_eq_default_name((uint8_t)m, tmp.mode_names[m]);
|
||||
need_repair = 1;
|
||||
}
|
||||
}
|
||||
|
||||
*out = tmp;
|
||||
/* 改动原因:检测到历史脏数据时自动修复并回写,后续读取稳定显示 */
|
||||
if (need_repair) {
|
||||
(void)fps_eq_flash_save(out);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fps_eq_flash_save(const fps_eq_flash_store_t *store)
|
||||
{
|
||||
fps_eq_flash_store_t to_write = *store;
|
||||
int m;
|
||||
|
||||
to_write.magic = FPS_EQ_FLASH_MAGIC;
|
||||
to_write.version = FPS_EQ_FLASH_VERSION;
|
||||
if (to_write.current_mode >= FPS_EQ_MODE_COUNT) {
|
||||
to_write.current_mode = 0;
|
||||
}
|
||||
for (m = 0; m < FPS_EQ_MODE_COUNT; m++) {
|
||||
to_write.mode_names[m][FPS_EQ_NAME_LEN - 1] = '\0';
|
||||
if (to_write.mode_names[m][0] == '\0') {
|
||||
fps_eq_default_name((uint8_t)m, to_write.mode_names[m]);
|
||||
}
|
||||
}
|
||||
|
||||
if (lfs_init() != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lfs_write_config((unsigned char *)FPS_EQ_FLASH_PATH,
|
||||
(unsigned char *)&to_write,
|
||||
sizeof(to_write));
|
||||
lfs_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fps_eq_name_get(const fps_eq_flash_store_t *store, uint8_t mode, char out_name[FPS_EQ_NAME_LEN])
|
||||
{
|
||||
if (mode >= FPS_EQ_MODE_COUNT) {
|
||||
mode = 0;
|
||||
}
|
||||
memcpy(out_name, store->mode_names[mode], FPS_EQ_NAME_LEN);
|
||||
out_name[FPS_EQ_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
|
||||
void fps_eq_name_set(fps_eq_flash_store_t *store, uint8_t mode, const char *name)
|
||||
{
|
||||
if (mode >= FPS_EQ_MODE_COUNT || name == NULL) {
|
||||
return;
|
||||
}
|
||||
memset(store->mode_names[mode], 0, FPS_EQ_NAME_LEN);
|
||||
strncpy(store->mode_names[mode], name, FPS_EQ_NAME_LEN - 1);
|
||||
store->mode_names[mode][FPS_EQ_NAME_LEN - 1] = '\0';
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef FPS_EQ_FLASH_H
|
||||
#define FPS_EQ_FLASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 改动原因:FPS库fps_eq五套预设(模式0-4),每套10段增益,单位0.01dB,存于tile0 Flash */
|
||||
#define FPS_EQ_MODE_COUNT 5
|
||||
#define FPS_EQ_BAND_COUNT 10
|
||||
#define FPS_EQ_NAME_LEN 16
|
||||
#define FPS_EQ_GAIN_DEFAULT 1
|
||||
#define FPS_EQ_GAIN_MIN (-600)
|
||||
#define FPS_EQ_GAIN_MAX 600
|
||||
#define FPS_EQ_FLASH_MAGIC 0x46505345u /* "FPSE" */
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint8_t version;
|
||||
uint8_t current_mode;
|
||||
uint8_t reserved[2];
|
||||
char mode_names[FPS_EQ_MODE_COUNT][FPS_EQ_NAME_LEN];
|
||||
int16_t gains[FPS_EQ_MODE_COUNT][FPS_EQ_BAND_COUNT];
|
||||
} fps_eq_flash_store_t;
|
||||
|
||||
void fps_eq_flash_set_defaults(fps_eq_flash_store_t *store);
|
||||
int fps_eq_flash_load(fps_eq_flash_store_t *out_data);
|
||||
int fps_eq_flash_save(const fps_eq_flash_store_t *store);
|
||||
|
||||
int16_t fps_eq_clamp_gain(int16_t gain);
|
||||
void fps_eq_name_get(const fps_eq_flash_store_t *store, uint8_t mode, char out_name[FPS_EQ_NAME_LEN]);
|
||||
void fps_eq_name_set(fps_eq_flash_store_t *store, uint8_t mode, const char *name);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef FPS_EQ_SYNC_H
|
||||
#define FPS_EQ_SYNC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "fps_eq_flash.h"
|
||||
|
||||
/* 改动原因:int16增益经5个int32共享字在tile0/tile1间传递(dp仅支持32位SHARED_GLOBAL) */
|
||||
extern unsigned g_fps_eq_mode;
|
||||
extern int32_t g_fps_eq_pack0;
|
||||
extern int32_t g_fps_eq_pack1;
|
||||
extern int32_t g_fps_eq_pack2;
|
||||
extern int32_t g_fps_eq_pack3;
|
||||
extern int32_t g_fps_eq_pack4;
|
||||
|
||||
void fps_eq_unpack_gains(int16_t out_gains[FPS_EQ_BAND_COUNT]);
|
||||
void fps_eq_publish_gains_to_shared(const int16_t gains[FPS_EQ_BAND_COUNT]);
|
||||
void fps_eq_publish_mode_and_gains(unsigned mode, const int16_t gains[FPS_EQ_BAND_COUNT]);
|
||||
|
||||
void fps_apply_eq_mode(void);
|
||||
void fps_apply_eq_band_gain(unsigned band, int16_t gain);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright 2024 XMOS LIMITED.
|
||||
// 改动原因:tile0→tile1 FPS 同步命令排队,解决单槽 g_sync_t0_to_t1_cmd 被覆盖及跨 tile 全局无效问题
|
||||
#include <stdint.h>
|
||||
#include "xc_ptr.h"
|
||||
#include "debug_print.h"
|
||||
#include "fps_tile_sync.h"
|
||||
#include "fps_eq_sync.h"
|
||||
#include "user_uart.h"
|
||||
|
||||
#define SYNC_T0_PENDING_MAX 12
|
||||
|
||||
extern unsigned g_sync_t0_to_t1_cmd;
|
||||
extern unsigned g_sync_t0_to_t1_data;
|
||||
extern unsigned g_sync_t0_to_t1_data2;
|
||||
|
||||
static struct {
|
||||
unsigned cmd;
|
||||
unsigned data;
|
||||
unsigned data2;
|
||||
} s_sync_t0_pending[SYNC_T0_PENDING_MAX];
|
||||
|
||||
static unsigned s_sync_t0_pending_count = 0;
|
||||
|
||||
void sync_t0_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2)
|
||||
{
|
||||
if (s_sync_t0_pending_count >= SYNC_T0_PENDING_MAX) {
|
||||
debug_printf("sync_t0: pending full, drop cmd 0x%02X\n", cmd);
|
||||
return;
|
||||
}
|
||||
s_sync_t0_pending[s_sync_t0_pending_count].cmd = cmd;
|
||||
s_sync_t0_pending[s_sync_t0_pending_count].data = data;
|
||||
s_sync_t0_pending[s_sync_t0_pending_count].data2 = data2;
|
||||
s_sync_t0_pending_count++;
|
||||
}
|
||||
|
||||
void sync_t0_send_or_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2)
|
||||
{
|
||||
unsigned cur = 0;
|
||||
|
||||
GET_SHARED_GLOBAL(cur, g_sync_t0_to_t1_cmd);
|
||||
if (cur == 0) {
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, cmd);
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, data);
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, data2);
|
||||
} else {
|
||||
sync_t0_enqueue_to_tile1(cmd, data, data2);
|
||||
}
|
||||
}
|
||||
|
||||
void sync_t0_promote_pending_to_tile1(void)
|
||||
{
|
||||
unsigned cur = 0;
|
||||
unsigned i;
|
||||
|
||||
GET_SHARED_GLOBAL(cur, g_sync_t0_to_t1_cmd);
|
||||
if (cur != 0 || s_sync_t0_pending_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_cmd, s_sync_t0_pending[0].cmd);
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_data, s_sync_t0_pending[0].data);
|
||||
SET_SHARED_GLOBAL(g_sync_t0_to_t1_data2, s_sync_t0_pending[0].data2);
|
||||
|
||||
for (i = 1; i < s_sync_t0_pending_count; i++) {
|
||||
s_sync_t0_pending[i - 1] = s_sync_t0_pending[i];
|
||||
}
|
||||
s_sync_t0_pending_count--;
|
||||
}
|
||||
|
||||
void fps_eq_queue_pack_words_to_tile1(unsigned apply_on_last, unsigned enqueue_only)
|
||||
{
|
||||
int32_t packs[5];
|
||||
unsigned i;
|
||||
|
||||
GET_SHARED_GLOBAL(packs[0], g_fps_eq_pack0);
|
||||
GET_SHARED_GLOBAL(packs[1], g_fps_eq_pack1);
|
||||
GET_SHARED_GLOBAL(packs[2], g_fps_eq_pack2);
|
||||
GET_SHARED_GLOBAL(packs[3], g_fps_eq_pack3);
|
||||
GET_SHARED_GLOBAL(packs[4], g_fps_eq_pack4);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
unsigned data1 = i;
|
||||
unsigned apply_flag = (apply_on_last != 0 && i == 4) ? 1u : 0u;
|
||||
|
||||
data1 |= (apply_flag << 8);
|
||||
|
||||
if (enqueue_only) {
|
||||
sync_t0_enqueue_to_tile1(SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK, data1, (unsigned)packs[i]);
|
||||
} else {
|
||||
sync_t0_send_or_enqueue_to_tile1(SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK, data1, (unsigned)packs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef FPS_TILE_SYNC_H
|
||||
#define FPS_TILE_SYNC_H
|
||||
|
||||
/* 改动原因:tile0/tile1 内存不共享,FPS 配置须经 channel 排队同步到 tile1 */
|
||||
|
||||
void sync_t0_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2);
|
||||
void sync_t0_send_or_enqueue_to_tile1(unsigned cmd, unsigned data, unsigned data2);
|
||||
void sync_t0_promote_pending_to_tile1(void);
|
||||
|
||||
/* 改动原因:将 tile0 上已发布的 g_fps_eq_pack0..4 经 sync 0x0B 传到 tile1;末包 apply=1 时调用 fps_apply_eq_mode */
|
||||
void fps_eq_queue_pack_words_to_tile1(unsigned apply_on_last, unsigned enqueue_only);
|
||||
|
||||
/* 改动原因:C1 无 UART/MCU 串口,上电在 tile0 直接从 Flash 恢复 FPS 并排队 sync 到 tile1(原 c3_fps 由 uart_handler 经 c_uart_sync 触发) */
|
||||
void fps_boot_load_from_flash(void);
|
||||
|
||||
#endif
|
||||
@@ -10,33 +10,119 @@
|
||||
#include "xc_ptr.h"
|
||||
|
||||
#include "xua_conf.h"
|
||||
|
||||
extern void fps_xmos_init();
|
||||
extern void fps_xmos_process(int16_t * input, int16_t* output, int channel);
|
||||
/* 改动原因:FPS库V1.5改为单核xc接口,使用fps_api.h中的fps_xmos_xc_*声明 */
|
||||
#include "fps_api.h"
|
||||
#include "fps_eq_sync.h"
|
||||
|
||||
|
||||
|
||||
#define FPS_SLOT_NUM 3
|
||||
#define FPS_FRAME_SIZE 512
|
||||
#define FPS_NUM_OUT 2
|
||||
short __attribute__((aligned (4))) dsp_fps_input_buf[FPS_SLOT_NUM][2][FPS_FRAME_SIZE];
|
||||
short __attribute__((aligned (4))) dsp_fps_out_buf[FPS_SLOT_NUM][2][FPS_FRAME_SIZE];
|
||||
/* 改动原因:新库process接口为平面双声道,左0..511、右512..1023,每槽1024个sample */
|
||||
#define FPS_PLANAR_SAMPLES (FPS_FRAME_SIZE * 2)
|
||||
|
||||
unsigned fps1_buf_ready = 0;
|
||||
unsigned fps2_buf_ready = 0;
|
||||
unsigned fps_write_pos = 0;
|
||||
unsigned fps_process_pos = 0;
|
||||
short __attribute__((aligned (4))) dsp_fps_input_buf[FPS_SLOT_NUM][FPS_PLANAR_SAMPLES];
|
||||
short __attribute__((aligned (4))) dsp_fps_out_buf[FPS_SLOT_NUM][FPS_PLANAR_SAMPLES];
|
||||
|
||||
unsigned fps_buf_ready = 0;
|
||||
unsigned fps_write_pos = 0;
|
||||
unsigned fps_process_pos = 0;
|
||||
/* 改动原因:tile0/tile1 内存不共享;game/level/使能/fps_eq 须经 channel sync 写入 tile1 副本 */
|
||||
unsigned g_fps_game_select = 1;
|
||||
unsigned g_fps_level_select = 2;
|
||||
/* 改动原因:FPS 默认开、DRC/fps_eq 默认关;与 audiohw 中 g_fps_enable(模式选择) 区分命名 */
|
||||
unsigned g_fps_drc_enable = 0;
|
||||
unsigned g_fps_sub_enable = 1;
|
||||
unsigned g_fps_eq_enable = 0;
|
||||
/* 改动原因:DRC压缩模式默认0=low柔和压缩,HID 0xBD/断电保存fps_drc_mode后经sync同步到tile1 */
|
||||
unsigned g_fps_drc_mode = 0;
|
||||
|
||||
/* 改动原因:fps_eq当前模式(0-4)与10段增益,经5个pack字在tile0/tile1共享 */
|
||||
unsigned g_fps_eq_mode = 0;
|
||||
int32_t g_fps_eq_pack0 = 0;
|
||||
int32_t g_fps_eq_pack1 = 0;
|
||||
int32_t g_fps_eq_pack2 = 0;
|
||||
int32_t g_fps_eq_pack3 = 0;
|
||||
int32_t g_fps_eq_pack4 = 0;
|
||||
|
||||
static int32_t fps_eq_make_pack(int16_t lo, int16_t hi)
|
||||
{
|
||||
return ((int32_t)(uint16_t)lo) | (((int32_t)(uint16_t)hi) << 16);
|
||||
}
|
||||
|
||||
static int16_t fps_eq_pack_lo(int32_t w)
|
||||
{
|
||||
return (int16_t)(w & 0xFFFF);
|
||||
}
|
||||
|
||||
static int16_t fps_eq_pack_hi(int32_t w)
|
||||
{
|
||||
return (int16_t)((w >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
void fps_eq_unpack_gains(int16_t out_gains[FPS_EQ_BAND_COUNT])
|
||||
{
|
||||
int32_t p0, p1, p2, p3, p4;
|
||||
|
||||
GET_SHARED_GLOBAL(p0, g_fps_eq_pack0);
|
||||
GET_SHARED_GLOBAL(p1, g_fps_eq_pack1);
|
||||
GET_SHARED_GLOBAL(p2, g_fps_eq_pack2);
|
||||
GET_SHARED_GLOBAL(p3, g_fps_eq_pack3);
|
||||
GET_SHARED_GLOBAL(p4, g_fps_eq_pack4);
|
||||
|
||||
out_gains[0] = fps_eq_pack_lo(p0);
|
||||
out_gains[1] = fps_eq_pack_hi(p0);
|
||||
out_gains[2] = fps_eq_pack_lo(p1);
|
||||
out_gains[3] = fps_eq_pack_hi(p1);
|
||||
out_gains[4] = fps_eq_pack_lo(p2);
|
||||
out_gains[5] = fps_eq_pack_hi(p2);
|
||||
out_gains[6] = fps_eq_pack_lo(p3);
|
||||
out_gains[7] = fps_eq_pack_hi(p3);
|
||||
out_gains[8] = fps_eq_pack_lo(p4);
|
||||
out_gains[9] = fps_eq_pack_hi(p4);
|
||||
}
|
||||
|
||||
void fps_eq_publish_gains_to_shared(const int16_t gains[FPS_EQ_BAND_COUNT])
|
||||
{
|
||||
SET_SHARED_GLOBAL(g_fps_eq_pack0, fps_eq_make_pack(gains[0], gains[1]));
|
||||
SET_SHARED_GLOBAL(g_fps_eq_pack1, fps_eq_make_pack(gains[2], gains[3]));
|
||||
SET_SHARED_GLOBAL(g_fps_eq_pack2, fps_eq_make_pack(gains[4], gains[5]));
|
||||
SET_SHARED_GLOBAL(g_fps_eq_pack3, fps_eq_make_pack(gains[6], gains[7]));
|
||||
SET_SHARED_GLOBAL(g_fps_eq_pack4, fps_eq_make_pack(gains[8], gains[9]));
|
||||
}
|
||||
|
||||
void fps_eq_publish_mode_and_gains(unsigned mode, const int16_t gains[FPS_EQ_BAND_COUNT])
|
||||
{
|
||||
SET_SHARED_GLOBAL(g_fps_eq_mode, mode);
|
||||
fps_eq_publish_gains_to_shared(gains);
|
||||
}
|
||||
|
||||
void fps_apply_eq_mode(void)
|
||||
{
|
||||
int16_t gains[FPS_EQ_BAND_COUNT];
|
||||
|
||||
fps_eq_unpack_gains(gains);
|
||||
/* 改动原因:切换模式时用eq_set_all_gains一次性加载当前模式10段增益 */
|
||||
fps_xmos_xc_eq_set_all_gains(gains);
|
||||
}
|
||||
|
||||
void fps_apply_eq_band_gain(unsigned band, int16_t gain)
|
||||
{
|
||||
if (band >= FPS_EQ_BAND_COUNT) {
|
||||
return;
|
||||
}
|
||||
/* 改动原因:运行中单段调节使用fps_xmos_xc_eq_set_band_gain */
|
||||
fps_xmos_xc_eq_set_band_gain((int)band, gain);
|
||||
}
|
||||
|
||||
void fps_main (chanend_t c_data ) {
|
||||
|
||||
int input[2];
|
||||
int output[2];
|
||||
int count = 0;
|
||||
unsigned write_pos = 0;
|
||||
unsigned process_pos = 0;
|
||||
unsigned write_pos = 0;
|
||||
unsigned read_pos = 0;
|
||||
|
||||
|
||||
while (1) {
|
||||
|
||||
chan_in_buf_word (c_data , input, 2) ;
|
||||
@@ -44,19 +130,12 @@ void fps_main (chanend_t c_data ) {
|
||||
if (count == 0)
|
||||
read_pos = (write_pos + 1 + FPS_SLOT_NUM) % FPS_SLOT_NUM;
|
||||
|
||||
// 修改原因: 写入当前buffer,读取前一个已处理完的buffer,实现1帧延时
|
||||
// 写入位置:write_pos(当前正在填充的buffer)
|
||||
for (int i = 0; i <2; i++)
|
||||
{
|
||||
dsp_fps_input_buf[write_pos][i][count] = (short)(input[i] >> 16);
|
||||
}
|
||||
/* 改动原因:按fps_xmos_xc_process要求的平面格式写入,左声道在前512,右声道在后512 */
|
||||
dsp_fps_input_buf[write_pos][count] = (short)(input[0] >> 16);
|
||||
dsp_fps_input_buf[write_pos][FPS_FRAME_SIZE + count] = (short)(input[1] >> 16);
|
||||
|
||||
// 读取位置:read_pos(前一个已经DSP处理完成的buffer)
|
||||
// 这样可以实现最小延时(1帧),避免原来的3帧延时问题
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
output[i] = (int)(dsp_fps_out_buf[read_pos][i][count]) << 16;
|
||||
}
|
||||
output[0] = (int)(dsp_fps_out_buf[read_pos][count]) << 16;
|
||||
output[1] = (int)(dsp_fps_out_buf[read_pos][FPS_FRAME_SIZE + count]) << 16;
|
||||
|
||||
if (count != (FPS_FRAME_SIZE - 1))
|
||||
{
|
||||
@@ -64,84 +143,118 @@ void fps_main (chanend_t c_data ) {
|
||||
}
|
||||
else
|
||||
{
|
||||
// 一帧完成,进行缓冲区切换
|
||||
count = 0;
|
||||
|
||||
// 修改原因: 实现1帧延时的三缓冲机制
|
||||
// 步骤1: 将当前完成的写入buffer交给DSP处理任务
|
||||
SET_SHARED_GLOBAL(fps_process_pos, write_pos);
|
||||
|
||||
// 步骤2: 切换到下一个buffer进行写入(三缓冲循环:0→1→2→0)
|
||||
|
||||
write_pos = (write_pos + 1) % FPS_SLOT_NUM;
|
||||
SET_SHARED_GLOBAL(fps_write_pos, write_pos);
|
||||
|
||||
SET_SHARED_GLOBAL(fps1_buf_ready, 1);
|
||||
SET_SHARED_GLOBAL(fps2_buf_ready, 1);
|
||||
|
||||
/* 改动原因:单核处理整帧立体声,仅需一个ready标志 */
|
||||
SET_SHARED_GLOBAL(fps_buf_ready, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long get_reference_time();
|
||||
/* 改动原因:按全局变量同步DRC压缩模式到算法库fps_xmos_xc_drc_set_mode */
|
||||
void fps_apply_drc_mode(void)
|
||||
{
|
||||
unsigned drc_mode;
|
||||
|
||||
GET_SHARED_GLOBAL(drc_mode, g_fps_drc_mode);
|
||||
/* 改动原因:mode仅允许0=low、1=high,无效值回默认0 */
|
||||
if (drc_mode > 1) {
|
||||
drc_mode = 0;
|
||||
}
|
||||
fps_xmos_xc_drc_set_mode((int)drc_mode);
|
||||
}
|
||||
|
||||
/* 改动原因:按全局变量同步DRC/FPS主处理/fps_eq三模块开关到算法库 */
|
||||
void fps_apply_module_enable(void)
|
||||
{
|
||||
unsigned drc_enable;
|
||||
unsigned fps_sub_enable;
|
||||
unsigned eq_enable;
|
||||
|
||||
GET_SHARED_GLOBAL(drc_enable, g_fps_drc_enable);
|
||||
GET_SHARED_GLOBAL(fps_sub_enable, g_fps_sub_enable);
|
||||
GET_SHARED_GLOBAL(eq_enable, g_fps_eq_enable);
|
||||
|
||||
fps_xmos_xc_set_module_enable(
|
||||
(drc_enable != 0) ? 1 : 0,
|
||||
(fps_sub_enable != 0) ? 1 : 0,
|
||||
(eq_enable != 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
/* 改动原因:HID/tile0同步时在audiohw.xc中调用,供tile1在收到 sync 0x03(来自 HID 0xBF)时更新FPS算法参数 */
|
||||
void fps_apply_game_level_select(void)
|
||||
{
|
||||
unsigned game_select;
|
||||
unsigned level_select;
|
||||
|
||||
GET_SHARED_GLOBAL(game_select, g_fps_game_select);
|
||||
GET_SHARED_GLOBAL(level_select, g_fps_level_select);
|
||||
if (game_select > 2) {
|
||||
game_select = 0;
|
||||
}
|
||||
/* 改动原因:无效 level 默认档位 2,与 fps_level_g0/g1/g2 及 g_fps_level_select 一致 */
|
||||
if (level_select > 4) {
|
||||
level_select = 2;
|
||||
}
|
||||
fps_xmos_xc_game_select((int)game_select, (int)level_select);
|
||||
}
|
||||
|
||||
/* 改动原因:集中FPS库初始化顺序——init→fps_eq全段增益→game/level→三模块使能 */
|
||||
static void fps_xmos_modules_init(void)
|
||||
{
|
||||
unsigned game_select;
|
||||
unsigned level_select;
|
||||
int16_t gains[FPS_EQ_BAND_COUNT];
|
||||
|
||||
fps_xmos_xc_init();
|
||||
|
||||
/* 改动原因:从tile0已同步的共享pack字解出当前模式10段增益后初始化fps_eq */
|
||||
fps_eq_unpack_gains(gains);
|
||||
fps_xmos_xc_eq_set_all_gains(gains);
|
||||
|
||||
GET_SHARED_GLOBAL(game_select, g_fps_game_select);
|
||||
GET_SHARED_GLOBAL(level_select, g_fps_level_select);
|
||||
if (game_select > 2) {
|
||||
game_select = 0;
|
||||
}
|
||||
/* 改动原因:上电/初始化时无效 level 默认档位 2 */
|
||||
if (level_select > 4) {
|
||||
level_select = 2;
|
||||
}
|
||||
fps_xmos_xc_game_select((int)game_select, (int)level_select);
|
||||
|
||||
/* 改动原因:上电/HID设置后须在module_enable前应用DRC压缩模式 */
|
||||
fps_apply_drc_mode();
|
||||
fps_apply_module_enable();
|
||||
}
|
||||
|
||||
void fps1_dsp_proc_task()
|
||||
{
|
||||
fps_xmos_init();
|
||||
#if 1
|
||||
fps_xmos_modules_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned ready1;
|
||||
// 修改原因: 使用声道0独立的ready标志,与声道1完全独立,避免竞态
|
||||
GET_SHARED_GLOBAL(ready1, fps1_buf_ready);
|
||||
while (ready1)
|
||||
{
|
||||
// 修改原因: 关键修复 - 直接读取fps_main设置好的process_pos,避免自己计算导致的竞态
|
||||
unsigned cur_pos;
|
||||
GET_SHARED_GLOBAL(cur_pos, fps_process_pos);
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < FPS_FRAME_SIZE; i++)
|
||||
{
|
||||
dsp_fps_out_buf[cur_pos][0][i] = dsp_fps_input_buf[cur_pos][0][i];
|
||||
}
|
||||
#else
|
||||
// 处理声道0数据
|
||||
fps_xmos_process(&dsp_fps_input_buf[cur_pos][0], &dsp_fps_out_buf[cur_pos][0], 0);
|
||||
#endif
|
||||
unsigned ready;
|
||||
|
||||
ready1 = 0;
|
||||
SET_SHARED_GLOBAL(fps1_buf_ready, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void fps2_dsp_proc_task()
|
||||
{
|
||||
#if 1
|
||||
while (1)
|
||||
{
|
||||
unsigned ready2;
|
||||
GET_SHARED_GLOBAL(ready2, fps2_buf_ready);
|
||||
while (ready2)
|
||||
GET_SHARED_GLOBAL(ready, fps_buf_ready);
|
||||
while (ready)
|
||||
{
|
||||
unsigned cur_pos;
|
||||
|
||||
GET_SHARED_GLOBAL(cur_pos, fps_process_pos);
|
||||
|
||||
// 处理声道1数据
|
||||
unsigned long start_time = get_reference_time();
|
||||
#if 0
|
||||
for (int i = 0; i < FPS_FRAME_SIZE; i++)
|
||||
{
|
||||
dsp_fps_out_buf[cur_pos][1][i] = dsp_fps_input_buf[cur_pos][1][i];
|
||||
}
|
||||
#else
|
||||
fps_xmos_process(&dsp_fps_input_buf[cur_pos][1], &dsp_fps_out_buf[cur_pos][1], 1);
|
||||
#endif
|
||||
unsigned long end_time = get_reference_time();
|
||||
// printf("fps2_dsp_proc_task time: %d ms\n", end_time - start_time);
|
||||
// 修改原因: 只清除自己的ready标志,不影响声道0
|
||||
ready2 = 0;
|
||||
SET_SHARED_GLOBAL(fps2_buf_ready, 0);
|
||||
|
||||
/* 改动原因:单核一次处理左右声道平面块,不再分声道两次调用 */
|
||||
fps_xmos_xc_process(dsp_fps_input_buf[cur_pos], dsp_fps_out_buf[cur_pos]);
|
||||
|
||||
ready = 0;
|
||||
SET_SHARED_GLOBAL(fps_buf_ready, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <xs1.h>
|
||||
#include <xclib.h>
|
||||
#include <print.h>
|
||||
/* 改动原因:FPS 移植自 c3_fps,main.xc 中 fps_main/fps1_dsp_proc_task 启动日志需要 debug_printf */
|
||||
#include "debug_print.h"
|
||||
#ifdef XSCOPE
|
||||
#include <xscope.h>
|
||||
#endif
|
||||
@@ -422,7 +424,6 @@ void usb_audio_io(chanend ?c_aud_in,
|
||||
#if XMOS_FPS_EN
|
||||
extern void fps_main(chanend c_data);
|
||||
extern void fps1_dsp_proc_task();
|
||||
extern void fps2_dsp_proc_task();
|
||||
#endif
|
||||
|
||||
/* Main for USB Audio Applications */
|
||||
@@ -521,17 +522,16 @@ int main()
|
||||
|
||||
#if XMOS_FPS_EN
|
||||
on tile[1]: {
|
||||
debug_printf("start fps_main\n");
|
||||
set_core_high_priority_on();
|
||||
fps_main(c_data_transport);
|
||||
}
|
||||
on tile[1]: {
|
||||
/* 改动原因:FPS库改为单核xc_process,仅需一个DSP任务处理整帧立体声 */
|
||||
debug_printf("start fps1_dsp_proc_task\n");
|
||||
set_core_high_priority_on();
|
||||
fps1_dsp_proc_task();
|
||||
}
|
||||
on tile[1]: {
|
||||
set_core_high_priority_on();
|
||||
fps2_dsp_proc_task();
|
||||
}
|
||||
#else
|
||||
#if UAC1
|
||||
on tile[1]: {
|
||||
|
||||
@@ -16,7 +16,7 @@ interface c1_led_ctrl_if {
|
||||
void switch_handler(void);
|
||||
void flag_handler();
|
||||
/* 改动原因:固件升级 START 在 AudioHwRemote2 处理,需传入 c_dfu;其余升级命令在 process_send_params 直接处理 */
|
||||
void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_erase, streaming chanend c_dfu);
|
||||
void AudioHwRemote(streaming chanend c, client interface c1_led_ctrl_if i_c1_led_ctrl, streaming chanend c_dfu, chanend c_app_sync);
|
||||
void i2s_driver(chanend c);
|
||||
extern unsafe chanend uc_i2s;
|
||||
extern unsafe chanend uc_br_data;
|
||||
@@ -24,61 +24,47 @@ extern unsafe chanend uc_eq_data;
|
||||
extern void UserBufferManagementSetChan(chanend c);
|
||||
extern void dsp_main (chanend c_data , chanend cc_br_eof);
|
||||
extern void br_dsp_proc_task(chanend c_validate, chanend cc_br_eof);
|
||||
extern void validate_algo(chanend c_validate);
|
||||
void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl);
|
||||
void app_control_slave(server interface c1_led_ctrl_if i_c1_led_ctrl, chanend c_sync);
|
||||
extern void dnr_dsp_proc_task(void);
|
||||
extern void dsp_core0(void);
|
||||
extern void eq_dsp_main(chanend c_data);
|
||||
extern unsafe streaming chanend uc_audiohw;
|
||||
extern unsafe streaming chanend uc_dfu;
|
||||
extern void fps1_dsp_proc_task(void);
|
||||
extern void fps2_dsp_proc_task(void);
|
||||
/* 改动原因:FPS库单核处理,fps2_dsp_proc_task已合并到fps1 */
|
||||
extern void fps_apply_game_level_select(void);
|
||||
extern void fps_apply_module_enable(void);
|
||||
extern void fps_apply_drc_mode(void);
|
||||
extern void fps_apply_eq_mode(void);
|
||||
extern void fps_apply_eq_band_gain(unsigned band, int16_t gain);
|
||||
extern void fps_eq_boot_publish_to_tile1(void);
|
||||
extern void fps_drc_boot_sync_to_tile1(void);
|
||||
extern void fps_boot_load_from_flash(void);
|
||||
extern unsigned g_fps_drc_enable;
|
||||
extern unsigned g_fps_sub_enable;
|
||||
extern unsigned g_fps_eq_enable;
|
||||
extern unsigned g_fps_drc_mode;
|
||||
|
||||
#define USER_MAIN_DECLARATIONS chan c_data_transport, cc_br_eof, c_validate; \
|
||||
streaming chan c_audiohw; streaming chan c_dfu; interface c1_led_ctrl_if i_c1_led_ctrl; \
|
||||
#define USER_MAIN_DECLARATIONS streaming chan c_audiohw; streaming chan c_dfu; interface c1_led_ctrl_if i_c1_led_ctrl; \
|
||||
chan c_usb_to_io; chan c_io_to_usb; chan c_io_to_dspL; chan c_dspL_to_io; chan c_io_to_dspR; chan c_dspR_to_io; \
|
||||
chan c_erase;
|
||||
chan c_app_sync, c_data_transport;
|
||||
|
||||
|
||||
|
||||
#if !UAC1
|
||||
#define USER_MAIN_CORES on tile[0]: {\
|
||||
unsafe { \
|
||||
uc_audiohw = (chanend) c_audiohw;\
|
||||
uc_dfu = (chanend) c_dfu;\
|
||||
} \
|
||||
flag_handler(); \
|
||||
}\
|
||||
on tile[0]: {\
|
||||
AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_erase, c_dfu);\
|
||||
}\
|
||||
on tile[AUDIO_IO_TILE]: par {\
|
||||
dsp_core0();\
|
||||
} \
|
||||
\
|
||||
on tile[1]: app_control_slave(i_c1_led_ctrl); \
|
||||
\
|
||||
|
||||
#else
|
||||
#define USER_MAIN_CORES on tile[0]: {\
|
||||
dnr_dsp_proc_task();\
|
||||
}\
|
||||
on tile[0]: {\
|
||||
unsafe { \
|
||||
uc_audiohw = (chanend) c_audiohw;\
|
||||
/* 改动原因:FPS/BR 音频经 c_data_transport 与 tile1 fps_main 交换;未赋值 uc_br_data 会导致 UserBufferManagement buffer_exchange ECALL */\
|
||||
uc_br_data = (chanend) c_data_transport;\
|
||||
uc_dfu = (chanend) c_dfu;\
|
||||
} \
|
||||
validate_algo(c_validate); \
|
||||
}\
|
||||
on tile[0]: {\
|
||||
AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_erase, c_dfu);\
|
||||
AudioHwRemote(c_audiohw, i_c1_led_ctrl, c_dfu, c_app_sync);\
|
||||
}\
|
||||
on tile[1]: { br_dsp_proc_task(c_validate, cc_br_eof); } \
|
||||
on tile[1]: app_control_slave(i_c1_led_ctrl); \
|
||||
on tile[1]: app_control_slave(i_c1_led_ctrl, c_app_sync); \
|
||||
\
|
||||
|
||||
#endif
|
||||
#else
|
||||
|
||||
#define USER_MAIN_DECLARATIONS_A
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#include <platform.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <xclib.h>
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include <xclib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
AUDIO_PCM_44100 = 0,
|
||||
@@ -263,4 +263,42 @@ typedef struct {
|
||||
unsigned char pendingReboot;
|
||||
} UserCmdConfig;
|
||||
|
||||
// Tile1到Tile0同步命令枚举
|
||||
// 改动原因:定义同步命令类型,用于tile1通过channel向tile0发送需要同步的操作
|
||||
typedef enum {
|
||||
SYNC_CMD_NONE = 0x00,
|
||||
SYNC_CMD_LOAD_CONFIGS = 0x01, // 加载配置(从Flash读取)
|
||||
SYNC_CMD_SAVE_CONFIGS = 0x02, // 保存配置(写入Flash)
|
||||
SYNC_CMD_SAVE_PRODUCT_INFO = 0x03, // 保存产品信息
|
||||
SYNC_CMD_SAVE_POWERUP_INFO = 0x04, // 保存上电配置
|
||||
SYNC_CMD_SAVE_USERCONFIG = 0x05, // 保存用户配置
|
||||
SYNC_CMD_GET_PID_VID = 0x06, // 获取并设置PID/VID
|
||||
SYNC_CMD_SET_DAC_VOLUME = 0x07, // 设置DAC音量
|
||||
SYNC_CMD_SET_ADC_VOLUME = 0x08, // 设置ADC音量
|
||||
SYNC_CMD_SET_3D_FPS = 0x09, // 设置3D FPS(0x33命令)
|
||||
SYNC_CMD_SET_ROLE_SWITCH = 0x0A, // 设置RoleSwitchFlag(oleSwitchFlag)
|
||||
SYNC_CMD_STORE_MEMORY = 0x0B, // 存储内存数据(store_memory)
|
||||
SYNC_CMD_SET_LED_MODE = 0x0C, // 设置LED模式(0x34命令)
|
||||
SYNC_CMD_SET_ADC_LOOP = 0x0D, // 设置ADC Loop(0x31命令)
|
||||
SYNC_CMD_MUTE_VALUE_FROM_MCU = 0x0E, // tile1收到MCU 0x5F响应后,将静音值传回tile0
|
||||
} SyncCmdType;
|
||||
|
||||
// Tile0到Tile1同步命令枚举
|
||||
// 改动原因:定义反向同步命令类型,用于tile0通过channel向tile1发送需要同步的操作
|
||||
typedef enum {
|
||||
SYNC_CMD_T0_TO_T1_NONE = 0x00,
|
||||
SYNC_CMD_T0_TO_T1_SET_GAME_MODE = 0x01, // 设置游戏模式(HID 0xA4 -> UART 0x5A)
|
||||
SYNC_CMD_T0_TO_T1_SET_UAC_MODE = 0x02, // 设置UAC模式(HID 0x9B -> UART 0x51)
|
||||
SYNC_CMD_T0_TO_T1_SET_FPS_XMOS_GAME_SELECT = 0x03, // 设置FPS XMOS游戏选择(HID 0xBF -> fps_xmos_game_select)
|
||||
SYNC_CMD_T0_TO_T1_SET_INPUT_SOURCE = 0x04, // 设置输入源(HID 0xB0 -> UART 0x5D)
|
||||
SYNC_CMD_T0_TO_T1_SET_FPS_MODULE_ENABLE = 0x08, // 设置FPS库DRC/FPS/fps_eq使能(HID 0xB5 -> fps_xmos_xc_set_module_enable)
|
||||
SYNC_CMD_T0_TO_T1_SET_FPS_EQ_MODE = 0x09, // 切换fps_eq模式并加载10段增益(HID 0xB7)
|
||||
SYNC_CMD_T0_TO_T1_SET_FPS_EQ_BAND_GAIN = 0x0A, // 设置fps_eq单段增益(HID 0xB9)
|
||||
SYNC_CMD_T0_TO_T1_SET_FPS_EQ_PACK = 0x0B, // 同步fps_eq pack字到tile1(上电/HID 0xB7)
|
||||
SYNC_CMD_T0_TO_T1_SET_FPS_DRC_MODE = 0x0C, // 设置DRC压缩模式(HID 0xBD -> fps_xmos_xc_drc_set_mode)
|
||||
SYNC_CMD_T0_TO_T1_SET_MUTE_SWITCH = 0x05, // 设置静音开关(HID 0xB1 -> UART 0x5E)
|
||||
SYNC_CMD_T0_TO_T1_SEND_GET_MUTE_REQUEST = 0x06, // 向MCU发0x5F获取静音(HID 0xB2)
|
||||
SYNC_CMD_T0_TO_T1_SET_LISTEN_SWITCH = 0x07, // 设置监听开关(HID 0xB3 -> UART 0x60)
|
||||
} SyncCmdT0ToT1Type;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@ extern "C" {
|
||||
#define RCV_CMD_TIMEOUT (500000000) //5s
|
||||
#define SEND_CMD_TIMEOUT (20000000) //200ms
|
||||
#define VOLUME_TIMEOUT (5500000) //55ms delay
|
||||
#define BEAT_DELAY (500000) //10ms delay
|
||||
#define START_COUNTS (4)
|
||||
|
||||
|
||||
@@ -67,6 +68,22 @@ unsigned char g_save_configs = 0;
|
||||
unsigned g_usb_state = 1;
|
||||
unsigned int g_xu316_id;
|
||||
|
||||
/* 改动原因:0x07/0x08/0x09/0x0C/0x0D/0x0E 仅在值变化时同步到 tile0,用 pending 存 UART 下发的值,last_sync 存上次已同步的值,初值 -1 */
|
||||
unsigned g_pending_dac_vol = (unsigned)(-1);
|
||||
unsigned g_pending_adc_vol = (unsigned)(-1);
|
||||
unsigned g_pending_3d_fps = (unsigned)(-1);
|
||||
unsigned g_pending_led_mode = (unsigned)(-1);
|
||||
unsigned g_pending_adc_loop = (unsigned)(-1);
|
||||
unsigned g_pending_mute_switch = (unsigned)(-1);
|
||||
unsigned g_pending_mcu_mute = (unsigned)(-1);
|
||||
unsigned g_last_sync_dac_vol = (unsigned)(-1);
|
||||
unsigned g_last_sync_adc_vol = (unsigned)(-1);
|
||||
unsigned g_last_sync_3d_fps = (unsigned)(-1);
|
||||
unsigned g_last_sync_led_mode = (unsigned)(-1);
|
||||
unsigned g_last_sync_adc_loop = (unsigned)(-1);
|
||||
unsigned g_last_sync_mute_switch = (unsigned)(-1);
|
||||
unsigned g_last_sync_mcu_mute = (unsigned)(-1);
|
||||
|
||||
extern audio_sampling g_playback_format;
|
||||
extern audio_type g_audio_type;
|
||||
extern unsigned g_led_mode;
|
||||
@@ -76,15 +93,18 @@ extern unsigned int read_key(void);
|
||||
extern unsigned g_dac_vol;
|
||||
extern unsigned g_adc_vol;
|
||||
extern unsigned g_adc_loop;
|
||||
extern unsigned g_mute_switch; // 改动原因:与g_adc_loop一致,UART收到0x5F响应时直接设置,供HID变化上报
|
||||
extern unsigned g_3d_fps;
|
||||
extern unsigned g_dac_mode;
|
||||
extern unsigned g_new_dac_mode;
|
||||
extern unsigned g_sync_t0_to_t1_cmd;
|
||||
extern unsigned g_sync_t0_to_t1_data;
|
||||
#if EQ_EN
|
||||
extern unsigned int g_current_eq_mode; // EQ当前模式
|
||||
extern unsigned int g_old_eq_mode; // EQ当前模式
|
||||
extern int process_eq_params_from_uart(uint8_t eq_mode, uint8_t eq_index, uint32_t sample_rate, float coefficients[5]);
|
||||
// EQ命令处理函数现在在eq.c中实现
|
||||
extern void process_uart_set_game_mode(uint8_t game_mode); // 改动原因:声明UART设置游戏模式函数,用于tile0到tile1同步
|
||||
extern void process_uart_set_uac_mode(uint8_t uac_mode); // 改动原因:声明UART设置UAC模式函数,用于tile0到tile1同步
|
||||
#endif
|
||||
extern void read_uid_did(uint8_t uid[]);
|
||||
|
||||
@@ -92,6 +112,41 @@ void device_reboot(void);
|
||||
|
||||
uint8_t send_data[MAX_BUFFER_LEN] = {0};
|
||||
|
||||
// 改动原因:用于存储需要同步的数据缓冲区(用于Flash操作等需要传递数据指针的情况)
|
||||
static uint8_t sync_buffer[128];
|
||||
// 改动原因:全局同步channel,用于process_command中需要同步的操作(使用unsafe chanend因为需要在函数间传递)
|
||||
static unsafe chanend g_c_uart_sync;
|
||||
|
||||
// 改动原因:实现tile1到tile0的同步函数,用于将需要在tile0执行的操作通过channel发送
|
||||
static void sync_to_tile0(unsigned cmd, unsigned data1, unsigned data2)
|
||||
{
|
||||
unsigned result;
|
||||
unsafe {
|
||||
g_c_uart_sync <: cmd;
|
||||
g_c_uart_sync <: data1;
|
||||
g_c_uart_sync <: data2;
|
||||
g_c_uart_sync :> result;
|
||||
}
|
||||
}
|
||||
|
||||
// 改动原因:实现tile1到tile0的数据传输函数,用于传输数据块(因为tile0和tile1内存不共享)
|
||||
static void sync_data_to_tile0(unsigned cmd, uint8_t *data, unsigned len, unsigned extra_data)
|
||||
{
|
||||
unsigned result;
|
||||
unsigned i;
|
||||
unsafe {
|
||||
g_c_uart_sync <: cmd;
|
||||
g_c_uart_sync <: len; // 先发送数据长度
|
||||
g_c_uart_sync <: extra_data; // 发送额外数据
|
||||
// 逐字节传输数据(因为tile0和tile1内存不共享,不能传递指针)
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
g_c_uart_sync <: data[i];
|
||||
}
|
||||
g_c_uart_sync :> result;
|
||||
}
|
||||
}
|
||||
|
||||
UserCmdConfig cmdConfig={0};
|
||||
|
||||
extern unsigned g_in_fw_upgrade;
|
||||
@@ -203,7 +258,7 @@ uint8_t send_user_cmd(uint8_t *request, uint8_t func_code, unsigned char version
|
||||
|
||||
case START_FINISH:
|
||||
unsigned mode_code = 0;
|
||||
unsigned mode = GetRoleSwitchFlag();
|
||||
unsigned mode =BT_IN_FLAG;
|
||||
switch (mode)
|
||||
{
|
||||
case UAC1_IN_FLAG:
|
||||
@@ -224,6 +279,7 @@ uint8_t send_user_cmd(uint8_t *request, uint8_t func_code, unsigned char version
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mode_code = 0x800100;
|
||||
request[4] = FINISH_CMD_DATA_LEN;
|
||||
|
||||
request[5] = 0;
|
||||
@@ -256,10 +312,10 @@ uint8_t send_user_cmd(uint8_t *request, uint8_t func_code, unsigned char version
|
||||
}
|
||||
|
||||
debug_printf("boot to user_mode %08x\n", mode_code);
|
||||
SetRoleSwitchFlag(mode_code);
|
||||
delay_milliseconds(1);
|
||||
device_reboot();
|
||||
while(1);
|
||||
//sync_to_tile0(0x0A, mode_code, 0); // SYNC_CMD_SET_ROLE_SWITCH
|
||||
//delay_milliseconds(20);
|
||||
//device_reboot();
|
||||
//while(1);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -309,7 +365,6 @@ void update_button(unsigned char b)
|
||||
debug_printf("update_button %02x\n", 1<<b);
|
||||
#endif
|
||||
}
|
||||
void user_set_hidpass(unsigned char * unsafe data);
|
||||
|
||||
void process_command(uint8_t *data)
|
||||
{
|
||||
@@ -356,12 +411,18 @@ void process_command(uint8_t *data)
|
||||
break;
|
||||
|
||||
case READ_AUDIO_MODE:
|
||||
store_memory(&data[CMD_DATA_POS], 5);
|
||||
// 改动原因:store_memory需要在tile0执行(Flash访问),通过同步channel发送
|
||||
// 改动原因:tile0和tile1内存不共享,需要实际传输数据内容,不能传递指针
|
||||
unsafe {
|
||||
memcpy(sync_buffer, &data[CMD_DATA_POS], 5);
|
||||
sync_data_to_tile0(0x0B, sync_buffer, 5, 0); // SYNC_CMD_STORE_MEMORY
|
||||
}
|
||||
unsigned mode_code = 0;
|
||||
unsigned audio_mode = (data[CMD_DATA_POS] << 24) | (data[CMD_DATA_POS + 1] << 16) | (data[CMD_DATA_POS + 2] << 8) | data[CMD_DATA_POS + 3] ;
|
||||
debug_printf("read audio_mode 0x%08x\n", audio_mode);
|
||||
delay_milliseconds(2);
|
||||
save_configs(g_save_configs);
|
||||
// 改动原因:save_configs需要在tile0执行(Flash访问),通过同步channel发送
|
||||
save_userconfig_info(&data[CMD_DATA_POS]);
|
||||
// sync_to_tile0(0x02, g_save_configs, 0); // SYNC_CMD_SAVE_CONFIGS
|
||||
switch (audio_mode)
|
||||
{
|
||||
case 0x10806510:
|
||||
@@ -383,14 +444,21 @@ void process_command(uint8_t *data)
|
||||
}
|
||||
|
||||
debug_printf("reboot to audio_mode 0x%08x\n", mode_code);
|
||||
SetRoleSwitchFlag(mode_code);
|
||||
delay_milliseconds(1);
|
||||
device_reboot();
|
||||
while(1);
|
||||
// 改动原因:SetRoleSwitchFlag需要在tile0执行,通过同步channel发送
|
||||
sync_to_tile0(0x0A, mode_code, 0); // SYNC_CMD_SET_ROLE_SWITCH
|
||||
//delay_milliseconds(1);
|
||||
// device_reboot();
|
||||
// while(1);
|
||||
break;
|
||||
|
||||
case READ_USER_CONFIG:
|
||||
save_userconfig_info(&data[CMD_DATA_POS]);
|
||||
// 改动原因:save_userconfig_info需要在tile0执行(Flash访问),通过同步channel发送
|
||||
// 改动原因:tile0和tile1内存不共享,需要实际传输数据内容,不能传递指针
|
||||
unsafe {
|
||||
memcpy(sync_buffer, &data[CMD_DATA_POS], CONFIG_CMD_DATA_LEN);
|
||||
sync_data_to_tile0(0x05, sync_buffer, CONFIG_CMD_DATA_LEN, 0); // SYNC_CMD_SAVE_USERCONFIG
|
||||
}
|
||||
save_userconfig_info(&data[CMD_DATA_POS]);
|
||||
unsigned audio_mode = (data[CMD_DATA_POS] << 24) | (data[CMD_DATA_POS + 1] << 16) | (data[CMD_DATA_POS + 2] << 8) | data[CMD_DATA_POS + 3] ;
|
||||
// print_buff(data, 6 + length);
|
||||
debug_printf("current audio_mode 0x%08x\n", audio_mode);
|
||||
@@ -402,9 +470,9 @@ void process_command(uint8_t *data)
|
||||
break;
|
||||
|
||||
case REPORT_APP_STATUS:
|
||||
unsigned mode = GetRoleSwitchFlag();
|
||||
debug_printf("mode %08x\n", mode);
|
||||
xmos_printf((unsigned char *)&mode, 4);
|
||||
unsigned old_mode = 0x800100;
|
||||
debug_printf("report app status %08x\n", old_mode);
|
||||
xmos_printf((unsigned char *)&old_mode, 4);
|
||||
|
||||
break;
|
||||
|
||||
@@ -419,8 +487,13 @@ void process_command(uint8_t *data)
|
||||
break;
|
||||
|
||||
case SWITCH_AUDIO_MODE:
|
||||
store_memory(&data[CMD_DATA_POS], 5);
|
||||
unsigned mode_code = 0, old_mode = 0;
|
||||
// 改动原因:store_memory需要在tile0执行(Flash访问),通过同步channel发送
|
||||
// 改动原因:tile0和tile1内存不共享,需要实际传输数据内容,不能传递指针
|
||||
unsafe {
|
||||
memcpy(sync_buffer, &data[CMD_DATA_POS], 5);
|
||||
sync_data_to_tile0(0x0B, sync_buffer, 5, 0); // SYNC_CMD_STORE_MEMORY
|
||||
}
|
||||
unsigned mode_code = 0, old_mode = BT_IN_FLAG;
|
||||
unsigned audio_mode = (data[CMD_DATA_POS] << 24) | (data[CMD_DATA_POS + 1] << 16) | (data[CMD_DATA_POS + 2] << 8) | data[CMD_DATA_POS + 3] ;
|
||||
switch (audio_mode)
|
||||
{
|
||||
@@ -445,10 +518,11 @@ void process_command(uint8_t *data)
|
||||
send_len = send_user_cmd(send_data, SWITCH_AUDIO_MODE, 1, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
|
||||
old_mode = GetRoleSwitchFlag();
|
||||
if (old_mode != mode_code)
|
||||
{
|
||||
SetRoleSwitchFlag(mode_code);
|
||||
// 改动原因:SetRoleSwitchFlag需要在tile0执行,通过同步channel发送
|
||||
sync_to_tile0(0x0A, mode_code, 0); // SYNC_CMD_SET_ROLE_SWITCH
|
||||
//delay_milliseconds(20);
|
||||
debug_printf("switch audio_mode 0x%08x\n", mode_code);
|
||||
cmdConfig.pendingReboot = 1;
|
||||
}
|
||||
@@ -463,9 +537,9 @@ void process_command(uint8_t *data)
|
||||
break;
|
||||
|
||||
case SET_DAC_VOLUME:
|
||||
SET_SHARED_GLOBAL(g_dac_vol, data[CMD_DATA_POS]);
|
||||
// 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0
|
||||
SET_SHARED_GLOBAL(g_pending_dac_vol, (unsigned)data[CMD_DATA_POS]);
|
||||
send_len = send_user_cmd(send_data, SET_DAC_VOLUME, 1, 0);
|
||||
SET_SHARED_GLOBAL(g_dac_vol, data[CMD_DATA_POS]);
|
||||
debug_printf("set dac vol %d\n", data[CMD_DATA_POS]);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
@@ -477,47 +551,59 @@ void process_command(uint8_t *data)
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
|
||||
case HID_PASS_THROUGH:
|
||||
user_set_hidpass(data);
|
||||
debug_printf("hid_pass_through\n");
|
||||
break;
|
||||
|
||||
case SET_ADC_VOLUME:
|
||||
SET_SHARED_GLOBAL(g_adc_vol, data[CMD_DATA_POS]);
|
||||
// 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0
|
||||
SET_SHARED_GLOBAL(g_pending_adc_vol, (unsigned)data[CMD_DATA_POS]);
|
||||
send_len = send_user_cmd(send_data, SET_ADC_VOLUME, 1, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
|
||||
case SET_ADC_LOOP:
|
||||
SET_SHARED_GLOBAL(g_adc_loop, data[CMD_DATA_POS]);
|
||||
// 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0
|
||||
SET_SHARED_GLOBAL(g_pending_adc_loop, (unsigned)data[CMD_DATA_POS]);
|
||||
debug_printf("set adc loop %d\n", data[CMD_DATA_POS]);
|
||||
send_len = send_user_cmd(send_data, SET_ADC_LOOP, 1, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
// 改动原因:0x61 MCU主动设置静音状态给XU316,与0x31 SET_ADC_LOOP一致直接设置g_mute_switch
|
||||
case SET_MCU_MUTE_STATE:
|
||||
if (length >= 1) {
|
||||
unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS];
|
||||
SET_SHARED_GLOBAL(g_mute_switch, mute_val);
|
||||
debug_printf("set mcu mute state (0x61) %d\n", mute_val);
|
||||
send_len = send_user_cmd(send_data, SET_MCU_MUTE_STATE, 0, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
#if UAC1
|
||||
case SET_3D_FPS:
|
||||
SET_SHARED_GLOBAL(g_3d_fps, data[CMD_DATA_POS]);
|
||||
// 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0
|
||||
SET_SHARED_GLOBAL(g_pending_3d_fps, (unsigned)data[CMD_DATA_POS]);
|
||||
debug_printf("set 3d fps %d\n", data[CMD_DATA_POS]);
|
||||
send_len = send_user_cmd(send_data, SET_3D_FPS, 1, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
#endif
|
||||
case SET_LED_MODE:
|
||||
SET_SHARED_GLOBAL(g_led_mode, data[CMD_DATA_POS]);
|
||||
// 改动原因:仅记录待同步值,在 859 区域定时检测到值变化时才同步到 tile0
|
||||
SET_SHARED_GLOBAL(g_pending_led_mode, (unsigned)data[CMD_DATA_POS]);
|
||||
debug_printf("set led mode %d\n", data[CMD_DATA_POS]);
|
||||
send_len = send_user_cmd(send_data, SET_LED_MODE, 1, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
// 改动原因:0x5D/0x5E/0x60 仅由 XMOS 主动发给 MCU(tile1 收到 tile0 sync 后发),MCU 不会主动发这些;0x5F 响应由 MCU 发回
|
||||
case GET_MUTE_SWITCH:
|
||||
// 改动原因:MCU 对 0x5F 请求的响应(1 字节静音值),与监听开关(g_adc_loop)一致,先缓存为pending,再在定时块按变化同步到tile0
|
||||
if (length >= 1) {
|
||||
unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS];
|
||||
SET_SHARED_GLOBAL(g_pending_mute_switch, mute_val);
|
||||
}
|
||||
break;
|
||||
// 改动原因:0x61 MCU设置静音状态给XU316,与0x31 SET_ADC_LOOP一致:先缓存为pending,定时块按变化同步到tile0(sync 0x0E)
|
||||
case SET_MCU_MUTE_STATE:
|
||||
if (length >= 1) {
|
||||
unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS];
|
||||
SET_SHARED_GLOBAL(g_pending_mute_switch, mute_val);
|
||||
debug_printf("set mcu mute state (0x61) %d\n", mute_val);
|
||||
send_len = send_user_cmd(send_data, SET_MCU_MUTE_STATE, 0, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
case SET_INPUT_SOURCE:
|
||||
case SET_MUTE_SWITCH:
|
||||
case SET_LISTEN_SWITCH:
|
||||
// 改动原因:0x5D/0x5E/0x60 仅由 XMOS 发给 MCU,若 MCU 发来则忽略
|
||||
break;
|
||||
case FW_VERSION:
|
||||
send_len = send_user_cmd(send_data, FW_VERSION, 0, 3);
|
||||
xmos_printf(send_data, send_len);
|
||||
@@ -527,382 +613,12 @@ void process_command(uint8_t *data)
|
||||
send_len = send_user_cmd(send_data, FLASH_ID, 0, 20);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
#if EQ_EN
|
||||
// EQ命令处理 - 调用eq.c中的函数
|
||||
case SET_EQ_MODE:
|
||||
{
|
||||
uint8_t mode = data[CMD_DATA_POS];
|
||||
uint8_t result = process_uart_set_eq_mode(mode);
|
||||
uint8_t send_len = 0;
|
||||
|
||||
// 发送确认响应
|
||||
send_len = send_user_cmd(send_data, SET_EQ_MODE, 0, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_EQ_MODE:
|
||||
{
|
||||
uint8_t response[64];
|
||||
// 检查是否有模式参数(数据长度>0表示有参数)
|
||||
if (length > 0) {
|
||||
uint8_t query_mode = data[CMD_DATA_POS];
|
||||
debug_printf("GET_EQ_MODE with mode parameter: %d\n", query_mode);
|
||||
// 如果mode不是0xFF,临时设置request模式用于查询
|
||||
if (query_mode != 0xFF) {
|
||||
SET_SHARED_GLOBAL(g_request_eq_mode, query_mode);
|
||||
}
|
||||
}
|
||||
uint8_t len = process_uart_get_eq_mode(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_MODE_GAIN_AND_NAME:
|
||||
{
|
||||
uint8_t result = process_uart_set_mode_gain_and_name(data);
|
||||
uint8_t send_len = 0;
|
||||
|
||||
// 发送确认响应
|
||||
send_len = send_user_cmd(send_data, SET_MODE_GAIN_AND_NAME, 0, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_EQ_PARAMS:
|
||||
{
|
||||
uint8_t result = process_uart_set_eq_params(data);
|
||||
uint8_t send_len = 0;
|
||||
|
||||
// 发送确认响应
|
||||
send_len = send_user_cmd(send_data, SET_EQ_PARAMS, 0, 0);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_EQ_PARAMS:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_eq_params(data, response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RESET_EQ_PARAMS:
|
||||
{
|
||||
uint8_t result = process_uart_reset_eq_params(data);
|
||||
uint8_t send_len = 0;
|
||||
|
||||
// 发送响应
|
||||
send_data[CMD_DATA_POS] = result;
|
||||
send_len = send_user_cmd(send_data, RESET_EQ_PARAMS, 0, 1);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_DEVICE_INFO:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_device_info(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_EQ_MODE_COUNT:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_eq_mode_count(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_AND_SAVE_EQ_MODE:
|
||||
{
|
||||
uint8_t result = process_uart_set_and_save_eq_mode(data);
|
||||
uint8_t send_len = 0;
|
||||
|
||||
// 发送响应
|
||||
send_data[CMD_DATA_POS] = result;
|
||||
send_len = send_user_cmd(send_data, SET_AND_SAVE_EQ_MODE, 0, 1);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_VOLUME:
|
||||
// 改动原因:使用g_dac_vol,参考SET_DAC_VOLUME的实现方式,直接设置全局变量
|
||||
SET_SHARED_GLOBAL(g_dac_vol, data[CMD_DATA_POS]);
|
||||
send_len = send_user_cmd(send_data, SET_VOLUME, 1, 0);
|
||||
SET_SHARED_GLOBAL(g_dac_vol, data[CMD_DATA_POS]);
|
||||
debug_printf("set volume %d\n", data[CMD_DATA_POS]);
|
||||
xmos_printf(send_data, send_len);
|
||||
break;
|
||||
|
||||
case GET_VOLUME:
|
||||
// 改动原因:直接读取g_dac_vol的值并返回,参考SET_DAC_VOLUME的实现方式
|
||||
{
|
||||
uint8_t response[64];
|
||||
unsigned dac_vol;
|
||||
GET_SHARED_GLOBAL(dac_vol, g_dac_vol);
|
||||
// 构建响应数据包:0x55 0xAA 0x00 0x4A 0x01 [volume] [checksum]
|
||||
response[0] = 0x55; // 帧头1
|
||||
response[1] = 0xAA; // 帧头2
|
||||
response[2] = 0x00; // 版本
|
||||
response[3] = GET_VOLUME; // 命令码
|
||||
response[4] = 0x01; // 数据长度
|
||||
response[5] = (uint8_t)dac_vol; // 音量级别
|
||||
// 计算校验和
|
||||
uint8_t checksum_pos = 6;
|
||||
// 改动原因:使用check_sum函数计算校验和,与send_user_cmd函数保持一致
|
||||
unsafe {
|
||||
response[checksum_pos] = check_sum(response, checksum_pos);
|
||||
}
|
||||
uint8_t len = checksum_pos + 1;
|
||||
debug_printf("get volume %d\n", dac_vol);
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_LED_INFO:
|
||||
{
|
||||
uint8_t led_index = data[CMD_DATA_POS];
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_led_info(led_index, response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_LED_SWITCH:
|
||||
// 改动原因:参考SET_LED_MODE,直接设置g_led_mode的值,0=关,1=开
|
||||
{
|
||||
uint8_t led_index = data[CMD_DATA_POS];
|
||||
uint8_t led_switch = data[CMD_DATA_POS + 1];
|
||||
SET_SHARED_GLOBAL(g_led_mode, led_switch);
|
||||
debug_printf("set led switch (g_led_mode) %d\n", led_switch);
|
||||
uint8_t send_len = 0;
|
||||
|
||||
// 发送响应
|
||||
send_data[CMD_DATA_POS] = 0; // 状态码:成功
|
||||
send_len = send_user_cmd(send_data, SET_LED_SWITCH, 0, 1);
|
||||
xmos_printf(send_data, send_len);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_LED_SWITCH:
|
||||
// 改动原因:参考SET_LED_MODE,直接读取g_led_mode的值,0=关,1=开
|
||||
{
|
||||
uint8_t led_index = data[CMD_DATA_POS];
|
||||
uint8_t response[64];
|
||||
unsigned led_mode;
|
||||
GET_SHARED_GLOBAL(led_mode, g_led_mode);
|
||||
|
||||
// 构建响应数据包:0x55 0xAA 0x00 0x4D 0x02 [led_index] [led_mode] [checksum]
|
||||
response[0] = 0x55; // 帧头1
|
||||
response[1] = 0xAA; // 帧头2
|
||||
response[2] = 0x00; // 版本
|
||||
response[3] = GET_LED_SWITCH; // 命令码
|
||||
response[4] = 0x02; // 数据长度
|
||||
response[5] = led_index; // LED索引
|
||||
response[6] = (uint8_t)led_mode; // LED开关状态
|
||||
// 计算校验和
|
||||
uint8_t checksum_pos = 7;
|
||||
unsafe {
|
||||
response[checksum_pos] = check_sum(response, checksum_pos);
|
||||
}
|
||||
uint8_t len = checksum_pos + 1;
|
||||
debug_printf("get led switch (g_led_mode) %d\n", led_mode);
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_LED_STATUS:
|
||||
{
|
||||
uint8_t led_index = data[CMD_DATA_POS];
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_led_status(led_index, response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_LED_COUNT:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_led_count(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_UAC_MODE_INFO:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_uac_mode_info(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_UAC_MODE:
|
||||
{
|
||||
uint8_t uac_mode = data[CMD_DATA_POS];
|
||||
// process_uart_set_uac_mode(uac_mode);
|
||||
// 设备重启,无响应
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_CURRENT_UAC_MODE:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_current_uac_mode(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_EQ_ENABLE:
|
||||
{
|
||||
uint8_t enable = data[CMD_DATA_POS];
|
||||
uint8_t result = process_uart_set_eq_enable(enable);
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_eq_enable_response(result, enable, response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_EQ_ENABLE:
|
||||
{
|
||||
debug_printf("user_uart.xc: GET_EQ_ENABLE command received, start processing\n");
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_eq_enable(response, sizeof(response));
|
||||
debug_printf("user_uart.xc: GET_EQ_ENABLE process_uart_get_eq_enable returned len=%d\n", len);
|
||||
if (len > 0) {
|
||||
debug_printf("user_uart.xc: GET_EQ_ENABLE sending response, length=%d, data: ", len);
|
||||
for (int i = 0; i < len && i < 16; i++) {
|
||||
debug_printf("%02X ", response[i]);
|
||||
}
|
||||
debug_printf("\n");
|
||||
xmos_printf(response, len);
|
||||
debug_printf("user_uart.xc: GET_EQ_ENABLE response sent\n");
|
||||
} else {
|
||||
debug_printf("user_uart.xc: GET_EQ_ENABLE error - process_uart_get_eq_enable returned len=0\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_SAMPLE_FORMAT:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_sample_format(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_GAIN_MODE:
|
||||
{
|
||||
uint8_t gain_mode = data[CMD_DATA_POS];
|
||||
uint8_t result = process_uart_set_gain_mode(gain_mode);
|
||||
// 无需发送响应,根据协议描述
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_GAIN_MODE:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_gain_mode(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_FILTER_MODE:
|
||||
{
|
||||
uint8_t filter_mode = data[CMD_DATA_POS];
|
||||
uint8_t result = process_uart_set_filter_mode(filter_mode);
|
||||
// 无需发送响应,根据协议描述
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_FILTER_MODE:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_filter_mode(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_GAME_MODE:
|
||||
{
|
||||
uint8_t game_mode = data[CMD_DATA_POS];
|
||||
// 改动原因:UART 0x5A命令透传给MCU处理,MCU负责执行模式设置和参数保存
|
||||
// process_uart_set_game_mode(game_mode);
|
||||
// 无需发送响应,根据协议描述
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_GAME_MODE:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_game_mode(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GET_FIRMWARE_VERSION:
|
||||
{
|
||||
uint8_t response[64];
|
||||
uint8_t len = process_uart_get_firmware_version(response, sizeof(response));
|
||||
if (len > 0) {
|
||||
xmos_printf(response, len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
// 改动原因:添加0x5D SET_INPUT_SOURCE,由HID 0xB0触发后XMOS主动发给MCU;若MCU发来0x5D则忽略
|
||||
case SET_INPUT_SOURCE:
|
||||
break;
|
||||
// 改动原因:添加0x5E SET_MUTE_SWITCH,由HID 0xB1触发后XMOS发给MCU;若MCU发来0x5E则忽略
|
||||
case SET_MUTE_SWITCH:
|
||||
break;
|
||||
// 改动原因:0x5F GET_MUTE_SWITCH 响应由MCU发来,含1字节静音值;与g_adc_loop一致直接设置g_mute_switch,0xB2读与变化上报均用g_mute_switch
|
||||
case GET_MUTE_SWITCH:
|
||||
if (length >= 1) {
|
||||
unsigned mute_val = (data[CMD_DATA_POS] > 1) ? 0 : (unsigned)data[CMD_DATA_POS];
|
||||
SET_SHARED_GLOBAL(g_mute_switch, mute_val);
|
||||
}
|
||||
break;
|
||||
// 改动原因:添加0x60 SET_LISTEN_SWITCH,由HID 0xB3触发后XMOS发给MCU;若MCU发来0x60则忽略
|
||||
case SET_LISTEN_SWITCH:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
cmdConfig.cmdCount = 0;
|
||||
}
|
||||
|
||||
|
||||
void xmos_uart_receive(void)
|
||||
{
|
||||
static unsigned cmd_start_time = 0;
|
||||
@@ -1137,115 +853,113 @@ void heatTick(unsigned long boot_time)
|
||||
|
||||
}
|
||||
|
||||
extern unsigned GetDFUFlag();
|
||||
extern uint8_t key_validate(uint8_t offset);
|
||||
extern void flash_opt_unlock(void);
|
||||
|
||||
/* 改动原因:固件升级 START 已移至 AudioHwRemote2,不再在此接收 c_dfu */
|
||||
void uart_handler(streaming chanend c_tx, streaming chanend c_rx)
|
||||
void uart_handler(streaming chanend c_tx, streaming chanend c_rx,chanend c_sync)
|
||||
{
|
||||
unsigned long boot_time = get_reference_time();
|
||||
long int flag = 0;
|
||||
long int dfu_flag = 0x11042011;
|
||||
uint8_t uart_rx_byte;
|
||||
g_xu316_id = read_key();
|
||||
unsigned long heat_tick_time = get_reference_time() + BEAT_DELAY * 10;
|
||||
// 改动原因:保存同步channel到全局变量,供process_command使用(使用unsafe转换)
|
||||
unsafe {
|
||||
g_c_uart_sync = (chanend)c_sync;
|
||||
}
|
||||
cmdConfig.pendingReboot = 0;
|
||||
cmdConfig.cmdPending = CMD_NONE;
|
||||
unsigned long se_time = 0;
|
||||
timer se_tmr;
|
||||
se_tmr :> se_time;
|
||||
se_time += 2000000;
|
||||
|
||||
#if UAC1
|
||||
delay_milliseconds(100);
|
||||
#endif
|
||||
|
||||
#if XUA_DFU_EN
|
||||
flag = GetDFUFlag();
|
||||
#endif
|
||||
// delay_milliseconds(100);
|
||||
|
||||
if (key_validate(1) == 1)
|
||||
{
|
||||
SetKeyFlag(0x20241224);
|
||||
}
|
||||
|
||||
|
||||
flash_opt_unlock();
|
||||
|
||||
#if BOOT_MODE
|
||||
|
||||
load_configs();
|
||||
|
||||
#if (XUA_DFU_EN == 1)
|
||||
get_pid_vid();
|
||||
if (flag == dfu_flag)
|
||||
SET_SHARED_GLOBAL(g_usb_state, 1);
|
||||
|
||||
#if (FACT_MODE == 1)
|
||||
SET_SHARED_GLOBAL(g_usb_state, 1);
|
||||
return;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
cmdConfig.startApp = 3;
|
||||
|
||||
#if (NUM_USB_CHAN_OUT != 0) || (NUM_USB_CHAN_IN != 0)
|
||||
load_configs();
|
||||
get_pid_vid();
|
||||
SET_SHARED_GLOBAL(g_usb_state, 1);
|
||||
#endif
|
||||
|
||||
|
||||
// 改动原因:load_configs和get_pid_vid需要在tile0执行(Flash访问和PID/VID设置),通过同步channel发送
|
||||
// 注意:此时g_c_uart_sync已经设置,可以直接使用
|
||||
sync_to_tile0(0x01, 0, 0); // SYNC_CMD_LOAD_CONFIGS
|
||||
sync_to_tile0(0x06, 0, 0); // SYNC_CMD_GET_PID_VID
|
||||
#endif
|
||||
|
||||
boot_time = get_reference_time();
|
||||
static unsigned char heat_tick_first_executed = 0; // 改动原因:跟踪heatTick是否已执行过第一次
|
||||
|
||||
while(1)
|
||||
{
|
||||
select {
|
||||
case c_rx :> uart_rx_byte:
|
||||
#if HID_DFU_EN
|
||||
if (!g_in_fw_upgrade)
|
||||
#endif
|
||||
{
|
||||
X_RXbuff[X_Rxfp] = uart_rx_byte;
|
||||
X_Rxfp = (X_Rxfp + 1) % MAX_RX_LEN;
|
||||
//debug_printf("in[%02x] %d %d len %d\n", uart_rx_byte, X_Rxfp, X_Rxrp, MAX_RX_LEN - ((X_Rxfp - X_Rxrp + MAX_RX_LEN) % MAX_RX_LEN));
|
||||
xmos_uart_receive();
|
||||
}
|
||||
break;
|
||||
case se_tmr when timerafter(se_time) :> void :
|
||||
se_time += 400000;
|
||||
/* 改动原因:若有固件升级开始/结束通知,先组包 0x62 发给 MCU,再清零标志 */
|
||||
#if HID_DFU_EN
|
||||
{
|
||||
unsigned notify = get_firmware_upgrade_mcu_notify();
|
||||
if (notify != 0)
|
||||
{
|
||||
unsigned char response[8];
|
||||
response[0] = 0x55;
|
||||
response[1] = 0xAA;
|
||||
response[2] = 0x01;
|
||||
response[3] = (unsigned char)FIRMWARE_UPGRADE_NOTIFY;
|
||||
response[4] = 0x01;
|
||||
response[5] = (unsigned char)notify;
|
||||
unsafe {
|
||||
response[6] = check_sum((unsigned char *)response, 6);
|
||||
}
|
||||
xmos_printf(response, 7);
|
||||
clear_firmware_upgrade_mcu_notify();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if XUA_DFU_EN
|
||||
if (flag != dfu_flag)
|
||||
#endif
|
||||
|
||||
|
||||
{
|
||||
xmos_printf_pross(c_tx);
|
||||
heatTick(boot_time);
|
||||
// 改动原因:第一次执行要在boot_time后200ms,后续一直执行
|
||||
unsigned long tick_now = get_reference_time();
|
||||
if (heat_tick_first_executed == 0) {
|
||||
// 第一次执行:检查是否已经过了boot_time + 200ms
|
||||
if (timeafter(tick_now, boot_time + 20000000)) { // 200ms = 20000000 时间单位(参考SEND_CMD_TIMEOUT)
|
||||
heatTick(boot_time);
|
||||
heat_tick_first_executed = 1;
|
||||
}
|
||||
} else {
|
||||
// 后续执行:一直执行
|
||||
heatTick(boot_time);
|
||||
}
|
||||
}
|
||||
|
||||
/* 改动原因:0x07/0x08/0x09/0x0C/0x0D/0x0E 仅当 pending 与 last_sync 不同时才同步到 tile0 */
|
||||
{
|
||||
unsigned pending_val, last_val;
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_dac_vol);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_dac_vol);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x07, pending_val, 0); /* SYNC_CMD_SET_DAC_VOLUME */
|
||||
SET_SHARED_GLOBAL(g_last_sync_dac_vol, pending_val);
|
||||
}
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_adc_vol);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_adc_vol);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x08, pending_val, 0); /* SYNC_CMD_SET_ADC_VOLUME */
|
||||
SET_SHARED_GLOBAL(g_last_sync_adc_vol, pending_val);
|
||||
}
|
||||
#if UAC1
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_3d_fps);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_3d_fps);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x09, pending_val, 0); /* SYNC_CMD_SET_3D_FPS */
|
||||
SET_SHARED_GLOBAL(g_last_sync_3d_fps, pending_val);
|
||||
}
|
||||
#endif
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_led_mode);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_led_mode);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x0C, pending_val, 0); /* SYNC_CMD_SET_LED_MODE */
|
||||
SET_SHARED_GLOBAL(g_last_sync_led_mode, pending_val);
|
||||
}
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_adc_loop);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_adc_loop);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x0D, pending_val, 0); /* SYNC_CMD_SET_ADC_LOOP */
|
||||
SET_SHARED_GLOBAL(g_last_sync_adc_loop, pending_val);
|
||||
}
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_mute_switch);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_mute_switch);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x0E, pending_val, 0); /* SYNC_CMD_MUTE_VALUE_FROM_MCU */
|
||||
SET_SHARED_GLOBAL(g_last_sync_mute_switch, pending_val);
|
||||
}
|
||||
GET_SHARED_GLOBAL(pending_val, g_pending_mcu_mute);
|
||||
GET_SHARED_GLOBAL(last_val, g_last_sync_mcu_mute);
|
||||
if (pending_val != last_val) {
|
||||
sync_to_tile0(0x0F, pending_val, 0); /* SYNC_CMD_SET_MCU_MUTE_STATE */
|
||||
SET_SHARED_GLOBAL(g_last_sync_mcu_mute, pending_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmdConfig.pendingReboot == 1)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user