2025-10-10 16:07:00 +08:00

433 lines
12 KiB
C
Executable File

// Copyright 2023-2024 Beken
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <os/mem.h>
#include <os/os.h>
#include <os/str.h>
#include <stdio.h>
#include <stdlib.h>
#include "aud_intf.h"
#include "aud_intf_types.h"
#include <driver/audio_ring_buff.h>
#include <modules/pm.h>
#include <asr_mb.h>
#include <driver/mailbox_channel.h>
#include "ui.h"
#include "voice_player.h"
#include "asr_app.h"
#include "BK7256_RegList.h"
#define ASR_APP_TAG "asr_app"
#define GPIO_DEBUG 0
#define ASR_BUFF_SIZE 8000 //>960*2
static beken_thread_t asr_app_thread_hdl = NULL;
static beken_queue_t asr_app_msg_que = NULL;
static aud_intf_drv_setup_t aud_intf_drv_setup = DEFAULT_AUD_INTF_DRV_SETUP_CONFIG();
static aud_intf_mic_setup_t aud_intf_mic_setup = DEFAULT_AUD_INTF_MIC_SETUP_CONFIG();
static aud_intf_work_mode_t aud_work_mode = AUD_INTF_WORK_MODE_NULL;
static uint8_t *asr_ring_buff = NULL;
static RingBufferContext asr_rb;
static int8_t *asr_buff = NULL;
typedef enum {
ASR_APP_INIT = 0,
ASR_APP_NOTIFY,
ASR_APP_EXIT,
} asr_app_op_t;
typedef struct {
asr_app_op_t op;
uint32_t data;
} asr_app_msg_t;
bk_err_t asr_app_stop(void);
static bk_err_t asr_app_send_msg(asr_app_op_t op, uint32_t data)
{
bk_err_t ret;
asr_app_msg_t msg;
msg.op = op;
msg.data = data;
if (asr_app_msg_que) {
ret = rtos_push_to_queue(&asr_app_msg_que, &msg, BEKEN_NO_WAIT);
if (kNoErr != ret) {
BK_LOGE(ASR_APP_TAG, "asr_app_send_int_msg fail \r\n");
return kOverrunErr;
}
return ret;
}
return kNoResourcesErr;
}
static void asr_mailbox_rx_isr(void *param, mb_chnl_cmd_t *cmd_buf)
{
#if GPIO_DEBUG
addAON_GPIO_Reg0x8 = 2;
addAON_GPIO_Reg0x8 = 0;
#endif
switch(cmd_buf->hdr.cmd)
{
case EVENT_ASR_OPEN:
case EVENT_ASR_CLOSE:
case EVENT_ASR_PROCESS:
break;
case EVENT_ASR_RESULT:
#if GPIO_DEBUG
addAON_GPIO_Reg0x9 = 2;
addAON_GPIO_Reg0x9 = 0;
#endif
asr_app_send_msg(ASR_APP_NOTIFY, cmd_buf->param1);
break;
default:
break;
}
}
static bk_err_t asr_mailbox_chl_open(void)
{
bk_err_t ret = BK_OK;
ret = mb_chnl_open(MB_CHNL_AUD, NULL);
if (ret == BK_OK)
mb_chnl_ctrl(MB_CHNL_AUD, MB_CHNL_SET_RX_ISR, asr_mailbox_rx_isr);
return ret;
}
static bk_err_t asr_mailbox_chal_close(void)
{
return mb_chnl_close(MB_CHNL_AUD);
}
static bk_err_t asr_send_mb(asr_mb_event_t cmd, uint32 arg)
{
bk_err_t ret = BK_FAIL;
mb_chnl_cmd_t mb_cmd;
mb_cmd.hdr.cmd = cmd;
mb_cmd.param1 = arg;
mb_cmd.param2 = 0;
mb_cmd.param3 = 0;
ret = mb_chnl_write(MB_CHNL_AUD, &mb_cmd);
return ret;
}
/* mic file format: signal channel, 16K sample rate, 16bit width */
static int aud_mic_handle(uint8_t *data, unsigned int len)
{
uint32 uiTemp = 0;
#if GPIO_DEBUG
addAON_GPIO_Reg0x2 = 2;
addAON_GPIO_Reg0x2 = 0;
#endif
/* write data to file */
if (ring_buffer_get_free_size(&asr_rb) >= len) {
uiTemp = ring_buffer_write(&asr_rb, data, len);
if (uiTemp != len) {
BK_LOGE(ASR_APP_TAG, "%s, write data fail, uiTemp: %d \n", __func__, uiTemp);
}
}
if (ring_buffer_get_fill_size(&asr_rb) >= 960) {
uiTemp = ring_buffer_read(&asr_rb, (uint8_t *)asr_buff, 960);
// extern void flush_dcache(void *va, long size);
// flush_dcache((void *)asr_buff, 960);
asr_send_mb(EVENT_ASR_PROCESS, (uint32_t)asr_buff);
#if GPIO_DEBUG
addAON_GPIO_Reg0x3 = 2;
addAON_GPIO_Reg0x3 = 0;
#endif
}
return len;
}
static void asr_app_main(void)
{
bk_err_t ret = BK_OK;
/* start voice play task */
// voice_play_init();
asr_app_msg_t msg;
while(1) {
ret = rtos_pop_from_queue(&asr_app_msg_que, &msg, BEKEN_WAIT_FOREVER);
//rtos_delay_milliseconds(1000);
if (kNoErr == ret) {
if (msg.op == ASR_APP_EXIT) {
break;
} else if (msg.op == ASR_APP_NOTIFY) {
switch (msg.data) {
case ASR_RESULT_ARMINO: //阿尔米诺
ui_tabview_set(1);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "armino.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "armino_EN.pcm");
#endif
break;
case ASR_RESULT_RECEPTION: //会客模式
lv_event_send(ui_Ui2Panel2, LV_EVENT_CLICKED, NULL);
if(lv_obj_has_state(ui_Ui2Panel2, LV_STATE_CHECKED)) {
lv_obj_clear_state(ui_Ui2Panel2, LV_STATE_CHECKED);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "hui_ke_mode_close.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "hui_ke_mode_close_EN.pcm");
#endif
} else {
lv_obj_add_state(ui_Ui2Panel2, LV_STATE_CHECKED);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "hui_ke_mode_open.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "hui_ke_mode_open_EN.pcm");
#endif
}
lv_event_send(ui_Ui2Panel2, LV_EVENT_VALUE_CHANGED, NULL);
break;
case ASR_RESULT_MEAL: //用餐模式
lv_event_send(ui_Ui2Panel4, LV_EVENT_CLICKED, NULL);
if(lv_obj_has_state(ui_Ui2Panel4, LV_STATE_CHECKED)) {
lv_obj_clear_state(ui_Ui2Panel4, LV_STATE_CHECKED);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "yong_can_mode_close.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "yong_can_mode_close_EN.pcm");
#endif
} else {
lv_obj_add_state(ui_Ui2Panel4, LV_STATE_CHECKED);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "yong_can_mode_open.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "yong_can_mode_open_EN.pcm");
#endif
}
lv_event_send(ui_Ui2Panel4, LV_EVENT_VALUE_CHANGED, NULL);
break;
case ASR_RESULT_LEAVE: //离开模式
lv_event_send(ui_Ui2Panel3, LV_EVENT_CLICKED, NULL);
lv_obj_clear_state(ui_Ui2Panel2, LV_STATE_CHECKED);
lv_obj_clear_state(ui_Ui2Panel4, LV_STATE_CHECKED);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "li_kai_mode.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "li_kai_mode_EN.pcm");
#endif
break;
case ASR_RESULT_GOHOME: //回家模式
lv_event_send(ui_Ui2Panel1, LV_EVENT_CLICKED, NULL);
lv_obj_add_state(ui_Ui2Panel2, LV_STATE_CHECKED);
lv_obj_add_state(ui_Ui2Panel4, LV_STATE_CHECKED);
#if CONFIG_86BOX_SMART_PANEL_VERSION_CN
voice_play_send_msg(VOICE_PLAY_START, "hui_jia_mode.pcm");
#endif
#if CONFIG_86BOX_SMART_PANEL_VERSION_EN
voice_play_send_msg(VOICE_PLAY_START, "hui_jia_mode_EN.pcm");
#endif
break;
default:
break;
}
} else {
BK_LOGE(ASR_APP_TAG, "not support op: %d \n", msg.op);
}
}
}
ret = bk_aud_intf_mic_stop();
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_mic_stop fail, ret:%d \r\n", ret);
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_mic_stop complete \r\n");
}
BK_LOGI(ASR_APP_TAG, "stop mic \r\n");
ret = bk_aud_intf_mic_deinit();
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_mic_deinit fail, ret:%d \r\n", ret);
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_mic_deinit complete \r\n");
}
ret = bk_aud_intf_drv_deinit();
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_drv_deinit fail, ret:%d \r\n", ret);
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_drv_deinit complete \r\n");
}
asr_send_mb(EVENT_ASR_CLOSE, 0);
/* free buffer */
ring_buffer_clear(&asr_rb);
if (asr_ring_buff) {
os_free(asr_ring_buff);
asr_ring_buff = NULL;
}
if (asr_buff) {
os_free(asr_buff);
asr_buff = NULL;
}
/* delete msg queue */
ret = rtos_deinit_queue(&asr_app_msg_que);
if (ret != kNoErr) {
BK_LOGE(ASR_APP_TAG, "delete message queue fail \r\n");
}
asr_app_msg_que = NULL;
BK_LOGI(ASR_APP_TAG, "delete message queue complete \r\n");
/* delete task */
asr_app_thread_hdl = NULL;
rtos_delete_thread(NULL);
}
bk_err_t asr_app_start(void)
{
bk_err_t ret = BK_OK;
BK_LOGI(ASR_APP_TAG, "init asr app \r\n");
/* init audio mailbox channel */
if (BK_OK != asr_mailbox_chl_open()) {
BK_LOGE(ASR_APP_TAG, "init mailbox fail \n");
return BK_FAIL;
}
asr_ring_buff = os_malloc(ASR_BUFF_SIZE);
if (asr_ring_buff == NULL) {
BK_LOGE(ASR_APP_TAG, "os_malloc asr_ring_buff fail \n");
goto exit;
}
ring_buffer_init(&asr_rb, asr_ring_buff, ASR_BUFF_SIZE, DMA_ID_MAX, RB_DMA_TYPE_NULL);
asr_buff = os_malloc(960);
if (asr_buff == NULL) {
BK_LOGE(ASR_APP_TAG, "os_malloc asr_buff fail \n");
goto exit;
}
aud_intf_drv_setup.aud_intf_tx_mic_data = aud_mic_handle;
ret = bk_aud_intf_drv_init(&aud_intf_drv_setup);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_drv_init fail, ret:%d \r\n", ret);
goto exit;
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_drv_init complete \r\n");
}
aud_work_mode = AUD_INTF_WORK_MODE_GENERAL;
ret = bk_aud_intf_set_mode(aud_work_mode);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_set_mode fail, ret:%d \r\n", ret);
goto exit;
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_set_mode complete \r\n");
}
aud_intf_mic_setup.samp_rate = 16000;
ret = bk_aud_intf_mic_init(&aud_intf_mic_setup);
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_mic_init fail, ret:%d \r\n", ret);
goto exit;
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_mic_init complete \r\n");
}
BK_LOGI(ASR_APP_TAG, "init mic complete \r\n");
ret = bk_aud_intf_mic_start();
if (ret != BK_ERR_AUD_INTF_OK) {
BK_LOGE(ASR_APP_TAG, "bk_aud_intf_mic_start fail, ret:%d \r\n", ret);
goto exit;
} else {
BK_LOGI(ASR_APP_TAG, "bk_aud_intf_mic_start complete \r\n");
}
BK_LOGI(ASR_APP_TAG, "start asr test \r\n");
ret = rtos_init_queue(&asr_app_msg_que,
"asr_app_que",
sizeof(asr_app_msg_t),
1);
if (ret != kNoErr) {
BK_LOGE(ASR_APP_TAG, "ceate asr app message queue fail \r\n");
asr_app_msg_que = NULL;
goto exit;
}
BK_LOGI(ASR_APP_TAG, "ceate asr app message queue complete \r\n");
/* create task to asr */
ret = rtos_create_thread(&asr_app_thread_hdl,
5,
"asr_app",
(beken_thread_function_t)asr_app_main,
1536,
NULL);
if (ret != kNoErr) {
BK_LOGE(ASR_APP_TAG, "create asr app task fail \r\n");
asr_app_thread_hdl = NULL;
goto exit;
}
BK_LOGI(ASR_APP_TAG, "create asr app task complete \r\n");
return ret;
exit:
asr_mailbox_chal_close();
if (asr_ring_buff) {
ring_buffer_clear(&asr_rb);
os_free(asr_ring_buff);
asr_ring_buff = NULL;
}
if (asr_buff) {
os_free(asr_buff);
asr_buff = NULL;
}
bk_aud_intf_mic_stop();
bk_aud_intf_mic_deinit();
aud_work_mode = AUD_INTF_WORK_MODE_NULL;
bk_aud_intf_set_mode(aud_work_mode);
bk_aud_intf_drv_deinit();
if (asr_app_msg_que) {
rtos_deinit_queue(&asr_app_msg_que);
asr_app_msg_que = NULL;
}
return BK_FAIL;
}
bk_err_t asr_app_stop(void)
{
return asr_app_send_msg(ASR_APP_EXIT, 0);
}