杰理AC695X Linein模式执行流程详解

Linein模式执行流程详解

概述

本文档详细描述linein模式从系统启动到正常工作的完整执行流程,包括关键函数调用链、接口跳转关系和代码位置。


完整执行流程图


#mermaid-svg-dwVmHQRgbaITdaFj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dwVmHQRgbaITdaFj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dwVmHQRgbaITdaFj .error-icon{fill:#552222;}#mermaid-svg-dwVmHQRgbaITdaFj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dwVmHQRgbaITdaFj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dwVmHQRgbaITdaFj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dwVmHQRgbaITdaFj .marker.cross{stroke:#333333;}#mermaid-svg-dwVmHQRgbaITdaFj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dwVmHQRgbaITdaFj p{margin:0;}#mermaid-svg-dwVmHQRgbaITdaFj .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dwVmHQRgbaITdaFj .cluster-label text{fill:#333;}#mermaid-svg-dwVmHQRgbaITdaFj .cluster-label span{color:#333;}#mermaid-svg-dwVmHQRgbaITdaFj .cluster-label span p{background-color:transparent;}#mermaid-svg-dwVmHQRgbaITdaFj .label text,#mermaid-svg-dwVmHQRgbaITdaFj span{fill:#333;color:#333;}#mermaid-svg-dwVmHQRgbaITdaFj .node rect,#mermaid-svg-dwVmHQRgbaITdaFj .node circle,#mermaid-svg-dwVmHQRgbaITdaFj .node ellipse,#mermaid-svg-dwVmHQRgbaITdaFj .node polygon,#mermaid-svg-dwVmHQRgbaITdaFj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dwVmHQRgbaITdaFj .rough-node .label text,#mermaid-svg-dwVmHQRgbaITdaFj .node .label text,#mermaid-svg-dwVmHQRgbaITdaFj .image-shape .label,#mermaid-svg-dwVmHQRgbaITdaFj .icon-shape .label{text-anchor:middle;}#mermaid-svg-dwVmHQRgbaITdaFj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dwVmHQRgbaITdaFj .rough-node .label,#mermaid-svg-dwVmHQRgbaITdaFj .node .label,#mermaid-svg-dwVmHQRgbaITdaFj .image-shape .label,#mermaid-svg-dwVmHQRgbaITdaFj .icon-shape .label{text-align:center;}#mermaid-svg-dwVmHQRgbaITdaFj .node.clickable{cursor:pointer;}#mermaid-svg-dwVmHQRgbaITdaFj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dwVmHQRgbaITdaFj .arrowheadPath{fill:#333333;}#mermaid-svg-dwVmHQRgbaITdaFj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dwVmHQRgbaITdaFj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dwVmHQRgbaITdaFj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dwVmHQRgbaITdaFj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dwVmHQRgbaITdaFj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dwVmHQRgbaITdaFj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dwVmHQRgbaITdaFj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dwVmHQRgbaITdaFj .cluster text{fill:#333;}#mermaid-svg-dwVmHQRgbaITdaFj .cluster span{color:#333;}#mermaid-svg-dwVmHQRgbaITdaFj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dwVmHQRgbaITdaFj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dwVmHQRgbaITdaFj rect.text{fill:none;stroke-width:0;}#mermaid-svg-dwVmHQRgbaITdaFj .icon-shape,#mermaid-svg-dwVmHQRgbaITdaFj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dwVmHQRgbaITdaFj .icon-shape p,#mermaid-svg-dwVmHQRgbaITdaFj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dwVmHQRgbaITdaFj .icon-shape .label rect,#mermaid-svg-dwVmHQRgbaITdaFj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dwVmHQRgbaITdaFj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dwVmHQRgbaITdaFj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dwVmHQRgbaITdaFj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

通过
失败
ADC采样
模拟直通
DAC输入
按键事件
设备事件
其他事件
设备拔出
系统启动
app_task_loop主循环
检测到linein设备?
app_task_switch_to

APP_LINEIN_TASK
其他任务模式
linein_app_check

设备在线检查
app_linein_task

linein主任务
切换失败
linein_app_init

应用初始化
UI_SHOW_WINDOW

显示linein界面
sys_key_event_enable

开启按键响应
clock_idle

时钟配置
tone_play_with_callback_by_name

播放linein提示音
line_tone_play_end_callback

提示音结束回调
app_task_put_key_msg

KEY_LINEIN_START
linein_key_msg_deal

按键消息处理
linein_start

启动linein音频
输入方式选择
__linein_way_adc_start

ADC输入方式
__linein_way_analog_start

模拟输入方式
__linein_way_dac_analog_start

DAC输入方式
linein_dec_open

打开解码器
audio_linein0/1/2_open

打开模拟通道
audio_linein_via_dac_open

打开DAC通道
消息循环处理
linein_sys_event_handler

系统事件处理
事件类型
linein_key_msg_deal

按键处理
设备插拔处理
app_default_event_deal

通用事件处理
音量调节/播放控制
app_task_switch_next

切换到下一模式
linein_task_close

任务退出清理
UI_HIDE_CURR_WINDOW

隐藏界面
linein_stop

停止音频
tone_play_stop_by_path

停止提示音
任务结束


关键执行阶段详解

1. 系统启动和任务调度

文件 : apps/soundbox/app_main.c

c 复制代码
void app_task_loop()
{
    while (1) {
        switch (app_curr_task) {
        case APP_LINEIN_TASK:
            log_info("APP_LINEIN_TASK \n");
            app_linein_task();  // 🔥调用linein主任务
            break;
        // ... 其他任务
        }
        app_task_clear_key_msg();//清理按键消息,防止消息堆积
        vm_check_all(0); //检查整理VM
    }
}

2. 任务切换和设备检测

文件 : apps/soundbox/task_manager/app_task_switch.c

c 复制代码
// 任务列表配置
static const u8 app_task_list[] = {
#if TCFG_APP_BT_EN
    APP_BT_TASK,
#endif
#if TCFG_APP_MUSIC_EN
    APP_MUSIC_TASK,
#endif
#if TCFG_APP_LINEIN_EN
    APP_LINEIN_TASK,  // 🔥第7号任务
#endif
    // ... 其他任务
};

// 任务切换检查
static int app_task_switch_check(u8 app_task)
{
    switch (app_task) {
#if TCFG_APP_LINEIN_EN
    case APP_LINEIN_TASK:
        ret = linein_app_check();  // 🔥检查linein设备是否在线
        break;
#endif
    }
    return ret;
}

// 任务切换函数
int app_task_switch_to(u8 app_task)
{
    if (app_curr_task == app_task) {
        return false;
    }

    if (!app_task_switch_check(app_task)) {  // 🔥设备检查
        return false;
    }

    app_prev_task = app_curr_task;
    app_next_task = app_task;
    app_task_put_usr_msg(APP_MSG_SWITCH_TASK, 0);  // 🔥发送切换消息

    return TRUE;
}

3. Linein设备在线检测

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
int linein_app_check(void)
{
    if (linein_is_online()) {  // 🔥检查设备是否在线
        return true;
    }
    return false;
}

文件 : apps/soundbox/task_manager/linein/linein_dev.c

c 复制代码
// 设备检测定时器回调
static void linein_detect(void *arg)
{
    u8 cur_stu = linein_sample_detect(arg);  // 🔥采样检测

    if (cur_stu != __this->stu) {
        __this->stu = cur_stu;
        __this->cnt = 0;
        __this->active = 1;
    } else {
        __this->cnt++;
    }

    if (__this->cnt < LINEIN_DETECT_CNT) {//滤波计算
        return;
    }

    // 🔥设备状态变化处理
    if ((linein_is_online()) && (!__this->stu)) {
        linein_set_online(false);
        linein_event_notify(DEVICE_EVENT_OUT);//发布下线消息
    } else if ((!linein_is_online()) && (__this->stu)) {
        linein_set_online(true);
        linein_event_notify(DEVICE_EVENT_IN);//发布上线消息
    }
}

4. Linein主任务执行

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
void app_linein_task()
{
    int msg[32];

#if TCFG_APP_BT_EN
    linein_bt_back_flag = get_bt_back_flag();//从蓝牙后台返回标志
    set_bt_back_flag(0);
#endif

    // 🔥1. 初始化linein应用
    linein_app_init();

    // 🔥2. 播放linein模式提示音
#if TCFG_DEC2TWS_ENABLE
    if (get_tws_background_connected_flag()) { //不播放提示音
        app_task_put_key_msg(KEY_LINEIN_START, 0);
        set_tws_background_connected_flag(0);
    } else
#endif
    {
        err = tone_play_with_callback_by_name(tone_table[IDEX_TONE_LINEIN], 1,
                                              line_tone_play_end_callback, (void *)IDEX_TONE_LINEIN);
    }

    // 🔥3. 进入消息循环
    while (1) {
        app_task_get_msg(msg, ARRAY_SIZE(msg), 1);

        switch (msg[0]) {
        case APP_MSG_SYS_EVENT:
            if (linein_sys_event_handler((struct sys_event *)(&msg[1])) == false) {
                app_default_event_deal((struct sys_event *)(&msg[1]));
            }
            break;
        }

        // 🔥4. 检查是否需要退出任务
        if (app_task_exitting()) {
            linein_task_close();
            return;
        }
    }
}

5. Linein应用初始化

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
static void linein_app_init(void)
{
    linein_idle_flag = 0;
    UI_SHOW_WINDOW(ID_WINDOW_LINEIN);     // 🔥打开ui主页
    UI_SHOW_MENU(MENU_AUX, 0, 0, NULL);  // 🔥显示AUX菜单
    sys_key_event_enable();               // 🔥开启按键
    ui_update_status(STATUS_LINEIN_MODE); // 🔥更新状态
    clock_idle(LINEIN_IDLE_CLOCK);        // 🔥时钟配置
}

6. 提示音播放完毕回调

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
static void line_tone_play_end_callback(void *priv, int flag)
{
    u32 index = (u32)priv;

    if (APP_LINEIN_TASK != app_get_curr_task()) {
        log_error("tone callback task out \n");
        return;
    }

    switch (index) {
    case IDEX_TONE_LINEIN:
        // 🔥提示音播放结束,启动播放器播放
        app_task_put_key_msg(KEY_LINEIN_START, 0);
        break;
    }
}

7. 按键消息处理和音频启动

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
static int linein_key_msg_deal(struct sys_event *event)
{
    struct key_event *key = &event->u.key;
    int key_event = key->event;
    int key_value = key->value;

    switch (key_event) {
    case KEY_LINEIN_START:
        linein_start();  // 🔥启动linein音频
        linein_last_onoff = 1;
        UI_REFLASH_WINDOW(true);//刷新主页并且支持打断显示
        break;
    case KEY_MUSIC_PP:
        linein_last_onoff = linein_volume_pp();  // 🔥播放/暂停控制
        linein_last_onoff ? ui_update_status(STATUS_LINEIN_PLAY)
        : ui_update_status(STATUS_LINEIN_PAUSE);
        break;
    case KEY_VOL_UP:
        linein_key_vol_up();    // 🔥音量增加
        break;
    case KEY_VOL_DOWN:
        linein_key_vol_down();  // 🔥音量减少
        break;
    }
    return TRUE;
}

8. Linein音频启动流程

文件 : apps/soundbox/task_manager/linein/linein_api.c

c 复制代码
int linein_start(void)
{
    if (__this->onoff == 1) {
        log_info("linein is aleady start\n");
        return true;
    }

    // 🔥根据配置选择不同的输入方式
#if (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)
    set_dac_start_delay_time(1, 1); //设置dac 通道的启动延时
    __linein_way_adc_start();        // 🔥ADC采样方式
    __this->audio_state = APP_AUDIO_STATE_MUSIC;

#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ANALOG)
    __this->volume = app_audio_get_volume(__this->audio_state);
    __this->audio_state = APP_AUDIO_STATE_LINEIN;
    __linein_way_analog_start();     // 🔥模拟直通方式
    audio_dac_vol_mute_lock(1);

#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_DAC)
    __this->volume = app_audio_get_volume(__this->audio_state);
    __this->audio_state = APP_AUDIO_STATE_LINEIN;
    __linein_way_dac_analog_start(); // 🔥DAC输入方式
    audio_dac_vol_mute_lock(1);
#endif

    __this->volume = app_audio_get_volume(__this->audio_state);
    __this->onoff = 1;
    UI_REFLASH_WINDOW(false);//刷新主页并且支持打断显示
    return true;
}

9. 三种输入方式详解

9.1 ADC采样方式

文件 : apps/soundbox/task_manager/linein/linein_api.c

c 复制代码
static inline void __linein_way_adc_start()
{
#if (TCFG_LINEIN_MULTIPLEX_WITH_FM && (defined(CONFIG_CPU_BR25)))
    linein_dec_open(AUDIO_LIN1R_CH, 44100);  // 🔥696X系列FM与LINEIN复用脚
#else
    linein_dec_open(TCFG_LINEIN_LR_CH, 44100); // 🔥打开linein解码器
#endif
}
9.2 模拟直通方式

文件 : apps/soundbox/task_manager/linein/linein_api.c

c 复制代码
static inline void __linein_way_analog_start()
{
    app_audio_state_switch(__this->audio_state, get_max_sys_vol());
    app_audio_set_volume(__this->audio_state, __this->volume, 1);

    // 🔥根据通道配置打开对应的linein
    if (TCFG_LINEIN_LR_CH & (BIT(0) | BIT(1))) {
        audio_linein0_open(TCFG_LINEIN_LR_CH, 1);
    } else if (TCFG_LINEIN_LR_CH & (BIT(2) | BIT(3))) {
        audio_linein1_open(TCFG_LINEIN_LR_CH, 1);
    } else if (TCFG_LINEIN_LR_CH & (BIT(4) | BIT(5))) {
        audio_linein2_open(TCFG_LINEIN_LR_CH, 1);
    }

    // 🔥通道合并和增益设置
    if (TCFG_LINEIN_LR_CH != AUDIO_LIN0_LR && TCFG_LINEIN_LR_CH != AUDIO_LIN1_LR && TCFG_LINEIN_LR_CH != AUDIO_LIN2_LR) {
        audio_linein_ch_combine(1, 1);
    }

    audio_linein_gain(1);   // 🔥high gain
    if (app_audio_get_volume(__this->audio_state)) {
        audio_linein_mute(0);
        app_audio_set_volume(__this->audio_state, app_audio_get_volume(__this->audio_state), 1);
    }
}
9.3 DAC输入方式

文件 : apps/soundbox/task_manager/linein/linein_api.c

c 复制代码
static inline void __linein_way_dac_analog_start()
{
    app_audio_state_switch(__this->audio_state, get_max_sys_vol());
    app_audio_set_volume(__this->audio_state, __this->volume, 1);

    // 🔥通过DAC通道输入
    if ((TCFG_LINEIN_LR_CH == AUDIO_LIN_DACL_CH)
        || (TCFG_LINEIN_LR_CH == AUDIO_LIN_DACR_CH)) {
        audio_linein_via_dac_open(TCFG_LINEIN_LR_CH, 1);
    } else {
        ASSERT(0, "linein ch err\n");
    }
    linein_volume_set(app_audio_get_volume(__this->audio_state));
}

10. 系统事件处理

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
static int linein_sys_event_handler(struct sys_event *event)
{
    int ret = TRUE;
    switch (event->type) {
    case SYS_KEY_EVENT:
        return linein_key_msg_deal(event);  // 🔥按键事件处理
        break;
    case SYS_DEVICE_EVENT:
        if ((u32)event->arg == DEVICE_EVENT_FROM_LINEIN) {
            if (event->u.dev.event == DEVICE_EVENT_IN) {
                log_info("linein online \n");  // 🔥设备插入
            } else if (event->u.dev.event == DEVICE_EVENT_OUT) {
                log_info("linein offline \n"); // 🔥设备拔出
                app_task_switch_next();         // 🔥切换到下一模式
            }
            return true;
        }
        return false;
        break;
    default:
        return false;
    }
    return false;
}

11. Linein任务退出和清理

文件 : apps/soundbox/task_manager/linein/linein.c

c 复制代码
static void linein_task_close(void)
{
    UI_HIDE_CURR_WINDOW();                              // 🔥隐藏当前窗口
    linein_stop();                                      // 🔥停止linein音频
    tone_play_stop_by_path(tone_table[IDEX_TONE_LINEIN]); // 🔥停止提示音
    linein_idle_flag = 1;                               // 🔥设置空闲标志
}

文件 : apps/soundbox/task_manager/linein/linein_api.c

c 复制代码
void linein_stop(void)
{
    if (__this->onoff == 0) {
        log_info("linein is aleady stop\n");
        return;
    }

    // 🔥根据输入方式进行相应的关闭操作
#if (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)
    set_dac_start_delay_time(0, 0);  //把dac的延时设置回默认的配置
    linein_dec_close();              // 🔥关闭解码器

#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ANALOG)
    // 🔥关闭对应的linein通道
    if (TCFG_LINEIN_LR_CH & (BIT(0) | BIT(1))) {
        audio_linein0_close(TCFG_LINEIN_LR_CH, 0);
    } else if (TCFG_LINEIN_LR_CH & (BIT(2) | BIT(3))) {
        audio_linein1_close(TCFG_LINEIN_LR_CH, 0);
    } else if (TCFG_LINEIN_LR_CH & (BIT(4) | BIT(5))) {
        audio_linein2_close(TCFG_LINEIN_LR_CH, 0);
    }
    audio_dac_vol_mute_lock(0);

#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_DAC)
    audio_linein_via_dac_close(TCFG_LINEIN_LR_CH, 0); // 🔥关闭DAC通道
    audio_dac_vol_mute_lock(0);
#endif

    app_audio_set_volume(APP_AUDIO_STATE_MUSIC, __this->volume, 1);
    __this->onoff = 0;
}

关键函数调用链总结

12.1 系统启动到任务切换调用链

复制代码
main()
├── app_task_handler()
├── app_main()
└── app_task_loop()
    ├── 检测设备插入事件
    ├── app_task_switch_to(APP_LINEIN_TASK)
    ├── app_task_switch_check()
    └── linein_app_check()

12.2 Linein主任务调用链

复制代码
app_linein_task()
├── get_bt_back_flag()                     // 检查蓝牙后台标志
├── linein_app_init()                      // 应用初始化
│   ├── UI_SHOW_WINDOW(ID_WINDOW_LINEIN)   // 显示界面
│   ├── UI_SHOW_MENU(MENU_AUX)             // 显示菜单
│   ├── sys_key_event_enable()             // 开启按键
│   ├── ui_update_status(STATUS_LINEIN_MODE) // 更新状态
│   └── clock_idle(LINEIN_IDLE_CLOCK)      // 时钟配置
├── tone_play_with_callback_by_name()      // 播放提示音
└── 消息循环
    ├── app_task_get_msg()                 // 获取消息
    ├── linein_sys_event_handler()         // 事件处理
    └── app_task_exitting()                // 检查退出

12.3 提示音回调到音频启动调用链

复制代码
line_tone_play_end_callback()
├── app_task_put_key_msg(KEY_LINEIN_START) // 发送启动消息
└── linein_key_msg_deal()                  // 按键消息处理
    └── linein_start()                     // 启动音频
        ├── __linein_way_adc_start()       // ADC方式
        │   └── linein_dec_open()          // 打开解码器
        ├── __linein_way_analog_start()    // 模拟方式
        │   ├── audio_linein0/1/2_open()   // 打开模拟通道
        │   ├── audio_linein_ch_combine()  // 通道合并
        │   └── audio_linein_gain()        // 设置增益
        └── __linein_way_dac_analog_start() // DAC方式
            └── audio_linein_via_dac_open() // 打开DAC通道

12.4 设备检测调用链

复制代码
linein_driver_init()
├── linein_set_online()                    // 设置在线状态
└── sys_timer_add(linein_detect)           // 添加检测定时器
    └── linein_detect()                    // 定时检测
        ├── linein_sample_detect()         // 采样检测
        ├── 滤波处理
        └── linein_event_notify()          // 发送设备事件
            └── linein_sys_event_handler() // 事件处理
                └── app_task_switch_next() // 设备拔出时切换模式

12.5 任务退出调用链

复制代码
app_task_exitting()
└── linein_task_close()                    // 任务关闭
    ├── UI_HIDE_CURR_WINDOW()              // 隐藏界面
    ├── linein_stop()                      // 停止音频
    │   ├── linein_dec_close()             // 关闭解码器(ADC方式)
    │   ├── audio_linein0/1/2_close()      // 关闭模拟通道(模拟方式)
    │   └── audio_linein_via_dac_close()   // 关闭DAC通道(DAC方式)
    ├── tone_play_stop_by_path()           // 停止提示音
    └── linein_idle_flag = 1               // 设置空闲标志

配置和接口说明

13.1 关键配置宏定义

文件 : apps/soundbox/board/br25/board_xxx_cfg.h

c 复制代码
#define TCFG_APP_LINEIN_EN              1                    // linein功能使能
#define TCFG_LINEIN_ENABLE              TCFG_APP_LINEIN_EN   // linein使能
#define TCFG_LINEIN_LR_CH               AUDIO_LIN0_LR        // linein通道配置
#define TCFG_LINEIN_CHECK_PORT          IO_PORTB_01          // linein检测IO
#define TCFG_LINEIN_PORT_UP_ENABLE      1                    // 检测IO上拉使能
#define TCFG_LINEIN_PORT_DOWN_ENABLE    0                    // 检测IO下拉使能
#define TCFG_LINEIN_DETECT_ENABLE       ENABLE               // 是否使用linein检测
#define TCFG_LINEIN_INPUT_WAY           LINEIN_INPUT_WAY_ANALOG // 输入方式选择

13.2 输入方式选择

c 复制代码
// 三种输入方式定义
#define LINEIN_INPUT_WAY_ADC            0    // ADC采样方式
#define LINEIN_INPUT_WAY_ANALOG         1    // 模拟直通方式
#define LINEIN_INPUT_WAY_DAC            2    // DAC输入方式

13.3 通道配置选项

c 复制代码
// 通道配置选项
#define AUDIO_LIN0_LR                   (BIT(0) | BIT(1))    // LIN0左右声道
#define AUDIO_LIN1_LR                   (BIT(2) | BIT(3))    // LIN1左右声道
#define AUDIO_LIN2_LR                   (BIT(4) | BIT(5))    // LIN2左右声道
#define AUDIO_LIN_DACL_CH               BIT(6)               // DAC左声道
#define AUDIO_LIN_DACR_CH               BIT(7)               // DAC右声道

时序控制要点

14.1 关键时序说明

  1. 设备检测时序:50ms定时器检测,连续检测到相同状态LINEIN_DETECT_CNT次才确认状态变化
  2. 提示音控制:必须等待提示音播放完毕才启动音频,通过回调机制控制
  3. 音频启动延时:ADC方式需要设置DAC启动延时,确保音频链路稳定
  4. 任务切换时序:设备拔出时立即切换到下一模式,避免无效状态

14.2 关键状态标志

c 复制代码
// 关键状态变量
static u8 linein_last_onoff = (u8)-1;    // 上次开关状态
static u8 linein_bt_back_flag = 0;       // 蓝牙后台返回标志
static u8 linein_idle_flag = 1;          // 空闲状态标志

14.3 音频状态管理

c 复制代码
// 音频状态定义
#define APP_AUDIO_STATE_MUSIC           0    // 音乐状态(ADC方式)
#define APP_AUDIO_STATE_LINEIN          1    // Linein状态(模拟/DAC方式)

调试要点

15.1 关键调试信息

  1. 设备检测:观察"linein online/offline"日志
  2. 任务切换:观察"APP_LINEIN_TASK"和任务切换日志
  3. 音频启动:观察"linein is aleady start"等状态日志
  4. 按键响应:观察"KEY_LINEIN_START"、"KEY_MUSIC_PP"等按键日志

15.2 常见问题排查

  1. 无法切换到linein模式:检查linein_app_check()返回值和设备检测
  2. 无音频输出:检查输入方式配置和通道配置是否正确
  3. 设备检测异常:检查GPIO配置和检测阈值设置
  4. 任务无法退出:检查app_task_exitting()和消息循环逻辑

这个完整的执行流程展示了从系统启动到linein正常工作的每一个关键步骤,帮助您深入理解整个linein模式的运行机制。

相关推荐
凡人叶枫1 天前
Effective C++ 条款04:确定对象被使用前已先被初始化
java·linux·开发语言·c++·嵌入式开发
声讯电子1 天前
AU-48双麦AI降噪回音消除模组
音频开发·aec回音消除·降噪模组
凡人叶枫3 天前
Effective C++ 条款03:尽可能使用 const
linux·开发语言·c++·嵌入式开发
俊基科技5 天前
AU-48 双麦语音处理模组详解:AEC+ENC 一体化音频方案,兼容 A-47 无缝替换
语音识别·嵌入式开发·硬件开发·ai降噪·回声消除
chipsense12 天前
变频空调能效虚标技术揭秘:压缩机电流检测的硬核解析
嵌入式开发·霍尔传感器·变频空调·电流传感器·an1v·foc控制·pfc电路
止观止14 天前
在 WSL2 上从零搭建 ARM 混合编程环境
汇编·arm开发·嵌入式开发·混合编程
十年编程老舅14 天前
读懂 MCU 启动:从上电到程序运行全链路
单片机·嵌入式硬件·mcu·嵌入式·cpu·嵌入式开发·ram
dozenyaoyida15 天前
RISC-V嵌入式开发:彻底解决“undefined reference to isatty“错误全攻略
经验分享·c·cmake·嵌入式开发·isatty·没有定义问题
wotaifuzao17 天前
指针和中断不是魔法:用第一性原理看穿嵌入式底层(万字解析)
stm32·嵌入式开发·内存模型·c语言指针·arm架构·中断机制·rtos内核