为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板【淘宝链接:思度科技CSR开发板】。

技术交流QQ群号:743434463
开发板会员QQ群号:725398389(凭订单号入群,赠PPT、项目源码、视频教程)
——————————正文分割线———————————–

1. 引言

最近接到一个项目,需求是开发一个蓝牙音频网关,用来测试车机上的蓝牙模块的A2DP、HFP功能是否正常。

花了一个星期的时间完成了ADK4.0.0的source app的学习,又花了一星期的时间在CSR8670开发板上调通了原型。

2. 主要功能

BlueCar是一款入门级的蓝牙音频网关。他的主要功能如下:

  • 支持music模式(A2DP音频播放)
  • 支持voip模式(AGHFP语音双讲)
  • 支持一键模式切换
  • 支持串口通信
  • 支持连接特定蓝牙地址的从设备

系统框图如下:

3. 项目难点

项目软件基于ADK4.0.0的source app,其实现了基于USB通信的语音双讲功能,也可以播放USB源的音频。

在此基础上,项目需要实现如下功能:

  • 串口通信
  • 本地AUX源A2DP播放
  • 本地模拟输入输出的AGHFP双讲
  • A2DP播放和AGHFP双讲一键切换
  • 连接特定蓝牙地址的设备

3.1. 串口通信

详细步骤请参考我的另一篇博文CSR8670的UART功能的应用笔记。

有一个需要注意的地方,source.mak文件会在使能“wired input”工程配置后将transport口指定成none,这会导致程序运行后找不到uart sink。建议修改source.mak如下:

# Set transport make variable
ifneq (,$(findstring -DANALOGUE_INPUT_DEVICE,$(DEFS)))
#TRANSPORT=none               ===> 屏蔽这句话
else
TRANSPORT=usb_vm
endif

3.2. 本地AUX源A2DP播放

参考官方文档《ADK Audio Source Application User Guide》的章【3.1 Supporting Different Input Source Modes】,烧录source.psr和source_analog.psr即可。

3.3. 本地模拟输入输出的AGHFP双讲

这个功能比较难开发,因为需要打通模拟信号在CSR8670内部的整个音频通路,需要修改VM层,library层和kalimba DSP层的代码。

3.3.1. VM层

VM层代码需修改source.audio.c的audio_aghfp_connect函数,手动设置模拟mic参数,取消USB参数设置:

static void audio_ag_mic_params_init(common_mic_params* mic_params)
{mic_params->mic_a.digital = 0;mic_params->mic_a.bias = 1;mic_params->mic_a.gain = 15;mic_params->mic_a.pre_amp = 1;mic_params->mic_a.instance = 0;mic_params->mic_b.digital = 0;mic_params->mic_b.bias = 1;mic_params->mic_b.gain = 15;mic_params->mic_b.pre_amp = 1;mic_params->mic_b.instance = 0;
}void audio_aghfp_connect(Sink sink, bool esco, bool wbs, uint16 size_warp, uint16 *warp)
{uint16 i = 0;AudioPluginFeatures features = {0,0,0}; /* no stereo or i2s output */AUDIO_DEBUG(("AUDIO: audio_aghfp_connect\n"));/* start audio active timer */audio_start_active_timer();/* remove any A2DP audio */audio_a2dp_disconnect_all();/* init mic params */audio_ag_mic_params_init(&theSource->audio_data.ag_mic_params);#ifdef USB_AUDIO    theSource->audio_data.audio_aghfp_connect_params.mic = NULL;theSource->audio_data.audio_aghfp_connect_params.usb = &theSource->audio_data.ag_usb_params;
#elsetheSource->audio_data.audio_aghfp_connect_params.mic = &theSource->audio_data.ag_mic_params;theSource->audio_data.audio_aghfp_connect_params.usb = NULL;/* features.stereo = 1; */
#endiftheSource->audio_data.ag_usb_params.usb_source = usb_get_speaker_source(); /* Set the USB Source */theSource->audio_data.ag_usb_params.usb_sink = usb_get_mic_sink(); /* Set the USB Sink */for (i = 0; i < size_warp; i++){theSource->audio_data.audio_aghfp_connect_params.warp[i] = warp[i];}if (theSource->audio_data.audio_routed == AUDIO_ROUTED_NONE){               theSource->audio_data.audio_routed = AUDIO_ROUTED_AGHFP;AudioConnect(audio_aghfp_get_plugin(wbs),sink, esco ? AUDIO_SINK_ESCO : AUDIO_SINK_SCO,theSource->codec,/*aghfp_gain*/10, 8000,features ,                        /* no stereo or I2S output required */volume_get_mute_mode(),AUDIO_ROUTE_INTERNAL,/*power*/0, &theSource->audio_data.audio_aghfp_connect_params,
}

3.3.2. library层

找到C:\ADK4.0.0\src\lib\csr_ag_audio_plugin\csr_ag_audio.c文件,修改CsrAgAudioPluginConnect以设置ADC、DAC采样率:

   /* Send warp values to DSP */KalimbaSendMessage(MESSAGE_SEND_WARP, CSR_AG_AUDIO->warp[0], CSR_AG_AUDIO->warp[1], CSR_AG_AUDIO->warp[2], CSR_AG_AUDIO->warp[3]);/* 设置Kalimba DSP的ADC,DAC采样率 */KalimbaSendMessage(MESSAGE_SET_DAC_SAMPLE_RATE, CSR_AG_AUDIO->dac_rate/10, 0,0,0);/* Connect audio */ConnectAudio (task, CSR_AG_AUDIO->stereo) ;SetAudioBusy(NULL);

修改ConnectAudio函数以支持双通道DAC输出:

/* Connect Ports to DSP */
r2 = (bool) StreamConnect(StreamKalimbaSource(DSP_TO_DAC_L_PORT),speaker_snk);   /* DSP->DAC *//* 初始化右通道DAC */
spkr_sink_b = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_B);
PanicFalse(SinkConfigure(spkr_sink_b, STREAM_CODEC_OUTPUT_RATE, CSR_AG_AUDIO->dac_rate));
SinkSynchronise(speaker_snk,spkr_sink_b);
r3 = (bool) StreamConnect(StreamKalimbaSource(DSP_TO_DAC_R_PORT),spkr_sink_b);   /* DSP->DAC *//* 设置硬件DAC增益到最大 */
PanicFalse( SinkConfigure(speaker_snk, STREAM_CODEC_OUTPUT_GAIN, 15) );
PanicFalse( SinkConfigure(spkr_sink_b, STREAM_CODEC_OUTPUT_GAIN, 15) );

3.3.3. Kalimba DSP层

打开C:\ADK4.0.0\kalimba\apps\one_mic_example_bluecar\usb_dongle_48_to_8k_stereo.xip文件,修改工程配置如下:

   <property key="defines" >uses_48_to_8kHz,DEBUG_LATE_WRITE</property><property key="hardware" >0</property><property key="libs" >core,frame_sync,cbops_multirate,sbc_wbs, plc100,math,cvc_modules,cvc_system,spi_comm</property>

在去掉了宏定义USB_DONGLE,STEREO_USB_INPUT后,编译出来的kalimba DSP烧录文件支持模拟输入输出。在编译过程中会提示不能识别某些函数名称,此时需添加cvc_modules,cvc_system,spi_comm这三个库文件,因为HFP里面用到了cvc库里的一些模块。

3.4. A2DP播放和AGHFP双讲一键切换

Source app支持music模式和voip模式,正好对应了A2DP播放和AGHFP双讲这两个功能。Source app也提供了audio_switch_voip_music_mode函数以支持在这两个模式间切换。这里需要注意的是,在切换之前一定要先挂起当前所有连接,否则会在从voip模式切换到music模式时系统崩溃。示例代码如下:

/* 挂起aghfp音频 */
aghfp_suspend_all_audio();    /* 挂起a2dp音频 */
a2dp_suspend_all_audio();/* 切换模式 */
if (data[1] == AUDIO_VOIP_MODE)
{audio_switch_voip_music_mode(AUDIO_VOIP_MODE);
}
else
{audio_switch_voip_music_mode(AUDIO_MUSIC_MODE);
}

3.5. 连接特定蓝牙地址的设备

Source app支持开机后直连特定蓝牙地址的设备,但不支持运行时动态修改。其实我们只需要将开机时直连的地址强制覆盖即可。参考代码如下:

/* 保存串口接收到的MAC地址 */
addr.nap = (((uint16_t)data[1]) << 8)|((uint16_t)data[2]);
addr.uap = data[3];
addr.lap = (((uint32_t)data[4]) << 16)|(((uint32_t)data[5]) << 8)|((uint32_t)data[6]);UART_DEBUG(("UART: Page nap[%x], uap[%x], lap[%lx]\n", addr.nap, addr.uap, addr.lap));        /* 更新开机直连的目标设备地址 */
theSource->ps_config->bdaddr_remote_device = addr;
connection_mgr_set_remote_device(&addr);/* 串口反馈消息 */
uart_send_msg(BLUECAR_UART_CMD_ID_HOST_COMMAND_EXTEND, data, 7);

在设置地址成功后,令CSR8670进入page状态,即可与指定蓝牙地址设备建立连接。

4. 总结

蓝牙音频网关项目一个深度开发Source app的成功案例。需要深刻理解CSR8670软硬件的运作机理,并能灵活运用并修改VM、library、kalimba DSP的源码。

BlueCar蓝牙音频网关的应用场景十分广阔,可以简单升级成蓝牙对讲机、车咪等实用产品。

CSR8670项目实战:BlueCar蓝牙音频网关相关推荐

  1. CSR8670项目实战:BluePager蓝牙寻呼机

    为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板[淘宝链接:思度科技CSR开发板]. 技术交流QQ群号:743434463 开发板会员QQ群号:725398389(凭订单号入 ...

  2. CSR8670项目实战:BlueDongle 蓝牙音频测试dongle

    为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板[思度科技CSR开发板]. 技术交流QQ群号:743434463 开发板会员QQ群号:725398389(凭订单号入群,赠PP ...

  3. CSR8670项目实战:4人组网蓝牙对讲耳机

    为了方便大家学习,现与我爱蓝牙网联合推出[QCC300x/CSR867x/QCC30xx/QCC51xx开发板]. 博主联系方式:Call-15715161220,QQ-705829339 技术交流Q ...

  4. CSR8670项目实战:BlueHeartSound电子心音计

    为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板[淘宝链接:思度科技CSR开发板]. 技术交流QQ群号:743434463 开发板会员QQ群号:725398389(凭订单号入 ...

  5. CSR8670项目实战:BlueHeartSound2电子心音计

    为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板[思度科技CSR开发板]. 技术交流QQ群号:743434463 开发板会员QQ群号:725398389(凭订单号入群,赠PP ...

  6. CSR8670项目实战:BlueHeart心率监测耳机

    为了让CSR867x的开发更容易,现与思度科技联合推出CSR867x学习板[淘宝链接:思度科技CSR开发板]. 技术交流QQ群号:743434463 开发板会员QQ群号:725398389(凭订单号入 ...

  7. CSR8670项目实战:BlueAgBatC蓝牙发射器BLE遥控器

    为了方便大家学习,现与我爱蓝牙网联合推出[QCC300x/CSR867x/QCC30xx/QCC51xx开发板]. ⭐⭐⭐⭐⭐[本项目为客户项目,欢迎商务合作]⭐⭐⭐⭐⭐ 技术交流QQ群号:10330 ...

  8. 基于QT平台的手持媒体播放器项目实战视频教程下载

    分享一套关于在QT平台的手持媒体播放器项目实战的视频教程,Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架. 它既可以开发GUI程式,也可用于开发非GUI程式,比如控制台工 ...

  9. 【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置(2)

    [.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) 原文:[.NET Core项目实战-统一认证平台]第四章 网关篇-数据库存储配置(2) [.NET Core项目实战- ...

最新文章

  1. Mybatis + SpringMVC + Maven实现分页查询
  2. pytorch加载预训练模型_Pytorch-Transformers 1.0发布,支持六个预训练框架,含27个预训练模型...
  3. 【资料】wpcap.dll/Packet.dll库中相应函数
  4. [云炬创业基础笔记]第五章创业机会评估测试4
  5. C语言三种常见排序算法
  6. 电脑维修:电脑维修必备工具整理
  7. Fast Paxos
  8. 突然听到一只公鸡的局域网聊天软件
  9. Python+matplotlib自定义坐标轴位置、颜色、箭头
  10. vant-ui的list
  11. 简短的计算机病毒,最简单的电脑病毒
  12. mysql yum 安装
  13. Excel合并两列数据到一列中并以逗号隔开的处理方式
  14. WMI服务是什么?Windows 7系统如何禁用WMI服务?
  15. 实验室管理系统[LIS],powerbuilder12.6开发,SQLSERVER2008数据库
  16. Java面试题(大内)3
  17. KBEngine warring项目源码阅读(一) 项目简介和注册
  18. Django mako 的使用(七)
  19. 同学用javascript写好了论坛自动灌水机。
  20. 20.Spring学习笔记_基于配置文件的方式来配置 AOP(by尚硅谷_佟刚)

热门文章

  1. java 定义map集合_Java中的Map集合
  2. 户外导航软件OruxMaps及其相关地图资源_我是亲民_新浪博客
  3. python模拟浏览器请求
  4. php解决m3u8卡顿,m3u8直播源为什么移动很流畅,电信很卡
  5. 物联网——光控灯的实现
  6. APP客服系统搭建,手机APP如何接入在线客服系统?
  7. 米兔积木机器人与履带机甲零件差别_米兔积木机器人履带机甲
  8. 宝安区-西乡街道-各社区-住宅小区信息
  9. 如何理解梯度下降算法
  10. display方法php,thinkphp 控制器中 display()步骤实现的原理