add first commit
This commit is contained in:
commit
235a402c8c
|
@ -0,0 +1,99 @@
|
|||
#
|
||||
# NOTE! Don't add files that are generated in specific
|
||||
# subdirectories here. Add them in the ".gitignore" file
|
||||
# in that subdirectory instead.
|
||||
#
|
||||
# NOTE! Please use 'git ls-files -i --exclude-standard'
|
||||
# command after changing this file, to see if there are
|
||||
# any tracked files which get ignored after the change.
|
||||
#
|
||||
# ('git ls-files -i --exclude-standard -ocs --directory'
|
||||
# command can show all the tracked and untracked files
|
||||
# which get ignored after the change.)
|
||||
#
|
||||
|
||||
# Hidden files
|
||||
.*
|
||||
# Except for these hidden files
|
||||
!.gitignore
|
||||
!.gitattributes
|
||||
!.mailmap
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
*.bak
|
||||
*.BAK
|
||||
*.orig
|
||||
\#*#
|
||||
|
||||
# Tag files
|
||||
/tags
|
||||
/TAGS
|
||||
/cscope.*
|
||||
/ncscope.*
|
||||
/compile_commands.json
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.o.*
|
||||
*.ko
|
||||
*.obj
|
||||
*.lo
|
||||
*.slo
|
||||
*.py[co]
|
||||
|
||||
# List files
|
||||
*.i
|
||||
*.lst
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lai
|
||||
*.pyd
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.elf
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Source insight project files
|
||||
/[sS][iI]/
|
||||
|
||||
# Generated project files
|
||||
*.ncb
|
||||
*.idb
|
||||
*.pdb
|
||||
*.sdf
|
||||
*.suo
|
||||
*.opensdf
|
||||
#/Debug/
|
||||
#/Release/
|
||||
Debug/
|
||||
Release/
|
||||
/ipch/
|
||||
|
||||
# Library dir
|
||||
#lib/
|
||||
|
||||
# Build dir
|
||||
/out/
|
||||
*.pre
|
||||
|
||||
# configuration file
|
||||
# *.ini
|
|
@ -0,0 +1,52 @@
|
|||
obj-y := audioplayers/ common/ main/ key/ pwl/ battery/ factory/
|
||||
|
||||
ifeq ($(APP_TEST_AUDIO),1)
|
||||
obj-y += apptester/
|
||||
endif
|
||||
|
||||
ifeq ($(BTUSB_AUDIO_MODE),1)
|
||||
obj-y += usbaudio/
|
||||
endif
|
||||
ifeq ($(BT_USB_AUDIO_DUAL_MODE),1)
|
||||
obj-y += btusbaudio/
|
||||
obj-y += usbaudio/
|
||||
endif
|
||||
|
||||
ifeq ($(APP_TEST_SDMMC),1)
|
||||
obj-y += sdmmc/
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_APP),1)
|
||||
obj-y += anc/
|
||||
endif
|
||||
|
||||
ifeq ($(VOICE_DETECTOR_EN),1)
|
||||
obj-y += voice_detector/
|
||||
endif
|
||||
|
||||
ifeq ($(PC_CMD_UART),1)
|
||||
obj-y += cmd/
|
||||
endif
|
||||
|
||||
subdir-ccflags-y += -Iapps/apptester \
|
||||
-Iapps/audioplayers \
|
||||
-Iapps/common \
|
||||
-Iapps/sdmmc \
|
||||
-Iapps/main \
|
||||
-Iapps/cmd \
|
||||
-Iapps/key \
|
||||
-Iapps/pwl \
|
||||
-Iapps/battery \
|
||||
-Iservices/voicepath \
|
||||
-Iservices/ble_app/app_datapath \
|
||||
-Iutils/list \
|
||||
-Iutils/heap \
|
||||
-Iservices/multimedia/audio/process/filters/include
|
||||
ifeq ($(BT_USB_AUDIO_DUAL_MODE),1)
|
||||
subdir-ccflags-y += -Iapps/btusbaudio
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_LDAC_ON),1)
|
||||
subdir-ccflags-y += -Ithirdparty/audio_codec_lib/ldac/inc
|
||||
endif
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
|
||||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj_s := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)src/*.s))
|
||||
obj_c := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)src/*.c))
|
||||
obj_cpp := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)src/*.cpp))
|
||||
|
||||
ifeq ($(ANC_APP),1)
|
||||
CFLAGS_app_anc.o += -DANC_APP
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_FF_ENABLED),1)
|
||||
CFLAGS_app_anc.o += -DANC_FF_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_FB_ENABLED),1)
|
||||
CFLAGS_app_anc.o += -DANC_FB_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_WNR_ENABLED),1)
|
||||
CFLAGS_app_anc.o += -DANC_WNR_ENABLED
|
||||
endif
|
||||
|
||||
|
||||
|
||||
ifeq ($(ANC_ASSIST_ENABLED),1)
|
||||
CFLAGS_app_anc.o += -DANC_ASSIST_ENABLED
|
||||
|
||||
ifeq ($(ANC_ASSIST_WNR_ENABLED),1)
|
||||
CFLAGS_anc_assist.o += -DANC_ASSIST_WNR_ENABLED
|
||||
endif
|
||||
ifeq ($(ANC_ASSIST_PILOT_ENABLED),1)
|
||||
CFLAGS_anc_assist.o += -DANC_ASSIST_PILOT_ENABLED
|
||||
endif
|
||||
ifeq ($(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED),1)
|
||||
CFLAGS_anc_assist.o += -DANC_ASSIST_NOISE_ADAPTIVE_ENABLED
|
||||
endif
|
||||
ifeq ($(ANC_ASSIST_HESS_ENABLED),1)
|
||||
CFLAGS_anc_assist.o += -DANC_ASSIST_HESS_ENABLED
|
||||
endif
|
||||
ifeq ($(ANC_ASSIST_PNC_ENABLED),1)
|
||||
CFLAGS_anc_assist.o += -DANC_ASSIST_PNC_ENABLED
|
||||
endif
|
||||
ifeq ($(ANC_ASSIST_DEHOWLING_ENABLED),1)
|
||||
CFLAGS_anc_assist.o += -DANC_ASSIST_DEHOWLING_ENABLED
|
||||
endif
|
||||
|
||||
else
|
||||
obj_c := $(filter-out src/anc_assist.c ,$(obj_c))
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(AUDIO_RESAMPLE),1)
|
||||
CFLAGS_app_anc.o += -D__AUDIO_RESAMPLE__
|
||||
endif
|
||||
ifeq ($(SW_PLAYBACK_RESAMPLE),1)
|
||||
CFLAGS_app_anc.o += -DSW_PLAYBACK_RESAMPLE
|
||||
endif
|
||||
ifeq ($(SW_CAPTURE_RESAMPLE),1)
|
||||
CFLAGS_app_anc.o += -DSW_CAPTURE_RESAMPLE
|
||||
endif
|
||||
ifeq ($(AUDIO_SECTION_SUPPT),1)
|
||||
CFLAGS_app_anc.o += -D__AUDIO_SECTION_SUPPT__
|
||||
endif
|
||||
|
||||
obj-y := $(obj_c:.c=.o) $(obj_s:.S=.o) $(obj_cpp:.cpp=.o)
|
||||
|
||||
subdir-ccflags-y += \
|
||||
-Iservices/fs/fat \
|
||||
-Iservices/fs/sd \
|
||||
-Iservices/fs/fat/ChaN \
|
||||
-Iservices/overlay \
|
||||
-Iservices/nvrecord \
|
||||
-Iservices/resources \
|
||||
-Iservices/multimedia/audio/process/resample/include \
|
||||
-Iservices/multimedia/audio/process/anc/include \
|
||||
-Iservices/multimedia/speech/inc \
|
||||
-Iplatform/drivers/uarthci \
|
||||
-Iplatform/drivers/ana \
|
||||
-Iplatform/drivers/bt \
|
||||
-Iutils/cqueue \
|
||||
-Iservices/audioflinger \
|
||||
-Iutils/lockcqueue \
|
||||
-Iutils/intersyshci \
|
||||
-Iapps/anc/inc \
|
||||
-Iapps/key \
|
||||
-Iapps/main \
|
||||
-Iapps/common \
|
||||
-Iapps/audioplayers \
|
||||
-Iapps/factory \
|
||||
-Iservices/ble_app \
|
||||
-Iservices/bt_app \
|
||||
-Iservices/anc/inc \
|
||||
-Iservices/multimedia/audio/codec/sbc/inc \
|
||||
-Iservices/nv_section/aud_section \
|
||||
-Iservices/nv_section/include \
|
||||
-Iutils/hwtimer_list \
|
||||
-Iservices/ibrt_core/inc \
|
||||
-Iservices/tota \
|
||||
$(BT_IF_INCLUDES) \
|
||||
-Iservices/app_ibrt/inc \
|
||||
-Iservices/ble_stack/common/api \
|
||||
-Iservices/ble_stack/ble_ip \
|
||||
-Iservices/ibrt_ui/inc \
|
||||
-Iservices/audio_dump/include
|
|
@ -0,0 +1,70 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef __ANC_ASSIT_H__
|
||||
#define __ANC_ASSIT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "plat_types.h"
|
||||
|
||||
//#define AF_ANC_DUMP_DATA
|
||||
|
||||
|
||||
#if defined(_24BITS_ENABLE)
|
||||
#define _SAMPLE_BITS (24)
|
||||
typedef int ASSIST_PCM_T;
|
||||
#else
|
||||
#define _SAMPLE_BITS (16)
|
||||
typedef short ASSIST_PCM_T;
|
||||
#endif
|
||||
|
||||
|
||||
#define ANC_ASSIST_FF1_MIC (1<<2)
|
||||
#define ANC_ASSIST_FF2_MIC (1<<1)
|
||||
#define ANC_ASSIST_FB_MIC (1<<0)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef enum{
|
||||
ANC_ASSIST_STANDALONE = 0,
|
||||
ANC_ASSIST_MUSIC,
|
||||
ANC_ASSIST_PHONE_8K,
|
||||
ANC_ASSIST_PHONE_16K,
|
||||
|
||||
ANC_ASSIST_MODE_QTY
|
||||
|
||||
}ANC_ASSIST_MODE_T;
|
||||
|
||||
|
||||
void anc_assist_open(ANC_ASSIST_MODE_T mode);
|
||||
|
||||
void anc_assist_process(uint8_t * buf, int len);
|
||||
void anc_assist_close();
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __ANC_WNR_H__
|
||||
#define __ANC_WNR_H__
|
||||
|
||||
// #include "plat_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ANC_WNR_OPEN_MODE_STANDALONE = 0,
|
||||
ANC_WNR_OPEN_MODE_CONFIGURE,
|
||||
|
||||
ANC_WNR_OPEN_MODE_QTY
|
||||
} anc_wnr_open_mode_t;
|
||||
|
||||
void anc_release_gain(void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APP_WNR_NOTIFY_DETECT_RESULT,
|
||||
APP_WNR_REQUEST_DETECT_RESULT,
|
||||
APP_WNR_RESPONSE_DETECT_RESULT,
|
||||
APP_WNR_PROCESS_DETECT_RESULT,
|
||||
APP_WNR_SET_TRIGGER,
|
||||
APP_WNR_EXCUTE_TRIGGER,
|
||||
APP_WNR_SHARE_MODULE_INFO,
|
||||
} anc_wnr_sync_ctrl_internal_event_e;
|
||||
|
||||
int32_t anc_wnr_ctrl(int32_t sample_rate, int32_t frame_len);
|
||||
int32_t anc_wnr_open(anc_wnr_open_mode_t mode);
|
||||
int32_t anc_wnr_close(void);
|
||||
int32_t anc_wnr_process(void *pcm_buf, uint32_t pcm_len);
|
||||
void app_wnr_sync_state(void);
|
||||
void app_wnr_cmd_receive_process(uint8_t *p_buff, uint16_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_ANC_H__
|
||||
#define __APP_ANC_H__
|
||||
|
||||
#include "hal_aud.h"
|
||||
#include "app_key.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void app_anc_set_playback_samplerate(enum AUD_SAMPRATE_T sample_rate);
|
||||
void app_anc_init(enum AUD_IO_PATH_T input_path, enum AUD_SAMPRATE_T playback_rate, enum AUD_SAMPRATE_T capture_rate);
|
||||
void app_anc_close(void);
|
||||
void app_anc_enable(void);
|
||||
void app_anc_disable(void);
|
||||
bool anc_enabled(void);
|
||||
void test_anc(void);
|
||||
void app_anc_resample(uint32_t res_ratio, uint32_t *in, uint32_t *out, uint32_t samples);
|
||||
#ifdef __BT_ANC_KEY__
|
||||
void app_anc_key(APP_KEY_STATUS *status, void *param);
|
||||
#endif
|
||||
int app_anc_open_module(void);
|
||||
int app_anc_close_module(void);
|
||||
enum AUD_SAMPRATE_T app_anc_get_play_rate(void);
|
||||
bool app_anc_work_status(void);
|
||||
void app_anc_send_howl_evt(uint32_t howl);
|
||||
uint32_t app_anc_get_anc_status(void);
|
||||
bool app_pwr_key_monitor_get_val(void);
|
||||
bool app_anc_switch_get_val(void);
|
||||
void app_anc_ios_init(void);
|
||||
void app_anc_set_init_done(void);
|
||||
bool app_anc_set_reboot(void);
|
||||
void app_anc_status_post(uint8_t status);
|
||||
bool app_anc_is_on(void);
|
||||
uint32_t app_anc_get_sample_rate(void);
|
||||
void app_anc_set_coef_idx(uint8_t idx);
|
||||
uint8_t app_anc_get_coef_idx(void);
|
||||
|
||||
#if defined(IBRT)
|
||||
void app_anc_cmd_receive_process(uint8_t *buf, uint16_t len);
|
||||
void app_anc_set_peer_coef_idx(uint8_t idx);
|
||||
uint8_t app_anc_get_peer_coef_idx(void);
|
||||
void app_anc_set_status_sync_flag(bool status);
|
||||
bool app_anc_get_status_sync_flag(void);
|
||||
#endif
|
||||
|
||||
#ifndef __BT_ANC_KEY__
|
||||
int app_anc_start(void);
|
||||
int app_anc_switch_coef(uint8_t index);
|
||||
int app_anc_stop(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __PEAK_DETECTOR_H__
|
||||
#define __PEAK_DETECTOR_H__
|
||||
|
||||
#include "plat_types.h"
|
||||
#include "hal_aud.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
enum AUD_SAMPRATE_T fs;
|
||||
enum AUD_BITS_T bits;
|
||||
float factor_up;
|
||||
float factor_down;
|
||||
float reduce_dB;
|
||||
} PEAK_DETECTOR_CFG_T;
|
||||
|
||||
void peak_detector_init(void);
|
||||
void peak_detector_setup(PEAK_DETECTOR_CFG_T *cfg);
|
||||
void peak_detector_run(uint8_t *buf, uint32_t len, float vol_multiple);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,445 @@
|
|||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "anc_assist.h"
|
||||
#include "hal_trace.h"
|
||||
#include "arm_math.h"
|
||||
#include "audio_dump.h"
|
||||
#include "speech_cfg.h"
|
||||
#include "anc_process.h"
|
||||
#include "audioflinger.h"
|
||||
#include "anc_assist_algo.h"
|
||||
#include "hal_codec.h"
|
||||
#include "audioflinger.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_aud.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "hal_aud.h"
|
||||
#include "anc_process.h"
|
||||
#include "anc_assist_algo.h"
|
||||
#include "speech_memory.h"
|
||||
#include "speech_ssat.h"
|
||||
|
||||
|
||||
#if defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
#include "main_classify.h"
|
||||
#endif
|
||||
|
||||
|
||||
static void _close_mic_anc_assist();
|
||||
static void _open_mic_anc_assist();
|
||||
#define _SAMPLE_RATE (16000)
|
||||
|
||||
#if defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
#define _FRAME_LEN (128)
|
||||
#else
|
||||
#define _FRAME_LEN (160)
|
||||
#endif
|
||||
|
||||
#define _CHANNEL_NUM_MAX (3)
|
||||
#define SAMPLE_BYTES (sizeof(ASSIST_PCM_T))
|
||||
#define AF_STREAM_BUFF_SIZE (_FRAME_LEN * SAMPLE_BYTES * _CHANNEL_NUM_MAX * 2)
|
||||
#define ANC_ADPT_STREAM_ID AUD_STREAM_ID_3
|
||||
|
||||
#define _FRAME_LEN_MAX (160)
|
||||
#define _SAMPLE_BITS_MAX (32)
|
||||
|
||||
static uint8_t __attribute__((aligned(4))) af_stream_buff[AF_STREAM_BUFF_SIZE];
|
||||
static ASSIST_PCM_T af_stream_mic1[_FRAME_LEN_MAX * (_SAMPLE_BITS_MAX / 8)];
|
||||
static ASSIST_PCM_T af_stream_mic2[_FRAME_LEN_MAX * (_SAMPLE_BITS_MAX / 8)];
|
||||
static ASSIST_PCM_T af_stream_mic3[_FRAME_LEN_MAX * (_SAMPLE_BITS_MAX / 8)];
|
||||
int MIC_NUM = 0;
|
||||
int MIC_MAP = 0;
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
#define _PLAY_SAMPLE_RATE (8000)
|
||||
#define _PLAY_FRAME_LEN (80)
|
||||
#define AF_PLAY_STREAM_BUFF_SIZE (_PLAY_FRAME_LEN * SAMPLE_BYTES * 1 * 2)
|
||||
static uint8_t __attribute__((aligned(4))) af_play_stream_buff[AF_PLAY_STREAM_BUFF_SIZE];
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
ClassifyState * NoiseClassify_st = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED) || defined(ANC_ASSIST_HESS_ENABLED) || defined(ANC_ASSIST_PNC_ENABLED) || defined(ANC_ASSIST_DEHOWLING_ENABLED) || defined(ANC_ASSIST_WNR_ENABLED) || defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
|
||||
extern const struct_anc_cfg * anc_coef_list_48k[1];
|
||||
void anc_assist_change_curve(int curve_id){
|
||||
TRACE(2,"[%s] change anc curve %d",__func__,curve_id);
|
||||
anc_set_cfg(anc_coef_list_48k[0],ANC_FEEDFORWARD,ANC_GAIN_NO_DELAY);
|
||||
anc_set_cfg(anc_coef_list_48k[0],ANC_FEEDBACK,ANC_GAIN_NO_DELAY);
|
||||
}
|
||||
bool audio_engine_tt_is_on(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define _tgt_ff_gain (512)
|
||||
void anc_assist_set_anc_gain(float gain_ch_l, float gain_ch_r,enum ANC_TYPE_T anc_type){
|
||||
|
||||
TRACE(2,"[%s] set anc gain %d",__func__,(int)(100*gain_ch_l));
|
||||
uint32_t tgt_ff_gain_l,tgt_ff_gain_r;
|
||||
tgt_ff_gain_l = (uint32_t)(_tgt_ff_gain*gain_ch_l);
|
||||
tgt_ff_gain_r = (uint32_t)(_tgt_ff_gain*gain_ch_r);
|
||||
anc_set_gain(tgt_ff_gain_l,tgt_ff_gain_r,anc_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
static LeakageDetectionState * pilot_st = NULL;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(ANC_ASSIST_HESS_ENABLED) || defined(ANC_ASSIST_PNC_ENABLED) || defined(ANC_ASSIST_DEHOWLING_ENABLED) || defined(ANC_ASSIST_WNR_ENABLED)
|
||||
static ANCAssistMultiState * anc_assist_multi_st = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
ANC_ASSIST_MODE_T g_anc_assist_mode = ANC_ASSIST_MODE_QTY;
|
||||
void anc_assist_open(ANC_ASSIST_MODE_T mode){
|
||||
g_anc_assist_mode = mode;
|
||||
|
||||
|
||||
//normal init
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
pilot_st = LeakageDetection_create(160,0);
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_HESS_ENABLED) || defined(ANC_ASSIST_PNC_ENABLED) || defined(ANC_ASSIST_DEHOWLING_ENABLED) || defined(ANC_ASSIST_WNR_ENABLED)
|
||||
anc_assist_multi_st = ANCAssistMulti_create(_SAMPLE_RATE,_FRAME_LEN,128);
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
NoiseClassify_st = classify_create(_SAMPLE_RATE, _FRAME_LEN);
|
||||
#endif
|
||||
|
||||
// audio_dump_init(160,sizeof(short),3);
|
||||
|
||||
|
||||
if( mode == ANC_ASSIST_MODE_QTY){
|
||||
return;
|
||||
}
|
||||
else{
|
||||
if(mode == ANC_ASSIST_STANDALONE || mode == ANC_ASSIST_MUSIC ){
|
||||
_open_mic_anc_assist();
|
||||
}
|
||||
if(mode == ANC_ASSIST_PHONE_8K){
|
||||
// normal init 8k
|
||||
}
|
||||
else if(mode == ANC_ASSIST_PHONE_16K){
|
||||
// normal init 16k
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void anc_assist_close(){
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
LeakageDetection_destroy(pilot_st);
|
||||
#endif
|
||||
#if defined(ANC_ASSIST_HESS_ENABLED) || defined(ANC_ASSIST_PNC_ENABLED) || defined(ANC_ASSIST_DEHOWLING_ENABLED) || defined(ANC_ASSIST_WNR_ENABLED)
|
||||
ANCAssistMulti_destroy(anc_assist_multi_st);
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
classify_destroy(NoiseClassify_st);
|
||||
#endif
|
||||
|
||||
// ext_heap_deinit();
|
||||
|
||||
if( g_anc_assist_mode == ANC_ASSIST_MODE_QTY){
|
||||
return;
|
||||
}
|
||||
else{
|
||||
if(g_anc_assist_mode == ANC_ASSIST_STANDALONE || g_anc_assist_mode == ANC_ASSIST_MUSIC ){
|
||||
_close_mic_anc_assist();
|
||||
}
|
||||
if(g_anc_assist_mode == ANC_ASSIST_PHONE_8K){
|
||||
// normal init 8k
|
||||
}
|
||||
else if(g_anc_assist_mode == ANC_ASSIST_PHONE_16K){
|
||||
// normal init 16k
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern ASSIST_PCM_T ref_buf_data[80];
|
||||
void anc_assist_process(uint8_t * buf, int len){
|
||||
|
||||
|
||||
int32_t frame_len = len / SAMPLE_BYTES / MIC_NUM;
|
||||
ASSERT(frame_len == _FRAME_LEN, "[%s] frame len(%d) is invalid.", __func__, frame_len);
|
||||
ASSIST_PCM_T *pcm_buf = (ASSIST_PCM_T *)buf;
|
||||
|
||||
ASSIST_PCM_T *mic1 = (ASSIST_PCM_T *)af_stream_mic1;
|
||||
ASSIST_PCM_T *mic2 = (ASSIST_PCM_T *)af_stream_mic2;
|
||||
ASSIST_PCM_T *mic3 = (ASSIST_PCM_T *)af_stream_mic3;
|
||||
|
||||
for (int32_t i=0; i<frame_len; i++) {
|
||||
mic1[i] = pcm_buf[MIC_NUM*i + 0];
|
||||
mic2[i] = pcm_buf[MIC_NUM*i + 1];
|
||||
mic3[i] = pcm_buf[MIC_NUM*i + 2];
|
||||
}
|
||||
// audio_dump_clear_up();
|
||||
// audio_dump_add_channel_data(0,mic1,160);
|
||||
// audio_dump_add_channel_data(1,mic2,160);
|
||||
// audio_dump_add_channel_data(2,mic3,160);
|
||||
// audio_dump_run();
|
||||
// TRACE(2,"in callback");
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
LeakageDetection_process(pilot_st,AF_ANC_OFF,mic3,ref_buf_data,frame_len);
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_HESS_ENABLED) || defined(ANC_ASSIST_PNC_ENABLED) || defined(ANC_ASSIST_DEHOWLING_ENABLED) || defined(ANC_ASSIST_WNR_ENABLED)
|
||||
ANCAssistMulti_process(anc_assist_multi_st,mic1,mic2,mic3,frame_len);
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
static int last_classify_res = -1;
|
||||
classify_process(NoiseClassify_st, mic1, last_classify_res);
|
||||
#endif
|
||||
|
||||
if(g_anc_assist_mode == ANC_ASSIST_PHONE_16K){
|
||||
//down sample
|
||||
}
|
||||
|
||||
//process fft
|
||||
|
||||
// wnr
|
||||
|
||||
|
||||
// pnc
|
||||
|
||||
|
||||
// hess
|
||||
|
||||
|
||||
|
||||
// pilot adpt
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static uint32_t anc_assist_callback(uint8_t *buf, uint32_t len){
|
||||
#ifdef TEST_MIPS
|
||||
start_ticks = hal_fast_sys_timer_get();
|
||||
#endif
|
||||
anc_assist_process(buf,len);
|
||||
|
||||
#ifdef TEST_MIPS
|
||||
end_ticks = hal_fast_sys_timer_get();
|
||||
used_mips = (end_ticks - start_ticks) * 1000 / (start_ticks - pre_ticks);
|
||||
TRACE(2,"[%s] Usage: %d in a thousand (MIPS).", __func__, used_mips);
|
||||
//wnr_ticks = start_ticks;
|
||||
//TRACE(2,"[%s] WNR frame takes %d ms.", __func__, FAST_TICKS_TO_MS((start_ticks - pre_ticks)*100));
|
||||
pre_ticks = start_ticks;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
static uint32_t anc_assist_playback_callback(uint8_t *buf, uint32_t len){
|
||||
get_pilot_data(buf,len);
|
||||
// TRACE(2,"playing data %d",len);
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void _open_mic_anc_assist(void)
|
||||
{
|
||||
|
||||
int anc_assist_mic_num = 0;
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
anc_assist_mic_num = anc_assist_mic_num | ANC_ASSIST_FB_MIC;
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_HESS_ENABLED) || defined(ANC_ASSIST_NOISE_ADAPTIVE_ENABLED)
|
||||
anc_assist_mic_num = anc_assist_mic_num | ANC_ASSIST_FF1_MIC;
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_PNC_ENABLED)
|
||||
anc_assist_mic_num = anc_assist_mic_num | ANC_ASSIST_FF1_MIC | ANC_ASSIST_FB_MIC;
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_DEHOWLING_ENABLED)
|
||||
anc_assist_mic_num = anc_assist_mic_num | ANC_ASSIST_FF1_MIC | ANC_ASSIST_FB_MIC;
|
||||
#endif
|
||||
|
||||
#if defined(ANC_ASSIST_WNR_ENABLED)
|
||||
anc_assist_mic_num = anc_assist_mic_num | ANC_ASSIST_FF1_MIC | ANC_ASSIST_FF2_MIC;
|
||||
#endif
|
||||
|
||||
switch(anc_assist_mic_num){
|
||||
case(0):
|
||||
{
|
||||
TRACE(2,"[%s] no mic is used",__func__);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case(1):
|
||||
{
|
||||
TRACE(2,"[%s] use fb mic only",__func__);
|
||||
MIC_NUM = 3;
|
||||
MIC_MAP = AUD_INPUT_PATH_AF_ANC;
|
||||
|
||||
}
|
||||
break;
|
||||
case(4):
|
||||
{
|
||||
TRACE(2,"[%s] use ff mic only",__func__);
|
||||
MIC_NUM = 3;
|
||||
MIC_MAP = AUD_INPUT_PATH_ANC_WNR;
|
||||
|
||||
}
|
||||
break;
|
||||
case(5):
|
||||
{
|
||||
TRACE(2,"[%s] use ff mic and fb mic",__func__);
|
||||
MIC_NUM = 3;
|
||||
MIC_MAP = AUD_INPUT_PATH_ANC_WNR;
|
||||
|
||||
}
|
||||
break;
|
||||
case(6):
|
||||
{
|
||||
TRACE(2,"[%s] use ff1 mic and ff2 mic",__func__);
|
||||
MIC_NUM = 2;
|
||||
MIC_MAP = AUD_INPUT_PATH_AF_ANC;
|
||||
|
||||
}
|
||||
break;
|
||||
case(7):
|
||||
{
|
||||
TRACE(2,"[%s] use ff1 mic and ff2 mic and fb mic",__func__);
|
||||
MIC_NUM = 2;
|
||||
MIC_MAP = AUD_INPUT_PATH_AF_ANC;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
TRACE(2,"[%s] invalid mic order is used",__func__);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
MIC_NUM = 3;
|
||||
MIC_MAP = AUD_INPUT_PATH_AF_ANC;
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
TRACE(1,"[%s] ...", __func__);
|
||||
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)MIC_NUM;
|
||||
stream_cfg.sample_rate = (enum AUD_SAMPRATE_T)_SAMPLE_RATE;
|
||||
stream_cfg.bits = (enum AUD_BITS_T)_SAMPLE_BITS;
|
||||
stream_cfg.vol = 12;
|
||||
stream_cfg.chan_sep_buf = false;
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = (enum AUD_IO_PATH_T)MIC_MAP;
|
||||
stream_cfg.handler = anc_assist_callback;
|
||||
stream_cfg.data_size = _FRAME_LEN * SAMPLE_BYTES * 2 * MIC_NUM;
|
||||
stream_cfg.data_ptr = af_stream_buff;
|
||||
ASSERT(stream_cfg.channel_num == MIC_NUM, "[%s] channel number(%d) is invalid.", __func__, stream_cfg.channel_num);
|
||||
TRACE(2,"[%s] sample_rate:%d, data_size:%d", __func__, stream_cfg.sample_rate, stream_cfg.data_size);
|
||||
TRACE(2,"[%s] af_stream_buff = %p", __func__, af_stream_buff);
|
||||
|
||||
af_stream_open(ANC_ADPT_STREAM_ID, AUD_STREAM_CAPTURE, &stream_cfg);
|
||||
af_stream_start(ANC_ADPT_STREAM_ID, AUD_STREAM_CAPTURE);
|
||||
|
||||
|
||||
#if defined(ANC_ASSIST_PILOT_ENABLED)
|
||||
// struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
TRACE(1,"[%s] set play ...", __func__);
|
||||
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
|
||||
|
||||
stream_cfg.bits = (enum AUD_BITS_T)_SAMPLE_BITS;
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
||||
stream_cfg.sample_rate = (enum AUD_SAMPRATE_T)_PLAY_SAMPLE_RATE;
|
||||
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
stream_cfg.vol = 15;
|
||||
|
||||
stream_cfg.handler = anc_assist_playback_callback;
|
||||
stream_cfg.data_ptr = af_play_stream_buff;
|
||||
stream_cfg.data_size = sizeof(af_play_stream_buff);
|
||||
|
||||
|
||||
af_stream_open(ANC_ADPT_STREAM_ID, AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
af_stream_start(ANC_ADPT_STREAM_ID, AUD_STREAM_PLAYBACK);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void _close_mic_anc_assist(){
|
||||
TRACE(1,"[%s] ...", __func__);
|
||||
|
||||
af_stream_stop(ANC_ADPT_STREAM_ID, AUD_STREAM_CAPTURE);
|
||||
af_stream_close(ANC_ADPT_STREAM_ID, AUD_STREAM_CAPTURE);
|
||||
if(g_anc_assist_mode == ANC_ASSIST_STANDALONE || g_anc_assist_mode == ANC_ASSIST_MUSIC ){
|
||||
// close capture
|
||||
}
|
||||
// destroy
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,196 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "math.h"
|
||||
#include "peak_detector.h"
|
||||
|
||||
// #define PKD_FACTOR_UP (0.6)
|
||||
// #define PKD_FACTOR_DOWN (2.0)
|
||||
// #define PKD_REDUCE_RATE (0.0335) // -30dB
|
||||
|
||||
static enum AUD_BITS_T pkd_samp_bits;
|
||||
static float pkd_alphaR = 0.0f;
|
||||
static float pkd_alphaA = 0.0f;
|
||||
static float pkd_factor1 = 0.0f;
|
||||
static float pkd_factor2 = 0.0f;
|
||||
static float pkd_reduce_rate = 1.0f;
|
||||
|
||||
#define FABS(x) ( (x) >= 0.f ? (x) : -(x) )
|
||||
#define Max(a,b) ((a)>(b) ? (a):(b))
|
||||
|
||||
// Depend on codec_dac_vol
|
||||
// const float pkd_vol_multiple[18] = {0.089125, 0.0, 0.005623, 0.007943, 0.011220, 0.015849, 0.022387, 0.031623, 0.044668, 0.063096, 0.089125, 0.125893, 0.177828, 0.251189, 0.354813, 0.501187, 0.707946, 1.000000};
|
||||
|
||||
// static uint32_t test_num = 0;
|
||||
|
||||
// int app_bt_stream_local_volume_get(void);
|
||||
|
||||
// y = 20log(x)
|
||||
static inline float convert_multiple_to_db(float multiple)
|
||||
{
|
||||
return 20*(float)log10(multiple);
|
||||
}
|
||||
|
||||
// x = 10^(y/20)
|
||||
static inline float convert_db_to_multiple(float db)
|
||||
{
|
||||
return (float)pow(10, db/20);
|
||||
}
|
||||
|
||||
void peak_detector_init(void)
|
||||
{
|
||||
pkd_alphaR = 0.0f;
|
||||
pkd_alphaA = 0.0f;
|
||||
pkd_factor1 = 0.0f;
|
||||
pkd_factor2 = 0.0f;
|
||||
pkd_reduce_rate = 1.0f;
|
||||
// TRACE(3,"[%s] pkd_alphaR = %f, pkd_alphaA = %f", __func__, (double)pkd_alphaR, (double)pkd_alphaA);
|
||||
}
|
||||
|
||||
void peak_detector_setup(PEAK_DETECTOR_CFG_T *cfg)
|
||||
{
|
||||
pkd_samp_bits = cfg->bits;
|
||||
pkd_alphaR = (float)exp(-1/(cfg->factor_down * cfg->fs));
|
||||
pkd_alphaA = (float)exp(-1/(cfg->factor_up * cfg->fs));
|
||||
pkd_reduce_rate = convert_db_to_multiple(cfg->reduce_dB);
|
||||
}
|
||||
|
||||
static void peak_detector_run_16bits(int16_t *buf, uint32_t len, float vol_multiple)
|
||||
{
|
||||
float normal_rate = 1.0;
|
||||
float tgt_rate = 1.0;
|
||||
|
||||
for(uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
pkd_factor1 = Max(buf[i], pkd_alphaR * pkd_factor1);
|
||||
pkd_factor2 = pkd_alphaA * pkd_factor2 + (1 - pkd_alphaA) * pkd_factor1;
|
||||
|
||||
normal_rate = pkd_factor2/32768;
|
||||
|
||||
tgt_rate = pkd_reduce_rate / normal_rate / vol_multiple;
|
||||
|
||||
if(tgt_rate > 1.0)
|
||||
{
|
||||
tgt_rate = 1.0;
|
||||
}
|
||||
|
||||
// rate += (tgt_rate - rate) / 10000.0;
|
||||
|
||||
// if(pkd_factor2>)
|
||||
// {
|
||||
// normal_rate = 0.25;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// normal_rate = 0.25;
|
||||
// }
|
||||
// normal_rate *= 1.0 - pkd_factor2/32768;
|
||||
|
||||
buf[i] = (int16_t)(buf[i] * tgt_rate);
|
||||
// buf[i] = 0;
|
||||
//
|
||||
// TRACE(2,"%d, %d", buf[i], pkd_factor2);
|
||||
}
|
||||
|
||||
// if(test_num == 500)
|
||||
// {
|
||||
// test_num = 0;
|
||||
// TRACE(0,"START>>>");
|
||||
// TRACE(2,"vol_level = %d, pkd_vol_multiple = %f", vol_level, pkd_vol_multiple[vol_level]);
|
||||
// TRACE(3,"buf = %d, pkd_alphaR = %f, pkd_alphaA = %f", buf[len-1], pkd_alphaR, pkd_alphaA);
|
||||
// TRACE(4,"pkd_factor1 = %f, pkd_factor2 = %f, normal_rate = %f, tgt_rate = %f", pkd_factor1, pkd_factor2, normal_rate, tgt_rate);
|
||||
// TRACE(0,"END<<<");
|
||||
// // TRACE(7,"[%s] buf = %d, pkd_alphaR = %f, pkd_alphaA = %f, pkd_factor1 = %f, pkd_factor2 = %f, normal_rate = %f", __func__, buf[len-1], pkd_alphaR, pkd_alphaA, pkd_factor1, pkd_factor2, (1.0 - pkd_factor2/32768));
|
||||
// }
|
||||
|
||||
#if 0
|
||||
short sample;
|
||||
short sample_max = 0;
|
||||
short sample_min = 0;
|
||||
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
sample = buf[i];
|
||||
if(sample > sample_max)
|
||||
{
|
||||
sample_max = sample;
|
||||
}
|
||||
|
||||
if(sample < sample_min)
|
||||
{
|
||||
sample_min = sample;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TRACE(2,"Max = %10d, Min = %10d",sample_max, sample_min);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void peak_detector_run_24bits(int32_t *buf, uint32_t len, float vol_multiple)
|
||||
{
|
||||
float normal_rate = 1.0;
|
||||
float tgt_rate = 1.0;
|
||||
|
||||
for(uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
pkd_factor1 = Max(buf[i], pkd_alphaR * pkd_factor1);
|
||||
pkd_factor2 = pkd_alphaA * pkd_factor2 + (1 - pkd_alphaA) * pkd_factor1;
|
||||
|
||||
normal_rate = pkd_factor2/32768;
|
||||
|
||||
tgt_rate = pkd_reduce_rate / normal_rate / vol_multiple;
|
||||
|
||||
if(tgt_rate > 1.0)
|
||||
{
|
||||
tgt_rate = 1.0;
|
||||
}
|
||||
|
||||
// rate += (tgt_rate - rate) / 10000.0;
|
||||
|
||||
// if(pkd_factor2>)
|
||||
// {
|
||||
// normal_rate = 0.25;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// normal_rate = 0.25;
|
||||
// }
|
||||
// normal_rate *= 1.0 - pkd_factor2/32768;
|
||||
|
||||
buf[i] = (int32_t)(buf[i] * tgt_rate);
|
||||
// buf[i] = 0;
|
||||
//
|
||||
// TRACE(2,"%d, %d", buf[i], pkd_factor2);
|
||||
}
|
||||
}
|
||||
|
||||
void peak_detector_run(uint8_t *buf, uint32_t len, float vol_multiple)
|
||||
{
|
||||
// int vol_level = 0;
|
||||
|
||||
if (pkd_samp_bits <= AUD_BITS_16) {
|
||||
len = len / sizeof(int16_t);
|
||||
peak_detector_run_16bits((int16_t *)buf, len, vol_multiple);
|
||||
} else {
|
||||
len = len / sizeof(int32_t);
|
||||
peak_detector_run_24bits((int32_t *)buf, len, vol_multiple);
|
||||
}
|
||||
|
||||
// test_num++;
|
||||
|
||||
// vol_level = app_bt_stream_local_volume_get();
|
||||
}
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
ifeq ($(ANC_APP),1)
|
||||
obj-y += ../../tests/anc_usb/anc_usb_app.c
|
||||
endif
|
||||
obj-y += ../../tests/anc_usb/usb_audio_app.c
|
||||
obj-y += ../../tests/anc_usb/safe_queue.c
|
||||
obj-y += ../../tests/anc_usb/memutils.c
|
||||
obj-y += ../../tests/anc_usb/speech_process.c
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
subdir-ccflags-y += \
|
||||
-Iutils/cqueue \
|
||||
-Iplatform/drivers/ana \
|
||||
-Iservices/audio_process \
|
||||
-Iservices/multimedia/rbcodec/inc \
|
||||
-Iservices/multimedia/audio/process/anc/include \
|
||||
-Iservices/multimedia/audio/process/filters/include \
|
||||
-Iservices/multimedia/audio/process/resample/include \
|
||||
-Iservices/multimedia/speech/inc \
|
||||
-Iservices/nv_section/include \
|
||||
-Iservices/nv_section/aud_section \
|
||||
-Iplatform/drivers/usb/usb_dev/inc \
|
||||
-Itests/anc_usb \
|
||||
-Iutils/hwtimer_list
|
||||
|
||||
CFLAGS_usb_audio_app.o += -DAUDIO_OUTPUT_VOLUME_DEFAULT=$(AUDIO_OUTPUT_VOLUME_DEFAULT)
|
||||
CFLAGS_adda_loop_app.o += -DAUDIO_OUTPUT_VOLUME_DEFAULT=$(AUDIO_OUTPUT_VOLUME_DEFAULT)
|
||||
|
||||
ifeq ($(APP_TEST_AUDIO),1)
|
||||
ccflags-y += -DAPP_TEST_AUDIO
|
||||
endif
|
||||
|
||||
ANC_USB_CFG_FLAGS :=
|
||||
|
||||
# ANC option
|
||||
ifeq ($(ANC_APP),1)
|
||||
ANC_USB_CFG_FLAGS += -DANC_APP
|
||||
endif
|
||||
|
||||
# USB audio option
|
||||
ifeq ($(USB_AUDIO_APP),1)
|
||||
ANC_USB_CFG_FLAGS += -DUSB_AUDIO_APP
|
||||
endif
|
||||
|
||||
ifeq ($(USB_HIGH_SPEED),1)
|
||||
ANC_USB_CFG_FLAGS += -DUSB_HIGH_SPEED
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_RESAMPLE),1)
|
||||
ANC_USB_CFG_FLAGS += -D__AUDIO_RESAMPLE__
|
||||
endif
|
||||
|
||||
ifeq ($(ADC_CH_SEP_BUFF),1)
|
||||
ANC_USB_CFG_FLAGS += -DADC_CH_SEP_BUFF
|
||||
endif
|
||||
|
||||
include platform/drivers/usb/usb_dev/uaud_cfg_flags.mk
|
||||
|
||||
platform/drivers/usb/usb_dev/uaud_cfg_flags.mk: ;
|
||||
|
||||
ANC_USB_CFG_FLAGS += $(UAUD_CFG_FLAGS)
|
||||
|
||||
# USB audio configuration
|
||||
ifeq ($(USB_AUDIO_DYN_CFG),1)
|
||||
ifneq ($(AUDIO_RESAMPLE),1)
|
||||
SW_CAPTURE_RESAMPLE ?= 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_PLAYBACK_24BIT),1)
|
||||
ANC_USB_CFG_FLAGS += -DAUDIO_PLAYBACK_24BIT
|
||||
endif
|
||||
|
||||
# DSD configuration
|
||||
ifeq ($(HW_FIR_DSD_PROCESS),1)
|
||||
ANC_USB_CFG_FLAGS += -D__HW_FIR_DSD_PROCESS__
|
||||
endif
|
||||
|
||||
# EQ configuration
|
||||
ifeq ($(HW_FIR_EQ_PROCESS),1)
|
||||
ANC_USB_CFG_FLAGS += -D__HW_FIR_EQ_PROCESS__
|
||||
endif
|
||||
|
||||
ifeq ($(HW_IIR_EQ_PROCESS),1)
|
||||
ANC_USB_CFG_FLAGS += -D__HW_IIR_EQ_PROCESS__
|
||||
endif
|
||||
|
||||
ifeq ($(SW_IIR_EQ_PROCESS),1)
|
||||
ANC_USB_CFG_FLAGS += -D__SW_IIR_EQ_PROCESS__
|
||||
endif
|
||||
|
||||
ifeq ($(SW_CAPTURE_RESAMPLE),1)
|
||||
ANC_USB_CFG_FLAGS += -DSW_CAPTURE_RESAMPLE
|
||||
endif
|
||||
|
||||
CFLAGS_app_audtest.o += $(ANC_USB_CFG_FLAGS)
|
||||
CFLAGS_usb_audio_app.o += $(ANC_USB_CFG_FLAGS)
|
||||
CFLAGS_anc_usb_app.o += $(ANC_USB_CFG_FLAGS)
|
||||
|
||||
ifeq ($(ANC_KEY_DOUBLE_CLICK_ON_OFF),1)
|
||||
CFLAGS_anc_usb_app.o += -DANC_KEY_DOUBLE_CLICK_ON_OFF
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_FF_ENABLED),1)
|
||||
CFLAGS_anc_usb_app.o += -DANC_FF_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_FB_ENABLED),1)
|
||||
CFLAGS_anc_usb_app.o += -DANC_FB_ENABLED
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_SECTION_SUPPT),1)
|
||||
CFLAGS_anc_usb_app.o += -D__AUDIO_SECTION_SUPPT__
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_INIT_OFF),1)
|
||||
CFLAGS_anc_usb_app.o += -DANC_INIT_OFF
|
||||
endif
|
||||
|
||||
ifeq ($(PC_CMD_UART),1)
|
||||
CFLAGS_app_audtest.o += -D__PC_CMD_UART__
|
||||
endif
|
||||
|
||||
ifeq ($(DELAY_STREAM_OPEN),1)
|
||||
CFLAGS_usb_audio_app.o += -DDELAY_STREAM_OPEN
|
||||
endif
|
||||
|
||||
ifeq ($(NOISE_GATING),1)
|
||||
CFLAGS_usb_audio_app.o += -DNOISE_GATING
|
||||
endif
|
||||
|
||||
ifeq ($(NOISE_REDUCTION),1)
|
||||
CFLAGS_usb_audio_app.o += -DNOISE_REDUCTION
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_L_R_MISALIGN_WORKAROUND),1)
|
||||
CFLAGS_usb_audio_app.o += -DANC_L_R_MISALIGN_WORKAROUND
|
||||
endif
|
||||
|
||||
ifeq ($(ANDROID_ACCESSORY_SPEC),1)
|
||||
CFLAGS_usb_audio_app.o += -DANDROID_ACCESSORY_SPEC
|
||||
ifeq ($(ANDROID_VOICE_CMD_KEY),1)
|
||||
CFLAGS_usb_audio_app.o += -DANDROID_VOICE_CMD_KEY
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DUAL_AUX_MIC_MORE_FILTER),1)
|
||||
CFLAGS_usb_audio_app.o += -DDUAL_AUX_MIC_MORE_FILTER
|
||||
endif
|
||||
|
||||
ifeq ($(FREQ_RESP_EQ),1)
|
||||
CFLAGS_usb_audio_app.o += -DFREQ_RESP_EQ
|
||||
endif
|
||||
|
||||
ifeq ($(KEEP_SAME_LATENCY),1)
|
||||
CFLAGS_usb_audio_app.o += -DKEEP_SAME_LATENCY
|
||||
endif
|
||||
|
||||
ifeq ($(USB_AUDIO_PWRKEY_TEST),1)
|
||||
CFLAGS_usb_audio_app.o += -DUSB_AUDIO_PWRKEY_TEST
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_RESAMPLE),1)
|
||||
# If neither best1000 nor best2000
|
||||
ifeq ($(filter best1000 best2000,$(CHIP)),)
|
||||
PLL_TUNE_SAMPLE_RATE ?= 1
|
||||
endif
|
||||
ifeq ($(PLL_TUNE_SAMPLE_RATE),1)
|
||||
CFLAGS_usb_audio_app.o += -DPLL_TUNE_SAMPLE_RATE
|
||||
endif
|
||||
endif
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_trace.h"
|
||||
#include "app_thread.h"
|
||||
|
||||
#include "hal_timer.h"
|
||||
#include "app_audtest_pattern.h"
|
||||
|
||||
#include "hal_aud.h"
|
||||
#include "audioflinger.h"
|
||||
#include "audiobuffer.h"
|
||||
#include "stdbool.h"
|
||||
#include <string.h>
|
||||
#include "eq_export.h"
|
||||
#include "app_utils.h"
|
||||
|
||||
#if defined(APP_TEST_AUDIO) && defined(ANC_APP)
|
||||
#include "anc_usb_app.h"
|
||||
#include "usb_audio_app.h"
|
||||
#include "usb_audio_frm_defs.h"
|
||||
//#include "dualadc_audio_app.h"
|
||||
#endif
|
||||
|
||||
#define USB_AUDIO_PLAYBACK_BUFF_SIZE (FRAME_SIZE_PLAYBACK * 4)
|
||||
#define USB_AUDIO_CAPTURE_BUFF_SIZE (FRAME_SIZE_CAPTURE * 4)
|
||||
|
||||
#define USB_AUDIO_RECV_BUFF_SIZE (FRAME_SIZE_RECV * 8)
|
||||
#define USB_AUDIO_SEND_BUFF_SIZE (FRAME_SIZE_SEND * 8)
|
||||
|
||||
#define APP_TEST_PLAYBACK_BUFF_SIZE (128 * 20)
|
||||
#define APP_TEST_CAPTURE_BUFF_SIZE (128 * 20)
|
||||
|
||||
#if (USB_AUDIO_PLAYBACK_BUFF_SIZE > APP_TEST_PLAYBACK_BUFF_SIZE)
|
||||
#define REAL_PLAYBACK_BUFF_SIZE USB_AUDIO_PLAYBACK_BUFF_SIZE
|
||||
#else
|
||||
#define REAL_PLAYBACK_BUFF_SIZE APP_TEST_PLAYBACK_BUFF_SIZE
|
||||
#endif
|
||||
|
||||
#if (USB_AUDIO_CAPTURE_BUFF_SIZE > APP_TEST_CAPTURE_BUFF_SIZE)
|
||||
#define REAL_CAPTURE_BUFF_SIZE USB_AUDIO_CAPTURE_BUFF_SIZE
|
||||
#else
|
||||
#define REAL_CAPTURE_BUFF_SIZE APP_TEST_CAPTURE_BUFF_SIZE
|
||||
#endif
|
||||
|
||||
#define ALIGNED4 ALIGNED(4)
|
||||
|
||||
static uint8_t ALIGNED4 app_test_playback_buff[REAL_PLAYBACK_BUFF_SIZE];
|
||||
static uint8_t ALIGNED4 app_test_capture_buff[REAL_CAPTURE_BUFF_SIZE];
|
||||
|
||||
#if defined(APP_TEST_AUDIO) && defined(ANC_APP)
|
||||
static uint8_t ALIGNED4 app_test_recv_buff[USB_AUDIO_RECV_BUFF_SIZE];
|
||||
static uint8_t ALIGNED4 app_test_send_buff[USB_AUDIO_SEND_BUFF_SIZE];
|
||||
#endif
|
||||
|
||||
uint32_t pcm_1ksin_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
static uint32_t nextPbufIdx = 0;
|
||||
uint32_t remain_size = len;
|
||||
uint32_t curr_size = 0;
|
||||
static uint32_t pcm_preIrqTime = 0;;
|
||||
uint32_t stime = 0;
|
||||
|
||||
|
||||
stime = hal_sys_timer_get();
|
||||
TRACE(3,"pcm_1ksin_more_data irqDur:%d readbuff:0x%08x %d\n ", TICKS_TO_MS(stime - pcm_preIrqTime), buf, len);
|
||||
pcm_preIrqTime = stime;
|
||||
|
||||
// TRACE(2,"[pcm_1ksin_more_data] len=%d nextBuf:%d\n", len, nextPbufIdx);
|
||||
if (remain_size > sizeof(sinwave))
|
||||
{
|
||||
do{
|
||||
if (nextPbufIdx)
|
||||
{
|
||||
curr_size = sizeof(sinwave)-nextPbufIdx;
|
||||
memcpy(buf,&sinwave[nextPbufIdx/2], curr_size);
|
||||
remain_size -= curr_size;
|
||||
nextPbufIdx = 0;
|
||||
}
|
||||
else if (remain_size>sizeof(sinwave))
|
||||
{
|
||||
memcpy(buf+curr_size,sinwave,sizeof(sinwave));
|
||||
curr_size += sizeof(sinwave);
|
||||
remain_size -= sizeof(sinwave);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf+curr_size,sinwave,remain_size);
|
||||
nextPbufIdx = remain_size;
|
||||
remain_size = 0;
|
||||
}
|
||||
}while(remain_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((sizeof(sinwave) - nextPbufIdx) >= len)
|
||||
{
|
||||
memcpy(buf, &sinwave[nextPbufIdx/2],len);
|
||||
nextPbufIdx += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_size = sizeof(sinwave)-nextPbufIdx;
|
||||
memcpy(buf, &sinwave[nextPbufIdx/2],curr_size);
|
||||
nextPbufIdx = len - curr_size;
|
||||
memcpy(buf+curr_size,sinwave, nextPbufIdx);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t pcm_mute_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
memset(buf, 0 , len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void da_output_sin1k(bool on)
|
||||
{
|
||||
static bool isRun = false;
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
|
||||
if (isRun==on)
|
||||
return;
|
||||
else
|
||||
isRun=on;
|
||||
TRACE(2,"%s %d\n", __func__, on);
|
||||
|
||||
if (on){
|
||||
stream_cfg.bits = AUD_BITS_16;
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_2;
|
||||
stream_cfg.sample_rate = AUD_SAMPRATE_44100;
|
||||
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
stream_cfg.vol = 16;
|
||||
|
||||
stream_cfg.handler = pcm_1ksin_more_data;
|
||||
stream_cfg.data_ptr = app_test_playback_buff;
|
||||
stream_cfg.data_size = APP_TEST_PLAYBACK_BUFF_SIZE;
|
||||
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
}else{
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void da_tester(uint8_t on)
|
||||
{
|
||||
da_output_sin1k(on);
|
||||
}
|
||||
|
||||
extern int voicecvsd_audio_init(void);
|
||||
extern uint32_t voicecvsd_audio_more_data(uint8_t *buf, uint32_t len);
|
||||
extern int get_voicecvsd_buffer_size(void);
|
||||
extern int store_voice_pcm2cvsd(unsigned char *buf, unsigned int len);
|
||||
|
||||
static uint32_t pcm_data_capture(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t stime, etime;
|
||||
static uint32_t preIrqTime = 0;
|
||||
|
||||
stime = hal_sys_timer_get();
|
||||
// audio_buffer_set_stereo2mono_16bits(buf, len, 1);
|
||||
audio_buffer_set(buf, len);
|
||||
etime = hal_sys_timer_get();
|
||||
TRACE(4,"%s irqDur:%d fsSpend:%d, Len:%d", __func__, TICKS_TO_MS(stime - preIrqTime), TICKS_TO_MS(etime - stime), len);
|
||||
preIrqTime = stime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t pcm_data_playback(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t stime, etime;
|
||||
static uint32_t preIrqTime = 0;
|
||||
stime = hal_sys_timer_get();
|
||||
// audio_buffer_get_mono2stereo_16bits(buf, len);
|
||||
audio_buffer_get(buf, len);
|
||||
etime = hal_sys_timer_get();
|
||||
TRACE(4,"%s irqDur:%d fsSpend:%d, Len:%d", __func__, TICKS_TO_MS(stime - preIrqTime), TICKS_TO_MS(etime - stime), len);
|
||||
preIrqTime = stime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t pcm_cvsd_data_capture(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t stime, etime;
|
||||
static uint32_t preIrqTime = 0;
|
||||
|
||||
//TRACE(1,"%s enter", __func__);
|
||||
stime = hal_sys_timer_get();
|
||||
len >>= 1;
|
||||
audio_stereo2mono_16bits(0, (uint16_t *)buf, (uint16_t *)buf, len);
|
||||
store_voice_pcm2cvsd(buf, len);
|
||||
etime = hal_sys_timer_get();
|
||||
TRACE(4,"%s exit irqDur:%d fsSpend:%d, add:%d", __func__, TICKS_TO_MS(stime - preIrqTime), TICKS_TO_MS(etime - stime), len);
|
||||
preIrqTime = stime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t pcm_cvsd_data_playback(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
int n;
|
||||
uint32_t stime, etime;
|
||||
static uint32_t preIrqTime = 0;
|
||||
|
||||
//TRACE(1,"%s enter", __func__);
|
||||
stime = hal_sys_timer_get();
|
||||
pcm_1ksin_more_data(buf, len);
|
||||
voicecvsd_audio_more_data(buf, len);
|
||||
n = get_voicecvsd_buffer_size();
|
||||
etime = hal_sys_timer_get();
|
||||
TRACE(5,"%s exit irqDur:%d fsSpend:%d, get:%d remain:%d", __func__, TICKS_TO_MS(stime - preIrqTime), TICKS_TO_MS(etime - stime), len, n);
|
||||
preIrqTime = stime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void adc_looptester(bool on, enum AUD_IO_PATH_T input_path, enum AUD_SAMPRATE_T sample_rate)
|
||||
{
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
|
||||
static bool isRun = false;
|
||||
|
||||
if (isRun==on)
|
||||
return;
|
||||
else
|
||||
isRun=on;
|
||||
|
||||
if (on){
|
||||
audio_buffer_init();
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
|
||||
stream_cfg.bits = AUD_BITS_16;
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_2;
|
||||
stream_cfg.sample_rate = sample_rate;
|
||||
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = input_path;
|
||||
stream_cfg.vol = 0x03;
|
||||
|
||||
stream_cfg.handler = pcm_data_capture;
|
||||
|
||||
stream_cfg.data_ptr = app_test_capture_buff;
|
||||
stream_cfg.data_size = APP_TEST_CAPTURE_BUFF_SIZE;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
||||
|
||||
stream_cfg.handler = pcm_data_playback;
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
|
||||
stream_cfg.data_ptr = app_test_playback_buff;
|
||||
stream_cfg.data_size = APP_TEST_PLAYBACK_BUFF_SIZE;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
}else{
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(APP_TEST_AUDIO) && defined(ANC_APP)
|
||||
void app_anc_usb_init(void)
|
||||
{
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
|
||||
|
||||
anc_usb_app_init(AUD_INPUT_PATH_MAINMIC, AUD_SAMPRATE_96000, AUD_SAMPRATE_192000);
|
||||
|
||||
struct USB_AUDIO_BUF_CFG cfg;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.play_buf = app_test_playback_buff;
|
||||
cfg.play_size = USB_AUDIO_PLAYBACK_BUFF_SIZE;
|
||||
cfg.cap_buf = app_test_capture_buff;
|
||||
cfg.cap_size = USB_AUDIO_CAPTURE_BUFF_SIZE;
|
||||
cfg.recv_buf = app_test_recv_buff;
|
||||
cfg.recv_size = USB_AUDIO_RECV_BUFF_SIZE;
|
||||
cfg.send_buf = app_test_send_buff;
|
||||
cfg.send_size = USB_AUDIO_SEND_BUFF_SIZE;
|
||||
|
||||
usb_audio_app_init(&cfg);
|
||||
|
||||
//dualadc_audio_app_init(app_test_playback_buff, USB_AUDIO_PLAYBACK_BUFF_SIZE,
|
||||
//app_test_capture_buff, USB_AUDIO_CAPTURE_BUFF_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_AUDTEST_H__
|
||||
#define __APP_AUDTEST_H__
|
||||
|
||||
#include "audioflinger.h"
|
||||
void da_output_sin1k(bool on);
|
||||
void adc_looptester(bool on, uint8_t mode, enum AUD_SAMPRATE_T sample_rate);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "cqueue.h"
|
||||
#include "string.h"
|
||||
#include "audiobuffer.h"
|
||||
|
||||
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
static osMutexId g_audio_queue_mutex_id = NULL;
|
||||
osMutexDef(g_audio_queue_mutex);
|
||||
#endif
|
||||
|
||||
static CQueue audio_queue;
|
||||
static unsigned char audio_queue_buf[AUDIO_BUFFER_FRAME_SIZE*AUDIO_BUFFER_FRAME_NUM];
|
||||
|
||||
void audio_mono2stereo_16bits(uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < src_len; ++i) {
|
||||
dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
void audio_stereo2mono_16bits(uint8_t chnlsel, uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < src_len; i+=2) {
|
||||
dst_buf[i/2] = src_buf[i + chnlsel];
|
||||
}
|
||||
}
|
||||
|
||||
void audio_buffer_init(void)
|
||||
{
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
if (g_audio_queue_mutex_id == NULL)
|
||||
g_audio_queue_mutex_id = osMutexCreate((osMutex(g_audio_queue_mutex)));
|
||||
#endif
|
||||
InitCQueue(&audio_queue, sizeof(audio_queue_buf), (unsigned char *)&audio_queue_buf);
|
||||
memset(&audio_queue_buf, 0x00, sizeof(audio_queue_buf));
|
||||
}
|
||||
|
||||
int audio_buffer_length(void)
|
||||
{
|
||||
int len;
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexWait(g_audio_queue_mutex_id, osWaitForever);
|
||||
#endif
|
||||
len = LengthOfCQueue(&audio_queue);
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexRelease(g_audio_queue_mutex_id);
|
||||
#endif
|
||||
return len;
|
||||
}
|
||||
|
||||
int audio_buffer_set(uint8_t *buff, uint16_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexWait(g_audio_queue_mutex_id, osWaitForever);
|
||||
#endif
|
||||
status = EnCQueue(&audio_queue, buff, len);
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexRelease(g_audio_queue_mutex_id);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
int audio_buffer_get(uint8_t *buff, uint16_t len)
|
||||
{
|
||||
uint8_t *e1 = NULL, *e2 = NULL;
|
||||
unsigned int len1 = 0, len2 = 0;
|
||||
int status;
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexWait(g_audio_queue_mutex_id, osWaitForever);
|
||||
#endif
|
||||
status = PeekCQueue(&audio_queue, len, &e1, &len1, &e2, &len2);
|
||||
if (len==(len1+len2)){
|
||||
memcpy(buff,e1,len1);
|
||||
memcpy(buff+len1,e2,len2);
|
||||
DeCQueue(&audio_queue, 0, len);
|
||||
DeCQueue(&audio_queue, 0, len2);
|
||||
}else{
|
||||
memset(buff, 0x00, len);
|
||||
status = -1;
|
||||
}
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexRelease(g_audio_queue_mutex_id);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
int audio_buffer_set_stereo2mono_16bits(uint8_t *buff, uint16_t len, uint8_t chnlsel)
|
||||
{
|
||||
int status;
|
||||
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexWait(g_audio_queue_mutex_id, osWaitForever);
|
||||
#endif
|
||||
audio_stereo2mono_16bits(chnlsel, (uint16_t *)buff, (uint16_t *)buff, len>>1);
|
||||
status = EnCQueue(&audio_queue, buff, len>>1);
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexRelease(g_audio_queue_mutex_id);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
int audio_buffer_get_mono2stereo_16bits(uint8_t *buff, uint16_t len)
|
||||
{
|
||||
uint8_t *e1 = NULL, *e2 = NULL;
|
||||
unsigned int len1 = 0, len2 = 0;
|
||||
int status;
|
||||
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexWait(g_audio_queue_mutex_id, osWaitForever);
|
||||
#endif
|
||||
status = PeekCQueue(&audio_queue, len>>1, &e1, &len1, &e2, &len2);
|
||||
if (len>>1== len1+len2){
|
||||
audio_mono2stereo_16bits((uint16_t *)buff, (uint16_t *)e1, len1>>1);
|
||||
audio_mono2stereo_16bits((uint16_t *)(buff+(len1<<1)), (uint16_t *)e2, len2>>1);
|
||||
DeCQueue(&audio_queue, 0, len1);
|
||||
DeCQueue(&audio_queue, 0, len2);
|
||||
status = len;
|
||||
}else{
|
||||
memset(buff, 0x00, len);
|
||||
status = -1;
|
||||
}
|
||||
#ifndef _AUDIO_NO_THREAD_
|
||||
osMutexRelease(g_audio_queue_mutex_id);
|
||||
#endif
|
||||
return status;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __AUDIOBUFFER_H__
|
||||
#define __AUDIOBUFFER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AUDIO_BUFFER_FRAME_SIZE (4*1024)
|
||||
#define AUDIO_BUFFER_FRAME_NUM (1)
|
||||
#define AUDIO_BUFFER_TOTAL_SIZE (AUDIO_BUFFER_FRAME_SIZE*AUDIO_BUFFER_FRAME_NUM)
|
||||
|
||||
void audio_mono2stereo_16bits(uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len);
|
||||
|
||||
void audio_stereo2mono_16bits(uint8_t chnlsel, uint16_t *dst_buf, uint16_t *src_buf, uint32_t src_len);
|
||||
|
||||
void audio_buffer_init(void);
|
||||
|
||||
int audio_buffer_length(void);
|
||||
|
||||
int audio_buffer_set(uint8_t *buff, uint16_t len);
|
||||
|
||||
int audio_buffer_get(uint8_t *buff, uint16_t len);
|
||||
|
||||
int audio_buffer_set_stereo2mono_16bits(uint8_t *buff, uint16_t len, uint8_t chnlsel);
|
||||
|
||||
int audio_buffer_get_mono2stereo_16bits(uint8_t *buff, uint16_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__FMDEC_H__
|
|
@ -0,0 +1,180 @@
|
|||
|
||||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj_s := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.s))
|
||||
obj_c := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c))
|
||||
obj_cpp := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.cpp))
|
||||
|
||||
ifeq ($(A2DP_DECODER_VER),2)
|
||||
obj_cpp := $(filter-out a2dpplay.cpp,$(obj_cpp))
|
||||
obj_cpp += a2dp_decoder/
|
||||
endif
|
||||
|
||||
bt_sco_chain_obj = bt_sco_chain.c bt_sco_chain_thirdparty.c bt_sco_chain_thirdparty_alango.c
|
||||
obj_c := $(filter-out $(bt_sco_chain_obj),$(obj_c))
|
||||
|
||||
ifeq ($(SPEECH_TX_THIRDPARTY_ALANGO),1)
|
||||
obj_c += bt_sco_chain_thirdparty_alango.c
|
||||
else ifeq ($(SPEECH_TX_THIRDPARTY),1)
|
||||
obj_c += bt_sco_chain_thirdparty.c
|
||||
else
|
||||
obj_c += bt_sco_chain.c
|
||||
endif
|
||||
|
||||
ifeq ($(SCO_DMA_SNAPSHOT),1)
|
||||
obj_cpp := $(filter-out voicebtpcmplay.cpp,$(obj_cpp))
|
||||
else
|
||||
obj_cpp := $(filter-out voicebtpcmplay_sco_dma_snapshot.cpp,$(obj_cpp))
|
||||
endif
|
||||
|
||||
ifeq ($(RB_CODEC),1)
|
||||
obj_cpp += $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)rbplay/*.cpp))
|
||||
endif
|
||||
|
||||
obj-y := $(obj_c:.c=.o) $(obj_s:.S=.o) $(obj_cpp:.cpp=.o)
|
||||
|
||||
CFLAGS_a2dpplay.o += -O3
|
||||
|
||||
ifeq ($(A2DP_AAC_ON),1)
|
||||
AAC_INCLUDES = \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libAACdec/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libAACenc/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libFDK/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libMpegTPDec/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libMpegTPEnc/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libPCMutils/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libSBRdec/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libSBRenc/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libSYS/include
|
||||
else
|
||||
AAC_INCLUDES =
|
||||
endif
|
||||
|
||||
ccflags-y := \
|
||||
$(AAC_INCLUDES) \
|
||||
-Iservices/osif \
|
||||
-Iservices/audio_process \
|
||||
-Iservices/fs/fat \
|
||||
-Iservices/fs/sd \
|
||||
-Iservices/resources \
|
||||
-Iservices/fs/fat/ChaN \
|
||||
-Iservices/bt_app \
|
||||
$(BT_IF_INCLUDES) \
|
||||
-Iplatform/drivers/uarthci \
|
||||
-Iutils/cqueue \
|
||||
-Iservices/audio_dump/include \
|
||||
-Iservices/multimedia/speech/inc \
|
||||
-Iservices/multimedia/rbcodec/inc \
|
||||
-Iservices/multimedia/audio/process/eq/include \
|
||||
-Iservices/multimedia/audio/process/resample/include \
|
||||
-Iservices/multimedia/audio/process/filters/include \
|
||||
-Iservices/multimedia/fm/inc \
|
||||
-Iservices/nv_section/aud_section \
|
||||
-Iservices/nv_section/include \
|
||||
-Iservices/overlay \
|
||||
-Iservices/norflash_api \
|
||||
-Iservices/nvrecord \
|
||||
-Iservices/nv_section/log_section \
|
||||
-Iapps/main \
|
||||
-Iapps/audioplayers/rbplay/ \
|
||||
-Iapps/audioplayers/a2dp_decoder \
|
||||
-Iutils/list \
|
||||
-Iutils/heap \
|
||||
-Iutils/intersyshci \
|
||||
-Irtos/rtos \
|
||||
-Iplatform/drivers/ana \
|
||||
-Ithirdparty/audio_codec_lib/scalable/ \
|
||||
-Ithirdparty/audio_codec_lib/liblhdc-dec/inc \
|
||||
-Iapps/apptester \
|
||||
-Iapps/key \
|
||||
-Iplatform/drivers/bt \
|
||||
-Iapps/anc/inc \
|
||||
-Iservices/multimedia/audio/codec/sbc/inc \
|
||||
-Iservices/multimedia/audio/codec/sbc/src/inc \
|
||||
-Iservices/bt_app/a2dp_codecs/include \
|
||||
-Iservices/bt_profiles_enhanced/inc \
|
||||
-Iservices/app_ai/inc
|
||||
|
||||
ifeq ($(IBRT),1)
|
||||
ccflags-y += -Iservices/ibrt_ui/inc
|
||||
ccflags-y += -Iservices/ibrt_core/inc
|
||||
ccflags-y += -Iservices/app_ibrt/inc
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_LDAC_ON),1)
|
||||
ccflags-y += -Ithirdparty/audio_codec_lib/ldac/inc
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_CP_ACCEL),1)
|
||||
ccflags-y += -Iservices/cp_accel
|
||||
else ifeq ($(SCO_CP_ACCEL),1)
|
||||
ccflags-y += -Iservices/cp_accel
|
||||
endif
|
||||
|
||||
ifeq ($(APP_TEST_AUDIO),1)
|
||||
CFLAGS_app_audio.o += -DAPP_TEST_AUDIO
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_RESAMPLE),1)
|
||||
CFLAGS_a2dpplay.o += -D__AUDIO_RESAMPLE__
|
||||
CFLAGS_voicebtpcmplay.o += -D__AUDIO_RESAMPLE__
|
||||
CFLAGS_voicebtpcmplay_sco_dma_snapshot.o += -D__AUDIO_RESAMPLE__
|
||||
endif
|
||||
|
||||
ifeq ($(SW_PLAYBACK_RESAMPLE),1)
|
||||
CFLAGS_a2dpplay.o += -DSW_PLAYBACK_RESAMPLE
|
||||
endif
|
||||
|
||||
ifeq ($(RESAMPLE_ANY_SAMPLE_RATE),1)
|
||||
CFLAGS_a2dpplay.o += -DRESAMPLE_ANY_SAMPLE_RATE
|
||||
endif
|
||||
|
||||
ifeq ($(SW_SCO_RESAMPLE),1)
|
||||
CFLAGS_voicebtpcmplay.o += -DSW_SCO_RESAMPLE
|
||||
CFLAGS_voicebtpcmplay_sco_dma_snapshot.o += -DSW_SCO_RESAMPLE
|
||||
endif
|
||||
|
||||
ifeq ($(SPEECH_TX_THIRDPARTY_ALANGO),1)
|
||||
CFLAGS_bt_sco_chain_thirdparty_alango.o += -Ithirdparty/alango_lib/include
|
||||
endif
|
||||
|
||||
ifeq ($(VOICE_PROMPT),1)
|
||||
CFLAGS_app_audio.o += -DMEDIA_PLAYER_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(AUDIO_QUEUE_SUPPORT),1)
|
||||
CFLAGS_app_audio.o += -D__AUDIO_QUEUE_SUPPORT__
|
||||
endif
|
||||
|
||||
ifeq ($(ANC_APP),1)
|
||||
CFLAGS_app_audio.o += -DANC_APP
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_EQ_24BIT),1)
|
||||
CFLAGS_app_audio.o += -DA2DP_EQ_24BIT
|
||||
CFLAGS_a2dpplay.o += -DA2DP_EQ_24BIT
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_TRACE_CP_ACCEL),1)
|
||||
CFLAGS_a2dpplay.o += -DA2DP_TRACE_CP_ACCEL
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_TRACE_DEC_TIME),1)
|
||||
CFLAGS_a2dpplay.o += -DA2DP_TRACE_DEC_TIME
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_TRACE_CP_DEC_TIME),1)
|
||||
CFLAGS_a2dpplay.o += -DA2DP_TRACE_CP_DEC_TIME
|
||||
endif
|
||||
|
||||
ifeq ($(SPEECH_TX_AEC_CODEC_REF),1)
|
||||
CFLAGS_voicebtpcmplay.o += -DSPEECH_TX_AEC_CODEC_REF
|
||||
CFLAGS_voicebtpcmplay_sco_dma_snapshot.o += -DSPEECH_TX_AEC_CODEC_REF
|
||||
endif
|
||||
|
||||
ifeq ($(SPEECH_RX_24BIT),1)
|
||||
CFLAGS_bt_sco_chain.o += -DSPEECH_RX_24BIT
|
||||
CFLAGS_voicebtpcmplay.o += -DSPEECH_RX_24BIT
|
||||
CFLAGS_voicebtpcmplay_sco_dma_snapshot.o += -DSPEECH_RX_24BIT
|
||||
endif
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := a2dp_decoder.o
|
||||
obj-y += a2dp_decoder_sbc.o
|
||||
CFLAGS_a2dp_decoder_sbc.o += -O3
|
||||
|
||||
ifeq ($(A2DP_AAC_ON),1)
|
||||
obj-y += a2dp_decoder_aac_lc.o
|
||||
CFLAGS_a2dp_decoder_aac_lc.o += -O3
|
||||
AAC_INCLUDES = \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libAACdec/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libAACenc/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libFDK/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libMpegTPDec/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libMpegTPEnc/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libPCMutils/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libSBRdec/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libSBRenc/include \
|
||||
-Iservices/multimedia/audio/codec/fdkaac_codec/libSYS/include
|
||||
else
|
||||
AAC_INCLUDES =
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_SCALABLE_ON),1)
|
||||
obj-y += a2dp_decoder_scalable.o
|
||||
CFLAGS_a2dp_decoder_scalable.o += -O3
|
||||
SCALABLE_INCLUDES = \
|
||||
-Ithirdparty/audio_codec_lib/scalable
|
||||
else
|
||||
SCALABLE_INCLUDES =
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_LHDC_ON),1)
|
||||
obj-y += a2dp_decoder_lhdc.o
|
||||
CFLAGS_a2dp_decoder_lhdc.o += -O3
|
||||
LHDC_INCLUDES = \
|
||||
-Ithirdparty/audio_codec_lib/liblhdc-dec/inc
|
||||
else
|
||||
LHDC_INCLUDES =
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_LDAC_ON),1)
|
||||
obj-y += a2dp_decoder_ldac.o
|
||||
CFLAGS_a2dp_decoder_ldac.o += -O3
|
||||
LDAC_INCLUDES = \
|
||||
-Ithirdparty/audio_codec_lib/ldac/inc
|
||||
else
|
||||
LDAC_INCLUDES =
|
||||
endif
|
||||
|
||||
ccflags-y := \
|
||||
$(AAC_INCLUDES) \
|
||||
$(SCALABLE_INCLUDES) \
|
||||
$(LHDC_INCLUDES) \
|
||||
$(LDAC_INCLUDES) \
|
||||
-Iservices/audio_process \
|
||||
-Iservices/app_ai/inc \
|
||||
-Iservices/fs/fat \
|
||||
-Iservices/fs/sd \
|
||||
-Iservices/resources \
|
||||
-Iservices/fs/fat/ChaN \
|
||||
-Iservices/bt_app \
|
||||
-Iservices/bt_app/a2dp_codecs/include \
|
||||
$(BT_IF_INCLUDES) \
|
||||
-Iplatform/drivers/uarthci \
|
||||
-Iutils/cqueue \
|
||||
-Iservices/audio_dump/include \
|
||||
-Iservices/multimedia/speech/inc \
|
||||
-Iservices/multimedia/rbcodec/inc \
|
||||
-Iservices/multimedia/audio/process/eq/include \
|
||||
-Iservices/multimedia/audio/process/resample/include \
|
||||
-Iservices/multimedia/audio/process/filters/include \
|
||||
-Iservices/multimedia/fm/inc \
|
||||
-Iservices/nv_section/aud_section \
|
||||
-Iservices/nv_section/include \
|
||||
-Iservices/overlay \
|
||||
-Iservices/norflash_api \
|
||||
-Iservices/nvrecord \
|
||||
-Iservices/nv_section/log_section \
|
||||
-Iapps/main \
|
||||
-Iapps/audioplayers/rbplay/ \
|
||||
-Iapps/audioplayers/a2dp_decoder \
|
||||
-Iutils/list \
|
||||
-Iutils/heap \
|
||||
-Iplatform/drivers/ana \
|
||||
-Iapps/apptester \
|
||||
-Iapps/key \
|
||||
-Iservices/multimedia/audio/codec/sbc/inc \
|
||||
-Iservices/multimedia/audio/codec/sbc/src/inc \
|
||||
-Iplatform/drivers/bt \
|
||||
-Iutils/crc32
|
||||
|
||||
ifeq ($(A2DP_LHDC_ON),1)
|
||||
ccflags-y += -Iservices/bt_if_enhanced/lhdc_license
|
||||
endif
|
||||
|
||||
ifeq ($(IBRT),1)
|
||||
ccflags-y += -Iservices/ibrt_core/inc
|
||||
ccflags-y += -Iservices/ibrt_ui/inc
|
||||
ccflags-y += -Iservices/app_ibrt/inc
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_CP_ACCEL),1)
|
||||
obj-y += a2dp_decoder_cp.o
|
||||
ccflags-y += -Iservices/cp_accel
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_TRACE_CP_ACCEL),1)
|
||||
ccflags-y += -DA2DP_TRACE_CP_ACCEL
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_TRACE_DEC_TIME),1)
|
||||
ccflags-y += -DA2DP_TRACE_DEC_TIME
|
||||
endif
|
||||
|
||||
ifeq ($(A2DP_TRACE_CP_DEC_TIME),1)
|
||||
ccflags-y += -DA2DP_TRACE_CP_DEC_TIME
|
||||
endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,155 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __A2DPPLAY_H__
|
||||
#define __A2DPPLAY_H__
|
||||
|
||||
#include "app_utils.h"
|
||||
#include "avdtp_api.h"
|
||||
|
||||
#define A2DP_DECODER_HISTORY_SEQ_SAVE (25)
|
||||
//#define A2DP_DECODER_HISTORY_LOCTIME_SAVE (1)
|
||||
//#define A2DP_DECODER_HISTORY_CHECK_SUM_SAVE (1)
|
||||
|
||||
typedef uint16_t A2DP_AUDIO_CODEC_TYPE;
|
||||
|
||||
#define A2DP_AUDIO_CODEC_TYPE_SBC (1u<<0)
|
||||
#define A2DP_AUDIO_CODEC_TYPE_MPEG2_4_AAC (1u<<1)
|
||||
#define A2DP_AUDIO_CODEC_TYPE_OPUS (1u<<2)
|
||||
#define A2DP_AUDIO_CODEC_TYPE_SCALABL (1u<<3)
|
||||
#define A2DP_AUDIO_CODEC_TYPE_LHDC (1u<<4)
|
||||
#define A2DP_AUDIO_CODEC_TYPE_LDAC (1u<<5)
|
||||
|
||||
#define A2DP_AUDIO_SYNCFRAME_MASK_SEQ (1u<<0)
|
||||
#define A2DP_AUDIO_SYNCFRAME_MASK_TIMESTAMP (1u<<1)
|
||||
#define A2DP_AUDIO_SYNCFRAME_MASK_CURRSUBSEQ (1u<<2)
|
||||
#define A2DP_AUDIO_SYNCFRAME_MASK_TOTALSUBSEQ (1u<<3)
|
||||
|
||||
#define A2DP_AUDIO_SYNCFRAME_MASK_ALL (A2DP_AUDIO_SYNCFRAME_MASK_SEQ | \
|
||||
A2DP_AUDIO_SYNCFRAME_MASK_TIMESTAMP | \
|
||||
A2DP_AUDIO_SYNCFRAME_MASK_CURRSUBSEQ | \
|
||||
A2DP_AUDIO_SYNCFRAME_MASK_TOTALSUBSEQ)
|
||||
|
||||
#define A2DP_AUDIO_SYNCFRAME_CHK(equ, mask_val, mask) (((equ)|!(mask_val&mask)))
|
||||
|
||||
typedef enum {
|
||||
A2DP_AUDIO_LATENCY_STATUS_LOW,
|
||||
A2DP_AUDIO_LATENCY_STATUS_HIGH,
|
||||
} A2DP_AUDIO_LATENCY_STATUS_E;
|
||||
|
||||
typedef struct {
|
||||
uint32_t sample_rate;
|
||||
uint8_t num_channels;
|
||||
uint8_t bits_depth;
|
||||
uint8_t curr_bits;
|
||||
uint32_t frame_samples;
|
||||
float factor_reference;
|
||||
} A2DP_AUDIO_OUTPUT_CONFIG_T;
|
||||
|
||||
typedef enum {
|
||||
A2DP_AUDIO_CHANNEL_SELECT_STEREO,
|
||||
A2DP_AUDIO_CHANNEL_SELECT_LRMERGE,
|
||||
A2DP_AUDIO_CHANNEL_SELECT_LCHNL,
|
||||
A2DP_AUDIO_CHANNEL_SELECT_RCHNL,
|
||||
} A2DP_AUDIO_CHANNEL_SELECT_E;
|
||||
|
||||
typedef struct {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint16_t curSubSequenceNumber;
|
||||
uint16_t totalSubSequenceNumber;
|
||||
uint32_t frame_samples;
|
||||
uint32_t list_samples;
|
||||
uint32_t decoded_frames;
|
||||
uint32_t undecode_frames;
|
||||
uint32_t undecode_min_frames;
|
||||
uint32_t undecode_max_frames;
|
||||
uint32_t average_frames;
|
||||
uint32_t check_sum;
|
||||
A2DP_AUDIO_OUTPUT_CONFIG_T stream_info;
|
||||
} A2DP_AUDIO_LASTFRAME_INFO_T;
|
||||
|
||||
typedef struct {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint16_t curSubSequenceNumber;
|
||||
uint16_t totalSubSequenceNumber;
|
||||
} A2DP_AUDIO_HEADFRAME_INFO_T;
|
||||
|
||||
typedef struct{
|
||||
float proportiongain;
|
||||
float integralgain;
|
||||
float derivativegain;
|
||||
float error[3];
|
||||
float result;
|
||||
}A2DP_AUDIO_SYNC_PID_T;
|
||||
|
||||
typedef A2DP_AUDIO_LASTFRAME_INFO_T A2DP_AUDIO_SYNCFRAME_INFO_T;
|
||||
|
||||
typedef int(*A2DP_AUDIO_DETECT_NEXT_PACKET_CALLBACK)(btif_media_header_t *, unsigned char *, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint32_t a2dp_audio_playback_handler(uint8_t *buffer, uint32_t buffer_bytes);
|
||||
float a2dp_audio_sync_pid_calc(A2DP_AUDIO_SYNC_PID_T *pid, float diff);
|
||||
int a2dp_audio_sync_init(double ratio);
|
||||
int a2dp_audio_sync_reset_data(void);
|
||||
int a2dp_audio_sync_tune_sample_rate(double ratio);
|
||||
int a2dp_audio_sync_direct_tune_sample_rate(double ratio);
|
||||
int a2dp_audio_sync_tune_cancel(void);
|
||||
int a2dp_audio_sysfreq_boost_start(uint32_t boost_cnt);
|
||||
int a2dp_audio_sysfreq_boost_running(void);
|
||||
int a2dp_audio_init(uint32_t sysfreq, A2DP_AUDIO_CODEC_TYPE codec_type, A2DP_AUDIO_OUTPUT_CONFIG_T *config,
|
||||
A2DP_AUDIO_CHANNEL_SELECT_E chnl_sel, uint16_t dest_packet_mut);
|
||||
int a2dp_audio_deinit(void);
|
||||
int a2dp_audio_start(void);
|
||||
int a2dp_audio_stop(void);
|
||||
int a2dp_audio_detect_next_packet_callback_register(A2DP_AUDIO_DETECT_NEXT_PACKET_CALLBACK callback);
|
||||
int a2dp_audio_detect_store_packet_callback_register(A2DP_AUDIO_DETECT_NEXT_PACKET_CALLBACK callback);
|
||||
int a2dp_audio_detect_first_packet(void);
|
||||
int a2dp_audio_detect_first_packet_clear(void);
|
||||
int a2dp_audio_store_packet(btif_media_header_t * header, unsigned char *buf, unsigned int len);
|
||||
int a2dp_audio_discards_packet(uint32_t packets);
|
||||
int a2dp_audio_synchronize_dest_packet_mut(uint32_t mtu);
|
||||
int a2dp_audio_discards_samples(uint32_t samples);
|
||||
int a2dp_audio_convert_list_to_samples(uint32_t *samples);
|
||||
int a2dp_audio_synchronize_packet(A2DP_AUDIO_SYNCFRAME_INFO_T *sync_info, uint32_t mask);
|
||||
int a2dp_audio_decoder_headframe_info_get(A2DP_AUDIO_HEADFRAME_INFO_T *headframe_info);
|
||||
int a2dp_audio_get_packet_samples(void);
|
||||
int a2dp_audio_lastframe_info_get(A2DP_AUDIO_LASTFRAME_INFO_T *lastframe_info);
|
||||
int a2dp_audio_lastframe_info_reset_undecodeframe(void);
|
||||
void a2dp_audio_clear_input_raw_packet_list(void);
|
||||
int a2dp_audio_refill_packet(void);
|
||||
bool a2dp_audio_auto_synchronize_support(void);
|
||||
A2DP_AUDIO_OUTPUT_CONFIG_T *a2dp_audio_get_output_config(void);
|
||||
int a2dp_audio_latency_factor_setlow(void);
|
||||
int a2dp_audio_latency_factor_sethigh(void);
|
||||
float a2dp_audio_latency_factor_get(void);
|
||||
int a2dp_audio_latency_factor_set(float factor);
|
||||
int a2dp_audio_frame_delay_get(void);
|
||||
int a2dp_audio_dest_packet_mut_get(void);
|
||||
int a2dp_audio_latency_factor_status_get(A2DP_AUDIO_LATENCY_STATUS_E *latency_status, float *more_latency_factor);
|
||||
#if A2DP_DECODER_HISTORY_SEQ_SAVE
|
||||
int a2dp_audio_show_history_seq(void);
|
||||
#endif
|
||||
int a2dp_audio_set_channel_select(A2DP_AUDIO_CHANNEL_SELECT_E chnl_sel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__A2DPPLAY_H__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,618 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
|
||||
#include "a2dp_decoder_internal.h"
|
||||
#include "a2dp_decoder_cp.h"
|
||||
#include "cp_accel.h"
|
||||
#include "hal_location.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#include "heap_api.h"
|
||||
#include "norflash_api.h"
|
||||
|
||||
#define CP_IN_FRAME_CNT 100
|
||||
#define CP_OUT_FRAME_CNT 3
|
||||
|
||||
#define CP_IN_CACHE_SIZE (1024 * 10)
|
||||
|
||||
#if defined(A2DP_LHDC_V3)
|
||||
#define CP_HEAP_SIZE (1024 * 64)
|
||||
#else
|
||||
#define CP_HEAP_SIZE (1024 * 32)
|
||||
#endif
|
||||
|
||||
enum CP_DEC_STATE_T {
|
||||
CP_DEC_STATE_IDLE,
|
||||
CP_DEC_STATE_WORKING,
|
||||
CP_DEC_STATE_DONE,
|
||||
CP_DEC_STATE_INIT_DONE,
|
||||
};
|
||||
|
||||
struct CP_IN_FRAME_INFO_T {
|
||||
uint32_t pos;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
struct CP_OUT_FRAME_INFO_T {
|
||||
enum CP_DEC_STATE_T state;
|
||||
uint32_t pos;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
static CP_BSS_LOC uint32_t cp_heap_buf[CP_HEAP_SIZE / 4];
|
||||
static CP_BSS_LOC heap_handle_t cp_heap;
|
||||
|
||||
static CP_BSS_LOC uint16_t cp_in_widx;
|
||||
static CP_BSS_LOC uint16_t cp_in_ridx;
|
||||
|
||||
static CP_BSS_LOC uint8_t cp_out_widx;
|
||||
static CP_BSS_LOC uint8_t cp_out_ridx;
|
||||
|
||||
static CP_BSS_LOC struct CP_IN_FRAME_INFO_T *in_frames;
|
||||
static CP_BSS_LOC struct CP_OUT_FRAME_INFO_T *out_frames;
|
||||
|
||||
static CP_BSS_LOC uint8_t *cp_in_cache;
|
||||
static CP_BSS_LOC uint8_t *cp_out_cache;
|
||||
|
||||
static CP_BSS_LOC bool reset_frames;
|
||||
|
||||
#ifdef A2DP_TRACE_CP_DEC_TIME
|
||||
static CP_BSS_LOC uint32_t cp_last_dec_time;
|
||||
#endif
|
||||
|
||||
static uint8_t max_buffer_frames = 2;
|
||||
static bool mcu_dec_inited;
|
||||
static A2DP_CP_DECODE_T decode_frame;
|
||||
static enum CP_PROC_DELAY_T proc_delay;
|
||||
|
||||
static bool cp_need_reset;
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
unsigned int set_cp_reset_flag(uint8_t evt)
|
||||
{
|
||||
cp_need_reset = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_cp_need_reset(void)
|
||||
{
|
||||
bool ret = cp_need_reset;
|
||||
cp_need_reset = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool is_cp_init_done(void)
|
||||
{
|
||||
return cp_accel_init_done();
|
||||
}
|
||||
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
static void reset_frame_info(void)
|
||||
{
|
||||
uint32_t idle_cnt;
|
||||
int i;
|
||||
|
||||
if (proc_delay == CP_PROC_DELAY_0_FRAME) {
|
||||
idle_cnt = CP_OUT_FRAME_CNT;
|
||||
} else if (proc_delay == CP_PROC_DELAY_1_FRAME) {
|
||||
idle_cnt = CP_OUT_FRAME_CNT - 1;
|
||||
} else {
|
||||
idle_cnt = CP_OUT_FRAME_CNT - 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < CP_OUT_FRAME_CNT; i++) {
|
||||
if (i < idle_cnt) {
|
||||
out_frames[i].state = CP_DEC_STATE_IDLE;
|
||||
} else {
|
||||
out_frames[i].state = CP_DEC_STATE_INIT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
cp_in_widx = 0;
|
||||
cp_in_ridx = 0;
|
||||
cp_out_widx = 0;
|
||||
cp_out_ridx = idle_cnt;
|
||||
|
||||
reset_frames = false;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
static unsigned int cp_a2dp_main(uint8_t event)
|
||||
{
|
||||
int ret;
|
||||
#ifdef A2DP_TRACE_CP_DEC_TIME
|
||||
uint32_t stime;
|
||||
uint32_t etime;
|
||||
#endif
|
||||
|
||||
if (!mcu_dec_inited) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (decode_frame) {
|
||||
do {
|
||||
#ifdef A2DP_TRACE_CP_DEC_TIME
|
||||
stime = hal_fast_sys_timer_get();
|
||||
#endif
|
||||
|
||||
ret = decode_frame();
|
||||
|
||||
#ifdef A2DP_TRACE_CP_DEC_TIME
|
||||
etime = hal_fast_sys_timer_get();
|
||||
TRACE_A2DP_DECODER_I("cp_decode: %5u us in %5u us", FAST_TICKS_TO_US(etime - stime), FAST_TICKS_TO_US(etime - cp_last_dec_time));
|
||||
cp_last_dec_time = etime;
|
||||
#endif
|
||||
} while (ret == 0);
|
||||
}
|
||||
|
||||
if (reset_frames) {
|
||||
reset_frame_info();
|
||||
#ifdef A2DP_TRACE_CP_ACCEL
|
||||
TRACE_A2DP_DECODER_I("%s: Reset frames", __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cp_task_desc TASK_DESC_A2DP = {CP_ACCEL_STATE_CLOSED, cp_a2dp_main, NULL, NULL, set_cp_reset_flag};
|
||||
int a2dp_cp_init(A2DP_CP_DECODE_T decode_func, enum CP_PROC_DELAY_T delay)
|
||||
{
|
||||
if (delay >= CP_PROC_DELAY_QTY) {
|
||||
return 1;
|
||||
}
|
||||
mcu_dec_inited = false;
|
||||
decode_frame = decode_func;
|
||||
proc_delay = delay;
|
||||
#ifdef A2DP_TRACE_CP_DEC_TIME
|
||||
cp_last_dec_time = hal_fast_sys_timer_get();
|
||||
#endif
|
||||
|
||||
norflash_api_flush_disable(NORFLASH_API_USER_CP,(uint32_t)cp_accel_init_done);
|
||||
cp_accel_open(CP_TASK_A2DP_DECODE, &TASK_DESC_A2DP);
|
||||
while(cp_accel_init_done() == false) {
|
||||
hal_sys_timer_delay_us(100);
|
||||
}
|
||||
norflash_api_flush_enable(NORFLASH_API_USER_CP);
|
||||
return 0;
|
||||
}
|
||||
int a2dp_cp_deinit(void)
|
||||
{
|
||||
cp_accel_close(CP_TASK_A2DP_DECODE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
int a2dp_cp_decoder_init(uint32_t out_frame_len, uint8_t max_frames)
|
||||
{
|
||||
uint32_t i;
|
||||
max_buffer_frames = max_frames;
|
||||
if (!mcu_dec_inited) {
|
||||
#ifdef A2DP_TRACE_CP_ACCEL
|
||||
TRACE_A2DP_DECODER_I("%s: Decoder init", __func__);
|
||||
#endif
|
||||
if(cp_accel_init_done() == false){
|
||||
TRACE_A2DP_DECODER_I("%s: CP ACCEL not init yet", __func__);
|
||||
return 6;
|
||||
}
|
||||
|
||||
cp_heap = heap_register(cp_heap_buf, sizeof(cp_heap_buf));
|
||||
if (cp_heap == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_frames = heap_malloc(cp_heap, sizeof(in_frames[0]) * CP_IN_FRAME_CNT);
|
||||
if (in_frames == NULL) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
out_frames = heap_malloc(cp_heap, sizeof(out_frames[0]) * CP_OUT_FRAME_CNT);
|
||||
if (out_frames == NULL) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
cp_in_cache = heap_malloc(cp_heap, CP_IN_CACHE_SIZE);
|
||||
if (cp_in_cache == NULL) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
cp_out_cache = heap_malloc(cp_heap, out_frame_len * CP_OUT_FRAME_CNT);
|
||||
if (cp_out_cache == NULL) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
for (i = 0; i < CP_OUT_FRAME_CNT; i++) {
|
||||
out_frames[i].pos = out_frame_len * i;
|
||||
out_frames[i].len = out_frame_len;
|
||||
}
|
||||
reset_frame_info();
|
||||
|
||||
mcu_dec_inited = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
static uint32_t get_in_frame_cnt(uint32_t in_widx, uint32_t in_ridx)
|
||||
{
|
||||
uint32_t cnt;
|
||||
|
||||
if (in_widx >= in_ridx) {
|
||||
cnt = in_widx - in_ridx;
|
||||
} else {
|
||||
cnt = CP_IN_FRAME_CNT - in_ridx + in_widx;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
uint32_t get_in_cp_frame_cnt(void)
|
||||
{
|
||||
return get_in_frame_cnt(cp_in_widx, cp_in_ridx);
|
||||
}
|
||||
|
||||
uint32_t get_in_cp_frame_delay(void)
|
||||
{
|
||||
return proc_delay;
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
static uint32_t get_in_frame_free_cnt(uint32_t in_widx, uint32_t in_ridx)
|
||||
{
|
||||
uint32_t free_cnt;
|
||||
|
||||
if (in_widx >= in_ridx) {
|
||||
free_cnt = CP_IN_FRAME_CNT - in_widx + in_ridx;
|
||||
} else {
|
||||
free_cnt = in_ridx - in_widx;
|
||||
}
|
||||
free_cnt -= 1;
|
||||
|
||||
return free_cnt;
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
int a2dp_cp_put_in_frame(const void *buf1, uint32_t len1, const void *buf2, uint32_t len2)
|
||||
{
|
||||
uint16_t free_cnt;
|
||||
uint16_t in_widx;
|
||||
uint16_t in_ridx;
|
||||
uint16_t prev_in_widx;
|
||||
uint32_t free_len;
|
||||
uint32_t in_wpos;
|
||||
uint32_t in_rpos;
|
||||
uint32_t aligned_len;
|
||||
|
||||
if (reset_frames) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
in_widx = cp_in_widx;
|
||||
in_ridx = cp_in_ridx;
|
||||
|
||||
if (max_buffer_frames < get_in_cp_frame_cnt()){
|
||||
return 1;
|
||||
}
|
||||
|
||||
free_cnt = get_in_frame_free_cnt(in_widx, in_ridx);
|
||||
if (free_cnt == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (in_widx == in_ridx) {
|
||||
in_wpos = 0;
|
||||
in_rpos = 0;
|
||||
} else {
|
||||
if (in_widx == 0) {
|
||||
prev_in_widx = CP_IN_FRAME_CNT - 1;
|
||||
} else {
|
||||
prev_in_widx = in_widx - 1;
|
||||
}
|
||||
in_wpos = in_frames[prev_in_widx].pos + in_frames[prev_in_widx].len;
|
||||
if (in_wpos >= CP_IN_CACHE_SIZE) {
|
||||
in_wpos -= CP_IN_CACHE_SIZE;
|
||||
}
|
||||
in_rpos = in_frames[in_ridx].pos;
|
||||
}
|
||||
|
||||
// Align to word boundary
|
||||
in_wpos = (in_wpos + 3) & ~3;
|
||||
if (in_wpos >= CP_IN_CACHE_SIZE) {
|
||||
in_wpos -= CP_IN_CACHE_SIZE;
|
||||
}
|
||||
aligned_len = (len1 + len2 + 3) & ~3;
|
||||
|
||||
if (in_wpos >= in_rpos) {
|
||||
free_len = CP_IN_CACHE_SIZE - in_wpos;
|
||||
if (in_rpos == 0) {
|
||||
free_len -= 1;
|
||||
}
|
||||
if (free_len < aligned_len) {
|
||||
free_len = (in_rpos > 0) ? (in_rpos - 1) : 0;
|
||||
if (free_len < aligned_len) {
|
||||
return 2;
|
||||
}
|
||||
in_wpos = 0;
|
||||
}
|
||||
} else {
|
||||
free_len = in_rpos - in_wpos - 1;
|
||||
if (free_len < aligned_len) {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
in_frames[in_widx].pos = in_wpos;
|
||||
in_frames[in_widx].len = len1 + len2;
|
||||
|
||||
if (len1) {
|
||||
memcpy(&cp_in_cache[in_wpos], buf1, len1);
|
||||
in_wpos += len1;
|
||||
}
|
||||
if (len2) {
|
||||
memcpy(&cp_in_cache[in_wpos], buf2, len2);
|
||||
in_wpos += len2;
|
||||
}
|
||||
|
||||
in_widx += 1;
|
||||
if (in_widx >= CP_IN_FRAME_CNT) {
|
||||
in_widx -= CP_IN_FRAME_CNT;
|
||||
}
|
||||
cp_in_widx = in_widx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
int a2dp_cp_get_in_frame(void **p_buf, uint32_t *p_len)
|
||||
{
|
||||
uint16_t in_widx;
|
||||
uint16_t in_ridx;
|
||||
uint32_t in_rpos;
|
||||
|
||||
if (reset_frames) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
in_widx = cp_in_widx;
|
||||
in_ridx = cp_in_ridx;
|
||||
|
||||
if (in_widx == in_ridx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_rpos = in_frames[in_ridx].pos;
|
||||
|
||||
if (p_buf) {
|
||||
*p_buf = &cp_in_cache[in_rpos];
|
||||
}
|
||||
if (p_len) {
|
||||
*p_len = in_frames[in_ridx].len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
int a2dp_cp_consume_in_frame(void)
|
||||
{
|
||||
uint16_t in_widx;
|
||||
uint16_t in_ridx;
|
||||
|
||||
if (reset_frames) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
in_widx = cp_in_widx;
|
||||
in_ridx = cp_in_ridx;
|
||||
|
||||
if (in_widx == in_ridx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_ridx += 1;
|
||||
if (in_ridx >= CP_IN_FRAME_CNT) {
|
||||
in_ridx -= CP_IN_FRAME_CNT;
|
||||
}
|
||||
cp_in_ridx = in_ridx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
uint32_t a2dp_cp_get_in_frame_index(void)
|
||||
{
|
||||
return cp_in_ridx;
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
uint32_t a2dp_cp_get_in_frame_cnt_by_index(uint32_t ridx)
|
||||
{
|
||||
return get_in_frame_cnt(cp_in_widx, ridx);
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
void a2dp_cp_reset_frame(void)
|
||||
{
|
||||
#ifdef A2DP_TRACE_CP_ACCEL
|
||||
TRACE_A2DP_DECODER_I("%s: Reset frames", __func__);
|
||||
#endif
|
||||
|
||||
reset_frames = true;
|
||||
|
||||
// Notify CP to work again
|
||||
cp_accel_send_event_mcu2cp(1);
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
bool a2dp_cp_get_frame_reset_status(void)
|
||||
{
|
||||
return reset_frames;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
enum CP_EMPTY_OUT_FRM_T a2dp_cp_get_emtpy_out_frame(void **p_buf, uint32_t *p_len)
|
||||
{
|
||||
enum CP_EMPTY_OUT_FRM_T ret;
|
||||
uint8_t out_widx;
|
||||
uint32_t out_wpos;
|
||||
enum CP_DEC_STATE_T state ;
|
||||
|
||||
if (reset_frames) {
|
||||
return CP_EMPTY_OUT_FRM_ERR;
|
||||
}
|
||||
|
||||
out_widx = cp_out_widx;
|
||||
state = out_frames[out_widx].state;
|
||||
|
||||
if (state != CP_DEC_STATE_IDLE && state != CP_DEC_STATE_WORKING) {
|
||||
return CP_EMPTY_OUT_FRM_ERR;
|
||||
}
|
||||
|
||||
if (state == CP_DEC_STATE_WORKING) {
|
||||
ret = CP_EMPTY_OUT_FRM_WORKING;
|
||||
} else {
|
||||
out_frames[out_widx].state = CP_DEC_STATE_WORKING;
|
||||
ret = CP_EMPTY_OUT_FRM_OK;
|
||||
}
|
||||
|
||||
out_wpos = out_frames[out_widx].pos;
|
||||
|
||||
if (p_buf) {
|
||||
*p_buf = &cp_out_cache[out_wpos];
|
||||
}
|
||||
if (p_len) {
|
||||
*p_len = out_frames[out_widx].len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
int a2dp_cp_consume_emtpy_out_frame(void)
|
||||
{
|
||||
uint8_t out_widx;
|
||||
|
||||
if (reset_frames) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_widx = cp_out_widx;
|
||||
|
||||
if (out_frames[out_widx].state != CP_DEC_STATE_WORKING) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
out_frames[out_widx].state = CP_DEC_STATE_DONE;
|
||||
|
||||
#ifdef A2DP_TRACE_CP_ACCEL
|
||||
TRACE_A2DP_DECODER_I("AD2P-CP out frame W[%d]", out_widx);
|
||||
#endif
|
||||
|
||||
out_widx += 1;
|
||||
if (out_widx >= CP_OUT_FRAME_CNT) {
|
||||
out_widx -= CP_OUT_FRAME_CNT;
|
||||
}
|
||||
cp_out_widx = out_widx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
int a2dp_cp_get_full_out_frame(void **p_buf, uint32_t *p_len)
|
||||
{
|
||||
uint8_t out_ridx;
|
||||
uint32_t out_rpos;
|
||||
enum CP_DEC_STATE_T state ;
|
||||
|
||||
if (reset_frames) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_ridx = cp_out_ridx;
|
||||
state = out_frames[out_ridx].state;
|
||||
|
||||
if (state != CP_DEC_STATE_DONE && state != CP_DEC_STATE_INIT_DONE) {
|
||||
// Notify CP to work again
|
||||
cp_accel_send_event_mcu2cp(CP_BUILD_ID(CP_TASK_A2DP_DECODE, CP_EVENT_A2DP_DECODE));
|
||||
if (state == CP_DEC_STATE_WORKING){
|
||||
return CP_EMPTY_OUT_FRM_WORKING;
|
||||
}else{
|
||||
return (10 + state);
|
||||
}
|
||||
}
|
||||
|
||||
out_rpos = out_frames[out_ridx].pos;
|
||||
|
||||
if (state == CP_DEC_STATE_DONE) {
|
||||
if (p_buf) {
|
||||
*p_buf = &cp_out_cache[out_rpos];
|
||||
}
|
||||
if (p_len) {
|
||||
*p_len = out_frames[out_ridx].len;
|
||||
}
|
||||
} else {
|
||||
if (p_buf) {
|
||||
*p_buf = NULL;
|
||||
}
|
||||
if (p_len) {
|
||||
*p_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SRAM_TEXT_LOC
|
||||
int a2dp_cp_consume_full_out_frame(void)
|
||||
{
|
||||
uint8_t out_ridx;
|
||||
enum CP_DEC_STATE_T state ;
|
||||
|
||||
if (reset_frames) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_ridx = cp_out_ridx;
|
||||
state = out_frames[out_ridx].state;
|
||||
|
||||
if (state != CP_DEC_STATE_DONE && state != CP_DEC_STATE_INIT_DONE) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef A2DP_TRACE_CP_ACCEL
|
||||
TRACE_A2DP_DECODER_I("AD2P-CP out frame R[%d]", out_ridx);
|
||||
#endif
|
||||
|
||||
out_frames[out_ridx].state = CP_DEC_STATE_IDLE;
|
||||
|
||||
out_ridx += 1;
|
||||
if (out_ridx >= CP_OUT_FRAME_CNT) {
|
||||
out_ridx -= CP_OUT_FRAME_CNT;
|
||||
}
|
||||
cp_out_ridx = out_ridx;
|
||||
|
||||
// Notify CP to work again
|
||||
cp_accel_send_event_mcu2cp(CP_BUILD_ID(CP_TASK_A2DP_DECODE, CP_EVENT_A2DP_DECODE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __A2DP_DECODER_CP_H__
|
||||
#define __A2DP_DECODER_CP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
enum CP_PROC_DELAY_T {
|
||||
CP_PROC_DELAY_0_FRAME = 0,
|
||||
CP_PROC_DELAY_1_FRAME,
|
||||
CP_PROC_DELAY_2_FRAMES,
|
||||
CP_PROC_DELAY_3_FRAMES,
|
||||
|
||||
CP_PROC_DELAY_QTY,
|
||||
};
|
||||
|
||||
enum CP_EMPTY_OUT_FRM_T {
|
||||
CP_EMPTY_OUT_FRM_OK,
|
||||
CP_EMPTY_OUT_FRM_WORKING,
|
||||
CP_EMPTY_OUT_FRM_ERR,
|
||||
};
|
||||
|
||||
typedef int (*A2DP_CP_DECODE_T)(void);
|
||||
|
||||
int a2dp_cp_init(A2DP_CP_DECODE_T decode_func, enum CP_PROC_DELAY_T delay);
|
||||
|
||||
int a2dp_cp_deinit(void);
|
||||
|
||||
int a2dp_cp_decoder_init(uint32_t out_frame_len, uint8_t max_frames);
|
||||
|
||||
int a2dp_cp_put_in_frame(const void *buf1, uint32_t len1, const void *buf2, uint32_t len2);
|
||||
|
||||
int a2dp_cp_get_in_frame(void **p_buf, uint32_t *p_len);
|
||||
|
||||
int a2dp_cp_consume_in_frame(void);
|
||||
|
||||
uint32_t a2dp_cp_get_in_frame_index(void);
|
||||
|
||||
uint32_t a2dp_cp_get_in_frame_cnt_by_index(uint32_t ridx);
|
||||
|
||||
void a2dp_cp_reset_frame(void);
|
||||
|
||||
bool a2dp_cp_get_in_frame_reset_status(void);
|
||||
|
||||
enum CP_EMPTY_OUT_FRM_T a2dp_cp_get_emtpy_out_frame(void **p_buf, uint32_t *p_len);
|
||||
|
||||
int a2dp_cp_consume_emtpy_out_frame(void);
|
||||
|
||||
int a2dp_cp_get_full_out_frame(void **p_buf, uint32_t *p_len);
|
||||
|
||||
int a2dp_cp_consume_full_out_frame(void);
|
||||
|
||||
unsigned int set_cp_reset_flag(uint8_t evt);
|
||||
|
||||
bool is_cp_need_reset(void);
|
||||
|
||||
bool is_cp_init_done(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include "cmsis.h"
|
||||
#include "plat_types.h"
|
||||
#include <string.h>
|
||||
#include "heap_api.h"
|
||||
#include "hal_location.h"
|
||||
#include "a2dp_decoder_internal.h"
|
||||
|
||||
static A2DP_AUDIO_CONTEXT_T *a2dp_audio_context_p = NULL;
|
||||
static A2DP_AUDIO_DECODER_LASTFRAME_INFO_T a2dp_audio_ldac_example_info;
|
||||
static A2DP_AUDIO_OUTPUT_CONFIG_T a2dp_audio_example_output_config;
|
||||
|
||||
typedef struct {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint8_t *buffer;
|
||||
uint32_t buffer_len;
|
||||
} a2dp_audio_example_decoder_frame_t;
|
||||
|
||||
|
||||
int a2dp_audio_example_decode_frame(uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_preparse_packet(btif_media_header_t * header, uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static void *a2dp_audio_example_frame_malloc(uint32_t packet_len)
|
||||
{
|
||||
a2dp_audio_example_decoder_frame_t *decoder_frame_p = NULL;
|
||||
uint8_t *buffer = NULL;
|
||||
|
||||
buffer = (uint8_t *)a2dp_audio_heap_malloc(packet_len);
|
||||
decoder_frame_p = (a2dp_audio_example_decoder_frame_t *)a2dp_audio_heap_malloc(sizeof(a2dp_audio_example_decoder_frame_t));
|
||||
decoder_frame_p->buffer = buffer;
|
||||
decoder_frame_p->buffer_len = packet_len;
|
||||
return (void *)decoder_frame_p;
|
||||
}
|
||||
|
||||
void a2dp_audio_example_free(void *packet)
|
||||
{
|
||||
a2dp_audio_example_decoder_frame_t *decoder_frame_p = (a2dp_audio_example_decoder_frame_t *)packet;
|
||||
a2dp_audio_heap_free(decoder_frame_p->buffer);
|
||||
a2dp_audio_heap_free(decoder_frame_p);
|
||||
}
|
||||
|
||||
int a2dp_audio_example_store_packet(btif_media_header_t * header, uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
a2dp_audio_example_decoder_frame_t *decoder_frame_p = (a2dp_audio_example_decoder_frame_t *)a2dp_audio_example_frame_malloc(buffer_bytes);
|
||||
|
||||
decoder_frame_p->sequenceNumber = header->sequenceNumber;
|
||||
decoder_frame_p->timestamp = header->timestamp;
|
||||
memcpy(decoder_frame_p->buffer, buffer, buffer_bytes);
|
||||
decoder_frame_p->buffer_len = buffer_bytes;
|
||||
a2dp_audio_list_append(list, decoder_frame_p);
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_discards_packet(uint32_t packets)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_headframe_info_get(A2DP_AUDIO_HEADFRAME_INFO_T* headframe_info)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_info_get(void *info)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_init(A2DP_AUDIO_OUTPUT_CONFIG_T *config, void *context)
|
||||
{
|
||||
TRACE_A2DP_DECODER_D("%s", __func__);
|
||||
a2dp_audio_context_p = (A2DP_AUDIO_CONTEXT_T *)context;
|
||||
|
||||
memset(&a2dp_audio_ldac_example_info, 0, sizeof(A2DP_AUDIO_DECODER_LASTFRAME_INFO_T));
|
||||
memcpy(&a2dp_audio_example_output_config, config, sizeof(A2DP_AUDIO_OUTPUT_CONFIG_T));
|
||||
a2dp_audio_ldac_example_info.stream_info = &a2dp_audio_example_output_config;
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_deinit(void)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_synchronize_packet(A2DP_AUDIO_SYNCFRAME_INFO_T *sync_info, uint32_t mask)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_example_synchronize_dest_packet_mut(uint16_t packet_mut)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
A2DP_AUDIO_DECODER_T a2dp_audio_example_decoder_config = {
|
||||
{44100, 2, 16},
|
||||
0,
|
||||
a2dp_audio_example_init,
|
||||
a2dp_audio_example_deinit,
|
||||
a2dp_audio_example_decode_frame,
|
||||
a2dp_audio_example_preparse_packet,
|
||||
a2dp_audio_example_store_packet,
|
||||
a2dp_audio_example_discards_packet,
|
||||
a2dp_audio_example_synchronize_packet,
|
||||
a2dp_audio_example_synchronize_dest_packet_mut,
|
||||
a2dp_audio_example_headframe_info_get,
|
||||
a2dp_audio_example_info_get,
|
||||
a2dp_audio_example_free,
|
||||
} ;
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __A2DP_DECODER_INTERNAL_H__
|
||||
#define __A2DP_DECODER_INTERNAL_H__
|
||||
|
||||
#include "list.h"
|
||||
#include "a2dp_decoder.h"
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
#include "a2dp_decoder_cp.h"
|
||||
#include "hal_location.h"
|
||||
#endif
|
||||
#include "a2dp_decoder_trace.h"
|
||||
|
||||
#define TEXT_A2DP_LOC_A(n, l) __attribute__((section(#n "." #l)))
|
||||
#define TEXT_A2DP_LOC(n, l) TEXT_A2DP_LOC_A(n, l)
|
||||
|
||||
#define TEXT_SBC_LOC TEXT_A2DP_LOC(.overlay_a2dp_sbc, __LINE__)
|
||||
#define TEXT_AAC_LOC TEXT_A2DP_LOC(.overlay_a2dp_aac, __LINE__)
|
||||
#define TEXT_SSC_LOC TEXT_A2DP_LOC(.overlay_a2dp_ssc, __LINE__)
|
||||
#define TEXT_LDAC_LOC TEXT_A2DP_LOC(.overlay_a2dp_ldac, __LINE__)
|
||||
#define TEXT_LHDC_LOC TEXT_A2DP_LOC(.overlay_a2dp_lhdc, __LINE__)
|
||||
|
||||
#define A2DP_DECODER_NO_ERROR (0)
|
||||
#define A2DP_DECODER_DECODE_ERROR (-1)
|
||||
#define A2DP_DECODER_BUSY_ERROR (-2)
|
||||
#define A2DP_DECODER_MEMORY_ERROR (-3)
|
||||
#define A2DP_DECODER_MTU_LIMTER_ERROR (-4)
|
||||
#define A2DP_DECODER_CACHE_UNDERFLOW_ERROR (-5)
|
||||
#define A2DP_DECODER_SYNC_ERROR (-6)
|
||||
#define A2DP_DECODER_NOT_SUPPORT (-128)
|
||||
|
||||
#ifdef MIN
|
||||
#undef MIN
|
||||
#endif
|
||||
#define MIN(a,b) ((a)<(b) ? (a):(b))
|
||||
#ifdef MAX
|
||||
#undef MAX
|
||||
#endif
|
||||
#define MAX(a,b) ((a)>(b) ? (a):(b))
|
||||
|
||||
typedef A2DP_AUDIO_OUTPUT_CONFIG_T AUDIO_DECODER_STREAM_INFO_T;
|
||||
|
||||
typedef int (*AUDIO_DECODER_INIT)(A2DP_AUDIO_OUTPUT_CONFIG_T *, void *);
|
||||
typedef int (*AUDIO_DECODER_DEINIT)(void);
|
||||
typedef int (*AUDIO_DECODER_DECODE_FRAME)(uint8_t *, uint32_t);
|
||||
typedef int (*AUDIO_DECODER_PREPARSE_PACKET)(btif_media_header_t *, uint8_t *, uint32_t);
|
||||
typedef int (*AUDIO_DECODER_STORE_PACKET)(btif_media_header_t *, uint8_t *, uint32_t);
|
||||
typedef int (*AUDIO_DECODER_DISCARDS_PACKET)(uint32_t);
|
||||
typedef int (*AUDIO_DECODER_SYNCHRONIZE_PACKET)(A2DP_AUDIO_SYNCFRAME_INFO_T *, uint32_t);
|
||||
typedef int (*AUDIO_DECODER_SYNCHRONIZE_DEST_PACKET_MUT)(uint16_t);
|
||||
typedef int (*AUDIO_DECODER_HEADFRAME_INFO_GET)(A2DP_AUDIO_HEADFRAME_INFO_T*);
|
||||
typedef int (*AUDIO_DECODER_INFO_GET)(void *);
|
||||
typedef void(*AUDIO_DECODER_PACKET_FREE)(void *);
|
||||
typedef int (*AUDIO_DECODER_SYNCHRONIZE_CONVERT_LIST_TO_SAMPLES)(uint32_t *);
|
||||
typedef int (*AUDIO_DECODER_SYNCHRONIZE_DISCARDS_SAMPLES)(uint32_t);
|
||||
typedef int (*AUDIO_DECODER_CHANNEL_SELECT)(A2DP_AUDIO_CHANNEL_SELECT_E);
|
||||
|
||||
typedef struct {
|
||||
AUDIO_DECODER_STREAM_INFO_T stream_info;
|
||||
uint32_t auto_synchronize_support;
|
||||
AUDIO_DECODER_INIT audio_decoder_init;
|
||||
AUDIO_DECODER_DEINIT audio_decoder_deinit;
|
||||
AUDIO_DECODER_DECODE_FRAME audio_decoder_decode_frame;
|
||||
AUDIO_DECODER_PREPARSE_PACKET audio_decoder_preparse_packet;
|
||||
AUDIO_DECODER_STORE_PACKET audio_decoder_store_packet;
|
||||
AUDIO_DECODER_DISCARDS_PACKET audio_decoder_discards_packet;
|
||||
AUDIO_DECODER_SYNCHRONIZE_PACKET audio_decoder_synchronize_packet;
|
||||
AUDIO_DECODER_SYNCHRONIZE_DEST_PACKET_MUT audio_decoder_synchronize_dest_packet_mut;
|
||||
AUDIO_DECODER_SYNCHRONIZE_CONVERT_LIST_TO_SAMPLES a2dp_audio_convert_list_to_samples;
|
||||
AUDIO_DECODER_SYNCHRONIZE_DISCARDS_SAMPLES a2dp_audio_discards_samples;
|
||||
AUDIO_DECODER_HEADFRAME_INFO_GET audio_decoder_headframe_info_get;
|
||||
AUDIO_DECODER_INFO_GET audio_decoder_info_get;
|
||||
AUDIO_DECODER_PACKET_FREE audio_decoder_packet_free;
|
||||
AUDIO_DECODER_CHANNEL_SELECT audio_decoder_channel_select;
|
||||
} A2DP_AUDIO_DECODER_T;
|
||||
|
||||
typedef struct {
|
||||
list_t *input_raw_packet_list;
|
||||
list_t *output_pcm_packet_list;
|
||||
} A2DP_AUDIO_DATAPATH_T;
|
||||
|
||||
typedef struct {
|
||||
bool enalbe;
|
||||
void *semaphore;
|
||||
} AUDIO_BUFFER_SEMAPHORE_T;
|
||||
|
||||
enum A2DP_AUDIO_DECODER_STATUS {
|
||||
A2DP_AUDIO_DECODER_STATUS_NULL,
|
||||
A2DP_AUDIO_DECODER_STATUS_READY,
|
||||
A2DP_AUDIO_DECODER_STATUS_START,
|
||||
A2DP_AUDIO_DECODER_STATUS_STOP
|
||||
};
|
||||
|
||||
enum A2DP_AUDIO_DECODER_STORE_PACKET_STATUS {
|
||||
A2DP_AUDIO_DECODER_STORE_PACKET_STATUS_IDLE,
|
||||
A2DP_AUDIO_DECODER_STORE_PACKET_STATUS_BUSY,
|
||||
};
|
||||
|
||||
enum A2DP_AUDIO_DECODER_PLAYBACK_STATUS {
|
||||
A2DP_AUDIO_DECODER_PLAYBACK_STATUS_IDLE,
|
||||
A2DP_AUDIO_DECODER_PLAYBACK_STATUS_BUSY,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint16_t curSubSequenceNumber;
|
||||
uint16_t totalSubSequenceNumber;
|
||||
uint32_t frame_samples;
|
||||
uint32_t list_samples;
|
||||
uint32_t decoded_frames;
|
||||
uint32_t undecode_frames;
|
||||
uint32_t check_sum;
|
||||
A2DP_AUDIO_OUTPUT_CONFIG_T stream_info;
|
||||
} A2DP_AUDIO_DECODER_LASTFRAME_INFO_T;
|
||||
|
||||
typedef struct {
|
||||
A2DP_AUDIO_SYNC_PID_T pid;
|
||||
uint32_t tick;
|
||||
uint32_t cnt;
|
||||
} A2DP_AUDIO_SYNC_T;
|
||||
|
||||
typedef struct {
|
||||
A2DP_AUDIO_OUTPUT_CONFIG_T output_cfg;
|
||||
float init_factor_reference;
|
||||
A2DP_AUDIO_CHANNEL_SELECT_E chnl_sel;
|
||||
uint16_t dest_packet_mut;
|
||||
float average_packet_mut;
|
||||
A2DP_AUDIO_DECODER_T audio_decoder;
|
||||
A2DP_AUDIO_DATAPATH_T audio_datapath;
|
||||
list_t *input_raw_packet_list;
|
||||
list_t *output_pcm_packet_list;
|
||||
bool need_detect_first_packet;
|
||||
bool underflow_onporcess;
|
||||
uint32_t skip_frame_cnt_after_no_cache;
|
||||
uint32_t mute_frame_cnt_after_no_cache;
|
||||
AUDIO_BUFFER_SEMAPHORE_T audio_semaphore;
|
||||
void *audio_buffer_mutex;
|
||||
void *audio_status_mutex;
|
||||
void *audio_stop_mutex;
|
||||
enum A2DP_AUDIO_DECODER_STATUS audio_decoder_status;
|
||||
enum A2DP_AUDIO_DECODER_STORE_PACKET_STATUS store_packet_status;
|
||||
enum A2DP_AUDIO_DECODER_PLAYBACK_STATUS playback_status;
|
||||
A2DP_AUDIO_SYNC_T audio_sync;
|
||||
#if A2DP_DECODER_HISTORY_SEQ_SAVE
|
||||
uint16_t historySeq[A2DP_DECODER_HISTORY_SEQ_SAVE];
|
||||
#ifdef A2DP_DECODER_HISTORY_LOCTIME_SAVE
|
||||
uint32_t historyLoctime[A2DP_DECODER_HISTORY_SEQ_SAVE];
|
||||
#endif
|
||||
#ifdef A2DP_DECODER_HISTORY_CHECK_SUM_SAVE
|
||||
uint32_t historyChecksum[A2DP_DECODER_HISTORY_SEQ_SAVE];
|
||||
#endif
|
||||
uint8_t historySeq_idx;
|
||||
#endif
|
||||
} A2DP_AUDIO_CONTEXT_T;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *a2dp_audio_heap_malloc(uint32_t size);
|
||||
void *a2dp_audio_heap_cmalloc(uint32_t size);
|
||||
void *a2dp_audio_heap_realloc(void *rmem, uint32_t newsize);
|
||||
void a2dp_audio_heap_free(void *rmem);
|
||||
|
||||
list_node_t *a2dp_audio_list_begin(const list_t *list);
|
||||
list_node_t *a2dp_audio_list_end(const list_t *list);
|
||||
uint32_t a2dp_audio_list_length(const list_t *list);
|
||||
void *a2dp_audio_list_node(const list_node_t *node);
|
||||
list_node_t *a2dp_audio_list_next(const list_node_t *node);
|
||||
bool a2dp_audio_list_remove(list_t *list, void *data);
|
||||
bool a2dp_audio_list_append(list_t *list, void *data);
|
||||
void a2dp_audio_list_clear(list_t *list);
|
||||
void a2dp_audio_list_free(list_t *list);
|
||||
list_t *a2dp_audio_list_new(list_free_cb callback, list_mempool_zmalloc zmalloc, list_mempool_free free);
|
||||
|
||||
int a2dp_audio_semaphore_wait(uint32_t timeout_ms);
|
||||
int a2dp_audio_semaphore_release(void);
|
||||
int a2dp_audio_decoder_internal_lastframe_info_set(A2DP_AUDIO_DECODER_LASTFRAME_INFO_T *lastframe_info);
|
||||
uint32_t a2dp_audio_get_passed(uint32_t curr_ticks, uint32_t prev_ticks, uint32_t max_ticks);
|
||||
uint32_t a2dp_audio_decoder_internal_check_sum_generate(const uint8_t *buf, uint32_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__A2DPPLAY_H__
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,969 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include "cmsis.h"
|
||||
#include "plat_types.h"
|
||||
#include <string.h>
|
||||
#include "heap_api.h"
|
||||
#include "hal_location.h"
|
||||
#include "codec_sbc.h"
|
||||
#include "a2dp_decoder_internal.h"
|
||||
#include "hal_timer.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#ifndef SBC_MTU_LIMITER
|
||||
#define SBC_MTU_LIMITER (250) /*must <= 332*/
|
||||
#endif
|
||||
#define SBC_PCMLEN_DEFAULT (512)
|
||||
|
||||
#define SBC_LIST_SAMPLES (128)
|
||||
|
||||
static A2DP_AUDIO_CONTEXT_T *a2dp_audio_context_p = NULL;
|
||||
extern A2DP_AUDIO_DECODER_T a2dp_audio_sbc_decoder_config;
|
||||
|
||||
typedef struct {
|
||||
btif_sbc_decoder_t *sbc_decoder;
|
||||
btif_sbc_pcm_data_t *pcm_data;
|
||||
} a2dp_audio_sbc_decoder_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint16_t curSubSequenceNumber;
|
||||
uint16_t totalSubSequenceNumber;
|
||||
uint8_t *sbc_buffer;
|
||||
uint32_t sbc_buffer_len;
|
||||
} a2dp_audio_sbc_decoder_frame_t;
|
||||
|
||||
static a2dp_audio_sbc_decoder_t a2dp_audio_sbc_decoder;
|
||||
static btif_sbc_decoder_t *a2dp_audio_sbc_decoder_preparse = NULL;
|
||||
|
||||
static A2DP_AUDIO_DECODER_LASTFRAME_INFO_T a2dp_audio_sbc_lastframe_info;
|
||||
|
||||
static uint16_t sbc_mtu_limiter = SBC_MTU_LIMITER;
|
||||
|
||||
static btif_media_header_t sbc_decoder_last_valid_frame = {0,};
|
||||
static bool sbc_decoder_last_valid_frame_ready = false;
|
||||
static bool sbc_chnl_mode_mono = false;
|
||||
|
||||
static int a2dp_audio_sbc_header_parser_init(void);
|
||||
|
||||
static void *a2dp_audio_sbc_subframe_malloc(uint32_t sbc_len)
|
||||
{
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame_p = NULL;
|
||||
uint8_t *sbc_buffer = NULL;
|
||||
|
||||
sbc_buffer = (uint8_t *)a2dp_audio_heap_malloc(sbc_len);
|
||||
sbc_decoder_frame_p = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_heap_malloc(sizeof(a2dp_audio_sbc_decoder_frame_t));
|
||||
sbc_decoder_frame_p->sbc_buffer = sbc_buffer;
|
||||
sbc_decoder_frame_p->sbc_buffer_len = sbc_len;
|
||||
return (void *)sbc_decoder_frame_p;
|
||||
}
|
||||
|
||||
static void a2dp_audio_sbc_subframe_free(void *packet)
|
||||
{
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame_p = (a2dp_audio_sbc_decoder_frame_t *)packet;
|
||||
a2dp_audio_heap_free(sbc_decoder_frame_p->sbc_buffer);
|
||||
a2dp_audio_heap_free(sbc_decoder_frame_p);
|
||||
}
|
||||
|
||||
static void sbc_codec_init(void)
|
||||
{
|
||||
btif_sbc_init_decoder(a2dp_audio_sbc_decoder.sbc_decoder);
|
||||
a2dp_audio_sbc_decoder.sbc_decoder->maxPcmLen = SBC_PCMLEN_DEFAULT;
|
||||
a2dp_audio_sbc_decoder.pcm_data->data = NULL;
|
||||
a2dp_audio_sbc_decoder.pcm_data->dataLen = 0;
|
||||
}
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
struct A2DP_CP_SBC_IN_FRM_INFO_T {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint16_t curSubSequenceNumber;
|
||||
uint16_t totalSubSequenceNumber;
|
||||
};
|
||||
|
||||
struct A2DP_CP_SBC_OUT_FRM_INFO_T {
|
||||
struct A2DP_CP_SBC_IN_FRM_INFO_T in_info;
|
||||
uint16_t frame_samples;
|
||||
uint16_t decoded_frames;
|
||||
uint16_t frame_idx;
|
||||
uint16_t pcm_len;
|
||||
};
|
||||
|
||||
static bool cp_codec_reset;
|
||||
extern "C" uint32_t get_in_cp_frame_cnt(void);
|
||||
extern "C" unsigned int set_cp_reset_flag(uint8_t evt);
|
||||
|
||||
int a2dp_cp_sbc_cp_decode(void);
|
||||
|
||||
extern uint32_t app_bt_stream_get_dma_buffer_samples(void);
|
||||
|
||||
static int TEXT_SBC_LOC a2dp_cp_sbc_after_cache_underflow(void)
|
||||
{
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
cp_codec_reset = true;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a2dp_cp_sbc_mcu_decode(uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
list_node_t *node = NULL;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
int ret, dec_ret;
|
||||
struct A2DP_CP_SBC_IN_FRM_INFO_T in_info;
|
||||
struct A2DP_CP_SBC_OUT_FRM_INFO_T *p_out_info = NULL;
|
||||
uint8_t *out = NULL;
|
||||
uint32_t out_len;
|
||||
uint32_t out_frame_len;
|
||||
uint32_t cp_buffer_frames_max = 0;
|
||||
uint32_t check_sum = 0;
|
||||
|
||||
cp_buffer_frames_max = app_bt_stream_get_dma_buffer_samples()/2;
|
||||
if (cp_buffer_frames_max %(a2dp_audio_sbc_lastframe_info.frame_samples) ){
|
||||
cp_buffer_frames_max = cp_buffer_frames_max /(a2dp_audio_sbc_lastframe_info.frame_samples) +1 ;
|
||||
}else{
|
||||
cp_buffer_frames_max = cp_buffer_frames_max /(a2dp_audio_sbc_lastframe_info.frame_samples) ;
|
||||
}
|
||||
|
||||
out_frame_len = sizeof(*p_out_info) + buffer_bytes;
|
||||
ret = a2dp_cp_decoder_init(out_frame_len, cp_buffer_frames_max * 2);
|
||||
if (ret){
|
||||
TRACE_A2DP_DECODER_W("[SBC][INIT] cp_decoder_init() failed: ret=%d", ret);
|
||||
set_cp_reset_flag(true);
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
while ((node = a2dp_audio_list_begin(list)) != NULL) {
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
|
||||
in_info.sequenceNumber = sbc_decoder_frame->sequenceNumber;
|
||||
in_info.timestamp = sbc_decoder_frame->timestamp;
|
||||
in_info.curSubSequenceNumber = sbc_decoder_frame->curSubSequenceNumber;
|
||||
in_info.totalSubSequenceNumber = sbc_decoder_frame->totalSubSequenceNumber;
|
||||
|
||||
ret = a2dp_cp_put_in_frame(&in_info, sizeof(in_info), sbc_decoder_frame->sbc_buffer, sbc_decoder_frame->sbc_buffer_len);
|
||||
if (ret) {
|
||||
TRACE_A2DP_DECODER_D("[MCU][SBC] piff !!!!!!ret: %d ", ret);
|
||||
break;
|
||||
}
|
||||
check_sum = a2dp_audio_decoder_internal_check_sum_generate(sbc_decoder_frame->sbc_buffer, sbc_decoder_frame->sbc_buffer_len);
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}
|
||||
|
||||
ret = a2dp_cp_get_full_out_frame((void **)&out, &out_len);
|
||||
if (ret) {
|
||||
if (!get_in_cp_frame_cnt()){
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] cp cache underflow list:%d in_cp:%d",a2dp_audio_list_length(list), get_in_cp_frame_cnt());
|
||||
return A2DP_DECODER_CACHE_UNDERFLOW_ERROR;
|
||||
}
|
||||
if (!a2dp_audio_sysfreq_boost_running()){
|
||||
a2dp_audio_sysfreq_boost_start(1);
|
||||
}
|
||||
osDelay(8);
|
||||
ret = a2dp_cp_get_full_out_frame((void **)&out, &out_len);
|
||||
if (ret) {
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] cp cache underflow list:%d in_cp:%d",a2dp_audio_list_length(list), get_in_cp_frame_cnt());
|
||||
a2dp_cp_sbc_after_cache_underflow();
|
||||
return A2DP_DECODER_CACHE_UNDERFLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_len == 0) {
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] olz!!!%d ",__LINE__);
|
||||
memset(buffer, 0, buffer_bytes);
|
||||
a2dp_cp_consume_full_out_frame();
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
if(out_len != out_frame_len){
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] Bad out len %u (should be %u)", out_len, out_frame_len);
|
||||
set_cp_reset_flag(true);
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
p_out_info = (struct A2DP_CP_SBC_OUT_FRM_INFO_T *)out;
|
||||
if (p_out_info->pcm_len) {
|
||||
a2dp_audio_sbc_lastframe_info.sequenceNumber = p_out_info->in_info.sequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.timestamp = p_out_info->in_info.timestamp;
|
||||
a2dp_audio_sbc_lastframe_info.curSubSequenceNumber = p_out_info->in_info.curSubSequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.totalSubSequenceNumber = p_out_info->in_info.totalSubSequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.frame_samples = p_out_info->frame_samples;
|
||||
a2dp_audio_sbc_lastframe_info.decoded_frames += p_out_info->decoded_frames;
|
||||
a2dp_audio_sbc_lastframe_info.undecode_frames =
|
||||
a2dp_audio_list_length(list) + a2dp_cp_get_in_frame_cnt_by_index(p_out_info->frame_idx) - 1;
|
||||
a2dp_audio_sbc_lastframe_info.check_sum= check_sum?check_sum:a2dp_audio_sbc_lastframe_info.check_sum;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&a2dp_audio_sbc_lastframe_info);
|
||||
}
|
||||
|
||||
if (p_out_info->pcm_len == buffer_bytes) {
|
||||
memcpy(buffer, p_out_info + 1, p_out_info->pcm_len);
|
||||
dec_ret = A2DP_DECODER_NO_ERROR;
|
||||
} else {
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] line:%d cp decoder error !!!!!!", __LINE__);
|
||||
set_cp_reset_flag(true);
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
|
||||
ret = a2dp_cp_consume_full_out_frame();
|
||||
if(ret){
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] cp_consume_full_out_frame failed: ret=%d", ret);
|
||||
set_cp_reset_flag(true);
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
return dec_ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __CP_EXCEPTION_TEST__
|
||||
static bool _cp_assert = false;
|
||||
int cp_assert_sbc(void)
|
||||
{
|
||||
_cp_assert = true;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
TEXT_SBC_LOC
|
||||
int a2dp_cp_sbc_cp_decode(void)
|
||||
{
|
||||
int ret = 0;
|
||||
enum CP_EMPTY_OUT_FRM_T out_frm_st;
|
||||
uint8_t *out = NULL;
|
||||
uint32_t out_len = 0;
|
||||
uint8_t *dec_start = NULL;
|
||||
uint32_t dec_len = 0;
|
||||
struct A2DP_CP_SBC_IN_FRM_INFO_T *p_in_info = NULL;
|
||||
struct A2DP_CP_SBC_OUT_FRM_INFO_T *p_out_info = NULL;
|
||||
uint8_t *in_buf = NULL;
|
||||
uint32_t in_len = 0;
|
||||
uint16_t bytes_parsed = 0;
|
||||
float sbc_subbands_gain[8]={1,1,1,1,1,1,1,1};
|
||||
btif_sbc_decoder_t *sbc_decoder = NULL;
|
||||
btif_sbc_pcm_data_t *pcm_data = NULL;
|
||||
bt_status_t decoder_err = 0;
|
||||
int error = 0;
|
||||
|
||||
if (cp_codec_reset) {
|
||||
cp_codec_reset = false;
|
||||
sbc_codec_init();
|
||||
}
|
||||
|
||||
|
||||
#ifdef __CP_EXCEPTION_TEST__
|
||||
if (_cp_assert){
|
||||
_cp_assert = false;
|
||||
*(int*) 0 = 1;
|
||||
//ASSERT_A2DP_DECODER(0, "ASSERT_A2DP_DECODER %s %d", __func__, __LINE__);
|
||||
}
|
||||
#endif
|
||||
|
||||
sbc_decoder = a2dp_audio_sbc_decoder.sbc_decoder;
|
||||
pcm_data = a2dp_audio_sbc_decoder.pcm_data;
|
||||
|
||||
out_frm_st = a2dp_cp_get_emtpy_out_frame((void **)&out, &out_len);
|
||||
if (out_frm_st != CP_EMPTY_OUT_FRM_OK && out_frm_st != CP_EMPTY_OUT_FRM_WORKING) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASSERT_A2DP_DECODER(out_len > sizeof(*p_out_info), "[CP][SBC] Bad out_len %u (should > %u)", out_len, sizeof(*p_out_info));
|
||||
|
||||
p_out_info = (struct A2DP_CP_SBC_OUT_FRM_INFO_T *)out;
|
||||
if (out_frm_st == CP_EMPTY_OUT_FRM_OK) {
|
||||
p_out_info->pcm_len = 0;
|
||||
p_out_info->decoded_frames = 0;
|
||||
}
|
||||
ASSERT_A2DP_DECODER(out_len > sizeof(*p_out_info) + p_out_info->pcm_len, "[CP][SBC] Bad out_len %u (should > %u + %u)", out_len, sizeof(*p_out_info), p_out_info->pcm_len);
|
||||
|
||||
dec_start = (uint8_t *)(p_out_info + 1) + p_out_info->pcm_len;
|
||||
dec_len = out_len - (dec_start - (uint8_t *)out);
|
||||
|
||||
pcm_data->data = dec_start;
|
||||
pcm_data->dataLen = 0;
|
||||
error = 0;
|
||||
|
||||
while (pcm_data->dataLen < dec_len && error == 0) {
|
||||
ret = a2dp_cp_get_in_frame((void **)&in_buf, &in_len);
|
||||
if (ret) {
|
||||
p_out_info->pcm_len += pcm_data->dataLen;
|
||||
return 4;
|
||||
}
|
||||
ASSERT_A2DP_DECODER(in_len > sizeof(*p_in_info), "%s: Bad in_len %u (should > %u)", __func__, in_len, sizeof(*p_in_info));
|
||||
|
||||
p_in_info = (struct A2DP_CP_SBC_IN_FRM_INFO_T *)in_buf;
|
||||
in_buf += sizeof(*p_in_info);
|
||||
in_len -= sizeof(*p_in_info);
|
||||
|
||||
decoder_err = btif_sbc_decode_frames(sbc_decoder, in_buf, in_len,
|
||||
&bytes_parsed,
|
||||
pcm_data,
|
||||
dec_len,
|
||||
sbc_subbands_gain);
|
||||
switch (decoder_err)
|
||||
{
|
||||
case BT_STS_SUCCESS:
|
||||
case BT_STS_CONTINUE:
|
||||
break;
|
||||
case BT_STS_NO_RESOURCES:
|
||||
error = 1;
|
||||
ASSERT_A2DP_DECODER(0, "sbc_decode BT_STS_NO_RESOURCES pcm has no more buffer, i think can't reach here");
|
||||
break;
|
||||
case BT_STS_FAILED:
|
||||
default:
|
||||
error = 1;
|
||||
sbc_codec_init();
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&p_out_info->in_info, p_in_info, sizeof(*p_in_info));
|
||||
p_out_info->decoded_frames++;
|
||||
p_out_info->frame_samples = sbc_decoder->maxPcmLen/4;
|
||||
p_out_info->frame_idx = a2dp_cp_get_in_frame_index();
|
||||
|
||||
ret = a2dp_cp_consume_in_frame();
|
||||
ASSERT_A2DP_DECODER(ret == 0, "%s: a2dp_cp_consume_in_frame() failed: ret=%d", __func__, ret);
|
||||
}
|
||||
|
||||
p_out_info->pcm_len += pcm_data->dataLen;
|
||||
|
||||
if (error || out_len <= sizeof(*p_out_info) + p_out_info->pcm_len) {
|
||||
ret = a2dp_cp_consume_emtpy_out_frame();
|
||||
ASSERT_A2DP_DECODER(ret == 0, "%s: a2dp_cp_consume_emtpy_out_frame() failed: ret=%d", __func__, ret);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int a2dp_audio_sbc_list_checker(void)
|
||||
{
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
int cnt = 0;
|
||||
|
||||
do {
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_sbc_subframe_malloc(SBC_LIST_SAMPLES);
|
||||
if (sbc_decoder_frame){
|
||||
a2dp_audio_list_append(list, sbc_decoder_frame);
|
||||
}
|
||||
cnt++;
|
||||
}while(sbc_decoder_frame && cnt < SBC_MTU_LIMITER);
|
||||
|
||||
do {
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node){
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}
|
||||
}while(node);
|
||||
|
||||
TRACE_A2DP_DECODER_I("[SBC][INIT] cnt:%d list:%d", cnt, a2dp_audio_list_length(list));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_init(A2DP_AUDIO_OUTPUT_CONFIG_T *config, void *context)
|
||||
{
|
||||
TRACE_A2DP_DECODER_I("[SBC][INIT]");
|
||||
|
||||
a2dp_audio_context_p = (A2DP_AUDIO_CONTEXT_T *)context;
|
||||
|
||||
a2dp_audio_sbc_header_parser_init();
|
||||
memset(&a2dp_audio_sbc_lastframe_info, 0, sizeof(A2DP_AUDIO_DECODER_LASTFRAME_INFO_T));
|
||||
a2dp_audio_sbc_lastframe_info.stream_info = *config;
|
||||
a2dp_audio_sbc_lastframe_info.frame_samples= SBC_LIST_SAMPLES;
|
||||
a2dp_audio_sbc_lastframe_info.list_samples = SBC_LIST_SAMPLES;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&a2dp_audio_sbc_lastframe_info);
|
||||
|
||||
ASSERT_A2DP_DECODER(a2dp_audio_context_p->dest_packet_mut < SBC_MTU_LIMITER, "%s MTU OVERFLOW:%u/%u", __func__, a2dp_audio_context_p->dest_packet_mut, SBC_MTU_LIMITER);
|
||||
|
||||
a2dp_audio_sbc_decoder.sbc_decoder = (btif_sbc_decoder_t *)a2dp_audio_heap_malloc(sizeof(btif_sbc_decoder_t));
|
||||
a2dp_audio_sbc_decoder.pcm_data = (btif_sbc_pcm_data_t *)a2dp_audio_heap_malloc(sizeof(btif_sbc_pcm_data_t));
|
||||
a2dp_audio_sbc_decoder_preparse = (btif_sbc_decoder_t *)a2dp_audio_heap_malloc(sizeof(btif_sbc_decoder_t));
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
int ret;
|
||||
cp_codec_reset = true;
|
||||
ret = a2dp_cp_init(a2dp_cp_sbc_cp_decode, CP_PROC_DELAY_2_FRAMES);
|
||||
ASSERT_A2DP_DECODER(ret == 0, "%s: a2dp_cp_init() failed: ret=%d", __func__, ret);
|
||||
#else
|
||||
sbc_codec_init();
|
||||
#endif
|
||||
a2dp_audio_sbc_list_checker();
|
||||
sbc_chnl_mode_mono = false;
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_deinit(void)
|
||||
{
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
a2dp_cp_deinit();
|
||||
#endif
|
||||
a2dp_audio_heap_free(a2dp_audio_sbc_decoder_preparse);
|
||||
a2dp_audio_heap_free(a2dp_audio_sbc_decoder.sbc_decoder);
|
||||
a2dp_audio_heap_free(a2dp_audio_sbc_decoder.pcm_data);
|
||||
|
||||
TRACE_A2DP_DECODER_I("[SBC][DEINIT]");
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_mcu_decode_frame(uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
bt_status_t ret = BT_STS_SUCCESS;
|
||||
uint16_t bytes_parsed = 0;
|
||||
float sbc_subbands_gain[8]={1,1,1,1,1,1,1,1};
|
||||
btif_sbc_decoder_t *sbc_decoder = NULL;
|
||||
btif_sbc_pcm_data_t *pcm_data = NULL;
|
||||
uint16_t frame_pcmbyte = 0;
|
||||
uint16_t pcm_output_byte = 0;
|
||||
bool cache_underflow = false;
|
||||
|
||||
sbc_decoder = a2dp_audio_sbc_decoder.sbc_decoder;
|
||||
pcm_data = a2dp_audio_sbc_decoder.pcm_data;
|
||||
frame_pcmbyte = sbc_decoder->maxPcmLen;
|
||||
|
||||
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
list_node_t *node = NULL;
|
||||
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
|
||||
pcm_data->data = buffer;
|
||||
pcm_data->dataLen = 0;
|
||||
|
||||
TRACE_A2DP_DECODER_D("[MCU][SBC] size:%d", a2dp_audio_list_length(list));
|
||||
|
||||
for (pcm_output_byte = 0; pcm_output_byte<buffer_bytes; pcm_output_byte += frame_pcmbyte){
|
||||
node = a2dp_audio_list_begin(list);
|
||||
|
||||
if (node){
|
||||
uint32_t lock;
|
||||
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
|
||||
lock = int_lock();
|
||||
ret = btif_sbc_decode_frames(sbc_decoder, sbc_decoder_frame->sbc_buffer, sbc_decoder_frame->sbc_buffer_len,
|
||||
&bytes_parsed,
|
||||
pcm_data,
|
||||
buffer_bytes,
|
||||
sbc_subbands_gain);
|
||||
int_unlock(lock);
|
||||
TRACE_A2DP_DECODER_D("[MCU][SBC] seq:%d/%d/%d len:%d ret:%d used:%d",
|
||||
sbc_decoder_frame->curSubSequenceNumber,
|
||||
sbc_decoder_frame->totalSubSequenceNumber,
|
||||
sbc_decoder_frame->sequenceNumber,
|
||||
sbc_decoder_frame->sbc_buffer_len,
|
||||
ret,
|
||||
bytes_parsed);
|
||||
|
||||
a2dp_audio_sbc_lastframe_info.sequenceNumber = sbc_decoder_frame->sequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.timestamp = sbc_decoder_frame->timestamp;
|
||||
a2dp_audio_sbc_lastframe_info.curSubSequenceNumber = sbc_decoder_frame->curSubSequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.totalSubSequenceNumber = sbc_decoder_frame->totalSubSequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.frame_samples = sbc_decoder->maxPcmLen/4;
|
||||
a2dp_audio_sbc_lastframe_info.decoded_frames++;
|
||||
a2dp_audio_sbc_lastframe_info.undecode_frames = a2dp_audio_list_length(list)-1;
|
||||
a2dp_audio_sbc_lastframe_info.check_sum = a2dp_audio_decoder_internal_check_sum_generate(sbc_decoder_frame->sbc_buffer, sbc_decoder_frame->sbc_buffer_len);
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&a2dp_audio_sbc_lastframe_info);
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
switch (ret)
|
||||
{
|
||||
case BT_STS_SUCCESS:
|
||||
if (pcm_data->dataLen != buffer_bytes){
|
||||
TRACE_A2DP_DECODER_W("[MCU][SBC] WARNING pcm buff mismatch %d/%d", pcm_data->dataLen, buffer_bytes);
|
||||
}
|
||||
if (pcm_data->dataLen == buffer_bytes){
|
||||
if (pcm_output_byte+frame_pcmbyte != buffer_bytes){
|
||||
TRACE_A2DP_DECODER_W("[MCU][SBC]WARNING loop not break %d/%d frame_pcm:%d", pcm_output_byte, buffer_bytes, frame_pcmbyte);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BT_STS_CONTINUE:
|
||||
continue;
|
||||
break;
|
||||
case BT_STS_NO_RESOURCES:
|
||||
ASSERT_A2DP_DECODER(0, "sbc_decode BT_STS_NO_RESOURCES pcm has no more buffer, i think can't reach here");
|
||||
break;
|
||||
case BT_STS_FAILED:
|
||||
default:
|
||||
sbc_codec_init();
|
||||
goto exit;
|
||||
}
|
||||
}else{
|
||||
TRACE_A2DP_DECODER_W("[MCU][SBC] A2DP PACKET CACHE UNDERFLOW");
|
||||
ret = BT_STS_FAILED;
|
||||
cache_underflow = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
exit:
|
||||
if (cache_underflow){
|
||||
TRACE_A2DP_DECODER_W("[MCU][SBC] A2DP PACKET CACHE UNDERFLOW need add some process");
|
||||
a2dp_audio_sbc_lastframe_info.undecode_frames = 0;
|
||||
a2dp_audio_sbc_lastframe_info.check_sum = 0;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&a2dp_audio_sbc_lastframe_info);
|
||||
ret = A2DP_DECODER_CACHE_UNDERFLOW_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_decode_frame(uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
int nRet = 0;
|
||||
if (sbc_chnl_mode_mono){
|
||||
int i = 0;
|
||||
int16_t *src = NULL,*dest = NULL;
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
nRet = a2dp_cp_sbc_mcu_decode(buffer, buffer_bytes/2);
|
||||
#else
|
||||
nRet = a2dp_audio_sbc_mcu_decode_frame(buffer, buffer_bytes/2);
|
||||
#endif
|
||||
i = buffer_bytes / 2;
|
||||
dest = (int16_t *)buffer + i - 1;
|
||||
i = i / 2;
|
||||
src = (int16_t *)buffer + i - 1;
|
||||
for (; i>=0; i--){
|
||||
*dest = *src;
|
||||
dest--;
|
||||
*dest = *src;
|
||||
dest--;
|
||||
src--;
|
||||
}
|
||||
}else{
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
nRet = a2dp_cp_sbc_mcu_decode(buffer, buffer_bytes);
|
||||
#else
|
||||
nRet = a2dp_audio_sbc_mcu_decode_frame(buffer, buffer_bytes);
|
||||
#endif
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_preparse_packet(btif_media_header_t * header, uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
uint16_t bytes_parsed = 0;
|
||||
uint32_t frame_num = 0;
|
||||
uint8_t *parser_p = buffer;
|
||||
|
||||
frame_num = *parser_p;
|
||||
parser_p++;
|
||||
buffer_bytes--;
|
||||
|
||||
// TODO: Remove the following sbc init and decode codes. They might conflict with the calls
|
||||
// during CP process. CP process is triggered by audioflinger PCM callback.
|
||||
|
||||
|
||||
if (*parser_p != 0x9c){
|
||||
TRACE_A2DP_DECODER_I("[SBC][PRE] ERROR SBC FRAME !!! frame_num:%d", frame_num);
|
||||
DUMP8("%02x ", parser_p, 12);
|
||||
}else{
|
||||
btif_sbc_decode_frames_parser(a2dp_audio_sbc_decoder_preparse,parser_p, buffer_bytes, &bytes_parsed);
|
||||
TRACE_A2DP_DECODER_I("[SBC][PRE] seq:%d tStmp:%08x smpR:%d ch:%d len:%d",
|
||||
header->sequenceNumber,
|
||||
header->timestamp,
|
||||
a2dp_audio_sbc_decoder_preparse->streamInfo.sampleFreq,
|
||||
a2dp_audio_sbc_decoder_preparse->streamInfo.channelMode,
|
||||
a2dp_audio_sbc_decoder_preparse->maxPcmLen);
|
||||
TRACE_A2DP_DECODER_I("[SBC][PRE] frmN:%d par:%d/%d", frame_num, buffer_bytes, bytes_parsed);
|
||||
|
||||
a2dp_audio_sbc_lastframe_info.sequenceNumber = header->sequenceNumber;
|
||||
a2dp_audio_sbc_lastframe_info.timestamp = header->timestamp;
|
||||
a2dp_audio_sbc_lastframe_info.curSubSequenceNumber = 0;
|
||||
a2dp_audio_sbc_lastframe_info.totalSubSequenceNumber = frame_num;
|
||||
a2dp_audio_sbc_lastframe_info.frame_samples = a2dp_audio_sbc_decoder_preparse->maxPcmLen/4;
|
||||
a2dp_audio_sbc_lastframe_info.list_samples = SBC_LIST_SAMPLES;
|
||||
a2dp_audio_sbc_lastframe_info.decoded_frames = 0;
|
||||
a2dp_audio_sbc_lastframe_info.undecode_frames = 0;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&a2dp_audio_sbc_lastframe_info);
|
||||
}
|
||||
if (a2dp_audio_sbc_decoder_preparse->streamInfo.channelMode == BTIF_SBC_CHNL_MODE_MONO){
|
||||
sbc_chnl_mode_mono = true;
|
||||
}
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static int a2dp_audio_sbc_header_parser_init(void)
|
||||
{
|
||||
a2dp_audio_sbc_decoder_config.auto_synchronize_support = true;
|
||||
sbc_decoder_last_valid_frame_ready = false;
|
||||
memset(&sbc_decoder_last_valid_frame, 0, sizeof(sbc_decoder_last_valid_frame));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a2dp_audio_sbc_packet_recover_save_last(btif_media_header_t *sbc_decoder_frame)
|
||||
{
|
||||
sbc_decoder_last_valid_frame = *sbc_decoder_frame;
|
||||
sbc_decoder_last_valid_frame_ready = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int a2dp_audio_sbc_packet_recover_find_missing(btif_media_header_t *sbc_decoder_frame, uint8_t frame_cnt)
|
||||
{
|
||||
uint16_t diff_seq = 0;
|
||||
uint32_t diff_timestamp = 0;
|
||||
uint32_t diff = 0;
|
||||
uint32_t need_recover_pkt = 0;
|
||||
|
||||
if (!sbc_decoder_last_valid_frame_ready){
|
||||
return need_recover_pkt;
|
||||
}
|
||||
|
||||
diff_seq = a2dp_audio_get_passed(sbc_decoder_frame->sequenceNumber, sbc_decoder_last_valid_frame.sequenceNumber, UINT16_MAX);
|
||||
diff_timestamp = a2dp_audio_get_passed(sbc_decoder_frame->timestamp, sbc_decoder_last_valid_frame.timestamp, UINT32_MAX);
|
||||
if (diff_seq > 1){
|
||||
diff = diff_timestamp/diff_seq;
|
||||
if (diff%SBC_LIST_SAMPLES == 0){
|
||||
need_recover_pkt = diff_timestamp/SBC_LIST_SAMPLES;
|
||||
if (need_recover_pkt > frame_cnt){
|
||||
need_recover_pkt -= frame_cnt;
|
||||
}
|
||||
}else{
|
||||
diff_seq--;
|
||||
need_recover_pkt = diff_seq * frame_cnt;
|
||||
}
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT][PLC] seq:%d/%d stmp:%d/%d", sbc_decoder_frame->sequenceNumber, sbc_decoder_last_valid_frame.sequenceNumber,
|
||||
sbc_decoder_frame->timestamp, sbc_decoder_last_valid_frame.timestamp);
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT][PLC] diff_seq:%d diff_stmp:%d diff:%d missing:%d", diff_seq, diff_timestamp, diff, need_recover_pkt);
|
||||
}
|
||||
|
||||
return need_recover_pkt;
|
||||
}
|
||||
|
||||
static int a2dp_audio_sbc_packet_recover_proc(btif_media_header_t *sbc_decoder_frame, a2dp_audio_sbc_decoder_frame_t *sbc_raw_frame, uint8_t frame_cnt)
|
||||
{
|
||||
int nRet = A2DP_DECODER_NO_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
int missing_pkt_cnt = 0;
|
||||
missing_pkt_cnt = a2dp_audio_sbc_packet_recover_find_missing(sbc_decoder_frame, frame_cnt);
|
||||
if (missing_pkt_cnt && sbc_raw_frame &&
|
||||
(a2dp_audio_list_length(list)+missing_pkt_cnt) < sbc_mtu_limiter){
|
||||
for (uint8_t i =0; i<missing_pkt_cnt; i++){
|
||||
a2dp_audio_sbc_decoder_frame_t *frame_p = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_sbc_subframe_malloc(sbc_raw_frame->sbc_buffer_len);
|
||||
if (!frame_p){
|
||||
nRet = A2DP_DECODER_MEMORY_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
frame_p->sequenceNumber = UINT16_MAX;
|
||||
frame_p->timestamp = UINT32_MAX;
|
||||
memcpy(frame_p->sbc_buffer, sbc_raw_frame->sbc_buffer, sbc_raw_frame->sbc_buffer_len);
|
||||
frame_p->sbc_buffer_len = sbc_raw_frame->sbc_buffer_len;
|
||||
a2dp_audio_list_append(list, frame_p);
|
||||
}
|
||||
}
|
||||
exit:
|
||||
return nRet;
|
||||
}
|
||||
|
||||
#define FRAME_LIST_MAX (20)
|
||||
int a2dp_audio_sbc_store_packet(btif_media_header_t * header, uint8_t *buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
int nRet = A2DP_DECODER_NO_ERROR;
|
||||
|
||||
uint32_t frame_cnt = 0;
|
||||
uint32_t frame_num = 0;
|
||||
uint32_t frame_len = 0;
|
||||
uint8_t *parser_p = buffer;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
uint16_t bytes_parsed = 0;
|
||||
a2dp_audio_sbc_decoder_frame_t *frame_list[FRAME_LIST_MAX] = {0,};
|
||||
uint8_t frame_list_idx = 0;
|
||||
bool find_err = false;
|
||||
uint32_t i = 0;
|
||||
|
||||
frame_num = *parser_p;
|
||||
|
||||
if (!frame_num){
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT] ERROR SBC FRAME !!! frame_num:%d", frame_num);
|
||||
DUMP8("%02x ", parser_p, 12);
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
|
||||
parser_p++;
|
||||
buffer_bytes--;
|
||||
frame_len = buffer_bytes/frame_num;
|
||||
|
||||
if ((a2dp_audio_list_length(list)+frame_num) < sbc_mtu_limiter){
|
||||
for (i=0; i<buffer_bytes; i+=bytes_parsed, frame_cnt++){
|
||||
bytes_parsed = 0;
|
||||
if (*(parser_p+i) == 0x9c){
|
||||
if (btif_sbc_decode_frames_parser(a2dp_audio_sbc_decoder_preparse, parser_p+i, buffer_bytes, &bytes_parsed) != BT_STS_SUCCESS){
|
||||
bytes_parsed = frame_len;
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT] ERROR SBC FRAME PARSER !!!");
|
||||
DUMP8("%02x ", parser_p+i, 12);
|
||||
find_err = true;
|
||||
break;
|
||||
}
|
||||
a2dp_audio_sbc_decoder_frame_t *frame_p = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_sbc_subframe_malloc(bytes_parsed);
|
||||
if (!frame_p){
|
||||
nRet = A2DP_DECODER_MEMORY_ERROR;
|
||||
find_err = true;
|
||||
break;
|
||||
}
|
||||
frame_p->sequenceNumber = header->sequenceNumber;
|
||||
frame_p->timestamp = header->timestamp;
|
||||
frame_p->curSubSequenceNumber = frame_cnt;
|
||||
frame_p->totalSubSequenceNumber = frame_num;
|
||||
memcpy(frame_p->sbc_buffer, (parser_p+i), bytes_parsed);
|
||||
frame_p->sbc_buffer_len = bytes_parsed;
|
||||
frame_list[frame_list_idx++] = frame_p;
|
||||
if (frame_list_idx >= FRAME_LIST_MAX){
|
||||
find_err = true;
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT] ERROR SBC FRAME !!!");
|
||||
DUMP8("%02x ", parser_p+i, 12);
|
||||
find_err = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (find_err){
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT] FIND ERR !!!");
|
||||
for (i = 0; i<frame_list_idx; i++){
|
||||
a2dp_audio_sbc_subframe_free(frame_list[i]);
|
||||
}
|
||||
nRet = A2DP_DECODER_DECODE_ERROR;
|
||||
}else{
|
||||
a2dp_audio_sbc_packet_recover_proc(header, frame_list[0], frame_num);
|
||||
a2dp_audio_sbc_packet_recover_save_last(header);
|
||||
for (i = 0; i<frame_list_idx; i++){
|
||||
a2dp_audio_list_append(list, frame_list[i]);
|
||||
}
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
}else{
|
||||
TRACE_A2DP_DECODER_W("[SBC][INPUT] OVERFLOW list:%d", a2dp_audio_list_length(list));
|
||||
nRet = A2DP_DECODER_MTU_LIMTER_ERROR;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_discards_packet(uint32_t packets)
|
||||
{
|
||||
int nRet = A2DP_DECODER_MEMORY_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
uint16_t totalSubSequenceNumber;
|
||||
uint8_t j = 0;
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
a2dp_cp_reset_frame();
|
||||
#endif
|
||||
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (!node){
|
||||
goto exit;
|
||||
}
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
|
||||
for (j=0; j<a2dp_audio_list_length(list); j++){
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (!node){
|
||||
goto exit;
|
||||
}
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
if (sbc_decoder_frame->curSubSequenceNumber != 0){
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (!node){
|
||||
goto exit;
|
||||
}
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
ASSERT_A2DP_DECODER(sbc_decoder_frame->curSubSequenceNumber == 0, "sbc_discards_packet not align curSubSequenceNumber:%d",
|
||||
sbc_decoder_frame->curSubSequenceNumber);
|
||||
|
||||
totalSubSequenceNumber = sbc_decoder_frame->totalSubSequenceNumber;
|
||||
|
||||
if (packets <= a2dp_audio_list_length(list)/totalSubSequenceNumber){
|
||||
for (uint8_t i=0; i<packets; i++){
|
||||
for (j=0; j<totalSubSequenceNumber; j++){
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (!node){
|
||||
goto exit;
|
||||
}
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}
|
||||
}
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
exit:
|
||||
TRACE_A2DP_DECODER_I("[SBC][DISCARDS] packets:%d nRet:%d", packets, nRet);
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_headframe_info_get(A2DP_AUDIO_HEADFRAME_INFO_T *headframe_info)
|
||||
{
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
|
||||
if (a2dp_audio_list_length(list) && ((node = a2dp_audio_list_begin(list)) != NULL)){
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
headframe_info->sequenceNumber = sbc_decoder_frame->sequenceNumber;
|
||||
headframe_info->timestamp = sbc_decoder_frame->timestamp;
|
||||
headframe_info->curSubSequenceNumber = sbc_decoder_frame->curSubSequenceNumber;
|
||||
headframe_info->totalSubSequenceNumber = sbc_decoder_frame->totalSubSequenceNumber;
|
||||
}else{
|
||||
memset(headframe_info, 0, sizeof(A2DP_AUDIO_HEADFRAME_INFO_T));
|
||||
}
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_info_get(void *info)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_synchronize_packet(A2DP_AUDIO_SYNCFRAME_INFO_T *sync_info, uint32_t mask)
|
||||
{
|
||||
int nRet = A2DP_DECODER_SYNC_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
int list_len;
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
a2dp_cp_reset_frame();
|
||||
#endif
|
||||
|
||||
list_len = a2dp_audio_list_length(list);
|
||||
|
||||
for (uint16_t i=0; i<list_len; i++){
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node){
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
if (A2DP_AUDIO_SYNCFRAME_CHK(sbc_decoder_frame->sequenceNumber == sync_info->sequenceNumber, A2DP_AUDIO_SYNCFRAME_MASK_SEQ, mask)&&
|
||||
A2DP_AUDIO_SYNCFRAME_CHK(sbc_decoder_frame->curSubSequenceNumber == sync_info->curSubSequenceNumber, A2DP_AUDIO_SYNCFRAME_MASK_CURRSUBSEQ, mask)&&
|
||||
A2DP_AUDIO_SYNCFRAME_CHK(sbc_decoder_frame->totalSubSequenceNumber == sync_info->totalSubSequenceNumber,A2DP_AUDIO_SYNCFRAME_MASK_TOTALSUBSEQ,mask)){
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
break;
|
||||
}
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}
|
||||
}
|
||||
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node){
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
TRACE_A2DP_DECODER_I("[MCU][SYNC][SBC] sync pkt nRet:%d SEQ:%d timestamp:%d %d/%d",
|
||||
nRet, sbc_decoder_frame->sequenceNumber, sbc_decoder_frame->timestamp,
|
||||
sbc_decoder_frame->curSubSequenceNumber, sbc_decoder_frame->totalSubSequenceNumber);
|
||||
}else{
|
||||
TRACE_A2DP_DECODER_I("[MCU][SYNC][SBC] sync pkt nRet:%d", nRet);
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_synchronize_dest_packet_mut(uint16_t packet_mut)
|
||||
{
|
||||
list_node_t *node = NULL;
|
||||
uint32_t list_len = 0;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
|
||||
list_len = a2dp_audio_list_length(list);
|
||||
if (list_len > packet_mut){
|
||||
do{
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node){
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}
|
||||
}while(a2dp_audio_list_length(list) > packet_mut);
|
||||
}
|
||||
|
||||
TRACE_A2DP_DECODER_I("[MCU][SYNC][SBC] dest pkt list:%d", a2dp_audio_list_length(list));
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_convert_list_to_samples(uint32_t *samples)
|
||||
{
|
||||
uint32_t list_len = 0;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
|
||||
list_len = a2dp_audio_list_length(list);
|
||||
*samples = SBC_LIST_SAMPLES*list_len;
|
||||
|
||||
TRACE_A2DP_DECODER_I("[MCU][SBC] list:%d samples:%d", list_len, *samples);
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_discards_samples(uint32_t samples)
|
||||
{
|
||||
int nRet = A2DP_DECODER_SYNC_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
a2dp_audio_sbc_decoder_frame_t *sbc_decoder_frame = NULL;
|
||||
list_node_t *node = NULL;
|
||||
int need_remove_list = 0;
|
||||
uint32_t list_samples = 0;
|
||||
ASSERT_A2DP_DECODER(!(samples%SBC_LIST_SAMPLES), "%s samples err:%d", __func__, samples);
|
||||
|
||||
a2dp_audio_sbc_convert_list_to_samples(&list_samples);
|
||||
if (list_samples >= samples){
|
||||
need_remove_list = samples/SBC_LIST_SAMPLES;
|
||||
for (int i=0; i<need_remove_list; i++){
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node){
|
||||
sbc_decoder_frame = (a2dp_audio_sbc_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, sbc_decoder_frame);
|
||||
}
|
||||
}
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int a2dp_audio_sbc_channel_select(A2DP_AUDIO_CHANNEL_SELECT_E chnl_sel)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
A2DP_AUDIO_DECODER_T a2dp_audio_sbc_decoder_config = {
|
||||
{44100, 2, 16},
|
||||
1,
|
||||
a2dp_audio_sbc_init,
|
||||
a2dp_audio_sbc_deinit,
|
||||
a2dp_audio_sbc_decode_frame,
|
||||
a2dp_audio_sbc_preparse_packet,
|
||||
a2dp_audio_sbc_store_packet,
|
||||
a2dp_audio_sbc_discards_packet,
|
||||
a2dp_audio_sbc_synchronize_packet,
|
||||
a2dp_audio_sbc_synchronize_dest_packet_mut,
|
||||
a2dp_audio_sbc_convert_list_to_samples,
|
||||
a2dp_audio_sbc_discards_samples,
|
||||
a2dp_audio_sbc_headframe_info_get,
|
||||
a2dp_audio_sbc_info_get,
|
||||
a2dp_audio_sbc_subframe_free,
|
||||
a2dp_audio_sbc_channel_select,
|
||||
} ;
|
||||
|
|
@ -0,0 +1,739 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include "cmsis.h"
|
||||
#include "plat_types.h"
|
||||
#include <string.h>
|
||||
#include "heap_api.h"
|
||||
#include "hal_location.h"
|
||||
#include "a2dp_decoder_internal.h"
|
||||
#include "app_audio.h"
|
||||
#if defined(A2DP_SCALABLE_ON)
|
||||
#include "heap_api.h"
|
||||
#include "ssc.h"
|
||||
|
||||
#define SCALABLE_MTU_LIMITER (32)
|
||||
#define SCALABLE_MEMPOOL_SIZE 1024
|
||||
|
||||
#define SCALABLE_OUTPUT_FRAME_SAMPLES (SCALABLE_FRAME_SIZE)
|
||||
|
||||
typedef void *HANDLE_DECODER;
|
||||
static A2DP_AUDIO_CONTEXT_T *a2dp_audio_context_p = NULL;
|
||||
static A2DP_AUDIO_OUTPUT_CONFIG_T output_config;
|
||||
|
||||
static unsigned char *scalable_decoder_place = NULL;
|
||||
static unsigned char *scalable_decoder_temp_buf = NULL;
|
||||
static short ss_pcm_buff[SCALABLE_FRAME_SIZE*4];
|
||||
static int scalable_uhq_flag __attribute__((unused)) = 0;
|
||||
|
||||
static HANDLE_DECODER scalableDec_handle = NULL;
|
||||
|
||||
static A2DP_AUDIO_DECODER_LASTFRAME_INFO_T lastframe_info;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
uint8_t *buffer;
|
||||
int buffer_len;
|
||||
} a2dp_audio_scalable_decoder_frame_t;
|
||||
|
||||
static void ss_to_24bit_buf(int32_t * out, int32_t * in, int size)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
out[i] = in[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void a2dp_audio_scalable_decoder_init(void)
|
||||
{
|
||||
if (scalableDec_handle == NULL) {
|
||||
scalableDec_handle = scalable_decoder_place;
|
||||
|
||||
|
||||
ssc_decoder_init(scalableDec_handle, output_config.num_channels, output_config.sample_rate);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int scalableDecoder_Close(HANDLE_DECODER handle)
|
||||
{
|
||||
if (handle) {
|
||||
a2dp_audio_heap_free(handle);
|
||||
a2dp_audio_heap_free(scalable_decoder_temp_buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void a2dp_audio_scalable_decoder_deinit(void)
|
||||
{
|
||||
if (scalableDec_handle) {
|
||||
scalableDecoder_Close(scalableDec_handle);
|
||||
scalableDec_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void a2dp_audio_scalable_decoder_reinit(void)
|
||||
{
|
||||
if (scalableDec_handle) {
|
||||
a2dp_audio_scalable_decoder_deinit();
|
||||
}
|
||||
a2dp_audio_scalable_decoder_init();
|
||||
}
|
||||
|
||||
static bool is_valid_frame(a2dp_audio_scalable_decoder_frame_t * decoder_frame_p)
|
||||
{
|
||||
int hw_tmp, len, bitrate_bps, frame_len, frame_size;
|
||||
|
||||
int sampling_rate = 44100;
|
||||
unsigned char *input_buf = decoder_frame_p->buffer;
|
||||
if (decoder_frame_p->buffer_len < SCALABLE_HEAD_SIZE) {
|
||||
TRACE_A2DP_DECODER_E("invalid scalable a2dp frame, length < SCALABLE_HEAD_SIZE !!!!!!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
scalable_uhq_flag = 0;
|
||||
|
||||
switch ((input_buf[3]&0xf7)) {
|
||||
case 0xF0:
|
||||
bitrate_bps = 88000;
|
||||
break;
|
||||
case 0xF1:
|
||||
bitrate_bps = 96000;
|
||||
break;
|
||||
case 0xF2:
|
||||
bitrate_bps = 128000;
|
||||
break;
|
||||
case 0xF3:
|
||||
bitrate_bps = 192000;
|
||||
break;
|
||||
case 0xF4:
|
||||
bitrate_bps = 229000;
|
||||
break;
|
||||
case 0xF5:
|
||||
scalable_uhq_flag = 1;
|
||||
bitrate_bps = 328000;
|
||||
sampling_rate = 96000;
|
||||
break;
|
||||
default:
|
||||
bitrate_bps = 192000;
|
||||
break;
|
||||
}
|
||||
|
||||
frame_size = SCALABLE_FRAME_SIZE;
|
||||
|
||||
len = bitrate_bps * frame_size / sampling_rate / 8;
|
||||
if (scalable_uhq_flag == 0) {
|
||||
hw_tmp = (len * 3) >> 7;
|
||||
len = hw_tmp + len;
|
||||
len = len + ((len & 1) ^ 1);
|
||||
} else {
|
||||
len = 369; //744/2-4+1
|
||||
}
|
||||
TRACE_A2DP_DECODER_D
|
||||
("scalable a2dp frame, length:%d bitrate:%d sampling_rate:%d",
|
||||
decoder_frame_p->buffer_len, bitrate_bps, sampling_rate);
|
||||
frame_len = SCALABLE_HEAD_SIZE + len - 1;
|
||||
|
||||
if (decoder_frame_p->buffer_len < frame_len) {
|
||||
TRACE_A2DP_DECODER_E
|
||||
("invalid scalable a2dp frame, length:%d < %d !!!!!!!", decoder_frame_p->buffer_len, frame_len);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
struct A2DP_CP_scalable_IN_FRM_INFO_T {
|
||||
uint16_t sequenceNumber;
|
||||
uint32_t timestamp;
|
||||
};
|
||||
|
||||
struct A2DP_CP_scalable_OUT_FRM_INFO_T {
|
||||
struct A2DP_CP_scalable_IN_FRM_INFO_T in_info;
|
||||
uint16_t frame_samples;
|
||||
uint16_t decoded_frames;
|
||||
uint16_t frame_idx;
|
||||
uint16_t pcm_len;
|
||||
};
|
||||
|
||||
static bool cp_codec_reset;
|
||||
extern uint32_t app_bt_stream_get_dma_buffer_samples(void);
|
||||
|
||||
TEXT_SSC_LOC static int a2dp_cp_scalable_mcu_decode(uint8_t * buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
list_node_t *node = NULL;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
int ret, dec_ret;
|
||||
struct A2DP_CP_scalable_IN_FRM_INFO_T in_info;
|
||||
struct A2DP_CP_scalable_OUT_FRM_INFO_T *p_out_info;
|
||||
uint8_t *out;
|
||||
uint32_t out_len;
|
||||
uint32_t out_frame_len;
|
||||
uint32_t cp_buffer_frames_max = 0;
|
||||
|
||||
cp_buffer_frames_max = app_bt_stream_get_dma_buffer_samples()/2;
|
||||
if (cp_buffer_frames_max %(lastframe_info.frame_samples) ){
|
||||
cp_buffer_frames_max = cp_buffer_frames_max /(lastframe_info.frame_samples) +1;
|
||||
}else{
|
||||
cp_buffer_frames_max = cp_buffer_frames_max /(lastframe_info.frame_samples);
|
||||
}
|
||||
|
||||
out_frame_len = sizeof(*p_out_info) + buffer_bytes;
|
||||
ret = a2dp_cp_decoder_init(out_frame_len, cp_buffer_frames_max * 2);
|
||||
|
||||
ASSERT(ret == 0, "%s: a2dp_cp_decoder_init() failed: ret=%d", __func__, ret);
|
||||
|
||||
while ((node = a2dp_audio_list_begin(list)) != NULL) {
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_list_node(node);
|
||||
|
||||
if (false == is_valid_frame(decoder_frame_p)) {
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
|
||||
in_info.sequenceNumber = decoder_frame_p->sequenceNumber;
|
||||
in_info.timestamp = decoder_frame_p->timestamp;
|
||||
|
||||
ret = a2dp_cp_put_in_frame(&in_info, sizeof(in_info), decoder_frame_p->buffer, decoder_frame_p->buffer_len);
|
||||
if (ret) {
|
||||
break;
|
||||
}
|
||||
|
||||
a2dp_audio_list_remove(list, decoder_frame_p);
|
||||
}
|
||||
|
||||
ret = a2dp_cp_get_full_out_frame((void **)&out, &out_len);
|
||||
if (ret) {
|
||||
return A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
if (out_len == 0) {
|
||||
memset(buffer, 0, buffer_bytes);
|
||||
a2dp_cp_consume_full_out_frame();
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
ASSERT(out_len == out_frame_len, "%s: Bad out len %u (should be %u)", __func__, out_len, out_frame_len);
|
||||
|
||||
p_out_info = (struct A2DP_CP_scalable_OUT_FRM_INFO_T *)out;
|
||||
if (p_out_info->pcm_len) {
|
||||
lastframe_info.sequenceNumber = p_out_info->in_info.sequenceNumber;
|
||||
lastframe_info.timestamp = p_out_info->in_info.timestamp;
|
||||
lastframe_info.curSubSequenceNumber = 0;
|
||||
lastframe_info.totalSubSequenceNumber = 0;
|
||||
lastframe_info.frame_samples = p_out_info->frame_samples;
|
||||
lastframe_info.decoded_frames += p_out_info->decoded_frames;
|
||||
lastframe_info.undecode_frames =
|
||||
a2dp_audio_list_length(list) + a2dp_cp_get_in_frame_cnt_by_index(p_out_info->frame_idx) - 1;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&lastframe_info);
|
||||
}
|
||||
|
||||
if (p_out_info->pcm_len == buffer_bytes) {
|
||||
memcpy(buffer, p_out_info + 1, p_out_info->pcm_len);
|
||||
dec_ret = A2DP_DECODER_NO_ERROR;
|
||||
} else {
|
||||
dec_ret = A2DP_DECODER_DECODE_ERROR;
|
||||
}
|
||||
|
||||
ret = a2dp_cp_consume_full_out_frame();
|
||||
ASSERT(ret == 0, "%s: a2dp_cp_consume_full_out_frame() failed: ret=%d", __func__, ret);
|
||||
|
||||
return dec_ret;
|
||||
}
|
||||
|
||||
TEXT_SSC_LOC int a2dp_cp_scalable_cp_decode(void)
|
||||
{
|
||||
int ret;
|
||||
enum CP_EMPTY_OUT_FRM_T out_frm_st;
|
||||
uint8_t *out;
|
||||
uint32_t out_len;
|
||||
uint8_t *dec_start;
|
||||
uint32_t dec_len;
|
||||
struct A2DP_CP_scalable_IN_FRM_INFO_T *p_in_info;
|
||||
struct A2DP_CP_scalable_OUT_FRM_INFO_T *p_out_info;
|
||||
uint8_t *in_buf;
|
||||
uint32_t in_len;
|
||||
uint32_t dec_sum;
|
||||
int error, output_samples = 0,output_byte = 0;
|
||||
|
||||
if (cp_codec_reset)
|
||||
{
|
||||
cp_codec_reset = false;
|
||||
a2dp_audio_scalable_decoder_init();
|
||||
}
|
||||
|
||||
out_frm_st = a2dp_cp_get_emtpy_out_frame((void **)&out, &out_len);
|
||||
|
||||
if (out_frm_st != CP_EMPTY_OUT_FRM_OK && out_frm_st != CP_EMPTY_OUT_FRM_WORKING)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ASSERT(out_len > sizeof(*p_out_info), "%s: Bad out_len %u (should > %u)", __func__, out_len, sizeof(*p_out_info));
|
||||
|
||||
p_out_info = (struct A2DP_CP_scalable_OUT_FRM_INFO_T *)out;
|
||||
if (out_frm_st == CP_EMPTY_OUT_FRM_OK)
|
||||
{
|
||||
p_out_info->pcm_len = 0;
|
||||
p_out_info->decoded_frames = 0;
|
||||
}
|
||||
|
||||
ASSERT(out_len > sizeof(*p_out_info) + p_out_info->pcm_len,
|
||||
"%s: Bad out_len %u (should > %u + %u)", __func__, out_len, sizeof(*p_out_info), p_out_info->pcm_len);
|
||||
|
||||
dec_start = (uint8_t *) (p_out_info + 1) + p_out_info->pcm_len;
|
||||
dec_len = out_len - (dec_start - (uint8_t *) out);
|
||||
if (!scalableDec_handle) {
|
||||
TRACE(0,"scalable_decode not ready");
|
||||
return 3;
|
||||
}
|
||||
|
||||
dec_sum = 0;
|
||||
error = 0;
|
||||
|
||||
while (dec_sum < dec_len && error == 0)
|
||||
{
|
||||
ret = a2dp_cp_get_in_frame((void * *) &in_buf, &in_len);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(in_len > sizeof(*p_in_info), "%s: Bad in_len %u (should > %u)", __func__, in_len, sizeof(*p_in_info));
|
||||
p_in_info = (struct A2DP_CP_scalable_IN_FRM_INFO_T *)in_buf;
|
||||
in_buf += sizeof(*p_in_info);
|
||||
in_len -= sizeof(*p_in_info);
|
||||
/* decode one SSC frame */
|
||||
output_samples = ssc_decode(scalableDec_handle,(const unsigned char*)in_buf, ss_pcm_buff, SCALABLE_FRAME_SIZE, 0, 2);
|
||||
if (0 == output_samples)
|
||||
{
|
||||
a2dp_audio_scalable_decoder_reinit();
|
||||
TRACE(0, "scalable_decode reinin codec \n");
|
||||
error = A2DP_DECODER_DECODE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ss_to_24bit_buf((int32_t *) (dec_start+dec_sum), (int32_t *) ss_pcm_buff, output_samples);
|
||||
output_byte = output_samples * 4;
|
||||
dec_sum += output_byte;
|
||||
exit:
|
||||
memcpy(&p_out_info->in_info, ss_pcm_buff, sizeof(*p_in_info));
|
||||
p_out_info->decoded_frames++;
|
||||
p_out_info->frame_samples = SCALABLE_OUTPUT_FRAME_SAMPLES;
|
||||
p_out_info->frame_idx = a2dp_cp_get_in_frame_index();
|
||||
|
||||
ret = a2dp_cp_consume_in_frame();
|
||||
ASSERT(ret == 0, "%s: a2dp_cp_consume_in_frame() failed: ret=%d", __func__, ret);
|
||||
}
|
||||
|
||||
p_out_info->pcm_len += dec_sum;
|
||||
|
||||
if (error || out_len <= sizeof(*p_out_info) + p_out_info->pcm_len) {
|
||||
ret = a2dp_cp_consume_emtpy_out_frame();
|
||||
ASSERT(ret == 0, "%s: a2dp_cp_consume_emtpy_out_frame() failed: ret=%d", __func__, ret);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int a2dp_audio_scalable_init(A2DP_AUDIO_OUTPUT_CONFIG_T * config, void *context)
|
||||
{
|
||||
TRACE_A2DP_DECODER_D("%s", __func__);
|
||||
|
||||
TRACE(0,"\n\nA2DP SSC-LC INIT\n");
|
||||
|
||||
a2dp_audio_context_p = (A2DP_AUDIO_CONTEXT_T *) context;
|
||||
|
||||
memcpy(&output_config, config, sizeof(A2DP_AUDIO_OUTPUT_CONFIG_T));
|
||||
|
||||
memset(&lastframe_info, 0, sizeof(A2DP_AUDIO_DECODER_LASTFRAME_INFO_T));
|
||||
lastframe_info.stream_info = output_config;
|
||||
lastframe_info.frame_samples = SCALABLE_FRAME_SIZE;
|
||||
lastframe_info.list_samples = SCALABLE_FRAME_SIZE;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&lastframe_info);
|
||||
|
||||
ASSERT(a2dp_audio_context_p->dest_packet_mut < SCALABLE_MTU_LIMITER,
|
||||
"%s MTU OVERFLOW:%u/%u", __func__, a2dp_audio_context_p->dest_packet_mut, SCALABLE_MTU_LIMITER);
|
||||
|
||||
int decoder_size;
|
||||
|
||||
decoder_size = ssc_decoder_get_size(output_config.num_channels); //todo: get size with codec capability
|
||||
|
||||
TRACE(0, "decoder size %d", decoder_size);
|
||||
|
||||
scalable_decoder_place = (unsigned char *)a2dp_audio_heap_malloc(decoder_size);
|
||||
ASSERT_A2DP_DECODER(scalable_decoder_place, "no memory resource for scalable_decoder_place");
|
||||
|
||||
scalable_decoder_temp_buf = (unsigned char *)a2dp_audio_heap_malloc(SCALABLE_FRAME_SIZE * 16);
|
||||
ASSERT_A2DP_DECODER(scalable_decoder_temp_buf, "no memory resource for scalable_decoder_temp_buf");
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
int ret;
|
||||
cp_codec_reset = true;
|
||||
ret = a2dp_cp_init(a2dp_cp_scalable_cp_decode, CP_PROC_DELAY_1_FRAME);
|
||||
ASSERT(ret == 0, "%s: a2dp_cp_init() failed: ret=%d", __func__, ret);
|
||||
#else
|
||||
a2dp_audio_scalable_decoder_init();
|
||||
#endif
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_deinit(void)
|
||||
{
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
a2dp_cp_deinit();
|
||||
#endif
|
||||
|
||||
a2dp_audio_scalable_decoder_deinit();
|
||||
|
||||
TRACE(0,"\n\nA2DP SCALABLE DEINIT\n");
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_scalable_mcu_decode_frame(uint8_t * buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
int ret = A2DP_DECODER_NO_ERROR;
|
||||
|
||||
bool cache_underflow = false;
|
||||
int output_byte = 0, output_samples = 0;
|
||||
uint8_t *output = buffer;
|
||||
// TRACE(1,"bbd %d",buffer_bytes );
|
||||
if (buffer_bytes < (SCALABLE_FRAME_SIZE * output_config.num_channels * output_config.bits_depth / 8)) {
|
||||
TRACE(1,"scalable_decode pcm_len = %d \n", buffer_bytes);
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
if (!scalableDec_handle) {
|
||||
TRACE(0,"scalable_decode not ready");
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
while (output < buffer + buffer_bytes) {
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (!node) {
|
||||
TRACE(0,"scalable_decode cache underflow");
|
||||
cache_underflow = true;
|
||||
goto exit;
|
||||
} else {
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_list_node(node);
|
||||
|
||||
if (false == is_valid_frame(decoder_frame_p)) {
|
||||
TRACE_A2DP_DECODER_E("%s %d invalid a2dp frame", __func__, __LINE__);
|
||||
ret = A2DP_DECODER_DECODE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* decode one SSC frame */
|
||||
output_samples =
|
||||
ssc_decode(scalableDec_handle,
|
||||
decoder_frame_p->buffer, ss_pcm_buff, SCALABLE_FRAME_SIZE,0,2);
|
||||
|
||||
TRACE_A2DP_DECODER_D
|
||||
("scalable_decode seq:%d len:%d output_samples:%d",
|
||||
decoder_frame_p->sequenceNumber, decoder_frame_p->buffer_len, output_samples);
|
||||
|
||||
if (0 == output_samples) {
|
||||
TRACE(0,"scalable_decode failed !!!!!!");
|
||||
//if failed reopen it again
|
||||
a2dp_audio_scalable_decoder_reinit();
|
||||
TRACE(0,"scalable_decode reinin codec \n");
|
||||
ret = A2DP_DECODER_DECODE_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
ss_to_24bit_buf((int32_t *) output, (int32_t *) ss_pcm_buff, output_samples * 2);
|
||||
output_byte = output_samples * 8;
|
||||
|
||||
|
||||
output += output_byte;
|
||||
ASSERT(SCALABLE_FRAME_SIZE == output_samples, "scalable_decode output mismatch samples:%d", output_samples);
|
||||
lastframe_info.sequenceNumber = decoder_frame_p->sequenceNumber;
|
||||
lastframe_info.timestamp = decoder_frame_p->timestamp;
|
||||
lastframe_info.curSubSequenceNumber = 0;
|
||||
lastframe_info.totalSubSequenceNumber = 0;
|
||||
lastframe_info.frame_samples = SCALABLE_FRAME_SIZE;
|
||||
lastframe_info.decoded_frames++;
|
||||
lastframe_info.undecode_frames = a2dp_audio_list_length(list) - 1;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&lastframe_info);
|
||||
a2dp_audio_list_remove(list, decoder_frame_p);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exit:
|
||||
if (cache_underflow) {
|
||||
lastframe_info.undecode_frames = 0;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&lastframe_info);
|
||||
ret = A2DP_DECODER_CACHE_UNDERFLOW_ERROR;
|
||||
}
|
||||
//TRACE(0,"abd");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_decode_frame(uint8_t * buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
return a2dp_cp_scalable_mcu_decode(buffer, buffer_bytes);
|
||||
#else
|
||||
return a2dp_audio_scalable_mcu_decode_frame(buffer, buffer_bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_preparse_packet(btif_media_header_t * header, uint8_t * buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
lastframe_info.sequenceNumber = header->sequenceNumber;
|
||||
lastframe_info.timestamp = header->timestamp;
|
||||
lastframe_info.curSubSequenceNumber = 0;
|
||||
lastframe_info.totalSubSequenceNumber = 0;
|
||||
lastframe_info.frame_samples = SCALABLE_FRAME_SIZE;
|
||||
lastframe_info.list_samples = SCALABLE_FRAME_SIZE;
|
||||
lastframe_info.decoded_frames = 0;
|
||||
lastframe_info.undecode_frames = 0;
|
||||
a2dp_audio_decoder_internal_lastframe_info_set(&lastframe_info);
|
||||
|
||||
TRACE(3,"%s seq:%d timestamp:%08x", __func__, header->sequenceNumber, header->timestamp);
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
static void *a2dp_audio_scalable_frame_malloc(uint32_t packet_len)
|
||||
{
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
uint8_t *buffer = NULL;
|
||||
|
||||
buffer = (uint8_t *) a2dp_audio_heap_malloc(SCALABLE_READBUF_SIZE);
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_heap_malloc(sizeof(a2dp_audio_scalable_decoder_frame_t));
|
||||
decoder_frame_p->buffer = buffer;
|
||||
decoder_frame_p->buffer_len = packet_len;
|
||||
return (void *)decoder_frame_p;
|
||||
}
|
||||
|
||||
static void a2dp_audio_scalable_free(void *packet)
|
||||
{
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *) packet;
|
||||
a2dp_audio_heap_free(decoder_frame_p->buffer);
|
||||
a2dp_audio_heap_free(decoder_frame_p);
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_store_packet(btif_media_header_t * header, uint8_t * buffer, uint32_t buffer_bytes)
|
||||
{
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
int nRet = A2DP_DECODER_NO_ERROR;
|
||||
if (a2dp_audio_list_length(list) < SCALABLE_MTU_LIMITER) {
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_scalable_frame_malloc(buffer_bytes);
|
||||
TRACE_A2DP_DECODER_D("%s seq:%d len:%d", __func__, header->sequenceNumber, buffer_bytes);
|
||||
decoder_frame_p->sequenceNumber = header->sequenceNumber;
|
||||
decoder_frame_p->timestamp = header->timestamp;
|
||||
memcpy(decoder_frame_p->buffer, buffer, buffer_bytes);
|
||||
decoder_frame_p->buffer_len = buffer_bytes;
|
||||
a2dp_audio_list_append(list, decoder_frame_p);
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
} else {
|
||||
TRACE(2,"%s list full current len:%d", __func__, a2dp_audio_list_length(list));
|
||||
nRet = A2DP_DECODER_MTU_LIMTER_ERROR;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_discards_packet(uint32_t packets)
|
||||
{
|
||||
int nRet = A2DP_DECODER_MEMORY_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
a2dp_cp_reset_frame();
|
||||
#endif
|
||||
|
||||
if (packets <= a2dp_audio_list_length(list)) {
|
||||
for (uint8_t i = 0; i < packets; i++) {
|
||||
if ((node = a2dp_audio_list_begin(list)) != NULL){
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, decoder_frame_p);
|
||||
}
|
||||
}
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
TRACE(3,"%s packets:%d nRet:%d", __func__, packets, nRet);
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_headframe_info_get(A2DP_AUDIO_HEADFRAME_INFO_T* headframe_info)
|
||||
{
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
|
||||
if (a2dp_audio_list_length(list)){
|
||||
if ((node = a2dp_audio_list_begin(list)) != NULL){
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
headframe_info->sequenceNumber = decoder_frame_p->sequenceNumber;
|
||||
headframe_info->timestamp = decoder_frame_p->timestamp;
|
||||
headframe_info->curSubSequenceNumber = 0;
|
||||
headframe_info->totalSubSequenceNumber = 0;
|
||||
}
|
||||
}else{
|
||||
memset(headframe_info, 0, sizeof(A2DP_AUDIO_HEADFRAME_INFO_T));
|
||||
}
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_info_get(void *info)
|
||||
{
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_synchronize_packet(A2DP_AUDIO_SYNCFRAME_INFO_T * sync_info, uint32_t mask)
|
||||
{
|
||||
int nRet = A2DP_DECODER_SYNC_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
list_node_t *node = NULL;
|
||||
int list_len;
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
|
||||
#ifdef A2DP_CP_ACCEL
|
||||
a2dp_cp_reset_frame();
|
||||
#endif
|
||||
|
||||
list_len = a2dp_audio_list_length(list);
|
||||
|
||||
for (uint16_t i = 0; i < list_len; i++) {
|
||||
if ((node = a2dp_audio_list_begin(list)) != NULL){
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_list_node(node);
|
||||
if (A2DP_AUDIO_SYNCFRAME_CHK(decoder_frame_p->sequenceNumber == sync_info->sequenceNumber, A2DP_AUDIO_SYNCFRAME_MASK_SEQ, mask)&&
|
||||
A2DP_AUDIO_SYNCFRAME_CHK(decoder_frame_p->timestamp == sync_info->timestamp, A2DP_AUDIO_SYNCFRAME_MASK_TIMESTAMP, mask)) {
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
break;
|
||||
}
|
||||
a2dp_audio_list_remove(list, decoder_frame_p);
|
||||
}
|
||||
}
|
||||
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node) {
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_list_node(node);
|
||||
TRACE(4,"%s nRet:%d SEQ:%d timestamp:%d", __func__, nRet,
|
||||
decoder_frame_p->sequenceNumber, decoder_frame_p->timestamp);
|
||||
} else {
|
||||
TRACE(2,"%s nRet:%d", __func__, nRet);
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static int a2dp_audio_scalable_synchronize_dest_packet_mut(uint16_t packet_mut)
|
||||
{
|
||||
list_node_t *node = NULL;
|
||||
uint32_t list_len = 0;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
a2dp_audio_scalable_decoder_frame_t *decoder_frame_p = NULL;
|
||||
|
||||
list_len = a2dp_audio_list_length(list);
|
||||
if (list_len > packet_mut) {
|
||||
do {
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node)
|
||||
{
|
||||
decoder_frame_p = (a2dp_audio_scalable_decoder_frame_t *)
|
||||
a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, decoder_frame_p);
|
||||
}
|
||||
} while (a2dp_audio_list_length(list) > packet_mut);
|
||||
}
|
||||
|
||||
TRACE(2,"%s list:%d", __func__, a2dp_audio_list_length(list));
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_scalable_convert_list_to_samples(uint32_t *samples)
|
||||
{
|
||||
uint32_t list_len = 0;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
|
||||
list_len = a2dp_audio_list_length(list);
|
||||
*samples = SCALABLE_FRAME_SIZE*list_len;
|
||||
|
||||
TRACE(3, "%s list:%d samples:%d", __func__, list_len, *samples);
|
||||
|
||||
return A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
int a2dp_audio_scalable_discards_samples(uint32_t samples)
|
||||
{
|
||||
int nRet = A2DP_DECODER_SYNC_ERROR;
|
||||
list_t *list = a2dp_audio_context_p->audio_datapath.input_raw_packet_list;
|
||||
a2dp_audio_scalable_decoder_frame_t *scalable_decoder_frame = NULL;
|
||||
list_node_t *node = NULL;
|
||||
int need_remove_list = 0;
|
||||
uint32_t list_samples = 0;
|
||||
ASSERT(!(samples%SCALABLE_FRAME_SIZE), "%s samples err:%d", __func__, samples);
|
||||
|
||||
a2dp_audio_scalable_convert_list_to_samples(&list_samples);
|
||||
if (list_samples >= samples){
|
||||
need_remove_list = samples/SCALABLE_FRAME_SIZE;
|
||||
for (int i=0; i<need_remove_list; i++){
|
||||
node = a2dp_audio_list_begin(list);
|
||||
if (node)
|
||||
{
|
||||
scalable_decoder_frame = (a2dp_audio_scalable_decoder_frame_t *)a2dp_audio_list_node(node);
|
||||
a2dp_audio_list_remove(list, scalable_decoder_frame);
|
||||
}
|
||||
}
|
||||
nRet = A2DP_DECODER_NO_ERROR;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
A2DP_AUDIO_DECODER_T a2dp_audio_scalable_decoder_config = {
|
||||
{44100, 2, 16},
|
||||
1,
|
||||
a2dp_audio_scalable_init,
|
||||
a2dp_audio_scalable_deinit,
|
||||
a2dp_audio_scalable_decode_frame,
|
||||
a2dp_audio_scalable_preparse_packet,
|
||||
a2dp_audio_scalable_store_packet,
|
||||
a2dp_audio_scalable_discards_packet,
|
||||
a2dp_audio_scalable_synchronize_packet,
|
||||
a2dp_audio_scalable_synchronize_dest_packet_mut,
|
||||
a2dp_audio_scalable_convert_list_to_samples,
|
||||
a2dp_audio_scalable_discards_samples,
|
||||
a2dp_audio_scalable_headframe_info_get,
|
||||
a2dp_audio_scalable_info_get,
|
||||
a2dp_audio_scalable_free,
|
||||
};
|
||||
#else
|
||||
A2DP_AUDIO_DECODER_T a2dp_audio_scalable_decoder_config = { 0, };
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __A2DP_DECODER_TRACE_H__
|
||||
#define __A2DP_DECODER_TRACE_H__
|
||||
|
||||
#include "hal_trace.h"
|
||||
|
||||
#ifdef ENABLE_COMPRESS_LOG
|
||||
#define TRACE_A2DP_DECODER_D(str, ...) hal_trace_dummy(str, ##__VA_ARGS__)
|
||||
//LOG_DEBUG(LOG_ATTR_ARG_NUM(COUNT_ARG_NUM(unused, ##__VA_ARGS__)), "[AUD][DECODER][DBG]"str, ##__VA_ARGS__)
|
||||
#define TRACE_A2DP_DECODER_I(str, ...) LOG_INFO(LOG_ATTR_ARG_NUM(COUNT_ARG_NUM(unused, ##__VA_ARGS__)), "[AUD][DECODER]"str, ##__VA_ARGS__)
|
||||
#define TRACE_A2DP_DECODER_W(str, ...) LOG_WARN(LOG_ATTR_ARG_NUM(COUNT_ARG_NUM(unused, ##__VA_ARGS__)), "[AUD][DECODER][WARN]"str, ##__VA_ARGS__)
|
||||
#define TRACE_A2DP_DECODER_E(str, ...) LOG_ERROR(LOG_ATTR_ARG_NUM(COUNT_ARG_NUM(unused, ##__VA_ARGS__)), "[AUD][DECODER][ERR]"str, ##__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE_A2DP_DECODER_D(str, ...) hal_trace_dummy(str, ##__VA_ARGS__)
|
||||
//LOG_DEBUG(LOG_MOD(AUDFLG), "[AUD][DECODER][DBG]"str, ##__VA_ARGS__)
|
||||
#define TRACE_A2DP_DECODER_I(str, ...) LOG_INFO(LOG_MOD(AUDFLG), "[AUD][DECODER]"str, ##__VA_ARGS__)
|
||||
#define TRACE_A2DP_DECODER_W(str, ...) LOG_WARN(LOG_MOD(AUDFLG), "[AUD][DECODER][WARN]"str, ##__VA_ARGS__)
|
||||
#define TRACE_A2DP_DECODER_E(str, ...) LOG_ERROR(LOG_MOD(AUDFLG), "[AUD][DECODER][ERR]"str, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define ASSERT_A2DP_DECODER(cond, str, ...) ASSERT(cond, str, ##__VA_ARGS__)
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,791 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "app_bt_trace.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "cqueue.h"
|
||||
#include "list.h"
|
||||
#include "hal_aud.h"
|
||||
#include "resources.h"
|
||||
#include "app_thread.h"
|
||||
#include "app_audio.h"
|
||||
#include "app_media_player.h"
|
||||
#include "app_ring_merge.h"
|
||||
#include "nvrecord.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "a2dp_api.h"
|
||||
|
||||
#include "btapp.h"
|
||||
#include "app_bt_media_manager.h"
|
||||
|
||||
extern uint8_t __StackLimit[];
|
||||
extern uint8_t __HeapLimit[];
|
||||
|
||||
static const size_t heap_size = __StackLimit - __HeapLimit - 512;
|
||||
|
||||
static bool app_audio_init = false;
|
||||
|
||||
static uint32_t capture_audio_buff_size_used;
|
||||
// from the bottom of the system available memory pool, size is APP_CAPTURE_AUDIO_BUFFER_SIZE
|
||||
// can be overlayed with the sco used audio buffer
|
||||
static uint8_t* capture_audio_buffer = __HeapLimit + heap_size - APP_CAPTURE_AUDIO_BUFFER_SIZE;
|
||||
|
||||
int app_capture_audio_mempool_init(void)
|
||||
{
|
||||
TRACE_AUD_HDL_I("[CAPMEM][INIT] size %d.", APP_CAPTURE_AUDIO_BUFFER_SIZE);
|
||||
capture_audio_buff_size_used = 0;
|
||||
memset((uint8_t *)capture_audio_buffer, 0, APP_CAPTURE_AUDIO_BUFFER_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t app_capture_audio_mempool_free_buff_size()
|
||||
{
|
||||
return APP_CAPTURE_AUDIO_BUFFER_SIZE - capture_audio_buff_size_used;
|
||||
}
|
||||
|
||||
int app_capture_audio_mempool_get_buff(uint8_t **buff, uint32_t size)
|
||||
{
|
||||
uint32_t buff_size_free;
|
||||
uint8_t* capture_buf_addr = (uint8_t *)capture_audio_buffer;
|
||||
buff_size_free = app_capture_audio_mempool_free_buff_size();
|
||||
|
||||
if (size % 4){
|
||||
size = size + (4 - size % 4);
|
||||
}
|
||||
|
||||
TRACE_AUD_HDL_I("[CAPMEM][GET] current free %d to allocate %d", buff_size_free, size);
|
||||
|
||||
ASSERT(size <= buff_size_free, "[%s] size = %d > free size = %d", __func__, size, buff_size_free);
|
||||
|
||||
*buff = capture_buf_addr + capture_audio_buff_size_used;
|
||||
|
||||
capture_audio_buff_size_used += size;
|
||||
TRACE_AUD_HDL_I("[CAPMEM][GET] %d, now used %d left %d",
|
||||
size, capture_audio_buff_size_used, app_capture_audio_mempool_free_buff_size());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
osPoolDef (app_audio_status_mempool, 20, APP_AUDIO_STATUS);
|
||||
osPoolId app_audio_status_mempool = NULL;
|
||||
|
||||
// control queue access
|
||||
osMutexId g_app_audio_queue_mutex_id = NULL;
|
||||
osMutexDef(g_app_audio_queue_mutex);
|
||||
|
||||
// control pcmbuff access
|
||||
static CQueue app_audio_pcm_queue;
|
||||
static osMutexId app_audio_pcmbuff_mutex_id = NULL;
|
||||
osMutexDef(app_audio_pcmbuff_mutex);
|
||||
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
|
||||
typedef struct {
|
||||
list_t *audio_list;
|
||||
}APP_AUDIO_CONFIG;
|
||||
|
||||
APP_AUDIO_CONFIG app_audio_conifg = {
|
||||
.audio_list = NULL
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void LOCK_APP_AUDIO_QUEUE()
|
||||
{
|
||||
osMutexWait(g_app_audio_queue_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
void UNLOCK_APP_AUDIO_QUEUE()
|
||||
{
|
||||
osMutexRelease(g_app_audio_queue_mutex_id);
|
||||
}
|
||||
|
||||
uint32_t app_audio_lr_balance(uint8_t *buf, uint32_t len, int8_t balance)
|
||||
{
|
||||
short *balance_buf=(short *)buf;
|
||||
uint32_t balance_len = len/2;
|
||||
float factor;
|
||||
|
||||
ASSERT((balance >= -100) && (balance <= 100), "balance = %d is invalid!", balance);
|
||||
|
||||
if(balance > 0)
|
||||
{
|
||||
//reduce L channel
|
||||
factor = 1 - 0.01 * balance;
|
||||
for(uint32_t i=0; i<balance_len;i+=2)
|
||||
{
|
||||
balance_buf[i] = (short) (factor * balance_buf[i]);
|
||||
}
|
||||
}
|
||||
else if(balance < 0)
|
||||
{
|
||||
//reduce R channel
|
||||
factor = 1 + 0.01 * balance;
|
||||
for(uint32_t i=0; i<balance_len;i+=2)
|
||||
{
|
||||
balance_buf[i+1] = (short) (factor * balance_buf[i+1]);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_audio_mempool_init_with_specific_size(uint32_t size)
|
||||
{
|
||||
syspool_init_specific_size(size);
|
||||
}
|
||||
|
||||
int app_audio_pcmbuff_init(uint8_t *buff, uint16_t len)
|
||||
{
|
||||
if (app_audio_pcmbuff_mutex_id == NULL)
|
||||
app_audio_pcmbuff_mutex_id = osMutexCreate((osMutex(app_audio_pcmbuff_mutex)));
|
||||
|
||||
if ((buff == NULL)||(app_audio_pcmbuff_mutex_id == NULL))
|
||||
return -1;
|
||||
|
||||
osMutexWait(app_audio_pcmbuff_mutex_id, osWaitForever);
|
||||
InitCQueue(&app_audio_pcm_queue, len, buff);
|
||||
memset(buff, 0x00, len);
|
||||
osMutexRelease(app_audio_pcmbuff_mutex_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_audio_pcmbuff_length(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
osMutexWait(app_audio_pcmbuff_mutex_id, osWaitForever);
|
||||
len = LengthOfCQueue(&app_audio_pcm_queue);
|
||||
osMutexRelease(app_audio_pcmbuff_mutex_id);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int app_audio_pcmbuff_put(uint8_t *buff, uint16_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
osMutexWait(app_audio_pcmbuff_mutex_id, osWaitForever);
|
||||
status = EnCQueue(&app_audio_pcm_queue, buff, len);
|
||||
osMutexRelease(app_audio_pcmbuff_mutex_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int app_audio_pcmbuff_get(uint8_t *buff, uint16_t len)
|
||||
{
|
||||
unsigned char *e1 = NULL, *e2 = NULL;
|
||||
unsigned int len1 = 0, len2 = 0;
|
||||
int status;
|
||||
|
||||
osMutexWait(app_audio_pcmbuff_mutex_id, osWaitForever);
|
||||
status = PeekCQueue(&app_audio_pcm_queue, len, &e1, &len1, &e2, &len2);
|
||||
if (len==(len1+len2)){
|
||||
memcpy(buff,e1,len1);
|
||||
memcpy(buff+len1,e2,len2);
|
||||
DeCQueue(&app_audio_pcm_queue, 0, len1);
|
||||
DeCQueue(&app_audio_pcm_queue, 0, len2);
|
||||
}else{
|
||||
memset(buff, 0x00, len);
|
||||
status = -1;
|
||||
}
|
||||
osMutexRelease(app_audio_pcmbuff_mutex_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int app_audio_pcmbuff_discard(uint16_t len)
|
||||
{
|
||||
int status;
|
||||
|
||||
osMutexWait(app_audio_pcmbuff_mutex_id, osWaitForever);
|
||||
status = DeCQueue(&app_audio_pcm_queue, 0, len);
|
||||
osMutexRelease(app_audio_pcmbuff_mutex_id);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void __attribute__((section(".fast_text_sram"))) app_audio_memcpy_16bit(int16_t *des, int16_t *src, int len)
|
||||
{
|
||||
// Check input
|
||||
for(int i=0; i<len; i++)
|
||||
{
|
||||
des[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((section(".fast_text_sram"))) app_audio_memset_16bit(int16_t *des, int16_t val, int len)
|
||||
{
|
||||
// Check input
|
||||
for(int i=0; i<len; i++)
|
||||
{
|
||||
des[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
int app_audio_sendrequest_param(uint16_t id, uint8_t status, uint32_t ptr, uint32_t param)
|
||||
{
|
||||
uint32_t audevt;
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
|
||||
if(app_audio_init == false)
|
||||
return -1;
|
||||
|
||||
msg.mod_id = APP_MODUAL_AUDIO;
|
||||
APP_AUDIO_SET_MESSAGE(audevt, id, status);
|
||||
msg.msg_body.message_id = audevt;
|
||||
msg.msg_body.message_ptr = ptr;
|
||||
msg.msg_body.message_Param0 = param;
|
||||
app_mailbox_put(&msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_audio_sendrequest(uint16_t id, uint8_t status, uint32_t ptr)
|
||||
{
|
||||
return app_audio_sendrequest_param(id, status, ptr, 0);
|
||||
}
|
||||
|
||||
extern bool app_audio_list_playback_exist(void);
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
static uint8_t app_audio_get_list_playback_num(void)
|
||||
{
|
||||
APP_AUDIO_STATUS *audio_handle = NULL;
|
||||
list_node_t *node = NULL;
|
||||
uint8_t num=0;
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node))
|
||||
{
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if(audio_handle == NULL)
|
||||
{
|
||||
return num;
|
||||
}
|
||||
if (audio_handle->id == APP_PLAY_BACK_AUDIO)
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static bool need_flush_flash_switch_audio = false;
|
||||
void app_audio_switch_flash_flush_req(void)
|
||||
{
|
||||
uint32_t lock;
|
||||
|
||||
lock = int_lock();
|
||||
need_flush_flash_switch_audio = true;
|
||||
int_unlock(lock);
|
||||
}
|
||||
|
||||
static void app_audio_switch_flash_proc(void)
|
||||
{
|
||||
// no need to do this across the audio switch,
|
||||
// will use suspend flash erase to assure that no audio
|
||||
// irq is missing for handling caused by long time global irq disabling
|
||||
// during flash erase.
|
||||
// Just flash the nvrecord flash periodically
|
||||
return;
|
||||
|
||||
uint32_t lock;
|
||||
bool need_flush_flash = false;
|
||||
|
||||
lock = int_lock();
|
||||
if (need_flush_flash_switch_audio){
|
||||
need_flush_flash_switch_audio = false;
|
||||
need_flush_flash = true;
|
||||
}
|
||||
int_unlock(lock);
|
||||
|
||||
if (need_flush_flash){
|
||||
#ifndef FPGA
|
||||
nv_record_flash_flush();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VOICE_DATAPATH
|
||||
static bool app_audio_handle_pre_processing(APP_MESSAGE_BODY *msg_body)
|
||||
{
|
||||
uint16_t stream_type;
|
||||
APP_AUDIO_GET_AUD_ID(msg_body->message_ptr, stream_type);
|
||||
|
||||
bool isToResetCaptureStream = false;
|
||||
if ((BT_STREAM_SBC == stream_type) || (BT_STREAM_MEDIA == stream_type))
|
||||
{
|
||||
if (app_audio_manager_capture_is_active())
|
||||
{
|
||||
isToResetCaptureStream = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isToResetCaptureStream)
|
||||
{
|
||||
app_audio_manager_sendrequest(APP_BT_STREAM_MANAGER_STOP,
|
||||
BT_STREAM_CAPTURE, 0, 0);
|
||||
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
msg.msg_body = *msg_body;
|
||||
msg.mod_id = APP_MODUAL_AUDIO_MANAGE;
|
||||
app_mailbox_put(&msg);
|
||||
app_audio_manager_sendrequest(APP_BT_STREAM_MANAGER_START,
|
||||
BT_STREAM_CAPTURE, 0, 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int app_audio_handle_process(APP_MESSAGE_BODY *msg_body)
|
||||
{
|
||||
int nRet = -1;
|
||||
|
||||
APP_AUDIO_STATUS aud_status;
|
||||
|
||||
if (app_audio_init == false)
|
||||
return -1;
|
||||
|
||||
#ifdef VOICE_DATAPATH
|
||||
bool isContinue = app_audio_handle_pre_processing(msg_body);
|
||||
if (!isContinue)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
APP_AUDIO_GET_ID(msg_body->message_id, aud_status.id);
|
||||
APP_AUDIO_GET_STATUS(msg_body->message_id, aud_status.status);
|
||||
APP_AUDIO_GET_AUD_ID(msg_body->message_ptr, aud_status.aud_id);
|
||||
APP_AUDIO_GET_FREQ(msg_body->message_Param0, aud_status.freq);
|
||||
|
||||
switch (aud_status.status)
|
||||
{
|
||||
case APP_BT_SETTING_OPEN:
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
TRACE_AUD_HDL_I(
|
||||
"[OPEN] before status_id: 0x%x%s, aud_id: %d, len = %d",
|
||||
aud_status.id,
|
||||
player2str(aud_status.id),
|
||||
aud_status.aud_id,
|
||||
list_length(app_audio_conifg.audio_list));
|
||||
|
||||
if (app_audio_list_append(&aud_status))
|
||||
{
|
||||
app_bt_stream_open(&aud_status);
|
||||
TRACE_AUD_HDL_I(
|
||||
"[OPEN] after status_id: 0x%x%s, len = %d",
|
||||
aud_status.id,
|
||||
player2str(aud_status.id),
|
||||
list_length(app_audio_conifg.audio_list));
|
||||
}
|
||||
#else
|
||||
app_bt_stream_open(&aud_status);
|
||||
#endif
|
||||
|
||||
break;
|
||||
case APP_BT_SETTING_CLOSE:
|
||||
app_audio_switch_flash_proc();
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
APP_AUDIO_STATUS next_status;
|
||||
TRACE_AUD_HDL_I(
|
||||
"[CLOSE] current id: 0x%x%s",
|
||||
aud_status.id,
|
||||
player2str(aud_status.id));
|
||||
app_bt_stream_close(aud_status.id);
|
||||
app_audio_switch_flash_proc();
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
if (aud_status.id == APP_PLAY_BACK_AUDIO)
|
||||
{
|
||||
TRACE_AUD_HDL_I("[CLOSE] list: %d", app_audio_get_list_playback_num());
|
||||
if (app_audio_get_list_playback_num() == 1)
|
||||
{
|
||||
TRACE_AUD_HDL_I("=======>APP_BT_SETTING_CLOSE MEDIA");
|
||||
bt_media_stop(BT_STREAM_MEDIA, BT_DEVICE_ID_1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (app_audio_list_rmv_callback(&aud_status, &next_status, APP_BT_SETTING_Q_POS_HEAD, false))
|
||||
{
|
||||
TRACE_AUD_HDL_I(
|
||||
"[CLOSE] %p, next id: 0x%x%s, status %d",
|
||||
&next_status,
|
||||
next_status.id,
|
||||
player2str(next_status.id),
|
||||
next_status.status);
|
||||
app_bt_stream_open(&next_status);
|
||||
}
|
||||
#else
|
||||
app_bt_stream_close(aud_status.id);
|
||||
app_audio_switch_flash_proc();
|
||||
#endif
|
||||
break;
|
||||
case APP_BT_SETTING_SETUP:
|
||||
app_bt_stream_setup(aud_status.id, msg_body->message_ptr);
|
||||
break;
|
||||
case APP_BT_SETTING_RESTART:
|
||||
app_bt_stream_restart(&aud_status);
|
||||
break;
|
||||
case APP_BT_SETTING_CLOSEALL:
|
||||
app_bt_stream_closeall();
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
app_audio_list_clear();
|
||||
#endif
|
||||
app_audio_switch_flash_proc();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
static void app_audio_handle_free(void* data)
|
||||
{
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
APP_AUDIO_STATUS * status = (APP_AUDIO_STATUS * )data;
|
||||
|
||||
if(status->id == APP_PLAY_BACK_AUDIO)
|
||||
{
|
||||
TRACE_AUD_HDL_I("[HANDLE_FREE] , aud_id: 0x%x, type = 0x%x", status->aud_id, status->aud_type);
|
||||
}
|
||||
#endif
|
||||
osPoolFree (app_audio_status_mempool, data);
|
||||
}
|
||||
|
||||
void app_audio_list_create()
|
||||
{
|
||||
if (app_audio_conifg.audio_list == NULL)
|
||||
{
|
||||
app_audio_conifg.audio_list = list_new(app_audio_handle_free, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool app_audio_list_stream_exist()
|
||||
{
|
||||
APP_AUDIO_STATUS *audio_handle = NULL;
|
||||
list_node_t *node = NULL;
|
||||
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node)) {
|
||||
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if(audio_handle == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (audio_handle->id == APP_BT_STREAM_HFP_PCM ||
|
||||
audio_handle->id == APP_BT_STREAM_HFP_CVSD ||
|
||||
audio_handle->id == APP_BT_STREAM_HFP_VENDOR ||
|
||||
audio_handle->id == APP_BT_STREAM_A2DP_SBC ||
|
||||
audio_handle->id == APP_BT_STREAM_A2DP_AAC ||
|
||||
#ifdef VOICE_DATAPATH
|
||||
audio_handle->id == APP_BT_STREAM_VOICEPATH ||
|
||||
#endif
|
||||
#ifdef __AI_VOICE__
|
||||
audio_handle->id == APP_BT_STREAM_AI_VOICE ||
|
||||
#endif
|
||||
#ifdef __THIRDPARTY
|
||||
audio_handle->id == APP_BT_STREAM_THIRDPARTY_VOICE ||
|
||||
#endif
|
||||
audio_handle->id == APP_BT_STREAM_A2DP_VENDOR
|
||||
) {
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][EXIST] id 0x%x", audio_handle->id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool app_audio_list_filter_exist(APP_AUDIO_STATUS* aud_status)
|
||||
{
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
APP_AUDIO_STATUS *audio_handle = NULL;
|
||||
list_node_t *node = NULL;
|
||||
uint8_t cnt = 0;
|
||||
|
||||
if (aud_status->id == APP_PLAY_BACK_AUDIO){
|
||||
if(aud_status->aud_id == AUD_ID_BT_CALL_INCOMING_CALL) {
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node)) {
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if(audio_handle == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (audio_handle->id == APP_PLAY_BACK_AUDIO && audio_handle->aud_id == AUD_ID_BT_CALL_INCOMING_CALL) {
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][FILTER] id 0x%x", audio_handle->id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node)) {
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if (cnt++ > 1) {
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][FILTER] cnt %d", cnt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool app_audio_list_playback_exist(void)
|
||||
{
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
APP_AUDIO_STATUS *audio_handle = NULL;
|
||||
list_node_t *node = NULL;
|
||||
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node)) {
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if(audio_handle == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (audio_handle->id == APP_PLAY_BACK_AUDIO) {
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][PLAYBACK_EXIST]");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void app_audio_list_playback_clear(void)
|
||||
{
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
APP_AUDIO_STATUS *audio_handle = NULL;
|
||||
list_node_t *node = NULL;
|
||||
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node)) {
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if(audio_handle == NULL)
|
||||
{
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][CLR] find null\n ");
|
||||
return;
|
||||
}
|
||||
if (audio_handle->id == APP_PLAY_BACK_AUDIO){
|
||||
list_remove(app_audio_conifg.audio_list, list_node(node));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool app_audio_list_append(APP_AUDIO_STATUS* aud_status)
|
||||
{
|
||||
APP_AUDIO_STATUS *data_to_append = NULL;
|
||||
bool add_data_to_head_of_list = false;
|
||||
bool ret = true;
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][APPEND] id 0x%x%s", aud_status->id, player2str(aud_status->id));
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
if (aud_status->id == APP_PLAY_BACK_AUDIO)
|
||||
{
|
||||
//ignore redundant ring ind from hfp...
|
||||
if (app_audio_list_filter_exist(aud_status))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (app_audio_list_playback_exist())
|
||||
{
|
||||
if (list_length(app_audio_conifg.audio_list) >= MAX_AUDIO_BUF_LIST)
|
||||
{
|
||||
if (app_audio_list_stream_exist())
|
||||
{
|
||||
data_to_append = (APP_AUDIO_STATUS *)osPoolCAlloc (app_audio_status_mempool);
|
||||
if(data_to_append == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memcpy(data_to_append, (const void *)list_front(app_audio_conifg.audio_list), sizeof(APP_AUDIO_STATUS));
|
||||
add_data_to_head_of_list = true;
|
||||
}
|
||||
|
||||
app_audio_list_clear();
|
||||
TRACE_AUD_HDL_E("[STREAM_LIST][APPEND] FIXME!!!!\n ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
add_data_to_head_of_list = true;
|
||||
}
|
||||
|
||||
if (data_to_append == NULL)
|
||||
{
|
||||
data_to_append = (APP_AUDIO_STATUS *)osPoolCAlloc (app_audio_status_mempool);
|
||||
if(data_to_append == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
memcpy(data_to_append, aud_status, sizeof(APP_AUDIO_STATUS));
|
||||
}
|
||||
|
||||
if (add_data_to_head_of_list)
|
||||
{
|
||||
list_prepend(app_audio_conifg.audio_list, (void*)data_to_append);
|
||||
}
|
||||
else
|
||||
{
|
||||
list_append(app_audio_conifg.audio_list, (void*)data_to_append);
|
||||
}
|
||||
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][APPEND] id 0x%x%s status %d len %d ret %d", data_to_append->id, player2str(data_to_append->id), \
|
||||
data_to_append->status, list_length(app_audio_conifg.audio_list), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool app_audio_list_rmv_callback(APP_AUDIO_STATUS *status_close, APP_AUDIO_STATUS *status_next, enum APP_BT_AUDIO_Q_POS pos, bool pop_next)
|
||||
{
|
||||
void *data_to_remove = NULL;
|
||||
bool ret = false;
|
||||
|
||||
//for status: first bt_a2dp->APP_BT_SETTING_CLOSE,then ring-> APP_BT_SETTING_CLOSE
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][RMV] audio list len %d close_id 0x%x%s", list_length(app_audio_conifg.audio_list), \
|
||||
status_close->id, player2str(status_close->id));
|
||||
if(list_length(app_audio_conifg.audio_list) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
APP_AUDIO_STATUS *audio_handle = NULL;
|
||||
list_node_t *node = NULL;
|
||||
if (status_close->id == APP_PLAY_BACK_AUDIO)
|
||||
{
|
||||
for (node = list_begin(app_audio_conifg.audio_list); node != list_end(app_audio_conifg.audio_list); node = list_next(node))
|
||||
{
|
||||
audio_handle = (APP_AUDIO_STATUS *)list_node(node);
|
||||
if(audio_handle == NULL)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (audio_handle->id == APP_PLAY_BACK_AUDIO)
|
||||
{
|
||||
list_node_t *nod_next = list_next(node);
|
||||
data_to_remove = list_node(node);
|
||||
|
||||
if (pop_next)
|
||||
{
|
||||
memcpy(status_next, list_node(node), sizeof(APP_AUDIO_STATUS));
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
if (nod_next != NULL)
|
||||
{
|
||||
memcpy(status_next, list_node(nod_next), sizeof(APP_AUDIO_STATUS));
|
||||
ASSERT(status_next->id == APP_PLAY_BACK_AUDIO, "[%s] 111ERROR: status_next->id != APP_PLAY_BACK_AUDIO", __func__);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
else if (app_audio_list_stream_exist())
|
||||
{
|
||||
void *indata = list_front(app_audio_conifg.audio_list);
|
||||
if(indata == NULL)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
memcpy(status_next, indata, sizeof(APP_AUDIO_STATUS));
|
||||
ASSERT(status_next->id != APP_PLAY_BACK_AUDIO, "[%s] 222ERROR: status_next->id != APP_PLAY_BACK_AUDIO", __func__);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else //maybe...a2dp send >> APP_BT_SETTING_CLOSE, when ring
|
||||
#endif
|
||||
{
|
||||
if (app_audio_list_stream_exist())
|
||||
{
|
||||
if(pos == APP_BT_SETTING_Q_POS_HEAD)
|
||||
{
|
||||
data_to_remove = list_front(app_audio_conifg.audio_list);
|
||||
}
|
||||
else if (pos == APP_BT_SETTING_Q_POS_TAIL)
|
||||
{
|
||||
data_to_remove = list_back(app_audio_conifg.audio_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data_to_remove)
|
||||
{
|
||||
list_remove(app_audio_conifg.audio_list, data_to_remove);
|
||||
}
|
||||
TRACE_AUD_HDL_I("[STREAM_LIST][RMV] end len:%d ret %d data %p", list_length(app_audio_conifg.audio_list), ret, data_to_remove);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void app_audio_list_clear()
|
||||
{
|
||||
list_clear(app_audio_conifg.audio_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_audio_open(void)
|
||||
{
|
||||
if(app_audio_init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (g_app_audio_queue_mutex_id == NULL)
|
||||
{
|
||||
g_app_audio_queue_mutex_id = osMutexCreate((osMutex(g_app_audio_queue_mutex)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0, "[%s] ERROR: g_app_audio_queue_mutex_id != NULL", __func__);
|
||||
}
|
||||
|
||||
if (app_audio_status_mempool == NULL)
|
||||
app_audio_status_mempool = osPoolCreate(osPool(app_audio_status_mempool));
|
||||
ASSERT(app_audio_status_mempool, "[%s] ERROR: app_audio_status_mempool != NULL", __func__);
|
||||
|
||||
#ifdef __AUDIO_QUEUE_SUPPORT__
|
||||
app_audio_list_create();
|
||||
#endif
|
||||
app_ring_merge_init();
|
||||
|
||||
app_set_threadhandle(APP_MODUAL_AUDIO, app_audio_handle_process);
|
||||
|
||||
app_bt_stream_init();
|
||||
|
||||
app_audio_init = true;
|
||||
}
|
||||
|
||||
void app_audio_close(void)
|
||||
{
|
||||
app_set_threadhandle(APP_MODUAL_AUDIO, NULL);
|
||||
app_audio_init = false;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_AUDIO_H__
|
||||
#define __APP_AUDIO_H__
|
||||
|
||||
#include "app_bt_stream.h"
|
||||
#include "heap_api.h"
|
||||
|
||||
//should solve this problem
|
||||
//#include "./../../utils/cqueue/cqueue.h"
|
||||
//#include "cqueue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//This buff is used as queue
|
||||
#ifndef APP_AUDIO_BUFFER_SIZE
|
||||
#if (RAM_SIZE >= 0x48000)
|
||||
|
||||
#if defined(AUDIO_ANC_FB_MC) && defined(ANC_APP) && !defined(__AUDIO_RESAMPLE__)
|
||||
|
||||
#if defined(A2DP_EQ_24BIT)
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 210)
|
||||
#else
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 140)
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 100)
|
||||
#endif
|
||||
|
||||
#elif (RAM_SIZE >= 0x40000)
|
||||
|
||||
#ifdef NEW_NV_RECORD_ENABLED
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 62)
|
||||
#else
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 59)
|
||||
#endif
|
||||
|
||||
#else // RAM_SIZE < 0x40000
|
||||
|
||||
#ifdef APP_TEST_AUDIO
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 10)
|
||||
#elif defined(SPEECH_RX_NS)
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 37)
|
||||
#else
|
||||
#define APP_AUDIO_BUFFER_SIZE (1024 * 32)
|
||||
#endif
|
||||
|
||||
#endif // RAM_SIZE < 0x40000
|
||||
#endif
|
||||
|
||||
#if defined(VOB_ENCODING_ALGORITHM) && (VOB_ENCODING_ALGORITHM == ENCODING_ALGORITHM_OPUS)
|
||||
|
||||
#ifdef __ALEXA_WWE
|
||||
#ifdef __ALEXA_WWE_LITE
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (63*1024)
|
||||
#else
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (305*1024)
|
||||
#endif
|
||||
|
||||
#elif defined(SPEECH_CAPTURE_TWO_CHANNEL)
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (76*1024)
|
||||
#elif defined(__DUAL_MIC_RECORDING__)
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (79*1024)
|
||||
#else
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (67*1024)
|
||||
#endif
|
||||
|
||||
#elif defined(__AMA_VOICE__) && (VOB_ENCODING_ALGORITHM == ENCODING_ALGORITHM_SBC)
|
||||
#if defined(CHIP_BEST1400) && defined(__AI_VOICE__)
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (13*1024)
|
||||
#else
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (17*1024)
|
||||
#endif
|
||||
#elif defined(__KWS_ALEXA__)
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (160*1024)
|
||||
#elif defined(AI_CAPTURE_DATA_AEC)
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (19*1024-512)
|
||||
#elif defined(GSOUND_HOTWORD_EXTERNAL)
|
||||
/// gsound_external_hotword_configuration
|
||||
#ifdef VOICE_DETECTOR_EN
|
||||
/// VAD_enabled_configuration
|
||||
#ifdef VAD_USE_8K_SAMPLE_RATE
|
||||
/// vad_use_8K_sample_rate_configuration
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE ((32 + 16 + 32)*1024-512)
|
||||
/// vad_use_8K_sample_rate_configuration
|
||||
#else
|
||||
/// vad_use_16K_sample_rate_configuration
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE ((32 + 32)*1024-512)
|
||||
/// vad_use_16K_sample_rate_configuration
|
||||
#endif
|
||||
/// VAD_enabled_configuration
|
||||
#else
|
||||
/// VAD_disabled_configuration
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (32*1024-512)
|
||||
/// VAD_disabled_configuration
|
||||
#endif
|
||||
/// gsound_external_hotword_configuration
|
||||
#else
|
||||
#ifdef VOICE_DETECTOR_EN
|
||||
/// VAD_enabled_configuration
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE ((13 + 32)*1024-512)
|
||||
/// VAD_enabled_configuration
|
||||
#else
|
||||
/// VAD_disabled_configuration
|
||||
#define APP_CAPTURE_AUDIO_BUFFER_SIZE (13*1024-512)
|
||||
/// VAD_disabled_configuration
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(A2DP_SCALABLE_ON)
|
||||
#define SCALABLE_FRAME_SIZE (864)
|
||||
#define SCALABLE_HEAD_SIZE (4) /* pick something big enough to hold a bunch of frames */
|
||||
#define SCALABLE_READBUF_SIZE (500) /* pick something big enough to hold a bunch of frames */
|
||||
#define SCALABLE_DECODER_SIZE (17456) /* pick something big enough to hold a bunch of frames */
|
||||
#define SBM_FAST_SPEED 67380 // 840 2.76%
|
||||
#define SBM_SLOW_SPEED 63730 // 888 2.76%
|
||||
#define SBM_NUM_NORMAL 100
|
||||
#endif
|
||||
|
||||
#define MAX_AUDIO_BUF_LIST 20
|
||||
enum APP_AUDIO_CACHE_T {
|
||||
APP_AUDIO_CACHE_CACHEING= 0,
|
||||
APP_AUDIO_CACHE_OK,
|
||||
APP_AUDIO_CACHE_QTY,
|
||||
};
|
||||
|
||||
#define APP_AUDIO_SET_MESSAGE(appevt, id, status) (appevt = (((uint32_t)id&0xffff)<<16)|(status&0xffff))
|
||||
#define APP_AUDIO_GET_ID(appevt, id) (id = (appevt>>16)&0xffff)
|
||||
#define APP_AUDIO_GET_STATUS(appevt, status) (status = appevt&0xffff)
|
||||
#define APP_AUDIO_GET_AUD_ID(appevt, aud_id) (aud_id = appevt)
|
||||
#define APP_AUDIO_GET_FREQ(appevt, freq) (freq = appevt)
|
||||
|
||||
#define APP_AUDIO_InitCQueue(a, b, c) InitCQueue(a, b, c)
|
||||
#define APP_AUDIO_AvailableOfCQueue(a) AvailableOfCQueue(a)
|
||||
#define APP_AUDIO_LengthOfCQueue(a) LengthOfCQueue(a)
|
||||
#define APP_AUDIO_PeekCQueue(a, b, c, d, e, f) PeekCQueue(a, b, c, d, e, f)
|
||||
#define APP_AUDIO_EnCQueue(a, b, c) EnCQueue(a, b, c)
|
||||
#define APP_AUDIO_DeCQueue(a, b, c) DeCQueue(a, b, c)
|
||||
|
||||
#define app_audio_mempool_init syspool_init
|
||||
|
||||
#define app_audio_mempool_noclr_init syspool_init
|
||||
|
||||
#define app_audio_mempool_use_mempoolsection_init syspool_init
|
||||
|
||||
#define app_audio_mempool_free_buff_size syspool_free_size
|
||||
|
||||
#define app_audio_mempool_get_buff syspool_get_buff
|
||||
|
||||
#if defined(A2DP_LDAC_ON)
|
||||
#define app_audio_mempool_total_buf syspool_total_size
|
||||
#define app_audio_mempool_force_set_buff_used syspool_force_used_size
|
||||
#endif
|
||||
|
||||
|
||||
void UNLOCK_APP_AUDIO_QUEUE();
|
||||
|
||||
void LOCK_APP_AUDIO_QUEUE();
|
||||
|
||||
uint32_t app_audio_lr_balance(uint8_t *buf, uint32_t len, int8_t balance);
|
||||
|
||||
void app_audio_mempool_init_with_specific_size(uint32_t size);
|
||||
|
||||
int app_audio_pcmbuff_init(uint8_t *buff, uint16_t len);
|
||||
|
||||
int app_audio_pcmbuff_length(void);
|
||||
|
||||
int app_audio_pcmbuff_put(uint8_t *buff, uint16_t len);
|
||||
|
||||
int app_audio_pcmbuff_get(uint8_t *buff, uint16_t len);
|
||||
|
||||
int app_audio_pcmbuff_discard(uint16_t len);
|
||||
|
||||
void app_audio_memcpy_16bit(int16_t *des, int16_t *src, int len);
|
||||
|
||||
void app_audio_memset_16bit(int16_t *des, int16_t val, int len);
|
||||
|
||||
|
||||
int app_audio_sendrequest(uint16_t id, uint8_t status, uint32_t ptr);
|
||||
|
||||
|
||||
int app_audio_sendrequest_param(uint16_t id, uint8_t status, uint32_t ptr, uint32_t param);
|
||||
|
||||
void app_audio_open(void);
|
||||
|
||||
void app_audio_close(void);
|
||||
|
||||
bool app_audio_list_append(APP_AUDIO_STATUS* aud_status);
|
||||
|
||||
bool app_audio_list_playback_exist(void);
|
||||
|
||||
void app_audio_list_playback_clear(void);
|
||||
|
||||
bool app_audio_list_rmv_callback(APP_AUDIO_STATUS *status_close, APP_AUDIO_STATUS *status_next, enum APP_BT_AUDIO_Q_POS pos, bool pop_next);
|
||||
|
||||
void app_audio_list_clear();
|
||||
|
||||
int app_capture_audio_mempool_init(void);
|
||||
|
||||
uint32_t app_capture_audio_mempool_free_buff_size();
|
||||
|
||||
int app_capture_audio_mempool_get_buff(uint8_t **buff, uint32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__FMDEC_H__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,76 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __BT_SCO_CHAIN_H__
|
||||
#define __BT_SCO_CHAIN_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Init speech algorithm, init all related states and memory
|
||||
* Input:
|
||||
* tx_sample_rate: capture sample rate
|
||||
* rx_sample_rate: playback sample rate
|
||||
* tx_frame_ms: capture frame size in ms
|
||||
* rx_frame_ms: playback frame size in ms
|
||||
* sco_frame_ms: sco frame size in ms(must be multiply of 7.5)
|
||||
* buf: buffer to be used for algorithms
|
||||
* len: buffer size
|
||||
*/
|
||||
int speech_init(int tx_sample_rate, int rx_sample_rate,
|
||||
int tx_frame_ms, int rx_frame_ms,
|
||||
int sco_frame_ms,
|
||||
uint8_t *buf, int len);
|
||||
|
||||
/*
|
||||
* Deinit speech algorithm, free all related states and memory
|
||||
*/
|
||||
int speech_deinit(void);
|
||||
|
||||
/*
|
||||
* Uplink process
|
||||
* Input:
|
||||
* pcm_buf: captured buffer by microphone, multi-channel is interleaved.
|
||||
* ref_buf: reference buffer for acoustic echo canceller.
|
||||
* buffee sample num should be tx_sample_rate * tx_frame_ms
|
||||
* pcm_len: capture buffer sample num, should be tx_sample_rate * sco_frame_ms * ch_num
|
||||
* Output:
|
||||
* pcm_buf: output buffer of speech algorithm, should be single channel
|
||||
* pcm_len: output buffer sample num, should be tx_sample_rate * sco_frame_ms
|
||||
*/
|
||||
int speech_tx_process(void *pcm_buf, void *ref_buf, int *pcm_len);
|
||||
|
||||
/*
|
||||
* Downlink process
|
||||
* Input:
|
||||
* pcm_buf: input buffer to be processed
|
||||
* pcm_len: input buffer sample num, should be rx_sample_rate * sco_frame_ms
|
||||
* Output:
|
||||
* pcm_buf: output buffer
|
||||
* pcm_len: output buffer sample num, should be rx_sample_rate * sco_frame_ms
|
||||
*/
|
||||
int speech_rx_process(void *pcm_buf, int *pcm_len);
|
||||
|
||||
void *speech_get_ext_buff(int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,146 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __BT_SCO_CHAIN_CFG_H__
|
||||
#define __BT_SCO_CHAIN_CFG_H__
|
||||
|
||||
#include "speech_cfg.h"
|
||||
|
||||
typedef struct {
|
||||
#if defined(SPEECH_TX_DC_FILTER)
|
||||
SpeechDcFilterConfig tx_dc_filter;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_AEC)
|
||||
SpeechAecConfig tx_aec;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_AEC2)
|
||||
SpeechAec2Config tx_aec2;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_AEC2FLOAT)
|
||||
Ec2FloatConfig tx_aec2float;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_AEC3)
|
||||
SubBandAecConfig tx_aec3;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_2MIC_NS)
|
||||
DUAL_MIC_DENOISE_CFG_T tx_2mic_ns;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_2MIC_NS2)
|
||||
Speech2MicNs2Config tx_2mic_ns2;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_2MIC_NS4)
|
||||
SensorMicDenoiseConfig tx_2mic_ns4;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_2MIC_NS5)
|
||||
LeftRightDenoiseConfig tx_2mic_ns5;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_3MIC_NS)
|
||||
Speech3MicNsConfig tx_3mic_ns;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_3MIC_NS3)
|
||||
TripleMicDenoise3Config tx_3mic_ns3;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_NS)
|
||||
SpeechNsConfig tx_ns;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_NS2)
|
||||
SpeechNs2Config tx_ns2;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_NS2FLOAT)
|
||||
SpeechNs2FloatConfig tx_ns2float;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_NS3)
|
||||
Ns3Config tx_ns3;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_WNR)
|
||||
WnrConfig tx_wnr;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_NOISE_GATE)
|
||||
NoisegateConfig tx_noise_gate;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_COMPEXP)
|
||||
CompexpConfig tx_compexp;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_AGC)
|
||||
AgcConfig tx_agc;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_EQ)
|
||||
EqConfig tx_eq;
|
||||
#endif
|
||||
#if defined(SPEECH_TX_POST_GAIN)
|
||||
SpeechGainConfig tx_post_gain;
|
||||
#endif
|
||||
// #if defined(SPEECH_CS_VAD)
|
||||
// VADConfig cs_vad;
|
||||
// #endif
|
||||
#if defined(SPEECH_RX_NS)
|
||||
SpeechNsConfig rx_ns;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_NS2)
|
||||
SpeechNs2Config rx_ns2;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_NS2FLOAT)
|
||||
SpeechNs2FloatConfig rx_ns2float;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_NS3)
|
||||
Ns3Config rx_ns3;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_NOISE_GATE)
|
||||
NoisegateConfig rx_noise_gate;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_COMPEXP)
|
||||
CompexpConfig rx_compexp;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_AGC)
|
||||
AgcConfig rx_agc;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_EQ)
|
||||
EqConfig rx_eq;
|
||||
#endif
|
||||
#if defined(SPEECH_RX_POST_GAIN)
|
||||
SpeechGainConfig rx_post_gain;
|
||||
#endif
|
||||
// Add more process
|
||||
} SpeechConfig;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,796 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "plat_types.h"
|
||||
#include "bt_sco_chain_cfg.h"
|
||||
|
||||
#if defined(SPEECH_TX_2MIC_NS4)
|
||||
static float ff_fb_h[256] = {1.f, };
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_MIC_CALIBRATION)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Mic Calibration Equalizer, implementation with 2 order iir filters
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* mic_num(1~4): the number of microphones. The filter num is (mic_num - 1)
|
||||
* calib: {bypass, gain, num, {type, frequency, gain, q}}. Please refer to SPEECH_TX_EQ section
|
||||
* in this file
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 0.5M/section;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
const SpeechIirCalibConfig WEAK speech_tx_mic_calib_cfg =
|
||||
{
|
||||
.bypass = 0,
|
||||
.mic_num = 2,
|
||||
.calib = {
|
||||
{
|
||||
.bypass = 0,
|
||||
.gain = 0.f,
|
||||
.num = 0,
|
||||
.params = {
|
||||
{IIR_BIQUARD_LOWSHELF, 150, -2.5, 0.707},
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_MIC_FIR_CALIBRATION)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Mic Calibration Equalizer, implementation with fir filter
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* mic_num(1~4): the number of microphones. The filter num is (mic_num - 1)
|
||||
* calib: {filter, filter_length, nfft}.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 0.5M/section;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
float mic2_ft_caliration[256] = {1.f, };
|
||||
const SpeechFirCalibConfig WEAK speech_tx_mic_fir_calib_cfg =
|
||||
{
|
||||
.bypass = 0,
|
||||
.mic_num = SPEECH_CODEC_CAPTURE_CHANNEL_NUM,
|
||||
.delay = 0,
|
||||
.calib = {
|
||||
{
|
||||
.filter = mic2_ft_caliration,
|
||||
.filter_length = ARRAY_SIZE(mic2_ft_caliration),
|
||||
},
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
const SpeechConfig WEAK speech_cfg_default = {
|
||||
|
||||
#if defined(SPEECH_TX_DC_FILTER)
|
||||
.tx_dc_filter = {
|
||||
.bypass = 0,
|
||||
.gain = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_AEC)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* delay(>0): delay samples from mic to speak, unit(sample).
|
||||
* leak_estimate(0~32767): echo supression value. This is a fixed mode. It has relatively large
|
||||
* echo supression and large damage to speech signal.
|
||||
* leak_estimate_shift(0~8): echo supression value. if leak_estimate == 0, then leak_estimate_shift
|
||||
* can take effect. This is a adaptive mode. It has relatively small echo supression and also
|
||||
* small damage to speech signal.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 40M;
|
||||
* Note:
|
||||
* If possible, use SPEECH_TX_AEC2FLOAT
|
||||
****************************************************************************************************/
|
||||
.tx_aec = {
|
||||
.bypass = 0,
|
||||
.delay = 60,
|
||||
.leak_estimate = 16383,
|
||||
.leak_estimate_shift = 4,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_AEC2)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* .
|
||||
* .
|
||||
* .
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, enNlpEnable = 1, 39M;
|
||||
* Note:
|
||||
* If possible, use SPEECH_TX_AEC2FLOAT
|
||||
****************************************************************************************************/
|
||||
.tx_aec2 = {
|
||||
.bypass = 0,
|
||||
.enEAecEnable = 1,
|
||||
.enHpfEnable = 1,
|
||||
.enAfEnable = 0,
|
||||
.enNsEnable = 0,
|
||||
.enNlpEnable = 1,
|
||||
.enCngEnable = 0,
|
||||
.shwDelayLength = 0,
|
||||
.shwNlpBandSortIdx = 0.75f,
|
||||
.shwNlpBandSortIdxLow = 0.5f,
|
||||
.shwNlpTargetSupp = 3.0f,
|
||||
.shwNlpMinOvrd = 1.0f,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_AEC2FLOAT)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* hpf_enabled(0/1): high pass filter enable or disable. Used to remove DC for Near and Ref signals.
|
||||
* af_enabled(0/1): adaptive filter enable or disable. If the echo signal is very large, enable this
|
||||
* nlp_enabled(0/1): non-linear process enable or disable. Enable this by default.
|
||||
* ns_enabled(0/1): noise supression enable or disable. Enable this by default.
|
||||
* cng_enabled(0/1): comfort noise generator enable or disable.
|
||||
* blocks(1~8): the length of adaptive filter = blocks * frame length
|
||||
* delay(>0): delay samples from mic to speak, unit(sample).
|
||||
* min_ovrd(1~6): supression factor, min_ovrd becomes larger and echo suppression becomes larger.
|
||||
* target_supp(<0): target echo suppression, unit(dB)
|
||||
* noise_supp(-30~0): noise suppression, unit(dB)
|
||||
* cng_type(0/1): noise type(0: White noise; 1: Pink noise)
|
||||
* cng_level(<0): noise gain, unit(dB)
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* This is the recommended AEC
|
||||
****************************************************************************************************/
|
||||
.tx_aec2float = {
|
||||
.bypass = 0,
|
||||
.hpf_enabled = false,
|
||||
.af_enabled = false,
|
||||
.nlp_enabled = true,
|
||||
.clip_enabled = false,
|
||||
.stsupp_enabled = false,
|
||||
.ns_enabled = true,
|
||||
.cng_enabled = false,
|
||||
.blocks = 1,
|
||||
.delay = 70,
|
||||
.min_ovrd = 2,
|
||||
.target_supp = -40,
|
||||
.noise_supp = -15,
|
||||
.cng_type = 1,
|
||||
.cng_level = -60,
|
||||
.clip_threshold = -20.f,
|
||||
.banks = 64,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_AEC3)
|
||||
.tx_aec3 = {
|
||||
.bypass = 0,
|
||||
.filter_size = 16,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_2MIC_NS)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* 2 MICs Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_2mic_ns = {
|
||||
.bypass = 0,
|
||||
.alpha_h = 0.8,
|
||||
.alpha_slow = 0.9,
|
||||
.alpha_fast = 0.6,
|
||||
.thegma = 0.01,
|
||||
.thre_corr = 0.2,
|
||||
.thre_filter_diff = 0.2,
|
||||
.cal_left_gain = 1.0,
|
||||
.cal_right_gain = 1.0,
|
||||
.delay_mono_sample = 6,
|
||||
.wnr_enable = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_2MIC_NS2)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* 2 MICs Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* delay_taps(0~4): ceil{[d(MIC1~mouth) - d(MIC2~mouth)] / 2}.
|
||||
* ceil: Returns the largest integer less than or equal to the specified data
|
||||
* d(MIC~mouth): The dinstance from MIC to mouth
|
||||
* e.g. 0: 0~2cm; 1: 2~4; 2: 5~6...
|
||||
* freq_smooth_enable(1): Must enable
|
||||
* wnr_enable(0/1): wind noise reduction enable or disable. This is also useful for improving
|
||||
* noise suppression, but it also has some damage to speech signal.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 32M;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_2mic_ns2 = {
|
||||
.bypass = 0,
|
||||
.delay_taps = 0.f,
|
||||
.freq_smooth_enable = 1,
|
||||
.wnr_enable = 1,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_2MIC_NS5)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* 2 MICs Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* delay_taps(0~4): ceil{[d(MIC1~mouth) - d(MIC2~mouth)] / 2}. Default as 0
|
||||
* ceil: Returns the largest integer less than or equal to the specified data
|
||||
* d(MIC~mouth): The dinstance from MIC to mouth
|
||||
* e.g. 0: 0~2cm; 1: 2~4; 2: 5~6...
|
||||
* freq_smooth_enable(1): Must enable
|
||||
* wnr_enable(0/1): wind noise reduction enable or disable. This is also useful for improving
|
||||
* noise suppression, but it also has some damage to speech signal.
|
||||
* delay_enable(0/1): enable the delay_taps or not. Ideally, never need to enable the delay and
|
||||
* delay_taps will be a useless parameter.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 32M;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_2mic_ns5 = {
|
||||
.bypass = 0,
|
||||
.delay_taps = 0.0f,
|
||||
.freq_smooth_enable = 1,
|
||||
.wnr_enable = 0,
|
||||
.delay_enable = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_2MIC_NS4)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* 2 MICs Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_2mic_ns4 = {
|
||||
.bypass = 0,
|
||||
.blend_en = 1,
|
||||
// .left_gain = 1.0f,
|
||||
// .right_gain = 1.0f,
|
||||
.delay_tapsM = 0,
|
||||
.delay_tapsS = 0,
|
||||
// .delay_tapsC = 32,
|
||||
//////////////////////////{{a0,a1,a2,a3,a4},{b0,b1,b2,b3,b4}}///////////////////////////
|
||||
// .coefH[0] = {1.0, -1.88561808316413, 1.55555555555556, -0.628539361054709, 0.111111111111111},
|
||||
// .coefH[1] = {0.323801506930344, -1.29520602772138, 1.94280904158206, -1.29520602772138, 0.323801506930344},
|
||||
// .coefL[0] = {1.0, -1.88561808316413, 1.55555555555556, -0.628539361054709, 0.111111111111111},
|
||||
// .coefL[1] = {0.00953182640298944, 0.0381273056119578, 0.0571909584179366, 0.0381273056119578, 0.00953182640298944},
|
||||
.crossover_freq = 1000,
|
||||
.ff_fb_coeff = ff_fb_h,
|
||||
.ff_fb_coeff_len = ARRAY_SIZE(ff_fb_h),
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_3MIC_NS)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* 3 MICs Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* delay_tapsM(0~4): MIC L/R delay samples. Refer to SPEECH_TX_2MIC_NS2 delay_taps
|
||||
* delay_tapsS(0~4): MIC L/S delay samples. Refer to SPEECH_TX_2MIC_NS2 delay_taps
|
||||
* freq_smooth_enable(1): Must enable
|
||||
* wnr_enable(0/1): wind noise reduction enable or disable. This is also useful for improving
|
||||
* noise suppression, but it also has some damage to speech signal.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_3mic_ns = {
|
||||
.bypass = 0,
|
||||
.blend_en = 1,
|
||||
.authen_en = 1,
|
||||
.delay_tapsM = 0.65f,
|
||||
.delay_tapsS = 2,
|
||||
.denoise_dB = -15.0f,
|
||||
// .coefH[0] = {1.0,-3.3384,4.2195,-2.3924,0.5136},
|
||||
// .coefH[1] = {0.7165,-2.8660,4.2990,-2.8660,0.7165},
|
||||
// .coefL[0] = {1.0,-3.3384,4.2195,-2.3924,0.5136},
|
||||
// .coefL[1] = {0.00014,0.00056,0.00084,0.00056,0.00014},
|
||||
.crossover_freq = 1000,
|
||||
.freq_smooth_enable = 1,
|
||||
.wnr_enable = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_3MIC_NS3)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* 3 MICs Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* delay_taps(0~4): ceil{[d(MIC1~mouth) - d(MIC2~mouth)] / 2}.
|
||||
* ceil: Returns the largest integer less than or equal to the specified data
|
||||
* d(MIC~mouth): The dinstance from MIC to mouth
|
||||
* e.g. 0: 0~2cm; 1: 2~4; 2: 5~6...
|
||||
* freq_smooth_enable(1): Must enable
|
||||
* wnr_enable(0/1): wind noise reduction enable or disable. This is also useful for improving
|
||||
* noise suppression, but it also has some damage to speech signal.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 32M;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_3mic_ns3 = {
|
||||
.bypass = 0,
|
||||
.endfire_enable = 1,
|
||||
.broadside_enable = 1,
|
||||
.delay_taps = 0.7f,
|
||||
.freq_smooth_enable = 1,
|
||||
.wnr_enable = 0,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_NS)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 30M;
|
||||
* Note:
|
||||
* If possible, use SPEECH_TX_NS2 or SPEECH_TX_NS2FLOAT
|
||||
****************************************************************************************************/
|
||||
.tx_ns = {
|
||||
.bypass = 0,
|
||||
.denoise_dB = -12,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_NS2)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* denoise_dB(-30~0): noise suppression, unit(dB).
|
||||
* e.g. -15: Can reduce 15dB of stationary noise.
|
||||
* Resource consumption:
|
||||
* RAM: fs = 16k: RAM = 8k;
|
||||
* fs = 8k: RAM = 4k;
|
||||
* RAM = frame_size * 30
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 16M;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_ns2 = {
|
||||
.bypass = 0,
|
||||
.denoise_dB = -15,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_NS2FLOAT)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* denoise_dB(-30~0): noise suppression, unit(dB).
|
||||
* e.g. -15: Can reduce 15dB of stationary noise.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* This is a 'float' version for SPEECH_TX_NS2.
|
||||
* It needs more MIPS and RAM, but can redece quantization noise.
|
||||
****************************************************************************************************/
|
||||
.tx_ns2float = {
|
||||
.bypass = 0,
|
||||
.denoise_dB = -15,
|
||||
.banks = 64,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_NS3)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* mode: None
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_ns3 = {
|
||||
.bypass = 0,
|
||||
.mode = NS3_SUPPRESSION_HIGH,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_WNR)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Wind Noise Suppression
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* lpf_cutoff: lowpass filter for wind noise detection
|
||||
* hpf_cutoff: highpass filter for wind noise suppression
|
||||
* power_ratio_thr: ratio of the power spectrum of the lower frequencies over the total power
|
||||
spectrum for all frequencies
|
||||
* power_thr: normalized power of the low frequencies
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_wnr = {
|
||||
.bypass = 0,
|
||||
.lpf_cutoff = 1000,
|
||||
.hpf_cutoff = 400,
|
||||
.power_ratio_thr = 0.9f,
|
||||
.power_thr = 1.f,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_NOISE_GATE)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Noise Gate
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* data_threshold(0~32767): distinguish between noise and speech, unit(sample).
|
||||
* data_shift(1~3): 1: -6dB; 2: -12dB; 3: -18dB
|
||||
* factor_up(float): attack time, unit(s)
|
||||
* factor_down(float): release time, unit(s)
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_noise_gate = {
|
||||
.bypass = 0,
|
||||
.data_threshold = 640,
|
||||
.data_shift = 1,
|
||||
.factor_up = 0.001f,
|
||||
.factor_down = 0.5f,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_COMPEXP)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Compressor and expander
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* ...
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_compexp = {
|
||||
.bypass = 0,
|
||||
.comp_threshold = -10.f,
|
||||
.comp_ratio = 2.f,
|
||||
.expand_threshold = -45.f,
|
||||
.expand_ratio = 0.5556f,
|
||||
.attack_time = 0.001f,
|
||||
.release_time = 0.6f,
|
||||
.makeup_gain = 6,
|
||||
.delay = 128,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_AGC)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Automatic Gain Control
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* target_level(>0): signal can not exceed (-1 * target_level)dB.
|
||||
* compression_gain(>0): excepted gain.
|
||||
* limiter_enable(0/1): 0: target_level does not take effect; 1: target_level takes effect.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 3M;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_agc = {
|
||||
.bypass = 0,
|
||||
.target_level = 3,
|
||||
.compression_gain = 6,
|
||||
.limiter_enable = 1,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_EQ)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Equalizer, implementation with 2 order iir filters
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* gain(float): normalized gain. It is usually less than or equal to 0
|
||||
* num(0~6): the number of EQs
|
||||
* params: {type, frequency, gain, q}. It supports a lot of types, please refer to iirfilt.h file
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz, 0.5M/section;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_eq = {
|
||||
.bypass = 0,
|
||||
.gain = 0.f,
|
||||
.num = 1,
|
||||
.params = {
|
||||
{IIR_BIQUARD_HPF, {{60, 0, 0.707f}}},
|
||||
},
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_POST_GAIN)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Linear Gain
|
||||
* Parameters:
|
||||
* bypass(0/1): bypass enable or disable.
|
||||
* Resource consumption:
|
||||
* RAM: None
|
||||
* FLASE: None
|
||||
* MIPS: fs = 16kHz;
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.tx_post_gain = {
|
||||
.bypass = 0,
|
||||
.gain_dB = 6.0f,
|
||||
},
|
||||
#endif
|
||||
|
||||
// #if defined(SPEECH_CS_VAD)
|
||||
// /****************************************************************************************************
|
||||
// * Describtion:
|
||||
// * Voice Activity Detector
|
||||
// * Parameters:
|
||||
// * bypass(0/1): bypass enable or disable.
|
||||
// * Resource consumption:
|
||||
// * RAM: None
|
||||
// * FLASE: None
|
||||
// * MIPS: fs = 16kHz;
|
||||
// * Note:
|
||||
// * None
|
||||
// ****************************************************************************************************/
|
||||
// .tx_vad = {
|
||||
// .snrthd = 5.f,
|
||||
// .energythd = 100.f,
|
||||
// },
|
||||
// #endif
|
||||
|
||||
#if defined(SPEECH_RX_NS)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_NS
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_ns = {
|
||||
.bypass = 0,
|
||||
.denoise_dB = -12,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_NS2)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_NS2
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_ns2 = {
|
||||
.bypass = 0,
|
||||
.denoise_dB = -15,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_NS2FLOAT)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_NS2FLOAT
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_ns2float = {
|
||||
.bypass = 0,
|
||||
.denoise_dB = -15,
|
||||
.banks = 64,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_NS3)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Acoustic Echo Cancellation
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_NS3
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_ns3 = {
|
||||
.bypass = 0,
|
||||
.mode = NS3_SUPPRESSION_HIGH,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_NOISE_GATE)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Noise Gate
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_NOISE_GATE
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_noise_gate = {
|
||||
.bypass = 0,
|
||||
.data_threshold = 640,
|
||||
.data_shift = 1,
|
||||
.factor_up = 0.001f,
|
||||
.factor_down = 0.5f,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_COMPEXP)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Compressor and expander
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_COMPEXP
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_compexp = {
|
||||
.bypass = 0,
|
||||
.comp_threshold = -10.f,
|
||||
.comp_slope = 0.5f,
|
||||
.expand_threshold = -40.f,
|
||||
.expand_slope = -0.5f,
|
||||
.attack_time = 0.01f,
|
||||
.release_time = 0.6f,
|
||||
.makeup_gain = 6,
|
||||
.delay = 128,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_AGC)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Automatic Gain Control
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_AGC
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_agc = {
|
||||
.bypass = 0,
|
||||
.target_level = 3,
|
||||
.compression_gain = 6,
|
||||
.limiter_enable = 1,
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_EQ)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Equalizer, implementation with 2 order iir filters
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_EQ
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_eq = {
|
||||
.bypass = 0,
|
||||
.gain = 0.f,
|
||||
.num = 1,
|
||||
.params = {
|
||||
{IIR_BIQUARD_HPF, {{60, 0, 0.707f}}},
|
||||
},
|
||||
},
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_RX_POST_GAIN)
|
||||
/****************************************************************************************************
|
||||
* Describtion:
|
||||
* Linear Gain
|
||||
* Parameters:
|
||||
* Refer to SPEECH_TX_POST_GAIN
|
||||
* Note:
|
||||
* None
|
||||
****************************************************************************************************/
|
||||
.rx_post_gain = {
|
||||
.bypass = 0,
|
||||
.gain_dB = 6.0f,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
|
@ -0,0 +1,228 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/**
|
||||
* Usage:
|
||||
* 1. Enable SCO_CP_ACCEL ?= 1 to enable dual core in sco
|
||||
* 2. Enable SCO_TRACE_CP_ACCEL ?= 1 to see debug log.
|
||||
* 3. Change channel number if the algo(run in cp) input is more than one channel: sco_cp_init(speech_tx_frame_len, 1);
|
||||
* 4. The code between SCO_CP_ACCEL_ALGO_START(); and SCO_CP_ACCEL_ALGO_END(); will run in CP core.
|
||||
* 5. These algorithms will work in AP. Need to move this algorithms from overlay to fast ram.
|
||||
*
|
||||
* NOTE:
|
||||
* 1. spx fft and hw fft will share buffer, so just one core can use these fft.
|
||||
* 2. audio_dump_add_channel_data function can not work correctly in CP core, because
|
||||
* audio_dump_add_channel_data is possible called after audio_dump_run();
|
||||
* 3. AP and CP just can use 85%
|
||||
*
|
||||
*
|
||||
*
|
||||
* TODO:
|
||||
* 1. FFT, RAM, CODE overlay
|
||||
**/
|
||||
#if defined(SCO_CP_ACCEL)
|
||||
#include "cp_accel.h"
|
||||
#include "hal_location.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_timer.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "speech_cfg.h"
|
||||
#include "math.h"
|
||||
#include "norflash_api.h"
|
||||
|
||||
// malloc data from pool in init function
|
||||
#define FRAME_LEN_MAX (256)
|
||||
#define CHANNEL_NUM_MAX (2)
|
||||
|
||||
enum CP_SCO_STATE_T {
|
||||
CP_SCO_STATE_NONE = 0,
|
||||
CP_SCO_STATE_IDLE,
|
||||
CP_SCO_STATE_WORKING,
|
||||
};
|
||||
|
||||
enum SCO_CP_CMD_T {
|
||||
SCO_CP_CMD_PRO = 0,
|
||||
SCO_CP_CMD_OTHER,
|
||||
|
||||
SCO_CP_CMD_QTY,
|
||||
};
|
||||
|
||||
static CP_DATA_LOC enum CP_SCO_STATE_T g_cp_state = CP_SCO_STATE_NONE;
|
||||
|
||||
// TODO: Use malloc to replace array
|
||||
// static CP_BSS_LOC char g_cp_heap_buf[1024 * 100];
|
||||
static CP_BSS_LOC short g_in_pcm_buf[FRAME_LEN_MAX * CHANNEL_NUM_MAX];
|
||||
static CP_BSS_LOC short g_out_pcm_buf[FRAME_LEN_MAX * CHANNEL_NUM_MAX];
|
||||
static CP_BSS_LOC short g_in_ref_buf[FRAME_LEN_MAX];
|
||||
static CP_BSS_LOC int g_pcm_len;
|
||||
|
||||
static CP_BSS_LOC int g_frame_len;
|
||||
static CP_BSS_LOC int g_channel_num;
|
||||
|
||||
static int g_require_cnt = 0;
|
||||
static int g_run_cnt = 0;
|
||||
|
||||
int sco_cp_process(short *pcm_buf, short *ref_buf, int *_pcm_len)
|
||||
{
|
||||
int32_t pcm_len = *_pcm_len;
|
||||
uint32_t wait_cnt = 0;
|
||||
|
||||
ASSERT(g_frame_len * g_channel_num == pcm_len, "[%s] g_frame_len(%d) * g_channel_num(%d) != pcm_len(%d)", __func__, g_frame_len, g_channel_num, pcm_len);
|
||||
|
||||
// Check CP has new data to get and can get data from buffer
|
||||
#if defined(SCO_TRACE_CP_ACCEL)
|
||||
TRACE(4,"[%s] g_require_cnt: %d, status: %d, pcm_len: %d", __func__, g_require_cnt, g_cp_state, pcm_len);
|
||||
#endif
|
||||
|
||||
while (g_cp_state == CP_SCO_STATE_WORKING)
|
||||
{
|
||||
hal_sys_timer_delay_us(10);
|
||||
|
||||
if (wait_cnt++ > 300000) { // 3s
|
||||
ASSERT(0, "cp is hung %d", g_cp_state);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_cp_state == CP_SCO_STATE_IDLE)
|
||||
{
|
||||
speech_copy_int16(g_in_pcm_buf, pcm_buf, pcm_len);
|
||||
if (ref_buf)
|
||||
{
|
||||
speech_copy_int16(g_in_ref_buf, ref_buf, pcm_len / g_channel_num);
|
||||
}
|
||||
speech_copy_int16(pcm_buf, g_out_pcm_buf, g_pcm_len);
|
||||
*_pcm_len = g_pcm_len;
|
||||
g_pcm_len = pcm_len;
|
||||
|
||||
g_require_cnt++;
|
||||
g_cp_state = CP_SCO_STATE_WORKING;
|
||||
cp_accel_send_event_mcu2cp(CP_BUILD_ID(CP_TASK_SCO, CP_EVENT_SCO_PROCESSING));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multi channels to one channel
|
||||
#if 0
|
||||
for (int i = 0; i < pcm_len / g_channel_num; i++)
|
||||
{
|
||||
pcm_buf[i] = pcm_buf[2*i];
|
||||
}
|
||||
|
||||
*_pcm_len = pcm_len / g_channel_num;
|
||||
#endif
|
||||
|
||||
// Check abs(g_require_cnt - g_run_cnt) > threshold, reset or assert
|
||||
|
||||
TRACE(2,"[%s] ERROR: status = %d", __func__, g_cp_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int sco_cp_algo(short *pcm_buf, short *ref_buf, int *_pcm_len);
|
||||
|
||||
CP_TEXT_SRAM_LOC
|
||||
static unsigned int sco_cp_main(uint8_t event)
|
||||
{
|
||||
#if defined(SCO_TRACE_CP_ACCEL)
|
||||
TRACE(2,"[%s] g_run_cnt: %d", __func__, g_run_cnt);
|
||||
#endif
|
||||
|
||||
// LOCK BUFFER
|
||||
|
||||
// process pcm
|
||||
#if 0
|
||||
// speech_copy_int16(g_out_pcm_buf, g_in_pcm_buf, g_pcm_len);
|
||||
|
||||
for (int i = 0; i < g_pcm_len; i++)
|
||||
{
|
||||
g_out_pcm_buf[i] = (short)(sinf(2 * 3.1415926 * i / 16 ) * 10000);
|
||||
}
|
||||
#else
|
||||
sco_cp_algo(g_in_pcm_buf, g_in_ref_buf, &g_pcm_len);
|
||||
speech_copy_int16(g_out_pcm_buf, g_in_pcm_buf, g_pcm_len);
|
||||
#endif
|
||||
|
||||
// set status
|
||||
g_run_cnt++;
|
||||
g_cp_state = CP_SCO_STATE_IDLE;
|
||||
|
||||
#if defined(SCO_TRACE_CP_ACCEL)
|
||||
TRACE(1,"[%s] CP_SCO_STATE_IDLE", __func__);
|
||||
#endif
|
||||
|
||||
// UNLOCK BUFFER
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cp_task_desc TASK_DESC_SCO = {CP_ACCEL_STATE_CLOSED, sco_cp_main, NULL, NULL, NULL};
|
||||
int sco_cp_init(int frame_len, int channel_num)
|
||||
{
|
||||
TRACE(3,"[%s] frame_len: %d, channel_num: %d", __func__, frame_len, channel_num);
|
||||
ASSERT(frame_len <= FRAME_LEN_MAX, "[%s] frame_len(%d) > FRAME_LEN_MAX", __func__, frame_len);
|
||||
ASSERT(channel_num <= CHANNEL_NUM_MAX, "[%s] channel_num(%d) > CHANNEL_NUM_MAX", __func__, channel_num);
|
||||
|
||||
g_require_cnt = 0;
|
||||
g_run_cnt = 0;
|
||||
|
||||
norflash_api_flush_disable(NORFLASH_API_USER_CP,(uint32_t)cp_accel_init_done);
|
||||
cp_accel_open(CP_TASK_SCO, &TASK_DESC_SCO);
|
||||
|
||||
uint32_t cnt=0;
|
||||
while(cp_accel_init_done() == false) {
|
||||
hal_sys_timer_delay_us(100);
|
||||
|
||||
cnt++;
|
||||
if (cnt % 10 == 0) {
|
||||
if (cnt == 10 * 200) { // 200ms
|
||||
ASSERT(0, "[%s] ERROR: Can not init cp!!!", __func__);
|
||||
} else {
|
||||
TRACE(1, "[%s] Wait CP init done...%d(ms)", __func__, cnt/10);
|
||||
}
|
||||
}
|
||||
}
|
||||
norflash_api_flush_enable(NORFLASH_API_USER_CP);
|
||||
#if 0
|
||||
speech_heap_cp_start();
|
||||
speech_heap_add_block(g_cp_heap_buf, sizeof(g_cp_heap_buf));
|
||||
speech_heap_cp_end();
|
||||
#endif
|
||||
|
||||
g_frame_len = frame_len;
|
||||
g_channel_num = channel_num;
|
||||
g_pcm_len = frame_len; // Initialize output pcm_len
|
||||
|
||||
speech_set_int16(g_in_pcm_buf, 0, g_frame_len * g_channel_num);
|
||||
speech_set_int16(g_out_pcm_buf, 0, g_frame_len * g_channel_num);
|
||||
speech_set_int16(g_in_ref_buf, 0, g_frame_len);
|
||||
g_cp_state = CP_SCO_STATE_IDLE;
|
||||
|
||||
TRACE(2,"[%s] status = %d", __func__, g_cp_state);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int sco_cp_deinit(void)
|
||||
{
|
||||
TRACE(1,"[%s] ...", __func__);
|
||||
|
||||
cp_accel_close(CP_TASK_SCO);
|
||||
|
||||
g_cp_state = CP_SCO_STATE_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __BT_SCO_CHAIN_CP_H__
|
||||
#define __BT_SCO_CHAIN_CP_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
// enum CP_EMPTY_OUT_FRM_T {
|
||||
// CP_EMPTY_OUT_FRM_OK,
|
||||
// CP_EMPTY_OUT_FRM_WORKING,
|
||||
// CP_EMPTY_OUT_FRM_ERR,
|
||||
// };
|
||||
|
||||
// typedef int (*A2DP_CP_DECODE_T)(void);
|
||||
|
||||
int sco_cp_init(int frame_len, int channel_num);
|
||||
|
||||
int sco_cp_deinit(void);
|
||||
|
||||
// int sco_cp_set_pcm(short *pcm_buf, int pcm_len);
|
||||
|
||||
// int sco_cp_get_pcm(short *pcm_buf, int pcm_len);
|
||||
|
||||
int sco_cp_process(short *pcm_buf, short *ref_buf, int *_pcm_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
#include "bt_sco_chain.h"
|
||||
#include "speech_memory.h"
|
||||
#include "speech_utils.h"
|
||||
#include "hal_trace.h"
|
||||
#include "audio_dump.h"
|
||||
#include "speech_cfg.h"
|
||||
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
int32_t *aec_echo_buf = NULL;
|
||||
|
||||
// Use to free buffer
|
||||
static int32_t *aec_echo_buf_ptr = NULL;
|
||||
#else
|
||||
short *aec_echo_buf = NULL;
|
||||
|
||||
// Use to free buffer
|
||||
static short *aec_echo_buf_ptr;
|
||||
#endif
|
||||
|
||||
#if defined(MSBC_8K_SAMPLE_RATE)
|
||||
#define SPEECH_HEAP_RESERVE_SIZE (1024 * 4)
|
||||
#else
|
||||
#define SPEECH_HEAP_RESERVE_SIZE (1024 * 4)
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_DC_FILTER)
|
||||
SpeechDcFilterState *speech_tx_dc_filter_st = NULL;
|
||||
#endif
|
||||
|
||||
int speech_init(int tx_sample_rate, int rx_sample_rate,
|
||||
int tx_frame_ms, int rx_frame_ms,
|
||||
int sco_frame_ms,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
// we shoule keep a minmum buffer for speech heap
|
||||
// MSBC_16K_SAMPLE_RATE = 0, 560 bytes
|
||||
// MSBC_16K_SAMPLE_RATE = 1, 2568 bytes
|
||||
speech_heap_init(buf, SPEECH_HEAP_RESERVE_SIZE);
|
||||
|
||||
uint8_t *free_buf = buf + SPEECH_HEAP_RESERVE_SIZE;
|
||||
int free_len = len - SPEECH_HEAP_RESERVE_SIZE;
|
||||
|
||||
// use free_buf for your algorithm
|
||||
memset(free_buf, 0, free_len);
|
||||
|
||||
int frame_len = SPEECH_FRAME_MS_TO_LEN(tx_sample_rate, tx_frame_ms);
|
||||
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
aec_echo_buf = (int32_t *)speech_calloc(frame_len, sizeof(int32_t));
|
||||
#else
|
||||
aec_echo_buf = (short *)speech_calloc(frame_len, sizeof(short));
|
||||
#endif
|
||||
aec_echo_buf_ptr = aec_echo_buf;
|
||||
|
||||
#if defined(SPEECH_TX_DC_FILTER)
|
||||
int channel_num = SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
||||
int data_separation = 0;
|
||||
|
||||
SpeechDcFilterConfig dc_filter_cfg = {
|
||||
.bypass = 0,
|
||||
.gain = 0.f,
|
||||
};
|
||||
|
||||
speech_tx_dc_filter_st = speech_dc_filter_create(tx_sample_rate, frame_len, &dc_filter_cfg);
|
||||
speech_dc_filter_ctl(speech_tx_dc_filter_st, SPEECH_DC_FILTER_SET_CHANNEL_NUM, &channel_num);
|
||||
speech_dc_filter_ctl(speech_tx_dc_filter_st, SPEECH_DC_FILTER_SET_DATA_SEPARATION, &data_separation);
|
||||
#endif
|
||||
|
||||
audio_dump_init(frame_len, sizeof(int16_t), 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speech_deinit(void)
|
||||
{
|
||||
#if defined(SPEECH_TX_DC_FILTER)
|
||||
speech_dc_filter_destroy(speech_tx_dc_filter_st);
|
||||
#endif
|
||||
|
||||
speech_free(aec_echo_buf_ptr);
|
||||
|
||||
size_t total = 0, used = 0, max_used = 0;
|
||||
speech_memory_info(&total, &used, &max_used);
|
||||
TRACE(3,"SPEECH MALLOC MEM: total - %d, used - %d, max_used - %d.", total, used, max_used);
|
||||
ASSERT(used == 0, "[%s] used != 0", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
extern void bt_sco_get_tdm_buffer(uint8_t **buf, uint32_t *len);
|
||||
#endif
|
||||
|
||||
int speech_tx_process(void *_pcm_buf, void *_ref_buf, int *_pcm_len)
|
||||
{
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
int32_t *pcm_buf = (int32_t *)_pcm_buf;
|
||||
int32_t *ref_buf = (int32_t *)_ref_buf;
|
||||
#else
|
||||
int16_t *pcm_buf = (int16_t *)_pcm_buf;
|
||||
int16_t *ref_buf = (int16_t *)_ref_buf;
|
||||
#endif
|
||||
|
||||
int pcm_len = *_pcm_len;
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
uint8_t *bone_buf = NULL;
|
||||
uint32_t bone_len = 0;
|
||||
bt_sco_get_tdm_buffer(&bone_buf, &bone_len);
|
||||
#endif
|
||||
|
||||
audio_dump_clear_up();
|
||||
audio_dump_add_channel_data(0, ref_buf, pcm_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM);
|
||||
audio_dump_add_channel_data_from_multi_channels(1, pcm_buf, pcm_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM, SPEECH_CODEC_CAPTURE_CHANNEL_NUM, 0);
|
||||
audio_dump_add_channel_data_from_multi_channels(2, pcm_buf, pcm_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM, SPEECH_CODEC_CAPTURE_CHANNEL_NUM, 1);
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
audio_dump_add_channel_data(3, bone_buf, pcm16_len/SPEECH_CODEC_CAPTURE_CHANNEL_NUM);
|
||||
#endif
|
||||
|
||||
audio_dump_run();
|
||||
|
||||
#if defined(SPEECH_TX_DC_FILTER)
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
speech_dc_filter_process_int24(speech_tx_dc_filter_st, pcm_buf, pcm_len);
|
||||
#else
|
||||
speech_dc_filter_process(speech_tx_dc_filter_st, pcm_buf, pcm_len);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Add your algrithm here and disable #if macro
|
||||
#if 1
|
||||
for (int i = 0, j = 0; i < pcm_len; i += SPEECH_CODEC_CAPTURE_CHANNEL_NUM, j++) {
|
||||
// choose main microphone data
|
||||
pcm_buf[j] = pcm_buf[i];
|
||||
// choose reference data, i.e. loopback
|
||||
//pcm16_buf[j] = ref16_buf[j];
|
||||
}
|
||||
pcm_len /= SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
||||
#endif
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
memcpy(pcm_buf, bone_buf, bone_len);
|
||||
#endif
|
||||
|
||||
*_pcm_len = pcm_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speech_rx_process(void *pcm_buf, int *pcm_len)
|
||||
{
|
||||
// Add your algorithm here
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
#include "bt_sco_chain.h"
|
||||
#include "speech_memory.h"
|
||||
#include "speech_utils.h"
|
||||
#include "hal_trace.h"
|
||||
#include "audio_dump.h"
|
||||
#include "vcp-api.h"
|
||||
#include "spf-postapi.h"
|
||||
|
||||
#define ALANGO_TRACE(s, ...) TRACE(1,"%s: " s, __FUNCTION__, ## __VA_ARGS__)
|
||||
|
||||
short *aec_echo_buf = NULL;
|
||||
|
||||
// Use to free buffer
|
||||
static short *aec_echo_buf_ptr;
|
||||
|
||||
static void *mem;
|
||||
|
||||
extern void *voicebtpcm_get_ext_buff(int size);
|
||||
|
||||
extern char* vcp_errorv(err_t err);
|
||||
|
||||
extern PROFILE_TYPE(t) alango_profile;
|
||||
|
||||
static vcp_profile_t *curr_profile = NULL;
|
||||
|
||||
mem_reg_t reg[NUM_MEM_REGIONS];
|
||||
|
||||
#if SPEECH_CODEC_CAPTURE_CHANNEL_NUM >= 2
|
||||
static int16_t *deinterleaved_buf = NULL;
|
||||
|
||||
static void deinterleave_audio(int16_t *dst, int16_t *src, uint32_t len, uint32_t ch_num)
|
||||
{
|
||||
uint32_t samples_per_channel = len / ch_num;
|
||||
|
||||
for (uint32_t i = 0; i < samples_per_channel; i++) {
|
||||
for (uint32_t j = 0; j < ch_num; j++) {
|
||||
dst[samples_per_channel * j + i] = src[ch_num * i + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int speech_init(int tx_sample_rate, int rx_sample_rate,
|
||||
int tx_frame_ms, int rx_frame_ms,
|
||||
int sco_frame_ms,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
speech_heap_init(buf, len);
|
||||
|
||||
int frame_len = SPEECH_FRAME_MS_TO_LEN(tx_sample_rate, tx_frame_ms);
|
||||
|
||||
aec_echo_buf = (short *)speech_calloc(frame_len, sizeof(short));
|
||||
aec_echo_buf_ptr = aec_echo_buf;
|
||||
|
||||
// init alango
|
||||
// check profile
|
||||
curr_profile = &alango_profile;
|
||||
err_t err = vcp_check_profile(curr_profile);
|
||||
if (err.err) {
|
||||
if (err.err == ERR_INVALID_CRC)
|
||||
ALANGO_TRACE(0,"Profile error: Invalid CRC!");
|
||||
else
|
||||
ALANGO_TRACE(1,"Profile error: %d", err.err);
|
||||
}
|
||||
|
||||
ASSERT(frame_len % curr_profile->p_gen->frlen == 0, "Profile error: frame_len(%d) should be divided by frlen(%d)", frame_len, curr_profile->p_gen->frlen);
|
||||
|
||||
unsigned int smem = vcp_get_hook_size();
|
||||
mem = speech_malloc(smem);
|
||||
|
||||
vcp_get_mem_size(curr_profile, reg, mem);
|
||||
|
||||
ALANGO_TRACE(0,"Hello, I am VCP8!");
|
||||
|
||||
for (int i = 0; i < NUM_MEM_REGIONS; i++) {
|
||||
reg[i].mem = (void *)speech_malloc(reg[i].size);
|
||||
ALANGO_TRACE(2,"I need %d bytes of memory in memory region %d to work.\n", reg[i].size, i + 1);
|
||||
}
|
||||
|
||||
err = vcp_init_debug(curr_profile, reg);
|
||||
if (err.err == ERR_NOT_ENOUGH_MEMORY) {
|
||||
ALANGO_TRACE(2,"%d more bytes needed in region %d!\n", -reg[err.pid].size, err.pid);
|
||||
} else if (err.err == ERR_UNKNOWN) {
|
||||
ALANGO_TRACE(0,"vcp_init_debug() returns UNKNOWN error\n!");
|
||||
} else if (err.err != ERR_NO_ERROR) {
|
||||
ALANGO_TRACE(2,"vcp_init_debug() returns error %d, pid %d!\n", err.err, err.pid);
|
||||
}
|
||||
|
||||
#if SPEECH_CODEC_CAPTURE_CHANNEL_NUM >= 2
|
||||
deinterleaved_buf = speech_malloc(curr_profile->p_gen->frlen * SPEECH_CODEC_CAPTURE_CHANNEL_NUM * sizeof(int16_t));
|
||||
#endif
|
||||
|
||||
audio_dump_init(frame_len, sizeof(int16_t), 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speech_deinit(void)
|
||||
{
|
||||
speech_free(aec_echo_buf_ptr);
|
||||
speech_free(mem);
|
||||
|
||||
for (int i = 0; i < NUM_MEM_REGIONS; i++)
|
||||
speech_free(reg[i].mem);
|
||||
|
||||
#if SPEECH_CODEC_CAPTURE_CHANNEL_NUM >= 2
|
||||
speech_free(deinterleaved_buf);
|
||||
#endif
|
||||
|
||||
size_t total = 0, used = 0, max_used = 0;
|
||||
speech_memory_info(&total, &used, &max_used);
|
||||
TRACE(3,"SPEECH MALLOC MEM: total - %d, used - %d, max_used - %d.", total, used, max_used);
|
||||
ASSERT(used == 0, "[%s] used != 0", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
extern void bt_sco_get_tdm_buffer(uint8_t **buf, uint32_t *len);
|
||||
#endif
|
||||
|
||||
int speech_tx_process(void *pcm_buf, void *ref_buf, int *pcm_len)
|
||||
{
|
||||
int16_t *pcm16_buf = (int16_t *)pcm_buf;
|
||||
int16_t *ref16_buf = (int16_t *)ref_buf;
|
||||
int pcm16_len = *pcm_len;
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
uint8_t *bone_buf = NULL;
|
||||
uint32_t bone_len = 0;
|
||||
bt_sco_get_tdm_buffer(&bone_buf, &bone_len);
|
||||
#endif
|
||||
|
||||
audio_dump_clear_up();
|
||||
audio_dump_add_channel_data(0, ref_buf, pcm16_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM);
|
||||
audio_dump_add_channel_data_from_multi_channels(1, pcm16_buf, pcm16_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM, SPEECH_CODEC_CAPTURE_CHANNEL_NUM, 0);
|
||||
audio_dump_add_channel_data_from_multi_channels(2, pcm16_buf, pcm16_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM, SPEECH_CODEC_CAPTURE_CHANNEL_NUM, 1);
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
audio_dump_add_channel_data(3, bone_buf, pcm16_len/SPEECH_CODEC_CAPTURE_CHANNEL_NUM);
|
||||
#endif
|
||||
|
||||
audio_dump_run();
|
||||
|
||||
// Add your algrithm here and disable #if macro
|
||||
#if 0
|
||||
for (int i = 0, j = 0; i < pcm16_len; i += SPEECH_CODEC_CAPTURE_CHANNEL_NUM, j++) {
|
||||
// choose main microphone data
|
||||
pcm16_buf[j] = pcm16_buf[i];
|
||||
// choose reference data, i.e. loopback
|
||||
//pcm16_buf[j] = ref16_buf[j];
|
||||
}
|
||||
pcm16_len /= SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
||||
#else
|
||||
for (int i = 0, j = 0; i < pcm16_len; i += curr_profile->p_gen->frlen * SPEECH_CODEC_CAPTURE_CHANNEL_NUM, j += curr_profile->p_gen->frlen) {
|
||||
#if SPEECH_CODEC_CAPTURE_CHANNEL_NUM >= 2
|
||||
deinterleave_audio(deinterleaved_buf, &pcm16_buf[i], curr_profile->p_gen->frlen * SPEECH_CODEC_CAPTURE_CHANNEL_NUM, SPEECH_CODEC_CAPTURE_CHANNEL_NUM);
|
||||
err_t err = vcp_process_tx(reg, deinterleaved_buf, &ref16_buf[j], &pcm16_buf[j]);
|
||||
//memcpy(&pcm16_buf[j], deinterleaved_buf, curr_profile->p_gen->frlen * sizeof(int16_t));
|
||||
#else
|
||||
err_t err = vcp_process_tx(reg, &pcm16_buf[i], &ref16_buf[j], &pcm16_buf[j]);
|
||||
#endif
|
||||
if (err.err != ERR_NO_ERROR) {
|
||||
ALANGO_TRACE(1,"vcp_process_tx error: %d", err.err);
|
||||
}
|
||||
}
|
||||
pcm16_len /= SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
||||
#endif
|
||||
|
||||
#if defined(BONE_SENSOR_TDM)
|
||||
memcpy(pcm_buf, bone_buf, bone_len);
|
||||
#endif
|
||||
|
||||
*pcm_len = pcm16_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speech_rx_process(void *pcm_buf, int *pcm_len)
|
||||
{
|
||||
int16_t *pcm16_buf = (int16_t *)pcm_buf;
|
||||
int pcm16_len = *pcm_len;
|
||||
|
||||
for (int i = 0; i < pcm16_len; i += curr_profile->p_gen->frlen) {
|
||||
err_t err = vcp_process_rx(reg, &pcm16_buf[i], &pcm16_buf[i]);
|
||||
if (err.err != ERR_NO_ERROR) {
|
||||
ALANGO_TRACE(1,"vcp_process_tx error: %d", err.err);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "bt_sco_chain_cfg.h"
|
||||
#include "aud_section.h"
|
||||
#include "hal_trace.h"
|
||||
|
||||
static bool speech_tuning_status = false;
|
||||
|
||||
extern int speech_store_config(const SpeechConfig *cfg);
|
||||
|
||||
#ifdef AUDIO_SECTION_ENABLE
|
||||
typedef struct {
|
||||
uint8_t reserved[AUDIO_SECTION_CFG_RESERVED_LEN];
|
||||
SpeechConfig cfg;
|
||||
} AUDIO_SECTION_SPEECH_CFG_T;
|
||||
|
||||
static AUDIO_SECTION_SPEECH_CFG_T audio_section_speech_cfg;
|
||||
|
||||
int store_speech_cfg_into_audio_section(SpeechConfig *cfg)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
memcpy(&audio_section_speech_cfg.cfg, cfg, sizeof(SpeechConfig));
|
||||
|
||||
res = audio_section_store_cfg(AUDIO_SECTION_DEVICE_SPEECH,
|
||||
(uint8_t *)&audio_section_speech_cfg,
|
||||
sizeof(AUDIO_SECTION_SPEECH_CFG_T));
|
||||
|
||||
|
||||
if(res)
|
||||
{
|
||||
TRACE(2,"[%s] ERROR: res = %d", __func__, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(1,"[%s] Store speech cfg into audio section!!!", __func__);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void *load_speech_cfg_from_audio_section(void)
|
||||
{
|
||||
int res = 0;
|
||||
res = audio_section_load_cfg(AUDIO_SECTION_DEVICE_SPEECH,
|
||||
(uint8_t *)&audio_section_speech_cfg,
|
||||
sizeof(AUDIO_SECTION_SPEECH_CFG_T));
|
||||
|
||||
void *res_ptr = NULL;
|
||||
|
||||
if (res)
|
||||
{
|
||||
TRACE(2,"[%s] ERROR: res = %d", __func__, res);
|
||||
res_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(1,"[%s] Load speech cfg from audio section!!!", __func__);
|
||||
res_ptr = (void *)&audio_section_speech_cfg.cfg;
|
||||
}
|
||||
|
||||
return res_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
int speech_tuning_set_status(bool en)
|
||||
{
|
||||
speech_tuning_status = en;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool speech_tuning_get_status(void)
|
||||
{
|
||||
return speech_tuning_status;
|
||||
}
|
||||
|
||||
uint32_t speech_tuning_check(unsigned char *buf, uint32_t len)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
// Check valid
|
||||
uint32_t config_size = sizeof(SpeechConfig);
|
||||
|
||||
if (config_size != len)
|
||||
{
|
||||
TRACE(2,"[speech tuning] len(%d) != config_size(%d)", len, config_size);
|
||||
res = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(1,"[speech tuning] len(%d) is OK", len);
|
||||
//SpeechConfig POSSIBLY_UNUSED *cfg = (SpeechConfig *)buf;
|
||||
|
||||
// Test parameters
|
||||
//#if defined(SPEECH_TX_2MIC_NS2)
|
||||
// TRACE(1,"[speech tuning] TX: delay_taps(x100): %d", (int)(cfg->tx_2mic_ns2.delay_taps * 100));
|
||||
//#endif
|
||||
//#if defined(SPEECH_TX_NOISE_GATE)
|
||||
// TRACE(1,"[speech tuning] TX: data_threshold: %d", cfg->tx_noise_gate.data_threshold);
|
||||
//#endif
|
||||
//#if defined(SPEECH_TX_EQ)
|
||||
// TRACE(1,"[speech tuning] TX: eq num: %d", cfg->tx_eq.num);
|
||||
//#endif
|
||||
//#if defined(SPEECH_RX_EQ)
|
||||
// TRACE(1,"[speech tuning] RX: eq num: %d", cfg->rx_eq.num);
|
||||
//#endif
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t speech_tuning_rx_callback(unsigned char *buf, uint32_t len)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
res = speech_tuning_check(buf, len);
|
||||
|
||||
if (res)
|
||||
{
|
||||
TRACE(1,"[speech tuning] ERROR: Send check res = %d", res);
|
||||
TRACE(0,"[Speech Tuning] res : 1; info : Send len(%d) != config_size(%d);", len, sizeof(SpeechConfig));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save cfg
|
||||
speech_store_config((SpeechConfig *)buf);
|
||||
|
||||
// Set status
|
||||
speech_tuning_set_status(true);
|
||||
|
||||
TRACE(0,"[speech tuning] OK: Send cfg");
|
||||
TRACE(0,"[Speech Tuning] res : 0;");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef AUDIO_SECTION_ENABLE
|
||||
uint32_t speech_tuning_burn_rx_callback(unsigned char *buf, uint32_t len)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
|
||||
res = speech_tuning_check(buf, len);
|
||||
|
||||
if (res)
|
||||
{
|
||||
TRACE(1,"[speech tuning] ERROR: Burn check res = %d", res);
|
||||
TRACE(0,"[Speech Tuning] res : 1; info : Burn len(%d) != config_size(%d);", len, sizeof(SpeechConfig));
|
||||
}
|
||||
else
|
||||
{
|
||||
res = store_speech_cfg_into_audio_section((SpeechConfig *)buf);
|
||||
|
||||
if(res)
|
||||
{
|
||||
TRACE(1,"[speech tuning] ERROR: Store res = %d", res);
|
||||
res += 100;
|
||||
TRACE(0,"[Speech Tuning] res : 2; info : Do not enable AUDIO_SECTION_ENABLE;");
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(0,"[speech tuning] OK: Store cfg");
|
||||
TRACE(0,"[Speech Tuning] res : 0;");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
int speech_tuning_init(void)
|
||||
{
|
||||
#if defined(HAL_TRACE_RX_ENABLE) && !defined(SPEECH_TX_THIRDPARTY)
|
||||
hal_trace_rx_register("Speech Tuning", (HAL_TRACE_RX_CALLBACK_T)speech_tuning_rx_callback);
|
||||
|
||||
#ifdef AUDIO_SECTION_ENABLE
|
||||
hal_trace_rx_register("Speech Tuning Burn", (HAL_TRACE_RX_CALLBACK_T)speech_tuning_burn_rx_callback);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
speech_tuning_set_status(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speech_tuning_open(void)
|
||||
{
|
||||
#ifdef AUDIO_SECTION_ENABLE
|
||||
SpeechConfig *speech_cfg_load = NULL;
|
||||
|
||||
speech_cfg_load = (SpeechConfig *)load_speech_cfg_from_audio_section();
|
||||
|
||||
if (speech_cfg_load)
|
||||
{
|
||||
speech_store_config(speech_cfg_load);
|
||||
}
|
||||
#endif
|
||||
|
||||
speech_tuning_set_status(false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int speech_tuning_close(void)
|
||||
{
|
||||
speech_tuning_set_status(false);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __BT_SCO_CHAIN_TUNING_H__
|
||||
#define __BT_SCO_CHAIN_TUNING_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initialize this module when platform setup
|
||||
int speech_tuning_init(void);
|
||||
|
||||
// Open this module when speech stream open
|
||||
int speech_tuning_open(void);
|
||||
|
||||
// Close this module when speech stream close
|
||||
int speech_tuning_close(void);
|
||||
|
||||
bool speech_tuning_get_status(void);
|
||||
int speech_tuning_set_status(bool en);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,264 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifdef MBED
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
// Standard C Included Files
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifdef MBED
|
||||
//#include "rtos.h"
|
||||
#endif
|
||||
#ifdef MBED
|
||||
#include "SDFileSystem.h"
|
||||
#endif
|
||||
#include "cqueue.h"
|
||||
#include "hal_uart.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#include "app_audio.h"
|
||||
|
||||
|
||||
// BT
|
||||
|
||||
#if 0
|
||||
/* mutex */
|
||||
osMutexId g_voicecvsd_queue_mutex_id = NULL;
|
||||
osMutexDef(g_voicecvsd_queue_mutex);
|
||||
|
||||
/* cvsd queue */
|
||||
#define VOICECVSD_TEMP_BUFFER_SIZE 128
|
||||
#define VOICECVSD_QUEUE_SIZE (VOICECVSD_TEMP_BUFFER_SIZE*20)
|
||||
CQueue voicecvsd_queue;
|
||||
|
||||
static enum APP_AUDIO_CACHE_T voicecvsd_cache_status = APP_AUDIO_CACHE_QTY;
|
||||
|
||||
#define LOCK_VOICECVSD_QUEUE() \
|
||||
osMutexWait(g_voicecvsd_queue_mutex_id, osWaitForever)
|
||||
|
||||
#define UNLOCK_VOICECVSD_QUEUE() \
|
||||
osMutexRelease(g_voicecvsd_queue_mutex_id)
|
||||
|
||||
void xLOCK_VOICECVSD_QUEUE(void)
|
||||
{
|
||||
osMutexWait(g_voicecvsd_queue_mutex_id, osWaitForever);
|
||||
}
|
||||
|
||||
void xUNLOCK_VOICECVSD_QUEUE(void)
|
||||
{
|
||||
osMutexRelease(g_voicecvsd_queue_mutex_id);
|
||||
}
|
||||
|
||||
//static void dump_buffer_to_psram(char *buf, unsigned int len)
|
||||
//{
|
||||
// static unsigned int offset = 0;
|
||||
// memcpy((void *)(0x1c000000 + offset), buf, len);
|
||||
//}
|
||||
|
||||
static void copy_one_trace_to_two_track_16bits(uint16_t *src_buf, uint16_t *dst_buf, uint32_t src_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < src_len; ++i) {
|
||||
dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
int store_voicecvsd_buffer(unsigned char *buf, unsigned int len)
|
||||
{
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
EnCQueue(&voicecvsd_queue, buf, len);
|
||||
#if 0
|
||||
dump_buffer_to_psram((char *)buf, len);
|
||||
TRACE(1,"%d\n", LengthOfCQueue(&voicecvsd_queue));
|
||||
#endif
|
||||
if (LengthOfCQueue(&voicecvsd_queue) > VOICECVSD_TEMP_BUFFER_SIZE*10) {
|
||||
voicecvsd_cache_status = APP_AUDIO_CACHE_OK;
|
||||
}
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int store_voice_pcm2cvsd(unsigned char *buf, unsigned int len)
|
||||
{
|
||||
uint8_t cvsdtmpbuffer[VOICECVSD_TEMP_BUFFER_SIZE];
|
||||
|
||||
short * pBuffProcessed = (short *)buf;
|
||||
uint32_t processed_len = 0;
|
||||
uint32_t remain_len = 0;
|
||||
|
||||
len >>= 1;
|
||||
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
while(processed_len < len){
|
||||
remain_len = len-processed_len;
|
||||
if (remain_len>VOICECVSD_TEMP_BUFFER_SIZE){
|
||||
Pcm8kToCvsd(pBuffProcessed + processed_len, cvsdtmpbuffer, VOICECVSD_TEMP_BUFFER_SIZE);
|
||||
EnCQueue(&voicecvsd_queue, cvsdtmpbuffer, VOICECVSD_TEMP_BUFFER_SIZE);
|
||||
processed_len += VOICECVSD_TEMP_BUFFER_SIZE;
|
||||
}else{
|
||||
Pcm8kToCvsd(pBuffProcessed + processed_len, cvsdtmpbuffer, remain_len);
|
||||
EnCQueue(&voicecvsd_queue, cvsdtmpbuffer, remain_len);
|
||||
processed_len += remain_len;
|
||||
}
|
||||
}
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
|
||||
#if 0
|
||||
dump_buffer_to_psram((char *)buf, len);
|
||||
TRACE(1,"%d\n", LengthOfCQueue(&voicecvsd_queue));
|
||||
#endif
|
||||
if (LengthOfCQueue(&voicecvsd_queue) > VOICECVSD_TEMP_BUFFER_SIZE*10) {
|
||||
voicecvsd_cache_status = APP_AUDIO_CACHE_OK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_voicecvsd_buffer_size(void)
|
||||
{
|
||||
int n;
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
n = LengthOfCQueue(&voicecvsd_queue);
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
return n;
|
||||
}
|
||||
|
||||
static short tmp_decode_buf[VOICECVSD_TEMP_BUFFER_SIZE*2];
|
||||
int decode_cvsd_frame(unsigned char *pcm_buffer, unsigned int pcm_len)
|
||||
{
|
||||
uint32_t r = 0, decode_len = 0;
|
||||
unsigned char *e1 = NULL, *e2 = NULL;
|
||||
unsigned int len1 = 0, len2 = 0;
|
||||
|
||||
while (decode_len < pcm_len) {
|
||||
get_again:
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
len1 = len2 = 0;
|
||||
r = PeekCQueue(&voicecvsd_queue, VOICECVSD_TEMP_BUFFER_SIZE, &e1, &len1, &e2, &len2);
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
|
||||
if(r == CQ_ERR || len1 == 0) {
|
||||
//return 0;
|
||||
Thread::wait(4);
|
||||
goto get_again;
|
||||
}
|
||||
|
||||
if (len1 != 0) {
|
||||
//CvsdToPcm8k(e1, (short *)(pcm_buffer + decode_len*4), len1, 0);
|
||||
CvsdToPcm8k(e1, (short *)(tmp_decode_buf), len1, 0);
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)tmp_decode_buf, (uint16_t *)(pcm_buffer + decode_len), len1);
|
||||
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
DeCQueue(&voicecvsd_queue, 0, len1);
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
|
||||
decode_len += len1*4;
|
||||
}
|
||||
|
||||
if (len2 != 0) {
|
||||
//CvsdToPcm8k(e2, (short *)(pcm_buffer + decode_len*4), len2, 0);
|
||||
CvsdToPcm8k(e2, (short *)(tmp_decode_buf), len2, 0);
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)tmp_decode_buf, (uint16_t *)(pcm_buffer + decode_len), len2);
|
||||
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
DeCQueue(&voicecvsd_queue, 0, len2);
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
|
||||
decode_len += len2*4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t decode_cvsd_frame_noblock(uint8_t *pcm_buffer, uint32_t pcm_len)
|
||||
{
|
||||
unsigned int len[2];
|
||||
uint8_t *e[2];
|
||||
uint32_t decode_len = 0;
|
||||
|
||||
LOCK_VOICECVSD_QUEUE();
|
||||
while (decode_len < pcm_len)
|
||||
{
|
||||
len[0] = len[1] = 0;
|
||||
e[0] = e[1] = NULL;
|
||||
|
||||
if(PeekCQueue(&voicecvsd_queue, VOICECVSD_TEMP_BUFFER_SIZE, &e[0], &len[0], &e[1], &len[1]) == CQ_OK)
|
||||
{
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
{
|
||||
if (len[i] != 0)
|
||||
{
|
||||
CvsdToPcm8k(e[i], (short *)(tmp_decode_buf), len[i], 0);
|
||||
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)tmp_decode_buf, (uint16_t *)(pcm_buffer + decode_len), len[i]);
|
||||
|
||||
DeCQueue(&voicecvsd_queue, 0, len[i]);
|
||||
|
||||
decode_len += len[i]*4;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
UNLOCK_VOICECVSD_QUEUE();
|
||||
return decode_len;
|
||||
}
|
||||
|
||||
uint32_t voicecvsd_audio_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t l = 0;
|
||||
uint32_t cur_ticks = 0, ticks = 0;
|
||||
|
||||
if (voicecvsd_cache_status == APP_AUDIO_CACHE_CACHEING)
|
||||
return 0;
|
||||
|
||||
TRACE(2,"%s enter reamin:%d", __func__, LengthOfCQueue(&voicecvsd_queue));
|
||||
|
||||
ticks = hal_sys_timer_get();
|
||||
l = decode_cvsd_frame_noblock(buf, len);
|
||||
cur_ticks = hal_sys_timer_get();
|
||||
TRACE(3,"%s exit reamin:%d spend:%d\n", __func__, LengthOfCQueue(&voicecvsd_queue) ,TICKS_TO_MS(cur_ticks-ticks));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int voicecvsd_audio_init(void)
|
||||
{
|
||||
uint8_t *buff = NULL;
|
||||
|
||||
app_audio_mempool_get_buff(&buff, VOICECVSD_QUEUE_SIZE);
|
||||
memset(buff, 0, VOICECVSD_QUEUE_SIZE);
|
||||
|
||||
/* voicebtpcm_pcm queue*/
|
||||
APP_AUDIO_InitCQueue(&voicecvsd_queue, VOICECVSD_QUEUE_SIZE, buff);
|
||||
|
||||
Pcm8k_CvsdInit();
|
||||
if (g_voicecvsd_queue_mutex_id == NULL)
|
||||
{
|
||||
g_voicecvsd_queue_mutex_id = osMutexCreate((osMutex(g_voicecvsd_queue_mutex)));
|
||||
}
|
||||
|
||||
voicecvsd_cache_status = APP_AUDIO_CACHE_CACHEING;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,47 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "cqueue.h"
|
||||
#include "hal_uart.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
|
||||
uint8_t digmic_buf[100*1024];
|
||||
uint32_t digmic_buf_len = 0;
|
||||
|
||||
uint32_t dig_mic_audio_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
TRACE(2,"%s:%d\n", __func__, __LINE__);
|
||||
memcpy(buf, digmic_buf, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
uint32_t dig_mic_audio_data_come(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
TRACE(2,"%s:%d\n", __func__, __LINE__);
|
||||
|
||||
memcpy(digmic_buf + digmic_buf_len, buf, len);
|
||||
|
||||
#if 1
|
||||
digmic_buf_len = (digmic_buf_len + len)%(100*1024);
|
||||
#endif
|
||||
return len;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "cqueue.h"
|
||||
#include "hal_uart.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#ifdef RTOS
|
||||
#include "cmsis_os.h"
|
||||
#endif
|
||||
|
||||
/* mutex */
|
||||
osMutexId g_flac_queue_mutex_id;
|
||||
osMutexDef(g_flac_queue_mutex);
|
||||
|
||||
/* flac queue */
|
||||
#define FLAC_TEMP_BUFFER_SIZE 2048
|
||||
#define FLAC_QUEUE_SIZE (FLAC_TEMP_BUFFER_SIZE*4)
|
||||
unsigned char flac_queue_buf[FLAC_QUEUE_SIZE];
|
||||
CQueue flac_queue;
|
||||
static uint32_t ok_to_decode = 0;
|
||||
|
||||
#define LOCK_FLAC_QUEUE() \
|
||||
osMutexWait(g_flac_queue_mutex_id, osWaitForever)
|
||||
|
||||
#define UNLOCK_FLAC_QUEUE() \
|
||||
osMutexRelease(g_flac_queue_mutex_id)
|
||||
|
||||
static void copy_one_trace_to_two_track_16bits(uint16_t *src_buf, uint16_t *dst_buf, uint32_t src_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < src_len; ++i) {
|
||||
dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
int store_flac_buffer(unsigned char *buf, unsigned int len)
|
||||
{
|
||||
LOCK_FLAC_QUEUE();
|
||||
EnCQueue(&flac_queue, buf, len);
|
||||
if (LengthOfCQueue(&flac_queue) > FLAC_TEMP_BUFFER_SIZE*2) {
|
||||
ok_to_decode = 1;
|
||||
}
|
||||
UNLOCK_FLAC_QUEUE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int decode_flac_frame(unsigned char *pcm_buffer, unsigned int pcm_len)
|
||||
{
|
||||
uint32_t r = 0, got_len = 0;
|
||||
unsigned char *e1 = NULL, *e2 = NULL;
|
||||
unsigned int len1 = 0, len2 = 0;
|
||||
get_again:
|
||||
LOCK_FLAC_QUEUE();
|
||||
r = PeekCQueue(&flac_queue, (pcm_len - got_len)/2, &e1, &len1, &e2, &len2);
|
||||
UNLOCK_FLAC_QUEUE();
|
||||
|
||||
if(r == CQ_ERR || len1 == 0) {
|
||||
osDelay(2);
|
||||
goto get_again;
|
||||
}
|
||||
|
||||
//memcpy(pcm_buffer + got_len, e1, len1);
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)e1, (uint16_t *)(pcm_buffer + got_len), len1/2);
|
||||
|
||||
LOCK_FLAC_QUEUE();
|
||||
DeCQueue(&flac_queue, 0, len1);
|
||||
UNLOCK_FLAC_QUEUE();
|
||||
|
||||
got_len += len1*2;
|
||||
|
||||
if (len2 != 0) {
|
||||
//memcpy(pcm_buffer + got_len, e2, len2);
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)e2, (uint16_t *)(pcm_buffer + got_len), len2/2);
|
||||
|
||||
LOCK_FLAC_QUEUE();
|
||||
DeCQueue(&flac_queue, 0, len2);
|
||||
UNLOCK_FLAC_QUEUE();
|
||||
}
|
||||
|
||||
got_len += len2*2;
|
||||
|
||||
if (got_len < pcm_len)
|
||||
goto get_again;
|
||||
|
||||
return pcm_len;
|
||||
}
|
||||
|
||||
uint32_t flac_audio_data_come(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
TRACE(1,"data come %d\n", len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t flac_audio_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t l = 0;
|
||||
//uint32_t cur_ticks = 0, ticks = 0;
|
||||
|
||||
if (ok_to_decode == 0)
|
||||
return 0;
|
||||
|
||||
//ticks = hal_sys_timer_get();
|
||||
l = decode_flac_frame(buf, len);
|
||||
//cur_ticks = hal_sys_timer_get();
|
||||
// TRACE(1,"flac %d t\n", (cur_ticks-ticks));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int flac_audio_init(void)
|
||||
{
|
||||
g_flac_queue_mutex_id = osMutexCreate((osMutex(g_flac_queue_mutex)));
|
||||
/* flac queue*/
|
||||
InitCQueue(&flac_queue, FLAC_QUEUE_SIZE, (unsigned char *)&flac_queue_buf);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,529 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifdef CHIP_BEST1000
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_trace.h"
|
||||
#include "fmdec.h"
|
||||
#include "hal_dma.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_cmu.h"
|
||||
#include "hal_analogif.h"
|
||||
#include "hal_chipid.h"
|
||||
#include "audioflinger.h"
|
||||
#include "audiobuffer.h"
|
||||
#include "cqueue.h"
|
||||
#include "app_audio.h"
|
||||
#include "app_utils.h"
|
||||
#include "app_overlay.h"
|
||||
#include "string.h"
|
||||
#include "pmu.h"
|
||||
|
||||
//#define FM_DEBUG 1
|
||||
|
||||
#define FM_DIGITAL_REG(a) *(volatile uint32_t *)(a)
|
||||
#define fm_read_rf_reg(reg,val) hal_analogif_reg_read(reg,val)
|
||||
#define fm_write_rf_reg(reg,val) hal_analogif_reg_write(reg,val)
|
||||
|
||||
#define FM_FRAME_NUM 4
|
||||
#define FM_SAMPLE_NUM NUMOFSAMPLE
|
||||
|
||||
#ifdef ATAN2_HARDWARE
|
||||
#ifdef FM_NEWMODE
|
||||
#define FM_SAMPLE_BUFFER_SIZE (FM_FRAME_NUM*FM_SAMPLE_NUM*4)
|
||||
#else
|
||||
#define FM_SAMPLE_BUFFER_SIZE (FM_FRAME_NUM*FM_SAMPLE_NUM/2*4)
|
||||
#endif
|
||||
#else
|
||||
#define FM_SAMPLE_BUFFER_SIZE (FM_FRAME_NUM*FM_SAMPLE_NUM*4)
|
||||
#endif
|
||||
#define FM_AUDIO_BUFFER_SIZE (4096)
|
||||
|
||||
extern int app_bt_stream_local_volume_get(void);
|
||||
static int32_t *fm_sample_buffer_p;
|
||||
|
||||
static void fm_handler(uint8_t chan, uint32_t remains, uint32_t error, struct HAL_DMA_DESC_T *lli)
|
||||
{
|
||||
static int cnt = 0;
|
||||
int16_t fm_decbuf[(FM_SAMPLE_NUM/9)];
|
||||
FmDemodulate((int16_t *)(fm_sample_buffer_p +((cnt%FM_FRAME_NUM)*FM_SAMPLE_NUM)), fm_decbuf,FM_SAMPLE_NUM);
|
||||
cnt++;
|
||||
app_audio_pcmbuff_put((uint8_t *)fm_decbuf, (FM_SAMPLE_NUM/9)<<1);
|
||||
FmDemodulate((int16_t *)(fm_sample_buffer_p +((cnt%FM_FRAME_NUM)*FM_SAMPLE_NUM)), fm_decbuf,FM_SAMPLE_NUM);
|
||||
cnt++;
|
||||
app_audio_pcmbuff_put((uint8_t *)fm_decbuf, (FM_SAMPLE_NUM/9)<<1);
|
||||
|
||||
#ifdef FM_DEBUG
|
||||
{
|
||||
static uint32_t preTicks;
|
||||
uint32_t diff_ticks = 0;
|
||||
uint32_t cur_ticks;
|
||||
|
||||
cur_ticks = hal_sys_timer_get();
|
||||
if (!preTicks){
|
||||
preTicks = cur_ticks;
|
||||
}else{
|
||||
diff_ticks = TICKS_TO_MS(cur_ticks - preTicks);
|
||||
preTicks = cur_ticks;
|
||||
}
|
||||
TRACE(3,"[fm_handler] diff=%d add:%d remain:%d input", diff_ticks, (FM_SAMPLE_NUM/9)<<1, app_audio_pcmbuff_length());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t fm_pcm_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
app_audio_pcmbuff_get(buf, len);
|
||||
#ifdef FM_DEBUG
|
||||
{
|
||||
static uint32_t preTicks;
|
||||
uint32_t diff_ticks = 0;
|
||||
uint32_t cur_ticks= hal_sys_timer_get();
|
||||
if (!preTicks){
|
||||
preTicks = cur_ticks;
|
||||
}else{
|
||||
diff_ticks = TICKS_TO_MS(cur_ticks - preTicks);
|
||||
preTicks = cur_ticks;
|
||||
}
|
||||
|
||||
TRACE(5,"[fm_pcm_more_data] diff=%d get:%d remain:%d output isr:0x%08x cnt:%d", diff_ticks, len/2, app_audio_pcmbuff_length(), FM_DIGITAL_REG(0x40160020), FM_DIGITAL_REG(0x40160028));
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t fm_capture_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
fm_handler(0,0,0,NULL);
|
||||
return len;
|
||||
}
|
||||
|
||||
void fm_radio_digit_init(void)
|
||||
{
|
||||
FM_DIGITAL_REG(0xd0350244) = (FM_DIGITAL_REG(0xd0350244) & ~0x01fff) | 0x20f; //-890k -> 0 if_shift, for 110.5292m adc
|
||||
|
||||
// FM_DIGITAL_REG(0x40180e0c) = 0x34;
|
||||
//FM_DIGITAL_REG(0x4000a050) = (FM_DIGITAL_REG(0x4000a050) & ~0x18000) | 0x18000;
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef ATAN2_HARDWARE
|
||||
|
||||
|
||||
FM_DIGITAL_REG(0xd0330038) |= (1 << 11);
|
||||
FM_DIGITAL_REG(0xd0330038) |= (1 << 17);
|
||||
FM_DIGITAL_REG(0xd0350248) = 0x80c00000;
|
||||
// FM_DIGITAL_REG(0x40160030) = 1;
|
||||
// FM_DIGITAL_REG(0x40160000) = 0x21;
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
|
||||
FM_DIGITAL_REG(0xd0330038) |= (1 << 11);
|
||||
FM_DIGITAL_REG(0xd0350248) = 0x80c00000;
|
||||
// FM_DIGITAL_REG(0x40160030) = 1;
|
||||
// FM_DIGITAL_REG(0x40160000) = 1;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef SINGLECHANLE
|
||||
//0x4000a010 bit2 写0 单channel dac
|
||||
FM_DIGITAL_REG(0x4000a010) = (1 << 5) |(1<<4);
|
||||
#else
|
||||
|
||||
FM_DIGITAL_REG(0x4000a010) = (1 << 5) | (1 << 2)|(1<<4);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
FM_DIGITAL_REG(0x4000a020) = ~0UL;
|
||||
FM_DIGITAL_REG(0x4000a02c) = 4;
|
||||
FM_DIGITAL_REG(0x4000a030) = 4;
|
||||
|
||||
FM_DIGITAL_REG(0x4000a034) = (1 << 2) | (1 << 1) | (1 << 0);
|
||||
|
||||
// Start DAC
|
||||
// FM_DIGITAL_REG(0x4000a010) |= (1 << 1);
|
||||
|
||||
#if 0
|
||||
//52M
|
||||
FM_DIGITAL_REG(0x40000060) |= (1 << 21);
|
||||
|
||||
|
||||
FM_DIGITAL_REG(0x40000060) |= (1 << 24);
|
||||
FM_DIGITAL_REG(0x40000060) |= (1 << 27);
|
||||
FM_DIGITAL_REG(0x40000060) =(FM_DIGITAL_REG(0x40000060) & ~ (1 << 20));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FM_DIGITAL_REG(0x40000060) |= (1 << 29);
|
||||
// FM_DIGITAL_REG(0x40000060) |= (1 << 27);
|
||||
FM_DIGITAL_REG(0x40000064) = (FM_DIGITAL_REG(0x40000064) & ~0xFF) | 0x7A | (1 << 10) | (1<<30);
|
||||
#endif
|
||||
|
||||
FM_DIGITAL_REG(0x4000a040) = 0xc0810000;
|
||||
FM_DIGITAL_REG(0x4000a044) = 0x08040c04;
|
||||
FM_DIGITAL_REG(0x4000a048) = 0x0e01f268;
|
||||
FM_DIGITAL_REG(0x4000a04c) = 0x00005100;
|
||||
// FM_DIGITAL_REG(0x40010010) = 0;
|
||||
// FM_DIGITAL_REG(0x40010014) = 0x03a80005;
|
||||
//FM_DIGITAL_REG(0x40010018) = 0x00200019;
|
||||
FM_DIGITAL_REG(0x4000a050) = 0x24200000; //for adc_div_3_6 bypass
|
||||
FM_DIGITAL_REG(0x4000a050) = (FM_DIGITAL_REG(0x4000a050) & ~0x780) | 0x380; // for channel 1 adc volume, bit10~7
|
||||
FM_DIGITAL_REG(0x4000a050) = (FM_DIGITAL_REG(0x4000a050) & ~0x18000) | 0x18000; // for dual channel adc/dac
|
||||
|
||||
#ifdef SINGLECHANLE
|
||||
//0x4000a050 bit16 写0 单channel dac for codec
|
||||
FM_DIGITAL_REG(0x4000a050) =(FM_DIGITAL_REG(0x4000a050) & ~ (1 << 16));
|
||||
#endif
|
||||
|
||||
|
||||
FM_DIGITAL_REG(0x4000a048) = (FM_DIGITAL_REG(0x4000a048) & ~0x00000f00) | 0x40000900; //set for sdm gain
|
||||
FM_DIGITAL_REG(0x4000a044) = (FM_DIGITAL_REG(0x4000a044) & ~0x60000000) | 0x60000000; //for adc en, and dac en
|
||||
|
||||
// Start DAC
|
||||
FM_DIGITAL_REG(0x4000a010) |= (1 << 1);
|
||||
|
||||
|
||||
|
||||
// Delay 2 ms
|
||||
// for (volatile int kk = 0; kk < 1000/64; kk++);
|
||||
osDelay(2);
|
||||
|
||||
//hal_sys_timer_delay(MS_TO_TICKS(2));
|
||||
// Start ADC
|
||||
// FM_DIGITAL_REG(0x4000a010) |= (1 << 0);
|
||||
|
||||
|
||||
#ifdef ATAN2_HARDWARE
|
||||
|
||||
|
||||
#ifdef FM_NEWMODE
|
||||
FM_DIGITAL_REG(0x40160030) = 1;
|
||||
FM_DIGITAL_REG(0x40160000) = 0x1;
|
||||
|
||||
#else
|
||||
FM_DIGITAL_REG(0x40160030) = 1;
|
||||
FM_DIGITAL_REG(0x40160000) = 0x21;
|
||||
#endif
|
||||
|
||||
#else
|
||||
//start FM
|
||||
FM_DIGITAL_REG(0x40160030) = 1;
|
||||
FM_DIGITAL_REG(0x40160000) =1;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int fm_radio_analog_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// fm initial
|
||||
rfspi_wvalue( 8'h2c , 16'b0111_0000_0101_1100 ) ; // dig_vtoi_en
|
||||
rfspi_wvalue( 8'h01 , 16'b1010_1101_1111_1111 ) ; // power on fm lna
|
||||
rfspi_wvalue( 8'h02 , 16'b1000_0000_1001_0100 ) ; // reg_fm_lna_pu_mixersw
|
||||
|
||||
rfspi_wvalue( 8'h1a , 16'b0101_0000_1011_0000 ) ; // reg_bt_vco_fm_buff_vctrl_dr=1
|
||||
|
||||
rfspi_wvalue( 8'h18 , 16'b0000_0110_1000_0000 ) ; // power on vco
|
||||
|
||||
rfspi_wvalue( 8'h19 , 16'b0110_0100_0100_0000 ) ; // reg_bt_vco_fm_buff_vctrl
|
||||
rfspi_wvalue( 8'h1d , 16'b0111_1000_1010_0100 ) ; // reg_bt_rfpll_pu_dr
|
||||
rfspi_wvalue( 8'h1c , 16'b0000_0000_1100_1000 ) ; // reg_bt_vco_fm_lo_en reg_bt_vco_fm_div_ctrl=8
|
||||
|
||||
rfspi_wvalue( 8'h0a , 16'b0001_0010_0010_1111 ) ; // reg_btfm_flt_fm_en
|
||||
|
||||
rfspi_wvalue( 8'h2d , 16'b0000_0111_1000_0010 ) ; // bb ldo on reg_bb_ldo_pu_vddr15a_dr
|
||||
rfspi_wvalue( 8'h07 , 16'b0000_0010_1011_1001 ) ; // reg_btfm_flt_pu_dr
|
||||
|
||||
rfspi_wvalue( 8'h2a , 16'b0001_0110_1100_0000 ) ; // reg_bt_rfpll_sdm_freq_dr
|
||||
rfspi_wvalue( 8'h26 , 16'b0000_0000_0000_0000 ) ; // vco freq[31:16] ( 2400 + x )*2^25/26MHZ*N (2400+x= frf)
|
||||
rfspi_wvalue( 8'h25 , 16'b0000_0000_0000_0000 ) ; // vco freq[15:00] fm_freq = frf/(4*reg_bt_vco_fm_div_ctrl)
|
||||
rfspi_wvalue( 8'h17 , 16'b1000_0000_0000_0000 ) ; // reg_bt_vco_calen
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
fm_write_rf_reg( 0x2c , 0b0111000001011100 ) ; // dig_vtoi_en
|
||||
fm_write_rf_reg( 0x01 , 0b1010110111111111 ) ; // power on fm lna
|
||||
fm_write_rf_reg( 0x02 , 0b1000000010010100 ) ; // reg_fm_lna_pu_mixersw
|
||||
|
||||
fm_write_rf_reg( 0x1a , 0b0101000010110000 ) ; // reg_bt_vco_fm_buff_vctrl_dr=1
|
||||
|
||||
fm_write_rf_reg( 0x18 , 0b0000011010000000 ) ; // power on vco
|
||||
|
||||
fm_write_rf_reg( 0x19 , 0b0110010001000000 ) ; // reg_bt_vco_fm_buff_vctrl
|
||||
fm_write_rf_reg( 0x1d , 0b0111100010100100 ) ; // reg_bt_rfpll_pu_dr
|
||||
fm_write_rf_reg( 0x1c , 0b0000000011001000 ) ; // reg_bt_vco_fm_lo_en reg_bt_vco_fm_div_ctrl=8
|
||||
|
||||
fm_write_rf_reg( 0x0a , 0b0001001000101111 ) ; // reg_btfm_flt_fm_en
|
||||
|
||||
fm_write_rf_reg( 0x2d , 0b0000011110000010 ) ; // bb ldo on reg_bb_ldo_pu_vddr15a_dr
|
||||
fm_write_rf_reg( 0x07 , 0b0000001010111001 ) ; // reg_btfm_flt_pu_dr
|
||||
|
||||
fm_write_rf_reg( 0x2a , 0b0001011011000000 ) ; // reg_bt_rfpll_sdm_freq_dr
|
||||
fm_write_rf_reg( 0x26 , 0b0000000000000000 ) ; // vco freq[31:16] ( 2400 + x )*2^25/26MHZ*N (2400+x= frf)
|
||||
fm_write_rf_reg( 0x25 , 0b0000000000000000 ) ; // vco freq[15:00] fm_freq = frf/(4*reg_bt_vco_fm_div_ctrl)
|
||||
fm_write_rf_reg( 0x17 , 0b1000000000000000 ) ; // reg_bt_vco_calen
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//adc也要开的话,需要配 cmu
|
||||
//0x40000060[29] = 1 最好先读再写,否则把别的bit冲掉了。
|
||||
|
||||
|
||||
|
||||
|
||||
//需要配置的spi寄存器:ana interface:
|
||||
|
||||
//0x05 = 0xFCB1 // Audio Pll
|
||||
//0x06 = 0x881C
|
||||
//0x31 = 0x0100 // audio_freq_en
|
||||
//0x37 = 0x1000 // codec_bbpll1_fm_adc_clk_en
|
||||
//0x31 = 0x0130 // codec_tx_en_ldac codec_tx_en_rdac
|
||||
|
||||
|
||||
ret = fm_write_rf_reg(0x05 , 0xfcb1);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = fm_write_rf_reg(0x06 , 0x881c);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fm_write_rf_reg(0x3a , 0xe644);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = fm_write_rf_reg(0x31 , 0x0100);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = fm_write_rf_reg(0x37 , 0x1000);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = fm_write_rf_reg(0x31 , 0x01f0);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//delay 32ms
|
||||
osDelay(32);
|
||||
|
||||
|
||||
ret = fm_write_rf_reg(0x31 , 0x0130);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
//[FM_RX]
|
||||
fm_write_rf_reg(0x01,0x91ff); //pu fm
|
||||
fm_write_rf_reg(0x2d,0x07fa); //ldo on
|
||||
fm_write_rf_reg(0x2e,0x6aaa); //tune fm filter IF
|
||||
fm_write_rf_reg(0x02,0xe694);
|
||||
fm_write_rf_reg(0x03,0xfe3a);
|
||||
fm_write_rf_reg(0x04,0x52a8);
|
||||
fm_write_rf_reg(0x07,0x02b9);
|
||||
fm_write_rf_reg(0x0a,0x1a2c);
|
||||
fm_write_rf_reg(0x0b,0x402b);
|
||||
fm_write_rf_reg(0x0c,0x7584);
|
||||
fm_write_rf_reg(0x0e,0x0000);
|
||||
fm_write_rf_reg(0x0f,0x2e18);
|
||||
fm_write_rf_reg(0x10,0x02b4);
|
||||
fm_write_rf_reg(0x13,0x0a48);
|
||||
|
||||
//[vco init]
|
||||
fm_write_rf_reg(0x18,0x077f);
|
||||
fm_write_rf_reg(0x19,0x3ff8);
|
||||
fm_write_rf_reg(0x1a,0xc090);
|
||||
fm_write_rf_reg(0x1b,0x0f88);
|
||||
fm_write_rf_reg(0x1c,0x04c6); //[3:0] 5,6,7,8 --> vco/2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fm_radio_poweron(void)
|
||||
|
||||
{
|
||||
hal_cmu_reset_clear(HAL_CMU_MOD_BTCPU);
|
||||
osDelay(2000);
|
||||
|
||||
{
|
||||
//wakp interface
|
||||
unsigned short read_val;
|
||||
|
||||
fm_read_rf_reg(0x50, &read_val);
|
||||
}
|
||||
|
||||
pmu_fm_config(1);
|
||||
|
||||
fm_write_rf_reg(0x0c, 0x3584);
|
||||
if(hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_2 || hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_3) ////
|
||||
{
|
||||
FM_DIGITAL_REG(0xc00003b4)=0x00060020;//turn off bt sleep
|
||||
}
|
||||
else if(hal_get_chip_metal_id() == HAL_CHIP_METAL_ID_4)
|
||||
{
|
||||
FM_DIGITAL_REG(0xc00003b0)=0x00060020;//turn off bt sleep
|
||||
}
|
||||
else
|
||||
{
|
||||
FM_DIGITAL_REG(0xc00003ac)=0x00060020;//turn off bt sleep
|
||||
}
|
||||
FM_DIGITAL_REG(0xd0330038) = 0x00008D0D;
|
||||
FM_DIGITAL_REG(0xd0340020)=0x010E01C0;// open ana rxon for open adc clk
|
||||
//fm_write_rf_reg(0x02, 0xe694);
|
||||
}
|
||||
|
||||
void* fm_radio_get_ext_buff(int size)
|
||||
{
|
||||
uint8_t *pBuff = NULL;
|
||||
size = size+size%4;
|
||||
app_audio_mempool_get_buff(&pBuff, size);
|
||||
return (void*)pBuff;
|
||||
}
|
||||
|
||||
int fm_radio_player(bool on)
|
||||
{
|
||||
static struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
static bool isRun = false;
|
||||
uint8_t *buff = NULL;
|
||||
|
||||
TRACE(2,"fm_radio_player work:%d op:%d", isRun, on);
|
||||
if (isRun==on)
|
||||
return 0;
|
||||
|
||||
if (on){
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
|
||||
app_audio_mempool_init();
|
||||
fm_radio_poweron();
|
||||
fm_radio_analog_init();
|
||||
fm_radio_digit_init();
|
||||
osDelay(200);
|
||||
buff = (uint8_t *)fm_radio_get_ext_buff(FM_AUDIO_BUFFER_SIZE*2);
|
||||
app_audio_pcmbuff_init(buff, FM_AUDIO_BUFFER_SIZE*2);
|
||||
fm_sample_buffer_p = (int32_t *)fm_radio_get_ext_buff(FM_SAMPLE_BUFFER_SIZE);
|
||||
#if FPGA==0
|
||||
app_overlay_select(APP_OVERLAY_FM);
|
||||
#endif
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
stream_cfg.vol = app_bt_stream_local_volume_get();
|
||||
stream_cfg.handler = fm_capture_more_data;
|
||||
stream_cfg.data_ptr = (uint8_t *)fm_sample_buffer_p;
|
||||
stream_cfg.data_size = FM_SAMPLE_BUFFER_SIZE;
|
||||
stream_cfg.device = AUD_STREAM_USE_DPD_RX;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
buff = (uint8_t *)fm_radio_get_ext_buff(FM_AUDIO_BUFFER_SIZE);
|
||||
stream_cfg.bits = AUD_BITS_16;
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
||||
stream_cfg.sample_rate = AUD_SAMPRATE_48000;
|
||||
#if FPGA==0
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
#else
|
||||
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
||||
#endif
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
stream_cfg.vol = app_bt_stream_local_volume_get();
|
||||
stream_cfg.handler = fm_pcm_more_data;
|
||||
stream_cfg.data_ptr = buff;
|
||||
stream_cfg.data_size = FM_AUDIO_BUFFER_SIZE;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
|
||||
}else{
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
||||
}
|
||||
|
||||
isRun=on;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fm_tune(uint32_t freqkhz)
|
||||
{
|
||||
uint32_t reg;
|
||||
unsigned long long tmp = 0;
|
||||
|
||||
|
||||
//[rfpll_cal]
|
||||
fm_write_rf_reg(0x21,0x3979); // ref sel 52MHz
|
||||
fm_write_rf_reg(0x22,0x7A22); // doubler setting
|
||||
fm_write_rf_reg(0x23,0x0380);
|
||||
fm_write_rf_reg(0x2b,0x32a0); // sdm
|
||||
fm_write_rf_reg(0x2a,0x12d1); // cal ini
|
||||
|
||||
//(freq(Mhz)-0.89(Mhz))*(2^28)*3/26
|
||||
tmp = freqkhz;
|
||||
reg =(((tmp-890))<<27)*3/13/1000;
|
||||
|
||||
fm_write_rf_reg(0x25, (reg&0xffff0000)>>16);
|
||||
fm_write_rf_reg(0x26, reg&0x0000ffff);
|
||||
|
||||
fm_write_rf_reg(0x1d,0x58e4); // pll_cal_en
|
||||
fm_write_rf_reg(0xf7,0x5597); // rst and enable pll_cal clk
|
||||
fm_write_rf_reg(0xf7,0x55d7); // rst and enable pll_cal clk
|
||||
fm_write_rf_reg(0x1d,0x7ae4); // pll cal start
|
||||
fm_write_rf_reg(0xff,0x0000); // wait 100us
|
||||
|
||||
osDelay(20);
|
||||
|
||||
|
||||
fm_write_rf_reg(0x1d,0x7ac4); // close pll loop
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fm_test_main(void)
|
||||
{
|
||||
fm_radio_player(true);
|
||||
osDelay(20);
|
||||
fm_tune(90500);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_AUDIO_H__
|
||||
#define __FMRADIO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int fm_radio_player(bool on);
|
||||
|
||||
void fm_tune(uint32_t freqkhz);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__FMRADIO_H__
|
|
@ -0,0 +1,152 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "cmsis_os.h"
|
||||
#include "cqueue.h"
|
||||
#include "hal_uart.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
|
||||
// BT
|
||||
|
||||
|
||||
#if 0
|
||||
/* mutex */
|
||||
osMutexId g_voicemsbc_queue_mutex_id;
|
||||
osMutexDef(g_voicemsbc_queue_mutex);
|
||||
|
||||
/* msbc queue */
|
||||
#define VOICEMSBC_TEMP_BUFFER_SIZE 128
|
||||
#define VOICEMSBC_QUEUE_SIZE (VOICEMSBC_TEMP_BUFFER_SIZE*100)
|
||||
unsigned char voicemsbc_queue_buf[VOICEMSBC_QUEUE_SIZE];
|
||||
CQueue voicemsbc_queue;
|
||||
static uint32_t ok_to_decode = 0;
|
||||
|
||||
#define LOCK_VOICEMSBC_QUEUE() \
|
||||
osMutexWait(g_voicemsbc_queue_mutex_id, osWaitForever)
|
||||
|
||||
#define UNLOCK_VOICEMSBC_QUEUE() \
|
||||
osMutexRelease(g_voicemsbc_queue_mutex_id)
|
||||
|
||||
static void dump_buffer_to_psram(char *buf, unsigned int len)
|
||||
{
|
||||
static unsigned int offset = 0;
|
||||
memcpy((void *)(0x1c000000 + offset), buf, len);
|
||||
}
|
||||
|
||||
static void copy_one_trace_to_two_track_16bits(uint16_t *src_buf, uint16_t *dst_buf, uint32_t src_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < src_len; ++i) {
|
||||
dst_buf[i*2 + 0] = dst_buf[i*2 + 1] = src_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
int store_voicemsbc_buffer(unsigned char *buf, unsigned int len)
|
||||
{
|
||||
LOCK_VOICEMSBC_QUEUE();
|
||||
EnCQueue(&voicemsbc_queue, buf, len);
|
||||
dump_buffer_to_psram((char *)buf, len);
|
||||
TRACE(1,"%d\n", LengthOfCQueue(&voicemsbc_queue));
|
||||
if (LengthOfCQueue(&voicemsbc_queue) > VOICEMSBC_TEMP_BUFFER_SIZE*20) {
|
||||
ok_to_decode = 1;
|
||||
}
|
||||
UNLOCK_VOICEMSBC_QUEUE();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static short tmp_decode_buf[VOICEMSBC_TEMP_BUFFER_SIZE*2];
|
||||
int decode_msbc_frame(unsigned char *pcm_buffer, unsigned int pcm_len)
|
||||
{
|
||||
int r = 0;
|
||||
uint32_t decode_len = 0;
|
||||
unsigned char *e1 = NULL, *e2 = NULL;
|
||||
unsigned int len1 = 0, len2 = 0;
|
||||
|
||||
while (decode_len < pcm_len) {
|
||||
get_again:
|
||||
LOCK_VOICEMSBC_QUEUE();
|
||||
len1 = len2 = 0;
|
||||
r = PeekCQueue(&voicemsbc_queue, VOICEMSBC_TEMP_BUFFER_SIZE, &e1, &len1, &e2, &len2);
|
||||
UNLOCK_VOICEMSBC_QUEUE();
|
||||
|
||||
if(r == CQ_ERR || len1 == 0) {
|
||||
//return 0;
|
||||
Thread::wait(4);
|
||||
goto get_again;
|
||||
}
|
||||
|
||||
if (len1 != 0) {
|
||||
//msbcToPcm8k(e1, (short *)(pcm_buffer + decode_len*4), len1, 0);
|
||||
CvsdToPcm8k(e1, (short *)(tmp_decode_buf), len1, 0);
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)tmp_decode_buf, (uint16_t *)(pcm_buffer + decode_len), len1);
|
||||
|
||||
LOCK_VOICEMSBC_QUEUE();
|
||||
DeCQueue(&voicemsbc_queue, 0, len1);
|
||||
UNLOCK_VOICEMSBC_QUEUE();
|
||||
|
||||
decode_len += len1*4;
|
||||
}
|
||||
|
||||
if (len2 != 0) {
|
||||
//msbcToPcm8k(e2, (short *)(pcm_buffer + decode_len*4), len2, 0);
|
||||
CvsdToPcm8k(e2, (short *)(tmp_decode_buf), len2, 0);
|
||||
copy_one_trace_to_two_track_16bits((uint16_t *)tmp_decode_buf, (uint16_t *)(pcm_buffer + decode_len), len2);
|
||||
|
||||
LOCK_VOICEMSBC_QUEUE();
|
||||
DeCQueue(&voicemsbc_queue, 0, len2);
|
||||
UNLOCK_VOICEMSBC_QUEUE();
|
||||
|
||||
decode_len += len2*4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t voicemsbc_audio_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t l = 0;
|
||||
uint32_t cur_ticks = 0, ticks = 0;
|
||||
|
||||
if (ok_to_decode == 0)
|
||||
return 0;
|
||||
|
||||
ticks = hal_sys_timer_get();
|
||||
l = decode_msbc_frame(buf, len);
|
||||
cur_ticks = hal_sys_timer_get();
|
||||
TRACE(1,"msbc %d t\n", (cur_ticks-ticks));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
int voicemsbc_audio_init(void)
|
||||
{
|
||||
Pcm8k_CvsdInit();
|
||||
|
||||
g_voicemsbc_queue_mutex_id = osMutexCreate((osMutex(g_voicemsbc_queue_mutex)));
|
||||
/* msbc queue*/
|
||||
InitCQueue(&voicemsbc_queue, VOICEMSBC_QUEUE_SIZE, (unsigned char *)&voicemsbc_queue_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,328 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "plc_utils.h"
|
||||
#include "hal_trace.h"
|
||||
|
||||
#if defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A)
|
||||
#define MSBC_MUTE_PATTERN (0x55)
|
||||
#else
|
||||
#define MSBC_MUTE_PATTERN (0x00)
|
||||
#endif
|
||||
|
||||
#define MSBC_PKTSIZE (60)
|
||||
|
||||
/*
|
||||
* msbc frame's last byte is a padding byte, we assume it is zero,
|
||||
* but it is not always true.
|
||||
* Do not check this by default
|
||||
*/
|
||||
//#define ENABLE_PAD_CHECK
|
||||
|
||||
/*
|
||||
* if msbc frame is filled by 10+ samples in the trail, crc maybe not detect this
|
||||
* satuation.
|
||||
* Do not check this by default
|
||||
*/
|
||||
//#define ENABLE_TRAILING_ZERO_CHECK
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
#define ENABLE_BLE_CONFLICT_CHECK
|
||||
|
||||
#define ENABLE_CRC_CHECK
|
||||
|
||||
/* check msbc sequence number */
|
||||
#define ENABLE_SEQ_CHECK
|
||||
|
||||
#ifdef ENABLE_CRC_CHECK
|
||||
static const uint8_t sbc_crc_tbl[256] = {
|
||||
0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF,
|
||||
0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E,
|
||||
0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0,
|
||||
0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
|
||||
0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85,
|
||||
0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40,
|
||||
0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9,
|
||||
0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
|
||||
0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B,
|
||||
0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A,
|
||||
0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01,
|
||||
0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
|
||||
0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24,
|
||||
0x77, 0x6A, 0x4D, 0x50, 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2,
|
||||
0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B,
|
||||
0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
|
||||
0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA,
|
||||
0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB,
|
||||
0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95,
|
||||
0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
|
||||
0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0,
|
||||
0xE3, 0xFE, 0xD9, 0xC4
|
||||
};
|
||||
#endif
|
||||
|
||||
static int sco_parse_synchronization_header(uint8_t *buf, uint8_t *sn)
|
||||
{
|
||||
uint8_t sn1, sn2;
|
||||
#ifdef ENABLE_CRC_CHECK
|
||||
uint8_t fcs = 0x0F;
|
||||
uint8_t crc = 0;
|
||||
uint8_t i, sb, bit, shift;
|
||||
uint8_t ind = 6, bitOffset = 24;
|
||||
#endif
|
||||
*sn = 0xff;
|
||||
#if defined(MSBC_SYNC_HACKER)
|
||||
if (((buf[0] != 0x01) && (buf[0] != 0x00)) ||
|
||||
((buf[1] & 0x0f) != 0x08) ||
|
||||
(buf[2] != 0xad)) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if ((buf[0] != 0x01) ||
|
||||
((buf[1] & 0x0f) != 0x08) ||
|
||||
(buf[2] != 0xad)) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
sn1 = (buf[1] & 0x30) >> 4;
|
||||
sn2 = (buf[1] & 0xc0) >> 6;
|
||||
if ((sn1 != 0) && (sn1 != 0x3)) {
|
||||
return -2;
|
||||
}
|
||||
if ((sn2 != 0) && (sn2 != 0x3)) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CRC_CHECK
|
||||
fcs = sbc_crc_tbl[fcs ^ buf[3]];
|
||||
if (buf[3] != 0x00)
|
||||
return -4;
|
||||
fcs = sbc_crc_tbl[fcs ^ buf[4]];
|
||||
if (buf[4] != 0x00)
|
||||
return -4;
|
||||
crc = buf[5];
|
||||
for (sb = 0; sb < 8; sb++) {
|
||||
if (bitOffset % 8) {
|
||||
/* Sum the whole byte */
|
||||
fcs = sbc_crc_tbl[fcs ^ buf[ind]];
|
||||
ind = ind + 1;
|
||||
}
|
||||
else {
|
||||
if (sb == 7) {
|
||||
/* Sum the next 4 bits */
|
||||
|
||||
/* Just sum the most significant 4 bits */
|
||||
shift = 7;
|
||||
for (i = 0; i < 4; i++) {
|
||||
bit = (uint8_t)((0x01 & (buf[ind] >> shift--)) ^ (fcs >> 7));
|
||||
if (bit) {
|
||||
fcs = (uint8_t)(((fcs << 1) | bit) ^ 0x1C);
|
||||
}
|
||||
else {
|
||||
fcs = (uint8_t)((fcs << 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitOffset += 4;
|
||||
}
|
||||
//TRACE(2,"msbc crc:%d fcs:%d", crc,fcs);
|
||||
if (crc != fcs)
|
||||
return -4;
|
||||
#endif
|
||||
|
||||
*sn = (sn1 & 0x01) | (sn2 & 0x02);
|
||||
|
||||
#ifdef ENABLE_PAD_CHECK
|
||||
// when pad error detected, we should return sn
|
||||
if (buf[MSBC_PKTSIZE - 1] != 0x0) {
|
||||
return -5;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BLE_CONFLICT_CHECK
|
||||
static bool memcmp_U8(uint8_t *x, uint8_t *y, uint16_t size)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (x[i] != y[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// when signal is mute, msbc data remains the same except seq num. We should check history flag,
|
||||
// otherwise a single conflict may be detected twice
|
||||
static bool update_ble_sco_conflict(PacketLossState* st, uint8_t *last_pkt, uint8_t *pkt)
|
||||
{
|
||||
// do not check padding byte as it maybe useless when msbc_offset is 1
|
||||
bool ret = (st->prev_ble_sco_conflict_flag[1] == false && memcmp_U8(last_pkt, pkt, MSBC_PKTSIZE - 1) == false);
|
||||
|
||||
memcpy(&last_pkt[0], &last_pkt[MSBC_PKTSIZE], MSBC_PKTSIZE);
|
||||
memcpy(&last_pkt[MSBC_PKTSIZE], pkt, MSBC_PKTSIZE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool check_ble_sco_conflict(PacketLossState* st, bool ret)
|
||||
{
|
||||
st->prev_ble_sco_conflict_flag[1] = st->prev_ble_sco_conflict_flag[0];
|
||||
st->prev_ble_sco_conflict_flag[0] = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool msbc_check_controller_mute_pattern(uint8_t *pkt, uint8_t pattern)
|
||||
{
|
||||
// do not check padding byte as it maybe useless when msbc_offset is 1
|
||||
for (int i = 0; i < MSBC_PKTSIZE - 1; i++)
|
||||
if (pkt[i] != pattern)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TRAILING_ZERO_CHECK
|
||||
static int msbc_check_pkt_trailing_zeros(uint8_t *pkt)
|
||||
{
|
||||
int idx = MSBC_PKTSIZE;
|
||||
|
||||
for (int i = MSBC_PKTSIZE - 1; i >= 0; i--) {
|
||||
if (pkt[i] != 0) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (MSBC_PKTSIZE - 1 - idx);
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint8_t get_next_sequence_num(uint8_t seq_num)
|
||||
{
|
||||
return (seq_num + 1 == 4) ? 0 : (seq_num + 1);
|
||||
}
|
||||
|
||||
void packet_loss_detection_init(PacketLossState *st)
|
||||
{
|
||||
st->last_seq_num = 0xff;
|
||||
|
||||
memset(st->last_pkt, 0, sizeof(st->last_pkt));
|
||||
memset(st->prev_ble_sco_conflict_flag, 0, sizeof(st->prev_ble_sco_conflict_flag));
|
||||
memset(st->hist, 0, sizeof(st->hist));
|
||||
}
|
||||
|
||||
plc_type_t packet_loss_detection_process(PacketLossState *st, uint8_t *sbc_buf)
|
||||
{
|
||||
plc_type_t plc_type = PLC_TYPE_PASS;
|
||||
|
||||
#ifdef ENABLE_BLE_CONFLICT_CHECK
|
||||
bool ble_sco_conflict = update_ble_sco_conflict(st, st->last_pkt, sbc_buf);
|
||||
#endif
|
||||
|
||||
uint8_t seq_num;
|
||||
if (msbc_check_controller_mute_pattern(sbc_buf, MSBC_MUTE_PATTERN) == true) {
|
||||
plc_type = PLC_TYPE_CONTROLLER_MUTE;
|
||||
st->last_seq_num = 0xff;
|
||||
}
|
||||
#ifdef ENABLE_BLE_CONFLICT_CHECK
|
||||
else if (check_ble_sco_conflict(st, ble_sco_conflict) == true) {
|
||||
plc_type = PLC_TYPE_BLE_CONFLICT;
|
||||
st->last_seq_num = 0xff;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
int err = sco_parse_synchronization_header(sbc_buf, &seq_num);
|
||||
if (err < 0 && err >= -3) {
|
||||
plc_type = PLC_TYPE_HEADER_ERROR;
|
||||
st->last_seq_num = 0xff;
|
||||
}
|
||||
#ifdef ENABLE_CRC_CHECK
|
||||
else if (err == -4) {
|
||||
plc_type = PLC_TYPE_CRC_ERROR;
|
||||
st->last_seq_num = 0xff;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_PAD_CHECK
|
||||
else if (err == -5) {
|
||||
plc_type = PLC_TYPE_PAD_ERROR;
|
||||
st->last_seq_num = seq_num;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_TRAILING_ZERO_CHECK
|
||||
else if (msbc_check_pkt_trailing_zeros(sbc_buf) > 10) {
|
||||
plc_type = PLC_TYPE_DATA_MISSING;
|
||||
st->last_seq_num = 0xff;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
#ifdef ENABLE_SEQ_CHECK
|
||||
if (st->last_seq_num == 0xff) {
|
||||
if (seq_num == 0xff) {
|
||||
plc_type = PLC_TYPE_SEQUENCE_DISCONTINUE;
|
||||
}
|
||||
else {
|
||||
plc_type = PLC_TYPE_PASS;
|
||||
}
|
||||
st->last_seq_num = seq_num;
|
||||
}
|
||||
else {
|
||||
if (seq_num == 0xff) {
|
||||
st->last_seq_num = 0xff;
|
||||
plc_type = PLC_TYPE_SEQUENCE_DISCONTINUE;
|
||||
}
|
||||
else if (seq_num == get_next_sequence_num(st->last_seq_num)) {
|
||||
st->last_seq_num = seq_num;
|
||||
plc_type = PLC_TYPE_PASS;
|
||||
}
|
||||
else {
|
||||
st->last_seq_num = 0xff;
|
||||
plc_type = PLC_TYPE_SEQUENCE_DISCONTINUE;
|
||||
}
|
||||
}
|
||||
#else
|
||||
plc_type = PLC_TYPE_PASS;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
packet_loss_detection_update_histogram(st, plc_type);
|
||||
|
||||
return plc_type;
|
||||
}
|
||||
|
||||
void packet_loss_detection_update_histogram(PacketLossState *st, plc_type_t plc_type)
|
||||
{
|
||||
if (plc_type < 0 || plc_type >= PLC_TYPE_NUM) {
|
||||
TRACE(2,"[%s] plc type %d is invalid", __FUNCTION__, plc_type);
|
||||
return;
|
||||
}
|
||||
|
||||
// The packet is detected as PLC_TYPE_PASS, but causes a decoder error.
|
||||
if (plc_type == PLC_TYPE_DECODER_ERROR) {
|
||||
st->hist[0] -= 1;
|
||||
}
|
||||
|
||||
st->hist[plc_type] += 1;
|
||||
}
|
||||
|
||||
void packet_loss_detection_report(PacketLossState *st)
|
||||
{
|
||||
uint32_t packet_loss_num = 0;
|
||||
|
||||
for (uint8_t i = 1; i < PLC_TYPE_NUM; i++) {
|
||||
TRACE(3,"[%s] plc type %d occurs %d times", __FUNCTION__, i, st->hist[i]);
|
||||
packet_loss_num += st->hist[i];
|
||||
}
|
||||
|
||||
uint32_t packet_total_num = st->hist[0] + packet_loss_num;
|
||||
TRACE(4,"[%s] packet loss percent %d/10000(%d/%d)", __FUNCTION__,
|
||||
(int32_t)(10000.f * packet_loss_num/ packet_total_num), packet_loss_num, packet_total_num);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef PLC_UTILS_H
|
||||
#define PLC_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum plc_type
|
||||
{
|
||||
PLC_TYPE_PASS = 0,
|
||||
PLC_TYPE_CONTROLLER_MUTE,
|
||||
PLC_TYPE_HEADER_ERROR,
|
||||
PLC_TYPE_CRC_ERROR,
|
||||
PLC_TYPE_PAD_ERROR,
|
||||
PLC_TYPE_DATA_MISSING,
|
||||
PLC_TYPE_SEQUENCE_DISCONTINUE,
|
||||
PLC_TYPE_BLE_CONFLICT,
|
||||
PLC_TYPE_DECODER_ERROR,
|
||||
PLC_TYPE_NUM,
|
||||
} plc_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t last_seq_num;
|
||||
uint8_t last_pkt[60 * 2];
|
||||
|
||||
// for ble sco conflict
|
||||
bool prev_ble_sco_conflict_flag[2];
|
||||
|
||||
// histogram
|
||||
uint32_t hist[PLC_TYPE_NUM];
|
||||
} PacketLossState;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void packet_loss_detection_init(PacketLossState *st);
|
||||
|
||||
plc_type_t packet_loss_detection_process(PacketLossState *st, uint8_t *sbc_buf);
|
||||
|
||||
/*
|
||||
* Update plc type histogram
|
||||
* Normally this function is called at the end of packet_loss_detection_process,
|
||||
* but if a decoder error occurs outside, it should be updated maually.
|
||||
*/
|
||||
void packet_loss_detection_update_histogram(PacketLossState *st, plc_type_t plc_type);
|
||||
|
||||
void packet_loss_detection_report(PacketLossState *st);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,887 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* rbplay source */
|
||||
/* playback control & rockbox codec porting & codec thread */
|
||||
|
||||
#ifdef MBED
|
||||
#include "mbed.h"
|
||||
#include "rtos.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include "SDFileSystem.h"
|
||||
#include "hal_uart.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#include "audioflinger.h"
|
||||
#include "cqueue.h"
|
||||
#include "app_audio.h"
|
||||
|
||||
#include "eq.h"
|
||||
#include "pga.h"
|
||||
#include "metadata.h"
|
||||
#include "dsp_core.h"
|
||||
#include "codecs.h"
|
||||
#include "codeclib.h"
|
||||
#include "compressor.h"
|
||||
#include "channel_mode.h"
|
||||
#include "audiohw.h"
|
||||
#include "codec_platform.h"
|
||||
#include "metadata_parsers.h"
|
||||
|
||||
#include "hal_overlay.h"
|
||||
#include "app_overlay.h"
|
||||
#include "rbpcmbuf.h"
|
||||
#include "rbplay.h"
|
||||
#include "app_thread.h"
|
||||
#include "app_utils.h"
|
||||
#include "app_key.h"
|
||||
|
||||
#include "rbplaysd.h"
|
||||
#include "rb_ctl.h"
|
||||
|
||||
/* Internals */
|
||||
|
||||
void rb_ctl_wait_lock_thread(bool lock);
|
||||
void app_rbcodec_ctl_set_play_status(bool st);
|
||||
extern bool app_rbcodec_check_hfp_active(void );
|
||||
|
||||
#include "SDFileSystem.h"
|
||||
|
||||
extern "C" void hal_sysfreq_print(void);
|
||||
|
||||
#define _LOG_TAG "[rb_ctl] "
|
||||
#undef __attribute__(a)
|
||||
|
||||
#define RBPLAY_DEBUG 1
|
||||
#if RBPLAY_DEBUG
|
||||
#define _LOG_DBG(str,...) TRACE(0,_LOG_TAG""str, ##__VA_ARGS__)
|
||||
#define _LOG_ERR(str,...) TRACE(0,_LOG_TAG"err:"""str, ##__VA_ARGS__)
|
||||
#else
|
||||
#define _LOG_DBG(str,...)
|
||||
#define _LOG_ERR(str,...) TRACE(0,_LOG_TAG"err:"""str, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#include "rb_ctl.h"
|
||||
void rb_thread_send_resume(void);
|
||||
|
||||
typedef struct {
|
||||
uint32_t evt;
|
||||
uint32_t arg;
|
||||
} RBCTL_MSG_BLOCK;
|
||||
|
||||
static osThreadId rb_ctl_tid;
|
||||
static void rb_ctl_thread(void const *argument);
|
||||
static int rb_ctl_default_priority;
|
||||
osThreadDef(rb_ctl_thread, osPriorityHigh, 1, 1024 * 4, "rb_ctl");
|
||||
|
||||
#define RBCTL_MAILBOX_MAX (20)
|
||||
osMailQDef (rb_ctl_mailbox, RBCTL_MAILBOX_MAX, RBCTL_MSG_BLOCK);
|
||||
static osMailQId rb_ctl_mailbox = NULL;
|
||||
|
||||
int rb_ctl_mailbox_put(RBCTL_MSG_BLOCK* msg_src);
|
||||
|
||||
//playlist
|
||||
extern playlist_struct sd_playlist;
|
||||
|
||||
|
||||
rb_ctl_struct rb_ctl_context;
|
||||
|
||||
extern void rb_thread_set_decode_vars(int fd, int type ,void* id3);
|
||||
extern void rb_play_codec_run(void);
|
||||
extern void rb_codec_set_halt(int halt);
|
||||
extern void rb_player_sync_set_wait_thread(osThreadId tid);
|
||||
extern void rb_player_sync_wait_close(void );
|
||||
extern bool rb_pcmbuf_suspend_play_loop(void);
|
||||
void app_rbplay_load_playlist(playlist_struct *list );
|
||||
int rb_thread_post_msg(RB_MODULE_EVT evt,uint32_t arg );
|
||||
|
||||
static rb_ctl_status rb_ctl_get_status(void)
|
||||
{
|
||||
return rb_ctl_context.status;
|
||||
}
|
||||
|
||||
bool rb_ctl_parse_file(const char* file_path)
|
||||
{
|
||||
/* open file */
|
||||
|
||||
_LOG_DBG(1,"open file %s\n", file_path);
|
||||
rb_ctl_context.file_handle = open((const char *)file_path, O_RDWR);
|
||||
if (rb_ctl_context.file_handle <= 0) {
|
||||
_LOG_DBG(1,"open file %s failed\n", file_path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!get_metadata(&rb_ctl_context.song_id3, rb_ctl_context.file_handle, rb_ctl_context.rb_fname)) {
|
||||
_LOG_DBG(0,"get_metadata failed\n");
|
||||
close(rb_ctl_context.file_handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
_LOG_DBG(4,"%s bitr:%d,saps %d, freq:%d\n",__func__,rb_ctl_context.song_id3.bitrate,rb_ctl_context.song_id3.samples,rb_ctl_context.song_id3.frequency);
|
||||
|
||||
rb_thread_set_decode_vars(rb_ctl_context.file_handle, rb_ctl_context.song_id3.codectype,&rb_ctl_context.song_id3);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void rb_ctl_vol_operation(bool inc )
|
||||
{
|
||||
uint32_t ret;
|
||||
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
||||
|
||||
_LOG_DBG(2,"%s inc:%d , ",__func__,inc);
|
||||
|
||||
if(inc ) {
|
||||
if(rb_ctl_context.rb_player_vol < 16 ) {
|
||||
rb_ctl_context.rb_player_vol++;
|
||||
|
||||
}
|
||||
} else {
|
||||
if(rb_ctl_context.rb_player_vol > 1 ) {
|
||||
rb_ctl_context.rb_player_vol--;
|
||||
}
|
||||
}
|
||||
if(rb_ctl_context.status != RB_CTL_PLAYING)
|
||||
return ;
|
||||
|
||||
ret = af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, true);
|
||||
if (ret == 0) {
|
||||
stream_cfg->vol = rb_ctl_context.rb_player_vol;
|
||||
af_stream_setup(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, stream_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
bool rb_ctl_is_playing(void)
|
||||
{
|
||||
return (rb_ctl_context.status == RB_CTL_PLAYING);
|
||||
}
|
||||
|
||||
void rb_ctl_set_vol(uint32_t vol)
|
||||
{
|
||||
uint32_t ret;
|
||||
struct AF_STREAM_CONFIG_T *stream_cfg = NULL;
|
||||
|
||||
_LOG_DBG(2,"%s set vol as :%d , ",__func__,vol);
|
||||
|
||||
if(rb_ctl_context.status != RB_CTL_PLAYING)
|
||||
return ;
|
||||
|
||||
vol = (vol > 16)?16:vol;
|
||||
rb_ctl_context.rb_player_vol = vol;
|
||||
|
||||
ret = af_stream_get_cfg(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg, true);
|
||||
if (ret == 0) {
|
||||
stream_cfg->vol = rb_ctl_context.rb_player_vol;
|
||||
af_stream_setup(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, stream_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
void rb_ctl_stop_play(void )
|
||||
{
|
||||
_LOG_DBG(1,"%s \n",__func__);
|
||||
|
||||
rb_codec_set_halt(1);
|
||||
//close file
|
||||
_LOG_DBG(0," af stream stop \n");
|
||||
af_stream_stop(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
_LOG_DBG(0," af stream close \n");
|
||||
af_stream_close(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
_LOG_DBG(0," close file \n");
|
||||
if(rb_ctl_context.file_handle != -1)
|
||||
close(rb_ctl_context.file_handle );
|
||||
rb_ctl_context.file_handle = -1;
|
||||
//release frequency
|
||||
_LOG_DBG(0," release freq \n");
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void rb_ctl_sync_stop_play(void )
|
||||
{
|
||||
rb_player_sync_set_wait_thread(osThreadGetId());
|
||||
|
||||
rb_ctl_stop_play();
|
||||
|
||||
rb_player_sync_wait_close();
|
||||
//close file
|
||||
_LOG_DBG(0," close file \n");
|
||||
if(rb_ctl_context.file_handle != -1)
|
||||
close(rb_ctl_context.file_handle );
|
||||
rb_ctl_context.file_handle = -1;
|
||||
}
|
||||
|
||||
void rb_ctl_pause_playing(void )
|
||||
{
|
||||
af_stream_stop(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
_LOG_DBG(0," af stream close \n");
|
||||
af_stream_close(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
//wait decoder suspend
|
||||
//osDelay(200);
|
||||
// while(!rb_pcmbuf_suspend_play_loop()) {
|
||||
//osThreadYield();
|
||||
// osDelay(1);
|
||||
// }
|
||||
|
||||
_LOG_DBG(1,"%s sucessed ",__func__);
|
||||
}
|
||||
|
||||
void rb_ctl_resume_playing(void )
|
||||
{
|
||||
#ifndef __TWS__
|
||||
rb_pcmbuf_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void rb_ctl_set_priority(int priority)
|
||||
{
|
||||
osThreadSetPriority(rb_ctl_tid, (osPriority)priority);
|
||||
}
|
||||
|
||||
int rb_ctl_get_priority(void)
|
||||
{
|
||||
return (int)osThreadGetPriority(rb_ctl_tid);
|
||||
}
|
||||
|
||||
int rb_ctl_get_default_priority(void)
|
||||
{
|
||||
return rb_ctl_default_priority;
|
||||
}
|
||||
|
||||
void rb_ctl_reset_priority(void)
|
||||
{
|
||||
osThreadSetPriority(rb_ctl_tid, (osPriority)rb_ctl_default_priority);
|
||||
}
|
||||
|
||||
#ifdef __IAG_BLE_INCLUDE__
|
||||
extern "C" void app_ble_inform_music_switch(uint16_t index);
|
||||
#endif
|
||||
static int rb_ctl_handle_event(RBCTL_MSG_BLOCK *msg_body)
|
||||
{
|
||||
RB_MODULE_EVT evt =(RB_MODULE_EVT) msg_body->evt;
|
||||
uint32_t arg = msg_body->arg;
|
||||
// hal_sysfreq_print();
|
||||
|
||||
|
||||
switch(evt) {
|
||||
case RB_MODULE_EVT_PLAY:
|
||||
if(rb_ctl_context.status != RB_CTL_IDLE) {
|
||||
if(rb_ctl_context.status == RB_CTL_SUSPEND)
|
||||
rb_thread_send_resume();
|
||||
else
|
||||
_LOG_DBG(2,"%s st %d not in idle \n",__func__,rb_ctl_context.status);
|
||||
break;
|
||||
}
|
||||
_LOG_DBG(3," %s start %d/%d ",__func__, rb_ctl_context.curr_song_idx ,sd_playlist.total_songs);
|
||||
if(sd_playlist.total_songs > 0 ) {
|
||||
playlist_item *it;
|
||||
|
||||
it = app_rbplay_get_playitem(rb_ctl_context.curr_song_idx) ;
|
||||
|
||||
if(it == NULL) {
|
||||
_LOG_DBG(2," %s get item fail idx %d",__func__,rb_ctl_context.curr_song_idx);
|
||||
}
|
||||
|
||||
_LOG_DBG(2,"%s start songidx %d \n",__func__,rb_ctl_context.curr_song_idx);
|
||||
|
||||
memcpy(rb_ctl_context.rb_audio_file,it->file_path,sizeof(uint16_t)*FILE_PATH_LEN - 4);
|
||||
memcpy(rb_ctl_context.rb_fname,it->file_name,sizeof(rb_ctl_context.rb_fname));
|
||||
|
||||
if(rb_ctl_parse_file((const char*)rb_ctl_context.rb_audio_file)) {
|
||||
_LOG_DBG(2,"%s start init, the tid 0x%x\n",__func__,osThreadGetId());
|
||||
rb_play_codec_init();
|
||||
_LOG_DBG(1,"%s start run\n",__func__);
|
||||
rb_play_codec_run();
|
||||
rb_ctl_context.status = RB_CTL_PLAYING;
|
||||
app_rbcodec_ctl_set_play_status(true);
|
||||
break;
|
||||
} else {
|
||||
_LOG_DBG(2,"%s evt %d parse fail,find next\n",__func__,msg_body->evt);
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY_NEXT,true);
|
||||
}
|
||||
|
||||
} else {
|
||||
_LOG_DBG(2,"%s evt %d no songs\n",__func__,msg_body->evt);
|
||||
}
|
||||
break;
|
||||
case RB_MODULE_EVT_STOP:
|
||||
if(rb_ctl_context.status == RB_CTL_IDLE) {
|
||||
_LOG_DBG(2,"%s st %d in idle \n",__func__,rb_ctl_context.status);
|
||||
break;
|
||||
}
|
||||
if(rb_ctl_context.status == RB_CTL_SUSPEND) {
|
||||
//osDelay(100);
|
||||
rb_ctl_resume_playing();
|
||||
rb_ctl_context.status = RB_CTL_PLAYING;
|
||||
}
|
||||
rb_ctl_sync_stop_play();
|
||||
rb_ctl_context.status = RB_CTL_IDLE;
|
||||
app_rbcodec_ctl_set_play_status(false);
|
||||
break;
|
||||
case RB_MODULE_EVT_SUSPEND:
|
||||
if (rb_ctl_context.status != RB_CTL_PLAYING) {
|
||||
_LOG_DBG(2,"%s st %d not running \n",__func__,rb_ctl_context.status);
|
||||
break;
|
||||
}
|
||||
rb_ctl_pause_playing();
|
||||
rb_ctl_context.status = RB_CTL_SUSPEND;
|
||||
break;
|
||||
case RB_MODULE_EVT_RESUME:
|
||||
if (rb_ctl_context.status != RB_CTL_SUSPEND) {
|
||||
_LOG_DBG(2,"%s st %d not suspend \n",__func__,rb_ctl_context.status);
|
||||
break;
|
||||
}
|
||||
rb_ctl_resume_playing();
|
||||
rb_ctl_context.status = RB_CTL_PLAYING;
|
||||
break;
|
||||
case RB_MODULE_EVT_PLAY_NEXT:
|
||||
if( rb_ctl_context.status == RB_CTL_PLAYING) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP,0 );
|
||||
} else if( rb_ctl_context.status == RB_CTL_SUSPEND) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP,0 );
|
||||
} else {
|
||||
|
||||
}
|
||||
if(arg == 0) {
|
||||
rb_ctl_context.curr_song_idx--;
|
||||
|
||||
if(rb_ctl_context.curr_song_idx == 0xffff)
|
||||
rb_ctl_context.curr_song_idx = sd_playlist.total_songs -1;
|
||||
|
||||
} else {
|
||||
|
||||
rb_ctl_context.curr_song_idx++;
|
||||
|
||||
if(rb_ctl_context.curr_song_idx >= sd_playlist.total_songs)
|
||||
rb_ctl_context.curr_song_idx = 0;
|
||||
}
|
||||
|
||||
#ifdef __IAG_BLE_INCLUDE__
|
||||
app_ble_inform_music_switch(rb_ctl_context.curr_song_idx);
|
||||
#endif
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY,0 );
|
||||
break;
|
||||
case RB_MODULE_EVT_CHANGE_VOL:
|
||||
rb_ctl_vol_operation(arg);
|
||||
break;
|
||||
case RB_MODULE_EVT_SET_VOL:
|
||||
rb_ctl_set_vol(arg);
|
||||
break;
|
||||
case RB_MODULE_EVT_CHANGE_IDLE:
|
||||
rb_ctl_stop_play();
|
||||
rb_ctl_context.status = RB_CTL_IDLE;
|
||||
break;
|
||||
case RB_MODULE_EVT_PLAY_IDX:
|
||||
if(arg > sd_playlist.total_songs -1 ) {
|
||||
break;
|
||||
}
|
||||
if( rb_ctl_context.status == RB_CTL_PLAYING) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP,0 );
|
||||
} else if( rb_ctl_context.status == RB_CTL_SUSPEND) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP,0 );
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
rb_ctl_context.curr_song_idx = (uint16_t)arg;
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY,0 );
|
||||
break;
|
||||
//for voice cocah
|
||||
#if 0
|
||||
case SBCREADER_ACTION_INIT:
|
||||
//prepare fs
|
||||
voiceCocah_prepare_fs();
|
||||
//init the data buff
|
||||
voiceCocah_read_sbc_data();
|
||||
break;
|
||||
case SBCREADER_ACTION_RUN:
|
||||
//fill sbc queue
|
||||
voiceCocah_read_sbc_data();
|
||||
break;
|
||||
case SBCREADER_ACTION_STOP:
|
||||
//release the res
|
||||
voiceCocah_stop_clean();
|
||||
rb_ctl_reset_priority();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef __TWS__
|
||||
case RB_MODULE_EVT_RESTORE_DUAL_PLAY:
|
||||
extern void rb_restore_dual_play(uint8_t stream_type);
|
||||
rb_restore_dual_play(arg);
|
||||
break;
|
||||
#endif
|
||||
case RB_MODULE_EVT_DEL_FILE:
|
||||
static rb_ctl_status prev_status = rb_ctl_context.status;
|
||||
if( rb_ctl_context.status == RB_CTL_PLAYING) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP,0 );
|
||||
rb_thread_post_msg(RB_MODULE_EVT_DEL_FILE,arg);
|
||||
} else if( rb_ctl_context.status == RB_CTL_SUSPEND) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP,0 );
|
||||
rb_thread_post_msg(RB_MODULE_EVT_DEL_FILE,arg);
|
||||
} else {
|
||||
app_ctl_remove_file(arg);
|
||||
if(prev_status == RB_CTL_PLAYING) {
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY,0 );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#if defined(TWS_LINEIN_PLAYER)
|
||||
case RB_MODULE_EVT_LINEIN_START:
|
||||
extern int app_linein_codec_start(void);
|
||||
app_linein_codec_start();
|
||||
break;
|
||||
|
||||
case RB_MODULE_EVT_RECONFIG_STREAM:
|
||||
extern void rb_tws_reconfig_stream(uint32_t arg);
|
||||
rb_tws_reconfig_stream(arg);
|
||||
break;
|
||||
|
||||
case RB_MODULE_EVT_SET_TWS_MODE:
|
||||
break;
|
||||
#endif
|
||||
#ifdef SBC_RECORD_TEST
|
||||
|
||||
case SBC_RECORD_ACTION_START:
|
||||
{
|
||||
rb_ctl_context.sbc_record_on = true;
|
||||
app_rbplay_set_store_flag(true);
|
||||
app_rbplay_open_sbc_file();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case SBC_RECORD_ACTION_DATA_IND:
|
||||
{
|
||||
if(rb_ctl_context.sbc_record_on) {
|
||||
app_rbplay_process_sbc_data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SBC_RECORD_ACTION_STOP:
|
||||
{
|
||||
rb_ctl_context.sbc_record_on = false;
|
||||
app_rbplay_set_store_flag(false);
|
||||
app_rbplay_close_sbc_file();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(SBC_RECORD_ACTION_DATA_IND !=msg_body->evt)
|
||||
_LOG_DBG(3,"%s rbcodec evt %d ,st %d ended\n",__func__,msg_body->evt,rb_ctl_context.status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_thread_post_msg(RB_MODULE_EVT evt,uint32_t arg )
|
||||
{
|
||||
int ret;
|
||||
RBCTL_MSG_BLOCK msg;
|
||||
|
||||
if(!rb_ctl_tid)
|
||||
return 0;
|
||||
/* APIs */
|
||||
msg.evt = (uint32_t)evt;
|
||||
msg.arg = (uint32_t)arg;
|
||||
ret = rb_ctl_mailbox_put(&msg);
|
||||
|
||||
_LOG_DBG(3,"%s ret %d evt:%d\n",__func__,ret ,evt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_wait_player_stoped(void )
|
||||
{
|
||||
while(rb_ctl_context.status != RB_CTL_IDLE)
|
||||
osThreadYield();
|
||||
}
|
||||
|
||||
void app_wait_player_suspend(void )
|
||||
{
|
||||
if(rb_ctl_context.status == RB_CTL_IDLE)
|
||||
return;
|
||||
|
||||
while(rb_ctl_context.status != RB_CTL_SUSPEND)
|
||||
osThreadYield();
|
||||
}
|
||||
|
||||
void app_wait_player_resumed(void )
|
||||
{
|
||||
if(rb_ctl_context.status == RB_CTL_IDLE)
|
||||
return;
|
||||
|
||||
while(rb_ctl_context.status != RB_CTL_PLAYING)
|
||||
osThreadYield();
|
||||
}
|
||||
|
||||
void rb_thread_send_play(void )
|
||||
{
|
||||
_LOG_DBG(1," %s ",__FUNCTION__);
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY, (uint32_t)osThreadGetId());
|
||||
}
|
||||
|
||||
void rb_thread_send_stop(void )
|
||||
{
|
||||
_LOG_DBG(1," %s ",__FUNCTION__);
|
||||
rb_thread_post_msg(RB_MODULE_EVT_STOP, (uint32_t)osThreadGetId());
|
||||
|
||||
osDelay(200);
|
||||
app_wait_player_stoped();
|
||||
}
|
||||
|
||||
void rb_thread_send_pause(void)
|
||||
{
|
||||
_LOG_DBG(1," %s ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_SUSPEND,(uint32_t)osThreadGetId());
|
||||
app_wait_player_suspend();
|
||||
|
||||
_LOG_DBG(1," %s end",__FUNCTION__);
|
||||
}
|
||||
|
||||
void rb_thread_send_resume(void)
|
||||
{
|
||||
_LOG_DBG(1," %s ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_RESUME,(uint32_t)osThreadGetId());
|
||||
|
||||
_LOG_DBG(1," %s end",__FUNCTION__);
|
||||
}
|
||||
|
||||
void rb_play_dual_play_restore(uint8_t stream_type )
|
||||
{
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_RESTORE_DUAL_PLAY, stream_type);
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
void rb_thread_send_switch(bool next)
|
||||
{
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY_NEXT,next);
|
||||
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
void rb_play_linein_start(void )
|
||||
{
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_LINEIN_START, 0);
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
void rb_play_reconfig_stream(uint32_t arg )
|
||||
{
|
||||
_LOG_DBG(3,"%s %d arg:0x%x\n", __func__, __LINE__, arg);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_RECONFIG_STREAM, arg);
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
void rb_play_set_tws_mode(uint32_t arg )
|
||||
{
|
||||
_LOG_DBG(3,"%s %d arg:0x%x\n", __func__, __LINE__, arg);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_SET_TWS_MODE, arg);
|
||||
_LOG_DBG(2,"%s %d \n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
void rb_thread_send_play_idx(uint32_t array_subidx)
|
||||
{
|
||||
_LOG_DBG(2," %s array_subidx %d, ",__FUNCTION__,array_subidx);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_PLAY_IDX,array_subidx);
|
||||
}
|
||||
|
||||
|
||||
void rb_thread_send_vol(bool inc)
|
||||
{
|
||||
_LOG_DBG(2," %s inc %d, ",__FUNCTION__,inc);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_CHANGE_VOL,inc);
|
||||
}
|
||||
|
||||
void rb_thread_send_status_change(void )
|
||||
{
|
||||
_LOG_DBG(1," %s , ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_CHANGE_IDLE,0);
|
||||
}
|
||||
|
||||
void rb_thread_set_vol(uint32_t vol)
|
||||
{
|
||||
_LOG_DBG(1," %s , ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_SET_VOL, vol);
|
||||
}
|
||||
|
||||
void rb_thread_send_del_file(uint16_t idx )
|
||||
{
|
||||
_LOG_DBG(1," %s , ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(RB_MODULE_EVT_DEL_FILE,idx);
|
||||
}
|
||||
|
||||
void rb_thread_send_sbc_record_start(void )
|
||||
{
|
||||
_LOG_DBG(1," %s , ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(SBC_RECORD_ACTION_START,(uint32_t)osThreadGetId());
|
||||
}
|
||||
|
||||
void rb_thread_send_sbc_record_data_ind(void )
|
||||
{
|
||||
if(!rb_ctl_context.sbc_record_on)
|
||||
return ;
|
||||
// _LOG_DBG(1," %s , ",__FUNCTION__);
|
||||
rb_thread_post_msg(SBC_RECORD_ACTION_DATA_IND,(uint32_t)osThreadGetId());
|
||||
}
|
||||
|
||||
void rb_thread_send_sbc_record_stop(void )
|
||||
{
|
||||
_LOG_DBG(1," %s , ",__FUNCTION__);
|
||||
|
||||
rb_thread_post_msg(SBC_RECORD_ACTION_STOP,(uint32_t)osThreadGetId());
|
||||
}
|
||||
|
||||
|
||||
//interface for audio module
|
||||
static bool user_key_pause_stream = false;
|
||||
void app_rbplay_audio_reset_pause_status(void)
|
||||
{
|
||||
user_key_pause_stream = false;
|
||||
}
|
||||
|
||||
int app_rbplay_audio_onoff(bool onoff, uint16_t aud_id)
|
||||
{
|
||||
_LOG_DBG(3," %s onoff %d, get status:%d",__FUNCTION__,onoff, rb_ctl_get_status());
|
||||
|
||||
if(app_rbcodec_check_hfp_active()&& !onoff) {
|
||||
if( RB_CTL_PLAYING == rb_ctl_get_status()) {
|
||||
rb_thread_send_pause();
|
||||
}
|
||||
} else if ( !onoff) {
|
||||
//rb_thread_send_stop();
|
||||
rb_thread_send_pause();
|
||||
} else {
|
||||
if(!user_key_pause_stream) {
|
||||
if( RB_CTL_SUSPEND == rb_ctl_get_status()) {
|
||||
rb_thread_send_resume();
|
||||
app_wait_player_resumed();
|
||||
} else {
|
||||
rb_thread_send_play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_rbplay_pause_resume(void)
|
||||
{
|
||||
_LOG_DBG(2," %s get status:%d",__func__, rb_ctl_get_status());
|
||||
|
||||
user_key_pause_stream = true;
|
||||
if( RB_CTL_SUSPEND == rb_ctl_get_status()) {
|
||||
user_key_pause_stream = false;
|
||||
rb_thread_send_resume();
|
||||
}
|
||||
if( RB_CTL_PLAYING == rb_ctl_get_status()) {
|
||||
user_key_pause_stream = true;
|
||||
rb_thread_send_pause();
|
||||
}
|
||||
}
|
||||
//sbc reader run within thread
|
||||
|
||||
static int rb_ctl_mailbox_init(void)
|
||||
{
|
||||
rb_ctl_mailbox = osMailCreate(osMailQ(rb_ctl_mailbox), NULL);
|
||||
if (rb_ctl_mailbox == NULL) {
|
||||
TRACE(0,"Failed to Create rb_ctl_mailbox\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_ctl_mailbox_put(RBCTL_MSG_BLOCK* msg_src)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
RBCTL_MSG_BLOCK *msg_p = NULL;
|
||||
|
||||
msg_p = (RBCTL_MSG_BLOCK*)osMailAlloc(rb_ctl_mailbox, 0);
|
||||
if(!msg_p) {
|
||||
TRACE(3,"%s fail, evt:%d,arg=%d \n",__func__,msg_src->evt,msg_src->arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ASSERT(msg_p, "osMailAlloc error");
|
||||
|
||||
msg_p->evt = msg_src->evt;
|
||||
msg_p->arg = msg_src->arg;
|
||||
|
||||
status = osMailPut(rb_ctl_mailbox, msg_p);
|
||||
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int rb_ctl_mailbox_free(RBCTL_MSG_BLOCK* msg_p)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
status = osMailFree(rb_ctl_mailbox, msg_p);
|
||||
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int rb_ctl_mailbox_get(RBCTL_MSG_BLOCK** msg_p)
|
||||
{
|
||||
osEvent evt;
|
||||
evt = osMailGet(rb_ctl_mailbox, osWaitForever);
|
||||
if (evt.status == osEventMail) {
|
||||
*msg_p = (RBCTL_MSG_BLOCK *)evt.value.p;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void rb_ctl_action_init(void)
|
||||
{
|
||||
|
||||
bool ind = voiceCocah_get_indication();
|
||||
TRACE(2," %s Cocah %d",__func__,ind);
|
||||
|
||||
if( !ind) return ;
|
||||
|
||||
// rb_ctl_set_priority(osPriorityHigh);
|
||||
|
||||
rb_thread_post_msg(SBCREADER_ACTION_INIT,(uint32_t)osThreadGetId());
|
||||
}
|
||||
|
||||
void rb_ctl_action_run(void)
|
||||
{
|
||||
bool ind = voiceCocah_get_indication();
|
||||
TRACE(2," %s Cocah %d",__func__,ind);
|
||||
|
||||
if( !ind) return ;
|
||||
|
||||
rb_thread_post_msg(SBCREADER_ACTION_RUN,(uint32_t)osThreadGetId());
|
||||
}
|
||||
|
||||
void rb_ctl_action_stop(void)
|
||||
{
|
||||
bool ind = voiceCocah_get_indication();
|
||||
TRACE(2," %s Cocah %d",__func__,ind);
|
||||
|
||||
if( !ind) return ;
|
||||
|
||||
rb_thread_post_msg(SBCREADER_ACTION_STOP,(uint32_t)osThreadGetId());
|
||||
|
||||
}
|
||||
#endif
|
||||
static void rb_ctl_thread(void const *argument)
|
||||
{
|
||||
osEvent evt;
|
||||
#if 1
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_PLAYER, APP_SYSFREQ_208M);
|
||||
|
||||
app_rbplay_load_playlist(&sd_playlist);
|
||||
#endif
|
||||
memset(&rb_ctl_context,0x0,sizeof(rb_ctl_struct));
|
||||
rb_ctl_context.rb_player_vol = 6;
|
||||
rb_ctl_context.status = RB_CTL_IDLE;
|
||||
|
||||
|
||||
rb_ctl_context.curr_song_idx = 0;
|
||||
//load playlist here
|
||||
|
||||
//voiceCocah_init();
|
||||
|
||||
rb_ctl_context.init_done = true;
|
||||
|
||||
while(1) {
|
||||
RBCTL_MSG_BLOCK *msg_p = NULL;
|
||||
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_PLAYER, APP_SYSFREQ_32K);
|
||||
|
||||
if (!rb_ctl_mailbox_get(&msg_p)) {
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_PLAYER, APP_SYSFREQ_104M);
|
||||
|
||||
rb_ctl_handle_event(msg_p);
|
||||
|
||||
rb_ctl_mailbox_free(msg_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rb_ctl_init(void)
|
||||
{
|
||||
_LOG_DBG(1,"%s \n",__func__);
|
||||
|
||||
rb_ctl_context.init_done = false;
|
||||
rb_ctl_context.sbc_record_on = false;
|
||||
|
||||
app_rbplay_open();
|
||||
|
||||
rb_ctl_mailbox_init();
|
||||
|
||||
rb_ctl_tid = osThreadCreate(osThread(rb_ctl_thread), NULL);
|
||||
rb_ctl_default_priority = osPriorityAboveNormal;
|
||||
|
||||
if (rb_ctl_tid == NULL) {
|
||||
TRACE(0,"Failed to Create rb_ctl_thread\n");
|
||||
return 0;
|
||||
}
|
||||
_LOG_DBG(1,"Leave %s \n",__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t rb_ctl_get_vol(void)
|
||||
{
|
||||
return rb_ctl_context.rb_player_vol;
|
||||
}
|
||||
|
||||
bool rb_ctl_is_init_done(void)
|
||||
{
|
||||
return rb_ctl_context.init_done;
|
||||
}
|
||||
|
||||
bool rb_ctl_is_paused(void)
|
||||
{
|
||||
return ( RB_CTL_SUSPEND == rb_ctl_get_status());
|
||||
}
|
||||
|
||||
uint16_t rb_ctl_songs_count(void)
|
||||
{
|
||||
return sd_playlist.total_songs;
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* rbplay source */
|
||||
/* playback control & rockbox codec porting & codec thread */
|
||||
#ifndef __RB_CTL_H__
|
||||
#define __RB_CTL_H__
|
||||
|
||||
|
||||
typedef enum {
|
||||
RB_MODULE_EVT_NONE,
|
||||
RB_MODULE_EVT_PLAY,
|
||||
RB_MODULE_EVT_PLAY_IDX,
|
||||
RB_MODULE_EVT_STOP,
|
||||
RB_MODULE_EVT_SUSPEND,
|
||||
RB_MODULE_EVT_RESUME,
|
||||
RB_MODULE_EVT_PLAY_NEXT,
|
||||
RB_MODULE_EVT_CHANGE_VOL,
|
||||
RB_MODULE_EVT_SET_VOL,
|
||||
RB_MODULE_EVT_CHANGE_IDLE,
|
||||
RB_MODULE_EVT_DEL_FILE,
|
||||
|
||||
RB_MODULE_EVT_RESTORE_DUAL_PLAY,
|
||||
RB_MODULE_EVT_LINEIN_START,
|
||||
RB_MODULE_EVT_RECONFIG_STREAM,
|
||||
RB_MODULE_EVT_SET_TWS_MODE,
|
||||
|
||||
SBCREADER_ACTION_NONE,
|
||||
SBCREADER_ACTION_INIT,
|
||||
SBCREADER_ACTION_RUN,
|
||||
SBCREADER_ACTION_STOP,
|
||||
|
||||
SBC_RECORD_ACTION_START,
|
||||
SBC_RECORD_ACTION_DATA_IND,
|
||||
SBC_RECORD_ACTION_STOP,
|
||||
|
||||
RB_MODULE_EVT_MAX
|
||||
} RB_MODULE_EVT;
|
||||
|
||||
typedef enum {
|
||||
RB_CTL_IDLE,
|
||||
RB_CTL_PLAYING,
|
||||
RB_CTL_SUSPEND,
|
||||
} rb_ctl_status;
|
||||
|
||||
typedef struct {
|
||||
struct mp3entry song_id3;
|
||||
char rb_fname[FILE_SHORT_NAME_LEN];
|
||||
rb_ctl_status status ; //playing,idle,pause,
|
||||
uint16_t rb_audio_file[FILE_PATH_LEN];
|
||||
uint16_t curr_song_idx ;
|
||||
uint8_t rb_player_vol ;
|
||||
int file_handle;
|
||||
int init_done;
|
||||
BOOL sbc_record_on;
|
||||
} rb_ctl_struct;
|
||||
|
||||
extern int app_rbmodule_post_msg(RB_MODULE_EVT evt,uint32_t arg);
|
||||
extern int rb_ctl_is_audio_file(const char* file_path);
|
||||
|
||||
uint8_t rb_ctl_get_vol(void);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* rbpcmbuf source */
|
||||
/* pcmbuf management & af control & mixer */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef MBED
|
||||
#include "mbed.h"
|
||||
#include "rtos.h"
|
||||
#endif
|
||||
#include "audioflinger.h"
|
||||
#include "cqueue.h"
|
||||
#include "app_audio.h"
|
||||
#include "app_utils.h"
|
||||
#include "hal_trace.h"
|
||||
|
||||
#include "rbplay.h"
|
||||
#include "rbpcmbuf.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define RB_PCMBUF_DMA_BUFFER_SIZE (1024*12)
|
||||
#define RB_PCMBUF_MEDIA_BUFFER_SIZE (1024*12)
|
||||
#define RB_DECODE_OUT_BUFFER_SIZE 1024
|
||||
|
||||
static uint8_t *rb_decode_out_buff;
|
||||
static uint8_t *rbplay_dma_buffer;
|
||||
static uint8_t *rb_pcmbuf_media_buf;
|
||||
static CQueue rb_pcmbuf_media_buf_queue;
|
||||
static osMutexId _rb_media_buf_queue_mutex_id = NULL;
|
||||
static osMutexDef(_rb_media_buf_queue_mutex);
|
||||
|
||||
#define LOCK_MEDIA_BUF_QUEUE() \
|
||||
if(osErrorISR == osMutexWait(_rb_media_buf_queue_mutex_id, osWaitForever)) {\
|
||||
error("%s LOCK_MEDIA_BUF_QUEUE from IRQ!!!!!!!\n",__func__);\
|
||||
}\
|
||||
|
||||
#define UNLOCK_MEDIA_BUF_QUEUE() \
|
||||
if(osErrorISR == osMutexRelease(_rb_media_buf_queue_mutex_id)){ \
|
||||
error("%s UNLOCK_MEDIA_BUF_QUEUE from IRQ!!!!!!\n"); \
|
||||
} \
|
||||
|
||||
static uint32_t rbplay_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
CQItemType *e1 = NULL;
|
||||
CQItemType *e2 = NULL;
|
||||
unsigned int len1 = 0;
|
||||
unsigned int len2 = 0;
|
||||
|
||||
LOCK_MEDIA_BUF_QUEUE();
|
||||
int ret = PeekCQueue(&rb_pcmbuf_media_buf_queue, len, &e1, &len1, &e2, &len2);
|
||||
UNLOCK_MEDIA_BUF_QUEUE();
|
||||
|
||||
if (ret == CQ_OK) {
|
||||
if (len1 > 0)
|
||||
memcpy(buf, e1, len1);
|
||||
if (len2 > 0)
|
||||
memcpy(buf + len1, e2, len - len1);
|
||||
LOCK_MEDIA_BUF_QUEUE();
|
||||
DeCQueue(&rb_pcmbuf_media_buf_queue, 0, len);
|
||||
UNLOCK_MEDIA_BUF_QUEUE();
|
||||
} else {
|
||||
warn("RBplay cache underflow");
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
extern uint8_t rb_ctl_get_vol(void);
|
||||
void rb_pcmbuf_init(void)
|
||||
{
|
||||
info("pcmbuff init");
|
||||
if(!_rb_media_buf_queue_mutex_id)
|
||||
_rb_media_buf_queue_mutex_id = osMutexCreate((osMutex(_rb_media_buf_queue_mutex)));
|
||||
|
||||
app_audio_mempool_init();
|
||||
|
||||
app_audio_mempool_get_buff(&rb_pcmbuf_media_buf, RB_PCMBUF_MEDIA_BUFFER_SIZE);
|
||||
InitCQueue(&rb_pcmbuf_media_buf_queue, RB_PCMBUF_MEDIA_BUFFER_SIZE, (unsigned char *)rb_pcmbuf_media_buf);
|
||||
|
||||
app_audio_mempool_get_buff(&rbplay_dma_buffer, RB_PCMBUF_DMA_BUFFER_SIZE);
|
||||
app_audio_mempool_get_buff(&rb_decode_out_buff, RB_DECODE_OUT_BUFFER_SIZE);
|
||||
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
|
||||
stream_cfg.bits = AUD_BITS_16;
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_2;
|
||||
stream_cfg.sample_rate = AUD_SAMPRATE_44100;
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
stream_cfg.vol = rb_ctl_get_vol();
|
||||
stream_cfg.handler = rbplay_more_data;
|
||||
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(rbplay_dma_buffer);
|
||||
stream_cfg.data_size = RB_PCMBUF_DMA_BUFFER_SIZE;
|
||||
|
||||
af_stream_open(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
af_stream_start(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
}
|
||||
|
||||
void *rb_pcmbuf_request_buffer(int *size)
|
||||
{
|
||||
*size = RB_DECODE_OUT_BUFFER_SIZE / 4;
|
||||
return rb_decode_out_buff;
|
||||
}
|
||||
|
||||
void rb_pcmbuf_write(unsigned int size)
|
||||
{
|
||||
int ret ;
|
||||
do {
|
||||
LOCK_MEDIA_BUF_QUEUE();
|
||||
ret = EnCQueue(&rb_pcmbuf_media_buf_queue, (CQItemType *)rb_decode_out_buff, size*(2*2));
|
||||
UNLOCK_MEDIA_BUF_QUEUE();
|
||||
osThreadYield();
|
||||
} while (ret == CQ_ERR);
|
||||
}
|
||||
|
||||
void rb_pcmbuf_stop(void)
|
||||
{
|
||||
af_stream_stop(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
af_stream_close(AUD_STREAM_ID_0,AUD_STREAM_PLAYBACK);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef RBPCMBUF_HEADER
|
||||
#define RBPCMBUF_HEADER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum _RB_PCMBUF_AUD_STATE_T {
|
||||
RB_PCMBUF_AUD_STATE_STOP = 0,
|
||||
RB_PCMBUF_AUD_STATE_START,
|
||||
} RB_PCMBUF_AUD_STATE_T;
|
||||
|
||||
void rb_pcmbuf_init(void);
|
||||
void rb_pcmbuf_stop(void);
|
||||
void *rb_pcmbuf_request_buffer(int *size);
|
||||
void rb_pcmbuf_write(unsigned int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RBPCMBUF_HEADER */
|
|
@ -0,0 +1,615 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* rbplay source */
|
||||
/* playback control & rockbox codec porting & codec thread */
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef MBED
|
||||
#include "mbed.h"
|
||||
#include "rtos.h"
|
||||
#endif
|
||||
#include "metadata.h"
|
||||
#include "codecs.h"
|
||||
#include "eq_export.h"
|
||||
#include "hal_overlay.h"
|
||||
#include "app_overlay.h"
|
||||
#include "audioflinger.h"
|
||||
#include "hal_trace.h"
|
||||
#include "apps.h"
|
||||
|
||||
#include "rbpcmbuf.h"
|
||||
#include "rbplaysd.h"
|
||||
#include "app_thread.h"
|
||||
#include "app_utils.h"
|
||||
#include "app_key.h"
|
||||
#include "rbplay.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __TWS__
|
||||
#include "app_tws.h"
|
||||
#endif
|
||||
|
||||
// TODO: remove
|
||||
#define BT_STREAM_RBCODEC 0x10 //from rockbox decoder
|
||||
|
||||
extern "C" {
|
||||
void flac_codec_main(int r);
|
||||
void flac_codec_run(void);
|
||||
void wav_codec_main(int r);
|
||||
void wav_codec_run(void);
|
||||
void mpa_codec_main(int r);
|
||||
void mpa_codec_run(void);
|
||||
void ape_codec_main(int r);
|
||||
void ape_codec_run(void);
|
||||
void sbc_codec_main(int r);
|
||||
void sbc_codec_run(void);
|
||||
}
|
||||
|
||||
extern void rb_pcm_player_open(enum AUD_BITS_T bits,enum AUD_SAMPRATE_T sample_rate,enum AUD_CHANNEL_NUM_T channel_num,uint8_t vol) ;
|
||||
|
||||
#if defined(__TWS__)
|
||||
typedef struct _rb_tws_codec_info{
|
||||
uint8_t update_codec_info;
|
||||
int32_t sample_freq;
|
||||
uint8_t channel_num;
|
||||
} rb_tws_codec_info;
|
||||
|
||||
rb_tws_codec_info codec_info = {1, 44100, 2};
|
||||
#endif
|
||||
|
||||
static osThreadId rb_decode_tid = NULL;
|
||||
static osThreadId rb_caller_tid = NULL;
|
||||
|
||||
typedef struct {
|
||||
uint32_t evt;
|
||||
uint32_t arg;
|
||||
} RBTHREAD_MSG_BLOCK;
|
||||
|
||||
#define RBTHREAD_MAILBOX_MAX (10)
|
||||
osMailQDef (rb_decode_mailbox, RBTHREAD_MAILBOX_MAX, RBTHREAD_MSG_BLOCK);
|
||||
int rb_decode_mailbox_put(RBTHREAD_MSG_BLOCK* msg_src);
|
||||
static osMailQId rb_decode_mailbox = NULL;
|
||||
|
||||
static void rb_decode_thread(void const *argument);
|
||||
osThreadDef(rb_decode_thread, osPriorityAboveNormal, 1, 1024 * 2, "rb_decorder");
|
||||
|
||||
// rbcodec info
|
||||
static int song_fd;
|
||||
static int song_format;
|
||||
static struct mp3entry *current_id3;
|
||||
static uint8_t rbplay_loop_on;
|
||||
|
||||
static volatile int rb_decode_halt_flag = 1;
|
||||
|
||||
struct codec_api ci_api;
|
||||
struct codec_api *ci = &ci_api;
|
||||
|
||||
// TODO
|
||||
volatile osThreadId thread_tid_waiter = NULL;
|
||||
|
||||
void init_dsp(void);
|
||||
void codec_configure(int setting, intptr_t value);
|
||||
|
||||
uint16_t g_rbplayer_curr_song_idx = 0;
|
||||
|
||||
extern void app_rbplay_exit(void);
|
||||
|
||||
extern void bt_change_to_iic(APP_KEY_STATUS *status, void *param);
|
||||
|
||||
extern void rb_thread_send_switch(bool next);
|
||||
extern void rb_thread_send_status_change(void );
|
||||
|
||||
enum APP_SYSFREQ_FREQ_T rb_player_get_work_freq(void);
|
||||
|
||||
static void rb_player_sync_close_done(void)
|
||||
{
|
||||
thread_tid_waiter = NULL;
|
||||
}
|
||||
|
||||
extern void rb_check_stream_reconfig(int32_t freq, uint8_t ch);
|
||||
static void f_codec_pcmbuf_insert_callback(
|
||||
const void *ch1, const void *ch2, int count)
|
||||
{
|
||||
struct dsp_buffer src;
|
||||
struct dsp_buffer dst;
|
||||
|
||||
src.remcount = count;
|
||||
src.pin[0] = (const unsigned char *)ch1;
|
||||
src.pin[1] = (const unsigned char *)ch2;
|
||||
src.proc_mask = 0;
|
||||
|
||||
if (rb_codec_running() == 0)
|
||||
return ;
|
||||
|
||||
#ifndef __TWS__
|
||||
while (src.remcount > 0) {
|
||||
dst.remcount = 0;
|
||||
dst.p16out = (short *)rb_pcmbuf_request_buffer(&dst.bufcount);
|
||||
|
||||
if (dst.p16out == NULL) {
|
||||
warn("No pcm buffer");
|
||||
osThreadYield();
|
||||
} else {
|
||||
dsp_process(ci->dsp, &src, &dst);
|
||||
|
||||
if (dst.remcount > 0) {
|
||||
rb_pcmbuf_write(dst.remcount);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
if(codec_info.update_codec_info){
|
||||
rb_set_sbc_encoder_freq_ch(codec_info.sample_freq, codec_info.channel_num); //should call this to set trigger timer
|
||||
rb_check_stream_reconfig(codec_info.sample_freq, codec_info.channel_num);
|
||||
codec_info.update_codec_info = 0;
|
||||
}
|
||||
|
||||
if(tws_local_player_need_tran_2_slave()){
|
||||
rb_tws_start_master_player(BT_STREAM_RBCODEC);
|
||||
}
|
||||
while(1){
|
||||
uint8_t * pcm_buff = NULL;
|
||||
dst.remcount = 0;
|
||||
dst.bufcount = MIN(src.remcount, 128); /* Arbitrary min request */
|
||||
dst.p16out = (short *)rb_pcmbuf_request_buffer(&dst.bufcount);
|
||||
pcm_buff = (uint8_t *)dst.p16out;
|
||||
ASSERT(pcm_buff, "Should request buffer");
|
||||
|
||||
dsp_process(ci->dsp, &src, &dst);
|
||||
|
||||
if (dst.remcount > 0) {
|
||||
while(rb_push_pcm_in_tws_buffer(pcm_buff, dst.remcount*2*2) == 0){
|
||||
osDelay(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (src.remcount <= 0) {
|
||||
return; /* No input remains and DSP purged */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void f_audio_codec_update_elapsed(unsigned long elapsed)
|
||||
{
|
||||
//info("Update elapsed: %d", elapsed);
|
||||
return;
|
||||
}
|
||||
|
||||
static size_t f_codec_filebuf_callback(void *ptr, size_t size)
|
||||
{
|
||||
ssize_t ret;
|
||||
ret = read(song_fd, ptr, size);
|
||||
if(ret < 0) {
|
||||
error("File read error: %d",ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static void * f_codec_request_buffer_callback(size_t *realsize, size_t reqsize)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void * f_codec_advance_buffer_callback(size_t amount)
|
||||
{
|
||||
off_t ret = lseek(song_fd, (off_t)(ci->curpos + amount), SEEK_SET);
|
||||
if(ret < 0) {
|
||||
error("File seek fail");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ci->curpos += amount;
|
||||
return (void *)ci;
|
||||
|
||||
}
|
||||
|
||||
static bool f_codec_seek_buffer_callback(size_t newpos)
|
||||
{
|
||||
off_t ret = lseek(song_fd, (off_t)newpos, SEEK_SET);
|
||||
if(ret < 0) {
|
||||
error("File seek fail");
|
||||
return false;
|
||||
}
|
||||
|
||||
ci->curpos = newpos;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void f_codec_seek_complete_callback(void)
|
||||
{
|
||||
info("Seek complete");
|
||||
dsp_configure(ci->dsp, DSP_FLUSH, 0);
|
||||
}
|
||||
|
||||
static void f_audio_codec_update_offset(size_t offset)
|
||||
{
|
||||
}
|
||||
|
||||
static void f_codec_configure_callback(int setting, intptr_t value)
|
||||
{
|
||||
dsp_configure(ci->dsp, setting, value);
|
||||
#ifdef __TWS__
|
||||
if(setting == DSP_SET_FREQUENCY){
|
||||
if(codec_info.sample_freq != value)
|
||||
codec_info.update_codec_info = 1;
|
||||
codec_info.sample_freq = value;
|
||||
}
|
||||
else if(setting == DSP_SET_STEREO_MODE){
|
||||
if(codec_info.channel_num != (value == STEREO_MONO ? 1 : 2))
|
||||
codec_info.update_codec_info = 1;
|
||||
codec_info.channel_num = value == STEREO_MONO ? 1 : 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static enum codec_command_action f_codec_get_command_callback(intptr_t *param)
|
||||
{
|
||||
if (rb_decode_halt_flag == 1)
|
||||
return CODEC_ACTION_HALT ;
|
||||
|
||||
return CODEC_ACTION_NULL;
|
||||
}
|
||||
|
||||
static bool f_codec_loop_track_callback(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static void init_ci_file(void)
|
||||
{
|
||||
ci->codec_get_buffer = 0;
|
||||
ci->pcmbuf_insert = f_codec_pcmbuf_insert_callback;
|
||||
ci->set_elapsed = f_audio_codec_update_elapsed;
|
||||
ci->read_filebuf = f_codec_filebuf_callback;
|
||||
ci->request_buffer = f_codec_request_buffer_callback;
|
||||
ci->advance_buffer = f_codec_advance_buffer_callback;
|
||||
ci->seek_buffer = f_codec_seek_buffer_callback;
|
||||
ci->seek_complete = f_codec_seek_complete_callback;
|
||||
ci->set_offset = f_audio_codec_update_offset;
|
||||
ci->configure = f_codec_configure_callback;
|
||||
ci->get_command = f_codec_get_command_callback;
|
||||
ci->loop_track = f_codec_loop_track_callback;
|
||||
}
|
||||
|
||||
static void rb_play_init(void)
|
||||
{
|
||||
init_dsp();
|
||||
|
||||
init_ci_file();
|
||||
|
||||
#ifndef __TWS__
|
||||
rb_pcmbuf_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void rb_play_codec_init(void)
|
||||
{
|
||||
RBTHREAD_MSG_BLOCK msg;
|
||||
msg.evt = (uint32_t)RB_CTRL_CMD_CODEC_INIT;
|
||||
msg.arg = (uint32_t)0;
|
||||
rb_decode_mailbox_put(&msg);
|
||||
}
|
||||
|
||||
void rb_play_codec_run(void)
|
||||
{
|
||||
RBTHREAD_MSG_BLOCK msg;
|
||||
msg.evt = (uint32_t)RB_CTRL_CMD_CODEC_RUN;
|
||||
msg.arg = (uint32_t)0;
|
||||
rb_decode_mailbox_put(&msg);
|
||||
}
|
||||
|
||||
static int rb_codec_init_desc(void )
|
||||
{
|
||||
info("Init decode format: %d", song_format);
|
||||
|
||||
switch (song_format) {
|
||||
case AFMT_MPA_L1:
|
||||
case AFMT_MPA_L2:
|
||||
case AFMT_MPA_L3:
|
||||
app_overlay_select(APP_OVERLAY_MPA);
|
||||
mpa_codec_main(CODEC_LOAD);
|
||||
break;
|
||||
// TODO: add APP_OVERLAY_APE
|
||||
#if 0
|
||||
case AFMT_APE:
|
||||
app_overlay_select(APP_OVERLAY_APE);
|
||||
ape_codec_main(CODEC_LOAD);
|
||||
break;
|
||||
case AFMT_SBC:
|
||||
app_overlay_select(APP_OVERLAY_A2DP);
|
||||
sbc_codec_main(CODEC_LOAD);
|
||||
break;
|
||||
case AFMT_FLAC:
|
||||
app_overlay_select(APP_OVERLAY_FLAC);
|
||||
flac_codec_main(CODEC_LOAD);
|
||||
break;
|
||||
case AFMT_PCM_WAV:
|
||||
app_overlay_select(APP_OVERLAY_WAV);
|
||||
wav_codec_main(CODEC_LOAD);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error("unkown codec type init\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rb_codec_loop_on(void)
|
||||
{
|
||||
#ifdef __TWS__
|
||||
//set start transfer to slave
|
||||
tws_local_player_set_tran_2_slave_flag(1);
|
||||
#endif
|
||||
switch (song_format) {
|
||||
case AFMT_MPA_L1:
|
||||
case AFMT_MPA_L2:
|
||||
case AFMT_MPA_L3:
|
||||
mpa_codec_run();
|
||||
break;
|
||||
#if 0
|
||||
case AFMT_SBC:
|
||||
sbc_codec_run();
|
||||
break;
|
||||
case AFMT_FLAC:
|
||||
flac_codec_run();
|
||||
break;
|
||||
case AFMT_PCM_WAV:
|
||||
wav_codec_run();
|
||||
break;
|
||||
case AFMT_APE:
|
||||
ape_codec_run();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error("unkown codec type run\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rb_thread_process_evt(RB_CTRL_CMD_T evt)
|
||||
{
|
||||
info("Decode event:%d", evt);
|
||||
|
||||
switch(evt) {
|
||||
case RB_CTRL_CMD_CODEC_INIT:
|
||||
rb_decode_halt_flag = 0;
|
||||
|
||||
rb_play_init();
|
||||
|
||||
/* get id3 */
|
||||
/* init ci info */
|
||||
ci->filesize = filesize(song_fd);
|
||||
ci->id3 = current_id3;
|
||||
ci->curpos = 0;
|
||||
|
||||
dsp_configure(ci->dsp, DSP_RESET, 0);
|
||||
dsp_configure(ci->dsp, DSP_FLUSH, 0);
|
||||
|
||||
rb_codec_init_desc();
|
||||
break;
|
||||
case RB_CTRL_CMD_CODEC_RUN:
|
||||
rbplay_loop_on = 1;
|
||||
|
||||
info("Play start");
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_PLAYER, rb_player_get_work_freq());
|
||||
app_stop_10_second_timer(APP_POWEROFF_TIMER_ID);
|
||||
rb_codec_loop_on();
|
||||
#if defined(__BTIF_AUTOPOWEROFF__)
|
||||
app_start_10_second_timer(APP_POWEROFF_TIMER_ID);
|
||||
#endif
|
||||
song_fd = 0;
|
||||
rb_decode_halt_flag = 1;
|
||||
if(thread_tid_waiter) {
|
||||
rb_player_sync_close_done();
|
||||
} else {
|
||||
rb_thread_send_status_change();
|
||||
rb_thread_send_switch(true);
|
||||
}
|
||||
#ifdef __TWS__
|
||||
//should update codec info after play one music
|
||||
codec_info.update_codec_info = 1;
|
||||
#endif
|
||||
rbplay_loop_on = 0;
|
||||
info("Play end");
|
||||
break;
|
||||
default:
|
||||
error("Unkown rb cmd %d\n",evt);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_decode_mailbox_put(RBTHREAD_MSG_BLOCK* msg_src)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
RBTHREAD_MSG_BLOCK *msg_p = NULL;
|
||||
|
||||
msg_p = (RBTHREAD_MSG_BLOCK*)osMailAlloc(rb_decode_mailbox, 0);
|
||||
if(!msg_p) {
|
||||
TRACE(3,"%s fail, evt:%d,arg=%d \n",__func__,msg_src->evt,msg_src->arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg_p->evt = msg_src->evt;
|
||||
msg_p->arg = msg_src->arg;
|
||||
|
||||
status = osMailPut(rb_decode_mailbox, msg_p);
|
||||
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int rb_decode_mailbox_free(RBTHREAD_MSG_BLOCK* msg_p)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
status = osMailFree(rb_decode_mailbox, msg_p);
|
||||
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int rb_decode_mailbox_get(RBTHREAD_MSG_BLOCK** msg_p)
|
||||
{
|
||||
osEvent evt;
|
||||
evt = osMailGet(rb_decode_mailbox, osWaitForever);
|
||||
if (evt.status == osEventMail) {
|
||||
*msg_p = (RBTHREAD_MSG_BLOCK *)evt.value.p;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void rb_decode_thread(void const *argument)
|
||||
{
|
||||
RB_CTRL_CMD_T action;
|
||||
RBTHREAD_MSG_BLOCK* msg_p;
|
||||
|
||||
while(1) {
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_PLAYER, APP_SYSFREQ_32K);
|
||||
// evt = osSignalWait(0, osWaitForever);
|
||||
if(0 == rb_decode_mailbox_get(&msg_p)) {
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_PLAYER, APP_SYSFREQ_104M);
|
||||
|
||||
action = (RB_CTRL_CMD_T) msg_p->evt;
|
||||
rb_caller_tid = (osThreadId) msg_p->arg ;
|
||||
|
||||
TRACE(3,"[%s] action:%d ,tid,0x%x", __func__, action,rb_caller_tid);
|
||||
rb_thread_process_evt(action);
|
||||
|
||||
rb_decode_mailbox_free(msg_p);
|
||||
if( rb_caller_tid)
|
||||
osSignalSet(rb_decode_tid, 0x1203);
|
||||
rb_caller_tid = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int app_rbplay_open(void)
|
||||
{
|
||||
if (rb_decode_tid != NULL) {
|
||||
warn("Decode thread reopen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rb_decode_mailbox = osMailCreate(osMailQ(rb_decode_mailbox), NULL);
|
||||
if (rb_decode_mailbox == NULL) {
|
||||
error("Failed to Create rb_decode_mailbox");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rb_decode_tid = osThreadCreate(osThread(rb_decode_thread), NULL);
|
||||
if (rb_decode_tid == NULL) {
|
||||
error("Failed to Create rb_thread \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rb_codec_running(void)
|
||||
{
|
||||
return ((rb_decode_halt_flag == 0)?1:0);
|
||||
}
|
||||
|
||||
void rb_codec_set_halt(int halt)
|
||||
{
|
||||
rb_decode_halt_flag = halt;
|
||||
}
|
||||
|
||||
void rb_thread_set_decode_vars(int fd, int type ,void* id3)
|
||||
{
|
||||
song_fd =fd;
|
||||
song_format = type;
|
||||
current_id3 = (struct mp3entry *)id3;
|
||||
}
|
||||
|
||||
void rb_player_sync_set_wait_thread(osThreadId tid)
|
||||
{
|
||||
if(rbplay_loop_on)
|
||||
thread_tid_waiter = tid;
|
||||
else
|
||||
thread_tid_waiter = NULL;
|
||||
}
|
||||
|
||||
void rb_player_sync_wait_close(void )
|
||||
{
|
||||
while(NULL != thread_tid_waiter) {
|
||||
osThreadYield();
|
||||
}
|
||||
}
|
||||
|
||||
enum APP_SYSFREQ_FREQ_T rb_player_get_work_freq(void)
|
||||
{
|
||||
enum APP_SYSFREQ_FREQ_T freq;
|
||||
|
||||
hal_sysfreq_print();
|
||||
|
||||
info("bitrate:%d freq:%d\n", ci->id3->bitrate, ci->id3->frequency);
|
||||
#ifndef __TWS__
|
||||
enum AUD_SAMPRATE_T sample_rate = AUD_SAMPRATE_44100;
|
||||
sample_rate =(enum AUD_SAMPRATE_T ) ci->id3->frequency;
|
||||
if(sample_rate > AUD_SAMPRATE_48000)
|
||||
freq = APP_SYSFREQ_208M;
|
||||
else if (sample_rate > AUD_SAMPRATE_44100)
|
||||
freq = APP_SYSFREQ_104M;
|
||||
else
|
||||
freq = APP_SYSFREQ_52M;
|
||||
|
||||
if(ci->id3->bitrate > 192)
|
||||
freq = APP_SYSFREQ_208M;
|
||||
else if (ci->id3->bitrate > 128)
|
||||
freq = APP_SYSFREQ_104M;
|
||||
else
|
||||
freq = APP_SYSFREQ_52M;
|
||||
|
||||
switch( song_format ) {
|
||||
case AFMT_APE:
|
||||
freq = APP_SYSFREQ_208M;
|
||||
break;
|
||||
case AFMT_FLAC:
|
||||
freq = APP_SYSFREQ_208M;
|
||||
break;
|
||||
case AFMT_PCM_WAV:
|
||||
freq = APP_SYSFREQ_208M;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
freq = APP_SYSFREQ_208M;
|
||||
#endif
|
||||
info("Decode thread run at: %d", freq);
|
||||
return freq;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* rbplay header */
|
||||
/* playback control & rockbox codec porting & codec thread */
|
||||
#ifndef RBPLAY_HEADER
|
||||
#define RBPLAY_HEADER
|
||||
|
||||
/* ---- APIs ---- */
|
||||
typedef enum _RB_CTRL_CMD_T {
|
||||
RB_CTRL_CMD_NONE = 0,
|
||||
RB_CTRL_CMD_SCAN_SONGS,
|
||||
RB_CTRL_CMD_CODEC_PARSE_FILE,
|
||||
RB_CTRL_CMD_CODEC_INIT,
|
||||
RB_CTRL_CMD_CODEC_RUN,
|
||||
RB_CTRL_CMD_CODEC_PAUSE,
|
||||
RB_CTRL_CMD_CODEC_STOP,
|
||||
RB_CTRL_CMD_CODEC_DEINIT,
|
||||
|
||||
RB_CTRL_CMD_CODEC_SEEK,
|
||||
|
||||
RB_CTRL_CMD_CODEC_MAX,
|
||||
} RB_CTRL_CMD_T;
|
||||
|
||||
int app_rbplay_open(void);
|
||||
void rb_play_codec_init(void);
|
||||
int rb_codec_running(void);
|
||||
|
||||
#endif /* RBPLAY_HEADER */
|
|
@ -0,0 +1,225 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* rbplay source */
|
||||
/* playback control & rockbox codec porting & codec thread */
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hal_trace.h"
|
||||
#include "metadata.h"
|
||||
#include "SDFileSystem.h"
|
||||
#include "rbplaysd.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define SD_LABEL "sd"
|
||||
#define PLAYLIST_PATH "/sd/Playlist"
|
||||
|
||||
static SDFileSystem *sdfs = NULL;
|
||||
|
||||
// TODO: remove ?
|
||||
static playlist_item sd_curritem;
|
||||
|
||||
playlist_struct sd_playlist;
|
||||
|
||||
static void playlist_insert(playlist_item* item)
|
||||
{
|
||||
int fd;
|
||||
fd = open(PLAYLIST_PATH, O_RDWR | O_CREAT);
|
||||
if (fd <= 0) {
|
||||
error("Playlist open fail");
|
||||
return;
|
||||
}
|
||||
|
||||
lseek(fd, item->song_idx * sizeof(playlist_item), SEEK_SET);
|
||||
write(fd, item, sizeof(playlist_item));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static bool sdcard_mount(void)
|
||||
{
|
||||
if (sdfs) {
|
||||
info("SD card already mount");
|
||||
return true;
|
||||
}
|
||||
|
||||
sdfs = new SDFileSystem(SD_LABEL);
|
||||
if (sdfs == NULL) {
|
||||
error("No memory for sd file system");
|
||||
return false;
|
||||
}
|
||||
|
||||
DIR *d;
|
||||
d = opendir("/" SD_LABEL);
|
||||
|
||||
if (!d) {
|
||||
warn("SD card mount error");
|
||||
return false;
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void app_rbplay_gen_playlist(playlist_struct *list)
|
||||
{
|
||||
struct dirent *p;
|
||||
DIR *d;
|
||||
uint32_t total;
|
||||
int fd = 0;
|
||||
struct mp3entry current_id3;
|
||||
playlist_item* sd_curritem_p = &sd_curritem;
|
||||
|
||||
memset(list,0x0,sizeof(playlist_struct));
|
||||
|
||||
d = opendir("/" SD_LABEL);
|
||||
if (!d) {
|
||||
error("SD card open fail");
|
||||
return;
|
||||
}
|
||||
|
||||
info("---------gen audio list---------");
|
||||
|
||||
total = 0;
|
||||
while (p = readdir(d)) {
|
||||
if (probe_file_format(p->d_name) == AFMT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
memset(&sd_curritem,0x0,sizeof(playlist_item));
|
||||
sd_curritem.song_idx = total;
|
||||
|
||||
sprintf(sd_curritem.file_path, "/" SD_LABEL "/%s", p->d_name);
|
||||
sprintf(sd_curritem.file_name, "%s", p->d_name);
|
||||
|
||||
info("Adding music: %s", sd_curritem.file_path);
|
||||
|
||||
fd = open(sd_curritem.file_path, O_RDONLY);
|
||||
|
||||
if (fd <= 0) {
|
||||
error("File %s open error", p->d_name);
|
||||
break;
|
||||
}
|
||||
|
||||
get_metadata(¤t_id3, fd, sd_curritem.file_path);
|
||||
close(fd);
|
||||
|
||||
if(current_id3.bitrate == 0 || current_id3.filesize == 0 || current_id3.length == 0)
|
||||
break;
|
||||
|
||||
info("bits:%d, type:%d, freq:%d", current_id3.bitrate,
|
||||
current_id3.codectype, current_id3.frequency);
|
||||
|
||||
sd_curritem_p->bitrate = current_id3.bitrate;
|
||||
sd_curritem_p->codectype = current_id3.codectype;
|
||||
sd_curritem_p->filesize = current_id3.filesize;
|
||||
sd_curritem_p->length = current_id3.length;
|
||||
sd_curritem_p->frequency = current_id3.frequency;
|
||||
|
||||
#ifdef PARSER_DETAIL
|
||||
char *str;
|
||||
str = current_id3.title;
|
||||
if(str != NULL) {
|
||||
memset(sd_curritem_p->title,0x0,MP3_TITLE_LEN);
|
||||
memcpy(sd_curritem_p->title ,str,strlen(str)>MP3_TITLE_LEN?MP3_TITLE_LEN:strlen(str));
|
||||
}
|
||||
|
||||
str = current_id3.artist;
|
||||
if(str != NULL) {
|
||||
memset(sd_curritem_p->artist,0x0,MP3_ARTIST_LEN);
|
||||
memcpy(sd_curritem_p->artist ,str,strlen(str)>MP3_ARTIST_LEN?MP3_ARTIST_LEN:strlen(str));
|
||||
}
|
||||
|
||||
str = current_id3.album;
|
||||
if(str != NULL) {
|
||||
memset(sd_curritem_p->album,0x0,MP3_ALBUM_LEN);
|
||||
memcpy(sd_curritem_p->album ,str,strlen(str)>MP3_ALBUM_LEN?MP3_ALBUM_LEN:strlen(str));
|
||||
}
|
||||
|
||||
str = current_id3.genre_string;
|
||||
if(str != NULL) {
|
||||
memset(sd_curritem_p->genre,0x0,MP3_GENRE_LEN);
|
||||
memcpy(sd_curritem_p->genre ,str,strlen(str)>MP3_GENRE_LEN?MP3_GENRE_LEN:strlen(str));
|
||||
}
|
||||
|
||||
str = current_id3.composer;
|
||||
if(str != NULL) {
|
||||
memset(sd_curritem_p->composer,0x0,MP3_COMPOSER_LEN);
|
||||
memcpy(sd_curritem_p->composer ,str,strlen(str)>MP3_COMPOSER_LEN?MP3_COMPOSER_LEN:strlen(str));
|
||||
}
|
||||
#endif
|
||||
playlist_insert(sd_curritem_p);
|
||||
total++;
|
||||
}
|
||||
|
||||
list->total_songs = total ;
|
||||
list->current_item = sd_curritem_p;
|
||||
|
||||
closedir(d);
|
||||
info("---------%d audio file searched---------" , total);
|
||||
|
||||
}
|
||||
|
||||
void app_rbplay_load_playlist(playlist_struct *list)
|
||||
{
|
||||
if(sdcard_mount() == false)
|
||||
return;
|
||||
|
||||
remove(PLAYLIST_PATH);
|
||||
|
||||
app_rbplay_gen_playlist(list);
|
||||
}
|
||||
|
||||
playlist_item *app_rbplay_get_playitem(const int idx)
|
||||
{
|
||||
int fd;
|
||||
if(idx >= sd_playlist.total_songs) {
|
||||
warn("Index exceed: %d / %d", idx, sd_playlist.total_songs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = open(PLAYLIST_PATH, O_RDONLY);
|
||||
|
||||
if (fd <= 0) {
|
||||
warn("SD card playlist can not open");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lseek(fd, sizeof(playlist_item) * idx, SEEK_SET);
|
||||
read(fd, sd_playlist.current_item, sizeof(playlist_item));
|
||||
info("Get playitem: %d: %s", idx, sd_playlist.current_item->file_path);
|
||||
|
||||
close(fd);
|
||||
|
||||
return sd_playlist.current_item;
|
||||
}
|
||||
|
||||
int app_ctl_remove_file(const int idx)
|
||||
{
|
||||
playlist_item *item = app_rbplay_get_playitem(idx);
|
||||
if (!item)
|
||||
return -1;
|
||||
remove(item->file_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __RBPLAYSD_H_
|
||||
#define __RBPLAYSD_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//playlist
|
||||
#define FILE_PATH_LEN (128+4)
|
||||
#define FILE_SHORT_NAME_LEN (128)
|
||||
#define MP3_TITLE_LEN (128)
|
||||
#define MP3_ARTIST_LEN (128)
|
||||
#define MP3_ALBUM_LEN (128)
|
||||
#define MP3_GENRE_LEN (128)
|
||||
#define MP3_COMPOSER_LEN (128)
|
||||
#define MP3_YEAR_STRING_LEN (8)
|
||||
#define MP3_TRACK_LEN (128)
|
||||
|
||||
typedef struct {
|
||||
char file_path[FILE_PATH_LEN];
|
||||
char file_name[FILE_SHORT_NAME_LEN];
|
||||
#ifdef PARSER_DETAIL
|
||||
uint16_t title[MP3_TITLE_LEN];
|
||||
uint16_t artist[MP3_ARTIST_LEN];
|
||||
uint16_t album[MP3_ALBUM_LEN];
|
||||
uint16_t genre[MP3_GENRE_LEN];
|
||||
uint16_t composer[MP3_COMPOSER_LEN];
|
||||
uint16_t year[MP3_YEAR_STRING_LEN];
|
||||
uint16_t track[MP3_TRACK_LEN];
|
||||
#endif
|
||||
uint16_t song_idx;
|
||||
|
||||
unsigned int codectype;
|
||||
unsigned int bitrate;
|
||||
unsigned long frequency;
|
||||
|
||||
unsigned long filesize; /* without headers; in bytes */
|
||||
unsigned long length; /* song length in ms */
|
||||
} playlist_item;
|
||||
|
||||
typedef struct {
|
||||
playlist_item *current_item;
|
||||
uint16_t total_songs;
|
||||
} playlist_struct;
|
||||
|
||||
void app_rbplay_load_playlist(playlist_struct *list);
|
||||
playlist_item *app_rbplay_get_playitem(const int idx);
|
||||
int app_ctl_remove_file(const int idx);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef RBPLAY_UTILS_H
|
||||
#define RBPLAY_UTILS_H
|
||||
|
||||
#undef warn
|
||||
#undef error
|
||||
|
||||
#define info(str, ...) TRACE(str, ##__VA_ARGS__)
|
||||
#define warn(str, ...) TRACE("\033[31mwarn: \033[0m" str, ##__VA_ARGS__)
|
||||
#define error(str, ...) TRACE("\033[31merr: \033[0m" str, ##__VA_ARGS__)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,185 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "app_utils.h"
|
||||
#include "audioflinger.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#include "string.h"
|
||||
#include "audio_dump.h"
|
||||
// #include "local_wav.h"
|
||||
|
||||
#define CHANNEL_NUM (2)
|
||||
|
||||
#define CHAR_BYTES (1)
|
||||
#define SHORT_BYTES (2)
|
||||
#define INT_BYTES (4)
|
||||
|
||||
#define SAMPLE_BITS (16)
|
||||
#define SAMPLE_BYTES (SAMPLE_BITS / 8)
|
||||
|
||||
|
||||
#define TX_SAMPLE_RATE (16000)
|
||||
#define RX_SAMPLE_RATE (16000)
|
||||
|
||||
|
||||
#define TX_FRAME_LEN (256)
|
||||
#define RX_FRAME_LEN (256)
|
||||
|
||||
#define TX_BUF_SIZE (TX_FRAME_LEN * CHANNEL_NUM * SAMPLE_BYTES * 2)
|
||||
#define RX_BUF_SIZE (RX_FRAME_LEN * CHANNEL_NUM * SAMPLE_BYTES * 2)
|
||||
|
||||
#if SAMPLE_BYTES == SHORT_BYTES
|
||||
typedef short VOICE_PCM_T;
|
||||
#elif SAMPLE_BYTES == INT_BYTES
|
||||
typedef int VOICE_PCM_T;
|
||||
#else
|
||||
#error "Invalid SAMPLE_BYTES!!!"
|
||||
#endif
|
||||
|
||||
static uint8_t POSSIBLY_UNUSED codec_capture_buf[TX_BUF_SIZE];
|
||||
static uint8_t POSSIBLY_UNUSED codec_playback_buf[RX_BUF_SIZE];
|
||||
|
||||
static uint32_t POSSIBLY_UNUSED codec_capture_cnt = 0;
|
||||
static uint32_t POSSIBLY_UNUSED codec_playback_cnt = 0;
|
||||
|
||||
#define CODEC_STREAM_ID AUD_STREAM_ID_0
|
||||
|
||||
static uint32_t codec_capture_callback(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
int POSSIBLY_UNUSED pcm_len = len / sizeof(VOICE_PCM_T) / CHANNEL_NUM;
|
||||
VOICE_PCM_T POSSIBLY_UNUSED *pcm_buf[CHANNEL_NUM];
|
||||
int interval_len = len * 2 / CHANNEL_NUM;
|
||||
|
||||
for (int i=0; i<CHANNEL_NUM; i++) {
|
||||
pcm_buf[i] = (VOICE_PCM_T *)(buf + i * interval_len);
|
||||
}
|
||||
|
||||
// TRACE(2,"[%s] cnt = %d", __func__, codec_capture_cnt++);
|
||||
|
||||
audio_dump_add_channel_data(0, pcm_buf[0], pcm_len);
|
||||
audio_dump_add_channel_data(1, pcm_buf[0], pcm_len);
|
||||
audio_dump_run();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint32_t codec_playback_callback(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
int POSSIBLY_UNUSED pcm_len = len / sizeof(VOICE_PCM_T) / CHANNEL_NUM;
|
||||
VOICE_PCM_T POSSIBLY_UNUSED *pcm_buf[CHANNEL_NUM];
|
||||
int interval_len = len * 2 / CHANNEL_NUM;
|
||||
|
||||
for (int i=0; i<CHANNEL_NUM; i++) {
|
||||
pcm_buf[i] = (VOICE_PCM_T *)(buf + i * interval_len);
|
||||
}
|
||||
|
||||
// TRACE(2,"[%s] cnt = %d", __func__, codec_playback_cnt++);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int voice_start(bool on)
|
||||
{
|
||||
int ret = 0;
|
||||
static bool isRun = false;
|
||||
enum APP_SYSFREQ_FREQ_T freq = APP_SYSFREQ_208M;
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
|
||||
if (isRun == on) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (on) {
|
||||
TRACE(1, "[%s]] ON", __func__);
|
||||
|
||||
af_set_priority(AF_USER_TEST, osPriorityHigh);
|
||||
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, freq);
|
||||
TRACE(2, "[%s] sys freq calc : %d\n", __func__, hal_sys_timer_calc_cpu_freq(5, 0));
|
||||
|
||||
// Initialize Cqueue
|
||||
codec_capture_cnt = 0;
|
||||
codec_playback_cnt = 0;
|
||||
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)CHANNEL_NUM;
|
||||
stream_cfg.data_size = TX_BUF_SIZE;
|
||||
stream_cfg.sample_rate = (enum AUD_SAMPRATE_T)TX_SAMPLE_RATE;
|
||||
stream_cfg.bits = (enum AUD_BITS_T)SAMPLE_BITS;
|
||||
stream_cfg.vol = 12;
|
||||
stream_cfg.chan_sep_buf = true;
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = AUD_INPUT_PATH_MAINMIC;
|
||||
stream_cfg.handler = codec_capture_callback;
|
||||
stream_cfg.data_ptr = codec_capture_buf;
|
||||
|
||||
TRACE(3, "[%s] codec capture sample_rate: %d, data_size: %d", __func__, stream_cfg.sample_rate, stream_cfg.data_size);
|
||||
af_stream_open(CODEC_STREAM_ID, AUD_STREAM_CAPTURE, &stream_cfg);
|
||||
ASSERT(ret == 0, "codec capture failed: %d", ret);
|
||||
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
stream_cfg.channel_num = (enum AUD_CHANNEL_NUM_T)CHANNEL_NUM;
|
||||
stream_cfg.data_size = RX_BUF_SIZE;
|
||||
stream_cfg.sample_rate = (enum AUD_SAMPRATE_T)RX_SAMPLE_RATE;
|
||||
stream_cfg.bits = (enum AUD_BITS_T)SAMPLE_BITS;
|
||||
stream_cfg.vol = 12;
|
||||
stream_cfg.chan_sep_buf = true;
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
stream_cfg.handler = codec_playback_callback;
|
||||
stream_cfg.data_ptr = codec_playback_buf;
|
||||
|
||||
TRACE(3, "[%s] codec playback sample_rate: %d, data_size: %d", __func__, stream_cfg.sample_rate, stream_cfg.data_size);
|
||||
af_stream_open(CODEC_STREAM_ID, AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
ASSERT(ret == 0, "codec playback failed: %d", ret);
|
||||
|
||||
audio_dump_init(TX_FRAME_LEN, sizeof(VOICE_PCM_T), 1);
|
||||
|
||||
// Start
|
||||
af_stream_start(CODEC_STREAM_ID, AUD_STREAM_CAPTURE);
|
||||
af_stream_start(CODEC_STREAM_ID, AUD_STREAM_PLAYBACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Close stream
|
||||
af_stream_stop(CODEC_STREAM_ID, AUD_STREAM_PLAYBACK);
|
||||
af_stream_stop(CODEC_STREAM_ID, AUD_STREAM_CAPTURE);
|
||||
|
||||
audio_dump_deinit();
|
||||
|
||||
af_stream_close(CODEC_STREAM_ID, AUD_STREAM_PLAYBACK);
|
||||
af_stream_close(CODEC_STREAM_ID, AUD_STREAM_CAPTURE);
|
||||
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
||||
|
||||
af_set_priority(AF_USER_TEST, osPriorityAboveNormal);
|
||||
|
||||
TRACE(1, "[%s] OFF", __func__);
|
||||
}
|
||||
|
||||
isRun=on;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool voice_test_status = true;
|
||||
void voice_test(void)
|
||||
{
|
||||
TRACE(2, "[%s] status = %d", __func__, voice_test_status);
|
||||
|
||||
voice_start(voice_test_status);
|
||||
voice_test_status = !voice_test_status;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,948 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
// Standard C Included Files
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "cmsis_os.h"
|
||||
#include "plat_types.h"
|
||||
#include "hal_uart.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#include "cqueue.h"
|
||||
#include "app_audio.h"
|
||||
#include "app_overlay.h"
|
||||
#include "app_ring_merge.h"
|
||||
#include "tgt_hardware.h"
|
||||
#include "bt_sco_chain.h"
|
||||
#include "iir_resample.h"
|
||||
#include "hfp_api.h"
|
||||
#include "audio_prompt_sbc.h"
|
||||
#ifdef TX_RX_PCM_MASK
|
||||
#include "bt_drv_interface.h"
|
||||
#endif
|
||||
|
||||
#define ENABLE_LPC_PLC
|
||||
|
||||
#define ENABLE_PLC_ENCODER
|
||||
|
||||
// BT
|
||||
#include "a2dp_api.h"
|
||||
#include "plc_utils.h"
|
||||
extern "C" {
|
||||
|
||||
#include "plc_8000.h"
|
||||
#include "speech_utils.h"
|
||||
#if defined(HFP_1_6_ENABLE)
|
||||
#include "codec_sbc.h"
|
||||
#ifndef ENABLE_LPC_PLC
|
||||
#include "plc_16000.h"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CVSD_BYPASS)
|
||||
#include "Pcm8k_Cvsd.h"
|
||||
#endif
|
||||
#ifndef ENABLE_LPC_PLC
|
||||
static void *speech_plc;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ENABLE_LPC_PLC)
|
||||
#include "lpc_plc_api.h"
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
extern int32_t *aec_echo_buf;
|
||||
#else
|
||||
extern short *aec_echo_buf;
|
||||
#endif
|
||||
|
||||
// #define SPEECH_RX_PLC_DUMP_DATA
|
||||
|
||||
// #define PLC_DEBUG_PRINT_DATA
|
||||
|
||||
//#define DEBUG_SCO_DUMP
|
||||
|
||||
#ifdef SPEECH_RX_PLC_DUMP_DATA
|
||||
#include "audio_dump.h"
|
||||
int16_t *audio_dump_temp_buf = NULL;
|
||||
#endif
|
||||
|
||||
// app_bt_stream.cpp::bt_sco_player(), used buffer size
|
||||
#define APP_BT_STREAM_USE_BUF_SIZE (1024*2)
|
||||
#if defined(SCO_OPTIMIZE_FOR_RAM)
|
||||
uint8_t *sco_overlay_ram_buf = NULL;
|
||||
int sco_overlay_ram_buf_len = 0;
|
||||
#endif
|
||||
|
||||
static bool resample_needed_flag = false;
|
||||
static int sco_frame_length;
|
||||
static int codec_frame_length;
|
||||
static int16_t *resample_buf = NULL;
|
||||
static IirResampleState *uplink_resample_st = NULL;
|
||||
static IirResampleState *downlink_resample_st = NULL;
|
||||
|
||||
#define MSBC_FRAME_SIZE (60)
|
||||
|
||||
#if defined(HFP_1_6_ENABLE)
|
||||
static btif_sbc_decoder_t *msbc_decoder;
|
||||
static float msbc_eq_band_gain[CFG_HW_AUD_EQ_NUM_BANDS]= {0,0,0,0,0,0,0,0};
|
||||
|
||||
#define MSBC_ENCODE_PCM_LEN (240)
|
||||
|
||||
#ifndef ENABLE_LPC_PLC
|
||||
struct PLC_State msbc_plc_state;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_PLC_ENCODER
|
||||
static btif_sbc_encoder_t *msbc_plc_encoder;
|
||||
static int16_t *msbc_plc_encoder_buffer = NULL;
|
||||
#define MSBC_CODEC_DELAY (73)
|
||||
#endif
|
||||
|
||||
static btif_sbc_encoder_t *msbc_encoder;
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_LPC_PLC)
|
||||
LpcPlcState *msbc_plc_state = NULL;
|
||||
#endif
|
||||
|
||||
#define VOICEBTPCM_TRACE(s,...)
|
||||
//TRACE(s, ##__VA_ARGS__)
|
||||
|
||||
#if defined(CHIP_BEST1400) || defined(CHIP_BEST1402) || defined(CHIP_BEST2300P) || defined(CHIP_BEST2300A) || defined(CHIP_BEST2001)
|
||||
#define MSBC_MUTE_PATTERN (0x55)
|
||||
#else
|
||||
#define MSBC_MUTE_PATTERN (0x00)
|
||||
#endif
|
||||
#define MSBC_LEN_FORMBT_PER_FRAME (60) //Bytes; only for BES platform.
|
||||
#define SAMPLES_LEN_PER_FRAME (120)
|
||||
#define MSBC_LEN_PER_FRAME (57+3)
|
||||
#define BYTES_PER_PCM_FRAME (SAMPLES_LEN_PER_FRAME*2)
|
||||
|
||||
// Add 1 to ensure it never be out of bounds when msbc_offset is 1
|
||||
unsigned char msbc_buf_all[MSBC_LEN_FORMBT_PER_FRAME*3+1];
|
||||
#if defined(HFP_1_6_ENABLE)
|
||||
static int msbc_find_first_sync = 0;
|
||||
static unsigned int msbc_offset = 0;
|
||||
static unsigned int next_frame_flag = 0;
|
||||
#endif
|
||||
static PacketLossState pld;
|
||||
|
||||
extern bool bt_sco_codec_is_msbc(void);
|
||||
|
||||
int process_downlink_msbc_frames(unsigned char *msbc_buf, unsigned int msbc_len, unsigned char *pcm_buf,unsigned int pcm_len);
|
||||
int process_downlink_cvsd_frames(unsigned char *cvsd_buf, unsigned int cvsd_len, unsigned char *pcm_buf,unsigned int pcm_len);
|
||||
int process_uplink_msbc_frames(unsigned char *pcm_buf, unsigned int pcm_len, unsigned char *msbc_buf,unsigned int msbc_len);
|
||||
int process_uplink_cvsd_frames(unsigned char *pcm_buf, unsigned int pcm_len, unsigned char *cvsd_buf,unsigned int cvsd_len);
|
||||
|
||||
|
||||
int process_downlink_bt_voice_frames(uint8_t *in_buf, uint32_t in_len, uint8_t *out_buf,uint32_t out_len,int32_t codec_type)
|
||||
{
|
||||
//TRACE(3,"[%s] in_len = %d, out_len = %d", __FUNCTION__, in_len, out_len);
|
||||
|
||||
#if defined(SPEECH_RX_24BIT)
|
||||
out_len /= 2;
|
||||
#endif
|
||||
|
||||
int16_t *pcm_buf = (int16_t *)out_buf;
|
||||
int pcm_len = out_len / sizeof(int16_t);
|
||||
|
||||
if (resample_needed_flag == true) {
|
||||
pcm_buf = resample_buf;
|
||||
pcm_len = sco_frame_length;
|
||||
}
|
||||
|
||||
if (bt_sco_codec_is_msbc()) {
|
||||
process_downlink_msbc_frames(in_buf, in_len, (uint8_t *)pcm_buf, pcm_len * sizeof(int16_t));
|
||||
|
||||
// Down sampling
|
||||
if (resample_needed_flag) {
|
||||
iir_resample_process(downlink_resample_st, pcm_buf, (int16_t *)out_buf, pcm_len);
|
||||
pcm_buf = (int16_t *)out_buf;
|
||||
pcm_len >>= 1;
|
||||
}
|
||||
} else {
|
||||
process_downlink_cvsd_frames(in_buf, in_len, (uint8_t *)pcm_buf, pcm_len * sizeof(int16_t));
|
||||
|
||||
// Up sampling
|
||||
if (resample_needed_flag) {
|
||||
iir_resample_process(downlink_resample_st, pcm_buf, (int16_t *)out_buf, pcm_len);
|
||||
pcm_buf = (int16_t *)out_buf;
|
||||
pcm_len <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SPEECH_RX_24BIT)
|
||||
int32_t *buf32 = (int32_t *)out_buf;
|
||||
for (int i = pcm_len - 1; i >= 0; i--) {
|
||||
buf32[i] = ((int32_t)pcm_buf[i] << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
speech_rx_process(pcm_buf, &pcm_len);
|
||||
|
||||
#if defined(SPEECH_RX_24BIT)
|
||||
out_len *= 2;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_uplink_bt_voice_frames(uint8_t *in_buf, uint32_t in_len, uint8_t *ref_buf, uint32_t ref_len, uint8_t *out_buf,uint32_t out_len,int32_t codec_type)
|
||||
{
|
||||
//TRACE(3,"[%s] in_len = %d, out_len = %d", __FUNCTION__, in_len, out_len);
|
||||
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
int32_t *pcm_buf = (int32_t *)in_buf;
|
||||
int pcm_len = in_len / sizeof(int32_t);
|
||||
#else
|
||||
int16_t *pcm_buf = (int16_t *)in_buf;
|
||||
int pcm_len = in_len / sizeof(int16_t);
|
||||
#endif
|
||||
|
||||
#if defined(SPEECH_TX_AEC_CODEC_REF)
|
||||
ASSERT(pcm_len % (SPEECH_CODEC_CAPTURE_CHANNEL_NUM + 1) == 0, "[%s] pcm_len(%d) should be divided by %d", __FUNCTION__, pcm_len, SPEECH_CODEC_CAPTURE_CHANNEL_NUM + 1);
|
||||
// copy reference buffer
|
||||
#if defined(SPEECH_TX_AEC) || defined(SPEECH_TX_AEC2) || defined(SPEECH_TX_AEC3) || defined(SPEECH_TX_AEC2FLOAT) || defined(SPEECH_TX_THIRDPARTY)
|
||||
for (int i = SPEECH_CODEC_CAPTURE_CHANNEL_NUM, j = 0; i < pcm_len; i += SPEECH_CODEC_CAPTURE_CHANNEL_NUM + 1, j++) {
|
||||
aec_echo_buf[j] = pcm_buf[i];
|
||||
}
|
||||
#endif
|
||||
for (int i = 0, j = 0; i < pcm_len; i += SPEECH_CODEC_CAPTURE_CHANNEL_NUM + 1, j += SPEECH_CODEC_CAPTURE_CHANNEL_NUM) {
|
||||
for (int k = 0; k < SPEECH_CODEC_CAPTURE_CHANNEL_NUM; k++)
|
||||
pcm_buf[j + k] = pcm_buf[i + k];
|
||||
}
|
||||
pcm_len = pcm_len / (SPEECH_CODEC_CAPTURE_CHANNEL_NUM + 1) * SPEECH_CODEC_CAPTURE_CHANNEL_NUM;
|
||||
#elif (defined(SPEECH_TX_AEC) || defined(SPEECH_TX_AEC2) || defined(SPEECH_TX_AEC3) || defined(SPEECH_TX_AEC2FLOAT) || defined(SPEECH_TX_THIRDPARTY))
|
||||
int ref_pcm_len = ref_len / sizeof(int16_t);
|
||||
ASSERT(pcm_len / SPEECH_CODEC_CAPTURE_CHANNEL_NUM == ref_pcm_len, "[%s] Length error: %d / %d != %d", __func__, pcm_len, SPEECH_CODEC_CAPTURE_CHANNEL_NUM, ref_pcm_len);
|
||||
|
||||
for (int i = 0; i < ref_pcm_len; i++) {
|
||||
aec_echo_buf[i] = ref_buf[i];
|
||||
}
|
||||
#endif
|
||||
speech_tx_process(pcm_buf, aec_echo_buf, &pcm_len);
|
||||
|
||||
#if defined(SPEECH_TX_24BIT)
|
||||
int32_t *buf24 = (int32_t *)pcm_buf;
|
||||
int16_t *buf16 = (int16_t *)pcm_buf;
|
||||
for (int i = 0; i < pcm_len; i++)
|
||||
buf16[i] = (buf24[i] >> 8);
|
||||
#endif
|
||||
|
||||
int16_t *pcm_buf_16bits = (int16_t *)pcm_buf;
|
||||
|
||||
if (bt_sco_codec_is_msbc()) {
|
||||
// Up sampling
|
||||
if (resample_needed_flag) {
|
||||
iir_resample_process(uplink_resample_st, (int16_t *)pcm_buf_16bits, resample_buf, pcm_len);
|
||||
pcm_buf_16bits = resample_buf;
|
||||
pcm_len = sco_frame_length;
|
||||
}
|
||||
|
||||
process_uplink_msbc_frames((uint8_t *)pcm_buf_16bits, pcm_len * sizeof(int16_t), out_buf, out_len);
|
||||
} else {
|
||||
// Down sampling
|
||||
if (resample_needed_flag) {
|
||||
iir_resample_process(uplink_resample_st, (int16_t *)pcm_buf_16bits, resample_buf, pcm_len);
|
||||
pcm_buf_16bits = resample_buf;
|
||||
pcm_len = sco_frame_length;
|
||||
}
|
||||
|
||||
process_uplink_cvsd_frames((uint8_t *)pcm_buf_16bits, pcm_len * sizeof(int16_t), out_buf, out_len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_downlink_msbc_frames(unsigned char *msbc_buf, unsigned int msbc_len, unsigned char *pcm_buf,unsigned int pcm_len)
|
||||
{
|
||||
#if defined(HFP_1_6_ENABLE)
|
||||
|
||||
|
||||
btif_sbc_pcm_data_t pcm_data;
|
||||
unsigned int msbc_offset_lowdelay = 0;
|
||||
unsigned int i,j;
|
||||
unsigned char *msbc_buffer=(unsigned char *)msbc_buf;
|
||||
int frame_flag[6]; // 1: good frame; 0:bad frame;
|
||||
bt_status_t ret;
|
||||
unsigned int frame_counter=0;
|
||||
unsigned short byte_decode = 0;
|
||||
unsigned int msbc_offset_total = 0;
|
||||
int msbc_offset_drift[6] = {0, };
|
||||
|
||||
short *dec_pcm_buf=( short *)pcm_buf;
|
||||
unsigned char dec_msbc_buf[MSBC_LEN_PER_FRAME] = {0, };
|
||||
|
||||
//unsigned int timer_begin=hal_sys_timer_get();
|
||||
|
||||
//TRACE(2,"process_downlink_msbc_frames:pcm_len:%d,msbc_len:%d",pcm_len,msbc_len);
|
||||
|
||||
//TRACE(1,"decode_msbc_frame,msbc_len:%d",msbc_len);
|
||||
for(i =0; i<msbc_len; i++)
|
||||
{
|
||||
msbc_buf_all[i+MSBC_LEN_FORMBT_PER_FRAME]=msbc_buffer[i];
|
||||
}
|
||||
|
||||
/*
|
||||
for(i =0; i<msbc_len/2; i=i+10)
|
||||
{
|
||||
TRACE(10,"0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,",
|
||||
DecMsbcBufAll[i],DecMsbcBufAll[i+1],DecMsbcBufAll[i+2],DecMsbcBufAll[i+3],DecMsbcBufAll[i+4],
|
||||
DecMsbcBufAll[i+5],DecMsbcBufAll[i+6],DecMsbcBufAll[i+7],DecMsbcBufAll[i+8],DecMsbcBufAll[i+9]);
|
||||
}
|
||||
*/
|
||||
|
||||
for(j =0; j<msbc_len/MSBC_LEN_FORMBT_PER_FRAME; j++)
|
||||
{
|
||||
frame_flag[j]=0;
|
||||
}
|
||||
|
||||
if(msbc_find_first_sync==0)
|
||||
{
|
||||
for(i =0; i<msbc_len; i++)
|
||||
{
|
||||
if((msbc_buf_all[i]==0x01)&&((msbc_buf_all[i+1]&0x0f)==0x08)&&(msbc_buf_all[i+2]==0xad))break;
|
||||
}
|
||||
|
||||
TRACE(1,"sync......:%d",i);
|
||||
|
||||
if(i<msbc_len)
|
||||
{
|
||||
msbc_find_first_sync=1;
|
||||
msbc_offset=i%MSBC_LEN_FORMBT_PER_FRAME;
|
||||
msbc_offset_total=i;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < msbc_len / MSBC_LEN_FORMBT_PER_FRAME; j++)
|
||||
{
|
||||
frame_flag[j] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(msbc_find_first_sync==1)
|
||||
{
|
||||
int value=0;
|
||||
unsigned char headerm1 = 0;
|
||||
unsigned char header0 = 0;
|
||||
unsigned char header1 = 0;
|
||||
unsigned char header2 = 0;
|
||||
unsigned char header3 = 0;
|
||||
// unsigned char tail0 = 0;
|
||||
|
||||
if(msbc_offset==0||msbc_offset==1)
|
||||
{
|
||||
msbc_offset_lowdelay=msbc_offset+60;
|
||||
//msbc_offset_lowdelay=msbc_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
msbc_offset_lowdelay=msbc_offset;
|
||||
}
|
||||
|
||||
|
||||
//check again
|
||||
for(j =0; j<(msbc_len/MSBC_LEN_FORMBT_PER_FRAME); j++)
|
||||
{
|
||||
if (next_frame_flag == 1)
|
||||
{
|
||||
next_frame_flag = 0;
|
||||
frame_flag[j] = 1;
|
||||
continue;
|
||||
}
|
||||
if(msbc_offset_lowdelay==0&&j==0)
|
||||
{
|
||||
headerm1=0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
headerm1 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME-1];
|
||||
}
|
||||
|
||||
header0 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME];
|
||||
header1 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME + 1];
|
||||
header2 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME + 2];
|
||||
header3 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME + 3];
|
||||
|
||||
/*if ((headerm1 == 0x01) && ((header0 & 0x0f) == 0x08) && (header1 == 0xad) ||
|
||||
(header0 == 0x01) && ((header1 & 0x0f) == 0x08) && (header2 == 0xad) ||
|
||||
(header1 == 0x01) && ((header2 & 0x0f) == 0x08) && (header3 == 0xad))
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
}*/
|
||||
if ((headerm1 == 0x01) && ((header0 & 0x0f) == 0x08) && (header1 == 0xad))
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
// It seems that offset is reduced by 1
|
||||
msbc_offset_drift[j] = -1;
|
||||
TRACE(1,"[%s] msbc_offset is reduced by 1", __FUNCTION__);
|
||||
/*
|
||||
tail0 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME + 59 - 1];
|
||||
if (tail0 == 0x00 || tail0 == 0x01|| tail0==0xff)
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_flag[j] = 1;
|
||||
next_frame_flag = 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if ((header0 == 0x01) && ((header1 & 0x0f) == 0x08) && (header2 == 0xad))
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
/*
|
||||
tail0 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME + 59];
|
||||
if (tail0 == 0x00 || tail0 == 0x01|| tail0==0xff)
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_flag[j] = 1;
|
||||
next_frame_flag = 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if ((header1 == 0x01) && ((header2 & 0x0f) == 0x08) && (header3 == 0xad))
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
msbc_offset_drift[j] = 1;
|
||||
TRACE(1,"[%s] msbc_offset is increased by 1", __FUNCTION__);
|
||||
/*
|
||||
tail0 = msbc_buf_all[msbc_offset_lowdelay + j*MSBC_LEN_FORMBT_PER_FRAME + 59 + 1];
|
||||
if (tail0 == 0x00 || tail0==0x01|| tail0==0xff)
|
||||
{
|
||||
frame_flag[j] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_flag[j] = 1;
|
||||
next_frame_flag = 1;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((header0 == MSBC_MUTE_PATTERN)&& ((header1 & 0x0f) == (MSBC_MUTE_PATTERN & 0x0f)) && (header2 == MSBC_MUTE_PATTERN))
|
||||
{
|
||||
frame_flag[j]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((msbc_offset_lowdelay+j*MSBC_LEN_FORMBT_PER_FRAME)>=msbc_offset_total)
|
||||
{
|
||||
frame_flag[j]=3;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_flag[j]=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(j =0; j<msbc_len/MSBC_LEN_FORMBT_PER_FRAME; j++)
|
||||
{
|
||||
value=value|frame_flag[j];
|
||||
}
|
||||
//abnormal msbc packet.
|
||||
if(value>1)msbc_find_first_sync=0;
|
||||
}
|
||||
|
||||
while((frame_counter<msbc_len/MSBC_LEN_FORMBT_PER_FRAME)&&(frame_counter<pcm_len/BYTES_PER_PCM_FRAME))
|
||||
{
|
||||
//TRACE(3,"[%s] decoding, offset %d, offset drift %d", __FUNCTION__, msbc_offset, msbc_offset_drift[frame_counter]);
|
||||
// skip first byte when msbc_offset == 0 and msbc_offset_drift == -1
|
||||
unsigned int start_idx = 0;
|
||||
if (msbc_offset_lowdelay == 0 && msbc_offset_drift[frame_counter] == -1) {
|
||||
start_idx = 1;
|
||||
dec_msbc_buf[0] = 0x01;
|
||||
}
|
||||
for(i = start_idx; i<MSBC_LEN_PER_FRAME; i++)
|
||||
{
|
||||
//DecMsbcBuf[i]=DecMsbcBufAll[i+msbc_offset_lowdelay+frame_counter*MSBC_LEN_FORMBT_PER_FRAME+2];
|
||||
dec_msbc_buf[i]=msbc_buf_all[i+msbc_offset_lowdelay+msbc_offset_drift[frame_counter]+frame_counter*MSBC_LEN_FORMBT_PER_FRAME];
|
||||
}
|
||||
|
||||
//TRACE(1,"msbc header:0x%x",DecMsbcBuf[0]);
|
||||
|
||||
#ifdef SPEECH_RX_PLC_DUMP_DATA
|
||||
audio_dump_add_channel_data(2, (short *)dec_msbc_buf, MSBC_LEN_PER_FRAME/2);
|
||||
#endif
|
||||
|
||||
plc_type_t plc_type = packet_loss_detection_process(&pld, dec_msbc_buf);
|
||||
|
||||
if(plc_type != PLC_TYPE_PASS) {
|
||||
memset(dec_pcm_buf, 0, SAMPLES_LEN_PER_FRAME * sizeof(int16_t));
|
||||
goto do_plc;
|
||||
}
|
||||
|
||||
pcm_data.sampleFreq = BTIF_SBC_CHNL_SAMPLE_FREQ_16;
|
||||
pcm_data.numChannels = 1;
|
||||
pcm_data.dataLen = 0;
|
||||
pcm_data.data = (uint8_t *)dec_pcm_buf;
|
||||
|
||||
ret = btif_sbc_decode_frames(msbc_decoder,
|
||||
(unsigned char *)dec_msbc_buf,
|
||||
MSBC_LEN_PER_FRAME, &byte_decode,
|
||||
&pcm_data, SAMPLES_LEN_PER_FRAME*2,
|
||||
msbc_eq_band_gain);
|
||||
|
||||
//ASSERT(ret == BT_STS_SUCCESS, "[%s] msbc decoder should never fail", __FUNCTION__);
|
||||
if (ret != BT_STS_SUCCESS) {
|
||||
plc_type = PLC_TYPE_DECODER_ERROR;
|
||||
packet_loss_detection_update_histogram(&pld, plc_type);
|
||||
}
|
||||
|
||||
do_plc:
|
||||
if (plc_type == PLC_TYPE_PASS) {
|
||||
#if defined(ENABLE_LPC_PLC)
|
||||
lpc_plc_save(msbc_plc_state, dec_pcm_buf);
|
||||
#else
|
||||
PLC_good_frame(&msbc_plc_state, dec_pcm_buf, dec_pcm_buf);
|
||||
#endif
|
||||
#ifdef SPEECH_RX_PLC_DUMP_DATA
|
||||
audio_dump_add_channel_data(0, (short *)dec_pcm_buf, MSBC_ENCODE_PCM_LEN/2);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(1,"PLC bad frame, plc type: %d", plc_type);
|
||||
#if defined(PLC_DEBUG_PRINT_DATA)
|
||||
DUMP8("0x%02x, ", dec_msbc_buf, 60);
|
||||
#endif
|
||||
|
||||
#ifdef SPEECH_RX_PLC_DUMP_DATA
|
||||
for(uint32_t i=0; i< MSBC_ENCODE_PCM_LEN/2; i++)
|
||||
{
|
||||
audio_dump_temp_buf[i] = (plc_type - 1) * 5000;
|
||||
}
|
||||
audio_dump_add_channel_data(0, audio_dump_temp_buf, MSBC_ENCODE_PCM_LEN/2);
|
||||
#endif
|
||||
#if defined(ENABLE_LPC_PLC)
|
||||
lpc_plc_generate(msbc_plc_state, dec_pcm_buf,
|
||||
#if defined(ENABLE_PLC_ENCODER)
|
||||
msbc_plc_encoder_buffer
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
#if defined(ENABLE_PLC_ENCODER)
|
||||
pcm_data.sampleFreq = BTIF_SBC_CHNL_SAMPLE_FREQ_16;
|
||||
pcm_data.numChannels = 1;
|
||||
pcm_data.dataLen = MSBC_ENCODE_PCM_LEN;
|
||||
pcm_data.data = (uint8_t *)(msbc_plc_encoder_buffer + MSBC_CODEC_DELAY);
|
||||
|
||||
btif_plc_update_sbc_decoder_state(msbc_plc_encoder, &pcm_data, msbc_decoder, msbc_eq_band_gain);
|
||||
#endif
|
||||
|
||||
#else
|
||||
pcm_data.sampleFreq = BTIF_SBC_CHNL_SAMPLE_FREQ_16;
|
||||
pcm_data.numChannels = 1;
|
||||
pcm_data.dataLen = 0;
|
||||
pcm_data.data = (uint8_t *)dec_pcm_buf;
|
||||
|
||||
ret = btif_sbc_decode_frames(msbc_decoder,
|
||||
(unsigned char *)indices0,
|
||||
MSBC_LEN_PER_FRAME, &byte_decode,
|
||||
&pcm_data, SAMPLES_LEN_PER_FRAME*2,
|
||||
msbc_eq_band_gain);
|
||||
|
||||
PLC_bad_frame(&msbc_plc_state, dec_pcm_buf, dec_pcm_buf);
|
||||
|
||||
ASSERT(ret == BT_STS_SUCCESS, "[%s] msbc decoder should never fail", __FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SPEECH_RX_PLC_DUMP_DATA
|
||||
audio_dump_add_channel_data(1, (short *)dec_pcm_buf, MSBC_ENCODE_PCM_LEN/2);
|
||||
audio_dump_run();
|
||||
#endif
|
||||
|
||||
dec_pcm_buf=dec_pcm_buf+SAMPLES_LEN_PER_FRAME;
|
||||
frame_counter++;
|
||||
}
|
||||
|
||||
for(i =0; i<MSBC_LEN_FORMBT_PER_FRAME; i++)
|
||||
{
|
||||
msbc_buf_all[i]=msbc_buf_all[i+msbc_len];
|
||||
}
|
||||
#endif
|
||||
//TRACE(1,"msbc + plc:%d", (hal_sys_timer_get()-timer_begin));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TX_RX_PCM_MASK
|
||||
#define MSBC_OFFSET_BYTES (0)
|
||||
#else
|
||||
#if defined (PCM_FAST_MODE)
|
||||
#define MSBC_OFFSET_BYTES (1) //This is reletive with chip.
|
||||
#else
|
||||
#define MSBC_OFFSET_BYTES (2) //This is reletive with chip.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MSBC_OFFSET_HEADER0_BYTES ((MSBC_LEN_PER_FRAME-MSBC_OFFSET_BYTES)%MSBC_LEN_PER_FRAME)
|
||||
#define MSBC_OFFSET_HEADER1_BYTES ((MSBC_LEN_PER_FRAME-MSBC_OFFSET_BYTES+1)%MSBC_LEN_PER_FRAME)
|
||||
|
||||
int process_uplink_msbc_frames(unsigned char *pcm_buf, unsigned int pcm_len, unsigned char *msbc_buf,unsigned int msbc_len)
|
||||
{
|
||||
#if defined(HFP_1_6_ENABLE)
|
||||
uint32_t frame_counter=0;
|
||||
static uint32_t frame_counter_total=0;
|
||||
static btif_sbc_pcm_data_t pcm_data_enc;
|
||||
uint16_t bytes_encoded = 0;
|
||||
static uint8_t msbc_buf_frame[MSBC_LEN_PER_FRAME*2];
|
||||
uint16_t msbc_len_frame=MSBC_LEN_PER_FRAME-3;
|
||||
|
||||
//TRACE(2,"process_uplink_msbc_frames:pcm_len:%d,msbc_len:%d",pcm_len,msbc_len);
|
||||
|
||||
while((frame_counter<msbc_len/MSBC_LEN_FORMBT_PER_FRAME)&&(frame_counter<pcm_len/BYTES_PER_PCM_FRAME))
|
||||
{
|
||||
unsigned short *msbc_buf_dst_p;
|
||||
pcm_data_enc.data = pcm_buf+frame_counter*BYTES_PER_PCM_FRAME;
|
||||
pcm_data_enc.dataLen = BYTES_PER_PCM_FRAME;
|
||||
|
||||
#if (MSBC_OFFSET_BYTES==0)||(MSBC_OFFSET_BYTES==1)||(MSBC_OFFSET_BYTES==2)
|
||||
//body
|
||||
btif_sbc_encode_frames(msbc_encoder, &pcm_data_enc, &bytes_encoded, &(msbc_buf_frame[2-MSBC_OFFSET_BYTES]), (uint16_t *)&msbc_len_frame, 0xFFFF);
|
||||
//tail
|
||||
msbc_buf_frame[59-MSBC_OFFSET_BYTES]=0x00;
|
||||
//header
|
||||
msbc_buf_frame[MSBC_OFFSET_HEADER0_BYTES]=0x01;
|
||||
switch((frame_counter_total%4))
|
||||
{
|
||||
case 0:
|
||||
msbc_buf_frame[MSBC_OFFSET_HEADER1_BYTES]=0x08;
|
||||
break;
|
||||
case 1:
|
||||
msbc_buf_frame[MSBC_OFFSET_HEADER1_BYTES]=0x38;
|
||||
break;
|
||||
case 2:
|
||||
msbc_buf_frame[MSBC_OFFSET_HEADER1_BYTES]=0xc8;
|
||||
break;
|
||||
default:
|
||||
msbc_buf_frame[MSBC_OFFSET_HEADER1_BYTES]=0xf8;
|
||||
break;
|
||||
}
|
||||
msbc_buf_dst_p=(uint16_t *)(msbc_buf+frame_counter*MSBC_LEN_PER_FRAME*2);
|
||||
|
||||
for (int i = 0; i < MSBC_LEN_PER_FRAME; i++)
|
||||
{
|
||||
msbc_buf_dst_p[i] = msbc_buf_frame[i]<<8;
|
||||
}
|
||||
#else
|
||||
btif_sbc_encode_frames(msbc_encoder, &pcm_data_enc, &bytes_encoded, &(msbc_buf_frame[MSBC_LEN_PER_FRAME+2]), (uint16_t *)&msbc_len_frame, 0xFFFF);
|
||||
msbc_buf_frame[MSBC_LEN_PER_FRAME+0]=0x01;
|
||||
switch((frame_counter_total%4))
|
||||
{
|
||||
case 0:
|
||||
msbc_buf_frame[MSBC_LEN_PER_FRAME+1]=0x08;
|
||||
break;
|
||||
case 1:
|
||||
msbc_buf_frame[MSBC_LEN_PER_FRAME+1]=0x38;
|
||||
break;
|
||||
case 2:
|
||||
msbc_buf_frame[MSBC_LEN_PER_FRAME+1]=0xc8;
|
||||
break;
|
||||
default:
|
||||
msbc_buf_frame[MSBC_LEN_PER_FRAME+1]=0xf8;
|
||||
break;
|
||||
}
|
||||
msbc_buf_frame[MSBC_LEN_PER_FRAME+59]=0x00;
|
||||
msbc_buf_dst_p=(uint16_t *)(msbc_buf+frame_counter*MSBC_LEN_PER_FRAME*2);
|
||||
|
||||
for (int i = 0; i < MSBC_LEN_PER_FRAME; i++)
|
||||
{
|
||||
msbc_buf_dst_p[i] = msbc_buf_frame[MSBC_OFFSET_BYTES+i]<<8;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MSBC_LEN_PER_FRAME; i++)
|
||||
{
|
||||
msbc_buf_frame[i] = msbc_buf_frame[MSBC_LEN_PER_FRAME+i];
|
||||
}
|
||||
#endif
|
||||
frame_counter_total++;
|
||||
frame_counter++;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CHIP_BEST2300A)
|
||||
#define CVSD_OFFSET_BYTES (120)
|
||||
#else
|
||||
#define CVSD_OFFSET_BYTES (120 - 2)
|
||||
#endif
|
||||
|
||||
#define CVSD_PACKET_SIZE (120)
|
||||
|
||||
#define CVSD_PACKET_NUM (2)
|
||||
|
||||
#define CVSD_MUTE_PATTERN (0x55)
|
||||
|
||||
#define CVSD_PCM_SIZE (120)
|
||||
|
||||
static POSSIBLY_UNUSED uint8_t cvsd_buf_all[CVSD_PACKET_SIZE + CVSD_OFFSET_BYTES];
|
||||
|
||||
POSSIBLY_UNUSED plc_type_t check_cvsd_mute_pattern(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
if (buf[i] != CVSD_MUTE_PATTERN)
|
||||
return PLC_TYPE_PASS;
|
||||
|
||||
return PLC_TYPE_CONTROLLER_MUTE;
|
||||
}
|
||||
|
||||
int process_downlink_cvsd_frames(unsigned char *cvsd_buf, unsigned int cvsd_len, unsigned char *pcm_buf,unsigned int pcm_len)
|
||||
{
|
||||
//TRACE(2,"process_downlink_cvsd_frames pcm_len:%d,cvsd_len:%d",pcm_len,cvsd_len);
|
||||
|
||||
#if defined(CVSD_BYPASS) && defined(ENABLE_LPC_PLC)
|
||||
ASSERT(cvsd_len % CVSD_PACKET_SIZE == 0, "[%s] cvsd input length(%d) error", __FUNCTION__, cvsd_len);
|
||||
for (uint32_t i = 0; i < cvsd_len; i += CVSD_PACKET_SIZE) {
|
||||
memcpy(&cvsd_buf_all[CVSD_OFFSET_BYTES], cvsd_buf, CVSD_PACKET_SIZE);
|
||||
memcpy(cvsd_buf, cvsd_buf_all, CVSD_PACKET_SIZE);
|
||||
memcpy(cvsd_buf_all, &cvsd_buf_all[CVSD_PACKET_SIZE], CVSD_OFFSET_BYTES);
|
||||
|
||||
//DUMP16("0x%x, ", cvsd_buf, CVSD_PACKET_SIZE / 2);
|
||||
|
||||
plc_type_t plc_type = check_cvsd_mute_pattern(cvsd_buf, CVSD_PACKET_SIZE);
|
||||
|
||||
if (plc_type != PLC_TYPE_PASS) {
|
||||
memset(pcm_buf, 0, CVSD_PCM_SIZE);
|
||||
goto do_plc;
|
||||
}
|
||||
|
||||
CvsdToPcm8k(cvsd_buf, (short *)(pcm_buf), CVSD_PACKET_SIZE/2, 0);
|
||||
|
||||
do_plc:
|
||||
if (plc_type == PLC_TYPE_PASS) {
|
||||
lpc_plc_save(msbc_plc_state, (int16_t *)pcm_buf);
|
||||
} else {
|
||||
TRACE(1,"PLC bad frame, plc type: %d", plc_type);
|
||||
#if defined(PLC_DEBUG_PRINT_DATA)
|
||||
DUMP16("0x%x, ", cvsd_buf, CVSD_PACKET_SIZE / 2);
|
||||
#endif
|
||||
lpc_plc_generate(msbc_plc_state, (int16_t *)pcm_buf, NULL);
|
||||
}
|
||||
|
||||
cvsd_buf += CVSD_PACKET_SIZE;
|
||||
pcm_buf += CVSD_PCM_SIZE;
|
||||
}
|
||||
#else
|
||||
#if defined(CVSD_BYPASS)
|
||||
CvsdToPcm8k(cvsd_buf, (short *)(pcm_buf), cvsd_len/2, 0);
|
||||
#else
|
||||
memcpy(pcm_buf,cvsd_buf,cvsd_len);
|
||||
#endif
|
||||
#ifndef ENABLE_LPC_PLC
|
||||
speech_plc_8000((PlcSt_8000 *)speech_plc, (short *)pcm_buf, pcm_len);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
int process_uplink_cvsd_frames(unsigned char *pcm_buf, unsigned int pcm_len, unsigned char *cvsd_buf,unsigned int cvsd_len)
|
||||
{
|
||||
//TRACE(2,"process_uplink_cvsd_frames pcm_len:%d,cvsd_len:%d",pcm_len,cvsd_len);
|
||||
#if defined(CVSD_BYPASS)
|
||||
Pcm8kToCvsd((short *)pcm_buf, cvsd_buf, pcm_len/2);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
void *voicebtpcm_get_ext_buff(int size)
|
||||
{
|
||||
uint8_t *pBuff = NULL;
|
||||
if (size % 4)
|
||||
{
|
||||
size = size + (4 - size % 4);
|
||||
}
|
||||
app_audio_mempool_get_buff(&pBuff, size);
|
||||
VOICEBTPCM_TRACE(2,"[%s] len:%d", __func__, size);
|
||||
return (void*)pBuff;
|
||||
}
|
||||
// sco sample rate: encoder/decoder sample rate
|
||||
// codec sample rate: hardware sample rate
|
||||
int voicebtpcm_pcm_audio_init(int sco_sample_rate, int codec_sample_rate)
|
||||
{
|
||||
uint8_t POSSIBLY_UNUSED *speech_buf = NULL;
|
||||
int POSSIBLY_UNUSED speech_len = 0;
|
||||
|
||||
sco_frame_length = SPEECH_FRAME_MS_TO_LEN(sco_sample_rate, SPEECH_SCO_FRAME_MS);
|
||||
codec_frame_length = SPEECH_FRAME_MS_TO_LEN(codec_sample_rate, SPEECH_SCO_FRAME_MS);
|
||||
|
||||
TRACE(3, "[%s] TX: sample rate = %d, frame len = %d", __func__, codec_sample_rate, codec_frame_length);
|
||||
TRACE(3, "[%s] RX: sample rate = %d, frame len = %d", __func__, codec_sample_rate, codec_frame_length);
|
||||
|
||||
memset(cvsd_buf_all, CVSD_MUTE_PATTERN, sizeof(cvsd_buf_all));
|
||||
#if defined(HFP_1_6_ENABLE)
|
||||
|
||||
memset(msbc_buf_all,MSBC_MUTE_PATTERN&0xFF, sizeof(msbc_buf_all));
|
||||
if (bt_sco_codec_is_msbc())
|
||||
{
|
||||
app_audio_mempool_get_buff((uint8_t **)&msbc_encoder, sizeof(btif_sbc_encoder_t));
|
||||
app_audio_mempool_get_buff((uint8_t **)&msbc_decoder, sizeof(btif_sbc_decoder_t));
|
||||
|
||||
//init msbc encoder
|
||||
btif_sbc_init_encoder(msbc_encoder);
|
||||
msbc_encoder->streamInfo.mSbcFlag = 1;
|
||||
msbc_encoder->streamInfo.numChannels = 1;
|
||||
msbc_encoder->streamInfo.channelMode = BTIF_SBC_CHNL_MODE_MONO;
|
||||
|
||||
msbc_encoder->streamInfo.bitPool = 26;
|
||||
msbc_encoder->streamInfo.sampleFreq = BTIF_SBC_CHNL_SAMPLE_FREQ_16;
|
||||
msbc_encoder->streamInfo.allocMethod = BTIF_SBC_ALLOC_METHOD_LOUDNESS;
|
||||
msbc_encoder->streamInfo.numBlocks = BTIF_MSBC_BLOCKS;
|
||||
msbc_encoder->streamInfo.numSubBands = 8;
|
||||
|
||||
//init msbc decoder
|
||||
const float EQLevel[25] =
|
||||
{
|
||||
0.0630957, 0.0794328, 0.1, 0.1258925, 0.1584893,
|
||||
0.1995262, 0.2511886, 0.3162278, 0.398107, 0.5011872,
|
||||
0.6309573, 0.794328, 1, 1.258925, 1.584893,
|
||||
1.995262, 2.5118864, 3.1622776, 3.9810717, 5.011872,
|
||||
6.309573, 7.943282, 10, 12.589254, 15.848932
|
||||
};//-12~12
|
||||
uint8_t i;
|
||||
|
||||
for (i=0; i<sizeof(msbc_eq_band_gain)/sizeof(float); i++)
|
||||
{
|
||||
msbc_eq_band_gain[i] = EQLevel[cfg_aud_eq_sbc_band_settings[i]+12];
|
||||
}
|
||||
|
||||
btif_sbc_init_decoder(msbc_decoder);
|
||||
|
||||
msbc_decoder->streamInfo.mSbcFlag = 1;
|
||||
msbc_decoder->streamInfo.bitPool = 26;
|
||||
msbc_decoder->streamInfo.sampleFreq = BTIF_SBC_CHNL_SAMPLE_FREQ_16;
|
||||
msbc_decoder->streamInfo.channelMode = BTIF_SBC_CHNL_MODE_MONO;
|
||||
msbc_decoder->streamInfo.allocMethod = BTIF_SBC_ALLOC_METHOD_LOUDNESS;
|
||||
/* Number of blocks used to encode the stream (4, 8, 12, or 16) */
|
||||
msbc_decoder->streamInfo.numBlocks = BTIF_MSBC_BLOCKS;
|
||||
/* The number of subbands in the stream (4 or 8) */
|
||||
msbc_decoder->streamInfo.numSubBands = 8;
|
||||
msbc_decoder->streamInfo.numChannels = 1;
|
||||
|
||||
//init msbc plc
|
||||
#ifndef ENABLE_LPC_PLC
|
||||
InitPLC(&msbc_plc_state);
|
||||
#endif
|
||||
|
||||
next_frame_flag = 0;
|
||||
msbc_find_first_sync = 0;
|
||||
|
||||
packet_loss_detection_init(&pld);
|
||||
|
||||
#if defined(ENABLE_PLC_ENCODER)
|
||||
app_audio_mempool_get_buff((uint8_t **)&msbc_plc_encoder, sizeof(btif_sbc_encoder_t));
|
||||
btif_sbc_init_encoder(msbc_plc_encoder);
|
||||
msbc_plc_encoder->streamInfo.mSbcFlag = 1;
|
||||
msbc_plc_encoder->streamInfo.bitPool = 26;
|
||||
msbc_plc_encoder->streamInfo.sampleFreq = BTIF_SBC_CHNL_SAMPLE_FREQ_16;
|
||||
msbc_plc_encoder->streamInfo.channelMode = BTIF_SBC_CHNL_MODE_MONO;
|
||||
msbc_plc_encoder->streamInfo.allocMethod = BTIF_SBC_ALLOC_METHOD_LOUDNESS;
|
||||
/* Number of blocks used to encode the stream (4, 8, 12, or 16) */
|
||||
msbc_plc_encoder->streamInfo.numBlocks = BTIF_MSBC_BLOCKS;
|
||||
/* The number of subbands in the stream (4 or 8) */
|
||||
msbc_plc_encoder->streamInfo.numSubBands = 8;
|
||||
msbc_plc_encoder->streamInfo.numChannels = 1;
|
||||
app_audio_mempool_get_buff((uint8_t **)&msbc_plc_encoder_buffer, sizeof(int16_t) * (SAMPLES_LEN_PER_FRAME + MSBC_CODEC_DELAY));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifndef ENABLE_LPC_PLC
|
||||
speech_plc = (PlcSt_8000 *)speech_plc_8000_init(voicebtpcm_get_ext_buff);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CVSD_BYPASS)
|
||||
Pcm8k_CvsdInit();
|
||||
#endif
|
||||
|
||||
#ifdef SPEECH_RX_PLC_DUMP_DATA
|
||||
audio_dump_temp_buf = (int16_t *)voicebtpcm_get_ext_buff(sizeof(int16_t) * 120);
|
||||
audio_dump_init(120, sizeof(short), 3);
|
||||
#endif
|
||||
|
||||
resample_needed_flag = (sco_sample_rate == codec_sample_rate) ? 0 : 1;
|
||||
|
||||
if (resample_needed_flag) {
|
||||
TRACE(1, "[%s] SCO <-- Resample --> CODEC", __func__);
|
||||
resample_buf = (int16_t *)voicebtpcm_get_ext_buff(sizeof(int16_t) * sco_frame_length);
|
||||
}
|
||||
|
||||
#if defined(SCO_OPTIMIZE_FOR_RAM)
|
||||
sco_overlay_ram_buf_len = hal_overlay_get_text_free_size((enum HAL_OVERLAY_ID_T)APP_OVERLAY_HFP);
|
||||
sco_overlay_ram_buf = (uint8_t *)hal_overlay_get_text_free_addr((enum HAL_OVERLAY_ID_T)APP_OVERLAY_HFP);
|
||||
#endif
|
||||
|
||||
speech_len = app_audio_mempool_free_buff_size() - APP_BT_STREAM_USE_BUF_SIZE;
|
||||
speech_buf = (uint8_t *)voicebtpcm_get_ext_buff(speech_len);
|
||||
|
||||
int tx_frame_ms = SPEECH_PROCESS_FRAME_MS;
|
||||
int rx_frame_ms = SPEECH_SCO_FRAME_MS;
|
||||
speech_init(codec_sample_rate, codec_sample_rate, tx_frame_ms, rx_frame_ms, SPEECH_SCO_FRAME_MS, speech_buf, speech_len);
|
||||
|
||||
if (resample_needed_flag) {
|
||||
uplink_resample_st = iir_resample_init(codec_frame_length, iir_resample_choose_mode(codec_sample_rate, sco_sample_rate));
|
||||
downlink_resample_st = iir_resample_init(sco_frame_length, iir_resample_choose_mode(sco_sample_rate, codec_sample_rate));
|
||||
}
|
||||
|
||||
#if defined(ENABLE_LPC_PLC)
|
||||
msbc_plc_state = lpc_plc_create(sco_sample_rate);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int voicebtpcm_pcm_audio_deinit(void)
|
||||
{
|
||||
TRACE(1,"[%s] Close...", __func__);
|
||||
// TRACE(2,"[%s] app audio buffer free = %d", __func__, app_audio_mempool_free_buff_size());
|
||||
|
||||
#if defined(ENABLE_LPC_PLC)
|
||||
lpc_plc_destroy(msbc_plc_state);
|
||||
#endif
|
||||
|
||||
if (resample_needed_flag) {
|
||||
iir_resample_destroy(uplink_resample_st);
|
||||
iir_resample_destroy(downlink_resample_st);
|
||||
}
|
||||
|
||||
speech_deinit();
|
||||
|
||||
packet_loss_detection_report(&pld);
|
||||
|
||||
#if defined(SCO_OPTIMIZE_FOR_RAM)
|
||||
sco_overlay_ram_buf = NULL;
|
||||
sco_overlay_ram_buf_len = 0;
|
||||
#endif
|
||||
|
||||
// TRACE(1,"Free buf = %d", app_audio_mempool_free_buff_size());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifdef MBED
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
// Standard C Included Files
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hal_uart.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_timer.h"
|
||||
|
||||
/*!
|
||||
* * @brief Standard Winodws PCM wave file header length
|
||||
* */
|
||||
#define WAVE_FILE_HEADER_SIZE 0x2CU
|
||||
|
||||
typedef struct wave_header
|
||||
{
|
||||
uint8_t riff[4];
|
||||
uint32_t size;
|
||||
uint8_t waveFlag[4];
|
||||
uint8_t fmt[4];
|
||||
uint32_t fmtLen;
|
||||
uint16_t tag;
|
||||
uint16_t channels;
|
||||
uint32_t sampFreq;
|
||||
uint32_t byteRate;
|
||||
uint16_t blockAlign;
|
||||
uint16_t bitSamp;
|
||||
uint8_t dataFlag[4];
|
||||
uint32_t length;
|
||||
} wave_header_t;
|
||||
|
||||
/*!
|
||||
* * @brief Wave file structure
|
||||
* */
|
||||
typedef struct wave_file
|
||||
{
|
||||
wave_header_t header;
|
||||
uint32_t *data;
|
||||
}wave_file_t;
|
||||
|
||||
/* player */
|
||||
static unsigned int g_total_play_count = 0;
|
||||
static unsigned int g_curr_play_index = 0;
|
||||
|
||||
/* wave */
|
||||
wave_file_t g_wave_file_info;
|
||||
static char g_wav_header[WAVE_FILE_HEADER_SIZE];
|
||||
FILE *g_wave_file_handle = NULL;
|
||||
static int32_t (*wav_file_palyback_callback)(int32_t ) = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void wav_file_set_playeback_cb(int32_t (* cb)(int32_t))
|
||||
{
|
||||
wav_file_palyback_callback = cb;
|
||||
}
|
||||
bool wav_file_isplaydone(void)
|
||||
{
|
||||
return (g_curr_play_index >= g_total_play_count)? true : false;
|
||||
}
|
||||
uint32_t wav_file_audio_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
// static uint32_t g_preIrqTime = 0;
|
||||
uint32_t reallen = 0;
|
||||
// int32_t stime,etime;
|
||||
int32_t status;
|
||||
|
||||
/* play done ? */
|
||||
if(wav_file_isplaydone()) {
|
||||
memset(buf, 0, len);
|
||||
status = 0;
|
||||
if (wav_file_palyback_callback)
|
||||
wav_file_palyback_callback(status);
|
||||
return (len);
|
||||
}
|
||||
// stime = hal_sys_timer_get();
|
||||
/* read file */
|
||||
if (g_wave_file_handle)
|
||||
reallen = fread(buf, 1, len, g_wave_file_handle);
|
||||
// etime = hal_sys_timer_get();
|
||||
if (reallen != len){
|
||||
memset(buf, 0, len);
|
||||
status = -1;
|
||||
if (wav_file_palyback_callback)
|
||||
wav_file_palyback_callback(status);
|
||||
return (len);
|
||||
}
|
||||
|
||||
// TRACE(5,"wav_file_audio_more_data irqDur:%d fsSpend:%d, readbuff:0x%08x %d/%d\n ", TICKS_TO_MS(stime - g_preIrqTime),TICKS_TO_MS(etime - stime),buf,reallen,len);
|
||||
// g_preIrqTime = stime;
|
||||
|
||||
/* walk index */
|
||||
g_curr_play_index += reallen;
|
||||
|
||||
return reallen;
|
||||
}
|
||||
|
||||
uint32_t get_wav_data(wave_file_t *waveFile)
|
||||
{
|
||||
uint8_t *dataTemp = (uint8_t *)waveFile->data;
|
||||
|
||||
// check for RIFF
|
||||
memcpy(waveFile->header.riff, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
if( memcmp( (uint8_t*)waveFile->header.riff, "RIFF", 4) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get size
|
||||
memcpy(&waveFile->header.size, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
|
||||
TRACE(1,"WAV header size [%d]\n", waveFile->header.size);
|
||||
|
||||
// .wav file flag
|
||||
memcpy(waveFile->header.waveFlag, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
if( memcmp( (uint8_t*)waveFile->header.waveFlag, "WAVE", 4) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fmt
|
||||
memcpy(waveFile->header.fmt, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
if( memcmp( (uint8_t*)waveFile->header.fmt, "fmt ", 4) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fmt length
|
||||
memcpy(&waveFile->header.fmtLen, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
|
||||
// Tag: PCM or not
|
||||
memcpy(&waveFile->header.tag, dataTemp, 4);
|
||||
dataTemp += 2;
|
||||
|
||||
// Channels
|
||||
memcpy(&waveFile->header.channels, dataTemp, 4);
|
||||
dataTemp += 2;
|
||||
|
||||
TRACE(1,"WAV channels [%d]\n", waveFile->header.channels);
|
||||
|
||||
// Sample Rate in Hz
|
||||
memcpy(&waveFile->header.sampFreq, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
memcpy(&waveFile->header.byteRate, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
|
||||
TRACE(1,"WAV sample_rate [%d]\n", waveFile->header.sampFreq);
|
||||
TRACE(1,"WAV byteRate [%d]\n", waveFile->header.byteRate);
|
||||
|
||||
// quantize bytes for per samp point
|
||||
memcpy(&waveFile->header.blockAlign, dataTemp, 4);
|
||||
dataTemp += 2;
|
||||
memcpy(&waveFile->header.bitSamp, dataTemp, 4);
|
||||
dataTemp += 2;
|
||||
|
||||
TRACE(1,"WAV bitSamp [%d]\n", waveFile->header.bitSamp);
|
||||
|
||||
// Data
|
||||
memcpy(waveFile->header.dataFlag, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
if( memcmp( (uint8_t*)waveFile->header.dataFlag, "data ", 4) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
memcpy(&waveFile->header.length, dataTemp, 4);
|
||||
dataTemp += 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void audio_wav_init(wave_file_t *newWav)
|
||||
{
|
||||
get_wav_data(newWav);
|
||||
|
||||
// Configure the play audio g_format
|
||||
//g_format.bits = newWav->header.bitSamp;
|
||||
//g_format.sample_rate = newWav->header.sampFreq;
|
||||
//g_format.mclk = 256 * g_format.sample_rate ;
|
||||
//g_format.mono_streo = (sai_mono_streo_t)((newWav->header.channels) - 1);
|
||||
}
|
||||
|
||||
uint32_t play_wav_file(char *file_path)
|
||||
{
|
||||
uint32_t bytesToRead = 0;
|
||||
|
||||
wave_file_t *newWav = &g_wave_file_info;
|
||||
|
||||
memset(&g_wave_file_info, 0, sizeof(g_wave_file_info));
|
||||
|
||||
g_wave_file_handle = fopen(file_path, "rb");
|
||||
|
||||
if(g_wave_file_handle == NULL) {
|
||||
TRACE(1,"WAV file %s open fail\n", file_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fread(&g_wav_header, WAVE_FILE_HEADER_SIZE, 1, g_wave_file_handle);
|
||||
|
||||
newWav->data = (uint32_t *)&g_wav_header;
|
||||
|
||||
audio_wav_init(newWav);
|
||||
|
||||
// Remove header size from byte count
|
||||
// Adjust note duration by divider value, wav tables in pcm_data.h are 200ms by default
|
||||
bytesToRead = (newWav->header.length - WAVE_FILE_HEADER_SIZE);
|
||||
|
||||
g_curr_play_index = 0;
|
||||
g_total_play_count = bytesToRead;
|
||||
|
||||
return newWav->header.sampFreq;
|
||||
}
|
||||
|
||||
uint32_t stop_wav_file(void)
|
||||
{
|
||||
memset(&g_wave_file_info, 0, sizeof(g_wave_file_info));
|
||||
g_curr_play_index = 0;
|
||||
g_total_play_count = 0;
|
||||
if (g_wave_file_handle){
|
||||
fclose(g_wave_file_handle);
|
||||
g_wave_file_handle = NULL;
|
||||
}
|
||||
if (wav_file_palyback_callback)
|
||||
wav_file_palyback_callback = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
subdir-ccflags-y += -Iplatform/drivers/ana \
|
||||
$(BT_IF_INCLUDES) \
|
||||
-Iservices/ble_app/app_main \
|
||||
-Iservices/app_ibrt/inc \
|
||||
-Iservices/ibrt_ui/inc \
|
||||
-Iservices/ibrt_core/inc
|
||||
|
||||
ifeq ($(VOICE_PROMPT),1)
|
||||
CFLAGS_app_battery.o += -DMEDIA_PLAYER_SUPPORT
|
||||
endif
|
||||
|
|
@ -0,0 +1,903 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "tgt_hardware.h"
|
||||
#include "pmu.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_gpadc.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_gpio.h"
|
||||
#include "hal_iomux.h"
|
||||
#include "hal_chipid.h"
|
||||
#include "app_thread.h"
|
||||
#include "app_battery.h"
|
||||
#include "apps.h"
|
||||
#include "app_status_ind.h"
|
||||
#ifdef BT_USB_AUDIO_DUAL_MODE
|
||||
#include "btusb_audio.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __INTERCONNECTION__
|
||||
#include "app_ble_mode_switch.h"
|
||||
#endif
|
||||
|
||||
#if (defined(BTUSB_AUDIO_MODE) || defined(BTUSB_AUDIO_MODE))
|
||||
extern "C" bool app_usbaudio_mode_on(void);
|
||||
#endif
|
||||
|
||||
#define APP_BATTERY_TRACE(s,...)
|
||||
// TRACE(s, ##__VA_ARGS__)
|
||||
|
||||
#ifndef APP_BATTERY_MIN_MV
|
||||
#define APP_BATTERY_MIN_MV (3200)
|
||||
#endif
|
||||
|
||||
#ifndef APP_BATTERY_MAX_MV
|
||||
#define APP_BATTERY_MAX_MV (4200)
|
||||
#endif
|
||||
|
||||
#ifndef APP_BATTERY_PD_MV
|
||||
#define APP_BATTERY_PD_MV (3100)
|
||||
#endif
|
||||
|
||||
#ifndef APP_BATTERY_CHARGE_TIMEOUT_MIN
|
||||
#define APP_BATTERY_CHARGE_TIMEOUT_MIN (90)
|
||||
#endif
|
||||
|
||||
#ifndef APP_BATTERY_CHARGE_OFFSET_MV
|
||||
#define APP_BATTERY_CHARGE_OFFSET_MV (20)
|
||||
#endif
|
||||
|
||||
#ifndef CHARGER_PLUGINOUT_RESET
|
||||
#define CHARGER_PLUGINOUT_RESET (0)
|
||||
#endif
|
||||
|
||||
#ifndef CHARGER_PLUGINOUT_DEBOUNCE_MS
|
||||
#define CHARGER_PLUGINOUT_DEBOUNCE_MS (50)
|
||||
#endif
|
||||
|
||||
#ifndef CHARGER_PLUGINOUT_DEBOUNCE_CNT
|
||||
#define CHARGER_PLUGINOUT_DEBOUNCE_CNT (3)
|
||||
#endif
|
||||
|
||||
#define APP_BATTERY_CHARGING_PLUGOUT_DEDOUNCE_CNT (APP_BATTERY_CHARGING_PERIODIC_MS<500?3:1)
|
||||
|
||||
#define APP_BATTERY_CHARGING_EXTPIN_MEASURE_CNT (APP_BATTERY_CHARGING_PERIODIC_MS<2*1000?2*1000/APP_BATTERY_CHARGING_PERIODIC_MS:1)
|
||||
#define APP_BATTERY_CHARGING_EXTPIN_DEDOUNCE_CNT (6)
|
||||
|
||||
#define APP_BATTERY_CHARGING_OVERVOLT_MEASURE_CNT (APP_BATTERY_CHARGING_PERIODIC_MS<2*1000?2*1000/APP_BATTERY_CHARGING_PERIODIC_MS:1)
|
||||
#define APP_BATTERY_CHARGING_OVERVOLT_DEDOUNCE_CNT (3)
|
||||
|
||||
#define APP_BATTERY_CHARGING_SLOPE_MEASURE_CNT (APP_BATTERY_CHARGING_PERIODIC_MS<20*1000?20*1000/APP_BATTERY_CHARGING_PERIODIC_MS:1)
|
||||
#define APP_BATTERY_CHARGING_SLOPE_TABLE_COUNT (6)
|
||||
|
||||
|
||||
#define APP_BATTERY_REPORT_INTERVAL (5)
|
||||
|
||||
#define APP_BATTERY_MV_BASE ((APP_BATTERY_MAX_MV-APP_BATTERY_PD_MV)/(APP_BATTERY_LEVEL_NUM))
|
||||
|
||||
#define APP_BATTERY_STABLE_COUNT (5)
|
||||
#define APP_BATTERY_MEASURE_PERIODIC_FAST_MS (200)
|
||||
#ifdef BLE_ONLY_ENABLED
|
||||
#define APP_BATTERY_MEASURE_PERIODIC_NORMAL_MS (25000)
|
||||
#else
|
||||
#define APP_BATTERY_MEASURE_PERIODIC_NORMAL_MS (10000)
|
||||
#endif
|
||||
#define APP_BATTERY_CHARGING_PERIODIC_MS (APP_BATTERY_MEASURE_PERIODIC_NORMAL_MS)
|
||||
|
||||
#define APP_BATTERY_SET_MESSAGE(appevt, status, volt) (appevt = (((uint32_t)status&0xffff)<<16)|(volt&0xffff))
|
||||
#define APP_BATTERY_GET_STATUS(appevt, status) (status = (appevt>>16)&0xffff)
|
||||
#define APP_BATTERY_GET_VOLT(appevt, volt) (volt = appevt&0xffff)
|
||||
#define APP_BATTERY_GET_PRAMS(appevt, prams) ((prams) = appevt&0xffff)
|
||||
|
||||
enum APP_BATTERY_MEASURE_PERIODIC_T
|
||||
{
|
||||
APP_BATTERY_MEASURE_PERIODIC_FAST = 0,
|
||||
APP_BATTERY_MEASURE_PERIODIC_NORMAL,
|
||||
APP_BATTERY_MEASURE_PERIODIC_CHARGING,
|
||||
|
||||
APP_BATTERY_MEASURE_PERIODIC_QTY,
|
||||
};
|
||||
|
||||
struct APP_BATTERY_MEASURE_CHARGER_STATUS_T
|
||||
{
|
||||
HAL_GPADC_MV_T prevolt;
|
||||
int32_t slope_1000[APP_BATTERY_CHARGING_SLOPE_TABLE_COUNT];
|
||||
int slope_1000_index;
|
||||
int cnt;
|
||||
};
|
||||
|
||||
|
||||
typedef void (*APP_BATTERY_EVENT_CB_T)(enum APP_BATTERY_STATUS_T, APP_BATTERY_MV_T volt);
|
||||
|
||||
struct APP_BATTERY_MEASURE_T
|
||||
{
|
||||
uint32_t start_time;
|
||||
enum APP_BATTERY_STATUS_T status;
|
||||
#ifdef __INTERCONNECTION__
|
||||
uint8_t currentBatteryInfo;
|
||||
uint8_t lastBatteryInfo;
|
||||
uint8_t isMobileSupportSelfDefinedCommand;
|
||||
#else
|
||||
uint8_t currlevel;
|
||||
#endif
|
||||
APP_BATTERY_MV_T currvolt;
|
||||
APP_BATTERY_MV_T lowvolt;
|
||||
APP_BATTERY_MV_T highvolt;
|
||||
APP_BATTERY_MV_T pdvolt;
|
||||
uint32_t chargetimeout;
|
||||
enum APP_BATTERY_MEASURE_PERIODIC_T periodic;
|
||||
HAL_GPADC_MV_T voltage[APP_BATTERY_STABLE_COUNT];
|
||||
uint16_t index;
|
||||
struct APP_BATTERY_MEASURE_CHARGER_STATUS_T charger_status;
|
||||
APP_BATTERY_EVENT_CB_T cb;
|
||||
APP_BATTERY_CB_T user_cb;
|
||||
};
|
||||
|
||||
static enum APP_BATTERY_CHARGER_T app_battery_charger_forcegetstatus(void);
|
||||
|
||||
static void app_battery_pluginout_debounce_start(void);
|
||||
static void app_battery_pluginout_debounce_handler(void const *param);
|
||||
osTimerDef (APP_BATTERY_PLUGINOUT_DEBOUNCE, app_battery_pluginout_debounce_handler);
|
||||
static osTimerId app_battery_pluginout_debounce_timer = NULL;
|
||||
static uint32_t app_battery_pluginout_debounce_ctx = 0;
|
||||
static uint32_t app_battery_pluginout_debounce_cnt = 0;
|
||||
|
||||
static void app_battery_timer_handler(void const *param);
|
||||
osTimerDef (APP_BATTERY, app_battery_timer_handler);
|
||||
static osTimerId app_battery_timer = NULL;
|
||||
static struct APP_BATTERY_MEASURE_T app_battery_measure;
|
||||
|
||||
static int app_battery_charger_handle_process(void);
|
||||
|
||||
#ifdef __INTERCONNECTION__
|
||||
uint8_t* app_battery_get_mobile_support_self_defined_command_p(void)
|
||||
{
|
||||
return &app_battery_measure.isMobileSupportSelfDefinedCommand;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void app_battery_irqhandler(uint16_t irq_val, HAL_GPADC_MV_T volt)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t meanBattVolt = 0;
|
||||
HAL_GPADC_MV_T vbat = volt;
|
||||
APP_BATTERY_TRACE(2,"%s %d",__func__, vbat);
|
||||
if (vbat == HAL_GPADC_BAD_VALUE)
|
||||
{
|
||||
app_battery_measure.cb(APP_BATTERY_STATUS_INVALID, vbat);
|
||||
return;
|
||||
}
|
||||
|
||||
#if (defined(BTUSB_AUDIO_MODE) || defined(BTUSB_AUDIO_MODE))
|
||||
if(app_usbaudio_mode_on()) return ;
|
||||
#endif
|
||||
app_battery_measure.voltage[app_battery_measure.index++%APP_BATTERY_STABLE_COUNT] = vbat<<2;
|
||||
|
||||
if (app_battery_measure.index > APP_BATTERY_STABLE_COUNT)
|
||||
{
|
||||
for (i=0; i<APP_BATTERY_STABLE_COUNT; i++)
|
||||
{
|
||||
meanBattVolt += app_battery_measure.voltage[i];
|
||||
}
|
||||
meanBattVolt /= APP_BATTERY_STABLE_COUNT;
|
||||
if (app_battery_measure.cb)
|
||||
{
|
||||
if (meanBattVolt>app_battery_measure.highvolt)
|
||||
{
|
||||
app_battery_measure.cb(APP_BATTERY_STATUS_OVERVOLT, meanBattVolt);
|
||||
}
|
||||
else if((meanBattVolt>app_battery_measure.pdvolt) && (meanBattVolt<app_battery_measure.lowvolt))
|
||||
{
|
||||
app_battery_measure.cb(APP_BATTERY_STATUS_UNDERVOLT, meanBattVolt);
|
||||
}
|
||||
else if(meanBattVolt<app_battery_measure.pdvolt)
|
||||
{
|
||||
app_battery_measure.cb(APP_BATTERY_STATUS_PDVOLT, meanBattVolt);
|
||||
}
|
||||
else
|
||||
{
|
||||
app_battery_measure.cb(APP_BATTERY_STATUS_NORMAL, meanBattVolt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int8_t level = 0;
|
||||
meanBattVolt = vbat<<2;
|
||||
level = (meanBattVolt-APP_BATTERY_PD_MV)/APP_BATTERY_MV_BASE;
|
||||
|
||||
if (level<APP_BATTERY_LEVEL_MIN)
|
||||
level = APP_BATTERY_LEVEL_MIN;
|
||||
if (level>APP_BATTERY_LEVEL_MAX)
|
||||
level = APP_BATTERY_LEVEL_MAX;
|
||||
|
||||
app_battery_measure.currvolt = meanBattVolt;
|
||||
#ifdef __INTERCONNECTION__
|
||||
APP_BATTERY_INFO_T* pBatteryInfo = (APP_BATTERY_INFO_T*)&app_battery_measure.currentBatteryInfo;
|
||||
pBatteryInfo->batteryLevel = level;
|
||||
#else
|
||||
app_battery_measure.currlevel = level;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void app_battery_timer_start(enum APP_BATTERY_MEASURE_PERIODIC_T periodic)
|
||||
{
|
||||
uint32_t periodic_millisec = 0;
|
||||
|
||||
if (app_battery_measure.periodic != periodic){
|
||||
app_battery_measure.periodic = periodic;
|
||||
switch (periodic)
|
||||
{
|
||||
case APP_BATTERY_MEASURE_PERIODIC_FAST:
|
||||
periodic_millisec = APP_BATTERY_MEASURE_PERIODIC_FAST_MS;
|
||||
break;
|
||||
case APP_BATTERY_MEASURE_PERIODIC_CHARGING:
|
||||
periodic_millisec = APP_BATTERY_CHARGING_PERIODIC_MS;
|
||||
break;
|
||||
case APP_BATTERY_MEASURE_PERIODIC_NORMAL:
|
||||
periodic_millisec = APP_BATTERY_MEASURE_PERIODIC_NORMAL_MS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
osTimerStop(app_battery_timer);
|
||||
osTimerStart(app_battery_timer, periodic_millisec);
|
||||
}
|
||||
}
|
||||
|
||||
static void app_battery_timer_handler(void const *param)
|
||||
{
|
||||
hal_gpadc_open(HAL_GPADC_CHAN_BATTERY, HAL_GPADC_ATP_ONESHOT, app_battery_irqhandler);
|
||||
}
|
||||
|
||||
static void app_battery_event_process(enum APP_BATTERY_STATUS_T status, APP_BATTERY_MV_T volt)
|
||||
{
|
||||
uint32_t app_battevt;
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
|
||||
APP_BATTERY_TRACE(3,"%s %d,%d",__func__, status, volt);
|
||||
msg.mod_id = APP_MODUAL_BATTERY;
|
||||
APP_BATTERY_SET_MESSAGE(app_battevt, status, volt);
|
||||
msg.msg_body.message_id = app_battevt;
|
||||
msg.msg_body.message_ptr = (uint32_t)NULL;
|
||||
app_mailbox_put(&msg);
|
||||
|
||||
}
|
||||
|
||||
int app_battery_handle_process_normal(uint32_t status, union APP_BATTERY_MSG_PRAMS prams)
|
||||
{
|
||||
int8_t level = 0;
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case APP_BATTERY_STATUS_UNDERVOLT:
|
||||
TRACE(1,"UNDERVOLT:%d", prams.volt);
|
||||
app_status_indication_set(APP_STATUS_INDICATION_CHARGENEED);
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
#if defined(IBRT)
|
||||
|
||||
#else
|
||||
app_voice_report(APP_STATUS_INDICATION_CHARGENEED, 0);
|
||||
#endif
|
||||
#endif
|
||||
case APP_BATTERY_STATUS_NORMAL:
|
||||
case APP_BATTERY_STATUS_OVERVOLT:
|
||||
app_battery_measure.currvolt = prams.volt;
|
||||
level = (prams.volt-APP_BATTERY_PD_MV)/APP_BATTERY_MV_BASE;
|
||||
|
||||
if (level<APP_BATTERY_LEVEL_MIN)
|
||||
level = APP_BATTERY_LEVEL_MIN;
|
||||
if (level>APP_BATTERY_LEVEL_MAX)
|
||||
level = APP_BATTERY_LEVEL_MAX;
|
||||
#ifdef __INTERCONNECTION__
|
||||
APP_BATTERY_INFO_T* pBatteryInfo;
|
||||
pBatteryInfo = (APP_BATTERY_INFO_T*)&app_battery_measure.currentBatteryInfo;
|
||||
pBatteryInfo->batteryLevel = level;
|
||||
if(level == APP_BATTERY_LEVEL_MAX)
|
||||
{
|
||||
level = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
level /= 10;
|
||||
}
|
||||
#else
|
||||
app_battery_measure.currlevel = level;
|
||||
#endif
|
||||
app_status_battery_report(level);
|
||||
break;
|
||||
case APP_BATTERY_STATUS_PDVOLT:
|
||||
#ifndef BT_USB_AUDIO_DUAL_MODE
|
||||
TRACE(1,"PDVOLT-->POWEROFF:%d", prams.volt);
|
||||
osTimerStop(app_battery_timer);
|
||||
app_shutdown();
|
||||
#endif
|
||||
break;
|
||||
case APP_BATTERY_STATUS_CHARGING:
|
||||
TRACE(1,"CHARGING-->APP_BATTERY_CHARGER :%d", prams.charger);
|
||||
if (prams.charger == APP_BATTERY_CHARGER_PLUGIN)
|
||||
{
|
||||
#ifdef BT_USB_AUDIO_DUAL_MODE
|
||||
TRACE(1,"%s:PLUGIN.", __func__);
|
||||
btusb_switch(BTUSB_MODE_USB);
|
||||
#else
|
||||
#if CHARGER_PLUGINOUT_RESET
|
||||
app_reset();
|
||||
#else
|
||||
app_battery_measure.status = APP_BATTERY_STATUS_CHARGING;
|
||||
#endif
|
||||
#endif
|
||||
}else{
|
||||
app_reset();
|
||||
}
|
||||
break;
|
||||
case APP_BATTERY_STATUS_INVALID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
app_battery_timer_start(APP_BATTERY_MEASURE_PERIODIC_NORMAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_battery_handle_process_charging(uint32_t status, union APP_BATTERY_MSG_PRAMS prams)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case APP_BATTERY_STATUS_OVERVOLT:
|
||||
case APP_BATTERY_STATUS_NORMAL:
|
||||
case APP_BATTERY_STATUS_UNDERVOLT:
|
||||
app_battery_measure.currvolt = prams.volt;
|
||||
app_status_battery_report(prams.volt);
|
||||
break;
|
||||
case APP_BATTERY_STATUS_CHARGING:
|
||||
TRACE(1,"CHARGING:%d", prams.charger);
|
||||
if (prams.charger == APP_BATTERY_CHARGER_PLUGOUT)
|
||||
{
|
||||
#ifdef BT_USB_AUDIO_DUAL_MODE
|
||||
TRACE(1,"%s:PlUGOUT.", __func__);
|
||||
btusb_switch(BTUSB_MODE_BT);
|
||||
#else
|
||||
#if CHARGER_PLUGINOUT_RESET
|
||||
TRACE(0,"CHARGING-->RESET");
|
||||
osTimerStop(app_battery_timer);
|
||||
app_shutdown();
|
||||
#else
|
||||
app_battery_measure.status = APP_BATTERY_STATUS_NORMAL;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else if (prams.charger == APP_BATTERY_CHARGER_PLUGIN)
|
||||
{
|
||||
#ifdef BT_USB_AUDIO_DUAL_MODE
|
||||
TRACE(1,"%s:PLUGIN.", __func__);
|
||||
btusb_switch(BTUSB_MODE_USB);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case APP_BATTERY_STATUS_INVALID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (app_battery_charger_handle_process()<=0)
|
||||
{
|
||||
if (app_status_indication_get() != APP_STATUS_INDICATION_FULLCHARGE)
|
||||
{
|
||||
TRACE(1,"FULL_CHARGING:%d", app_battery_measure.currvolt);
|
||||
app_status_indication_set(APP_STATUS_INDICATION_FULLCHARGE);
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
#if defined(BT_USB_AUDIO_DUAL_MODE) || defined(IBRT)
|
||||
#else
|
||||
app_voice_report(APP_STATUS_INDICATION_FULLCHARGE, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
app_battery_timer_start(APP_BATTERY_MEASURE_PERIODIC_CHARGING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int app_battery_handle_process(APP_MESSAGE_BODY *msg_body)
|
||||
{
|
||||
uint8_t status;
|
||||
union APP_BATTERY_MSG_PRAMS msg_prams;
|
||||
|
||||
APP_BATTERY_GET_STATUS(msg_body->message_id, status);
|
||||
APP_BATTERY_GET_PRAMS(msg_body->message_id, msg_prams.prams);
|
||||
|
||||
uint32_t generatedSeed = hal_sys_timer_get();
|
||||
for (uint8_t index = 0; index < sizeof(bt_addr); index++)
|
||||
{
|
||||
generatedSeed ^= (((uint32_t)(bt_addr[index])) << (hal_sys_timer_get()&0xF));
|
||||
}
|
||||
srand(generatedSeed);
|
||||
|
||||
if (status == APP_BATTERY_STATUS_PLUGINOUT){
|
||||
app_battery_pluginout_debounce_start();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (app_battery_measure.status)
|
||||
{
|
||||
case APP_BATTERY_STATUS_NORMAL:
|
||||
app_battery_handle_process_normal((uint32_t)status, msg_prams);
|
||||
break;
|
||||
|
||||
case APP_BATTERY_STATUS_CHARGING:
|
||||
app_battery_handle_process_charging((uint32_t)status, msg_prams);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (NULL != app_battery_measure.user_cb)
|
||||
{
|
||||
uint8_t batteryLevel;
|
||||
#ifdef __INTERCONNECTION__
|
||||
APP_BATTERY_INFO_T* pBatteryInfo;
|
||||
pBatteryInfo = (APP_BATTERY_INFO_T*)&app_battery_measure.currentBatteryInfo;
|
||||
pBatteryInfo->chargingStatus = ((app_battery_measure.status == APP_BATTERY_STATUS_CHARGING)? 1:0);
|
||||
batteryLevel = pBatteryInfo->batteryLevel;
|
||||
|
||||
#else
|
||||
batteryLevel = app_battery_measure.currlevel;
|
||||
#endif
|
||||
app_battery_measure.user_cb(app_battery_measure.currvolt,
|
||||
batteryLevel, app_battery_measure.status,status,msg_prams);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_battery_register(APP_BATTERY_CB_T user_cb)
|
||||
{
|
||||
if(NULL == app_battery_measure.user_cb)
|
||||
{
|
||||
app_battery_measure.user_cb = user_cb;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int app_battery_get_info(APP_BATTERY_MV_T *currvolt, uint8_t *currlevel, enum APP_BATTERY_STATUS_T *status)
|
||||
{
|
||||
if (currvolt)
|
||||
{
|
||||
*currvolt = app_battery_measure.currvolt;
|
||||
}
|
||||
|
||||
if (currlevel)
|
||||
{
|
||||
#ifdef __INTERCONNECTION__
|
||||
*currlevel = app_battery_measure.currentBatteryInfo;
|
||||
#else
|
||||
*currlevel = app_battery_measure.currlevel;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (status)
|
||||
{
|
||||
*status = app_battery_measure.status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_battery_open(void)
|
||||
{
|
||||
APP_BATTERY_TRACE(3,"%s batt range:%d~%d",__func__, APP_BATTERY_MIN_MV, APP_BATTERY_MAX_MV);
|
||||
int nRet = APP_BATTERY_OPEN_MODE_INVALID;
|
||||
|
||||
if (app_battery_timer == NULL)
|
||||
app_battery_timer = osTimerCreate (osTimer(APP_BATTERY), osTimerPeriodic, NULL);
|
||||
|
||||
if (app_battery_pluginout_debounce_timer == NULL)
|
||||
app_battery_pluginout_debounce_timer = osTimerCreate (osTimer(APP_BATTERY_PLUGINOUT_DEBOUNCE), osTimerOnce, &app_battery_pluginout_debounce_ctx);
|
||||
|
||||
app_battery_measure.status = APP_BATTERY_STATUS_NORMAL;
|
||||
#ifdef __INTERCONNECTION__
|
||||
app_battery_measure.currentBatteryInfo = APP_BATTERY_DEFAULT_INFO;
|
||||
app_battery_measure.lastBatteryInfo = APP_BATTERY_DEFAULT_INFO;
|
||||
app_battery_measure.isMobileSupportSelfDefinedCommand = 0;
|
||||
#else
|
||||
app_battery_measure.currlevel = APP_BATTERY_LEVEL_MAX;
|
||||
#endif
|
||||
app_battery_measure.currvolt = APP_BATTERY_MAX_MV;
|
||||
app_battery_measure.lowvolt = APP_BATTERY_MIN_MV;
|
||||
app_battery_measure.highvolt = APP_BATTERY_MAX_MV;
|
||||
app_battery_measure.pdvolt = APP_BATTERY_PD_MV;
|
||||
app_battery_measure.chargetimeout = APP_BATTERY_CHARGE_TIMEOUT_MIN;
|
||||
|
||||
app_battery_measure.periodic = APP_BATTERY_MEASURE_PERIODIC_QTY;
|
||||
app_battery_measure.cb = app_battery_event_process;
|
||||
app_battery_measure.user_cb = NULL;
|
||||
|
||||
app_battery_measure.charger_status.prevolt = 0;
|
||||
app_battery_measure.charger_status.slope_1000_index = 0;
|
||||
app_battery_measure.charger_status.cnt = 0;
|
||||
|
||||
app_set_threadhandle(APP_MODUAL_BATTERY, app_battery_handle_process);
|
||||
|
||||
if (app_battery_ext_charger_detecter_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
hal_iomux_init((struct HAL_IOMUX_PIN_FUNCTION_MAP *)&app_battery_ext_charger_detecter_cfg, 1);
|
||||
hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_IN, 1);
|
||||
}
|
||||
|
||||
if (app_battery_ext_charger_enable_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
hal_iomux_init((struct HAL_IOMUX_PIN_FUNCTION_MAP *)&app_battery_ext_charger_detecter_cfg, 1);
|
||||
hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_OUT, 1);
|
||||
}
|
||||
|
||||
if (app_battery_charger_indication_open() == APP_BATTERY_CHARGER_PLUGIN)
|
||||
{
|
||||
app_battery_measure.status = APP_BATTERY_STATUS_CHARGING;
|
||||
app_battery_measure.start_time = hal_sys_timer_get();
|
||||
//pmu_charger_plugin_config();
|
||||
if (app_battery_ext_charger_enable_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_OUT, 0);
|
||||
}
|
||||
|
||||
#if (CHARGER_PLUGINOUT_RESET == 0)
|
||||
nRet = APP_BATTERY_OPEN_MODE_CHARGING_PWRON;
|
||||
#else
|
||||
nRet = APP_BATTERY_OPEN_MODE_CHARGING;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
app_battery_measure.status = APP_BATTERY_STATUS_NORMAL;
|
||||
//pmu_charger_plugout_config();
|
||||
nRet = APP_BATTERY_OPEN_MODE_NORMAL;
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int app_battery_start(void)
|
||||
{
|
||||
APP_BATTERY_TRACE(2,"%s %d",__func__, APP_BATTERY_MEASURE_PERIODIC_FAST_MS);
|
||||
|
||||
app_battery_timer_start(APP_BATTERY_MEASURE_PERIODIC_FAST);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_battery_stop(void)
|
||||
{
|
||||
osTimerStop(app_battery_timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_battery_close(void)
|
||||
{
|
||||
hal_gpadc_close(HAL_GPADC_CHAN_BATTERY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int32_t app_battery_charger_slope_calc(int32_t t1, int32_t v1, int32_t t2, int32_t v2)
|
||||
{
|
||||
int32_t slope_1000;
|
||||
slope_1000 = (v2-v1)*1000/(t2-t1);
|
||||
return slope_1000;
|
||||
}
|
||||
|
||||
static int app_battery_charger_handle_process(void)
|
||||
{
|
||||
int nRet = 1;
|
||||
int8_t i=0,cnt=0;
|
||||
uint32_t slope_1000 = 0;
|
||||
uint32_t charging_min;
|
||||
static uint8_t overvolt_full_charge_cnt = 0;
|
||||
static uint8_t ext_pin_full_charge_cnt = 0;
|
||||
|
||||
charging_min = hal_sys_timer_get() - app_battery_measure.start_time;
|
||||
charging_min = TICKS_TO_MS(charging_min)/1000/60;
|
||||
if (charging_min >= app_battery_measure.chargetimeout)
|
||||
{
|
||||
// TRACE(0,"TIMEROUT-->FULL_CHARGING");
|
||||
nRet = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((app_battery_measure.charger_status.cnt++%APP_BATTERY_CHARGING_OVERVOLT_MEASURE_CNT) == 0)
|
||||
{
|
||||
if (app_battery_measure.currvolt>=(app_battery_measure.highvolt+APP_BATTERY_CHARGE_OFFSET_MV))
|
||||
{
|
||||
overvolt_full_charge_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
overvolt_full_charge_cnt = 0;
|
||||
}
|
||||
if (overvolt_full_charge_cnt>=APP_BATTERY_CHARGING_OVERVOLT_DEDOUNCE_CNT)
|
||||
{
|
||||
//TRACE(0,"OVERVOLT-->FULL_CHARGING");
|
||||
nRet = -1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if ((app_battery_measure.charger_status.cnt++%APP_BATTERY_CHARGING_EXTPIN_MEASURE_CNT) == 0)
|
||||
{
|
||||
if (app_battery_ext_charger_detecter_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
if (hal_gpio_pin_get_val((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin))
|
||||
{
|
||||
ext_pin_full_charge_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_pin_full_charge_cnt = 0;
|
||||
}
|
||||
if (ext_pin_full_charge_cnt>=APP_BATTERY_CHARGING_EXTPIN_DEDOUNCE_CNT)
|
||||
{
|
||||
TRACE(0,"EXT PIN-->FULL_CHARGING");
|
||||
nRet = -1;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((app_battery_measure.charger_status.cnt++%APP_BATTERY_CHARGING_SLOPE_MEASURE_CNT) == 0)
|
||||
{
|
||||
if (!app_battery_measure.charger_status.prevolt)
|
||||
{
|
||||
app_battery_measure.charger_status.slope_1000[app_battery_measure.charger_status.slope_1000_index%APP_BATTERY_CHARGING_SLOPE_TABLE_COUNT] = slope_1000;
|
||||
app_battery_measure.charger_status.prevolt = app_battery_measure.currvolt;
|
||||
for (i=0; i<APP_BATTERY_CHARGING_SLOPE_TABLE_COUNT; i++)
|
||||
{
|
||||
app_battery_measure.charger_status.slope_1000[i]=100;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
slope_1000 = app_battery_charger_slope_calc(0, app_battery_measure.charger_status.prevolt,
|
||||
APP_BATTERY_CHARGING_PERIODIC_MS*APP_BATTERY_CHARGING_SLOPE_MEASURE_CNT/1000, app_battery_measure.currvolt);
|
||||
app_battery_measure.charger_status.slope_1000[app_battery_measure.charger_status.slope_1000_index%APP_BATTERY_CHARGING_SLOPE_TABLE_COUNT] = slope_1000;
|
||||
app_battery_measure.charger_status.prevolt = app_battery_measure.currvolt;
|
||||
for (i=0; i<APP_BATTERY_CHARGING_SLOPE_TABLE_COUNT; i++)
|
||||
{
|
||||
if (app_battery_measure.charger_status.slope_1000[i]>0)
|
||||
cnt++;
|
||||
else
|
||||
cnt--;
|
||||
TRACE(3,"slope_1000[%d]=%d cnt:%d", i,app_battery_measure.charger_status.slope_1000[i], cnt);
|
||||
}
|
||||
TRACE(3,"app_battery_charger_slope_proc slope*1000=%d cnt:%d nRet:%d", slope_1000, cnt, nRet);
|
||||
if (cnt>1)
|
||||
{
|
||||
nRet = 1;
|
||||
}/*else (3>=cnt && cnt>=-3){
|
||||
nRet = 0;
|
||||
}*/else
|
||||
{
|
||||
if (app_battery_measure.currvolt>=(app_battery_measure.highvolt-APP_BATTERY_CHARGE_OFFSET_MV))
|
||||
{
|
||||
TRACE(0,"SLOPE-->FULL_CHARGING");
|
||||
nRet = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
app_battery_measure.charger_status.slope_1000_index++;
|
||||
}
|
||||
exit:
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static enum APP_BATTERY_CHARGER_T app_battery_charger_forcegetstatus(void)
|
||||
{
|
||||
enum APP_BATTERY_CHARGER_T status = APP_BATTERY_CHARGER_QTY;
|
||||
enum PMU_CHARGER_STATUS_T charger;
|
||||
|
||||
charger = pmu_charger_get_status();
|
||||
|
||||
if (charger == PMU_CHARGER_PLUGIN)
|
||||
{
|
||||
status = APP_BATTERY_CHARGER_PLUGIN;
|
||||
// TRACE(0,"force APP_BATTERY_CHARGER_PLUGIN");
|
||||
}
|
||||
else
|
||||
{
|
||||
status = APP_BATTERY_CHARGER_PLUGOUT;
|
||||
// TRACE(0,"force APP_BATTERY_CHARGER_PLUGOUT");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void app_battery_charger_handler(enum PMU_CHARGER_STATUS_T status)
|
||||
{
|
||||
TRACE(2,"%s: status=%d", __func__, status);
|
||||
pmu_charger_set_irq_handler(NULL);
|
||||
app_battery_event_process(APP_BATTERY_STATUS_PLUGINOUT,
|
||||
(status == PMU_CHARGER_PLUGIN) ? APP_BATTERY_CHARGER_PLUGIN : APP_BATTERY_CHARGER_PLUGOUT);
|
||||
}
|
||||
|
||||
static void app_battery_pluginout_debounce_start(void)
|
||||
{
|
||||
TRACE(1,"%s", __func__);
|
||||
app_battery_pluginout_debounce_ctx = (uint32_t)app_battery_charger_forcegetstatus();
|
||||
app_battery_pluginout_debounce_cnt = 1;
|
||||
osTimerStart(app_battery_pluginout_debounce_timer, CHARGER_PLUGINOUT_DEBOUNCE_MS);
|
||||
}
|
||||
|
||||
static void app_battery_pluginout_debounce_handler(void const *param)
|
||||
{
|
||||
enum APP_BATTERY_CHARGER_T status_charger = app_battery_charger_forcegetstatus();
|
||||
|
||||
if(app_battery_pluginout_debounce_ctx == (uint32_t) status_charger){
|
||||
app_battery_pluginout_debounce_cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(2,"%s dithering cnt %u", __func__, app_battery_pluginout_debounce_cnt);
|
||||
app_battery_pluginout_debounce_cnt = 0;
|
||||
app_battery_pluginout_debounce_ctx = (uint32_t)status_charger;
|
||||
}
|
||||
|
||||
if (app_battery_pluginout_debounce_cnt >= CHARGER_PLUGINOUT_DEBOUNCE_CNT){
|
||||
TRACE(2,"%s %s", __func__, status_charger == APP_BATTERY_CHARGER_PLUGOUT ? "PLUGOUT" : "PLUGIN");
|
||||
if (status_charger == APP_BATTERY_CHARGER_PLUGIN)
|
||||
{
|
||||
if (app_battery_ext_charger_enable_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_OUT, 0);
|
||||
}
|
||||
app_battery_measure.start_time = hal_sys_timer_get();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (app_battery_ext_charger_enable_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
hal_gpio_pin_set_dir((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin, HAL_GPIO_DIR_OUT, 1);
|
||||
}
|
||||
}
|
||||
app_battery_event_process(APP_BATTERY_STATUS_CHARGING, status_charger);
|
||||
pmu_charger_set_irq_handler(app_battery_charger_handler);
|
||||
osTimerStop(app_battery_pluginout_debounce_timer);
|
||||
}else{
|
||||
osTimerStart(app_battery_pluginout_debounce_timer, CHARGER_PLUGINOUT_DEBOUNCE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
int app_battery_charger_indication_open(void)
|
||||
{
|
||||
enum APP_BATTERY_CHARGER_T status = APP_BATTERY_CHARGER_QTY;
|
||||
uint8_t cnt = 0;
|
||||
|
||||
APP_BATTERY_TRACE(1,"%s",__func__);
|
||||
|
||||
pmu_charger_init();
|
||||
|
||||
do
|
||||
{
|
||||
status = app_battery_charger_forcegetstatus();
|
||||
if (status == APP_BATTERY_CHARGER_PLUGIN)
|
||||
break;
|
||||
osDelay(20);
|
||||
}
|
||||
while(cnt++<5);
|
||||
|
||||
if (app_battery_ext_charger_detecter_cfg.pin != HAL_IOMUX_PIN_NUM)
|
||||
{
|
||||
if (!hal_gpio_pin_get_val((enum HAL_GPIO_PIN_T)app_battery_ext_charger_detecter_cfg.pin))
|
||||
{
|
||||
status = APP_BATTERY_CHARGER_PLUGIN;
|
||||
}
|
||||
}
|
||||
|
||||
pmu_charger_set_irq_handler(app_battery_charger_handler);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int8_t app_battery_current_level(void)
|
||||
{
|
||||
#ifdef __INTERCONNECTION__
|
||||
return app_battery_measure.currentBatteryInfo & 0x7f;
|
||||
#else
|
||||
return app_battery_measure.currlevel;
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t app_battery_is_charging(void)
|
||||
{
|
||||
return (APP_BATTERY_STATUS_CHARGING == app_battery_measure.status);
|
||||
}
|
||||
|
||||
typedef uint16_t NTP_VOLTAGE_MV_T;
|
||||
typedef uint16_t NTP_TEMPERATURE_C_T;
|
||||
|
||||
#define NTC_CAPTURE_STABLE_COUNT (5)
|
||||
#define NTC_CAPTURE_TEMPERATURE_STEP (4)
|
||||
#define NTC_CAPTURE_TEMPERATURE_REF (15)
|
||||
#define NTC_CAPTURE_VOLTAGE_REF (1100)
|
||||
|
||||
typedef void (*NTC_CAPTURE_MEASURE_CB_T)(NTP_TEMPERATURE_C_T);
|
||||
|
||||
struct NTC_CAPTURE_MEASURE_T
|
||||
{
|
||||
NTP_TEMPERATURE_C_T temperature;
|
||||
NTP_VOLTAGE_MV_T currvolt;
|
||||
NTP_VOLTAGE_MV_T voltage[NTC_CAPTURE_STABLE_COUNT];
|
||||
uint16_t index;
|
||||
NTC_CAPTURE_MEASURE_CB_T cb;
|
||||
};
|
||||
|
||||
static struct NTC_CAPTURE_MEASURE_T ntc_capture_measure;
|
||||
|
||||
void ntc_capture_irqhandler(uint16_t irq_val, HAL_GPADC_MV_T volt)
|
||||
{
|
||||
uint32_t meanVolt = 0;
|
||||
TRACE(3,"%s %d irq:0x%04x",__func__, volt, irq_val);
|
||||
|
||||
if (volt == HAL_GPADC_BAD_VALUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ntc_capture_measure.voltage[ntc_capture_measure.index++%NTC_CAPTURE_STABLE_COUNT] = volt;
|
||||
|
||||
if (ntc_capture_measure.index > NTC_CAPTURE_STABLE_COUNT)
|
||||
{
|
||||
for (uint8_t i=0; i<NTC_CAPTURE_STABLE_COUNT; i++)
|
||||
{
|
||||
meanVolt += ntc_capture_measure.voltage[i];
|
||||
}
|
||||
meanVolt /= NTC_CAPTURE_STABLE_COUNT;
|
||||
ntc_capture_measure.currvolt = meanVolt;
|
||||
}
|
||||
else if (!ntc_capture_measure.currvolt)
|
||||
{
|
||||
ntc_capture_measure.currvolt = volt;
|
||||
}
|
||||
ntc_capture_measure.temperature = ((int32_t)ntc_capture_measure.currvolt - NTC_CAPTURE_VOLTAGE_REF)/NTC_CAPTURE_TEMPERATURE_STEP + NTC_CAPTURE_TEMPERATURE_REF;
|
||||
pmu_ntc_capture_disable();
|
||||
TRACE(3,"%s ad:%d temperature:%d",__func__, ntc_capture_measure.currvolt, ntc_capture_measure.temperature);
|
||||
}
|
||||
|
||||
int ntc_capture_open(void)
|
||||
{
|
||||
|
||||
ntc_capture_measure.currvolt = 0;
|
||||
ntc_capture_measure.index = 0;
|
||||
ntc_capture_measure.temperature = 0;
|
||||
ntc_capture_measure.cb = NULL;
|
||||
|
||||
pmu_ntc_capture_enable();
|
||||
hal_gpadc_open(HAL_GPADC_CHAN_0, HAL_GPADC_ATP_ONESHOT, ntc_capture_irqhandler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ntc_capture_start(void)
|
||||
{
|
||||
pmu_ntc_capture_enable();
|
||||
hal_gpadc_open(HAL_GPADC_CHAN_0, HAL_GPADC_ATP_ONESHOT, ntc_capture_irqhandler);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_BATTERY_H__
|
||||
#define __APP_BATTERY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define APP_BATTERY_LEVEL_MIN (0)
|
||||
|
||||
#ifdef __INTERCONNECTION__
|
||||
#define APP_BATTERY_LEVEL_MAX (100)
|
||||
#define APP_BATTERY_DEFAULT_INFO 0xE4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t chargingStatus : 1;
|
||||
uint8_t batteryLevel : 7;
|
||||
}APP_BATTERY_INFO_T;
|
||||
|
||||
uint8_t* app_battery_get_mobile_support_self_defined_command_p(void);
|
||||
#else // #ifdef __INTERCONNECTION__
|
||||
#define APP_BATTERY_LEVEL_MAX (9)
|
||||
#endif // #ifdef __INTERCONNECTION__
|
||||
|
||||
#define APP_BATTERY_LEVEL_NUM (APP_BATTERY_LEVEL_MAX-APP_BATTERY_LEVEL_MIN+1)
|
||||
|
||||
enum APP_BATTERY_STATUS_T {
|
||||
APP_BATTERY_STATUS_NORMAL,
|
||||
APP_BATTERY_STATUS_CHARGING,
|
||||
APP_BATTERY_STATUS_OVERVOLT,
|
||||
APP_BATTERY_STATUS_UNDERVOLT,
|
||||
APP_BATTERY_STATUS_PDVOLT,
|
||||
APP_BATTERY_STATUS_PLUGINOUT,
|
||||
APP_BATTERY_STATUS_INVALID,
|
||||
|
||||
APP_BATTERY_STATUS_QTY
|
||||
};
|
||||
|
||||
#define APP_BATTERY_OPEN_MODE_INVALID (-1)
|
||||
#define APP_BATTERY_OPEN_MODE_NORMAL (0)
|
||||
#define APP_BATTERY_OPEN_MODE_CHARGING (1)
|
||||
#define APP_BATTERY_OPEN_MODE_CHARGING_PWRON (2)
|
||||
|
||||
typedef uint16_t APP_BATTERY_MV_T;
|
||||
|
||||
enum APP_BATTERY_CHARGER_T
|
||||
{
|
||||
APP_BATTERY_CHARGER_PLUGOUT = 0,
|
||||
APP_BATTERY_CHARGER_PLUGIN,
|
||||
APP_BATTERY_CHARGER_QTY,
|
||||
};
|
||||
|
||||
union APP_BATTERY_MSG_PRAMS{
|
||||
APP_BATTERY_MV_T volt;
|
||||
enum APP_BATTERY_CHARGER_T charger;
|
||||
uint32_t prams;
|
||||
};
|
||||
|
||||
typedef void (*APP_BATTERY_CB_T)(APP_BATTERY_MV_T currvolt, uint8_t currlevel,enum APP_BATTERY_STATUS_T curstatus,uint32_t status, union APP_BATTERY_MSG_PRAMS prams);
|
||||
|
||||
|
||||
int app_battery_get_info(APP_BATTERY_MV_T *currvolt, uint8_t *currlevel, enum APP_BATTERY_STATUS_T *status);
|
||||
|
||||
/**
|
||||
* Battery App owns its own context where it will periodically update the
|
||||
* battery level and state. Makes sense for it to act as a Model and publish
|
||||
* battery change events to any interested users.
|
||||
*
|
||||
* Note: Callback will execute out of BES "App Thread" context.
|
||||
*
|
||||
* TODO: ideally implemented as proper observer pattern with support for multiple
|
||||
* listeners
|
||||
*
|
||||
* Returns
|
||||
* - 0: On success
|
||||
* - 1: If registration failed
|
||||
*/
|
||||
int app_battery_register(APP_BATTERY_CB_T user_cb);
|
||||
|
||||
int app_battery_open(void);
|
||||
|
||||
int app_battery_start(void);
|
||||
|
||||
int app_battery_stop(void);
|
||||
|
||||
int app_battery_close(void);
|
||||
|
||||
int app_battery_charger_indication_open(void);
|
||||
|
||||
int8_t app_battery_current_level(void);
|
||||
|
||||
int8_t app_battery_is_charging(void);
|
||||
|
||||
int ntc_capture_open(void);
|
||||
|
||||
int ntc_capture_start(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
|
||||
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
ccflags-y += \
|
||||
$(BT_IF_INCLUDES) \
|
||||
$(BT_PROFILES_INCLUDES) \
|
||||
-Iservices/bt_app \
|
||||
-Iservices/bt_app/a2dp_codecs/include \
|
||||
-Iservices/audioflinger \
|
||||
-Iservices/nvrecord \
|
||||
-Iservices/overlay \
|
||||
-Iservices/resources \
|
||||
-Iservices/audio_process \
|
||||
-Iapps/apptester \
|
||||
-Iapps/factory \
|
||||
-Iutils/crc32 \
|
||||
-Iplatform/drivers/bt \
|
||||
-Iplatform/drivers/ana \
|
||||
-Iapps/audioplayers/rbplay \
|
||||
-Itests/anc_usb \
|
||||
-Iapps/anc/inc \
|
||||
-Iapps/ota \
|
||||
-Ithirdparty/userapi \
|
||||
-Iservices/voicepath \
|
||||
-Iservices/voicepath/gsound/gsound_service \
|
||||
-Iservices/voicepath/gsound/gsound_target \
|
||||
-Iservices/communication \
|
||||
-Iutils/cqueue \
|
||||
-Iservices/ai_voice/ama/ama_manager \
|
||||
-Iservices/ai_voice/manager \
|
||||
-Iservices/multimedia/audio/codec/sbc/inc \
|
||||
-Iservices/multimedia/audio/codec/sbc/src/inc \
|
||||
-Iservices/interconnection
|
||||
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "stdio.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_trace.h"
|
||||
#include "app_audio.h"
|
||||
|
||||
#include "a2dp_api.h"
|
||||
#include "app_bt.h"
|
||||
#include "btapp.h"
|
||||
#include "usb_audio_app.h"
|
||||
#include "btusb_audio.h"
|
||||
|
||||
extern void btusbaudio_entry(void);
|
||||
extern void btusbaudio_exit(void);
|
||||
extern a2dp_stream_t* app_bt_get_steam(enum BT_DEVICE_ID_T id);
|
||||
extern int app_bt_get_bt_addr(enum BT_DEVICE_ID_T id,bt_bdaddr_t *bdaddr);
|
||||
extern bool app_bt_a2dp_service_is_connected(void);
|
||||
int app_bt_A2DP_OpenStream(a2dp_stream_t *Stream, bt_bdaddr_t *Addr);
|
||||
int app_bt_A2DP_CloseStream(a2dp_stream_t *Stream);
|
||||
|
||||
extern bool btapp_hfp_is_call_active(void);
|
||||
static bool btusb_usb_is_on = false;
|
||||
static enum BTUSB_MODE btusb_mode = BTUSB_MODE_INVALID;
|
||||
static bool btusb_bt_audio_is_suspend = false;
|
||||
|
||||
#define BT_USB_DEBUG() //TRACE(2,"_debug: %s,%d",__func__,__LINE__)
|
||||
extern struct BT_DEVICE_T app_bt_device;
|
||||
|
||||
static void _btusb_stream_open(unsigned int timeout_ms)
|
||||
{
|
||||
a2dp_stream_t *stream = NULL;
|
||||
bt_bdaddr_t bdaddr;
|
||||
uint32_t stime = 0;
|
||||
uint32_t etime = 0;
|
||||
|
||||
stime = hal_sys_timer_get();
|
||||
//BT_USB_DEBUG();
|
||||
stream = (a2dp_stream_t*)app_bt_get_steam(BT_DEVICE_ID_1);
|
||||
|
||||
app_bt_get_bt_addr(BT_DEVICE_ID_1,&bdaddr);
|
||||
if(stream)
|
||||
{
|
||||
//struct BT_DEVICE_T *bt_dev = &app_bt_device;
|
||||
//A2DP_Register((a2dp_stream_t *)bt_dev->a2dp_stream[BT_DEVICE_ID_1]->a2dp_stream, &a2dp_avdtpcodec, NULL, (A2dpCallback) a2dp_callback);
|
||||
//AVRCP_Register((AvrcpChannel *)bt_dev->avrcp_channel[BT_DEVICE_ID_1]->avrcp_channel_handle, (AvrcpCallback)avrcp_callback_CT, BTIF_AVRCP_CT_CATEGORY_1 | BTIF_AVRCP_CT_CATEGORY_2 | BTIF_AVRCP_TG_CATEGORY_2);
|
||||
BT_USB_DEBUG();
|
||||
osDelay(10);
|
||||
app_bt_A2DP_OpenStream(stream,&bdaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
return;
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
if(app_bt_a2dp_service_is_connected()){
|
||||
etime = hal_sys_timer_get();
|
||||
TRACE(1,"_debug: a2dp service connected, wait time = 0x%x.",TICKS_TO_MS(etime - stime));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
etime = hal_sys_timer_get();
|
||||
if(TICKS_TO_MS(etime - stime) >= timeout_ms)
|
||||
{
|
||||
TRACE(1,"_debug: a2dp service connect timeout = 0x%x.",
|
||||
TICKS_TO_MS(etime - stime));
|
||||
break;
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
}
|
||||
//BT_USB_DEBUG();
|
||||
}
|
||||
|
||||
static void _btusb_stream_close(unsigned int timeout_ms)
|
||||
{
|
||||
a2dp_stream_t *stream = NULL;
|
||||
uint32_t stime = 0;
|
||||
uint32_t etime = 0;
|
||||
|
||||
stime = hal_sys_timer_get();
|
||||
BT_USB_DEBUG();
|
||||
stream = (a2dp_stream_t*)app_bt_get_steam(BT_DEVICE_ID_1);
|
||||
if(stream)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
app_bt_A2DP_CloseStream(stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
return;
|
||||
}
|
||||
stime = hal_sys_timer_get();
|
||||
while(1)
|
||||
{
|
||||
if(!app_bt_a2dp_service_is_connected()){
|
||||
//struct BT_DEVICE_T *bt_dev = &app_bt_device;
|
||||
//AVRCP_Deregister(bt_dev->avrcp_channel[BT_DEVICE_ID_1]->avrcp_channel_handle);
|
||||
//A2DP_Deregister(stream);
|
||||
etime = hal_sys_timer_get();
|
||||
TRACE(1,"a2dp service diconnected, wait time = 0x%x.",
|
||||
TICKS_TO_MS(etime - stime));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
etime = hal_sys_timer_get();
|
||||
if(TICKS_TO_MS(etime - stime) >= timeout_ms)
|
||||
{
|
||||
TRACE(1,"a2dp service diconnect timeout = 0x%x.",
|
||||
TICKS_TO_MS(etime - stime));
|
||||
break;
|
||||
}
|
||||
osDelay(10);
|
||||
}
|
||||
}
|
||||
BT_USB_DEBUG();
|
||||
}
|
||||
|
||||
static void btusb_usbaudio_entry(void)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
btusbaudio_entry();
|
||||
btusb_usb_is_on = true ;
|
||||
}
|
||||
|
||||
void btusb_usbaudio_open(void)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
if(!btusb_usb_is_on)
|
||||
{
|
||||
btusb_usbaudio_entry();
|
||||
BT_USB_DEBUG();
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_audio_app(1);
|
||||
}
|
||||
BT_USB_DEBUG();
|
||||
}
|
||||
|
||||
void btusb_usbaudio_close(void)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
if(btusb_usb_is_on)
|
||||
{
|
||||
usb_audio_app(0);
|
||||
BT_USB_DEBUG();
|
||||
}
|
||||
else
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
}
|
||||
}
|
||||
|
||||
void btusb_btaudio_close(bool is_wait)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
//if(!btusb_bt_audio_is_suspend)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
if(is_wait)
|
||||
{
|
||||
app_audio_sendrequest(APP_PLAY_BACK_AUDIO, (uint8_t)APP_BT_SETTING_CLOSEALL, 0);
|
||||
_btusb_stream_close(BTUSB_OUTTIME_MS);
|
||||
}
|
||||
else
|
||||
{
|
||||
_btusb_stream_close(0);
|
||||
}
|
||||
btusb_bt_audio_is_suspend = true;
|
||||
}
|
||||
}
|
||||
|
||||
void btusb_btaudio_open(bool is_wait)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
//if(btusb_bt_audio_is_suspend)
|
||||
{
|
||||
TRACE(2,"%s: %d.",__func__,__LINE__);
|
||||
if(is_wait)
|
||||
{
|
||||
_btusb_stream_open(BTUSB_OUTTIME_MS);
|
||||
app_audio_sendrequest(APP_PLAY_BACK_AUDIO, (uint8_t)APP_BT_SETTING_CLOSE, 0);
|
||||
app_audio_sendrequest(APP_PLAY_BACK_AUDIO, (uint8_t)APP_BT_SETTING_SETUP, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_btusb_stream_open(0);
|
||||
}
|
||||
TRACE(2,"%s: %d.",__func__,__LINE__);
|
||||
btusb_bt_audio_is_suspend = false;
|
||||
}
|
||||
}
|
||||
|
||||
void btusb_switch(enum BTUSB_MODE mode)
|
||||
{
|
||||
//BT_USB_DEBUG();
|
||||
if(mode != BTUSB_MODE_BT && mode != BTUSB_MODE_USB)
|
||||
{
|
||||
ASSERT(0, "%s:%d, mode = %d.",__func__,__LINE__,mode);
|
||||
}
|
||||
|
||||
if(btusb_mode == mode) {
|
||||
BT_USB_DEBUG();
|
||||
return;
|
||||
}
|
||||
|
||||
if(btusb_mode == BTUSB_MODE_INVALID)
|
||||
{
|
||||
if(mode == BTUSB_MODE_BT) {
|
||||
TRACE(1,"%s: switch to BT mode.",__func__);
|
||||
btusb_mode = BTUSB_MODE_BT;
|
||||
}
|
||||
else {
|
||||
TRACE(1,"%s: switch to USB mode.",__func__);
|
||||
//btusb_btaudio_close(true);
|
||||
osDelay(500);
|
||||
btusb_usbaudio_open();
|
||||
btusb_mode = BTUSB_MODE_USB;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mode == BTUSB_MODE_BT) {
|
||||
TRACE(1,"%s: switch to BT mode.",__func__);
|
||||
if(btusb_usb_is_on)
|
||||
{
|
||||
TRACE(1,"%s: btusb_usbaudio_close.",__func__);
|
||||
btusb_usbaudio_close();
|
||||
TRACE(1,"%s: btusb_usbaudio_close done.",__func__);
|
||||
osDelay(500);
|
||||
}
|
||||
btusb_mode = BTUSB_MODE_BT;
|
||||
btusb_btaudio_open(true);
|
||||
TRACE(1,"%s: switch to BT mode done.",__func__);
|
||||
}
|
||||
else {
|
||||
if(btapp_hfp_is_call_active() == 1)
|
||||
{
|
||||
TRACE(1,"%s: hfp is call active.",__func__);
|
||||
return;
|
||||
}
|
||||
TRACE(1,"%s: switch to USB mode.",__func__);
|
||||
btusb_btaudio_close(true);
|
||||
TRACE(1,"%s: btusb_btaudio_close done.",__func__);
|
||||
osDelay(500);
|
||||
btusb_usbaudio_open();
|
||||
btusb_mode = BTUSB_MODE_USB;
|
||||
TRACE(1,"%s: switch to USB mode done.",__func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool btusb_is_bt_mode(void)
|
||||
{
|
||||
BT_USB_DEBUG();
|
||||
return btusb_mode == BTUSB_MODE_BT ? true : false;
|
||||
}
|
||||
|
||||
bool btusb_is_usb_mode(void)
|
||||
{
|
||||
return btusb_mode == BTUSB_MODE_USB ? true : false;
|
||||
}
|
||||
|
||||
|
||||
#if defined(BT_USB_AUDIO_DUAL_MODE_TEST)
|
||||
void test_btusb_switch(void)
|
||||
{
|
||||
if(btusb_mode == BTUSB_MODE_BT)
|
||||
{
|
||||
btusb_switch(BTUSB_MODE_USB);
|
||||
}
|
||||
else
|
||||
{
|
||||
btusb_switch(BTUSB_MODE_BT);
|
||||
}
|
||||
}
|
||||
|
||||
void test_btusb_switch_to_bt(void)
|
||||
{
|
||||
btusb_switch(BTUSB_MODE_BT);
|
||||
}
|
||||
|
||||
void test_btusb_switch_to_usb(void)
|
||||
{
|
||||
btusb_switch(BTUSB_MODE_USB);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _BTUSB_AUDIO_H_
|
||||
#define _BTUSB_AUDIO_H_
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BTUSB_OUTTIME_MS 1000
|
||||
enum BTUSB_MODE{
|
||||
BTUSB_MODE_BT,
|
||||
BTUSB_MODE_USB,
|
||||
BTUSB_MODE_INVALID
|
||||
};
|
||||
|
||||
void btusb_usbaudio_open(void);
|
||||
void btusb_usbaudio_close(void);
|
||||
void btusb_btaudio_open(bool is_wait);
|
||||
void btusb_btaudio_close(bool is_wait);
|
||||
void btusb_switch(enum BTUSB_MODE mode);
|
||||
bool btusb_is_bt_mode(void);
|
||||
bool btusb_is_usb_mode(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // _BTUSB_AUDIO_H_
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_trace.h"
|
||||
#include "app_utils.h"
|
||||
#include "usb_audio_app.h"
|
||||
#include "usbaudio_thread.h"
|
||||
|
||||
static void usb_thread(void const *argument);
|
||||
osThreadDef(usb_thread, osPriorityHigh, 1, 2048, "usb");
|
||||
|
||||
osMailQDef (usb_mailbox, USB_MAILBOX_MAX, USB_MESSAGE);
|
||||
static osMailQId usb_mailbox = NULL;
|
||||
static uint8_t usb_mailbox_cnt = 0;
|
||||
#define USBAUDIO_DEBUG TRACE
|
||||
static int usb_mailbox_init(void)
|
||||
{
|
||||
USBAUDIO_DEBUG("%s,%d",__func__,__LINE__);
|
||||
usb_mailbox = osMailCreate(osMailQ(usb_mailbox), NULL);
|
||||
if (usb_mailbox == NULL) {
|
||||
USBAUDIO_DEBUG("Failed to Create usb_mailbox\n");
|
||||
return -1;
|
||||
}
|
||||
usb_mailbox_cnt = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_mailbox_put(USB_MESSAGE* msg_src)
|
||||
{
|
||||
osStatus status;
|
||||
USB_MESSAGE *msg_p = NULL;
|
||||
|
||||
USBAUDIO_DEBUG("%s,%d",__func__,__LINE__);
|
||||
if(usb_mailbox_cnt >= 1)
|
||||
{
|
||||
USBAUDIO_DEBUG("%s,%d usb_mailbox_cnt = %d.",
|
||||
__func__,__LINE__,usb_mailbox_cnt);
|
||||
return 0;
|
||||
}
|
||||
msg_p = (USB_MESSAGE*)osMailAlloc(usb_mailbox, 0);
|
||||
ASSERT(msg_p, "osMailAlloc error");
|
||||
msg_p->id = msg_src->id;
|
||||
msg_p->ptr = msg_src->ptr;
|
||||
msg_p->param0 = msg_src->param0;
|
||||
msg_p->param1 = msg_src->param1;
|
||||
|
||||
status = osMailPut(usb_mailbox, msg_p);
|
||||
if (osOK == status)
|
||||
usb_mailbox_cnt++;
|
||||
USBAUDIO_DEBUG("%s,%d,usb_mailbox_cnt = %d.",__func__,__LINE__,usb_mailbox_cnt);
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int usb_mailbox_free(USB_MESSAGE* msg_p)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
USBAUDIO_DEBUG("%s,%d",__func__,__LINE__);
|
||||
status = osMailFree(usb_mailbox, msg_p);
|
||||
if (osOK == status)
|
||||
usb_mailbox_cnt--;
|
||||
USBAUDIO_DEBUG("%s,%d,usb_mailbox_cnt = %d.",__func__,__LINE__,usb_mailbox_cnt);
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int usb_mailbox_get(USB_MESSAGE **msg_p)
|
||||
{
|
||||
osEvent evt;
|
||||
evt = osMailGet(usb_mailbox, osWaitForever);
|
||||
if (evt.status == osEventMail) {
|
||||
*msg_p = (USB_MESSAGE*)evt.value.p;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void usb_thread(void const *argument)
|
||||
{
|
||||
// USB_FUNC_T usb_funcp;
|
||||
USBAUDIO_DEBUG("%s,%d",__func__,__LINE__);
|
||||
while(1){
|
||||
USB_MESSAGE *msg_p = NULL;
|
||||
|
||||
if (!usb_mailbox_get(&msg_p)) {
|
||||
//TRACE(2,"_debug: %s,%d",__func__,__LINE__);
|
||||
USBAUDIO_DEBUG("usb_thread: id = 0x%x, ptr = 0x%x,param0 = 0x%x,param1 = 0x%x.",
|
||||
msg_p->id,msg_p->ptr,msg_p->param0,msg_p->param1);
|
||||
usb_mailbox_free(msg_p);
|
||||
usb_audio_app_loop();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_enqueue_cmd(uint32_t data)
|
||||
{
|
||||
USB_MESSAGE usb_msg;
|
||||
|
||||
usb_msg.id = 0;
|
||||
usb_msg.param0 = 0;
|
||||
usb_msg.param1 = 0;
|
||||
usb_msg.ptr = 0;
|
||||
usb_mailbox_put(&usb_msg);
|
||||
}
|
||||
|
||||
int usb_os_init(void)
|
||||
{
|
||||
osThreadId usb_tid;
|
||||
|
||||
USBAUDIO_DEBUG("%s,%d",__func__,__LINE__);
|
||||
if (usb_mailbox_init()) {
|
||||
USBAUDIO_DEBUG("_debug: %s,%d",__func__,__LINE__);
|
||||
return -1;
|
||||
}
|
||||
usb_tid = osThreadCreate(osThread(usb_thread), NULL);
|
||||
if (usb_tid == NULL) {
|
||||
USBAUDIO_DEBUG("Failed to Create usb_thread\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
usb_audio_set_enqueue_cmd_callback(usb_enqueue_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __USB_THREAD_H__
|
||||
#define __USB_THREAD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USB_MAILBOX_MAX (20)
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t ptr;
|
||||
uint32_t param0;
|
||||
uint32_t param1;
|
||||
} USB_MESSAGE;
|
||||
|
||||
|
||||
//typedef int (*USB_MOD_HANDLER_T)(USB_MESSAGE_BODY *);
|
||||
typedef void (*USB_FUNC_T)(uint32_t, uint32_t);
|
||||
|
||||
int usb_mailbox_put(USB_MESSAGE* msg_src);
|
||||
|
||||
int usb_mailbox_free(USB_MESSAGE* msg_p);
|
||||
|
||||
int usb_mailbox_get(USB_MESSAGE** msg_p);
|
||||
|
||||
int usb_os_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __USB_THREAD_H__
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
subdir-ccflags-y += \
|
||||
-Iservices/audio_process \
|
||||
-Iservices/multimedia/audio/process/filters/include
|
|
@ -0,0 +1,71 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifdef __PC_CMD_UART__
|
||||
#include "cmsis_os.h"
|
||||
#include "list.h"
|
||||
#include "string.h"
|
||||
#include "app_thread.h"
|
||||
#include "app_cmd.h"
|
||||
#include "hal_cmd.h"
|
||||
#include "hal_trace.h"
|
||||
#include "audio_process.h"
|
||||
|
||||
#define APP_CMD_TRACE(s,...) TRACE(s, ##__VA_ARGS__)
|
||||
|
||||
void cmd_event_process(hal_cmd_rx_status_t status)
|
||||
{
|
||||
APP_CMD_TRACE(1,"%s",__func__);
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
msg.mod_id = APP_MODUAL_CMD;
|
||||
msg.msg_body.message_id = status;
|
||||
msg.msg_body.message_ptr = (uint32_t)NULL;
|
||||
app_mailbox_put(&msg);
|
||||
return;
|
||||
}
|
||||
|
||||
static int app_cmd_handle_process(APP_MESSAGE_BODY *msg_body)
|
||||
{
|
||||
hal_cmd_run((hal_cmd_rx_status_t)msg_body->message_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t app_cmd_flag = 0;
|
||||
|
||||
void app_cmd_open(void)
|
||||
{
|
||||
APP_CMD_TRACE(1,"%s",__func__);
|
||||
|
||||
app_cmd_flag = 1;
|
||||
|
||||
app_set_threadhandle(APP_MODUAL_CMD, app_cmd_handle_process);
|
||||
hal_cmd_set_callback(cmd_event_process);
|
||||
hal_cmd_open();
|
||||
return;
|
||||
}
|
||||
|
||||
void app_cmd_close(void)
|
||||
{
|
||||
APP_CMD_TRACE(1,"%s",__func__);
|
||||
if(app_cmd_flag)
|
||||
{
|
||||
app_cmd_flag = 0;
|
||||
hal_cmd_close();
|
||||
app_set_threadhandle(APP_MODUAL_CMD, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_CMD_H__
|
||||
#define __APP_CMD_H__
|
||||
#ifdef __PC_CMD_UART__
|
||||
|
||||
#include "hal_cmd.h"
|
||||
typedef struct {
|
||||
void *param;
|
||||
} APP_CMD_HANDLE;
|
||||
|
||||
void app_cmd_open(void);
|
||||
|
||||
void app_cmd_close(void);
|
||||
#endif
|
||||
#endif//__FMDEC_H__
|
|
@ -0,0 +1,17 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
subdir-ccflags-y += \
|
||||
-Iplatform/drivers/ana \
|
||||
-Iservices/ibrt_ui/inc \
|
||||
-Iservices/ibrt_core/inc
|
||||
|
||||
ifeq ($(RAND_FROM_MIC),1)
|
||||
subdir-ccflags-y += \
|
||||
-Iservices/bt_app \
|
||||
-Iservices/app_ai/inc
|
||||
endif
|
|
@ -0,0 +1,97 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "stdint.h"
|
||||
#include "app_spec_ostimer.h"
|
||||
#include "hal_trace.h"
|
||||
|
||||
|
||||
/// Create timer
|
||||
osStatus app_spec_timer_create (SPEC_TIMER_CTX_T *spec_timer_ctx, const osTimerDef_t *timer_def, os_timer_type type, void *argument)
|
||||
{
|
||||
spec_timer_ctx->type = type;
|
||||
spec_timer_ctx->argument = argument;
|
||||
spec_timer_ctx->timerid = osTimerCreate(timer_def, type, spec_timer_ctx);
|
||||
return spec_timer_ctx->timerid ? osOK: osErrorOS;
|
||||
}
|
||||
|
||||
/// Start or restart timer
|
||||
osStatus app_spec_timer_start (SPEC_TIMER_CTX_T *spec_timer_ctx, uint32_t millisec)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
//TRACE(1,"%s", __func__);
|
||||
if (millisec > UINT16_MAX){
|
||||
spec_timer_ctx->interval = millisec;
|
||||
spec_timer_ctx->ctx = millisec;
|
||||
status = osTimerStart(spec_timer_ctx->timerid, UINT16_MAX);
|
||||
}else{
|
||||
spec_timer_ctx->interval = millisec;
|
||||
spec_timer_ctx->ctx = millisec;
|
||||
status = osTimerStart(spec_timer_ctx->timerid, (uint32_t)millisec);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/// Stop timer
|
||||
osStatus app_spec_timer_stop (SPEC_TIMER_CTX_T *spec_timer_ctx)
|
||||
{
|
||||
return osTimerStop(spec_timer_ctx->timerid);
|
||||
}
|
||||
|
||||
/// Delete timer
|
||||
osStatus app_spec_timer_delete (SPEC_TIMER_CTX_T *spec_timer_ctx)
|
||||
{
|
||||
return osTimerDelete(spec_timer_ctx->timerid);
|
||||
}
|
||||
|
||||
void app_spec_timer_handler(void const *para)
|
||||
{
|
||||
SPEC_TIMER_CTX_T *spec_timer_ctx = (SPEC_TIMER_CTX_T *)para;
|
||||
|
||||
if (spec_timer_ctx->ctx > UINT16_MAX){
|
||||
spec_timer_ctx->ctx -= UINT16_MAX;
|
||||
if (spec_timer_ctx->ctx > UINT16_MAX){
|
||||
osTimerStart(spec_timer_ctx->timerid, UINT16_MAX);
|
||||
}else{
|
||||
osTimerStart(spec_timer_ctx->timerid, spec_timer_ctx->ctx);
|
||||
}
|
||||
}else{
|
||||
(*spec_timer_ctx->ptimer)(spec_timer_ctx->argument);
|
||||
if (spec_timer_ctx->type == osTimerPeriodic){
|
||||
app_spec_timer_start(spec_timer_ctx, spec_timer_ctx->interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//tester
|
||||
uint32_t ibrt_test_arg;
|
||||
void app_tws_ibrt_test_timer_cb(void const *para);
|
||||
specTimerDef (IBRT_TEST_TIMER, app_tws_ibrt_test_timer_cb);
|
||||
|
||||
void app_tws_ibrt_test_timer_cb(void const *para)
|
||||
{
|
||||
TRACE(2,"%s %08x", __func__, para);
|
||||
}
|
||||
|
||||
void app_tws_ibrt_test_timer(void)
|
||||
{
|
||||
app_spec_timer_create(specTimerCtx(IBRT_TEST_TIMER), specTimer(IBRT_TEST_TIMER), osTimerOnce, &ibrt_test_arg);
|
||||
app_spec_timer_start(specTimerCtx(IBRT_TEST_TIMER), 0x10100);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_SPEC_OSTIMER__
|
||||
#define __APP_SPEC_OSTIMER__
|
||||
#include "cmsis_os.h"
|
||||
|
||||
typedef struct{
|
||||
osTimerId timerid;
|
||||
os_timer_type type;
|
||||
os_ptimer ptimer;
|
||||
uint32_t interval;
|
||||
uint32_t ctx;
|
||||
void *argument;
|
||||
}SPEC_TIMER_CTX_T;
|
||||
|
||||
#define specTimerDef(name, function) \
|
||||
SPEC_TIMER_CTX_T spec_timer_ctx_##name = \
|
||||
{NULL, osTimerOnce, function, 0, 0, NULL}; \
|
||||
osTimerDef(name, app_spec_timer_handler)
|
||||
|
||||
#define specTimer osTimer
|
||||
|
||||
#define specTimerCtx(name) \
|
||||
&spec_timer_ctx_##name
|
||||
|
||||
void app_spec_timer_handler(void const *para);
|
||||
osStatus app_spec_timer_create (SPEC_TIMER_CTX_T *spec_timer_ctx, const osTimerDef_t *timer_def, os_timer_type type, void *argument);
|
||||
osStatus app_spec_timer_start (SPEC_TIMER_CTX_T *spec_timer_ctx, uint32_t millisec);
|
||||
osStatus app_spec_timer_stop (SPEC_TIMER_CTX_T *spec_timer_ctx);
|
||||
osStatus app_spec_timer_delete (SPEC_TIMER_CTX_T *spec_timer_ctx);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,164 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_timer.h"
|
||||
#include "app_utils.h"
|
||||
#include "app_thread.h"
|
||||
|
||||
|
||||
static APP_MOD_HANDLER_T mod_handler[APP_MODUAL_NUM];
|
||||
|
||||
static void app_thread(void const *argument);
|
||||
osThreadDef(app_thread, osPriorityHigh, 1, 1024*3, "app_thread");
|
||||
|
||||
osMailQDef (app_mailbox, APP_MAILBOX_MAX, APP_MESSAGE_BLOCK);
|
||||
static osMailQId app_mailbox = NULL;
|
||||
static uint8_t app_mailbox_cnt = 0;
|
||||
osThreadId app_thread_tid;
|
||||
|
||||
static int app_mailbox_init(void)
|
||||
{
|
||||
app_mailbox = osMailCreate(osMailQ(app_mailbox), NULL);
|
||||
if (app_mailbox == NULL) {
|
||||
TRACE(0,"Failed to Create app_mailbox\n");
|
||||
return -1;
|
||||
}
|
||||
app_mailbox_cnt = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_mailbox_put(APP_MESSAGE_BLOCK* msg_src)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
APP_MESSAGE_BLOCK *msg_p = NULL;
|
||||
|
||||
msg_p = (APP_MESSAGE_BLOCK*)osMailAlloc(app_mailbox, 0);
|
||||
|
||||
if (!msg_p){
|
||||
osEvent evt;
|
||||
TRACE_IMM(0,"osMailAlloc error dump");
|
||||
for (uint8_t i=0; i<APP_MAILBOX_MAX; i++){
|
||||
evt = osMailGet(app_mailbox, 0);
|
||||
if (evt.status == osEventMail) {
|
||||
TRACE_IMM(9,"cnt:%d mod:%d src:%08x tim:%d id:%x ptr:%08x para:%08x/%08x/%08x",
|
||||
i,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->mod_id,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->src_thread,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->system_time,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_id,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_ptr,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param0,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param1,
|
||||
((APP_MESSAGE_BLOCK *)(evt.value.p))->msg_body.message_Param2);
|
||||
}else{
|
||||
TRACE_IMM(2,"cnt:%d %d", i, evt.status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
TRACE_IMM(0,"osMailAlloc error dump end");
|
||||
}
|
||||
|
||||
ASSERT(msg_p, "osMailAlloc error");
|
||||
msg_p->src_thread = (uint32_t)osThreadGetId();
|
||||
msg_p->dest_thread = (uint32_t)NULL;
|
||||
msg_p->system_time = hal_sys_timer_get();
|
||||
msg_p->mod_id = msg_src->mod_id;
|
||||
msg_p->msg_body.message_id = msg_src->msg_body.message_id;
|
||||
msg_p->msg_body.message_ptr = msg_src->msg_body.message_ptr;
|
||||
msg_p->msg_body.message_Param0 = msg_src->msg_body.message_Param0;
|
||||
msg_p->msg_body.message_Param1 = msg_src->msg_body.message_Param1;
|
||||
msg_p->msg_body.message_Param2 = msg_src->msg_body.message_Param2;
|
||||
|
||||
status = osMailPut(app_mailbox, msg_p);
|
||||
if (osOK == status)
|
||||
app_mailbox_cnt++;
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int app_mailbox_free(APP_MESSAGE_BLOCK* msg_p)
|
||||
{
|
||||
osStatus status;
|
||||
|
||||
status = osMailFree(app_mailbox, msg_p);
|
||||
if (osOK == status)
|
||||
app_mailbox_cnt--;
|
||||
|
||||
return (int)status;
|
||||
}
|
||||
|
||||
int app_mailbox_get(APP_MESSAGE_BLOCK** msg_p)
|
||||
{
|
||||
osEvent evt;
|
||||
evt = osMailGet(app_mailbox, osWaitForever);
|
||||
if (evt.status == osEventMail) {
|
||||
*msg_p = (APP_MESSAGE_BLOCK *)evt.value.p;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void app_thread(void const *argument)
|
||||
{
|
||||
while(1){
|
||||
APP_MESSAGE_BLOCK *msg_p = NULL;
|
||||
|
||||
if (!app_mailbox_get(&msg_p)) {
|
||||
if (msg_p->mod_id < APP_MODUAL_NUM) {
|
||||
if (mod_handler[msg_p->mod_id]) {
|
||||
int ret = mod_handler[msg_p->mod_id](&(msg_p->msg_body));
|
||||
if (ret)
|
||||
TRACE(2,"mod_handler[%d] ret=%d", msg_p->mod_id, ret);
|
||||
}
|
||||
}
|
||||
app_mailbox_free(msg_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int app_os_init(void)
|
||||
{
|
||||
if (app_mailbox_init())
|
||||
return -1;
|
||||
|
||||
app_thread_tid = osThreadCreate(osThread(app_thread), NULL);
|
||||
if (app_thread_tid == NULL) {
|
||||
TRACE(0,"Failed to Create app_thread\n");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_set_threadhandle(enum APP_MODUAL_ID_T mod_id, APP_MOD_HANDLER_T handler)
|
||||
{
|
||||
if (mod_id>=APP_MODUAL_NUM)
|
||||
return -1;
|
||||
|
||||
mod_handler[mod_id] = handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void * app_os_tid_get(void)
|
||||
{
|
||||
return (void *)app_thread_tid;
|
||||
}
|
||||
|
||||
bool app_is_module_registered(enum APP_MODUAL_ID_T mod_id)
|
||||
{
|
||||
return mod_handler[mod_id];
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_THREAD_H__
|
||||
#define __APP_THREAD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define APP_MAILBOX_MAX (20)
|
||||
|
||||
enum APP_MODUAL_ID_T {
|
||||
APP_MODUAL_KEY = 0,
|
||||
APP_MODUAL_AUDIO,
|
||||
APP_MODUAL_BATTERY,
|
||||
APP_MODUAL_BT,
|
||||
APP_MODUAL_FM,
|
||||
APP_MODUAL_SD,
|
||||
APP_MODUAL_LINEIN,
|
||||
APP_MODUAL_USBHOST,
|
||||
APP_MODUAL_USBDEVICE,
|
||||
APP_MODUAL_WATCHDOG,
|
||||
APP_MODUAL_AUDIO_MANAGE,
|
||||
APP_MODUAL_ANC,
|
||||
APP_MODUAL_SMART_MIC,
|
||||
#ifdef __PC_CMD_UART__
|
||||
APP_MODUAL_CMD,
|
||||
#endif
|
||||
#ifdef TILE_DATAPATH
|
||||
APP_MODUAL_TILE,
|
||||
#endif
|
||||
APP_MODUAL_MIC,
|
||||
#ifdef VOICE_DETECTOR_EN
|
||||
APP_MODUAL_VOICE_DETECTOR,
|
||||
#endif
|
||||
APP_MODUAL_CUSTOM_FUNCTION,
|
||||
APP_MODUAL_OHTER,
|
||||
APP_MODUAL_WNR,
|
||||
|
||||
APP_MODUAL_NUM
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t message_id;
|
||||
uint32_t message_ptr;
|
||||
uint32_t message_Param0;
|
||||
uint32_t message_Param1;
|
||||
uint32_t message_Param2;
|
||||
} APP_MESSAGE_BODY;
|
||||
|
||||
typedef struct {
|
||||
uint32_t src_thread;
|
||||
uint32_t dest_thread;
|
||||
uint32_t system_time;
|
||||
uint32_t mod_id;
|
||||
APP_MESSAGE_BODY msg_body;
|
||||
} APP_MESSAGE_BLOCK;
|
||||
|
||||
typedef int (*APP_MOD_HANDLER_T)(APP_MESSAGE_BODY *);
|
||||
|
||||
int app_mailbox_put(APP_MESSAGE_BLOCK* msg_src);
|
||||
|
||||
int app_mailbox_free(APP_MESSAGE_BLOCK* msg_p);
|
||||
|
||||
int app_mailbox_get(APP_MESSAGE_BLOCK** msg_p);
|
||||
|
||||
int app_os_init(void);
|
||||
|
||||
int app_set_threadhandle(enum APP_MODUAL_ID_T mod_id, APP_MOD_HANDLER_T handler);
|
||||
|
||||
void * app_os_tid_get(void);
|
||||
|
||||
bool app_is_module_registered(enum APP_MODUAL_ID_T mod_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__FMDEC_H__
|
|
@ -0,0 +1,281 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hal_wdt.h"
|
||||
#include "pmu.h"
|
||||
#include "analog.h"
|
||||
#include "app_utils.h"
|
||||
#ifdef RTOS
|
||||
#include "cmsis_os.h"
|
||||
#endif
|
||||
|
||||
#define FREQ_FREE 0UL
|
||||
#define FREQ_26M 26UL
|
||||
#define FREQ_52M 52UL
|
||||
#define FREQ_78M 78UL
|
||||
#define FREQ_104M 104UL
|
||||
#define FREQ_208M 208UL
|
||||
|
||||
/*
|
||||
* qos_users, quality of services users, this kind of user must run with the
|
||||
* minist frequency they requiested, if there are more users, the frequency
|
||||
* should be boost for these users
|
||||
* e.g. the key word recorgnithion function request 26M Hz, and the music
|
||||
* also need 26M, if both of them are running, the cpu freq should boost to
|
||||
* 26M + 26M = 52M Hz
|
||||
*/
|
||||
/*
|
||||
* NOTE:
|
||||
* The macro QOS_USERS works only when the APP_SYSFREQ_USER_APP_XXX is not large than
|
||||
* 32, currently this works, but if the are more user, another way needed
|
||||
*/
|
||||
#define QOS_USERS ((1 << (APP_SYSFREQ_USER_AI_VOICE)) | \
|
||||
(1 << (APP_SYSFREQ_USER_BT_A2DP)))
|
||||
|
||||
static const uint32_t freq_map[] = {
|
||||
[HAL_CMU_FREQ_32K] = FREQ_FREE,
|
||||
[HAL_CMU_FREQ_26M] = FREQ_26M,
|
||||
[HAL_CMU_FREQ_52M] = FREQ_52M,
|
||||
[HAL_CMU_FREQ_78M] = FREQ_78M,
|
||||
[HAL_CMU_FREQ_104M] = FREQ_104M,
|
||||
[HAL_CMU_FREQ_208M] = FREQ_208M,
|
||||
};
|
||||
|
||||
static const uint32_t user_map[] = {
|
||||
[0] = APP_SYSFREQ_USER_AI_VOICE,
|
||||
[1] = APP_SYSFREQ_USER_BT_A2DP,
|
||||
};
|
||||
/*
|
||||
* qos_freqs_map
|
||||
* filled with user's freq, one user's freq occupy 4bits,
|
||||
* that limit the frequecy number is not large than 16
|
||||
*
|
||||
* bit field structure:
|
||||
-----------------------------------------------------
|
||||
|user7 | user6 |..................|user1 | user 0|
|
||||
-----------------------------------------------------
|
||||
|31~28 | 27~24 |..................|7~4 | 3~0 |
|
||||
-----------------------------------------------------
|
||||
*
|
||||
* Ok, this is ugly, but there is not so much frequecy level,
|
||||
* and maybe work for a long time
|
||||
*/
|
||||
static uint32_t qos_freqs_map;
|
||||
|
||||
/*
|
||||
* qos_users_map
|
||||
* filled with user's number, one user's occupy 1 bit,
|
||||
*
|
||||
bit field structure:
|
||||
-----------------------------------------------------
|
||||
|user31~7(reseverd)| user7 |........| user 1| user 0|
|
||||
-----------------------------------------------------
|
||||
*
|
||||
*/
|
||||
static uint32_t qos_users_map;
|
||||
|
||||
static int app_qosfreq_req(enum APP_SYSFREQ_USER_T user, enum APP_SYSFREQ_FREQ_T freq)
|
||||
{
|
||||
int ret;
|
||||
int qos_freq_num = 0;
|
||||
uint32_t max_qos_freq = 0;
|
||||
int user_idx;
|
||||
int i;
|
||||
uint32_t lock;
|
||||
|
||||
if (freq >= APP_SYSFREQ_FREQ_QTY)
|
||||
return -1;
|
||||
|
||||
lock = int_lock();
|
||||
for (i = 0; i < ARRAY_SIZE(user_map); i++) {
|
||||
if (user == user_map[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(user_map)) {
|
||||
int_unlock(lock);
|
||||
ASSERT(0, "can not find qos user");
|
||||
return 0;
|
||||
}
|
||||
|
||||
user_idx = i;
|
||||
if ((int)freq != (int)HAL_CMU_FREQ_32K) { // require freq
|
||||
qos_freqs_map &= ~(0xf << (4 * i));
|
||||
qos_freqs_map |= freq << (4 * i);
|
||||
qos_users_map |= 1 << user_idx;
|
||||
} else { //release freq
|
||||
qos_freqs_map &= ~(0xf << (4 * i));
|
||||
qos_users_map &= ~ (1 << user_idx);
|
||||
}
|
||||
|
||||
//scan the qos_user_map and sum every user's request freq
|
||||
for(i = 0; i < ARRAY_SIZE(user_map); i++) {
|
||||
if ((qos_users_map >> i) & 0x1) {
|
||||
uint32_t real_freq;
|
||||
int freq_num;
|
||||
|
||||
freq_num = (qos_freqs_map >> (4 * i )) & 0xf;
|
||||
real_freq = freq_map[freq_num];
|
||||
max_qos_freq += real_freq;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(freq_map); i++) {
|
||||
if (i) {
|
||||
if ((max_qos_freq > freq_map[i-1]) && (max_qos_freq <= freq_map[i])) {
|
||||
qos_freq_num = i;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (max_qos_freq == freq_map[i]) {
|
||||
qos_freq_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= ARRAY_SIZE(freq_map)) {
|
||||
qos_freq_num = (HAL_CMU_FREQ_QTY - 1);
|
||||
int_unlock(lock);
|
||||
TRACE(0, "WARNING: required sysfreq exceed");
|
||||
// ASSERT(0, "can not find actual freq");
|
||||
return 0;
|
||||
}
|
||||
|
||||
user = APP_SYSFREQ_USER_QOS;
|
||||
TRACE(2, "User %d require sysfreq %d", user, qos_freq_num);
|
||||
ret = hal_sysfreq_req((enum HAL_SYSFREQ_USER_T)user, (enum HAL_CMU_FREQ_T)qos_freq_num);
|
||||
|
||||
int_unlock(lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_sysfreq_req(enum APP_SYSFREQ_USER_T user, enum APP_SYSFREQ_FREQ_T freq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
// if user is qos user
|
||||
if ((1 << user) & QOS_USERS) {
|
||||
ret = app_qosfreq_req(user, freq);
|
||||
} else { // if user is NOT qos user
|
||||
ret = hal_sysfreq_req((enum HAL_SYSFREQ_USER_T)user, (enum HAL_CMU_FREQ_T)freq);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef RTOS
|
||||
|
||||
extern int rtx_task_idle_health_check(void);
|
||||
static void watchdog_ping_handler(void const *n);
|
||||
static osTimerId wdt_ping_timer_id;
|
||||
osTimerDef(wdt_ping_timer, watchdog_ping_handler);
|
||||
static uint32_t wdt_ping_period;
|
||||
|
||||
static void watchdog_ping(void)
|
||||
{
|
||||
hal_wdt_ping(HAL_WDT_ID_0);
|
||||
#ifndef CHIP_BEST2000
|
||||
pmu_wdt_feed();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_wdt_irq_handle(enum HAL_WDT_ID_T id, uint32_t status)
|
||||
{
|
||||
analog_aud_codec_mute();
|
||||
ASSERT(0, "%s id:%d status:%d",__func__, id, status);
|
||||
}
|
||||
|
||||
static void pmu_wdt_irq_handle(void)
|
||||
{
|
||||
analog_aud_codec_mute();
|
||||
ASSERT(1, "%s", __func__);
|
||||
}
|
||||
|
||||
static void watchdog_ping_handler(void const *unused)
|
||||
{
|
||||
int ret;
|
||||
|
||||
watchdog_ping();
|
||||
ret = rtx_task_idle_health_check();
|
||||
if (ret < 0) {
|
||||
ASSERT(0, "System soft lockup");
|
||||
}
|
||||
|
||||
osTimerStart(wdt_ping_timer_id, wdt_ping_period);
|
||||
}
|
||||
|
||||
int app_wdt_open(int seconds)
|
||||
{
|
||||
uint32_t lock = int_lock();
|
||||
|
||||
hal_wdt_set_irq_callback(HAL_WDT_ID_0, app_wdt_irq_handle);
|
||||
hal_wdt_set_timeout(HAL_WDT_ID_0, seconds);
|
||||
hal_wdt_start(HAL_WDT_ID_0);
|
||||
pmu_wdt_set_irq_handler(pmu_wdt_irq_handle);
|
||||
#ifndef CHIP_BEST2000
|
||||
pmu_wdt_config(seconds * 1100, seconds * 1100);
|
||||
pmu_wdt_start();
|
||||
#endif
|
||||
int_unlock(lock);
|
||||
wdt_ping_timer_id = osTimerCreate(osTimer(wdt_ping_timer), osTimerOnce, NULL);
|
||||
if (!wdt_ping_timer_id) {
|
||||
TRACE(0,"Warning: can not create watchdog ping timer");
|
||||
return -1;
|
||||
}
|
||||
wdt_ping_period = seconds * 1000 / 4;
|
||||
|
||||
osTimerStart(wdt_ping_timer_id, wdt_ping_period);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_wdt_reopen(int seconds)
|
||||
{
|
||||
uint32_t lock = int_lock();
|
||||
hal_wdt_stop(HAL_WDT_ID_0);
|
||||
hal_wdt_set_timeout(HAL_WDT_ID_0, seconds);
|
||||
hal_wdt_start(HAL_WDT_ID_0);
|
||||
#ifndef CHIP_BEST2000
|
||||
pmu_wdt_config(seconds * 1000, seconds * 1000);
|
||||
pmu_wdt_start();
|
||||
#endif
|
||||
int_unlock(lock);
|
||||
|
||||
osTimerStart(wdt_ping_timer_id, wdt_ping_period);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_wdt_close(void)
|
||||
{
|
||||
uint32_t lock;
|
||||
|
||||
osTimerStop(wdt_ping_timer_id);
|
||||
|
||||
lock = int_lock();
|
||||
hal_wdt_stop(HAL_WDT_ID_0);
|
||||
#ifndef CHIP_BEST2000
|
||||
pmu_wdt_stop();
|
||||
#endif
|
||||
int_unlock(lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_UTILS_H__
|
||||
#define __APP_UTILS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "hal_sysfreq.h"
|
||||
|
||||
// APP_SYSFREQ_USER_APP_0 is APP_MAIN
|
||||
#define APP_SYSFREQ_USER_BT_MAIN APP_SYSFREQ_USER_APP_1
|
||||
#define APP_SYSFREQ_USER_HCI APP_SYSFREQ_USER_APP_2
|
||||
#define APP_SYSFREQ_USER_BT_A2DP APP_SYSFREQ_USER_APP_3
|
||||
#define APP_SYSFREQ_USER_UNUSED APP_SYSFREQ_USER_APP_4
|
||||
#define APP_SYSFREQ_USER_AI_VOICE APP_SYSFREQ_USER_APP_5
|
||||
#define APP_SYSFREQ_USER_BT_SCO APP_SYSFREQ_USER_APP_6
|
||||
#define APP_SYSFREQ_USER_OTA APP_SYSFREQ_USER_APP_7
|
||||
#define APP_SYSFREQ_USER_PROMPT_MIXER APP_SYSFREQ_USER_APP_8
|
||||
#define APP_SYSFREQ_USER_APP_NT APP_SYSFREQ_USER_APP_9
|
||||
#define APP_SYSFREQ_USER_ANC_WNR APP_SYSFREQ_USER_APP_10
|
||||
#ifdef __RAND_FROM_MIC__
|
||||
#define APP_SYSFREQ_USER_RANDOM APP_SYSFREQ_USER_APP_11
|
||||
#endif
|
||||
#ifdef __DUAL_MIC_RECORDING__
|
||||
#define APP_SYSFREQ_USER_RECORDING APP_SYSFREQ_USER_APP_12
|
||||
#endif
|
||||
/*
|
||||
* Pseudo user, if one of user is belong to qos(quality of service) user,
|
||||
* when request cpu freq, it will changed to this user
|
||||
*/
|
||||
#define APP_SYSFREQ_USER_QOS APP_SYSFREQ_USER_APP_12
|
||||
|
||||
enum APP_SYSFREQ_USER_T {
|
||||
APP_SYSFREQ_USER_APP_INIT = HAL_SYSFREQ_USER_INIT,
|
||||
APP_SYSFREQ_USER_APP_0 = HAL_SYSFREQ_USER_APP_0,
|
||||
APP_SYSFREQ_USER_APP_1 = HAL_SYSFREQ_USER_APP_1,
|
||||
APP_SYSFREQ_USER_APP_2 = HAL_SYSFREQ_USER_APP_2,
|
||||
APP_SYSFREQ_USER_APP_3 = HAL_SYSFREQ_USER_APP_3,
|
||||
APP_SYSFREQ_USER_APP_4 = HAL_SYSFREQ_USER_APP_4,
|
||||
APP_SYSFREQ_USER_APP_5 = HAL_SYSFREQ_USER_APP_5,
|
||||
APP_SYSFREQ_USER_APP_6 = HAL_SYSFREQ_USER_APP_6,
|
||||
APP_SYSFREQ_USER_APP_7 = HAL_SYSFREQ_USER_APP_7,
|
||||
APP_SYSFREQ_USER_APP_8 = HAL_SYSFREQ_USER_APP_8,
|
||||
APP_SYSFREQ_USER_APP_9 = HAL_SYSFREQ_USER_APP_9,
|
||||
APP_SYSFREQ_USER_APP_10 = HAL_SYSFREQ_USER_APP_10,
|
||||
APP_SYSFREQ_USER_APP_11 = HAL_SYSFREQ_USER_APP_11,
|
||||
APP_SYSFREQ_USER_APP_12 = HAL_SYSFREQ_USER_APP_12,
|
||||
APP_SYSFREQ_USER_APP_13 = HAL_SYSFREQ_USER_APP_13,
|
||||
APP_SYSFREQ_USER_APP_14 = HAL_SYSFREQ_USER_APP_14,
|
||||
APP_SYSFREQ_USER_APP_15 = HAL_SYSFREQ_USER_APP_15,
|
||||
APP_SYSFREQ_USER_QTY
|
||||
};
|
||||
|
||||
enum APP_SYSFREQ_FREQ_T {
|
||||
APP_SYSFREQ_32K = HAL_CMU_FREQ_32K,
|
||||
APP_SYSFREQ_26M = HAL_CMU_FREQ_26M,
|
||||
APP_SYSFREQ_52M = HAL_CMU_FREQ_52M,
|
||||
APP_SYSFREQ_78M = HAL_CMU_FREQ_78M,
|
||||
APP_SYSFREQ_104M = HAL_CMU_FREQ_104M,
|
||||
APP_SYSFREQ_208M = HAL_CMU_FREQ_208M,
|
||||
|
||||
APP_SYSFREQ_FREQ_QTY = HAL_CMU_FREQ_QTY
|
||||
};
|
||||
|
||||
enum APP_WDT_THREAD_CHECK_USER_T {
|
||||
APP_WDT_THREAD_CHECK_USER_APP,
|
||||
APP_WDT_THREAD_CHECK_USER_AF,
|
||||
APP_WDT_THREAD_CHECK_USER_BT,
|
||||
APP_WDT_THREAD_CHECK_USER_3,
|
||||
APP_WDT_THREAD_CHECK_USER_4,
|
||||
APP_WDT_THREAD_CHECK_USER_5,
|
||||
APP_WDT_THREAD_CHECK_USER_6,
|
||||
APP_WDT_THREAD_CHECK_USER_7,
|
||||
APP_WDT_THREAD_CHECK_USER_8,
|
||||
APP_WDT_THREAD_CHECK_USER_9,
|
||||
APP_WDT_THREAD_CHECK_USER_10,
|
||||
|
||||
APP_WDT_THREAD_CHECK_USER_QTY
|
||||
};
|
||||
|
||||
int app_sysfreq_req(enum APP_SYSFREQ_USER_T user, enum APP_SYSFREQ_FREQ_T freq);
|
||||
|
||||
int app_wdt_open(int seconds);
|
||||
|
||||
int app_wdt_reopen(int seconds);
|
||||
|
||||
int app_wdt_close(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//__FMDEC_H__
|
|
@ -0,0 +1,267 @@
|
|||
#ifdef __RAND_FROM_MIC__
|
||||
#include "audioflinger.h"
|
||||
#include "hal_trace.h"
|
||||
#include "app_utils.h"
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdio.h"
|
||||
#include "app_bt_stream.h"
|
||||
#include "randfrommic.h"
|
||||
#include "hal_timer.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "cmsis_gcc.h"
|
||||
#include "app_audio.h"
|
||||
|
||||
#if BT_DRV_DEBUG
|
||||
#define RAND_TRACE(n, fmt, ...) TRACE(n, fmt, ##__VA_ARGS__)
|
||||
#define RAND_DUMP(s,buff,len) DUMP8(s,buff,len)
|
||||
#else
|
||||
#define RAND_TRACE(n, fmt, ...)
|
||||
#define RAND_DUMP(s,buff,len)
|
||||
#endif
|
||||
|
||||
static void generateRand(bool on);
|
||||
static uint32_t rand_data_handle(uint8_t *buf, uint32_t len);
|
||||
|
||||
static uint8_t deviceId = 0;
|
||||
static uint8_t *captureBuffer = NULL;
|
||||
static uint32_t randSeed = 1;
|
||||
static bool randInitialised = false;
|
||||
|
||||
// 4 bytes aligned
|
||||
#define RAND_GRAB_BITS_PER_SAMPLE 4
|
||||
#define RAND_GRAB_BITS_MASK_PER_SAMPLE ((1 << RAND_GRAB_BITS_PER_SAMPLE)-1)
|
||||
|
||||
RAND_NUMBER_T randomBuffer =
|
||||
{
|
||||
25,
|
||||
RAND_STATUS_CLOSE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Description: parse mic data according to the stream cfg(bit mode and channel number)
|
||||
* only the lowest byte of each frame is taken
|
||||
* ADC format:
|
||||
* 16bit mode -> [15:0] is valid
|
||||
* 24bit mode -> [23:4] is valid
|
||||
* 32bit mode -> [31:12] is valid
|
||||
*
|
||||
*/
|
||||
static int randDataParse(uint8_t *buf, uint32_t len, enum AUD_BITS_T bits,
|
||||
enum AUD_CHANNEL_NUM_T ch_num)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
|
||||
union {
|
||||
uint32_t seedValue;
|
||||
uint8_t value[4];
|
||||
}seedData;
|
||||
|
||||
if ((NULL == buf) ||
|
||||
((RANDOM_CAPTURE_BUFFER_SIZE/2) > len)) // ping-pong buffer
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
RAND_TRACE(1, "%s", __func__);
|
||||
RAND_DUMP("%x ",buf, 16);
|
||||
|
||||
switch (bits)
|
||||
{
|
||||
case AUD_BITS_16:
|
||||
{
|
||||
uint16_t* content = (uint16_t *)buf;
|
||||
|
||||
for (index = 0;index < 4; index++)
|
||||
{
|
||||
seedData.value[index] = ((*content) & RAND_GRAB_BITS_MASK_PER_SAMPLE) |
|
||||
(((*(content+ch_num)) & RAND_GRAB_BITS_MASK_PER_SAMPLE) << RAND_GRAB_BITS_PER_SAMPLE);
|
||||
content += ((8/RAND_GRAB_BITS_PER_SAMPLE)*ch_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUD_BITS_24:
|
||||
{
|
||||
uint32_t* content = (uint32_t *)buf;
|
||||
for (index = 0;index < 4; index++)
|
||||
{
|
||||
// bit 23:4 are valid
|
||||
seedData.value[index] = (((*content) >> 4) & RAND_GRAB_BITS_MASK_PER_SAMPLE) |
|
||||
((((*(content+ch_num)) >> 4)&RAND_GRAB_BITS_MASK_PER_SAMPLE) << RAND_GRAB_BITS_PER_SAMPLE);
|
||||
content += ((8/RAND_GRAB_BITS_PER_SAMPLE)*ch_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUD_BITS_32:
|
||||
{
|
||||
uint32_t* content = (uint32_t *)buf;
|
||||
for (index = 0;index < 4; index++)
|
||||
{
|
||||
// bit 31:12 are valid
|
||||
seedData.value[index] = (((*content) >> 12) & RAND_GRAB_BITS_MASK_PER_SAMPLE) |
|
||||
((((*(content+ch_num)) >> 12) & RAND_GRAB_BITS_MASK_PER_SAMPLE) << RAND_GRAB_BITS_PER_SAMPLE);
|
||||
content += ((8/RAND_GRAB_BITS_PER_SAMPLE)*ch_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
randSeed = seedData.seedValue;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void generateRand(bool on)
|
||||
{
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
|
||||
RAND_TRACE(2, "%s op:%d", __func__, on);
|
||||
|
||||
if (on)
|
||||
{
|
||||
randomBuffer.skipRound = 10;
|
||||
|
||||
randomBuffer.status = random_mic_is_on(&deviceId);
|
||||
RAND_TRACE(2, "%s random status = %d", __func__, randomBuffer.status);
|
||||
|
||||
if (RAND_STATUS_CLOSE == randomBuffer.status)
|
||||
{
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_RANDOM, APP_SYSFREQ_208M);
|
||||
app_capture_audio_mempool_init();
|
||||
app_capture_audio_mempool_get_buff(&captureBuffer,
|
||||
RANDOM_CAPTURE_BUFFER_SIZE);
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
stream_cfg.bits = AUD_BITS_16;
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
stream_cfg.sample_rate = AUD_SAMPRATE_8000;
|
||||
stream_cfg.vol = TGT_VOLUME_LEVEL_15;
|
||||
stream_cfg.io_path = AUD_INPUT_PATH_MAINMIC;
|
||||
stream_cfg.handler = rand_data_handle;
|
||||
|
||||
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(captureBuffer);
|
||||
stream_cfg.data_size = RANDOM_CAPTURE_BUFFER_SIZE;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
randomBuffer.status = RAND_STATUS_OPEN;
|
||||
}
|
||||
else if(RAND_STATUS_MIC_OPENED == randomBuffer.status)
|
||||
{
|
||||
af_stream_start(deviceId, AUD_STREAM_CAPTURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// release the acquired system clock
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_RANDOM, APP_SYSFREQ_32K);
|
||||
if (RAND_STATUS_MIC_OPENED == randomBuffer.status)
|
||||
{
|
||||
af_stream_stop(deviceId, AUD_STREAM_CAPTURE);
|
||||
}
|
||||
else if (RAND_STATUS_OPEN == randomBuffer.status)
|
||||
{
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
}
|
||||
randomBuffer.status = RAND_STATUS_CLOSE;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t rand_data_handle(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (buf == NULL)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
if ((1 == randomBuffer.skipRound) &&
|
||||
(!randDataParse(buf, len, AUD_BITS_16, AUD_CHANNEL_NUM_1)))
|
||||
{
|
||||
generateRand(false);
|
||||
randomBuffer.skipRound = 0;
|
||||
}
|
||||
else if (1 != randomBuffer.skipRound)
|
||||
{
|
||||
randomBuffer.skipRound--;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void initSeed(void)
|
||||
{
|
||||
uint8_t count = 100; // avoid deed loop
|
||||
|
||||
RAND_TRACE(2, "%s:+++ initialised = %d", __func__, randInitialised);
|
||||
|
||||
if (randInitialised)
|
||||
{
|
||||
generateRand(true);
|
||||
|
||||
while ((0 != randomBuffer.skipRound) && (0 != count))
|
||||
{
|
||||
osDelay(10);
|
||||
count --;
|
||||
}
|
||||
}
|
||||
|
||||
if ((0 == count) || (false == randInitialised))
|
||||
{
|
||||
RAND_TRACE(1, "%s not ready", __func__);
|
||||
randSeed = (uint32_t)hal_sys_timer_get();
|
||||
generateRand(false);
|
||||
}
|
||||
|
||||
srand(randSeed);
|
||||
RAND_TRACE(2, "%s:--- count = %d", __func__, count);
|
||||
}
|
||||
|
||||
void random_status_sync(void)
|
||||
{
|
||||
if (RAND_STATUS_OPEN == randomBuffer.status)
|
||||
{
|
||||
RAND_TRACE(1, "%s random mic has already on,should be closed", __func__);
|
||||
generateRand(false);
|
||||
}
|
||||
}
|
||||
|
||||
void random_data_process(uint8_t *buf, uint32_t len,enum AUD_BITS_T bits,
|
||||
enum AUD_CHANNEL_NUM_T ch_num)
|
||||
{
|
||||
if (buf == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((RAND_STATUS_MIC_STARTED == randomBuffer.status) ||
|
||||
(RAND_STATUS_MIC_OPENED == randomBuffer.status))
|
||||
{
|
||||
if (len >= RANDOM_CAPTURE_BUFFER_SIZE/2)
|
||||
{
|
||||
RAND_TRACE(4, "%s buf address = 0x%p, bits = %d, channel num = %d", __func__, buf, bits, ch_num);
|
||||
RAND_DUMP("%02x ", buf, 32);
|
||||
if ((1 == randomBuffer.skipRound) &&
|
||||
(!randDataParse(buf, len, bits, ch_num)))
|
||||
{
|
||||
generateRand(false);
|
||||
randomBuffer.skipRound = 0;
|
||||
}
|
||||
else if (1 != randomBuffer.skipRound)
|
||||
{
|
||||
randomBuffer.skipRound--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void randInit(void)
|
||||
{
|
||||
randInitialised = true;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
#ifdef __RAND_FROM_MIC__
|
||||
#ifndef __RANDFROMMIC_H__
|
||||
#define __RANDFROMMIC_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RANDOM_CAPTURE_BUFFER_SIZE 512
|
||||
|
||||
// random module state machine
|
||||
typedef enum {
|
||||
RAND_STATUS_CLOSE = 0x00, // initial state
|
||||
RAND_STATUS_OPEN = 0x01, // indicate MIC has been started by random module
|
||||
RAND_STATUS_MIC_STARTED = 0x02, // indicate MIC has been started
|
||||
RAND_STATUS_MIC_OPENED = 0x03, // indicate MIC has been opened but not start
|
||||
RAND_STATUS_NUM = 0x0F
|
||||
}RAND_STATUS_E;
|
||||
|
||||
typedef struct{
|
||||
uint8_t skipRound; // used to indicate the number of rounds should be skipped to avoid all zero value
|
||||
RAND_STATUS_E status;
|
||||
}__attribute__ ((__packed__))RAND_NUMBER_T;
|
||||
|
||||
void initSeed(void);
|
||||
void random_status_sync(void);
|
||||
void random_data_process(uint8_t *buf, uint32_t len,enum AUD_BITS_T bits, enum AUD_CHANNEL_NUM_T ch_num);
|
||||
void randInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,882 @@
|
|||
0, 0,
|
||||
4652, 4653,
|
||||
9211, 9210,
|
||||
13583, 13583,
|
||||
17679, 17680,
|
||||
21418, 21417,
|
||||
24722, 24722,
|
||||
27525, 27524,
|
||||
29770, 29770,
|
||||
31413, 31413,
|
||||
32418, 32418,
|
||||
32767, 32767,
|
||||
32452, 32452,
|
||||
31478, 31479,
|
||||
29867, 29867,
|
||||
27651, 27651,
|
||||
24875, 24874,
|
||||
21594, 21594,
|
||||
17876, 17876,
|
||||
13795, 13795,
|
||||
9435, 9434,
|
||||
4884, 4884,
|
||||
234, 234,
|
||||
-4421, -4422,
|
||||
-8986, -8987,
|
||||
-13370, -13371,
|
||||
-17483, -17482,
|
||||
-21240, -21241,
|
||||
-24568, -24568,
|
||||
-27398, -27398,
|
||||
-29672, -29673,
|
||||
-31345, -31346,
|
||||
-32384, -32383,
|
||||
-32766, -32765,
|
||||
-32483, -32483,
|
||||
-31542, -31542,
|
||||
-29963, -29963,
|
||||
-27776, -27775,
|
||||
-25026, -25026,
|
||||
-21769, -21769,
|
||||
-18071, -18071,
|
||||
-14007, -14006,
|
||||
-9659, -9658,
|
||||
-5114, -5114,
|
||||
-466, -467,
|
||||
4190, 4190,
|
||||
8763, 8763,
|
||||
13157, 13157,
|
||||
17284, 17284,
|
||||
21062, 21063,
|
||||
24413, 24413,
|
||||
27269, 27268,
|
||||
29572, 29573,
|
||||
31277, 31277,
|
||||
32347, 32347,
|
||||
32762, 32762,
|
||||
32512, 32513,
|
||||
31605, 31605,
|
||||
30057, 30057,
|
||||
27898, 27899,
|
||||
25175, 25176,
|
||||
21943, 21943,
|
||||
18265, 18265,
|
||||
14217, 14217,
|
||||
9881, 9881,
|
||||
5345, 5345,
|
||||
700, 700,
|
||||
-3959, -3958,
|
||||
-8537, -8536,
|
||||
-12943, -12943,
|
||||
-17086, -17086,
|
||||
-20883, -20883,
|
||||
-24257, -24256,
|
||||
-27139, -27139,
|
||||
-29470, -29471,
|
||||
-31207, -31207,
|
||||
-32309, -32308,
|
||||
-32757, -32756,
|
||||
-32540, -32541,
|
||||
-31665, -31666,
|
||||
-30149, -30148,
|
||||
-28020, -28020,
|
||||
-25324, -25325,
|
||||
-22115, -22116,
|
||||
-18458, -18458,
|
||||
-14427, -14428,
|
||||
-10104, -10102,
|
||||
-5575, -5575,
|
||||
-934, -934,
|
||||
3727, 3727,
|
||||
8312, 8311,
|
||||
12728, 12728,
|
||||
16886, 16886,
|
||||
20702, 20702,
|
||||
24100, 24099,
|
||||
27008, 27008,
|
||||
29369, 29368,
|
||||
31135, 31135,
|
||||
32270, 32269,
|
||||
32750, 32750,
|
||||
32567, 32567,
|
||||
31725, 31725,
|
||||
30239, 30239,
|
||||
28141, 28140,
|
||||
25472, 25471,
|
||||
22287, 22288,
|
||||
18650, 18651,
|
||||
14636, 14637,
|
||||
10326, 10325,
|
||||
5805, 5805,
|
||||
1166, 1166,
|
||||
-3495, -3495,
|
||||
-8086, -8086,
|
||||
-12513, -12513,
|
||||
-16686, -16685,
|
||||
-20521, -20521,
|
||||
-23940, -23940,
|
||||
-26875, -26875,
|
||||
-29265, -29263,
|
||||
-31062, -31060,
|
||||
-32228, -32228,
|
||||
-32741, -32742,
|
||||
-32592, -32592,
|
||||
-31783, -31781,
|
||||
-30328, -30329,
|
||||
-28260, -28259,
|
||||
-25618, -25617,
|
||||
-22458, -22457,
|
||||
-18842, -18843,
|
||||
-14844, -14845,
|
||||
-10547, -10547,
|
||||
-6034, -6034,
|
||||
-1400, -1400,
|
||||
3263, 3263,
|
||||
7859, 7859,
|
||||
12297, 12296,
|
||||
16484, 16485,
|
||||
20338, 20338,
|
||||
23781, 23780,
|
||||
26741, 26740,
|
||||
29158, 29159,
|
||||
30986, 30986,
|
||||
32184, 32185,
|
||||
32731, 32733,
|
||||
32615, 32616,
|
||||
31839, 31838,
|
||||
30417, 30416,
|
||||
28377, 28377,
|
||||
25763, 25763,
|
||||
22627, 22628,
|
||||
19032, 19033,
|
||||
15052, 15052,
|
||||
10767, 10767,
|
||||
6263, 6264,
|
||||
1633, 1634,
|
||||
-3030, -3030,
|
||||
-7632, -7633,
|
||||
-12079, -12080,
|
||||
-16283, -16283,
|
||||
-20155, -20154,
|
||||
-23620, -23619,
|
||||
-26604, -26605,
|
||||
-29051, -29051,
|
||||
-30908, -30909,
|
||||
-32140, -32141,
|
||||
-32720, -32721,
|
||||
-32638, -32638,
|
||||
-31893, -31892,
|
||||
-30502, -30502,
|
||||
-28494, -28493,
|
||||
-25907, -25906,
|
||||
-22796, -22795,
|
||||
-19222, -19222,
|
||||
-15259, -15259,
|
||||
-10987, -10987,
|
||||
-6493, -6492,
|
||||
-1866, -1866,
|
||||
2797, 2797,
|
||||
7404, 7405,
|
||||
11862, 11862,
|
||||
16079, 16079,
|
||||
19971, 19971,
|
||||
23457, 23457,
|
||||
26468, 26468,
|
||||
28943, 28942,
|
||||
30830, 30831,
|
||||
32094, 32093,
|
||||
32707, 32707,
|
||||
32657, 32656,
|
||||
31946, 31946,
|
||||
30586, 30586,
|
||||
28608, 28608,
|
||||
26049, 26050,
|
||||
22962, 22963,
|
||||
19411, 19411,
|
||||
15466, 15465,
|
||||
11207, 11206,
|
||||
6722, 6722,
|
||||
2099, 2099,
|
||||
-2565, -2565,
|
||||
-7177, -7178,
|
||||
-11644, -11645,
|
||||
-15875, -15875,
|
||||
-19785, -19784,
|
||||
-23294, -23294,
|
||||
-26330, -26330,
|
||||
-28833, -28832,
|
||||
-30751, -30751,
|
||||
-32046, -32046,
|
||||
-32692, -32692,
|
||||
-32676, -32675,
|
||||
-31997, -31997,
|
||||
-30670, -30670,
|
||||
-28721, -28721,
|
||||
-26190, -26190,
|
||||
-23128, -23129,
|
||||
-19598, -19599,
|
||||
-15671, -15672,
|
||||
-11425, -11426,
|
||||
-6950, -6950,
|
||||
-2331, -2332,
|
||||
2332, 2333,
|
||||
6949, 6949,
|
||||
11426, 11426,
|
||||
15671, 15671,
|
||||
19598, 19598,
|
||||
23128, 23128,
|
||||
26190, 26190,
|
||||
28722, 28720,
|
||||
30669, 30669,
|
||||
31997, 31996,
|
||||
32676, 32675,
|
||||
32692, 32692,
|
||||
32046, 32046,
|
||||
30751, 30751,
|
||||
28832, 28833,
|
||||
26330, 26330,
|
||||
23293, 23294,
|
||||
19785, 19785,
|
||||
15876, 15875,
|
||||
11645, 11645,
|
||||
7177, 7177,
|
||||
2566, 2565,
|
||||
-2100, -2100,
|
||||
-6722, -6721,
|
||||
-11207, -11208,
|
||||
-15465, -15465,
|
||||
-19412, -19412,
|
||||
-22963, -22962,
|
||||
-26049, -26049,
|
||||
-28608, -28608,
|
||||
-30586, -30586,
|
||||
-31946, -31946,
|
||||
-32657, -32657,
|
||||
-32707, -32707,
|
||||
-32095, -32093,
|
||||
-30830, -30830,
|
||||
-28943, -28943,
|
||||
-26467, -26468,
|
||||
-23457, -23457,
|
||||
-19970, -19971,
|
||||
-16079, -16079,
|
||||
-11862, -11863,
|
||||
-7406, -7404,
|
||||
-2798, -2798,
|
||||
1866, 1866,
|
||||
6492, 6493,
|
||||
10987, 10987,
|
||||
15260, 15259,
|
||||
19222, 19222,
|
||||
22795, 22795,
|
||||
25906, 25907,
|
||||
28493, 28493,
|
||||
30502, 30502,
|
||||
31893, 31893,
|
||||
32638, 32637,
|
||||
32721, 32721,
|
||||
32141, 32140,
|
||||
30909, 30909,
|
||||
29051, 29052,
|
||||
26605, 26605,
|
||||
23619, 23619,
|
||||
20155, 20155,
|
||||
16282, 16282,
|
||||
12080, 12080,
|
||||
7631, 7632,
|
||||
3031, 3031,
|
||||
-1633, -1633,
|
||||
-6263, -6264,
|
||||
-10767, -10767,
|
||||
-15053, -15052,
|
||||
-19033, -19033,
|
||||
-22627, -22627,
|
||||
-25763, -25763,
|
||||
-28377, -28377,
|
||||
-30416, -30416,
|
||||
-31839, -31838,
|
||||
-32616, -32616,
|
||||
-32732, -32731,
|
||||
-32184, -32185,
|
||||
-30986, -30985,
|
||||
-29159, -29159,
|
||||
-26740, -26740,
|
||||
-23780, -23780,
|
||||
-20339, -20339,
|
||||
-16485, -16484,
|
||||
-12297, -12296,
|
||||
-7859, -7859,
|
||||
-3263, -3262,
|
||||
1399, 1401,
|
||||
6034, 6034,
|
||||
10547, 10546,
|
||||
14845, 14844,
|
||||
18842, 18842,
|
||||
22457, 22458,
|
||||
25619, 25619,
|
||||
28260, 28259,
|
||||
30329, 30328,
|
||||
31783, 31783,
|
||||
32593, 32593,
|
||||
32742, 32742,
|
||||
32228, 32228,
|
||||
31061, 31060,
|
||||
29264, 29264,
|
||||
26875, 26875,
|
||||
23940, 23940,
|
||||
20521, 20521,
|
||||
16686, 16686,
|
||||
12512, 12513,
|
||||
8085, 8085,
|
||||
3495, 3494,
|
||||
-1167, -1167,
|
||||
-5804, -5805,
|
||||
-10325, -10326,
|
||||
-14636, -14636,
|
||||
-18651, -18651,
|
||||
-22287, -22288,
|
||||
-25472, -25472,
|
||||
-28141, -28141,
|
||||
-30239, -30239,
|
||||
-31725, -31725,
|
||||
-32568, -32567,
|
||||
-32750, -32751,
|
||||
-32270, -32269,
|
||||
-31134, -31135,
|
||||
-29368, -29369,
|
||||
-27007, -27008,
|
||||
-24099, -24099,
|
||||
-20703, -20703,
|
||||
-16886, -16886,
|
||||
-12728, -12728,
|
||||
-8311, -8311,
|
||||
-3726, -3728,
|
||||
934, 933,
|
||||
5575, 5575,
|
||||
10104, 10104,
|
||||
14426, 14427,
|
||||
18458, 18458,
|
||||
22115, 22115,
|
||||
25324, 25324,
|
||||
28021, 28021,
|
||||
30149, 30148,
|
||||
31666, 31665,
|
||||
32541, 32541,
|
||||
32757, 32757,
|
||||
32310, 32309,
|
||||
31206, 31206,
|
||||
29471, 29472,
|
||||
27139, 27139,
|
||||
24257, 24257,
|
||||
20883, 20883,
|
||||
17085, 17086,
|
||||
12943, 12944,
|
||||
8537, 8537,
|
||||
3958, 3959,
|
||||
-700, -700,
|
||||
-5345, -5345,
|
||||
-9882, -9881,
|
||||
-14217, -14217,
|
||||
-18265, -18265,
|
||||
-21942, -21943,
|
||||
-25176, -25175,
|
||||
-27899, -27899,
|
||||
-30056, -30056,
|
||||
-31605, -31605,
|
||||
-32513, -32513,
|
||||
-32762, -32761,
|
||||
-32347, -32347,
|
||||
-31277, -31277,
|
||||
-29573, -29573,
|
||||
-27269, -27269,
|
||||
-24413, -24414,
|
||||
-21062, -21062,
|
||||
-17284, -17284,
|
||||
-13156, -13157,
|
||||
-8762, -8762,
|
||||
-4190, -4190,
|
||||
467, 466,
|
||||
5115, 5115,
|
||||
9659, 9658,
|
||||
14006, 14007,
|
||||
18070, 18070,
|
||||
21769, 21769,
|
||||
25026, 25025,
|
||||
27776, 27776,
|
||||
29962, 29963,
|
||||
31541, 31542,
|
||||
32482, 32483,
|
||||
32765, 32765,
|
||||
32383, 32383,
|
||||
31346, 31346,
|
||||
29672, 29672,
|
||||
27397, 27398,
|
||||
24568, 24568,
|
||||
21240, 21241,
|
||||
17482, 17482,
|
||||
13371, 13370,
|
||||
8987, 8987,
|
||||
4421, 4422,
|
||||
-233, -234,
|
||||
-4883, -4883,
|
||||
-9435, -9435,
|
||||
-13795, -13795,
|
||||
-17876, -17875,
|
||||
-21594, -21594,
|
||||
-24874, -24875,
|
||||
-27651, -27651,
|
||||
-29868, -29867,
|
||||
-31478, -31478,
|
||||
-32451, -32451,
|
||||
-32767, -32767,
|
||||
-32419, -32418,
|
||||
-31413, -31413,
|
||||
-29770, -29770,
|
||||
-27525, -27525,
|
||||
-24722, -24722,
|
||||
-21418, -21417,
|
||||
-17680, -17680,
|
||||
-13583, -13582,
|
||||
-9211, -9212,
|
||||
-4653, -4653,
|
||||
-1, 1,
|
||||
4652, 4652,
|
||||
9211, 9211,
|
||||
13584, 13582,
|
||||
17679, 17679,
|
||||
21418, 21418,
|
||||
24722, 24722,
|
||||
27525, 27525,
|
||||
29771, 29771,
|
||||
31412, 31413,
|
||||
32418, 32419,
|
||||
32767, 32767,
|
||||
32452, 32451,
|
||||
31478, 31478,
|
||||
29868, 29867,
|
||||
27650, 27651,
|
||||
24874, 24874,
|
||||
21593, 21593,
|
||||
17876, 17875,
|
||||
13795, 13795,
|
||||
9435, 9436,
|
||||
4883, 4884,
|
||||
234, 233,
|
||||
-4421, -4422,
|
||||
-8987, -8987,
|
||||
-13370, -13370,
|
||||
-17483, -17483,
|
||||
-21240, -21240,
|
||||
-24568, -24569,
|
||||
-27398, -27398,
|
||||
-29672, -29672,
|
||||
-31346, -31346,
|
||||
-32383, -32384,
|
||||
-32765, -32765,
|
||||
-32483, -32484,
|
||||
-31542, -31542,
|
||||
-29963, -29963,
|
||||
-27775, -27775,
|
||||
-25026, -25026,
|
||||
-21769, -21769,
|
||||
-18070, -18071,
|
||||
-14006, -14007,
|
||||
-9658, -9658,
|
||||
-5115, -5115,
|
||||
-467, -467,
|
||||
4190, 4190,
|
||||
8762, 8763,
|
||||
13157, 13157,
|
||||
17285, 17284,
|
||||
21062, 21062,
|
||||
24413, 24413,
|
||||
27269, 27269,
|
||||
29573, 29572,
|
||||
31276, 31277,
|
||||
32347, 32346,
|
||||
32762, 32762,
|
||||
32513, 32512,
|
||||
31605, 31604,
|
||||
30056, 30057,
|
||||
27899, 27899,
|
||||
25176, 25176,
|
||||
21943, 21943,
|
||||
18265, 18265,
|
||||
14217, 14217,
|
||||
9881, 9881,
|
||||
5344, 5345,
|
||||
700, 700,
|
||||
-3958, -3958,
|
||||
-8537, -8537,
|
||||
-12942, -12943,
|
||||
-17085, -17086,
|
||||
-20883, -20883,
|
||||
-24257, -24257,
|
||||
-27138, -27138,
|
||||
-29471, -29471,
|
||||
-31206, -31207,
|
||||
-32309, -32308,
|
||||
-32757, -32757,
|
||||
-32541, -32540,
|
||||
-31666, -31666,
|
||||
-30148, -30148,
|
||||
-28021, -28020,
|
||||
-25325, -25325,
|
||||
-22115, -22116,
|
||||
-18458, -18458,
|
||||
-14427, -14427,
|
||||
-10103, -10103,
|
||||
-5575, -5575,
|
||||
-934, -933,
|
||||
3727, 3726,
|
||||
8312, 8311,
|
||||
12729, 12728,
|
||||
16886, 16886,
|
||||
20703, 20702,
|
||||
24099, 24100,
|
||||
27007, 27008,
|
||||
29369, 29369,
|
||||
31135, 31134,
|
||||
32270, 32270,
|
||||
32750, 32750,
|
||||
32568, 32567,
|
||||
31724, 31724,
|
||||
30239, 30240,
|
||||
28140, 28142,
|
||||
25472, 25473,
|
||||
22287, 22288,
|
||||
18651, 18651,
|
||||
14636, 14635,
|
||||
10325, 10325,
|
||||
5805, 5805,
|
||||
1167, 1167,
|
||||
-3495, -3495,
|
||||
-8085, -8085,
|
||||
-12512, -12513,
|
||||
-16685, -16685,
|
||||
-20521, -20521,
|
||||
-23941, -23940,
|
||||
-26875, -26875,
|
||||
-29264, -29265,
|
||||
-31060, -31061,
|
||||
-32228, -32228,
|
||||
-32742, -32742,
|
||||
-32593, -32593,
|
||||
-31782, -31782,
|
||||
-30328, -30328,
|
||||
-28260, -28260,
|
||||
-25618, -25619,
|
||||
-22458, -22458,
|
||||
-18842, -18842,
|
||||
-14845, -14844,
|
||||
-10546, -10546,
|
||||
-6035, -6035,
|
||||
-1400, -1400,
|
||||
3262, 3263,
|
||||
7859, 7859,
|
||||
12296, 12297,
|
||||
16485, 16485,
|
||||
20339, 20339,
|
||||
23780, 23780,
|
||||
26741, 26741,
|
||||
29159, 29158,
|
||||
30985, 30985,
|
||||
32185, 32185,
|
||||
32732, 32733,
|
||||
32615, 32616,
|
||||
31839, 31839,
|
||||
30416, 30416,
|
||||
28377, 28377,
|
||||
25763, 25762,
|
||||
22627, 22628,
|
||||
19032, 19032,
|
||||
15053, 15052,
|
||||
10767, 10767,
|
||||
6264, 6263,
|
||||
1633, 1634,
|
||||
-3030, -3030,
|
||||
-7632, -7632,
|
||||
-12081, -12079,
|
||||
-16282, -16283,
|
||||
-20154, -20155,
|
||||
-23618, -23619,
|
||||
-26604, -26605,
|
||||
-29051, -29051,
|
||||
-30910, -30909,
|
||||
-32140, -32141,
|
||||
-32721, -32720,
|
||||
-32637, -32637,
|
||||
-31892, -31893,
|
||||
-30502, -30502,
|
||||
-28493, -28493,
|
||||
-25907, -25907,
|
||||
-22795, -22796,
|
||||
-19222, -19222,
|
||||
-15260, -15259,
|
||||
-10987, -10987,
|
||||
-6493, -6492,
|
||||
-1867, -1867,
|
||||
2798, 2798,
|
||||
7405, 7405,
|
||||
11862, 11862,
|
||||
16079, 16079,
|
||||
19971, 19970,
|
||||
23457, 23456,
|
||||
26468, 26468,
|
||||
28942, 28942,
|
||||
30831, 30830,
|
||||
32095, 32095,
|
||||
32707, 32706,
|
||||
32657, 32657,
|
||||
31946, 31945,
|
||||
30587, 30586,
|
||||
28607, 28607,
|
||||
26049, 26049,
|
||||
22963, 22963,
|
||||
19411, 19411,
|
||||
15466, 15465,
|
||||
11206, 11208,
|
||||
6721, 6721,
|
||||
2100, 2099,
|
||||
-2565, -2565,
|
||||
-7177, -7177,
|
||||
-11644, -11644,
|
||||
-15875, -15876,
|
||||
-19785, -19785,
|
||||
-23293, -23294,
|
||||
-26330, -26330,
|
||||
-28833, -28832,
|
||||
-30751, -30751,
|
||||
-32046, -32047,
|
||||
-32692, -32692,
|
||||
-32675, -32675,
|
||||
-31997, -31997,
|
||||
-30669, -30669,
|
||||
-28720, -28720,
|
||||
-26190, -26190,
|
||||
-23129, -23128,
|
||||
-19598, -19598,
|
||||
-15671, -15671,
|
||||
-11425, -11426,
|
||||
-6949, -6949,
|
||||
-2332, -2332,
|
||||
2333, 2333,
|
||||
6950, 6950,
|
||||
11426, 11427,
|
||||
15670, 15671,
|
||||
19599, 19598,
|
||||
23128, 23128,
|
||||
26190, 26189,
|
||||
28720, 28720,
|
||||
30670, 30669,
|
||||
31996, 31996,
|
||||
32675, 32676,
|
||||
32692, 32692,
|
||||
32046, 32046,
|
||||
30751, 30751,
|
||||
28832, 28831,
|
||||
26330, 26329,
|
||||
23293, 23293,
|
||||
19784, 19785,
|
||||
15875, 15875,
|
||||
11645, 11645,
|
||||
7177, 7178,
|
||||
2564, 2565,
|
||||
-2100, -2099,
|
||||
-6722, -6722,
|
||||
-11207, -11206,
|
||||
-15466, -15466,
|
||||
-19410, -19411,
|
||||
-22962, -22962,
|
||||
-26049, -26049,
|
||||
-28608, -28607,
|
||||
-30586, -30586,
|
||||
-31945, -31946,
|
||||
-32658, -32657,
|
||||
-32707, -32707,
|
||||
-32095, -32094,
|
||||
-30832, -30830,
|
||||
-28943, -28943,
|
||||
-26468, -26467,
|
||||
-23457, -23456,
|
||||
-19971, -19970,
|
||||
-16080, -16080,
|
||||
-11862, -11863,
|
||||
-7406, -7405,
|
||||
-2797, -2797,
|
||||
1867, 1866,
|
||||
6492, 6492,
|
||||
10987, 10987,
|
||||
15260, 15259,
|
||||
19222, 19222,
|
||||
22796, 22796,
|
||||
25907, 25906,
|
||||
28494, 28493,
|
||||
30502, 30502,
|
||||
31893, 31893,
|
||||
32637, 32637,
|
||||
32720, 32721,
|
||||
32140, 32140,
|
||||
30909, 30909,
|
||||
29052, 29052,
|
||||
26605, 26605,
|
||||
23619, 23619,
|
||||
20155, 20155,
|
||||
16281, 16282,
|
||||
12080, 12079,
|
||||
7632, 7632,
|
||||
3031, 3030,
|
||||
-1634, -1633,
|
||||
-6263, -6264,
|
||||
-10767, -10767,
|
||||
-15052, -15053,
|
||||
-19033, -19032,
|
||||
-22627, -22628,
|
||||
-25763, -25763,
|
||||
-28377, -28377,
|
||||
-30416, -30416,
|
||||
-31838, -31838,
|
||||
-32616, -32616,
|
||||
-32732, -32732,
|
||||
-32185, -32185,
|
||||
-30986, -30986,
|
||||
-29158, -29158,
|
||||
-26741, -26741,
|
||||
-23780, -23780,
|
||||
-20339, -20338,
|
||||
-16485, -16484,
|
||||
-12296, -12296,
|
||||
-7859, -7859,
|
||||
-3262, -3263,
|
||||
1400, 1400,
|
||||
6035, 6034,
|
||||
10546, 10546,
|
||||
14845, 14845,
|
||||
18842, 18842,
|
||||
22457, 22458,
|
||||
25619, 25619,
|
||||
28260, 28260,
|
||||
30327, 30328,
|
||||
31782, 31782,
|
||||
32592, 32592,
|
||||
32742, 32742,
|
||||
32229, 32227,
|
||||
31061, 31061,
|
||||
29264, 29264,
|
||||
26875, 26874,
|
||||
23940, 23941,
|
||||
20521, 20521,
|
||||
16685, 16686,
|
||||
12513, 12513,
|
||||
8086, 8085,
|
||||
3495, 3495,
|
||||
-1167, -1167,
|
||||
-5804, -5805,
|
||||
-10325, -10324,
|
||||
-14636, -14636,
|
||||
-18651, -18651,
|
||||
-22287, -22287,
|
||||
-25471, -25473,
|
||||
-28141, -28140,
|
||||
-30239, -30240,
|
||||
-31724, -31725,
|
||||
-32567, -32567,
|
||||
-32750, -32751,
|
||||
-32270, -32269,
|
||||
-31135, -31135,
|
||||
-29369, -29369,
|
||||
-27007, -27007,
|
||||
-24099, -24099,
|
||||
-20703, -20703,
|
||||
-16886, -16886,
|
||||
-12728, -12728,
|
||||
-8311, -8312,
|
||||
-3727, -3727,
|
||||
934, 934,
|
||||
5576, 5575,
|
||||
10104, 10104,
|
||||
14427, 14427,
|
||||
18459, 18458,
|
||||
22115, 22115,
|
||||
25325, 25324,
|
||||
28020, 28020,
|
||||
30148, 30148,
|
||||
31665, 31666,
|
||||
32541, 32541,
|
||||
32757, 32757,
|
||||
32309, 32310,
|
||||
31206, 31206,
|
||||
29472, 29472,
|
||||
27139, 27138,
|
||||
24257, 24257,
|
||||
20883, 20883,
|
||||
17086, 17086,
|
||||
12942, 12942,
|
||||
8537, 8537,
|
||||
3958, 3958,
|
||||
-700, -701,
|
||||
-5344, -5345,
|
||||
-9881, -9881,
|
||||
-14218, -14217,
|
||||
-18264, -18265,
|
||||
-21942, -21943,
|
||||
-25175, -25176,
|
||||
-27899, -27898,
|
||||
-30057, -30057,
|
||||
-31605, -31605,
|
||||
-32512, -32513,
|
||||
-32761, -32761,
|
||||
-32347, -32347,
|
||||
-31277, -31277,
|
||||
-29573, -29572,
|
||||
-27269, -27269,
|
||||
-24414, -24414,
|
||||
-21062, -21062,
|
||||
-17284, -17285,
|
||||
-13156, -13157,
|
||||
-8763, -8762,
|
||||
-4190, -4190,
|
||||
467, 467,
|
||||
5114, 5114,
|
||||
9658, 9659,
|
||||
14006, 14006,
|
||||
18071, 18071,
|
||||
21769, 21769,
|
||||
25026, 25026,
|
||||
27775, 27776,
|
||||
29963, 29962,
|
||||
31543, 31542,
|
||||
32483, 32483,
|
||||
32765, 32765,
|
||||
32384, 32384,
|
||||
31345, 31345,
|
||||
29671, 29672,
|
||||
27398, 27398,
|
||||
24568, 24568,
|
||||
21241, 21241,
|
||||
17483, 17483,
|
||||
13369, 13370,
|
||||
8986, 8987,
|
||||
4422, 4421,
|
||||
-233, -234,
|
||||
-4885, -4884,
|
||||
-9435, -9435,
|
||||
-13795, -13794,
|
||||
-17876, -17875,
|
||||
-21594, -21594,
|
||||
-24875, -24874,
|
||||
-27651, -27651,
|
||||
-29867, -29868,
|
||||
-31478, -31478,
|
||||
-32452, -32451,
|
||||
-32768, -32767,
|
||||
-32419, -32418,
|
||||
-31412, -31413,
|
||||
-29771, -29771,
|
||||
-27525, -27526,
|
||||
-24722, -24721,
|
||||
-21417, -21418,
|
||||
-17680, -17679,
|
||||
-13583, -13583,
|
||||
-9211, -9210,
|
||||
-4653, -4653
|
|
@ -0,0 +1,96 @@
|
|||
0,
|
||||
0,
|
||||
4234,
|
||||
4234,
|
||||
8396,
|
||||
8396,
|
||||
12414,
|
||||
12414,
|
||||
16220,
|
||||
16220,
|
||||
19748,
|
||||
19748,
|
||||
22938,
|
||||
22938,
|
||||
25736,
|
||||
25736,
|
||||
28094,
|
||||
28094,
|
||||
29970,
|
||||
29970,
|
||||
31334,
|
||||
31334,
|
||||
32162,
|
||||
32162,
|
||||
32440,
|
||||
32440,
|
||||
32162,
|
||||
32162,
|
||||
31334,
|
||||
31334,
|
||||
29970,
|
||||
29970,
|
||||
28094,
|
||||
28094,
|
||||
25736,
|
||||
25736,
|
||||
22938,
|
||||
22938,
|
||||
19748,
|
||||
19748,
|
||||
16220,
|
||||
16220,
|
||||
12414,
|
||||
12414,
|
||||
8396,
|
||||
8396,
|
||||
4234,
|
||||
4234,
|
||||
0,
|
||||
0,
|
||||
-4234,
|
||||
-4234,
|
||||
-8396,
|
||||
-8396,
|
||||
-12414,
|
||||
-12414,
|
||||
-16220,
|
||||
-16220,
|
||||
-19748,
|
||||
-19748,
|
||||
-22938,
|
||||
-22938,
|
||||
-25736,
|
||||
-25736,
|
||||
-28094,
|
||||
-28094,
|
||||
-29970,
|
||||
-29970,
|
||||
-31334,
|
||||
-31334,
|
||||
-32162,
|
||||
-32162,
|
||||
-32440,
|
||||
-32440,
|
||||
-32162,
|
||||
-32162,
|
||||
-31334,
|
||||
-31334,
|
||||
-29970,
|
||||
-29970,
|
||||
-28094,
|
||||
-28094,
|
||||
-25736,
|
||||
-25736,
|
||||
-22938,
|
||||
-22938,
|
||||
-19748,
|
||||
-19748,
|
||||
-16220,
|
||||
-16220,
|
||||
-12414,
|
||||
-12414,
|
||||
-8396,
|
||||
-8396,
|
||||
-4234,
|
||||
-4234
|
|
@ -0,0 +1,43 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
ccflags-y += \
|
||||
-Iutils/boot_struct \
|
||||
-Iutils/intersyshci \
|
||||
-Iutils/hwtimer_list \
|
||||
-Iservices/bt_app \
|
||||
-Iservices/nvrecord \
|
||||
$(BT_IF_INCLUDES) \
|
||||
-Iservices/resources \
|
||||
-Iservices/overlay \
|
||||
-Iservices/multimedia/algorithm/fft/include \
|
||||
-Iapps/key \
|
||||
-Iplatform/drivers/bt \
|
||||
-Iplatform/drivers/ana \
|
||||
-Iplatform/drivers/usb/usb_dev/inc \
|
||||
-Iapps/battery \
|
||||
-Iservices/multimedia/audio/codec/sbc/inc \
|
||||
-Iservices/multimedia/audio/codec/sbc/src/inc \
|
||||
-Iutils/cqueue \
|
||||
-Iservices/nv_section/factory_section \
|
||||
-Iservices/app_ai/inc \
|
||||
|
||||
ifeq ($(AUDIO_RESAMPLE),1)
|
||||
CFLAGS_app_factory_audio.o += -D__AUDIO_RESAMPLE__
|
||||
endif
|
||||
ifeq ($(SW_CAPTURE_RESAMPLE),1)
|
||||
CFLAGS_app_factory_audio.o += -DSW_CAPTURE_RESAMPLE
|
||||
endif
|
||||
|
||||
ifeq ($(POWERKEY_I2C_SWITCH),1)
|
||||
CFLAGS_app_factory.o += -DPOWERKEY_I2C_SWITCH
|
||||
endif
|
||||
|
||||
ifeq ($(SPEECH_TX_AEC_CODEC_REF),1)
|
||||
CFLAGS_app_factory_audio.o += -DSPEECH_TX_AEC_CODEC_REF
|
||||
endif
|
||||
|
|
@ -0,0 +1,689 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "list.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_bootmode.h"
|
||||
#include "hal_cmu.h"
|
||||
#include "hal_sleep.h"
|
||||
#include "app_key.h"
|
||||
#include "app_factory.h"
|
||||
#include "bt_drv_interface.h"
|
||||
#include "bt_drv_reg_op.h"
|
||||
#include "bluetooth.h"
|
||||
#include "nvrecord.h"
|
||||
#include "nvrecord_dev.h"
|
||||
#include "nvrecord_env.h"
|
||||
#include "resources.h"
|
||||
#include "app_bt_stream.h"
|
||||
#include "app_media_player.h"
|
||||
#include "pmu.h"
|
||||
|
||||
// for init
|
||||
#include "apps.h"
|
||||
#include "app_status_ind.h"
|
||||
#include "app_thread.h"
|
||||
#include "app_key.h"
|
||||
#include "app_pwl.h"
|
||||
#include "app_overlay.h"
|
||||
#include "app_battery.h"
|
||||
#include "app_utils.h"
|
||||
|
||||
// for bt
|
||||
#include "besbt.h"
|
||||
#include "app_bt.h"
|
||||
#include "app_factory_bt.h"
|
||||
|
||||
// for audio
|
||||
#include "audioflinger.h"
|
||||
#include "app_audio.h"
|
||||
#include "app_utils.h"
|
||||
|
||||
|
||||
|
||||
// for progress
|
||||
#include "hal_uart.h"
|
||||
#include "tool_msg.h"
|
||||
|
||||
#include "factory_section.h"
|
||||
|
||||
#ifdef __FACTORY_MODE_SUPPORT__
|
||||
|
||||
#define APP_FACTORYMODE_RETRY_LIMITED (2)
|
||||
|
||||
typedef enum APP_FACTORYMODE_STATUS_INDICATION_T {
|
||||
APP_FACTORYMODE_STATUS_INDICATION_RUNNING = 0,
|
||||
APP_FACTORYMODE_STATUS_INDICATION_PASS,
|
||||
APP_FACTORYMODE_STATUS_INDICATION_FAILED,
|
||||
APP_FACTORYMODE_STATUS_INDICATION_INVALID,
|
||||
|
||||
APP_FACTORYMODE_STATUS_INDICATION_NUM
|
||||
}APP_FACTORYMODE_STATUS_INDICATION_T;
|
||||
|
||||
static void app_factorymode_timehandler(void const *param);
|
||||
void app_bt_key_shutdown(APP_KEY_STATUS *status, void *param);
|
||||
void app_factorymode_result_set(bool result);
|
||||
|
||||
static osThreadId app_factorymode_tid= NULL;
|
||||
static struct message_t send_msg = { { PREFIX_CHAR, }, };
|
||||
static unsigned char send_seq = 0;
|
||||
|
||||
osTimerId app_factory_timer = NULL;
|
||||
osTimerDef (APP_FACTORY_TIMER, app_factorymode_timehandler);
|
||||
|
||||
int app_factorymode_languageswitch_proc(void)
|
||||
{
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
int lan;
|
||||
int new_lan;
|
||||
struct nvrecord_env_t *nvrecord_env;
|
||||
|
||||
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
lan = app_play_audio_get_lang();
|
||||
new_lan = lan;
|
||||
app_play_audio_set_lang(new_lan);
|
||||
|
||||
nv_record_env_get(&nvrecord_env);
|
||||
nvrecord_env->media_language.language = new_lan;
|
||||
nv_record_env_set(nvrecord_env);
|
||||
|
||||
APP_FACTORY_TRACE(2,"languages old:%d new:%d",lan ,new_lan);
|
||||
media_PlayAudio(AUD_ID_LANGUAGE_SWITCH, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_factorymode_languageswitch(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
app_factorymode_languageswitch_proc();
|
||||
}
|
||||
|
||||
void app_factorymode_enter(void)
|
||||
{
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
hal_sw_bootmode_set(HAL_SW_BOOTMODE_TEST_MODE|HAL_SW_BOOTMODE_TEST_SIGNALINGMODE);
|
||||
hal_cmu_sys_reboot();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
static bool isInFactoryMode = false;
|
||||
|
||||
bool app_factorymode_get(void)
|
||||
{
|
||||
return isInFactoryMode;
|
||||
}
|
||||
|
||||
void app_factorymode_set(bool set)
|
||||
{
|
||||
isInFactoryMode = set;
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef POWERKEY_I2C_SWITCH
|
||||
void app_factorymode_i2c_switch(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
static int i = 0;
|
||||
|
||||
i++;
|
||||
if (i & 1) {
|
||||
TRACE(0,"set analog i2c mode !!!");
|
||||
osDelay(100);
|
||||
hal_iomux_set_analog_i2c();
|
||||
} else {
|
||||
hal_iomux_set_uart0();
|
||||
osDelay(100);
|
||||
TRACE(0,"hal_iomux_set_uart0 !!!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __IBRT_IBRT_TESTMODE__
|
||||
void bt_drv_ibrt_test_key_click(APP_KEY_STATUS *status, void *param);
|
||||
void bt_drv_ibrt_test_key_click(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
btdrv_connect_ibrt_device(bt_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void app_factorymode_key_init(void)
|
||||
{
|
||||
const APP_KEY_HANDLE app_factorymode_handle_cfg[] = {
|
||||
#ifdef POWERKEY_I2C_SWITCH
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_RAMPAGECLICK},"bt i2c key",app_factorymode_i2c_switch, NULL},
|
||||
#endif
|
||||
#ifdef __POWERKEY_CTRL_ONOFF_ONLY__
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_UP},"bt function key",app_bt_key_shutdown, NULL},
|
||||
#else
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_LONGLONGPRESS},"bt function key",app_bt_key_shutdown, NULL},
|
||||
#endif
|
||||
#ifdef __IBRT_IBRT_TESTMODE__
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_CLICK},"bt function key",bt_drv_ibrt_test_key_click, NULL},
|
||||
#else
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_CLICK},"bt function key",app_factorymode_languageswitch, NULL},
|
||||
#endif
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_DOUBLECLICK},"bt function key",app_factorymode_bt_xtalcalib, NULL},
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_LONGPRESS},"bt function key",app_factorymode_bt_signalingtest, NULL},
|
||||
};
|
||||
|
||||
uint8_t i = 0;
|
||||
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
|
||||
app_key_handle_clear();
|
||||
for (i=0; i<(sizeof(app_factorymode_handle_cfg)/sizeof(APP_KEY_HANDLE)); i++){
|
||||
app_key_handle_registration(&app_factorymode_handle_cfg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void app_factorymode_audioloopswitch(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
static bool onaudioloop = false;
|
||||
|
||||
onaudioloop = onaudioloop?false:true;
|
||||
|
||||
if (onaudioloop)
|
||||
app_audio_sendrequest(APP_FACTORYMODE_AUDIO_LOOP, (uint8_t)APP_BT_SETTING_OPEN, 0);
|
||||
else
|
||||
app_audio_sendrequest(APP_FACTORYMODE_AUDIO_LOOP, (uint8_t)APP_BT_SETTING_CLOSE, 0);
|
||||
}
|
||||
|
||||
void app_factorymode_test_key_init(void)
|
||||
{
|
||||
const APP_KEY_HANDLE app_factorymode_handle_cfg[] = {
|
||||
{{APP_KEY_CODE_PWR,APP_KEY_EVENT_CLICK},"bt function key",app_factorymode_audioloopswitch, NULL},
|
||||
};
|
||||
|
||||
uint8_t i = 0;
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
for (i=0; i<(sizeof(app_factorymode_handle_cfg)/sizeof(APP_KEY_HANDLE)); i++){
|
||||
app_key_handle_registration(&app_factorymode_handle_cfg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void app_factorymode_result_clean(void)
|
||||
{
|
||||
osSignalClear(app_factorymode_tid, 0x01);
|
||||
osSignalClear(app_factorymode_tid, 0x02);
|
||||
}
|
||||
|
||||
void app_factorymode_result_set(bool result)
|
||||
{
|
||||
if (result)
|
||||
osSignalSet(app_factorymode_tid ,0x01);
|
||||
else
|
||||
osSignalSet(app_factorymode_tid ,0x02);
|
||||
}
|
||||
|
||||
bool app_factorymode_result_wait(void)
|
||||
{
|
||||
bool nRet;
|
||||
osEvent evt;
|
||||
|
||||
while(1)
|
||||
{
|
||||
//wait any signal
|
||||
evt = osSignalWait(0x0, osWaitForever);
|
||||
|
||||
//get role from signal value
|
||||
if(evt.status == osEventSignal)
|
||||
{
|
||||
if(evt.value.signals & 0x01)
|
||||
{
|
||||
nRet = true;
|
||||
break;
|
||||
}
|
||||
else if(evt.value.signals & 0x02)
|
||||
{
|
||||
nRet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nRet;
|
||||
}
|
||||
|
||||
static int app_factorymode_send_progress (uint8_t progress)
|
||||
{
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
|
||||
msg.mod_id = APP_MODUAL_OHTER;
|
||||
msg.msg_body.message_id = 2;
|
||||
msg.msg_body.message_Param0 = progress;
|
||||
app_mailbox_put(&msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int app_factorymode_send_code (uint32_t progress)
|
||||
{
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
|
||||
msg.mod_id = APP_MODUAL_OHTER;
|
||||
msg.msg_body.message_id = 3;
|
||||
msg.msg_body.message_Param0 = progress;
|
||||
app_mailbox_put(&msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_factorymode_proc(void)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
bool nRet;
|
||||
app_factorymode_tid = osThreadGetId();
|
||||
|
||||
app_factorymode_send_progress(60);
|
||||
app_factorymode_bt_init_connect();
|
||||
|
||||
do{
|
||||
app_factorymode_result_clean();
|
||||
app_factorymode_bt_create_connect();
|
||||
nRet = app_factorymode_result_wait();
|
||||
}while(!nRet && ++cnt < APP_FACTORYMODE_RETRY_LIMITED);
|
||||
|
||||
if (!nRet)
|
||||
goto exit;
|
||||
app_factorymode_send_progress(90);
|
||||
app_factorymode_result_clean();
|
||||
if (!nRet)
|
||||
goto exit;
|
||||
app_factorymode_send_progress(100);
|
||||
osDelay(100);
|
||||
exit:
|
||||
app_factorymode_result_clean();
|
||||
if (nRet){
|
||||
return 0;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char app_factorymode_msg_check_sum(unsigned char *buf, unsigned char len)
|
||||
{
|
||||
int i;
|
||||
unsigned char sum = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int app_factorymode_msg_uart_send(const unsigned char *buf, size_t len)
|
||||
{
|
||||
uint32_t sent = 0;
|
||||
|
||||
while (sent < len) {
|
||||
hal_uart_blocked_putc(HAL_UART_ID_0, buf[sent++]);
|
||||
}
|
||||
|
||||
if (sent != len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int app_factorymode_msg_send_ping(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
send_msg.hdr.type = 0x88;
|
||||
send_msg.hdr.seq = send_seq++;
|
||||
send_msg.hdr.len = 2;
|
||||
send_msg.data[0] = 0xaa;
|
||||
send_msg.data[1] = 0x55;
|
||||
send_msg.data[2] = ~app_factorymode_msg_check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
|
||||
|
||||
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int app_factorymode_msg_send_progress (uint8_t progress)
|
||||
{
|
||||
int ret;
|
||||
|
||||
send_msg.hdr.type = 0x88;
|
||||
send_msg.hdr.seq = send_seq++;
|
||||
send_msg.hdr.len = 2;
|
||||
send_msg.data[0] = progress;
|
||||
send_msg.data[1] = 100;
|
||||
send_msg.data[2] = ~app_factorymode_msg_check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
|
||||
|
||||
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int app_factorymode_msg_send_32bitcode(uint32_t code)
|
||||
{
|
||||
int ret;
|
||||
|
||||
send_msg.hdr.type = 0x88;
|
||||
send_msg.hdr.seq = send_seq++;
|
||||
send_msg.hdr.len = 4;
|
||||
send_msg.data[0] = 0xf2;
|
||||
*(uint32_t *)&(send_msg.data[1]) = code;
|
||||
send_msg.data[4] = ~app_factorymode_msg_check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
|
||||
|
||||
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int app_factorymode_process(APP_MESSAGE_BODY *msg_body)
|
||||
{
|
||||
if (msg_body->message_id == 1){
|
||||
app_factorymode_msg_send_ping();
|
||||
}
|
||||
if (msg_body->message_id == 2){
|
||||
app_factorymode_msg_send_progress(msg_body->message_Param0);
|
||||
}
|
||||
if (msg_body->message_id == 3){
|
||||
app_factorymode_msg_send_32bitcode(msg_body->message_Param0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int app_factorymode_uart_init(void)
|
||||
{
|
||||
struct HAL_UART_CFG_T uart_cfg;
|
||||
|
||||
memset(&uart_cfg, 0, sizeof(struct HAL_UART_CFG_T));
|
||||
uart_cfg.parity = HAL_UART_PARITY_NONE,
|
||||
uart_cfg.stop = HAL_UART_STOP_BITS_1,
|
||||
uart_cfg.data = HAL_UART_DATA_BITS_8,
|
||||
uart_cfg.flow = HAL_UART_FLOW_CONTROL_NONE,//HAL_UART_FLOW_CONTROL_RTSCTS,
|
||||
uart_cfg.tx_level = HAL_UART_FIFO_LEVEL_1_2,
|
||||
uart_cfg.rx_level = HAL_UART_FIFO_LEVEL_1_4,
|
||||
uart_cfg.baud = 921600,
|
||||
uart_cfg.dma_rx = false,
|
||||
uart_cfg.dma_tx = false,
|
||||
uart_cfg.dma_rx_stop_on_err = false;
|
||||
hal_uart_close(HAL_UART_ID_0);
|
||||
hal_uart_open(HAL_UART_ID_0, &uart_cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void app_factorymode_timehandler(void const *param)
|
||||
{
|
||||
APP_MESSAGE_BLOCK msg;
|
||||
|
||||
msg.mod_id = APP_MODUAL_OHTER;
|
||||
msg.msg_body.message_id = 1;
|
||||
app_mailbox_put(&msg);
|
||||
}
|
||||
|
||||
static uint8_t app_factorymode_indication_init(void)
|
||||
{
|
||||
struct APP_PWL_CFG_T cfg;
|
||||
|
||||
memset(&cfg, 0, sizeof(struct APP_PWL_CFG_T));
|
||||
app_pwl_open();
|
||||
app_pwl_setup(APP_PWL_ID_0, &cfg);
|
||||
app_pwl_setup(APP_PWL_ID_1, &cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_T status)
|
||||
{
|
||||
struct APP_PWL_CFG_T cfg0;
|
||||
struct APP_PWL_CFG_T cfg1;
|
||||
APP_FACTORY_TRACE(2,"%s %d",__func__, status);
|
||||
memset(&cfg0, 0, sizeof(struct APP_PWL_CFG_T));
|
||||
memset(&cfg1, 0, sizeof(struct APP_PWL_CFG_T));
|
||||
app_pwl_stop(APP_PWL_ID_0);
|
||||
app_pwl_stop(APP_PWL_ID_1);
|
||||
switch (status) {
|
||||
case APP_FACTORYMODE_STATUS_INDICATION_RUNNING:
|
||||
cfg0.part[0].level = 0;
|
||||
cfg0.part[0].time = (300);
|
||||
cfg0.part[1].level = 1;
|
||||
cfg0.part[1].time = (300);
|
||||
cfg0.parttotal = 2;
|
||||
cfg0.startlevel = 0;
|
||||
cfg0.periodic = true;
|
||||
|
||||
cfg1.part[0].level = 1;
|
||||
cfg1.part[0].time = (300);
|
||||
cfg1.part[1].level = 0;
|
||||
cfg1.part[1].time = (300);
|
||||
cfg1.parttotal = 2;
|
||||
cfg1.startlevel = 1;
|
||||
cfg1.periodic = true;
|
||||
|
||||
app_pwl_setup(APP_PWL_ID_0, &cfg0);
|
||||
app_pwl_start(APP_PWL_ID_0);
|
||||
app_pwl_setup(APP_PWL_ID_1, &cfg1);
|
||||
app_pwl_start(APP_PWL_ID_1);
|
||||
break;
|
||||
case APP_FACTORYMODE_STATUS_INDICATION_PASS:
|
||||
cfg0.part[0].level = 1;
|
||||
cfg0.part[0].time = (5000);
|
||||
cfg0.parttotal = 1;
|
||||
cfg0.startlevel = 1;
|
||||
cfg0.periodic = false;
|
||||
|
||||
app_pwl_setup(APP_PWL_ID_0, &cfg0);
|
||||
app_pwl_start(APP_PWL_ID_0);
|
||||
break;
|
||||
case APP_FACTORYMODE_STATUS_INDICATION_FAILED:
|
||||
cfg1.part[0].level = 1;
|
||||
cfg1.part[0].time = (5000);
|
||||
cfg1.parttotal = 1;
|
||||
cfg1.startlevel = 1;
|
||||
cfg1.periodic = false;
|
||||
|
||||
app_pwl_setup(APP_PWL_ID_1, &cfg1);
|
||||
app_pwl_start(APP_PWL_ID_1);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_factorymode_init(uint32_t factorymode)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
int nRet = 0;
|
||||
uint32_t capval = 0x00;
|
||||
struct nvrecord_env_t *nvrecord_env;
|
||||
APP_FACTORY_TRACE(1,"app_factorymode_init mode:%x\n", factorymode);
|
||||
|
||||
osThreadSetPriority(osThreadGetId(), osPriorityRealtime);
|
||||
app_factorymode_uart_init();
|
||||
#ifdef __WATCHER_DOG_RESET__
|
||||
app_wdt_open(60);
|
||||
#endif
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
|
||||
list_init();
|
||||
app_os_init();
|
||||
app_factorymode_indication_init();
|
||||
app_battery_open();
|
||||
if (app_key_open(false)){
|
||||
nRet = -1;
|
||||
goto exit;
|
||||
}
|
||||
app_set_threadhandle(APP_MODUAL_OHTER, app_factorymode_process);
|
||||
app_factory_timer = osTimerCreate (osTimer(APP_FACTORY_TIMER), osTimerPeriodic, NULL);
|
||||
osTimerStart(app_factory_timer, 300);
|
||||
app_factorymode_send_progress(10);
|
||||
|
||||
app_bt_init();
|
||||
af_open();
|
||||
app_audio_open();
|
||||
app_overlay_open();
|
||||
|
||||
nv_record_env_init();
|
||||
nvrec_dev_data_open();
|
||||
nv_record_env_get(&nvrecord_env);
|
||||
#ifdef MEDIA_PLAYER_SUPPORT
|
||||
app_play_audio_set_lang(nvrecord_env->media_language.language);
|
||||
app_voice_report(APP_STATUS_INDICATION_POWERON, 0);
|
||||
#endif
|
||||
app_status_indication_set(APP_STATUS_INDICATION_POWERON);
|
||||
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_RUNNING);
|
||||
|
||||
if (factorymode&HAL_SW_BOOTMODE_CALIB){
|
||||
btdrv_start_bt();
|
||||
app_factorymode_send_progress(20);
|
||||
|
||||
do {
|
||||
nRet = app_factorymode_bt_xtalcalib_proc();
|
||||
}while(nRet && cnt++<APP_FACTORYMODE_RETRY_LIMITED);
|
||||
|
||||
if (nRet)
|
||||
goto err;
|
||||
osDelay(200);
|
||||
app_factorymode_send_progress(30);
|
||||
}
|
||||
|
||||
nvrec_dev_get_xtal_fcap((unsigned int*)&capval);
|
||||
app_factorymode_send_code(capval);
|
||||
|
||||
btdrv_start_bt();
|
||||
bt_drv_reg_op_key_gen_after_reset(false);
|
||||
app_factorymode_send_progress(40);
|
||||
BesbtInit();
|
||||
osDelay(600);
|
||||
|
||||
nRet = app_factorymode_proc();
|
||||
if (nRet)
|
||||
goto err;
|
||||
|
||||
app_factorymode_test_key_init();
|
||||
//osTimerStop(app_factory_timer);
|
||||
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_PASS);
|
||||
|
||||
//wait forever
|
||||
osSignalWait(0x01, osWaitForever);
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
osTimerStop(app_factory_timer);
|
||||
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_FAILED);
|
||||
app_factorymode_send_code(0xff);
|
||||
osSignalWait(0x01, osWaitForever);
|
||||
exit:
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
||||
pmu_shutdown();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
int app_factorymode_calib_only(void)
|
||||
{
|
||||
uint8_t cnt = 0;
|
||||
int nRet = 0;
|
||||
uint32_t capval = 0x00;
|
||||
|
||||
app_factorymode_uart_init();
|
||||
#ifdef __WATCHER_DOG_RESET__
|
||||
app_wdt_reopen(60);
|
||||
#endif
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
|
||||
list_init();
|
||||
app_os_init();
|
||||
nv_record_env_init();
|
||||
nvrec_dev_data_open();
|
||||
factory_section_open();
|
||||
app_factorymode_indication_init();
|
||||
|
||||
app_set_threadhandle(APP_MODUAL_OHTER, app_factorymode_process);
|
||||
app_factory_timer = osTimerCreate(osTimer(APP_FACTORY_TIMER),osTimerPeriodic,NULL);
|
||||
osTimerStart(app_factory_timer,300);
|
||||
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_RUNNING);
|
||||
app_factorymode_send_progress(10);
|
||||
btdrv_start_bt();
|
||||
osDelay(20);
|
||||
app_factorymode_send_progress(20);
|
||||
do {
|
||||
nRet = app_factorymode_bt_xtalcalib_proc();
|
||||
}while(nRet && ++cnt < APP_FACTORYMODE_RETRY_LIMITED);
|
||||
if(nRet)
|
||||
goto err;
|
||||
|
||||
nvrec_dev_get_xtal_fcap((unsigned int*)&capval);
|
||||
app_factorymode_send_code(capval);
|
||||
|
||||
app_factorymode_send_progress(50);
|
||||
osDelay(200);
|
||||
app_factorymode_send_progress(80);
|
||||
osDelay(100);
|
||||
app_factorymode_send_progress(100);
|
||||
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_PASS);
|
||||
osSignalWait(0x01, osWaitForever);
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
osTimerStop(app_factory_timer);
|
||||
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_FAILED);
|
||||
app_factorymode_send_code(0xff);
|
||||
osSignalWait(0x01, osWaitForever);
|
||||
exit:
|
||||
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
||||
pmu_shutdown();
|
||||
return nRet;
|
||||
}
|
||||
|
||||
#ifdef __USB_COMM__
|
||||
// for usb
|
||||
#include "usb_cdc.h"
|
||||
#include "hal_timer.h"
|
||||
#include "hwtimer_list.h"
|
||||
|
||||
#include "hal_usb.h"
|
||||
#include "app_factory_cdc_comm.h"
|
||||
#include "sys_api_cdc_comm.h"
|
||||
|
||||
static const struct USB_SERIAL_CFG_T cdc_cfg = {
|
||||
.mode = USB_SERIAL_API_NONBLOCKING,
|
||||
};
|
||||
|
||||
static void usb_serial_recv_timeout(void *param)
|
||||
{
|
||||
usb_serial_cancel_recv();
|
||||
}
|
||||
|
||||
int app_factorymode_cdc_comm(void)
|
||||
{
|
||||
HWTIMER_ID timer;
|
||||
pmu_usb_config(PMU_USB_CONFIG_TYPE_DEVICE);
|
||||
usb_serial_open(&cdc_cfg);
|
||||
osDelay(500);
|
||||
|
||||
hwtimer_init();
|
||||
timer = hwtimer_alloc(usb_serial_recv_timeout, NULL);
|
||||
ASSERT(timer, "Failed to alloc usb serial recv timer");
|
||||
|
||||
usb_serial_flush_recv_buffer();
|
||||
usb_serial_init_xfer();
|
||||
af_open();
|
||||
|
||||
comm_loop();
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_FACTORY_H__
|
||||
#define __APP_FACTORY_H__
|
||||
|
||||
#define APP_FACTORY_TRACE(s,...) TRACE(s, ##__VA_ARGS__)
|
||||
|
||||
void app_factorymode_result_set(bool result);
|
||||
|
||||
void app_factorymode_result_clean(void);
|
||||
|
||||
bool app_factorymode_result_wait(void);
|
||||
|
||||
void app_factorymode_enter(void);
|
||||
|
||||
void app_factorymode_key_init(void);
|
||||
|
||||
int app_factorymode_init(uint32_t factorymode);
|
||||
|
||||
int app_factorymode_calib_only(void);
|
||||
|
||||
int app_factorymode_languageswitch_proc(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __USB_COMM__
|
||||
int app_factorymode_cdc_comm(void);
|
||||
#endif
|
||||
|
||||
bool app_factorymode_get(void);
|
||||
|
||||
void app_factorymode_set(bool set);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,293 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_trace.h"
|
||||
#include "resources.h"
|
||||
#include "app_bt_stream.h"
|
||||
#include "app_media_player.h"
|
||||
#include "app_factory.h"
|
||||
#include "string.h"
|
||||
|
||||
// for audio
|
||||
#include "audioflinger.h"
|
||||
#include "app_audio.h"
|
||||
#include "app_utils.h"
|
||||
|
||||
#include "app_factory_audio.h"
|
||||
|
||||
|
||||
#ifdef __FACTORY_MODE_SUPPORT__
|
||||
|
||||
#define BT_AUDIO_FACTORMODE_BUFF_SIZE (1024*2)
|
||||
static enum APP_AUDIO_CACHE_T a2dp_cache_status = APP_AUDIO_CACHE_QTY;
|
||||
static int16_t *app_audioloop_play_cache = NULL;
|
||||
|
||||
static uint32_t app_factorymode_data_come(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
app_audio_pcmbuff_put(buf, len);
|
||||
if (a2dp_cache_status == APP_AUDIO_CACHE_QTY){
|
||||
a2dp_cache_status = APP_AUDIO_CACHE_OK;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static uint32_t app_factorymode_more_data(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
if (a2dp_cache_status != APP_AUDIO_CACHE_QTY){
|
||||
app_audio_pcmbuff_get((uint8_t *)app_audioloop_play_cache, len/2);
|
||||
app_bt_stream_copy_track_one_to_two_16bits((int16_t *)buf, app_audioloop_play_cache, len/2/2);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int app_factorymode_audioloop(bool on, enum APP_SYSFREQ_FREQ_T freq)
|
||||
{
|
||||
uint8_t *buff_play = NULL;
|
||||
uint8_t *buff_capture = NULL;
|
||||
uint8_t *buff_loop = NULL;
|
||||
struct AF_STREAM_CONFIG_T stream_cfg;
|
||||
static bool isRun = false;
|
||||
APP_FACTORY_TRACE(3,"app_factorymode_audioloop work:%d op:%d freq:%d", isRun, on, freq);
|
||||
|
||||
if (isRun==on)
|
||||
return 0;
|
||||
|
||||
if (on){
|
||||
if (freq < APP_SYSFREQ_52M) {
|
||||
freq = APP_SYSFREQ_52M;
|
||||
}
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, freq);
|
||||
|
||||
a2dp_cache_status = APP_AUDIO_CACHE_QTY;
|
||||
app_audio_mempool_init();
|
||||
app_audio_mempool_get_buff(&buff_capture, BT_AUDIO_FACTORMODE_BUFF_SIZE);
|
||||
app_audio_mempool_get_buff(&buff_play, BT_AUDIO_FACTORMODE_BUFF_SIZE*2);
|
||||
app_audio_mempool_get_buff((uint8_t **)&app_audioloop_play_cache, BT_AUDIO_FACTORMODE_BUFF_SIZE*2/2/2);
|
||||
app_audio_mempool_get_buff(&buff_loop, BT_AUDIO_FACTORMODE_BUFF_SIZE<<2);
|
||||
app_audio_pcmbuff_init(buff_loop, BT_AUDIO_FACTORMODE_BUFF_SIZE<<2);
|
||||
memset(&stream_cfg, 0, sizeof(stream_cfg));
|
||||
stream_cfg.bits = AUD_BITS_16;
|
||||
//stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
||||
|
||||
#ifdef SPEECH_TX_AEC_CODEC_REF
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_2;
|
||||
#else
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_1;
|
||||
#endif
|
||||
#if defined(__AUDIO_RESAMPLE__) && defined(SW_CAPTURE_RESAMPLE)
|
||||
stream_cfg.sample_rate = AUD_SAMPRATE_8463;
|
||||
#else
|
||||
stream_cfg.sample_rate = AUD_SAMPRATE_8000;
|
||||
#endif
|
||||
#if FPGA==0
|
||||
stream_cfg.device = AUD_STREAM_USE_INT_CODEC;
|
||||
#else
|
||||
stream_cfg.device = AUD_STREAM_USE_EXT_CODEC;
|
||||
#endif
|
||||
stream_cfg.vol = TGT_VOLUME_LEVEL_15;
|
||||
stream_cfg.io_path = AUD_INPUT_PATH_MAINMIC;
|
||||
stream_cfg.handler = app_factorymode_data_come;
|
||||
|
||||
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(buff_capture);
|
||||
stream_cfg.data_size = BT_AUDIO_FACTORMODE_BUFF_SIZE;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg);
|
||||
|
||||
stream_cfg.channel_num = AUD_CHANNEL_NUM_2;
|
||||
stream_cfg.io_path = AUD_OUTPUT_PATH_SPEAKER;
|
||||
stream_cfg.handler = app_factorymode_more_data;
|
||||
|
||||
stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(buff_play);
|
||||
stream_cfg.data_size = BT_AUDIO_FACTORMODE_BUFF_SIZE*2;
|
||||
af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK, &stream_cfg);
|
||||
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
APP_FACTORY_TRACE(0,"app_factorymode_audioloop on");
|
||||
} else {
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE);
|
||||
af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_PLAYBACK);
|
||||
APP_FACTORY_TRACE(0,"app_factorymode_audioloop off");
|
||||
|
||||
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
|
||||
}
|
||||
|
||||
isRun=on;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_factorymode_output_pcmpatten(audio_test_pcmpatten_t *pcmpatten, uint8_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t remain_size = len;
|
||||
uint32_t curr_size = 0;
|
||||
|
||||
if (remain_size > pcmpatten->len)
|
||||
{
|
||||
do{
|
||||
if (pcmpatten->cuur_buf_pos)
|
||||
{
|
||||
curr_size = pcmpatten->len-pcmpatten->cuur_buf_pos;
|
||||
memcpy(buf,&(pcmpatten->buf[pcmpatten->cuur_buf_pos/2]), curr_size);
|
||||
remain_size -= curr_size;
|
||||
pcmpatten->cuur_buf_pos = 0;
|
||||
}
|
||||
else if (remain_size>pcmpatten->len)
|
||||
{
|
||||
memcpy(buf+curr_size, pcmpatten->buf, pcmpatten->len);
|
||||
curr_size += pcmpatten->len;
|
||||
remain_size -= pcmpatten->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(buf+curr_size,pcmpatten->buf, remain_size);
|
||||
pcmpatten->cuur_buf_pos = remain_size;
|
||||
remain_size = 0;
|
||||
}
|
||||
}while(remain_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((pcmpatten->len - pcmpatten->cuur_buf_pos) >= len)
|
||||
{
|
||||
memcpy(buf, &(pcmpatten->buf[pcmpatten->cuur_buf_pos/2]),len);
|
||||
pcmpatten->cuur_buf_pos += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_size = pcmpatten->len-pcmpatten->cuur_buf_pos;
|
||||
memcpy(buf, &(pcmpatten->buf[pcmpatten->cuur_buf_pos/2]),curr_size);
|
||||
pcmpatten->cuur_buf_pos = len - curr_size;
|
||||
memcpy(buf+curr_size, pcmpatten->buf, pcmpatten->cuur_buf_pos);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "fft128dot.h"
|
||||
|
||||
#define N 64
|
||||
#define NFFT 128
|
||||
|
||||
struct mic_st_t{
|
||||
FftTwiddle_t w[N];
|
||||
FftTwiddle_t w128[N*2];
|
||||
FftData_t x[N*2];
|
||||
FftData_t data_odd[N];
|
||||
FftData_t data_even[N];
|
||||
FftData_t data_odd_d[N];
|
||||
FftData_t data_even_d[N];
|
||||
FftData_t data[N*2];
|
||||
signed long out[N];
|
||||
};
|
||||
|
||||
int app_factorymode_mic_cancellation_run(void * mic_st, signed short *inbuf, int sample)
|
||||
{
|
||||
struct mic_st_t *st = (struct mic_st_t *)mic_st;
|
||||
int i,k,jj,ii;
|
||||
//int dataWidth = 16; // input word format is 16 bit twos complement fractional format 1.15
|
||||
int twiddleWidth = 16; // input word format is 16 bit twos complement fractional format 2.14
|
||||
FftMode_t ifft = FFT_MODE;
|
||||
|
||||
make_symmetric_twiddles(st->w,N,twiddleWidth);
|
||||
make_symmetric_twiddles(st->w128,N*2,twiddleWidth);
|
||||
// input data
|
||||
for (i=0; i<sample; i++){
|
||||
st->x[i].re = inbuf[i];
|
||||
st->x[i].im = 0;
|
||||
}
|
||||
|
||||
for(ii = 0; ii < 1; ii++)
|
||||
{
|
||||
k = 0;
|
||||
for (jj = 0; jj < N*2; jj+=2)
|
||||
{
|
||||
FftData_t tmp;
|
||||
|
||||
tmp.re = st->x[jj].re;
|
||||
tmp.im = st->x[jj].im;
|
||||
|
||||
st->data_even[k].re = tmp.re;//(int) (double(tmp.re)*double(1 << FFTR4_INPUT_FORMAT_Y)) ;
|
||||
st->data_even[k].im = tmp.im;//(int) (double(tmp.im)*double(1 << FFTR4_INPUT_FORMAT_Y)) ;
|
||||
tmp.re = st->x[jj+1].re;
|
||||
tmp.im = st->x[jj+1].im;
|
||||
st->data_odd[k].re = tmp.re;//(int) (double(tmp.re)*double(1 << FFTR4_INPUT_FORMAT_Y)) ;
|
||||
st->data_odd[k].im = tmp.im;//(int) (double(tmp.im)*double(1 << FFTR4_INPUT_FORMAT_Y)) ;
|
||||
k++;
|
||||
}
|
||||
|
||||
fftr4(NFFT/2, st->data_even, st->w, FFTR4_TWIDDLE_WIDTH, FFTR4_DATA_WIDTH, ifft);
|
||||
fftr4(NFFT/2, st->data_odd, st->w, FFTR4_TWIDDLE_WIDTH, FFTR4_DATA_WIDTH, ifft);
|
||||
|
||||
for (jj = 0; jj < NFFT/2; jj++)
|
||||
{
|
||||
|
||||
int idx = dibit_reverse_int(jj, NFFT/2);
|
||||
st->data_even_d[jj].re = st->data_even[idx].re;
|
||||
st->data_even_d[jj].im = st->data_even[idx].im;
|
||||
st->data_odd_d[jj].re = st->data_odd[idx].re;
|
||||
st->data_odd_d[jj].im = st->data_odd[idx].im;
|
||||
}
|
||||
for (jj=0;jj<NFFT/2;jj++)
|
||||
{
|
||||
long long mbr,mbi;
|
||||
FftData_t ta;
|
||||
FftData_t tmp;
|
||||
double a;
|
||||
mbr = (long long)(st->data_odd_d[jj].re) * st->w128[jj].re - (long long)(st->data_odd_d[jj].im) * st->w128[jj].im;
|
||||
mbi = (long long)(st->data_odd_d[jj].im) * st->w128[jj].re + (long long)(st->data_odd_d[jj].re) * st->w128[jj].im;
|
||||
ta.re = int(mbr>>(FFTR4_TWIDDLE_WIDTH-2));
|
||||
ta.im = int(mbi>>(FFTR4_TWIDDLE_WIDTH-2));
|
||||
st->data[jj].re = (st->data_even_d[jj].re + ta.re)/2;
|
||||
st->data[jj].im = (st->data_even_d[jj].im + ta.im)/2;
|
||||
//data[jj] = sat(data[jj],FFTR4_DATA_WIDTH);
|
||||
st->data[jj+NFFT/2].re = (st->data_even_d[jj].re - ta.re)/2;
|
||||
st->data[jj+NFFT/2].im = (st->data_even_d[jj].im - ta.im)/2;
|
||||
//data[jj+NFFT/2] = sat(data[jj+NFFT/2],FFTR4_DATA_WIDTH);
|
||||
|
||||
a = st->data[jj].re;///double(1 << FFTR4_OUTPUT_FORMAT_Y);// * double(1 << FFTR4_SCALE);
|
||||
tmp.re = (int)a;
|
||||
a = st->data[jj].im;///double(1 << FFTR4_OUTPUT_FORMAT_Y);// * double(1 << FFTR4_SCALE);
|
||||
tmp.im = (int)a;
|
||||
st->x[ii*NFFT+jj].re = (int) tmp.re;
|
||||
st->x[ii*NFFT+jj].im = (int) tmp.im;
|
||||
a = st->data[jj+NFFT/2].re;///double(1 << FFTR4_OUTPUT_FORMAT_Y);// * double(1 << FFTR4_SCALE);
|
||||
tmp.re = (int)a;
|
||||
a = st->data[jj+NFFT/2].im;///double(1 << FFTR4_OUTPUT_FORMAT_Y);// * double(1 << FFTR4_SCALE);
|
||||
tmp.im = (int)a;
|
||||
st->x[ii*NFFT+jj+NFFT/2].re = (int) tmp.re;
|
||||
st->x[ii*NFFT+jj+NFFT/2].im = (int) tmp.im;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<N; i++){
|
||||
st->out[i] = st->x[i].re * st->x[i].re + st->x[i].im * st->x[i].im;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void *app_factorymode_mic_cancellation_init(void* (* alloc_ext)(int))
|
||||
{
|
||||
struct mic_st_t *mic_st;
|
||||
mic_st = (struct mic_st_t *)alloc_ext(sizeof(struct mic_st_t));
|
||||
return (void *)mic_st;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_FACTORY_BT_H__
|
||||
#define __APP_FACTORY__BTH__
|
||||
|
||||
#include "app_utils.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t *buf;
|
||||
uint32_t len;
|
||||
uint32_t cuur_buf_pos;
|
||||
}audio_test_pcmpatten_t;
|
||||
|
||||
int app_factorymode_audioloop(bool on, enum APP_SYSFREQ_FREQ_T freq);
|
||||
|
||||
int app_factorymode_output_pcmpatten(audio_test_pcmpatten_t *pcmpatten, uint8_t *buf, uint32_t len);
|
||||
|
||||
int app_factorymode_mic_cancellation_run(void * mic_st, signed short *inbuf, int sample);
|
||||
|
||||
void *app_factorymode_mic_cancellation_init(void* (* alloc_ext)(int));
|
||||
|
||||
#endif
|
|
@ -0,0 +1,331 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "cmsis_os.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_sleep.h"
|
||||
#include "bt_drv_interface.h"
|
||||
#include "intersyshci.h"
|
||||
#include "apps.h"
|
||||
#include "app_factory.h"
|
||||
#include "app_factory_bt.h"
|
||||
#include "app_utils.h"
|
||||
#include "bluetooth.h"
|
||||
#include "nvrecord.h"
|
||||
#include "nvrecord_dev.h"
|
||||
#include "pmu.h"
|
||||
#include "tgt_hardware.h"
|
||||
#include "app_battery.h"
|
||||
#include "bt_drv_reg_op.h"
|
||||
#include "conmgr_api.h"
|
||||
#include "me_api.h"
|
||||
#include "hal_bootmode.h"
|
||||
#include "hal_chipid.h"
|
||||
|
||||
|
||||
#define APP_FACT_CPU_WAKE_LOCK HAL_CPU_WAKE_LOCK_USER_3
|
||||
|
||||
#ifdef __FACTORY_MODE_SUPPORT__
|
||||
static uint8_t inquiry_buff[] = {0x01, 0x72, 0x77, 0xb0, 0x18, 0x57, 0x60,\
|
||||
0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00};
|
||||
|
||||
|
||||
static btif_cmgr_handler_t *app_factorymode_cmgrHandler;
|
||||
|
||||
|
||||
static void bt_error_check_timer_handler(void const *param);
|
||||
osTimerDef(bt_error_check_timer, bt_error_check_timer_handler);
|
||||
static osTimerId bt_error_check_timer_id = NULL;
|
||||
uint8_t test_mode_type=0;
|
||||
static void bt_error_check_timer_handler(void const *param)
|
||||
{
|
||||
//dump rssi
|
||||
bt_drv_rssi_dump_handler();
|
||||
//check BT core status
|
||||
if(bt_drv_error_check_handler())
|
||||
{
|
||||
if(test_mode_type==1)
|
||||
{
|
||||
hal_sw_bootmode_set(HAL_SW_BOOTMODE_TEST_MODE|HAL_SW_BOOTMODE_TEST_SIGNALINGMODE);
|
||||
}
|
||||
else if(test_mode_type==2)
|
||||
{
|
||||
hal_sw_bootmode_set(HAL_SW_BOOTMODE_TEST_MODE|HAL_SW_BOOTMODE_TEST_NOSIGNALINGMODE);
|
||||
}
|
||||
hal_cmu_sys_reboot();
|
||||
}
|
||||
}
|
||||
|
||||
static void app_factorymode_bt_inquiry_buff_update(void)
|
||||
{
|
||||
bt_bdaddr_t flsh_dongle_addr;
|
||||
int ret = -1;
|
||||
|
||||
ret = nvrec_dev_get_dongleaddr(&flsh_dongle_addr);
|
||||
if(0 == ret) {
|
||||
memcpy((void *)&inquiry_buff[1],(void *)flsh_dongle_addr.address,BTIF_BD_ADDR_SIZE);
|
||||
DUMP8("0x%02x ", &inquiry_buff[2], BTIF_BD_ADDR_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static void app_factorymode_CmgrCallback(btif_cmgr_handler_t *cHandler,
|
||||
cmgr_event_t Event,
|
||||
bt_status_t Status)
|
||||
{
|
||||
APP_FACTORY_TRACE(4,"%s cHandler:%p Event:%d status:%d", __func__, cHandler, Event, Status);
|
||||
if (Event == BTIF_CMEVENT_DATA_LINK_CON_CNF){
|
||||
if (Status == BT_STS_SUCCESS){
|
||||
APP_FACTORY_TRACE(0,"connect ok");
|
||||
app_factorymode_result_set(true);
|
||||
btif_cmgr_remove_data_link(cHandler);
|
||||
|
||||
}else{
|
||||
APP_FACTORY_TRACE(0,"connect failed");
|
||||
app_factorymode_result_set(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (Event == BTIF_CMEVENT_DATA_LINK_DIS){
|
||||
if (Status == BT_STS_SUCCESS){
|
||||
APP_FACTORY_TRACE(0,"disconnect ok");
|
||||
}else{
|
||||
APP_FACTORY_TRACE(0,"disconnect failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void app_factorymode_bt_InquiryResult_add(void)
|
||||
{
|
||||
U8 len = 15;
|
||||
bool rssi = false, extended = false;
|
||||
U8* parm = (U8*)inquiry_buff;
|
||||
|
||||
/* Found one or more devices. Report to clients */
|
||||
APP_FACTORY_TRACE(4,"%s len:%d rssi:%d extended:%d", __func__, len, rssi, extended);
|
||||
DUMP8("0x%02x ", parm, len);
|
||||
btif_me_inquiry_result_setup(parm, rssi, extended);
|
||||
}
|
||||
|
||||
void app_factorymode_bt_create_connect(void)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t *bdAddr = (bt_bdaddr_t *)(inquiry_buff+1);
|
||||
|
||||
status = btif_cmgr_create_data_link(app_factorymode_cmgrHandler, bdAddr);
|
||||
APP_FACTORY_TRACE(2,"%s:%d", __func__, status);
|
||||
}
|
||||
|
||||
void app_factorymode_bt_init_connect(void)
|
||||
{
|
||||
app_factorymode_cmgrHandler = btif_cmgr_handler_create();
|
||||
|
||||
btif_cmgr_register_handler(app_factorymode_cmgrHandler,
|
||||
app_factorymode_CmgrCallback);
|
||||
app_factorymode_bt_inquiry_buff_update();
|
||||
app_factorymode_bt_InquiryResult_add();
|
||||
}
|
||||
|
||||
extern osTimerId app_bt_accessmode_timer;
|
||||
|
||||
#if defined(CHIP_BEST1400) || defined(CHIP_BEST1402)
|
||||
#define XTAL_FCAP_RANGE (0x1FF)
|
||||
#else
|
||||
#define XTAL_FCAP_RANGE (0xFF)
|
||||
#endif
|
||||
|
||||
void app_factorymode_bt_xtalrangetest(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
dev_addr_name devinfo;
|
||||
uint32_t fcap = 0;
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
#ifdef __WATCHER_DOG_RESET__
|
||||
app_wdt_close();
|
||||
#endif
|
||||
hal_cpu_wake_lock(APP_FACT_CPU_WAKE_LOCK);
|
||||
app_stop_10_second_timer(APP_PAIR_TIMER_ID);
|
||||
app_stop_10_second_timer(APP_POWEROFF_TIMER_ID);
|
||||
if (app_bt_accessmode_timer){
|
||||
osTimerStop(app_bt_accessmode_timer);
|
||||
}
|
||||
if (!bt_error_check_timer_id){
|
||||
bt_error_check_timer_id = osTimerCreate(osTimer(bt_error_check_timer), osTimerPeriodic, NULL);
|
||||
}
|
||||
if (bt_error_check_timer_id != NULL) {
|
||||
osTimerStart(bt_error_check_timer_id, 1000);
|
||||
}
|
||||
test_mode_type = 1;
|
||||
app_status_indication_set(APP_STATUS_INDICATION_TESTMODE);
|
||||
pmu_sleep_en(0);
|
||||
BESHCI_Close();
|
||||
btdrv_hciopen();
|
||||
btdrv_hci_reset();
|
||||
|
||||
#ifndef BT_50_FUNCTION
|
||||
btdrv_sleep_config(0);
|
||||
osDelay(2000);
|
||||
btdrv_ins_patch_test_init();
|
||||
btdrv_feature_default();
|
||||
#endif
|
||||
devinfo.btd_addr = bt_addr;
|
||||
devinfo.ble_addr = ble_addr;
|
||||
devinfo.localname = BT_LOCAL_NAME;
|
||||
nvrec_dev_localname_addr_init(&devinfo);
|
||||
btdrv_write_localinfo((char *)devinfo.localname, strlen(devinfo.localname) + 1, devinfo.btd_addr);
|
||||
|
||||
btdrv_vco_test_start(78);
|
||||
while(1){
|
||||
btdrv_rf_set_xtal_fcap(fcap%XTAL_FCAP_RANGE, 1);
|
||||
osDelay(300);
|
||||
TRACE(2,"xtal tune:%d", fcap%XTAL_FCAP_RANGE);
|
||||
fcap++;
|
||||
}
|
||||
}
|
||||
|
||||
void app_factorymode_bt_signalingtest(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
dev_addr_name devinfo;
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
#ifdef __WATCHER_DOG_RESET__
|
||||
app_wdt_close();
|
||||
#endif
|
||||
hal_cpu_wake_lock(APP_FACT_CPU_WAKE_LOCK);
|
||||
app_stop_10_second_timer(APP_PAIR_TIMER_ID);
|
||||
app_stop_10_second_timer(APP_POWEROFF_TIMER_ID);
|
||||
if (app_bt_accessmode_timer){
|
||||
osTimerStop(app_bt_accessmode_timer);
|
||||
}
|
||||
if (!bt_error_check_timer_id){
|
||||
bt_error_check_timer_id = osTimerCreate(osTimer(bt_error_check_timer), osTimerPeriodic, NULL);
|
||||
}
|
||||
if (bt_error_check_timer_id != NULL) {
|
||||
osTimerStart(bt_error_check_timer_id, 1000);
|
||||
}
|
||||
test_mode_type = 1;
|
||||
app_status_indication_set(APP_STATUS_INDICATION_TESTMODE);
|
||||
pmu_sleep_en(0);
|
||||
BESHCI_Close();
|
||||
btdrv_hciopen();
|
||||
btdrv_ins_patch_test_init();
|
||||
btdrv_hci_reset();
|
||||
|
||||
#ifndef BT_50_FUNCTION
|
||||
btdrv_sleep_config(0);
|
||||
osDelay(2000);
|
||||
btdrv_testmode_start();
|
||||
btdrv_feature_default();
|
||||
#endif
|
||||
devinfo.btd_addr = bt_addr;
|
||||
devinfo.ble_addr = ble_addr;
|
||||
devinfo.localname = BT_LOCAL_NAME;
|
||||
devinfo.ble_name= BT_LOCAL_NAME;
|
||||
nvrec_dev_localname_addr_init(&devinfo);
|
||||
#ifdef __IBRT_IBRT_TESTMODE__
|
||||
uint8_t ibrt_address[6] = {0x11,0x22,0x33,0x44,0x55,0x66};
|
||||
memcpy(bt_addr,ibrt_address,6);
|
||||
memcpy(devinfo.btd_addr,ibrt_address,6);
|
||||
#endif
|
||||
btdrv_write_localinfo((char *)devinfo.localname, strlen(devinfo.localname) + 1, devinfo.btd_addr);
|
||||
bt_drv_extra_config_after_init();
|
||||
btdrv_enable_dut();
|
||||
#ifdef __IBRT_IBRT_TESTMODE__
|
||||
btdrv_enable_ibrt_test();
|
||||
#endif
|
||||
}
|
||||
|
||||
int app_battery_stop(void);
|
||||
void app_factorymode_bt_nosignalingtest(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
dev_addr_name devinfo;
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
#ifdef __WATCHER_DOG_RESET__
|
||||
app_wdt_close();
|
||||
#endif
|
||||
hal_cpu_wake_lock(APP_FACT_CPU_WAKE_LOCK);
|
||||
app_stop_10_second_timer(APP_PAIR_TIMER_ID);
|
||||
app_stop_10_second_timer(APP_POWEROFF_TIMER_ID);
|
||||
app_status_indication_set(APP_STATUS_INDICATION_TESTMODE1);
|
||||
osTimerStop(app_bt_accessmode_timer);
|
||||
if (!bt_error_check_timer_id){
|
||||
bt_error_check_timer_id = osTimerCreate(osTimer(bt_error_check_timer), osTimerPeriodic, NULL);
|
||||
}
|
||||
if (bt_error_check_timer_id != NULL) {
|
||||
osTimerStart(bt_error_check_timer_id, 1000);
|
||||
}
|
||||
test_mode_type = 2;
|
||||
app_battery_stop();
|
||||
pmu_sleep_en(0);
|
||||
BESHCI_Close();
|
||||
btdrv_hciopen();
|
||||
btdrv_ins_patch_test_init();
|
||||
bt_drv_reg_op_key_gen_after_reset(false);
|
||||
btdrv_hci_reset();
|
||||
#ifndef BT_50_FUNCTION
|
||||
btdrv_sleep_config(0);
|
||||
#endif
|
||||
osDelay(2000);
|
||||
btdrv_testmode_start();
|
||||
#ifndef BT_50_FUNCTION
|
||||
btdrv_feature_default();
|
||||
devinfo.btd_addr = bt_addr;
|
||||
devinfo.ble_addr = ble_addr;
|
||||
devinfo.localname = BT_LOCAL_NAME;
|
||||
devinfo.ble_name= BT_LOCAL_NAME;
|
||||
nvrec_dev_localname_addr_init(&devinfo);
|
||||
btdrv_write_localinfo((char *)devinfo.localname, strlen(devinfo.localname) + 1, devinfo.btd_addr);
|
||||
#endif
|
||||
bt_drv_extra_config_after_init();
|
||||
btdrv_hcioff();
|
||||
#ifdef __BT_DEBUG_TPORTS__
|
||||
{
|
||||
extern void bt_enable_tports(void);
|
||||
bt_enable_tports();
|
||||
//hal_iomux_tportopen();
|
||||
}
|
||||
#endif
|
||||
btdrv_uart_bridge_loop();
|
||||
}
|
||||
int app_factorymode_bt_xtalcalib_proc(void)
|
||||
{
|
||||
uint32_t capval = 0x80;
|
||||
int nRet;
|
||||
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
hal_cpu_wake_lock(APP_FACT_CPU_WAKE_LOCK);
|
||||
APP_FACTORY_TRACE(1,"calib default, capval:%d", capval);
|
||||
btdrv_hciopen();
|
||||
btdrv_hci_reset();
|
||||
#ifndef BT_50_FUNCTION
|
||||
btdrv_ins_patch_test_init();
|
||||
#endif
|
||||
btdrv_hcioff();
|
||||
capval = 0x80;
|
||||
bt_drv_calib_open();
|
||||
nRet = bt_drv_calib_result_porc(&capval);
|
||||
bt_drv_calib_close();
|
||||
TRACE(2,"!!!!!!!!!!!!!!!!!!!!!!!!!!!calib ret:%d, capval:%d", nRet, capval);
|
||||
if (!nRet)
|
||||
nvrec_dev_set_xtal_fcap((unsigned int)capval);
|
||||
|
||||
return nRet;
|
||||
}
|
||||
|
||||
void app_factorymode_bt_xtalcalib(APP_KEY_STATUS *status, void *param)
|
||||
{
|
||||
APP_FACTORY_TRACE(1,"%s",__func__);
|
||||
app_factorymode_bt_xtalcalib_proc();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/***************************************************************************
|
||||
*
|
||||
* Copyright 2015-2019 BES.
|
||||
* All rights reserved. All unpublished rights reserved.
|
||||
*
|
||||
* No part of this work may be used or reproduced in any form or by any
|
||||
* means, or stored in a database or retrieval system, without prior written
|
||||
* permission of BES.
|
||||
*
|
||||
* Use of this work is governed by a license granted by BES.
|
||||
* This work contains confidential and proprietary information of
|
||||
* BES. which is protected by copyright, trade secret,
|
||||
* trademark and other intellectual property rights.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef __APP_FACTORY_BT_H__
|
||||
#define __APP_FACTORY__BTH__
|
||||
|
||||
#include "app_key.h"
|
||||
|
||||
|
||||
void app_factorymode_bt_create_connect(void);
|
||||
|
||||
void app_factorymode_bt_init_connect(void);
|
||||
|
||||
int app_factorymode_bt_xtalcalib_proc(void);
|
||||
|
||||
void app_factorymode_bt_xtalrangetest(APP_KEY_STATUS *status, void *param);
|
||||
|
||||
void app_factorymode_bt_signalingtest(APP_KEY_STATUS *status, void *param);
|
||||
|
||||
void app_factorymode_bt_nosignalingtest(APP_KEY_STATUS *status, void *param);
|
||||
|
||||
void app_factorymode_bt_xtalcalib(APP_KEY_STATUS *status, void *param);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,314 @@
|
|||
#ifdef __USB_COMM__
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
#include "plat_types.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "tool_msg.h"
|
||||
#include "sys_api_cdc_comm.h"
|
||||
#include "app_factory_cdc_comm.h"
|
||||
|
||||
static enum PARSE_STATE parse_state;
|
||||
static struct message_t recv_msg;
|
||||
static struct message_t send_msg = { { PREFIX_CHAR, }, };
|
||||
|
||||
static unsigned char check_sum(unsigned char *buf, unsigned char len)
|
||||
{
|
||||
int i;
|
||||
unsigned char sum = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
int send_reply(const unsigned char *payload, unsigned int len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (len + 1 > sizeof(send_msg.data)) {
|
||||
TRACE(1,"Packet length too long: %u", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
send_msg.hdr.type = recv_msg.hdr.type;
|
||||
send_msg.hdr.seq = recv_msg.hdr.seq;
|
||||
send_msg.hdr.len = len;
|
||||
memcpy(&send_msg.data[0], payload, len);
|
||||
send_msg.data[len] = ~check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
|
||||
|
||||
ret = send_data((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void reset_parse_state(unsigned char **buf, size_t *len)
|
||||
{
|
||||
parse_state = PARSE_HEADER;
|
||||
memset(&recv_msg.hdr, 0, sizeof(recv_msg.hdr));
|
||||
|
||||
*buf = (unsigned char *)&recv_msg.hdr;
|
||||
*len = sizeof(recv_msg.hdr);
|
||||
}
|
||||
|
||||
static enum ERR_CODE check_msg_hdr(void)
|
||||
{
|
||||
enum ERR_CODE errcode = ERR_NONE;
|
||||
|
||||
switch (recv_msg.hdr.type) {
|
||||
case TYPE_SYS:
|
||||
if (recv_msg.hdr.len != 1 && recv_msg.hdr.len != 5) {
|
||||
//TRACE(1,"SYS msg length error: %u", recv_msg.hdr.len);
|
||||
errcode = ERR_LEN;
|
||||
}
|
||||
break;
|
||||
case TYPE_READ:
|
||||
if (recv_msg.hdr.len != 4) {
|
||||
//TRACE(1,"READ msg length error: %u", recv_msg.hdr.len);
|
||||
errcode = ERR_LEN;
|
||||
}
|
||||
break;
|
||||
case TYPE_WRITE:
|
||||
if (recv_msg.hdr.len <= 4 || recv_msg.hdr.len > 20) {
|
||||
//TRACE(1,"WRITE msg length error: %u", recv_msg.hdr.len);
|
||||
errcode = ERR_LEN;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (errcode == ERR_NONE && recv_msg.hdr.len + 1 > sizeof(recv_msg.data)) {
|
||||
errcode = ERR_LEN;
|
||||
}
|
||||
|
||||
return errcode;
|
||||
}
|
||||
|
||||
static enum ERR_CODE handle_sys_cmd(enum SYS_CMD_TYPE cmd, unsigned char *param, unsigned int len)
|
||||
{
|
||||
unsigned char cret[5];
|
||||
unsigned int bootmode;
|
||||
|
||||
cret[0] = ERR_NONE;
|
||||
|
||||
if (cmd == SYS_CMD_SET_BOOTMODE || cmd == SYS_CMD_CLR_BOOTMODE) {
|
||||
if (len != 4) {
|
||||
TRACE(2,"Invalid SYS CMD len %u for cmd: 0x%x", len, cmd);
|
||||
return ERR_DATA_LEN;
|
||||
}
|
||||
} else {
|
||||
if (len != 0) {
|
||||
TRACE(2,"Invalid SYS CMD len %u for cmd: 0x%x", len, cmd);
|
||||
return ERR_DATA_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SYS_CMD_REBOOT: {
|
||||
TRACE(0,"--- Reboot---");
|
||||
send_reply(cret, 1);
|
||||
system_reboot();
|
||||
break;
|
||||
}
|
||||
case SYS_CMD_SHUTDOWN: {
|
||||
TRACE(0,"--- Shutdown ---");
|
||||
send_reply(cret, 1);
|
||||
system_shutdown();
|
||||
break;
|
||||
}
|
||||
case SYS_CMD_SET_BOOTMODE: {
|
||||
TRACE(0,"--- Set bootmode ---");
|
||||
memcpy(&bootmode, param, 4);
|
||||
system_set_bootmode(bootmode);
|
||||
send_reply(cret, 1);
|
||||
break;
|
||||
}
|
||||
case SYS_CMD_CLR_BOOTMODE: {
|
||||
TRACE(0,"--- Clear bootmode ---");
|
||||
memcpy(&bootmode, param, 4);
|
||||
system_clear_bootmode(bootmode);
|
||||
send_reply(cret, 1);
|
||||
break;
|
||||
}
|
||||
case SYS_CMD_GET_BOOTMODE: {
|
||||
TRACE(0,"--- Get bootmode ---");
|
||||
bootmode = system_get_bootmode();
|
||||
memcpy(&cret[1], &bootmode, 4);
|
||||
send_reply(cret, 5);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
TRACE(1,"Invalid command: 0x%x", recv_msg.data[0]);
|
||||
return ERR_SYS_CMD;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
static enum ERR_CODE handle_data(unsigned char **buf, size_t *len, int *extra)
|
||||
{
|
||||
enum ERR_CODE errcode = ERR_NONE;
|
||||
#if 0
|
||||
uint32_t rlen = 0;
|
||||
#endif
|
||||
*extra = 0;
|
||||
|
||||
// Checksum
|
||||
if (check_sum((unsigned char *)&recv_msg, MSG_TOTAL_LEN(&recv_msg)) != 0xFF) {
|
||||
TRACE(0,"Checksum error");
|
||||
return ERR_CHECKSUM;
|
||||
}
|
||||
|
||||
switch (recv_msg.hdr.type) {
|
||||
case TYPE_SYS: {
|
||||
TRACE_TIME(0,"------ SYS CMD ------");
|
||||
errcode = handle_sys_cmd((enum SYS_CMD_TYPE)recv_msg.data[0], &recv_msg.data[1], recv_msg.hdr.len - 1);
|
||||
if (errcode != ERR_NONE) {
|
||||
return errcode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TYPE_READ: {
|
||||
TRACE_TIME(0,"------ READ CMD ------");
|
||||
#if 0
|
||||
uint32_t addr = (recv_msg.data[0] << 16) | (recv_msg.data[1] << 8) | recv_msg.data[2];
|
||||
uint8_t data[4] = {0};
|
||||
rlen = read_reg(addr, data);
|
||||
if(rlen == 0)
|
||||
return ERR_LEN;
|
||||
else {
|
||||
send_reply(data, rlen);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case TYPE_WRITE: {
|
||||
TRACE_TIME(0,"------ WRITE CMD ------");
|
||||
#if 0
|
||||
uint32_t addr = (recv_msg.data[0] << 16) | (recv_msg.data[1] << 8) | recv_msg.data[2];
|
||||
uint32_t wdata = (recv_msg.data[3] << 24) | (recv_msg.data[4] << 16) | (recv_msg.data[5] << 8) | recv_msg.data[6];
|
||||
uint8_t data[1] = {0};
|
||||
errcode = write_reg(addr, wdata);
|
||||
if (errcode != ERR_NONE)
|
||||
return errcode;
|
||||
else
|
||||
send_reply(data, 1);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
static int parse_packet(unsigned char **buf, size_t *len)
|
||||
{
|
||||
enum ERR_CODE errcode;
|
||||
int rlen = *len;
|
||||
unsigned char *data;
|
||||
int i;
|
||||
int extra;
|
||||
unsigned char cret;
|
||||
|
||||
switch (parse_state) {
|
||||
case PARSE_HEADER:
|
||||
ASSERT(rlen > 0 && rlen <= sizeof(recv_msg.hdr), "Invalid rlen!");
|
||||
|
||||
if (recv_msg.hdr.prefix == PREFIX_CHAR) {
|
||||
errcode = check_msg_hdr();
|
||||
if (errcode != ERR_NONE) {
|
||||
goto _err;
|
||||
}
|
||||
parse_state = PARSE_DATA;
|
||||
*buf = &recv_msg.data[0];
|
||||
*len = recv_msg.hdr.len + 1;
|
||||
} else {
|
||||
data = (unsigned char *)&recv_msg.hdr.prefix;
|
||||
for (i = 1; i < rlen; i++) {
|
||||
if (data[i] == PREFIX_CHAR) {
|
||||
memmove(&recv_msg.hdr.prefix, &data[i], rlen - i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
*buf = &data[rlen - i];
|
||||
*len = sizeof(recv_msg.hdr) + i - rlen;
|
||||
}
|
||||
break;
|
||||
case PARSE_DATA:
|
||||
errcode = handle_data(buf, len, &extra);
|
||||
if (errcode != ERR_NONE) {
|
||||
goto _err;
|
||||
}
|
||||
// Receive next message
|
||||
reset_parse_state(buf, len);
|
||||
break;
|
||||
default:
|
||||
TRACE(1,"Invalid parse_state: %d", parse_state);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
cancel_input();
|
||||
cret = (unsigned char)errcode;
|
||||
send_reply(&cret, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void comm_loop(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned char *buf = NULL;
|
||||
size_t len = 0;
|
||||
size_t buf_len, rlen;
|
||||
|
||||
_sync:
|
||||
reset_transport();
|
||||
reset_parse_state(&buf, &len);
|
||||
|
||||
while (1) {
|
||||
rlen = 0;
|
||||
if (parse_state == PARSE_HEADER) {
|
||||
set_recv_timeout(default_recv_timeout_idle);
|
||||
} else {
|
||||
set_recv_timeout(default_recv_timeout_short);
|
||||
}
|
||||
buf_len = 0;
|
||||
|
||||
ret = recv_data_ex(buf, buf_len, len, &rlen);
|
||||
if (ret) {
|
||||
TRACE(1,"Receiving data failed: %d", ret);
|
||||
goto _err;
|
||||
}
|
||||
|
||||
if (len != rlen) {
|
||||
TRACE(2,"Receiving part of the data: expect=%u real=%u", len, rlen);
|
||||
goto _err;
|
||||
}
|
||||
|
||||
ret = parse_packet(&buf, &len);
|
||||
if (ret) {
|
||||
TRACE(0,"Parsing packet failed");
|
||||
goto _err;
|
||||
}
|
||||
}
|
||||
|
||||
_err:
|
||||
ret = handle_error();
|
||||
if (ret == 0) {
|
||||
TRACE(0,"retry ...");
|
||||
goto _sync;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef __APP_FACTORY_CDC_COMM__H__
|
||||
#define __APP_FACTORY_CDC_COMM__H__
|
||||
#ifdef __USB_COMM__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void comm_loop(void);
|
||||
|
||||
int send_reply(const unsigned char *payload, unsigned int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,229 @@
|
|||
#ifdef __USB_COMM__
|
||||
#include "sys_api_cdc_comm.h"
|
||||
#include "app_factory_cdc_comm.h"
|
||||
#include "hal_bootmode.h"
|
||||
#include "hwtimer_list.h"
|
||||
#include "pmu.h"
|
||||
#ifdef CHIP_HAS_USB
|
||||
#include "usb_cdc.h"
|
||||
#endif
|
||||
|
||||
#define TIMEOUT_INFINITE ((uint32_t)-1)
|
||||
|
||||
const unsigned int default_recv_timeout_short = MS_TO_TICKS(500);
|
||||
const unsigned int default_recv_timeout_idle = TIMEOUT_INFINITE; //MS_TO_TICKS(10 * 60 * 1000);
|
||||
const unsigned int default_recv_timeout_4k_data = MS_TO_TICKS(500);
|
||||
const unsigned int default_send_timeout = MS_TO_TICKS(500);
|
||||
|
||||
static uint32_t send_timeout;
|
||||
static uint32_t recv_timeout;
|
||||
|
||||
static volatile bool cancel_xfer = false;
|
||||
|
||||
static uint32_t xfer_err_time = 0;
|
||||
static uint32_t xfer_err_cnt = 0;
|
||||
|
||||
static HWTIMER_ID xfer_timer;
|
||||
|
||||
static const struct USB_SERIAL_CFG_T cdc_cfg = {
|
||||
.mode = USB_SERIAL_API_NONBLOCKING,
|
||||
};
|
||||
|
||||
void reset_transport(void)
|
||||
{
|
||||
cancel_xfer = false;
|
||||
|
||||
if (xfer_timer) {
|
||||
hwtimer_stop(xfer_timer);
|
||||
} else {
|
||||
xfer_timer = hwtimer_alloc(NULL, NULL);
|
||||
}
|
||||
|
||||
usb_serial_flush_recv_buffer();
|
||||
usb_serial_init_xfer();
|
||||
set_recv_timeout(default_recv_timeout_short);
|
||||
set_send_timeout(default_send_timeout);
|
||||
}
|
||||
|
||||
void set_recv_timeout(unsigned int timeout)
|
||||
{
|
||||
recv_timeout = timeout;
|
||||
}
|
||||
|
||||
void set_send_timeout(unsigned int timeout)
|
||||
{
|
||||
send_timeout = timeout;
|
||||
}
|
||||
|
||||
static void usb_send_timeout(void *param)
|
||||
{
|
||||
usb_serial_cancel_send();
|
||||
}
|
||||
|
||||
static void usb_send_timer_start(void)
|
||||
{
|
||||
if (send_timeout == TIMEOUT_INFINITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (xfer_timer) {
|
||||
hwtimer_update_then_start(xfer_timer, usb_send_timeout, NULL, send_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_send_timer_stop(void)
|
||||
{
|
||||
if (xfer_timer) {
|
||||
hwtimer_stop(xfer_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_send_data(const unsigned char *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
usb_send_timer_start();
|
||||
ret = usb_serial_send(buf, len);
|
||||
usb_send_timer_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int send_data(const unsigned char *buf, size_t len)
|
||||
{
|
||||
if (cancel_xfer) {
|
||||
return -1;
|
||||
}
|
||||
return usb_send_data(buf, len);
|
||||
}
|
||||
|
||||
static void usb_recv_timeout(void *param)
|
||||
{
|
||||
usb_serial_cancel_recv();
|
||||
}
|
||||
|
||||
static void usb_recv_timer_start(void)
|
||||
{
|
||||
if (recv_timeout == TIMEOUT_INFINITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (xfer_timer) {
|
||||
hwtimer_update_then_start(xfer_timer, usb_recv_timeout, NULL, recv_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_recv_timer_stop(void)
|
||||
{
|
||||
if (xfer_timer) {
|
||||
hwtimer_stop(xfer_timer);
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_recv_data(unsigned char *buf, size_t len, size_t *rlen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
usb_recv_timer_start();
|
||||
ret = usb_serial_recv(buf, len);
|
||||
usb_recv_timer_stop();
|
||||
if (ret == 0) {
|
||||
*rlen = len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int recv_data_ex(unsigned char *buf, size_t len, size_t expect, size_t *rlen)
|
||||
{
|
||||
if (cancel_xfer) {
|
||||
return -1;
|
||||
}
|
||||
return usb_recv_data(buf, expect, rlen);
|
||||
}
|
||||
|
||||
static int usb_handle_error(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
TRACE(0,"****** Send break ******");
|
||||
|
||||
// Send break signal, to tell the peer to reset the connection
|
||||
ret = usb_serial_send_break();
|
||||
if (ret) {
|
||||
TRACE(1,"Sending break failed: %d", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int handle_error(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t err_time;
|
||||
|
||||
hal_sys_timer_delay(MS_TO_TICKS(50));
|
||||
|
||||
if (!cancel_xfer) {
|
||||
ret = usb_handle_error();
|
||||
}
|
||||
|
||||
err_time = hal_sys_timer_get();
|
||||
if (xfer_err_cnt == 0 || err_time - xfer_err_time > MS_TO_TICKS(5000)) {
|
||||
xfer_err_cnt = 0;
|
||||
xfer_err_time = err_time;
|
||||
}
|
||||
xfer_err_cnt++;
|
||||
if (xfer_err_cnt < 3) {
|
||||
hal_sys_timer_delay(MS_TO_TICKS(100));
|
||||
} else if (xfer_err_cnt < 5) {
|
||||
hal_sys_timer_delay(MS_TO_TICKS(500));
|
||||
} else {
|
||||
hal_sys_timer_delay(MS_TO_TICKS(2000));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usb_cancel_input(void)
|
||||
{
|
||||
return usb_serial_flush_recv_buffer();
|
||||
}
|
||||
|
||||
int cancel_input(void)
|
||||
{
|
||||
return usb_cancel_input();
|
||||
}
|
||||
|
||||
void system_reboot(void)
|
||||
{
|
||||
hal_sys_timer_delay(MS_TO_TICKS(10));
|
||||
hal_cmu_sys_reboot();
|
||||
}
|
||||
|
||||
void system_shutdown(void)
|
||||
{
|
||||
#if 0
|
||||
if (dld_transport == TRANSPORT_USB) {
|
||||
// Avoid PC usb serial driver hanging
|
||||
usb_serial_close();
|
||||
}
|
||||
#endif
|
||||
hal_sys_timer_delay(MS_TO_TICKS(10));
|
||||
pmu_shutdown();
|
||||
}
|
||||
|
||||
void system_set_bootmode(unsigned int bootmode)
|
||||
{
|
||||
bootmode &= ~(HAL_SW_BOOTMODE_READ_ENABLED | HAL_SW_BOOTMODE_WRITE_ENABLED);
|
||||
hal_sw_bootmode_set(bootmode);
|
||||
}
|
||||
|
||||
void system_clear_bootmode(unsigned int bootmode)
|
||||
{
|
||||
bootmode &= ~(HAL_SW_BOOTMODE_READ_ENABLED | HAL_SW_BOOTMODE_WRITE_ENABLED);
|
||||
hal_sw_bootmode_clear(bootmode);
|
||||
}
|
||||
|
||||
unsigned int system_get_bootmode(void)
|
||||
{
|
||||
return hal_sw_bootmode_get();
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef __SYS_API_USB_CDC_H__
|
||||
#define __SYS_API_USB_CDC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "tool_msg.h"
|
||||
#include "hal_trace.h"
|
||||
#include "hal_timer.h"
|
||||
|
||||
#define TRACE_TIME(num,str, ...) TRACE(num+1,"[%05u] " str, TICKS_TO_MS(hal_sys_timer_get()), ##__VA_ARGS__)
|
||||
|
||||
extern const unsigned int default_recv_timeout_short;
|
||||
extern const unsigned int default_recv_timeout_idle;
|
||||
extern const unsigned int default_recv_timeout_4k_data;
|
||||
extern const unsigned int default_send_timeout;
|
||||
|
||||
void reset_transport(void);
|
||||
|
||||
void set_recv_timeout(unsigned int timeout);
|
||||
void set_send_timeout(unsigned int timeout);
|
||||
|
||||
int send_data(const unsigned char *buf, size_t len);
|
||||
int recv_data_ex(unsigned char *buf, size_t len, size_t expect, size_t *rlen);
|
||||
int handle_error(void);
|
||||
int cancel_input(void);
|
||||
|
||||
void system_reboot(void);
|
||||
void system_shutdown(void);
|
||||
void system_flash_boot(void);
|
||||
void system_set_bootmode(unsigned int bootmode);
|
||||
void system_clear_bootmode(unsigned int bootmode);
|
||||
unsigned int system_get_bootmode(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
cur_dir := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
|
||||
obj-y := $(patsubst $(cur_dir)%,%,$(wildcard $(cur_dir)*.c $(cur_dir)*.cpp $(cur_dir)*.S))
|
||||
obj-y := $(obj-y:.c=.o)
|
||||
obj-y := $(obj-y:.cpp=.o)
|
||||
obj-y := $(obj-y:.S=.o)
|
||||
|
||||
subdir-ccflags-y += -Iutils/list
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue