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

文章封面

Linein模式执行流程详解

概述

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


完整执行流程图

Linein完整执行流程

通过

失败

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

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

// 任务列表配置
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

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

文件: apps/soundbox/task_manager/linein/linein_dev.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

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

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

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

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

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. 三种输入方式详解

Linein三种输入方式

9.1 ADC采样方式

文件: apps/soundbox/task_manager/linein/linein_api.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

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

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. 系统事件处理

Linein设备检测与事件处理
文件: apps/soundbox/task_manager/linein/linein.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

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

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

#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 输入方式选择

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

13.3 通道配置选项

// 通道配置选项
#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 关键状态标志

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

14.3 音频状态管理

// 音频状态定义
#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模式的运行机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值