KDocs 研发资料库
  • 音频技术应用文档入口汇总
  • 杰理WINDOWS环境安装及其他事项
  • LINUX安装和编译
  • Linux环境编译SDK教程(ubuntu18.04)
  • 音频类补丁汇总表
  • 认证资料获取汇总(最新资料后台会更新)
  • 《Hi-Res申请指南v1.0》
  • FreeRTOS 开源协议版本
  • uCOS 开源协议版本信息
  • 各个模块关键资料汇总
  • 软件调试方法
  • Makefile编译
  • 提bug的规范
  • 常规设备使用指导
  • 对外特别发布开发注意点信息汇总
  • AD697X软件问题整理
  • AC700N软件问题整理
  • AC701X耳机软件问题整理
  • 951&961软件问题整理
  • AC104X软件问题整理
  • AC128N问题整理文档
  • 可视化工具调试问题整理
  • 耳机资料汇总
  • AC704N、 AC705N相关应用
  • AC695N&AC696N&AC608N音箱问题整理
  • JL701N音箱问题整理
  • AC692X软件问题整理
  • AC706N音箱问题整理
  • JL701N音箱问题整理(可视化工具SDK)
  • JL703N音箱问题整理
  • JL709N(JL689N)音箱问题整理
  • JL7094系列-入门到进阶开发指导
  • AC210N音箱问题整理
  • 无线麦系列版本支持指南
  • AW32N无线麦问题整理
  • lAD697X&JL701X 无线麦软件共性问题整理
  • AC706N无线麦问题整理
  • AW36N无线麦问题整理
  • AC710X无线麦问题整理
  • 唤醒源获取及唤醒IO设置
  • 电源
  • LVD
  • 长按复位配置方法
  • 低功耗应用
  • TIMER
  • UART
  • SPI
  • 内部FLASH空间添加用户自定义区域
  • IIC
  • GPIO
  • MCPWM
  • SD&U盘
  • 时钟&晶振
  • GPCNT
  • IO口crossbar映射功能
  • 文件系统使用总结
  • 复用应用
  • LINEIN_AUX相关应用
  • IIS音频接口应用
  • SPDIF模式相关(HDMI_ARC、光纤、同轴)
  • PDM LINK
  • 外设相关应用
  • 蓝牙相关
  • 杰理蓝牙距离调试文档
  • TWS耳机配对方式使用及生产把控指南
  • GFP谷歌快连及其认证流程指引
  • 蓝牙发射器(bt_emitter)相关
  • BLE应用
  • 关于提升BLE传输速率说明
  • BLE测试数据
  • MUSIC 模式相关应用
  • MIDI音乐实现
  • PC相关应用
  • FM相关应用
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20250107
  • fm应用详细设计说明书
  • 杰理FM硬件指南-20230315
  • ADC模块
  • AUDIO相关应用
  • 新Tools的音效调试使用
  • 混响应用使用说明
  • 音效调式
  • 音箱耳机低音小音量增强实现方法
  • DAC输出功率调试
  • DAC性能测试指南
  • 针对各类底噪、电流声分析流程
  • 录音相关应用
  • OPUS编解码相关
  • RTC相关应用
  • 升级相关
  • UI相关应用
  • 通话调试流程指南
  • 通话相关应用
  • 省电容mic使用手册
  • 如何测试验证手表通话系统的语音失真 V1.0
  • AC695X_AC696X_AD697X 常见通话问题处理参考资料
  • 通话调试问题确定步骤
  • 内置触摸调试指南
  • 低功耗内置触摸介绍V2.2
  • 触摸相关文档
  • AC697X、AC698X内置触摸调试及整改方法V1.0
  • 产测相关应用
  • AC63X BLE DUT测试介绍
  • 兆华序列使用简易说明
  • JL_1T2蓝牙测试盒音频文件更换说明
  • ENC相关应用入口汇总
  • ANC相关应用入口汇总
  • JL DMS通话调试手册-V3.9.4
  • ANC-ENC结构设计要点-20240407
  • 半入耳式ANC耳机器件选型与结构设计指南V1.0
  • JL 耳道自适应调试指南
  • ANC相关问题处理
  • ANC调试文档
  • 评估蓝牙耳机通话上行降噪性能的方法 V1.0 (2)
  • FCC 或者 BQB 认证相关应用
  • BQB profile 测试中常遇到的问题点汇总
  • 蓝牙参数整理20210811
  • 杰理科技认证问题参考
  • 无线音频产品开发指南
  • 无线麦系列从入门到进阶开发指导
  • 量产烧录相关说明
  • 一拖八烧录器远程过程调用说明
  • 量产相关建议
  • EffectTool(eq)调试工具说明文档
  • AC897AD697系列的EQ调试方法-V3
  • 杰理调音指南-20220622
  • 音效模块总结
  • 简要调音步骤指引(可视化)
  • 耳机充电与通信调试指南
  • 充电仓硬件调试指南
  • 充电仓软件问题整理
  • AC951常用说明
  • AC951_AC961_开发板使用说明V1.0
  • 彩屏仓AC982 入门指导及FAQ
  • 蓝牙音频APP相关应用
  • 手机APP的简介和开发流程
  • 蓝牙音频系列-硬件设计指南
  • 静电测试及整改方法-20220706
  • TWS耳机底噪整改指南V1.2
  • 杰理蓝牙距离调试文档
  • 蓝牙RF硬件设计与调试V1.1-20250219
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20241228
  • 音效调试指南
  • 无线话筒K歌音箱标准开发流程
  • 杰理科技 700N TWS耳机产品标准-202303
  • 杰理科技 701N 广播产品标准-202303
  • JL-HAT ANC高效产测自适应
  • 无线话筒测试板使用介绍
  • 一拖八频偏校准使用说明
  • 领夹麦产测工具使用介绍
  • Dongle量产测试说明
  • Dongle+Tws或头戴式 SDK通过工具绑定配对功能说明文档
  • 双麦ENC产测宏配置验证方法 V1.0
  • JL耳机方案麦克风声学测试指令_V1.0
  • JL耳机方案麦克风声学测试指令_V2.0
  • JL_ENC自动测试命令_V0.0.1
  • JL蓝牙测试盒用例说明
  • LDAC自测环境搭建_ubuntu
  • 延迟小板使用手册
  • 杰理库文件的制作及添加实现过程
  • 关于 AC635N&AC636N系列免晶振兼容性补丁 说明
  • 关于 AC63系列VM兼容性修复补丁_20250224 说明
  • 关于 AC632N &AE632N_ 蓝牙& 低功耗兼容性修复补丁 说明
  • AD698N和AC638N电压优化补丁V3说明
  • 关于 AC635N&AC636N漏电和E&G版兼容联合补丁 说明
  • AD698N和AC638N电压优化补丁V2说明
  • 702相关应用
  • 2024-4-30 发布歌词显示SDK开发注意事项
  • BQB RF & FCC 认证测试固件问题汇总及源码
  • BQB profile 测试中常遇到的问题点汇总
  • 进dut测试模式方法及固件
  • 704-频偏修改bin文件合集
  • 701手表BQB PROFILE认证注意事项
  • 认证的干扰规避整改
  • 海外CRA认证报告生成说明
  • JL700N可视化工具问题处理文档
  • JL701X可视化工具问题处理文档
  • JL701N_earphone_release_v1.6.0_ANC 低功耗问题补丁
  • JL708X可视化工具问题处理文档
  • JL709N可视化工具问题处理文档
  • JLstudio可视化工具使用说明
  • 一拖二-串口_蓝牙_app在线EQ、通话参数及调试方式和内置触摸调试
  • 可视化JL701M_DONGLE_SDK添加MIC为发射源
  • 可视化JL701M_DONGLE_SDK添加按键切换usb audio与MIC发射源
  • JL701M_DONGLE_SDK_1.0.0_dongle输入linein输出dac
  • 701可视化_a2dp_to_le_demo说明
  • 耳机系列demo汇总
  • JL7018F&JL7006F_7003F AUX IIS
  • 一键连接应用
  • 普通SDK动态开关一拖二功能
  • 蓝牙分析仪(EllisysBluetoothAnalyzer)抓包例程
  • TWS配对常见应用
  • APP自定义按键的demo
  • AC700N 播歌双EQ DEMO示例及说明
  • AC698V164 MIC与蓝牙音乐共同输出DAC demo
  • 添加第三方算法以及多算法授权流程
  • 空间音频配置方法
  • 普通高低电平TWS耳机控制通讯
  • 入耳检测状态更新demo解析
  • 资源优化(非可视化的SDK)
  • 资源优化(可视化SDK)
  • 翻译耳机、语音识别应用demo
  • 耳机抗干扰问题排查和优化
  • AC698D2 抗干扰优化
  • AC696X软件问题整理
  • AC695X软件问题整理
  • AC695X软件问题整理_1722249702
  • AC608X软件问题整理
  • JL701N_2T1_DUPLEX 应用软件问题汇总
  • le_audio_1.0.0_patch05 以及之前的版本IRkey 功能异常修改
  • AC706N-le_audio-200SDK有线_无线麦录音demo
  • jl701n_le_audio_v200patch02 IO串口升级修改串口单次发送字节长度的修改办法
  • 703创建IIS 输入dac输出音频流demo
  • 703将媒体流音频同时上传PC_mic录音demo实现
  • 703四路IIS输入输出demo
  • 底噪调试
  • AW328A烧录说明
  • 文档合集
  • AC706N_wireless_mic_release_PATCH_20240712 补丁 说明
  • AC706N_wireless_mic_release_PATCH_20240726 补丁 说明
  • AC706N_wireless_mic_release_V1.0.0、1.0.1、1.0.2 补丁 说明
  • AC706N_wireless_mic_release_V1.1.2 中的2T1应用 RX端不绑定配对,TX端实现绑定配对的修改方法
  • 各系列省晶振实现方法
  • iis tx rx说明文档
  • spdif信号
  • 蓝牙电话本
  • 安卓手机同步时间补丁
  • CDC配置
  • PC模式下增加Teams唤起功能
  • 杰理HDMIARC开发实现过程
  • AC701N patch06之前的版本用第三方算法节点实现新版本的pcm delay节点功能
  • (K歌音箱)各SDK音效配置相关说明
  • 长文件录音
  • 点阵屏歌词字库相关(蓝牙歌词,普通歌词)
  • 字模提取工具说明
  • 音箱可视化彩屏-入门到进阶开发指导
  • 彩屏LVGL UI设计及工具使用
  • 使用内部UI框架进行UI调试的系列步骤
  • AD101C使用强制升级工具spi 烧录不了问题处理(测试版本)
  • AD161扩展灯板说明文档
  • 歌词显示器开发注意项
  • 使用硬件数字增益控制通话下行音量(可视化)
  • 杰理小牛产测资料
  • ENC配置说明
  • 通话调试流程指引
  • ANC相关功能demo
  • 无线麦硬件资料汇总
  • 无线麦相关应用
  • 无线麦复杂功能补丁包汇总
  • 无线话筒形态SDK程序&开发经验&问题点分享
  • 双模式结合应用问题汇总
  • 无线麦距离优化案例
  • 无线麦系列中的双工形态(duplex)演变开发对讲机方案开发资料
  • 音箱入门到进阶指导文档(编写中)
  • 蓝牙耳机品控和生产技巧
  • 982过_欠压标志获取异常
  • 如何获取最新涂鸦SDK及库文件
  • 无线话筒K歌音响-调音标准流程
  • 无线话筒产测流程

蓝牙相关

📎 原始文档:https://www.kdocs.cn/l/cq7C8uzFydQS 蓝牙相关

蓝牙ID3

  1. 把以下变量置1
const u8 more_avctp_cmd_support = 1;
//检查以下宏是否定义
#define TCFG_DEC_ID3_V1_ENABLE                ENABLE
#define TCFG_DEC_ID3_V2_ENABLE                ENABLE
  1. void bredr_handle_register() 添加获取歌曲信息的回调
////获取歌曲信息回调
bt_music_info_handle_register(user_get_bt_music_info);
  1. 添加歌曲信息的处理函数(如果SDK已实现该函数,使用默认就可以)
/*----------------------------------------------------------------------------*/
/**@brief    蓝牙歌词信息获取回调
   @param
   @return
   @note
   const u8 more_avctp_cmd_support = 1;置上1
   需要在void bredr_handle_register()注册回调函数
   要动态获取播放时间的,可以发送USER_CTRL_AVCTP_OPID_GET_PLAY_TIME命令就可以了
   要半秒或者1秒获取就做个定时发这个命令
*/
/*----------------------------------------------------------------------------*/
void user_get_bt_music_info(u8 type, u32 time, u8 *info, u16 len)
{
    //profile define type: 1-title 2-artist name 3-album names 4-track number 5-total number of tracks 6-genre  7-playing time
    //JL define 0x10-total time , 0x11 current play position
    u8  min, sec;
    printf("type %d\n", type );
    if ((info != NULL) && (len != 0)) {
        printf(" %s \n", info);
    }
    if (time != 0) {
        min = time / 1000 / 60;
        sec = time / 1000 - (min * 60);
        printf(" time %d %d\n ", min, sec);
    }
}
  1. 打印如下 image

  2. 蓝牙空闲状态时间设置(可优化连接速度)

  • 减少空间状态时间,可以减少蓝牙连接,TWS配对,无线测试盒连接的时间。但是相对功耗会高
//普通SDKe
set_idle_period_slot(1600);

//可视化SDK 使用以下函数
void dut_idle_run_slot(u16 slot);

SDK 默认值为 1600(时间实际为 1600*0.625ms), 建议修改为 200。 该值最小为 100, 注意不能使用低功耗适用于音箱对功耗要求不高的产品使用。
image 2. 蓝牙名修改

  • 普通模式下蓝牙名(默认使用配置文件的蓝牙名)
const char *bt_get_local_name()

{

    return (const char *)(bt_cfg.edr_name);

}
  • 独立自拍模式下的蓝牙名设置(该函数需要自行写入代码)
const char *bt_get_hid_name()

{

    return "JL_HID_DEFAULT";

}
- 注意:如果打开了TWS功能,需要修改HID名字需要修改以下内容

需要自行添加判断
image

  • 动态修改蓝牙名
extern void hci_vendor_update_name(void);

int bt_modify_name(u8 *new_name)

{

    u8 new_len = strlen(new_name);



    if (new_len >= LOCAL_NAME_LEN) {

        new_name[LOCAL_NAME_LEN - 1] = 0;

    }



    if (strcmp(new_name, bt_cfg.edr_name)) {

        syscfg_write(CFG_BT_NAME, new_name, LOCAL_NAME_LEN);

        memcpy(bt_cfg.edr_name, new_name, LOCAL_NAME_LEN);

        hci_vendor_update_name();

        log_info("mdy_name sucess\\n");

        return 1;

    }

    return 0;

}
  • BLE名字修改 搜索程序上 HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME字样,找到数据部分的传参就是实际的蓝牙名。根据实际需要修改指针指向的内容。注意:包数据最长只有31字节每个包都是 31 字节,数据包中分为有效数据(significant)和无效数据(non-significant)两部分。 有效数据部分 包含若干个广播数据单元,组成是: 长度 Len ,表示这个 AD Structure 的长度(除去 len本身 1) 类型 AD Type 标记这段广播数据代表什么, 比如设备名, uuid 等。 数据 AD data 无效数据部分 广播包的长度必须是 31 个 byte,如果有效数据部分不到 31 自己,剩下的就用 0 补全。这部分的数据是无效的。 蓝牙名 数据类型 HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME 所以需要隐藏BLE名称在蓝牙搜索列表中显示的方式
    image
  1. A2DP延时
  • 音箱版本SDK
const int CONFIG_A2DP_DELAY_TIME            = 200;
  • 耳机SDK版本 image

备注:调小延迟会影响蓝牙距离,要严格测试确认。
4. A2DP 开关

/*----------------------------------------------------------------------------*/
/**@brief  蓝牙  开关a2dp
   @param
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
void bredr_a2dp_open_and_close()
{
    if (get_curr_channel_state() & A2DP_CH) {
        puts("start to disconnect a2dp ");
        user_send_cmd_prepare(USER_CTRL_DISCONN_A2DP, 0, NULL);
    } else {
        puts("start to connect a2dp ");
        user_send_cmd_prepare(USER_CTRL_CONN_A2DP, 0, NULL);
    }
}
  1. AAC、SBC格式
  2. 开启AAC格式支持 打开下面的宏定义
#define TCFG_BT_SUPPORT_AAC                 1   //AAC格式支持

注意点:

  • AC696音箱版本SDK还需要打开(1.5.0SDK及以上才支持AAC) SDK\apps\soundbox\log_config\lib_media_config.c
const int config_aac_dec_use_malloc     = 1;
  1. A2DP解码去除开头杂音数据,添加淡入效果 对比696_1.5.0_SDK的此文件修改,能解决某些AAC切SBC格式存在杂音问题
    【金山文档】 audio_dec_bt
    https://kdocs.cn/l/cvoRvEMih9Se
    此处需要修改
    image

  2. SBC、AAC码率

  3. SBC码率修改接口(不同SDK,接口可能会不同,可以通过模糊搜索”bitpool“定位): AC700X为例:
    image

SBC是一种 可设置Bitpool的编解码,Bitpool设置范围在2~53之间,但在通用的A2DP协议(不考虑V1.2的Extension)中,对于联合立体声,Bitpool可用范围在35~53之间,因此可用码率在229kbps~345kbps之间,但要注意,这并不是可变码率。具体的Bitpool数值和码率的运算可以使用如下网站的工具:
https://link.zhihu.com/?target=https%3A//btcodecs.valdikss.org.ru/sbc-bitrate-calculator/
image

2、AAC码率修改接口(不同SDK,接口可能会不同,可以通过模糊搜索”bitrate“定位):
AC700X为例:
image

扩展:
1、sbc是通用的最基本的解码方式,蓝牙耳机都支持,支持44khz/16bit的音频,最高码率是328kbps,延时大约220ms,所以音质一般。
2、aac是苹果产品通用的解码方式,跟sbc差不多,支持44khz/16bit的音频,最高码率512kbps,延时大约100ms,音质略好于sbc。
3、aptx是高通的专利,支持48khz/16bit的音频,最高码率352kbps,延时约40ms,音质好于sbc,但相比sbc提升并不大。
4、ldac是真正的高音质解码,索尼出品,支持96khz/24bit的音频,最高码率达990kbps,接近无损解码。
5、lhac(hwa)也是接近无损解码,华为主推,支持96khz/24bit的音频,最高码率900kbps,可以媲美ldac
以flac格式的无损音乐为例,FLAC 24bit/96kHz典型压缩编码码率在2350kbps左右,我们网上下载的flac无损音质一般是44khz/16bit的,码率大约990kbps,网上下载的wav无损音乐一般也是44khz/16bit的,码率大约1400kbps。所以高品质的无损音乐体积是比较大的

  1. HID 独立模式(独立拍照模式) apps\soundbox\task_manager\bt\bt.c 添加对应消息
case KEY_CHANGE_MODE:
        if(__this->hid_mode){
            __this->hid_mode = 0;
            extern int app_task_switch_check(u8 app_task);
            if(app_task_switch_check(APP_MUSIC_TASK)||\
            app_task_switch_check(APP_LINEIN_TASK)\
            ){
                ret = false;
            }else{
                user_change_profile_mode(__this->hid_mode);///HID设备名称, 默认蓝牙名称追加_HID
            }
        }else{
            __this->hid_mode = 1;
            user_change_profile_mode(__this->hid_mode);///HID设备名称, 默认蓝牙名称追加_HID
            //如果要修改名称, 可以重写重写这个函数,上面有重写例子
            //const char *__attribute__((weak)) bt_get_hid_name()
        }
        break;
  1. 音量同步
  2. 连接使用默认音量
AC芯片型号SDK修改方法补丁文件
AC692NAC692x_SDK_release_V2.6.31. 外部定义下以下代码:
extern void __set_bt_music_default_vol(u8 vol);
__set_bt_music_default_vol(50); /*1-127*/

| •AC692 2.6.3SDK
替换下面链接的库文件
【金山文档】 AC692x_SDK_release_V2.6.3_改音量同步 | | AC695N | AC695N_soundbox_sdk_release_3.1.0以及以前SDK | 1.配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。


2. 替换库文件 | AC695N_soundbox_sdk_release_3.1.0:
【金山文档】 btstack-695-v310-调整音量同步-C
btstack-695-v310-调整音量同步-C.zip
btstack-695-v310-20240301.zip(支持首次连接使用默认音量,
部分测试仪不支持delay_report,需要关掉:u8 a2dp_support_delay_report = 0;)
AC695N_soundbox_sdk_release_3.0.6:
【金山文档】 btstack-695-v306-改同步默认音量
btstack-695-v306-改同步默认音量.zip
AC695N_soundbox_sdk_release_3.0.1:
btstack-695-v301-修改音量同步.zip
以前SDK版本联系我们改库

需要map功能:
【金山文档】 310版本
https://kdocs.cn/l/cmySs38X8CAR


| | AC696N | ac696n_soundbox_sdk_v1.5.0以上 | 1. 配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。

| 无需替换文件 | | AC696N | ac696n_soundbox_sdk_v1.5.0及以前SDK
ac696n_earphone_v0.2.0--2M_
| 1. 配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。


2. 替换库文件 | ac696n_soundbox_sdk_v1.3.3&ac696n_soundbox_sdk_v1.5.0:【金山文档】 ac696n_soundbox_sdk_v1.5.0_改音量同步
ac696n_soundbox_sdk_v1.2.2:【金山文档】 AC696N_SOUNDBOX_SDK_1.2.2-修改默认音量配置
ac696n_soundbox_sdk_v1.1.1:【金山文档】 btstack-696_v111加同步默认音量
ac696n_earphone_v0.2.0:btstack_2M_flash-696-v0.2.0修好同步默认音量: | | AC697N | AC897N_AD697N_earphone_release_V2.3.0(包含)以上 | 1.配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。

| 无需替换文件 | | AC697N | AC897N_AD697N_earphone_release_V2.3.0以下SDK | 1.配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。


2.替换库文件 | AC897N_AD697N_earphone_release_V2.2.5:【金山文档】 697_SDk225_默认音量同步值 | | AC698N | ad698n_earphone_release_v1.6.0及以上 | 1. 配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。

| 无需替换文件 | | AC698N | ad698n_earphone_release_v1.6.0以下 | 1. 配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。


2. 替换库文件 | ad698n_earphone_release_v1.3.3:【金山文档】 btstack-698_v1.3.3修改音量同步
ad698n_earphone_release_v1.2.5:【金山文档】 ad698n_earphone_release_v1.2.5 支持默认音量同步值修改的库 | | 新系列(AC700N、AC701N...) | | 参考以下修改:
1.配合外面重新定义一个变量

u8 need_default_volume = 127*8/10; 为初始化80%。

| |

  1. 首次连接使用默认音量

AC697X/700n/701n/708n/709n/710n

配合外面重新定义u8 need_default_volume = 127*8/10; 为初始化80%。
外面程序定义u8 sync_default_volume_every_time = 0 ; //0是首次连接时使用默认音量即(need_default_volume) 1是每次都使用默认音量
特殊版本:

  • AC897N_AD697N_earphone_release_V2.2.5 替换下面链接的库文件
    【金山文档】 SDK225 修改首次连接音量同步值,之后按记忆
    https://kdocs.cn/l/cdToz8mQqt0X
  • AC897N_AD697N_earphone_release_V2.3.0 替换下面链接的库文件
    【金山文档】 SDK230 修改首次连接音量同步值,之后按记忆
    btstack-697-v230-20250325.zip

AC696X

  • ac696n_soundbox_sdk_v1.7.0 【金山文档】 SDK170 修改首次连接音量同步值,之后按记忆
    btstack-696-v170-音量支持首次连接固定音量-20251009.zip
  1. 自定义音量同步下,手机每一个对应的音量大小 image 上图是单独调节模拟音量的,如果需要更加细致的音量调节,需要调节数字音量,找到app_audio控制音量处修改:
static unsigned short user_combined_vol_list[31][2] = {
    { 0,     0}, //0: None
    {30,    65}, // 1:-48.00 db
    {30,    92}, // 2:-45.00 db
    {30,   130}, // 3:-42.00 db
    {30,   184}, // 4:-39.00 db
    {30,   260}, // 5:-36.00 db
    {30,   367}, // 6:-33.00 db
    {30,   518}, // 7:-30.00 db
    {30,   732}, // 8:-27.00 db
    {30,  1034}, // 9:-24.00 db
    {30,  1460}, // 10:-21.00 db
    {30,  2063}, // 11:-18.00 db
    {30,  2914}, // 12:-15.00 db
    {30,  4115}, // 13:-12.00 db
    {30,  5813}, // 14:-9.00 db
    {30,  8211}, // 15:-6.00 db
    {30,  9213}, // 16:-5.00 db
    {30,  9600}, // 17:-4.64 db
    {30, 10003}, // 18:-4.29 db
    {30, 10423}, // 19:-3.93 db
    {30, 10860}, // 20:-3.57 db
    {30, 11316}, // 21:-3.21 db
    {30, 11791}, // 22:-2.86 db
    {30, 12286}, // 23:-2.50 db
    {30, 12802}, // 24:-2.14 db
    {30, 13339}, // 25:-1.79 db
    {30, 13899}, // 26:-1.43 db
    {30, 14483}, // 27:-1.07 db
    {30, 15091}, // 28:-0.71 db
    {30, 15724}, // 29:-0.36 db
    {30, 16384}, // 30:0.00 db
};
static int audio_vol_set(u8 gain_l, u8 gain_r, u8 gain_rl, u8 gain_rr, u8 fade)
{
#if (AUDIO_VOL_MANUAL)
    return 0;
#endif

#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
    return 0;
#endif

#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS)
    extern void *iis_digvol_last;
    if (iis_digvol_last) {
        audio_dig_vol_set(iis_digvol_last, AUDIO_DIG_VOL_ALL_CH, gain_l);
    }
#endif

#if (TCFG_APP_FM_EMITTER_EN)
    extern void *fmtx_digvol_last;
    audio_dig_vol_set(fmtx_digvol_last, AUDIO_DIG_VOL_ALL_CH, gain_l);
#endif

#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
    bt_emitter_set_vol(gain_l);
#endif
    /* r_printf("dac_fade_begin:0x%x\n", __this->fade_timer); */
    local_irq_disable();
    __this->fade_gain_l = gain_l;
    __this->fade_gain_r = gain_r;
    __this->fade_gain_rl = gain_rl;
    __this->fade_gain_rr = gain_rr;

#if AUDIO_OUTPUT_INCLUDE_DAC

#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_L)
    audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), gain_l, fade);
    audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_l ? DEFAULT_DIGTAL_VOLUME : 0, fade);
#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R)
    audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), gain_r, fade);
    audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_r ? DEFAULT_DIGTAL_VOLUME : 0, fade);
#else
    //将原先此处固定数字音量然后设置模拟音量的方式 改为 同时更改数字和模拟音量,注意TCFG_AUDIO_DAC_CONNECT_MODE的定义
    u16 analog_vol_l  = user_combined_vol_list[gain_l][0];
    u16 analog_vol_r  = user_combined_vol_list[gain_r][0];
    u16 digital_vol_l = user_combined_vol_list[gain_l][1];
    u16 digital_vol_r = user_combined_vol_list[gain_r][1];

    audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), analog_vol_l, fade);
    audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), analog_vol_r, fade);
    audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), digital_vol_l, fade);
    audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(1), digital_vol_r, fade);
#endif

#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) \
    || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF))
    audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(2), gain_rl, fade);
    audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(3), gain_rr, fade);
    audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(2), gain_rl ? DEFAULT_DIGTAL_VOLUME : 0, fade);
    audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(3), gain_rr ? DEFAULT_DIGTAL_VOLUME : 0, fade);
#endif

#endif // AUDIO_OUTPUT_INCLUDE_DAC

    local_irq_enable();

    return 0;
}
  1. 固定通话音量 image

  2. 首次连接同步通话音量 imageimageimage

  3. 696v160 支持同步音量的手机连接时设置默认50%音量,如果不是音量同步的手机则设置最大音量。 btstack-696-v160修改音量同步细节.rar

  4. 同步样机音量到手机端 image

  5. 获取电话本功能

使用指令

user_send_cmd_prepare(USER_CTRL_PBAP_READ_ALL,0,NULL);

回调函数

//此处拿数据,结束标志:type == 255
void phonebook_packet_handler(u8 type, const u8 *name, const u8 *number, const u8 *date)
{
    static u16 number_cnt = 0;
    printf("NO.%d:", number_cnt);
    number_cnt++;
    printf("type:%d ", type);
    if (type == 0xff) {
        number_cnt = 0;
    }
    if (name) {
        printf(" NAME:%s  ", name);
    }
    if (number) {
        printf("number:%s  ", number);
    }
    if (date) {
        printf("date:%s ", date);
    }
    putchar('\n');
}

【金山文档】 蓝牙电话本
蓝牙电话本.otl

  1. 三方通话 关键词:三方通话
    image 用途:当手机支持三方通话时,实现结束当前通话接听另一个打入的电话或者保留当前通话并接听另一个打入的电话的效果
user_send_cmd_prepare(USER_CTRL_HFP_THREE_WAY_ANSWER1, 0, NULL);
user_send_cmd_prepare(USER_CTRL_HFP_THREE_WAY_ANSWER2, 0, NULL);

注意点:

  1. 如果无效果注意此变量有无开启,开启后才有效 image 2.本功能单纯是让手机执行这两个功能,具体是否支持三方通话以及三方通话的实际效果只与手机有关。
    3.挂断当前通话切回另一个,需要同时发USER_CTRL_HFP_THREE_WAY_ANSWER1和USER_CTRL_HFP_THREE_WAY_ANSWER2,只发answer1会停在保留界面。
  2. 蓝牙功率 接口函数
/* --------------------------------------------------------------------------*/
/**
 * @brief ble_set_fix_pwr
 *
 * @param fix (0~max)
 * 动态调整BLE的发射功率
 */
/* ----------------------------------------------------------------------------*/
void ble_set_fix_pwr(u8 fix);
/* --------------------------------------------------------------------------*/
/**
 * @brief bredr_set_fix_pwr
 *
 * @param fix (0~max)
 * 动态调整EDR的发射功率
 */
/* ----------------------------------------------------------------------------*/
void bredr_set_fix_pwr(u8 fix);

//pwr:普通状态pg_pwr:发起连接请求 iq_pwr:发现周围蓝牙设备 ble_pwr:BLE
void bt_max_pwr_set(u8 pwr, u8 pg_pwr, u8 iq_pwr, u8 ble_pwr);
  1. 蓝牙rssi信号强度获取

BREDR 获取已连接设备的rssi

image

BLE 获取已连接设备的rssi

image 12. 清除连接记录(恢复出厂设置)

1、 在蓝牙模式下非连接状态下执行:

   清除手机配对信息: user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);  
   清除 TWS 配对信息: bt_tws_remove_pairs();  

2、 如果是手机和 TWS 连接的状态:

  先断开手机连接: user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL);  
  断开后清除手机配对信息:  
 case BT_STATUS_FIRST_DISCONNECT:  
 case BT_STATUS_SECOND_DISCONNECT:  
 user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);  
 清除 TWS 配对信息: tws_api_remove_pairs();  

3、 非蓝牙模式下:

 清除 TWS 配对信息:   

image 清除手机配对信息:先记录要清除配对信息的标志,进入蓝牙模式后再调用
user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);
来清除手机配对信息。

image

例如在idle模式下清除配对信息:
image

进入蓝牙模式后执行清除:
image

  1. 频偏

AC708N,AC710N程序上频偏修改:

使用以下函数进行频偏修改,可同时修改edr和ble,调用位置如图:

    extern void bt_osc_offset_ext_save(s32 offset);
    bt_osc_offset_ext_save(-55);//参数跟bt_osc_offset_set规则一致,特别注意此函数需要全擦才能清除

image

AC700X &701&703&(706音箱 )程序上频偏修改:

extern void bt_osc_offset_set(s32 offset); 该函数要在power_reset_source_dump();后调用。参数使用说明:如果测试盒测试到未修改频偏前数值是+20 ,那么就填bt_osc_offset_set(20); 如果测试到是-20 那么就填bt_osc_offset_set(-20);
image

带ble的需要使用此函数,建议在app_main调用;

    extern void bt_osc_offset_ext_save(s32 offset);
    bt_osc_offset_ext_save(-55);//参数跟bt_osc_offset_set规则一致,特别注意此函数需要全擦才能清除

image

AC698X 程序上频偏修改:

void bt_osc_offset_ext_updata(s32 offset);在下图的地方调用,
参数使用说明:如果测试盒测试到未修改频偏前数值是+20 ,那么就填bt_osc_offset_ext_updata(20); 如果测试到是-20 那么就填bt_osc_offset_ext_updata(-20);
image

AC696 音箱程序上频偏修改:

默认值修改:
image

动态修改:
使用函数:bt_osc_offset_ext_save(s32 offset)
使用方法: 该函数要在power_reset_source_dump();后调用。参数使用说明:如果测试盒测试到未修改频偏前数值是+20 ,那么就填bt_osc_offset_ext_save(20); 如果测试到是-20 那么就填bt_osc_offset_ext_save(-20);
image

AC696 耳机程序上频偏修改:

image

  1. 蓝牙版本号
  2. 蓝牙测试仪连接蓝牙样机读取到的蓝牙版本号可以通过以下接口修改: (蓝牙5.3就设置0x0c) btcontroller_modules.h:
    image

image

  1. AC690X 蓝牙版本号修改
/*AC690蓝牙BQB版本设置
这里的0x08改为0x0a,对应的就是5.1的。
0x08  4.2
0x09  5.0
0x0a  5.1
0x0b  5.2
0x0c  5.3
0x0d  5.4
AC690 系列修改蓝牙版本号,由于 SDK 中默认把蓝牙的版本写为 2.1,在外层可以进行修改。ac690x 系列程序修改蓝牙版本信息修改在 bt_configs_user.c 文件里面添加下面代码
*/
struct lmp_deviceni
{
    u8 *name;
    u8 pin_code[16];
    u8 addr[6];
    u8 version[5];
};
extern struct lmp_device local;
void patch_version()
{
    local.version[0]=0x08;
    local.version[1]=0xd6;
    local.version[2]=0x05;
}

在bt_app_cfg 函数开头调用 patch_version 函数如下!
image 【金山文档】 bluetooth_lib-690-emitter_v107-BQB-修改5.3
https://kdocs.cn/l/cnEkA0rXnc45
【金山文档】 bluetooth_lib-690-v2012v4-BQB-修改5.3
https://kdocs.cn/l/cqWEp330X0sl
2. AC692X 蓝牙版本号修改 在上层 APP 程序加入如下修改,把蓝牙版本修改为 5.0 版本。
extern u8 *get_device_version(void);
u8 *lmp_pal_version = get_device_version();
*lmp_pal_version = 0x09;
image 【金山文档】 bluetooth_lib-br21-v2.6.3-BQB-修改5.3
https://kdocs.cn/l/ck7wl55B6q0S
3. AC696X/AC695X/AC697X/AC700X 蓝牙版本号修改 蓝牙版本修改(蓝牙5.3就设置0x0c,蓝牙5.4就设置0x0d):
image 4. AC702X 蓝牙版本号修改 蓝牙版本修改(蓝牙5.3就设置0x0c,蓝牙5.4就设置0x0d):
image 5. 蓝牙6.0修改 蓝牙core 6.0修改说明.pdf

  1. 蓝牙设备类型(蓝牙HCI属性)修改 http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
    例如如下应用设置:
    image SDK程序端接口
#define BD_CLASS_LOUDSPEAKER        0x240414
extern void __change_hci_class_type(u32 class);
///例如:
__change_hci_class_type(BD_CLASS_LOUDSPEAKER);

image

image

备注:AC702N flash版本SDK的void __change_hci_class_type(u32 class)函数没有引出。需要按以下重定义处理:
image

extern struct _stack_config rom_stack_configs_app;
void __change_hci_class_type(u32 class)
{​
struct _stack_config *user_stack_configs = &rom_stack_configs_app;
user_stack_configs->hci_dev_class = class;
​}

调用位置一样是在蓝牙初始化配置函数中调用:

image

  1. BT HID

AC700X键盘简单应用

  1. 添加hid_user.h,hid_user.c以及standard_hid.h文件到对应目录 【金山文档】 AC700X_BTHID文件
    https://kdocs.cn/l/cjw2RPKaP93G
    \apps\common\third_party_profile\jieli\hid_user.h
    \apps\common\third_party_profile\jieli\hid_user.c
    \apps\common\include\standard_hid.h

  2. HID描述符,如需修改参考官方标准HID协议文档

const u8 use_hid_descriptor[] = {
    0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
    0x09, 0x06,        // Usage (Keyboard)
    0xA1, 0x01,        // Collection (Application)
    0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
    0x85, 0x01,        //   Report ID (1)
    0x19, 0xE0,        //   Usage Minimum (0xE0)
    0x29, 0xE7,        //   Usage Maximum (0xE7)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x08,        //   Report Count (8)
    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x08,        //   Report Size (8)
    0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x05,        //   Report Count (5)
    0x75, 0x01,        //   Report Size (1)
    0x05, 0x08,        //   Usage Page (LEDs)
    0x19, 0x01,        //   Usage Minimum (Num Lock)
    0x29, 0x05,        //   Usage Maximum (Kana)
    0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x03,        //   Report Size (3)
    0x91, 0x03,        //   Output (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
    0x95, 0x06,        //   Report Count (6)
    0x75, 0x08,        //   Report Size (8)
    0x15, 0x00,        //   Logical Minimum (0)
    0x26, 0xA4, 0x00,  //   Logical Maximum (164)
    0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
    0x19, 0x28,        //   Usage Minimum (0x28)
    0x2A, 0x28, 0x00,  //   Usage Maximum (0x28)
    0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              // End Collection

    0x05, 0x0C,        // Usage Page (Consumer)
    0x09, 0x01,        // Usage (Consumer Control)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x02,        //   Report ID (2)
    0x75, 0x10,        //   Report Size (16)
    0x95, 0x01,        //   Report Count (1)
    0x15, 0x01,        //   Logical Minimum (1)
    0x26, 0xFC, 0x03,  //   Logical Maximum (1020)
    0x19, 0x01,        //   Usage Minimum (Consumer Control)
    0x2A, 0xFC, 0x03,  //   Usage Maximum (0x03FC)
    0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              // End Collection
};
  1. 使用例子
struct user_hid_consumer_cmd {
    //Bluetooth HID Protocol Message Header Octet
    u8 HIDP_Hdr;
    //Bluetooth HID Boot Reports
    u8 report_id;
    u8 button;
} _GNU_PACKED_;

static struct user_hid_consumer_cmd u_consumer = {
    .HIDP_Hdr = 0xA1,
    .report_id = 0x02,
    .button = 0,
};
// consumer key
#define CONSUMER_MENU               0x01
#define CONSUMER_MENU_ESCAPE        0x02
#define CONSUMER_AC_HOME            0x04
void hid_consumer_send_test(u8 menu)
{
    y_printf("hid_consumer_send_test menu = %d", menu);
    if (menu == 1) {
        u_consumer.button = CONSUMER_MENU;
    }
    if (menu == 2) {
        u_consumer.button = CONSUMER_MENU_ESCAPE;
    }
    if (menu == 3) {
        u_consumer.button = CONSUMER_AC_HOME;
    }
    put_buf((u8 *)&u_consumer, sizeof(u_consumer));
    user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer));
    u_consumer.button = 0x00;
    user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer));
}

u8 sdp_make_hid_service_data[0x200];
static void user_hid_sdp_init(const u8 *hid_descriptor, u16 size)
{
    int real_size;
    real_size = sdp_create_diy_hid_service(sdp_make_hid_service_data, sizeof(sdp_make_hid_service_data), hid_descriptor, size);
    printf("dy_hid_service(%d):", real_size);
}
void user_hid_descriptor_init(void)
{
    __change_hci_class_type(BD_CLASS_KEYBOARD);  /*键盘图标,需要更换手机显示图标的可以自己改成以前的值*/
    user_hid_init(user_hid_interrupt_handler);
    user_hid_sdp_init(use_hid_descriptor, sizeof(use_hid_descriptor));
}

//用户修改成自定义的描述符说明
//1、在void bredr_handle_register();中调用user_hid_descriptor_init;
//2、user_hid_sdp_init换成自己的表
//3、文件上方HID_CHANGE_DESCRIPTOR定义为1
//4、在bt_profile_config.c文件中extern sdp_make_hid_service_data数组,
//  把sdp_hid_service_data替换为sdp_make_hid_service_data.
//5、把const u8 hid_conn_depend_on_dev_company的值置0;
#define USER_HID_MUSIC_PP           0x00CD      //播放暂停
#define USER_HID_MUSIC_NEXT         0x00B5      //下一首
#define USER_HID_MUSIC_PREV         0x00B6      //上一首
#define USER_HID_VOL_UP             0x00E9      //音量+
#define USER_HID_VOL_DOWN           0x00EA      //音量-
#define USER_HID_FAST_FORWARD       0x00B3      //快进
#define USER_HID_REWIND             0x00B4      //快退
#define USER_HID_IOS_HOME           0x0040      //IOS HOME键
switch (key_event) {
    case  KEY_HID_TEST_1:
        log_info("KEY_HID_TEST_1");
        edr_hid_key_deal_test(USER_HID_MUSIC_PP);
        break;
    case  KEY_HID_TEST_2:
        log_info("KEY_HID_TEST_2");
        edr_hid_key_deal_test(USER_HID_MUSIC_NEXT);
        break;
    case  KEY_HID_TEST_3:
        log_info("KEY_HID_TEST_3");
        edr_hid_key_deal_test(USER_HID_MUSIC_PREV);
        break;
    case  KEY_HID_TEST_4:
        log_info("KEY_HID_TEST_4");
        edr_hid_key_deal_test(USER_HID_VOL_UP);
        break;
    case  KEY_HID_TEST_5:
        log_info("KEY_HID_TEST_5");
        edr_hid_key_deal_test(USER_HID_VOL_DOWN);
        break;
    case  KEY_HID_TEST_6:
        log_info("KEY_HID_TEST_6");
        edr_hid_key_deal_test(USER_HID_FAST_FORWARD);
        break;
    case  KEY_HID_TEST_7:
        log_info("KEY_HID_TEST_7");
        edr_hid_key_deal_test(USER_HID_REWIND);
        break;
    case  KEY_HID_TEST_8:
        log_info("KEY_HID_TEST_8");
        // edr_hid_long_key_deal_test(USER_HID_IOS_HOME);
        break;
}
  1. 蓝牙发射器 蓝牙发射器(bt_emitter)相关.otl
  2. TWS 主从机相关 【金山文档】 TWS配对常见应用
    TWS配对常见应用.otl
  3. 蓝牙TWS自定义消息同步功能 该功能用于TWS连接后的消息交互处理
  4. 注册消息回调函数 使用以下函数注册
    image 示例:
#define USER_TWS_FUNC_ID_USER_INFO_SYNC   TWS_FUNC_ID('U', 'S', 'E', 'R') //自定义ID号
//回调函数
static void bt_tws_user_info_sync(void *_data, u16 len, bool rx)
{
    if (rx/*&& len==2*/) {
        u8 *data = (u8 *)_data;
        printf(">>>> tws sync DATA0:%d DATA1:%d\n",data[0],data[1]);
        
        switch(data[0]){
        case USER_TWS_VOL_SYNC:
            break;
        default:
            printf("unknow tws user sync\n");
            break;
        }

    }
}

//注册TWS同步信息
REGISTER_TWS_FUNC_STUB(app_led_mode_sync_stub) = //注册 app_led_mode_sync_stub 类
{
    .func_id = USER_TWS_FUNC_ID_USER_INFO_SYNC,//自定义ID号
    .func    = bt_tws_user_info_sync,//回调函数
};


  1. 发送自定义ID的消息 使用以下函数:
    image 示例:
//消息枚举表
 

//实例发送
        user_bt_tws_sync_msg_send(USER_TWS_VOL_SYNC,(u8)data);

  1. 开关主从自动切换接口: image

  2. 通话时切换左右耳的mic 通话状态下才能调用!!!!!!!!
    mic_switch_to_left(); //用左耳的mic
    mic_switch_to_right(); //用右耳的mic
    代码如下
    #define MIC_SWITCH_DELAY_MS (1000)
    extern void test_esco_role_switch(unsigned char);
    static int rs_timer = 0;
    void mic_switch(void *p)
    {​
    rs_timer = 0;
    test_esco_role_switch(1);
    ​}
    void mic_switch_to_left(void)
    {​
    if(rs_timer)
    {​
    g_printf("cancle prev mic switch\n");
    sys_timeout_del(rs_timer);
    rs_timer = 0;
    ​}
    if(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED){​
    if(tws_api_get_role() == TWS_ROLE_MASTER && tws_api_get_local_channel() == 'R'){​
    g_printf("mic_switch_to_left\n");
    rs_timer = sys_timeout_add(NULL, mic_switch, MIC_SWITCH_DELAY_MS);
    ​}
    ​}
    ​}
    void mic_switch_to_right(void)
    {​
    if(rs_timer)
    {​
    g_printf("cancle prev mic switch\n");
    sys_timeout_del(rs_timer);
    rs_timer = 0;
    ​}
    if(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED){​
    if(tws_api_get_role() == TWS_ROLE_MASTER && tws_api_get_local_channel() == 'L'){​
    g_printf("mic_switch_to_right\n");
    rs_timer = sys_timeout_add(NULL, mic_switch, MIC_SWITCH_DELAY_MS);
    ​}
    ​}
    ​}

  3. 打开TWS功能,如何实现不可发现可连接状态AC695/AC696

//把程序上调用以下函数的接口,的name传参改为 NULL,可以实现不可发现可连接状态
int tws_open_tws_wait_pair(u16 code, const char *name);
int tws_open_phone_wait_pair(u16 code, const char *name);
  1. 蓝牙电话本 【金山文档】 蓝牙电话本
    蓝牙电话本.otl

  2. PINCODE image 修改方法

  • AC695&AC696 音箱SDK
//开启pincode功能
extern void __set_simple_pair_flag(u8 flag); 
//添加位置bt_function_select_init下一行或者在bt_function_select_init中的最后一行
bt_function_select_init();
__set_simple_pair_flag(0);
//修改pincode默认值
const char *bt_get_pin_code()
{
    return "0250";
}

可视化SDK:

//开启pincode功能
void bt_set_simple_pair_flag(bool flag);
//添加位置bt_function_select_init下一行或者在bt_function_select_init中的最后一行
bt_function_select_init();
bt_set_simple_pair_flag(0);
//修改pincode默认值
const char *bt_get_pin_code()
{
    return "0250";
}

注意:
必须在协议栈配置bt_function_select_init接口中设置
imageimage

  1. 开启DUT模式
extern void bredr_set_dut_enble(u8 en, u8 phone); //en:开启   phone:手机是否能链接
bredr_set_dut_enble(1, 0);
  1. 回连 多个设备 如果需要支持上电回连多个设置需要把以下变量置
const u8 more_addr_reconnect_support = 1;  

//设置上电回连设备的数量最多9台设备(1~9)
__set_auto_conn_device_num(9);
  1. MAP方式获取安卓手机时间到样机 关键词:MAP、同步时间、安卓系统
    发布的SDK中有profile HFP协议,支持小机端获取手机的时间信息,但是HFP协议不能够获取安卓手机的时间,所以需要额外添加补丁支持profile MAP协议,通过获取安卓手机的通讯录获取时间。通常的应用在时钟音箱,用于连接蓝牙后的时间同步更新。

以下是各版本的补丁链接,下载后请仔细阅读文档内容。
【金山文档】 安卓手机同步时间补丁
安卓手机同步时间补丁.otl

耳机SDK获取手机时间:

  1. 定义以下宏:
#define  TCFG_BT_SUPPORT_MAP 0x1
  1. 在earphone.c加以下代码:
#if TCFG_BT_SUPPORT_MAP
#define PROFILE_CMD_TRY_AGAIN_LATER         -1004
void bt_get_time_date()
{
    int error = bt_cmd_prepare(USER_CTRL_HFP_GET_PHONE_DATE_TIME, 0, NULL);
    log_info(">>>>>error = %d\n", error);
    if (error == PROFILE_CMD_TRY_AGAIN_LATER) {
        sys_timeout_add(NULL, bt_get_time_date, 100);
    }
}
void phone_date_and_time_feedback(u8 *data, u16 len)
{
    log_info("time:%s ", data);
}
void map_get_time_data(char *time, int status)
{
    if (status == 0) {
        log_info("time:%s ", time);
    } else {
        log_info(">>>map get fail\n");
        sys_timeout_add(NULL, bt_get_time_date, 100);
    }
}
#endif
  1. 对应蓝牙事件bt_connction_status_event_handler里添加流程:
case BT_STATUS_RECONN_OR_CONN:
        log_info("++++++++ BT_STATUS_RECONN_OR_CONN +++++++++  \n");
        bt_cmd_prepare(USER_CTRL_MAP_READ_TIME, 0, NULL);
        break;
  1. 获取到时间: 必须同意才能获取的到手机时间(ios不用)
    image

image 5.目前支持的SDK:
可视化SDK: AC700N-demo 2.0.2 (patch 08)、AC701N 1.0.0 patch_05.31及以后
非可视化SDK: AC897N_AD697N_earphone_release_V2.4.1 、ad698n_earphone_release_v1.7.2、AC700N_earphone_release_V1.3.8、JL701n_earphone_release_v1.6.1
24. 样机连接、断开高级音频(SQ) 注意点:如果手机主动断开,样机是不能通过命令进行连接的
image eg. 695 310SDK

/*----------------------------------------------------------------------------*/
/**@brief  蓝牙  开关a2dp
   @param
   @return
   @note
*/
/*----------------------------------------------------------------------------*/
void bredr_a2dp_open_and_close()
{
    if (get_curr_channel_state() & A2DP_CH) {
        puts("start to disconnect a2dp ");
        user_send_cmd_prepare(USER_CTRL_DISCONN_A2DP, 0, NULL);
    } else {
        puts("start to connect a2dp ");
        user_send_cmd_prepare(USER_CTRL_CONN_A2DP, 0, NULL);
    }
}
  1. 广播音箱 先仔细阅读随SDK发布的:广播音箱开发文档,目前广播音箱通信是单向的
  2. 广播音箱配对 建议使用demo板级(不要用1tn板级),使能TCFG_BROADCAST_ENABLE
    按键消息:KEY_BROADCAST_SW
    备注:广播音响大部分连接不上,连接慢的情况都是开启了n个从机却没有主机导致
//按键消息执行的函数
int app_broadcast_switch(void)
{
    int temp_broadcast_hdl;
    if (!app_bt_hdl.init_ok) {
        return -1;
    }
//判断是否目前广播支持的模式
    if ((app_get_curr_task() == APP_BT_TASK) &&
        (get_call_status() != BT_CALL_HANGUP)) {
        return -1;
    }
    if ((app_get_curr_task() == APP_FM_TASK) ||
        (app_get_curr_task() == APP_PC_TASK) /*||
        (app_get_curr_task() == APP_MUSIC_TASK)*/) {
        return -1;
    }

    if (broadcast_hdl) {   //判断是否已经开启广播,是则关闭广播
        log_info("broadcast_close");
#if defined(RCSP_MODE) && RCSP_MODE
        ble_module_enable(1);
#endif
        tone_play_with_callback_by_name(tone_table[IDEX_TONE_BROADCAST_CLOSE], 1, broadcast_tone_play_end_callback, (void *)IDEX_TONE_BROADCAST_CLOSE);
        broadcast_close(broadcast_hdl);
        broadcast_hdl = 0;
        broadcast_status = APP_BROADCAST_STATUS_STOP;
    } else {
        log_info("broadcast_open");
#if defined(RCSP_MODE) && RCSP_MODE
        ble_module_enable(0);
#endif
        tone_play_with_callback_by_name(tone_table[IDEX_TONE_BROADCAST_OPEN], 1, broadcast_tone_play_end_callback, (void *)IDEX_TONE_BROADCAST_OPEN);
//重要部分,判断开启广播后是作为广播端,还是接收端,大部分连接不上,连接慢的情况都是开启了n个从机却没有主机导致
        if (is_broadcast_as_transmitter()) {
            temp_broadcast_hdl = broadcast_transmitter();
        } else {
            temp_broadcast_hdl = broadcast_receiver();
        }
        if (temp_broadcast_hdl < -1) {
            broadcast_hdl = 0;
        } else if (temp_broadcast_hdl >= 0) {
            broadcast_hdl = temp_broadcast_hdl;
            broadcast_status = APP_BROADCAST_STATUS_START;
        }
    }
    return 0;
}


程序开启广播后判断作为主机或者从机(默认程序,在弄清楚整个流程前不建议改)
广播音箱140之后的版本支持固定主从;

//蓝牙模式下,只有连接手机并且正在播歌的机器才作为广播端,否则是接收端   
//公版1.2.0_sdk如果作为主机的话,需要在开启广播前,本次开机连接过手机,播放过一次音频
 if ((app_get_curr_task() == APP_BT_TASK) &&
        (get_bt_connect_status() != BT_STATUS_WAITINT_CONN)) {
        /* if (get_a2dp_decoder_status()) { */
        /* if (get_a2dp_start_flag()) { */
        if ((a2dp_get_status() == BT_MUSIC_STATUS_STARTING) ||
            get_a2dp_decoder_status() ||
            get_a2dp_start_flag()) {
            return true;
        } else {
            return false;
        }
    }
//linein模式默认也是播放音频的设备为广播端
#if TCFG_LINEIN_ENABLE
    if (app_get_curr_task() == APP_LINEIN_TASK)  {
        if (linein_get_status() || config_broadcast_as_master) {
            return true;
        } else {
            return false;
        }
    }
#endif
//音乐模式默认也是播放音频的设备作为广播端
    if (app_get_curr_task() == APP_MUSIC_TASK) {
        if ((music_player_get_play_status() == FILE_DEC_STATUS_PLAY) || config_broadcast_as_master) {
            return true;
        } else {
            return false;
        }
    }

播放暂停歌曲广播切换逻辑
image 模式切换广播切换逻辑
image 2. 广播音箱基本函数功能以及使用

//宏定义:
#define BROADCAST_DATA_SYNC_EN      1   //广播状态同步,同步消息位置,可修改自定义发送消息
#define BROADCAST_TX_LOCAL_DEC_EN   1   //广播音频发送端是否解码发送的音频
#define BROADCAST_RECEIVER_CLOSE_EDR_CONN   0//广播从机关闭经典蓝牙连接
#define BROADCAST_FIXED_ROLE        0   //固定广播角色, 配0不固定角色,配1做发送端,配2做接收端
#define BROADCAST_TX_CHANNEL_SEPARATION     0   //发送端音频声道分离使能,要求发送端为双声道,接收端为单声道并且码率为发送端一半
#define BROADCAST_AUTO_SWITCH_ROLE  0   //播放和暂停自动切换发射和接收状态

//按键消息:
KEY_BROADCAST_SW       //广播音箱开启关闭消息,广播开启分主从机,主机广播音频,从机接收音频
KEY_WIRELESS_AUTH_ENTER  //广播配对,主机广播配对码,需要退出消息;从机接收配对码后自动退出;
KEY_WIRELESS_AUTH_EXIT   //广播配对退出

//基本函数:
is_broadcast_as_transmitter  //广播音箱主从机判断,可自行修改判断条件
live_audio_mode_setup(LIVE_AUX_CAPTURE_MODE, 48000, &wireless_aux_mode_ops);
//广播模式配置:wireless_aux_mode_ops:广播开启以及数据流capture配置

  1. 广播音箱声道配置 image

  2. 广播音箱1tn介绍(做无线麦使用) 先仔细阅读此文档
    【金山文档】 低延时1tN无线Linein音频传输功能说明
    低延时1tN无线Linein音频传输功能说明.pdf
    配对逻辑:
    image 此处以TX举例:
    配对码生成的位置在蓝牙底层库文件内,每次配对生成新的配对码

  3. 固定配对码

1.1.2.1_sdk

如果不希望生成新配对码,修改方法:

  1. 替换库文件 【金山文档】 btstack_701_1.2.1_配对补丁
    https://kdocs.cn/l/cv36MxUOnrzr
  2. 修改配对流程,修改为如果已经存在配对码则不生成新的配对码 修改位置:
    image
    extern void select_old_pri_ch(uint32_t old_pri_ch);
    u32 pair_code = 0;
    int  ret = syscfg_read(VM_WIRELESS_PAIR_CODE, &pair_code, sizeof(u32));
    printf("select_old_pri_chaaa == %x ret == %d\n",pair_code,ret);
    if (ret > 0 && pair_code != 0 && pair_code != 0xffffffff) {
        select_old_pri_ch(pair_code);
        printf("select_old_pri_ch == %x\n",pair_code);
    }

使用配对码位置:
image

2.1.3.0_sdk修改

【金山文档】 广播固定配对码修改
https://kdocs.cn/l/chGolp8SWgAj
替换所有文件后,配对前会先判断VM区是否有配对码存在,有则固定配对码
image 2. jl701n_soundbox_release_v1.3.01TN应用增加LLNS降噪算法 jl701n_soundbox_release_v1.3.01TN应用增加LLNS降噪算法
3. 实现AC701N 1TN形态自动配对需求实现 【金山文档】 jl701n_soundbox_release_v1.2.1_1TN_自动配对功能实现方式_20230904
jl701n_soundbox_release_v1.2.1_1TN_自动配对功能实现方式_20230904.rar

  1. 广播音箱音量同步以及自定义消息(TX->RX) 1.2.1得修改此处
    image

开启广播状态同步后,默认是做音量同步
image

广播端:
调用此消息即可,但一直会在广播
void user_status_sync()
{​
char data[6] = "11111"; //测试使用,无任何格式意义
wireless_dev_status_sync("big_tx", data, 6, NULL);//使用此函数会一直广播数据
​}

接收端:
image

//广播数据接收端  
printf("broadcast_rx_padv_data_callback == %s\n",buf);  
u8 test_buf[6];  
memcpy(test_buf, buf, 6);  
put_buf(test_buf,6);  
if(test_buf[0] == '1'){​  
    printf("dddddddddddddddddddddddd\n");  
    return;  
​}  

1.4.2版本sdk ,做1TN应用自定义同步数据
TX和RX都要打开广播状态同步宏使能
image 发送自定义数据的方式可以自行参考音量同步的做法和接收解析方式:
image 6. 广播音箱配对功能实现

  1. 通过修改配对码方式,适用于130以后SDK:
步骤:
1.主机调用:KEY_WIRELESS_AUTH_ENTER发送配对码
2.从机调用:KEY_WIRELESS_AUTH_ENTER接收配对码
3.主机调用:KEY_WIRELESS_AUTH_EXIT退出配对
4.从机可以直接调用:KEY_BROADCAST_SW开启广播从机;
5.主机链接手机播放歌曲后,调用KEY_BROADCAST_SW开启广播主机;
6.链接成功

配对码等会有打印的,进入配对状态以及最后广播使用的配对码都是可以修改的,可以根据打印的信息去跟下
最后使用到的位置,但配对码不能随意写,比如不能直接:0x11111111,需要符合底层的规定,建议直接
使用主机多次调用:KEY_WIRELESS_AUTH_ENTER,生成多个不同的配对码自行保存,用于配对码修改
  1. RX获取当前接收包的miss和err数 【金山文档】 btstack_701_1.3.0_get_miss
    https://kdocs.cn/l/coe9W8msBwdU
    imageimage

【金山文档 | WPS云文档】 btstack_701_142_sdk_get_miss
https://kdocs.cn/l/cbiehioBk7GG

【金山文档 | WPS云文档】 btstack_701_sdk141_sdk_get_miss
https://kdocs.cn/l/ccmxSCojXGgW

image

//报错解决
const char *bt_get_ble_name()
{
    printf("bt_cfg.ble_name == %s\n",bt_cfg.ble_name);
    return (const char *)(bt_cfg.ble_name);
}


//参考使用方式
u32 rx_buf[3] = {0};
extern void get_big_rx_condition(void *rx_info);
get_big_rx_condition(rx_buf);
printf("total:%d Miss:%d Err:%d\n",rx_buf[0],rx_buf[1],rx_buf[2]);
  1. AURACAST(杰理开发者平台SDK) 关于芯片选型,请优先仔细看此表格!!!
    补充:AC210N同样支持标准auracast功能,资源较JL709N少,降本方案可考虑;
    image

建议:通用的le_audio应用采用JL7094芯片去做;
JL7094开发参考文档:JL7094系列-入门到进阶开发指导.otl
私有的不需要与其他厂家手机等连接的,可考虑JL701N系列;
以下是代码端配置项:
功能开启,使能le_audio应用,角色固定和不固定看实际项目需求,其他项建议不修改:
image BIS参数配置,不了解配置项意义以及影响的情况下,不建议做修改,按照每个版本默认的配置进行使用,不用修改得跟下图一致;
image

代码使用接口说明:

APP_MSG_LE_BROADCAST_SW //程序参考使用消息,用于广播开关切换使用
app_auracast_switch();  //广播开关实际调用到的接口
app_auracast_open();    //广播开启api,未初始化前不能调用,详情见实际代码调用方式
is_auracast_as_source();
/*广播开机角色判断,可根据需求自行修改,比如程序默认是蓝牙播放歌曲情况下是主机,也可自行修改为比如链接手机的就是主机而不需要播放歌曲;大多数le-audio无法连接的问题都是开启了多个从机,但没有主机导致的,请先确定主从机问题正常后(开启广播会有log),还出现主从机无法连接的问题再反馈*/
app_auracast_sink_close();//广播接收关闭,详情见实际代码调用方式
app_auracast_source_close();//广播发送关闭,详情见实际代码调用方式

对外测试方式:

  1. JBL GO 4:GO4开启广播后,使用杰理平台打开从机后就能接受到GO 4端广播音频;(杰理平台做主机的话需要发JBL定制化的数据,可能存在法律风险,默认不支持杰理平台做主机去链接JBL从机)

  2. 三星 s23等支持auracast功能手机,此处以三星s23举例,在设置->蓝牙->auracast广播音频(蓝牙设置右上角三个点)->配置无密码广播;(无法打开auracast的话进开发者选项先打开le_audio功能)

  3. 加PA配置 以下这些系列IC的RX和TX口是固定的,硬件对正确后,软件调用使能函数bt_set_rxtx_status_enable(1)即可:

include_lib\btctrler\btcontroller_modules.h

/* --------------------------------------------------------------------------*/
/**
 * @brief bt_set_rxtx_status_enable
 *
 * @param en
 *
 *

                TX     RX
       AI800x   PA13   PA12
       AC692x   PA13   PA12
       AC693x   PA8    PA9
       AC695x   PA9    PA10
       AC696x   PC1    PC2  //! 代码上的注释是PA9/PA10有误,以这个为准
       AC694x   PB1    PB2
       AC697x   PC2    PC3
       AC631x   PA7    PA8

 */
/* ----------------------------------------------------------------------------*/
void bt_set_rxtx_status_enable(u8 en);

JL700X、JL701N、JL703N TX和RX口 可以映射到其他IO:

    bt_rf_PA_control_io_remap(IO_PORTB_06,IO_PORTB_07); //697/701N 有其他芯片可能没有这个   txen->PB6

    
    bt_set_rxtx_status_io(u32 tx_pin, u32 rx_pin);//br28(701) 可视化sdk 用这个api替代上述接口
    
    bt_set_rxtx_status_io(IO_PORTB_06,IO_PORTB_07); //700N

    bt_set_rxtx_status_enable(1);//695,696等

硬件:
image 28. 获取手机产商 case BT_STATUS_PHONE_MANUFACTURER:
log_info("BT_STATUS_PHONE_MANUFACTURER:%d\n", bt->value);
app_var.remote_dev_company = bt->value;
image

  1. HFP 通话协议

  2. 设置要保留hfp做电量显示,但不要蓝牙通话(参考设置) AC695X :
    对应接口:
    image

调用接口函数:

image 2. HFP TWS耳机 每次来电都在耳机端出声音,接听电话之后,从耳机出声音 关键字:通话 默认 【金山文档】 HFP TWS耳机 每次来电都在耳机端出声音的,接听电话之后,从耳机出声音
HFP TWS耳机 每次来电都在耳机端出声音的,接听电话之后,从耳机出声音.otl

3.通话时按键切换手机的输入输出方式为蓝牙或者手机

user_send_cmd_prepare(USER_CTRL_SCO_LINK, 0, NULL);

4.设置仅保留HFP做电量显示,通话时固定输入输出方式为手机,避免苹果手机HFP通话时,BT断连以及可以切换到耳机输出 问题

const int CONFIG_BTCTLER_FUN = EDR_LMP_SUPPORT_ESCO;    // 使能EDR_LMP_SUPPORT_ESCO

image

  1. 获取设备蓝牙名
  2. 把以下变量置1
const int CONFIG_LMP_NAME_REQ_ENABLE  =  1;
  1. void bredr_handle_register() 添加获取信息的回调
read_remote_name_handle_register(user_remote_name_hdl);
  1. 自定义user_remote_name_hdl函数
static void user_remote_name_hdl(u8 status, u8 *addr, u8 *name)
{
    printf("%s\n",__func__);
    put_buf(addr ,6);
    printf("name = %s\n",name);
}
  1. 发命令获取设备蓝牙名
user_send_cmd_prepare(USER_CTRL_READ_REMOTE_NAME, 6, user_addr);
//user_addr为设备蓝牙MAC
  1. 蓝牙库更新

AC690:

兼容性更新蓝牙库,版本:ac69_sdk_v2012_p4_opp,ac69_emitter_sdk_v107
【金山文档】 bluetooth_lib
https://kdocs.cn/l/cdU59qM1poJN
发射器使用这版:
bluetooth_lib-690发射器-20230228.zip

AC695:

兼容性修改,版本:AC695N_soundbox_sdk_release_3.1.0
emitter_btlib_V311_20240313-1418.zip
修改以下文件:

 #if TCFG_BLE_BRIDGE_EDR_ENALBE                                                                                                                                          
const int config_le_sm_sub_sc_enable = 1;            /*SC加密模式使能,need config_le_sm_support_enable = 1*/ const int config_le_sm_sub_sc_bridge_edr_enable = 1; /*SC加密模式下,ios app ble配对快连edr,need config_le_sm_sub_sc_enable = 1*/
 #else                         
const int config_le_sm_sub_sc_enable = 0;            /**/
const int config_le_sm_sub_sc_bridge_edr_enable = 0; /**/
#endif                        
                             
const int config_btstask_use_malloc = 1;

image u8 a2dp_support_delay_report =0;
image

小度音箱库文件更新:

AC696:修复多次唤醒断连问题
【金山文档】 dueros_stack-696v170 修复SPP拼包问题,支持配置是否支持电量显示
dueros_stack-696-v170-20250523.zip

// 电量显示 不支持:0, 对耳:2, 对耳 + 盒子:3, 单机:4
void dma_change_battery_structure(u8 flag);  //默认返回0

注:公版小度默认不开启电量显示回调。
image

AC695::修复多次唤醒断连问题
【金山文档】 dueros_stack-695-v310-修复spp拼包问题
dueros_stack-695-v310-修复spp拼包问题.zip

JL701N :修复多次唤醒断连问题
dueros_stack-AC701v142 修改SPP拼包问题.zip

  1. 修改PNP的PID和VID 要修改的是下图中的内容
    image 在apps\common\config\bt_profile_config.c添加数组
//定义的产品信息,for test
#define  PNP_VID_SOURCE   0x02
#define  PNP_VID          0x05ac //0x05d6
#define  PNP_PID          0x022C //
#define  PNP_PID_VERSION  0x011b //1.1.11

static const u8 sdp_pnp_service_data_hid[] = {
    0x36, 0x00, 0x34, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x0A, 0x09, 0x00, 0x01, 0x36, 0x00,
    0x03, 0x19, 0x12, 0x00, 0x09, 0x02, 0x00, 0x09, 0x01, 0x03, 0x09, 0x02, 0x01, 0x09, PNP_VID >> 8, PNP_VID & 0xFF,

    0x09, 0x02, 0x02, 0x09, PNP_PID >> 8, PNP_PID & 0xFF, 0x09, 0x02, 0x03, 0x09, PNP_PID_VERSION >> 8, PNP_PID_VERSION & 0xFF, 0x09, 0x02, 0x04, 0x28,
    0x01, 0x09, 0x02, 0x05, 0x09, 0x09, PNP_VID_SOURCE >> 8, PNP_VID_SOURCE & 0xFF, 0x00, 0x00
};

替换公版数组
image

FAQ

1.手机主动取消配对后,耳机不删除手机信息

image

2.蓝牙上电蓝牙回连时间修改

#define TIMEOUT_CONN_TIME             60 //超时断开之后回连的时间s
#define POWERON_AUTO_CONN_TIME        12  //开机去回连的时间

3.蓝牙打开1托2功能后,两台手机播放音乐按播放暂停进行切换操作注意事项

1. 目前设计不支持太快切换的,要有足够的数据包进行计数。故意测试打断功能时,两个手机操作应10秒以上。
- SDK提供数据包的阈值设置
/*高级音频打断检测数据包阈值设置*/
extern void __set_a2dp_sound_detect_counter(u8 sound_come, u8 sound_go);//默认 sound_come:70 sound_go:30 (单位都是数据包的个数)
//第一个参数是检测到有能量数据包的值,计数满了之后会进行打断,第二个参数就检测没有能量数据包的包数,计数满了之后会释放自己

4.蓝牙通话 输出方式选择:(选择不对可能通过算法不起作用)

image

f    aec_param->output_way = 1; //默认DAC有声音的方案,默认填0

5. 设置蓝牙加密的level

    ////设置蓝牙加密的level
    //io_capabilities ; /*0: Display only 1: Display YesNo 2: KeyboardOnly 3: NoInputNoOutput*/
    //authentication_requirements: 0:not protect  1 :protect
    __set_simple_pair_param(1, 0, 1);

6. 发送自定义AT指令示例

AC700N系列旧SDK(非可视化工具)

  1. lib_btctrler_config.c使能自定义AT命令功能 image
u8 user_at_cmd_send_support = 1;
  1. 定义自定义AT命令头和命令尾 image
#define USER_AT_CMD_HEAD "AT+USER="
#define USER_AT_CMD_TAIL "\r\0"
  1. 定义发送命令内容 参考示例如下:
    image
  2. 发送自定义AT命令 这样去发送
    image
sprintf(at_buf, "%s%d%s",USER_AT_CMD_HEAD, USER_AT_CMD_CALL_REJECT, USER_AT_CMD_TAIL);
user_send_at_cmd_prepare(at_buf, strlen(at_buf));
  1. 接收AT指令
int at_cmd_analysis_by_user(u8 *packet, u16 size)
{
    //puts(packet);
    return 0;
}

可视化版本

//发送
bt_cmd_prepare(USER_CTRL_HFP_SEND_USER_AT_CMD,len,data_ptr);
//接收
int at_cmd_analysis_by_user(u8 *addr, u8 *packet, u16 size) 
{
    return 0;
}

7.配置最大记忆的设备记录,默认是10(范围:0-10)

可视化SDK

void bt_set_max_remote_device_number(u8 number); 

非可视化SDK

void set_bt_remote_device_number(u8 remote_device_number); 

本文档为保密信息,未经授权,请勿转发或告知第三方。非常感谢!
This electronic documentation and any attachments are confidential and may be legally privileged or otherwise protected from disclosure. If you are not the intended recipient, please do not disclose the contents to anyone。
Thank you for your cooperation!
解析权归杰理所有!
The analysis right belongs to JieLi Technology Co., Ltd.

8.可视化SDK接收AT指令

int at_cmd_analysis_by_user(u8 *addr, u8 *packet, u16 size)
{​
puts(packet);
printf("lllllllllllsize == %d\n",size);
return 0;
​}

9. 蓝牙后台开启时,其他模式下播放音频,手机启动 a2dp 播放不返回蓝牙模式

方法一:后台丢包检测直接丢包。
测试 SDK :701 le audio v2.0.0 patch 02.14
修改接口(只贴出修改部分,接口内其他内容已省略):

void bt_background_resume(void) // 后台返回需要关闭能量检测重新打开 a2dp 链路
static void a2dp_slience_detect(void *_detect) // 后台能量检测直接丢包
#if TCFG_BACKGROUND_WITHOUT_EDR_CONNECT
    void *devices[2];
    if (btstack_get_conn_devices(devices, 2) < 1) {          //无设备连接才打开自动关机
        sys_auto_shut_down_enable();
    }
#else
    void *devices[2] = { 0 }; // 防止野指针
    u8 conn_num = btstack_get_conn_devices(devices, 2);
    if (conn_num < 1) {
        sys_auto_shut_down_enable();
    } else {
        for (int i = 0; i < conn_num; i++) {
            if (!devices[i]) {
                continue;
            }
            u8* addr = btstack_get_device_mac_addr(devices[i]);
            if (addr) {
                log_info("conn addr:");
                put_buf(addr, 6);
                extern u8 app_get_a2dp_play_status(void);
                if (app_get_a2dp_play_status()) {
                    set_g_play_addr(addr);
#if !TCFG_USER_TWS_ENABLE
                    a2dp_play_close(addr);
#else
                    tws_a2dp_player_close(addr);
#endif
                }
            } else {
                log_info("get addr fail");
            }
        }
    }
#endif

static void a2dp_slience_detect(void *_detect)
{
        /*
         * 不检测,一直丢包
         */
#if ((TCFG_A2DP_PREEMPTED_ENABLE == 0) && (TCFG_BT_DUAL_CONN_ENABLE))
#if (TCFG_BT_BACKGROUND_ENABLE)
#if !TCFG_USER_A2DP_PREEMPTED_RETURN // TCFG_USER_A2DP_PREEMPTED_RETURN = 1
        if (bt_background_active() == true)
#else
        if (bt_background_active() == false)
#endif
#endif
        {
            seqn += 10;
            if ((seqn & 0xffff) == 0) {
                seqn = 1;
            }
            a2dp_media_free_packet(detect->file, packet);
            break;
        }
#endif
}

方法二:断开 A2DP 链路

// 后台返回时重新连接
void bt_background_resume(void)
{
    if (g_bt_hdl.background.backmode == BACKGROUND_GOBACK_WITH_MODE_SWITCH) {
        if (tws_api_get_role() == TWS_ROLE_MASTER) {
            bt_cmd_prepare(USER_CTRL_AUTO_CONN_A2DP, 0, NULL);
        }
    }
}
// 后台挂起时断开
void bt_background_suspend()
{
    if (tws_api_get_role() == TWS_ROLE_MASTER) {
        bt_cmd_prepare(USER_CTRL_DISCONN_A2DP, 0, NULL);
    }
}

// 后台运行时手机断开连接时会自动连接 A2DP , 马上断开
static int bt_background_btstack_event_filter(struct bt_event *event)
{
    case BT_STATUS_CONN_A2DP_CH:
        if (tws_api_get_role() == TWS_ROLE_MASTER) {
            bt_cmd_prepare_for_addr(event->args, USER_CTRL_DISCONN_A2DP, 0, NULL);
        }
        break;
}

本文档包含以下子页面

  • 蓝牙电话本
  • 蓝牙core 6.0修改说明
  • 安卓手机同步时间补丁
  • 低延时1tN无线Linein音频传输功能说明
  • HFP TWS耳机 每次来电都在耳机端出声音的,接听电话之后,从耳机出声音
Prev
外设相关应用
Next
杰理蓝牙距离调试文档