mcu_hi3321_watch/application/audio/sample_audio.c
2025-05-26 20:15:20 +08:00

432 lines
11 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) CompanyNameMagicTag 2020-2021. All rights reserved.
* Description: source file for module operation
*/
#include <stdlib.h>
#ifdef __LITEOS__
#include <los_task.h>
#endif
#include "cmsis_os.h"
#include "thread_os.h"
#include "securec.h"
#include "sample_audio_api.h"
#include "chip_type.h"
#include "audio_struct.h"
#include "soc_uapi_audio_sys.h"
#include "sample_audio.h"
#if (SAP_CHIP_TYPE == brandy)
#include "es8311_codec.h"
#include "pm_clocks.h"
#endif /* SAP_CHIP_TYPE */
#define TEST_SUITE_TASK_STACK_SIZE 0xc00
#define TEST_SUITE_NAME "audio"
#define TEST_SUITE_MAX_ARGV_LEN 128
#ifdef BOARD_CS
#define AUDIO_MEM_PROT_CFG 0x500006a0
#define AUDIO_MEM_PROT_LOCK 0x3
#endif
#define HIFI_FREQ_176M 176947200
#define HIFI_FREQ_147M 147456000
#define HIFI_FREQ_64M 64000000
#define HIFI_INVALID_PROFILE 0xF
static td_u8 g_dsp_profile = HIFI_INVALID_PROFILE;
typedef struct {
td_s32 argc;
td_char argv[TEST_SUITE_MAX_ARGC][TEST_SUITE_MAX_ARGV_LEN];
} cmd_msg_queue;
typedef struct {
td_char *name;
td_s32 (*func)(td_s32 argc, td_char *argv[]);
td_bool running;
} functions;
typedef struct {
athread_handle task;
td_bool task_active;
} sample_audio_inst;
/* only one sample instance when set to true */
static td_bool g_sample_cfg_singleton = TD_TRUE;
static sample_audio_inst *g_sample_audio_inst;
typedef struct {
td_char *sample;
td_char *config;
td_char *value;
} sample_set_config_arg;
static td_void sample_set_dump_mask(td_u8 dump_mask)
{
td_s32 ret;
uapi_audio_debug_cfg cfg = {0};
ret = uapi_audio_get_debug_cfg(&cfg);
if (ret != EXT_SUCCESS) {
sap_err_log_fun(uapi_audio_get_debug_cfg, ret);
return;
}
cfg.dump_mask = dump_mask;
ret = uapi_audio_set_debug_cfg(&cfg);
if (ret != EXT_SUCCESS) {
sap_err_log_fun(uapi_audio_set_debug_cfg, ret);
return;
}
sap_alert_log_info("dump mask status");
sap_alert_log_bool((dump_mask & UAPI_AUDIO_DUMP_MASK_AI) != 0);
sap_alert_log_bool((dump_mask & UAPI_AUDIO_DUMP_MASK_SEA) != 0);
sap_alert_log_bool((dump_mask & UAPI_AUDIO_DUMP_MASK_AENC) != 0);
sap_alert_log_bool((dump_mask & UAPI_AUDIO_DUMP_MASK_ADEC) != 0);
sap_alert_log_bool((dump_mask & UAPI_AUDIO_DUMP_MASK_TRACK) != 0);
sap_alert_log_bool((dump_mask & UAPI_AUDIO_DUMP_MASK_AO) != 0);
}
static td_void sample_set_proc_mask(td_u8 proc_mask)
{
td_s32 ret;
uapi_audio_debug_cfg cfg = {0};
ret = uapi_audio_get_debug_cfg(&cfg);
if (ret != EXT_SUCCESS) {
sap_err_log_fun(uapi_audio_get_debug_cfg, ret);
return;
}
cfg.proc_mask = proc_mask;
ret = uapi_audio_set_debug_cfg(&cfg);
if (ret != EXT_SUCCESS) {
sap_err_log_fun(uapi_audio_set_debug_cfg, ret);
return;
}
sap_alert_log_info("proc mask status");
sap_alert_log_bool((proc_mask & UAPI_AUDIO_PROC_MASK_UART) != 0);
sap_alert_log_bool((proc_mask & UAPI_AUDIO_PROC_MASK_DIAG_SHELL) != 0);
}
static td_void sample_set_tws_role(td_u8 role)
{
if (role != AUDIO_TWS_ROLE_MASTER && role != AUDIO_TWS_ROLE_SLAVE && role != AUDIO_TWS_ROLE_FREEMAN) {
sap_err_log_info("invalid tws role, need to set tws role as 0/1/2(master/salve/freeman)\n");
return;
}
uapi_audio_set_tws_role((uapi_audio_tws_role)role);
}
static td_void sample_set_dsp_profile(td_u8 profile)
{
g_dsp_profile = profile;
sap_alert_log_u32(g_dsp_profile);
}
static td_s32 sample_set_config(td_s32 argc, td_char *argv[])
{
td_u8 tmp_mask;
sample_set_config_arg *arg = (sample_set_config_arg *)argv;
if (argc == 0x2 && (strcmp("q", argv[1]) == 0)) {
return EXT_SUCCESS;
}
if (argc != sizeof(sample_set_config_arg) / sizeof(td_char *)) {
sap_err_log_info("nothing changed!");
return EXT_SUCCESS;
}
tmp_mask = (td_u8)strtoul(arg->value, TD_NULL, 0);
if (strcmp(arg->config, "singleton") == 0) {
g_sample_cfg_singleton = ((strtoul(arg->value, TD_NULL, 0)) == 0) ? TD_FALSE : TD_TRUE;
sap_alert_log_u32(g_sample_cfg_singleton);
} else if (strcmp(arg->config, "dump_mask") == 0) {
sample_set_dump_mask(tmp_mask);
} else if (strcmp(arg->config, "proc_mask") == 0) {
sample_set_proc_mask(tmp_mask);
} else if (strcmp(arg->config, "tws_role") == 0) {
sample_set_tws_role(tmp_mask);
} else if (strcmp(arg->config, "profile") == 0) {
sample_set_dsp_profile(tmp_mask);
} else {
sap_err_log_info("nothing changed!");
}
return EXT_SUCCESS;
}
#if (SAP_CHIP_TYPE == socmn1)
FILE *fopen(const char *name, const char *type)
{
sap_unused(name);
sap_unused(type);
return NULL;
}
int fclose(FILE *f)
{
sap_unused(f);
return 0;
}
size_t fread(void *v, size_t size, size_t n, FILE *f)
{
sap_unused(v);
sap_unused(size);
sap_unused(n);
sap_unused(f);
return 0;
}
size_t fwrite(const void *v, size_t size, size_t n, FILE *f)
{
sap_unused(v);
sap_unused(size);
sap_unused(n);
sap_unused(f);
return 0;
}
td_s32 fseek(FILE *f, td_slong offset, td_s32 fromwhere)
{
unused(f);
unused(offset);
unused(fromwhere);
return 0;
}
td_slong ftell(FILE *f)
{
unused(f);
return 0;
}
void rewind(FILE *f)
{
sap_unused(f);
}
#endif
static functions g_audio_func[] = {
#ifndef CONFIG_PROT_CORE
{"sample_ai", sample_ai, TD_FALSE},
{"sample_ao", sample_ao, TD_FALSE},
{"sample_encode", sample_encode, TD_FALSE},
{"sample_cast_aenc_play", sample_cast_aenc_play, TD_FALSE},
{"sample_encode_play", sample_encode_play, TD_FALSE},
{"sample_decode", sample_decode, TD_FALSE},
{"sample_ai_aenc", sample_ai_aenc, TD_FALSE},
{"sample_ai_sea_aenc", sample_ai_sea_aenc, TD_FALSE},
{"sample_ai_ao", sample_ai_ao, TD_FALSE},
{"sample_sea", sample_sea, TD_FALSE},
{"sample_gui_aef", sample_gui_aef, TD_FALSE},
#if defined(SAP_HAID_SUPPORT)
{"sample_haid", sample_haid, TD_FALSE},
{"sample_spk_calib", sample_spk_calib, TD_FALSE},
#endif /* SAP_HAID_SUPPORT */
#if defined(SAP_DPM_SUPPORT)
{"sample_dpm", sample_dpm, TD_FALSE},
#endif /* SAP_DPM_SUPPORT */
{"sample_lpwk", sample_lpwk, TD_FALSE},
{"sample_dump", sample_dump, TD_FALSE},
{"sample_phone", sample_phone_application, TD_FALSE},
{"sample_proc", sample_proc, TD_FALSE},
#else
{"sample_phone", sample_phone_protocol, TD_FALSE},
#endif
{"sample_set_config", sample_set_config, TD_FALSE},
};
static osMessageQueueId_t g_msg_queue_id = TD_NULL;
static cmd_msg_queue g_cmd_msg;
static td_void audio_auto_exit_function(td_s32 argc, td_char *argv[], td_u32 fun_id)
{
td_u32 i;
td_char *q = "q";
td_char *cmd[] = {argv[0], q};
if (!g_sample_cfg_singleton) {
return;
}
/* audio func q */
if (argc == 0x2 && (strcmp("q", argv[1]) == 0)) {
g_audio_func[fun_id].running = TD_FALSE;
return;
}
for (i = 0; i < (sizeof(g_audio_func) / sizeof(g_audio_func[0])); i++) {
if (g_audio_func[i].running == TD_TRUE) {
(td_void)g_audio_func[i].func(0x2, cmd);
g_audio_func[i].running = TD_FALSE;
}
}
g_audio_func[fun_id].running = TD_TRUE;
}
static td_void update_dsp_profile(td_void)
{
#if (SAP_CHIP_TYPE == brandy)
#ifndef CONFIG_PROT_CORE
/* brandy默认进入低功耗模式按最小频点工作启动sample业务前需更新到所需频点 */
pm_hifi_mode_t hifi_mode;
if (SAP_DSP_CLK_HZ > HIFI_FREQ_176M) {
hifi_mode = HIFI_LPM_CLK_HIGH_LEVEL;
} else if (SAP_DSP_CLK_HZ > HIFI_FREQ_147M) {
hifi_mode = HIFI_LPM_CLK_LEVEL2;
} else if (SAP_DSP_CLK_HZ > HIFI_FREQ_64M) {
hifi_mode = HIFI_LPM_CLK_LEVEL1;
} else {
hifi_mode = HIFI_LPM_CLK_LOW_LEVEL;
}
if ((td_u32)g_dsp_profile < HIFI_LPM_CLK_MAX) {
/* 对于需要指定DSP工作频点的场景使用上层用户配置的频点 */
hifi_mode = g_dsp_profile;
}
sap_printf("SAP_DSP_CLK_HZ = %d, hifi_mode = %d.\n", SAP_DSP_CLK_HZ, hifi_mode);
uapi_set_hifi_mode(hifi_mode);
#endif
#endif
}
td_void audio_execute_function(td_s32 argc, td_char *argv[])
{
td_u32 i;
td_s32 ret;
if (argc == 0) {
return;
}
if (strcmp("help", *argv) == 0) {
return;
}
for (i = 0; i < (sizeof(g_audio_func) / sizeof(g_audio_func[0])); i++) {
if (strcmp(*argv, g_audio_func[i].name) != 0) {
continue;
}
if (strcmp(*argv, "sample_proc") != 0) {
/* do not need to quit when reading proc */
update_dsp_profile();
audio_auto_exit_function(argc, argv, i);
}
ret = g_audio_func[i].func(argc, argv);
sap_alert_log_str(g_audio_func[i].name);
if (ret != EXT_SUCCESS) {
sap_err_log_info("sample execute failed.");
} else {
sap_alert_log_info("sample execute succeeded.");
}
return;
}
}
static td_void audio_task_entry(const td_void *param)
{
td_s32 ret;
td_u32 i;
td_char *msg_argv[TEST_SUITE_MAX_ARGC];
sample_audio_inst *inst = (sample_audio_inst *)param;
while (inst->task_active) {
ret = osMessageQueueGet(g_msg_queue_id, (td_void *)&g_cmd_msg, NULL, osWaitForever);
if (ret != osOK) {
continue;
}
for (i = 0; i < TEST_SUITE_MAX_ARGC; i++) {
msg_argv[i] = g_cmd_msg.argv[i];
}
audio_execute_function(g_cmd_msg.argc, msg_argv);
}
sap_alert_log_info("thread exit.");
athread_set_exit(inst->task, TD_TRUE);
}
static td_s32 audio_create_task(sample_audio_inst *inst)
{
td_s32 ret;
athread_attr attr;
g_msg_queue_id = osMessageQueueNew(1, sizeof(cmd_msg_queue), TD_NULL);
inst->task_active = TD_TRUE;
attr.priority = ATHREAD_PRIORITY_NORMAL;
attr.stack_size = TEST_SUITE_TASK_STACK_SIZE;
attr.name = TEST_SUITE_NAME;
ret = athread_create(&inst->task, (td_void (*)(td_void *))audio_task_entry, (td_void *)inst, &attr);
if (ret != EXT_SUCCESS) {
sap_err_log_fun(athread_create, ret);
}
return EXT_SUCCESS;
}
td_s32 audio_init(td_void)
{
if (g_sample_audio_inst != TD_NULL) {
sap_printf("inst had already existed!");
return EXT_FAILURE;
}
g_sample_audio_inst = (sample_audio_inst *)malloc(sizeof(sample_audio_inst));
if (g_sample_audio_inst == TD_NULL) {
sap_printf("sample audio inst alloc failed\n");
return EXT_FAILURE;
}
sample_audio_inst *inst = g_sample_audio_inst;
memset_s(inst, sizeof(*inst), 0, sizeof(sample_audio_inst));
audio_create_task(inst);
#if (SAP_CHIP_TYPE == brandy)
#ifndef CONFIG_PROT_CORE
return uapi_audio_init();
#else
sap_alert_log_info("execute succeeded.");
return EXT_SUCCESS;
#endif
#endif /* SAP_CHIP_TYPE */
#ifdef BOARD_CS
uapi_reg_write32(AUDIO_MEM_PROT_CFG, AUDIO_MEM_PROT_LOCK); /* lock audio memory access */
#endif
return EXT_SUCCESS;
}
static td_void audio_destroy_task(sample_audio_inst *inst)
{
if (inst->task != TD_NULL) {
inst->task_active = TD_FALSE;
athread_exit(inst->task);
inst->task = TD_NULL;
}
}
td_s32 audio_deinit(td_void)
{
audio_destroy_task(g_sample_audio_inst);
free(g_sample_audio_inst);
g_sample_audio_inst = TD_NULL;
return EXT_SUCCESS;
}