您尚未登录。

楼主 #1 2018-05-15 17:58:12

mkseven32
会员
注册时间: 2018-04-24
已发帖子: 57
积分: 57

ESP-ADF 事件的添加和配置。

在ESP-ADF 的框架下, 软件编程将 要实现的功能  虚拟化, 串了一串, 成为了 一条 “管道”。

“管道” 在大while 下 串流不息~~  而在这个过程中如果触发了某一件事(需要做成对应的处理,例如打印个消息),可以添加和配置event,
从而在大while 下面 对event 传上来的msg 进行解析获取具体什么事情发生了。。。


第一步: 配置event,然后 通过初始化 这个配置 ,从而获取到该event 的句柄 (这个句柄 后期用于设置监听者用)

    audio_event_iface_cfg_t evt_cfg = AUDIO_EVENT_IFACE_DEFAULT_CFG();
    audio_event_iface_handle_t evt = audio_event_iface_init(&evt_cfg);

AUDIO_EVENT_IFACE_DEFAULT_CFG(); 的具体配置信息如下:
其实event 就是一个queue ,配置的一些queue的size ,超时时间,回调函数等等

#define DEFAULT_AUDIO_EVENT_IFACE_SIZE  (5)

#define AUDIO_EVENT_IFACE_DEFAULT_CFG() {                   \
    .internal_queue_size = DEFAULT_AUDIO_EVENT_IFACE_SIZE,  \
    .external_queue_size = DEFAULT_AUDIO_EVENT_IFACE_SIZE,  \
    .queue_set_size = DEFAULT_AUDIO_EVENT_IFACE_SIZE,       \
    .on_cmd = NULL,                                         \
    .context = NULL,                                        \
    .wait_time = portMAX_DELAY,                             \
    .type = 0,                                              \
}

第二步: 设置监听者, 监听者有多种情况,

有些是已经被包含在”管道“ 中角色,
如在”管道“ pipeline 包含内容:  [Bluetooth]-->bt_stream_reader-->i2s_stream_writer-->[codec_chip] 中, 需要监听bt 状态触发的事件。
则需要使用 pipeline 的 设置监听函数

audio_pipeline_set_listener(pipeline, evt);

有些是没有包含在管道中的 ,如触摸按键 这样外设。则采用下面函数设置监听者。

audio_event_iface_set_listener(esp_periph_get_event_iface(), evt);

esp_periph_get_event_iface() 得到的是一个 也是一个event 的句柄 audio_event_iface_handle_t
这个函数简化就是 set(a, listener);
将 event a 添加到 the listener 里面, 后面 我们就可以从 listen 中监听到a event。 (这里的listen 和 listener 是不同的)

第三步:在 大while 下 开始解析 event 传回来的msg

audio_event_iface_msg_t msg;
esp_err_t ret = audio_event_iface_listen(evt, &msg, portMAX_DELAY);

先看看 msg 结构体包含哪些信息

/**
 * Event message
 */
typedef struct {
    int cmd;                /*!< Command id */
    void *data;             /*!< Data pointer */
    int data_len;           /*!< Data length */
    void *source;           /*!< Source event */
    int source_type;        /*!< Source type (To know where it came from) */
    bool need_free_data;    /*!< Need to free data pointer after the event has been processed */
} audio_event_iface_msg_t;

例子:

  if (msg.source_type == AUDIO_ELEMENT_TYPE_ELEMENT && msg.source == (void *) bt_stream_reader
                && msg.cmd == AEL_MSG_CMD_REPORT_MUSIC_INFO)

cmd ====>这个的值其实就是event id,它的内容主要根据source_type 来定,source_type 决定是element 还是 stream 还是什么,
而对应的每个element(或者stream)都是有对应的event id,
如果是AUDIO_ELEMENT_TYPE_ELEMENT 则cmd 分为以下几类,
/**
* Audio element action command, process on dispatcher
*/
typedef enum {
    AEL_MSG_CMD_NONE                = 0,
    AEL_MSG_CMD_ERROR               = 1,
    AEL_MSG_CMD_FINISH              = 2,
    AEL_MSG_CMD_STOP                = 3,
    AEL_MSG_CMD_PAUSE               = 4,
    AEL_MSG_CMD_RESUME              = 5,
    AEL_MSG_CMD_DESTROY             = 6,
    // AEL_MSG_CMD_CHANGE_STATE        = 7,
    AEL_MSG_CMD_REPORT_STATUS       = 8,
    AEL_MSG_CMD_REPORT_MUSIC_INFO   = 9,
    AEL_MSG_CMD_REPORT_CODEC_FMT    = 10,
} audio_element_msg_cmd_t;

但是根据 source_type 的不同,如果是PERIPH_ID_BLUETOOTH ,则cmd 又可以是以下的id
例如:

 if (msg.source_type == PERIPH_ID_BLUETOOTH
                && msg.source == (void *)bt_periph) {
            if (msg.cmd == PERIPH_BLUETOOTH_DISCONNECTED || msg.cmd == PERIPH_BLUETOOTH_AUDIO_SUSPENDED)

这些分类 主要是蓝牙的事件:

/**
 * brief      Bluetooth peripheral event id
 */
typedef enum {
    PERIPH_BLUETOOTH_UNKNOWN = 0,       /*!< No event */
    PERIPH_BLUETOOTH_CONNECTED,         /*!< A bluetooth device was connected */
    PERIPH_BLUETOOTH_DISCONNECTED,      /*!< Last connection was disconnected */
    PERIPH_BLUETOOTH_AUDIO_STARTED,     /*!< The audio session has been started */
    PERIPH_BLUETOOTH_AUDIO_SUSPENDED,   /*!< The audio session has been suspended */
    PERIPH_BLUETOOTH_AUDIO_STOPPED,     /*!< The audio session has been stopped */
} periph_bluetooth_event_id_t;

data====> 主要是element 的状态

/**
 * Audio element status report
 */
typedef enum {
    AEL_STATUS_NONE                     = 0,
    AEL_STATUS_ERROR_OPEN               = 1,
    AEL_STATUS_ERROR_INPUT              = 2,
    AEL_STATUS_ERROR_PROCESS            = 3,
    AEL_STATUS_ERROR_OUTPUT             = 4,
    AEL_STATUS_ERROR_CLOSE              = 5,
    AEL_STATUS_ERROR_TIMEOUT            = 6,
    AEL_STATUS_ERROR_UNKNOWN            = 7,
    AEL_STATUS_INPUT_DONE               = 8,
    AEL_STATUS_INPUT_BUFFERING          = 9,
    AEL_STATUS_OUTPUT_DONE              = 10,
    AEL_STATUS_OUTPUT_BUFFERING         = 11,
    AEL_STATUS_STATE_RUNNING            = 12,
    AEL_STATUS_STATE_PAUSED             = 13,
    AEL_STATUS_STATE_STOPPED            = 14,
    AEL_STATUS_MOUNTED                  = 15,
    AEL_STATUS_UNMOUNTED                = 16,
} audio_element_status_t;

source =====> 这一项其实就是 一开始在做”管道“ 注册时,各个组件的 句柄
如注册 时

    audio_pipeline_register(pipeline, bt_stream_reader, "bt");
    audio_pipeline_register(pipeline, i2s_stream_writer, "i2s");

那么bt_stream_reader和i2s_stream_writer 都将是source的 可选值之一。

source_type ====》就是触发事件的 element 的 id
首先分为5大类

typedef enum {
    AUDIO_ELEMENT_TYPE_UNKNOW = 0x01<<ELEMENT_SUB_TYPE_OFFSET,
    AUDIO_ELEMENT_TYPE_ELEMENT= 0x01<<(ELEMENT_SUB_TYPE_OFFSET+1),
    AUDIO_ELEMENT_TYPE_PLAYER = 0x01<<(ELEMENT_SUB_TYPE_OFFSET+2),
    AUDIO_ELEMENT_TYPE_SERVICE = 0x01<<(ELEMENT_SUB_TYPE_OFFSET+3),
    AUDIO_ELEMENT_TYPE_PERIPH = 0x01<<(ELEMENT_SUB_TYPE_OFFSET+4),
} audio_element_type_t;

在这5大类中每一类都有衍生, 例如硬件外设,就具体分了下面几种。

/**
 * @brief Peripheral Identify, this must be unique for each peripheral added to the peripherals list
 */
typedef enum {
    PERIPH_ID_BUTTON    = AUDIO_ELEMENT_TYPE_PERIPH + 1,
    PERIPH_ID_TOUCH     = AUDIO_ELEMENT_TYPE_PERIPH + 2,
    PERIPH_ID_SDCARD    = AUDIO_ELEMENT_TYPE_PERIPH + 3,
    PERIPH_ID_WIFI      = AUDIO_ELEMENT_TYPE_PERIPH + 4,
    PERIPH_ID_FLASH     = AUDIO_ELEMENT_TYPE_PERIPH + 5,
    PERIPH_ID_AUXIN     = AUDIO_ELEMENT_TYPE_PERIPH + 6,
    PERIPH_ID_ADC       = AUDIO_ELEMENT_TYPE_PERIPH + 7,
    PERIPH_ID_CONSOLE   = AUDIO_ELEMENT_TYPE_PERIPH + 8,
    PERIPH_ID_BLUETOOTH = AUDIO_ELEMENT_TYPE_PERIPH + 9,
} esp_periph_id_t;

其余两个值暂时还没有例子可循, 说到这里发现自己还是没有深入的理解,感觉更多只是在贴代码~~~

希望有高手可以帮忙斧正!

最近编辑记录 mkseven32 (2018-05-16 10:08:48)

离线

#2 2018-05-15 19:16:37

daydayup
会员
注册时间: 2017-10-09
已发帖子: 343
积分: 343

Re: ESP-ADF 事件的添加和配置。

感谢楼主分享!

离线

#3 2020-05-12 11:09:39

guguo8266
会员
注册时间: 2020-01-16
已发帖子: 4
积分: 4

Re: ESP-ADF 事件的添加和配置。

强烈建议楼主带小白入局:win10 64位,想用乐鑫的编译链,搭建adf屡次失败,现在用着idf cmake好好的。我的球球36351109.

离线

#4 2020-05-12 11:10:57

哇酷小二
wechat微信:whycan_cn
所在地: 你猜
注册时间: 2020-04-22
已发帖子: 3,378
积分: 1902
个人网站

Re: ESP-ADF 事件的添加和配置。

guguo8266 说:

强烈建议楼主带小白入局:win10 64位,想用乐鑫的编译链,搭建adf屡次失败,现在用着idf cmake好好的。我的球球36351109.

有问题直接跟帖就行了哦,比QQ更快解决你的问题。





离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn