跳转至

低延时音箱SDK开发手册


快速上手指南

概述

文档目的

本文档完整描述了SDK常用的配置、 使用及调试方法,供用户快速上手,并解决实际开发过程中所遇到的绝大多数问题。

术语说明

TBD

硬件相关

硬件框图

TLSR9517CBAR56D_c1T253A91 (TX):

TX硬件框图

TLSR9517CDK56D_c1T253A20 (RX):

RX硬件框图

EVB开发板

TX端使用开发板型号:

TLSR9517CBAR56D_c1T253A91

如图:

TX开发板

开发板名称:

Soundbar 6p1 EVB对外售卖名称为TLSR9517CBAR56D,客户以此名字提交订单进行采购;

Soundbar 6p1 EVB在板子上有串号进行版本区分,如下图是V1.1版本的串号。 Soundbar 6p1 EVB最新版本是V1.1。

TX开发板版本号

RX端使用开发板型号:

TLSR9517CDK56D_c1T253A20

如图:

RX开发板

开发板名称:

Single-end Audio EVB对外售卖名称为TLSR9517CDK56D,客户以此名字提交订单进行采购;

Single-end Audio EVB在板子上有串号进行版本区分,如下图是V1.3版本的串号。 Single-end Audio EVB最新版本是V1.3。

RX开发板版本号

开发板具体细节可参考wiki:

TLSR9517CBAR56D:

http://wiki.telink-semi.cn/doc/hw/B91_Soundbar_DevelopmentBoard_TLSR9517CBAR56D.zip

TLSR9517CDK56D:

http://wiki.telink-semi.cn/doc/hw/B91_Audio_DevelopmentBoard_TLSR9517CDK56D.zip

注意

  • TLSR9517CBAR56D作为音频发送端TX;
  • 一对一情况时,TLSR9517CDK56D作为低音SUB;
  • 一对三情况时,TLSR9517CDK56D需要三块,分别作为左环绕SODL,右环绕SODR,低音SUB。

说明

LED指示说明

TX端:

LED灯_TX

D7: main loop指示灯,500ms闪烁一次,如果持续闪烁代表正常。

D2: 连接指示灯,常亮代表所有rx设备都连接上。(最多可连接三个rx设备)

主芯片 D1, 从芯片D4 D5 D6: 工作指示灯,闪烁代表从芯片工作正常。

RX端:

LED灯_RX

D1: 常亮代表rx设备上电初始化工作正常。

D2: main loop指示灯,500ms闪烁一次,如果持续闪烁代表正常。

D3 & D4: 代表连接状态,D4亮D3灭代表连接正常,D4灭D3灯亮代表断连。

D5: 代表充电状态指示灯。(目前程序上电会默认常亮)

按键功能介绍

TX端:

按键_TX

Sw1: 硬件复位。

Sw2: 短按,切换APP mode,由App1 切到App2。

Sw3: 短按,进入配对模式,持续10s。长按(hold按键),删除所有设备配对记录,并进入配对模式,持续3s。

Sw4: 短按,mute。短按两次, unmute。

RX端:

按键_RX

Sw8: 短按,切换APP mode,由App1 切到App2。

Sw9: 短按,进入配对模式,持续10s。长按(hold按键),删除所有设备配对记录,并进入配对模式,持续3s。

Sw10: 短按,切换audio chn(chn 0,1,2;chn0 sodl,chn1 sodr,chn2 sub)。

Sw11: 硬件复位。

Demo 运⾏(以4p1_16bit为例)

连接方式

(1) LINEIN_LINEOUT

该连接方式仅限用于通路测试,不得用于音频性能测试;

LINEIN_LINEOUT

LINEIN_LINEOUT2

(2) I2SIN_LINEOUT 该连接方式仅限用于通路测试,不得用于音频性能测试;

I2SIN_LINEOUT

I2SIN_LINEOUT2

(3) I2SIN_I2SOUT 该连接方式贴合实际应用方式,一般用于音频指标测试。

I2SIN_I2SOUT

TX:

I2SIN_I2SOUT_TX

RX:

I2SIN_I2SOUT_RX

硬件准备

需要一块TLSR9517CBAR56D EVB 板,三块 TLSR9517CDK56D EVB 板,四根USB线。

编译SDK

(1) 导入

首先打开Andesight IDE,会弹出选择workspace的对话框,点击“Browser”选择一个目录作为你的workspace。可以选择任意的目录作为workspace目录。

选择workspace

选择File -> Import,如下图所示:

导入工程

在弹出的窗口中,点击General,选择Existing Projects into Workspace。

导入工程

在Select root directory框中输入SDK所在路径,或直接点击Browser,选择SDK所在的目录,接着勾选SDK,点击Finish,即可导入工程(注:建议IDE工作路径和SDK源码所在路径做区分,便于多个工程打开)。

导入工程

(2) 编译

在编译工程前,需要先点中相应的工程,并首先编译_proj_boot_device_和_proj_boot_dongle_两个工程,用于后续生成合并固件。

注意

  • 首次编译时,必须先编译两个boot工程,再编译项目工程,否则会报错。

boot工程

配置:

如果使用I2SIN_LINEOUT模式,需要将Tx APP配置文件中的AUDIO_INTERFACE宏定义设置为AUDIO_I2S_GPIO,需要将Rx APP配置文件中的AUDIO_INTERFACE宏定义设置为AUDIO_I2S_CODEC,默认为I2S_IN和I2S_OUT。

vendor/_proj_soundbar_tx_/app_config.h

配置TX

vendor/_proj_soundbar_rx_/app_config.h

配置RX

如果想配置设备连接数,可以通过vendor/_proj_soundbar_tx_/app_config.hvendor/_proj_soundbar_rx_/app_config.h中的宏DEVICE_CONNECT_NUM来修改,默认值为3,可选1、2、3。

再编译11(TX_4P1_16bit)、12(RX_SOD_16bit)和 14(RX_SUB_16bit)工程。

编译工程

软件烧录

一块TLSR9517CBAR56D 作为TX,烧录_img_proj_low_latency_soundbar_4p1_tx_.bin文件

一块TLSR9517CDK56D 作为SUB,烧录_img_proj_low_latency_soundbar_rx_sub_.bin文件

两块TLSR9517CDK56D 作为SOD,分别为SODL、SODR(通过配置文件区分),烧录_img_proj_low_latency_soundbar _rx_.bin文件

固件在 output ⽬录,烧录步骤如下:

Step 1: 准备Telink烧录器,按照下图所示接法。

TX (TLSR9517CBAR56D):

TX烧录接线

RX (TLSR9517CDK56D):

RX烧录接线

Step 2: 打开 Telink BDT.exe 程序。

BDT界面

Step 3: 点击 Activate。

BDT_Activate

Step 4: 固件、配置文件、MAC烧录。

配置文件

DEVICE_CONNECT_NUM为1

RX配置文件选择:

config_bar_telink_rx1.bin

DEVICE_CONNECT_NUM为2

RX配置文件选择:

config_bar_telink_rx1.bin

config_bar_telink_rx2.bin

DEVICE_CONNECT_NUM为3

RX配置文件选择:

config_bar_telink_rx1.bin

config_bar_telink_rx2.bin

config_bar_telink_rx3.bin

BDT下载配置

上图展示了对应的bin烧录地址:

在固件地址(0x00000000)、配置文件地址(0x000fc000)下分别烧录对应文件。

BT MAC地址(0x000ff000)写入MAC。

其他注意事项:

- 在MAC地址填写值的时候,务必确保每个模组的唯一性,且不要烧录全ff或全0的地址;
- 以上烧录地址的Flash Size默认是1M大小,若Flash Size为2M,那么固件地址(0x00000000)、配置文件地址(0x001fc000)、BT MAC地址(0x001ff000)。

配对操作流程

Step 1: 各EVB上电;

Step 2: TX端接入输入信号;

Step 3: RX(左环绕SODL,右环绕SODR,低音SUB)、TX端依次点击配对按钮;

Step 4: 待配对成功,各RX端音频接口即可收到对应数据。

配对成功显示

QA

(1) 使用I2SIN_LINEOUT连接方式搭建Demo Rx无声问题 我们在使用I2SIN_LINEOUT连接方式搭建Demo时,会使用支持多通道输出的HDMI转I2S的转接板作为音源,此时可能会遇到某个Rx无声的情况,我们需要进行多声道配置。

Window10:

(a) 将转接板接入PC,打开声音设置:

声音设置

(b) 选择对应设备,单击设备属性:

设备属性

(c) 修改空间音效格式:

空间音效格式

Window11:

(a) 将转接板接入PC,然后右键点击任务栏的喇叭图标,选择声音设置:

声音设置2

(b) 在声音设置界面中,点击“更多声音设置”:

更多声音设置win11

(c) 右键点击对应的播放设备,点击“配置扬声器”:

选择播放设备

(d) 在配置界面中,选择“5.1环绕”,然后按照向导的提示完成配置:

配置扬声器

SDK简介

概述

Soundbar SDK根据功能一般分为收发两端,下面简称为TX、RX。

TX是信号采样端,信号通过I2S信号或Line-in采集之后经过压缩/编码,通过2.4GHz无线信号进行数据发送,以b91_ll_soundbar_sdk为例,对应的工程有:

_proj_low_latency_soundbar_0p1_sub_24_tx_
_proj_low_latency_soundbar_0p1_sub_tx_
_proj_low_latency_soundbar_2p0_stereo_24_tx_
_proj_low_latency_soundbar_2p0_stereo_tx_
_proj_low_latency_soundbar_2p1_24_tx_
_proj_low_latency_soundbar_2p1_tx_
_proj_low_latency_soundbar_4p1_24_tx_
_proj_low_latency_soundbar_4p1_tx_

RX是通过2.4GHz信号接收TX端发送过来的数据,对数据解码/解压,通过I2S信号或Line-out输出音频,以b91_ll_soundbar_sdk为例,对应的工程有:

_proj_low_latency_soundbar_rx_
_proj_low_latency_soundbar_rx_24_
_proj_low_latency_soundbar_rx_sub_
_proj_low_latency_soundbar_rx_sub_24_

软件组织架构

在IDE中导⼊SDK⼯程后,显⽰的⽂件组织结构如下图所⽰。顶层⽂件夹有8个:application、boot、codec、common、drivers、output、proj_lib、vendor。

软件组织结构

application: 提供一些通用的应用处理程序,如print、keyboard等。

boot: 存放cstartup_9518.S文件。 cstartup_9518.S: 完成retention_reset、aes_data、retention_data、ramcode、data、sbss、bss、stack的初始化和搬移拷贝,flash初始化,中断向量的入口,一些需要写成汇编的函数。

codec: 编解码相关算法,例如filter、resample等。

common: 提供一些通用的跨平台的处理函数,如内存处理函数、字符串处理函数等。

drivers: 提供与MCU紧密相关的硬件设置和外设驱动程序,如clock、flash、I2C、USB、GPIO、UART等。

output: 工程编译输出目录。

proj_lib: 存放SDK运行所必需的库文件(如 libB91_driver_dm.a)。RF驱动、PM驱动等文件,被封装在库文件里,用户无法看到源文件。

vendor: 用于存放用户应用层代码。

bootlink: 是内存布局文件,里面描述了不同代码section,放在Flash、I-SRAM、D-SRAM里的情况。

boot.link: _proj_boot_xx项目对应的bootlink。

boot-36k.link: vendor下的项目对应bootlink差异是SRAM和对应flash的地址偏移了0x9000(36k)。

main.c

包括 main 函数⼊⼝,系统初始化的相关函数,以及⽆限循环 while(1) 的写法,建议不要对此⽂件进⾏任何修改,直接使⽤固有写法(已省略部分不重要的代码)。

int main(void)
{
    blc_pm_select_internal_32k_crystal();

    sys_init(DCDC_1P4_LDO_1P8,VBAT_MAX_VALUE_GREATER_THAN_3V6);
    async.power_on_tick = (u32)stimer_get_tick;
    clock_init(PLL_CLK_192M, PAD_PLL_DIV, PLL_DIV2_TO_CCLK, CCLK_DIV2_TO_HCLK, HCLK_DIV2_TO_PCLK, PLL_DIV4_TO_MSPI_CLK);
    gpio_init(1);

    async_readFlashSize_autoConfigCustomFlashSector();

    user_init_normal();

    while(1)
    {
        main_loop();
    }
    return 0;
}

配置文件

(1) app_config.h

应用功能配置⽂件,⽤于对整个系统的应用功能参数进⾏配置,包括board选择、USB相关功能、音频输入输出功能、算法相关功能的配置。

后⾯介绍各个模块时会对配置文件中的各个参数的含义进⾏详细说明。

BootLoader介绍

包括TX和RX的BootLoader工程,分别是_proj_boot_dongle_和_proj_boot_device_,上电后会检测APP固件完整性并跳转到APP执行,在APP固件里也可以通过调用函数进入BootLoader来进行OTA操作。OTA的操作方法可查看OTA小节。

SDK概述

b91_ll_soundbar_sdk支持1对1(1低音)/1对2(2全频段)/1对3(2全频段+1低音), 三种形态,具有延时低,抗干扰强等特点,有效使用距离和产品形态、传输次数有关,需根据具体产品实际测试。典型的1对3音频性能如下:

16bit I2S输入输出:19.29ms(LC3+、私有编解码),频响20 ~ 20kHz,THD+N低至0.05%,SNR达到90dB。

24bit I2S输入输出:19.90ms(LC3+、私有编解码),频响20 ~ 20kHz,THD+N低至0.05%,SNR达到90dB。

SDK给用户提供了八个工程demo,如下:

SDK Demo

SDK功能介绍

TX端具体的功能如下:

(1) 支持的应用相关功能:

(a) USB模块:USB HID、USB Debug;
(b) 看门狗模块;
(c) 算法模块:包括EQ、降噪算法、重采样算法;
(d) OTA模块;
(e) EMI模块:支持EMI测试指令;
(f) 2.4GHz模块:RF相关:2.4GHz Tx、发射功率自适应、跳频;无线相关:手动配对、回连、自动配对。

(2) 支持的音频相关功能:

(a) 编码:低音SUB chn用的是私有算法编码,全频段SOD chn用的是LC3+编码;
(b) 音频输入:Line-in、I2S。

(3) 支持的UI相关功能:

(a) KEY:短按、长按、双击;
(b) LED;

RX端UI功能同TX端,其他功能如下:

(1) 支持的应用相关功能:

(a) USB模块:USB HID、USB Debug;
(b) 看门狗模块;
(c) OTA模块:OTA升级;
(d) EMI模块:支持EMI定频测试;
(e) 2.4GHz模块:RF相关:2.4GHz Rx、跳频、收包纠错;无线相关:手动配对、回连、自动配对、一对一、一对二、一对三、一对三同时。

(2) 支持的音频相关功能:

(a) 编码:低音SUB chn用的是私有算法编码,全频段SOD chn用的是LC3+编码;
(b) 音频输出:本地Line-out、I2S。

注意

  • 某些音频编解码器的版税:

    • 此SDK包括多种音频编解码器的选项,需要注意的是,使用某些编解码器可能会产生版权费用。最终产品制造商有责任与许可所有者签订许可协议并支付版权费用。作为IC提供商的Telink无法承担这些费用。
    • 使用LC3+编解码器:如果您选择使用LC3+编解码器,请联系Fraunhofer/Ericsson(Fraunhofer IIS:lc3-licensing@iis.fraunhofer.de 和 Ericsson:lc3.licensing@ericsson.com)以获得适当的许可协议和版权费用信息。这些许可所有者对采用LC3+编解码器的产品收取固定费用。版权费用是公开透明的,按设备收费(例如耳机、电视、盒子等)。
    • 使用LC3编解码器:只有被蓝牙SIG认证为蓝牙产品的产品才可以免费使用LC3编解码器。如果您的产品未经蓝牙认证且选择使用LC3编解码器,请联系Fraunhofer/Ericsson(Fraunhofer IIS:lc3-licensing@iis.fraunhofer.de 和 Ericsson:lc3.licensing@ericsson.com)以获得适当的许可协议和版权费用信息。这些许可所有者对非蓝牙产品采用LC3编解码器收取固定费用。版权费用是公开透明的,按设备收费(例如耳机、电视、盒子等)。

关键宏介绍

SDK很多功能都是通过宏开关控制。下面简单介绍app_config.h.

(1) 自动配置项

通过编译工程的对应宏去切换的配置项

BOARD_CHIP_NUM:

作用说明:TX的芯片数量;

AUDIO_BIT_WIDTH_24:

作用说明:Audio算法及通路的bit位深选择;

ALGORITHM_BIT_WIDTH_24:

作用说明:Audio算法的位深选择;

ASRC_ALGORITHM_24:

作用说明:ASRC算法位深选择;

PCM_MAX_LEN:

作用说明:算法数据buff大小;

(2) Board及GPIO相关配置

BOARD_MODEL:

默认值:BOARD_ADK_80D;

作用说明:设置Board;

备注:目前支持两种Board: BOARD_ADK_80D(c91T213A20_V2_2_20210908)、BOARD_BAR_56D(c1T253A91 _V1_1_20210909)。

RST_PIN_S1:

作用说明:从芯片1 reset引脚;

RST_PIN_S2:

作用说明:从芯片2 reset引脚;

RST_PIN_S3:

作用说明:从芯片3 reset引脚;

SW2:

作用说明:按键2 引脚;

SW3:

作用说明:按键3 引脚;

SW4:

作用说明:按键4 引脚;

MASTER_SYNC_PIN:

作用说明:主芯片同步 引脚;

SLAVE_SYNC_PIN:

作用说明: 从芯片同步 引脚;

MASTER_ROLE_PIN:

作用说明:识别主芯片引脚;

LED_GREEN:

作用说明:green led引脚;

LED_BLUE:

作用说明:blue led引脚;

LED_RED:

作用说明:red led引脚;

(3) UI配置

UI_LED_ENABLE:

默认值:1;

作用说明:使能SDK LED指示UI;

UI_KEY_ENABLE:

默认值:1;

作用说明:使能SDK按键UI;

SWIRE_DEF_ID:

默认值:0;

作用说明:swire默认id;

SLV1_ID:

默认值:1;

作用说明:从芯片1 swire id;

SLV2_ID:

默认值:2;

作用说明:从芯片2 swire id;

SLV3_ID:

默认值:3;

作用说明:从芯片3 swire id;

SWIRE_SPEED:

默认值:16000000;

作用说明:swire传输速率;

SWM_CLK:

默认值:8000000 //8MHz;

作用说明:swire clk速率;

DEVICE_CONNECT_NUM:

默认值:3;可选1、2、3.

作用说明: 设备可连接数;

ALL_PAIR_TOGETHER:

默认值:0;

作用说明:SODL、SODR、SUB同时配对使能;

WATCHDOG_ENABLE:

默认值:1;

作用说明:看门狗使能;

SOFTWARE_PA_ENABLE:

默认值:0;

作用说明:PA 使能;

AUDIO_I2S_CODEC:

作用说明:Audio驱动模式 codec,输入输出接口为line in、lineout;

AUDIO_I2S_GPIO:

作用说明:Audio驱动模式 gpio,输入输出接口为i2s in、i2s out;

RSSI_CHECK_MECHANISM:

默认值:1;

作用说明:RSSI检查机制;

NEW_ACCESS_CODE_ALGORITHM:

默认值:1;

作用说明:使用新的access code算法;

UI_UART_ENABLE:

默认值:0;

作用说明:uart SDK功能使能;

UI_I2C_SLAVE_ENABLE:

默认值:1;

作用说明:I2C SDK功能使能;

UI_I2C_OTA_ENABLE:

默认值:1;

作用说明:I2C OTA使能;

APP_REGISTER_I2C_IRQ:

默认值:1;

作用说明:I2C中断使能;

UI_I2C_STRETCH:

默认值:1;

作用说明:I2C strech使能;

I2C_CMD_PAIRING_EN:

默认值:1;

作用说明:I2C 指令配对使能;

I2C_CLEAR_PAIR_INFO_EN:

默认值:1;

作用说明:I2C 清除配对信息指令使能;

UI_UART_REPORT_EVENT:

默认值:1;

作用说明: 串口上报事件使能;

UART0_DMA_CHANNEL_TX:

默认值:DMA4;

作用说明: 配置UART0 DMA channel;

UART0_BAUDRATE:

默认值:115200;

作用说明: 串口上报波特率;

UART_SYNC_HEADER:

默认值:0x5A;

作用说明: 串口同步头;

DEBUG_GPIO_ENABLE:

默认值:0;

作用说明:GPIO调试使能;

Audio配置

TWS_MIC_FIFO_SIZE:

默认值:1024;

作用说明:MIC BUFFER大小;

TWS_PLAY_FIFO_SIZE:

默认值:1024;

作用说明:PLAYBACK BUFFER大小;

AUDIO_INTERFACE:

作用说明:设置Audio驱动模式;

APP_REGISTER_GPIO_RISC1_FUNC:

默认值:1;

作用说明:TX芯片同步中断使能;

AUDIO_I2S_DATA_INVERT:

默认值:0;

作用说明:I2S数据通道翻转;

Flash配置

LOCAL_APP_ADDR:

默认值:0x8000;

作用说明:APP分区地址;

LOCAL_UPGRADE_ADDR:

默认值:0x40000;

作用说明:OTA分区地址;

LOCAL_VERSION_ADDR:

默认值:0x901c;

作用说明:版本号地址;

UPDATE_STATUS_ADDR:

默认值:0x40800;

作用说明:OTA状态位地址;

FIRSR_UPDATE_STATUS_ADDR:

默认值:0x40810;

作用说明:FIRST OTA状态位地址;

CFG_ADR_BT_USE_TIME_1M_FLASH:

默认值:0xEA000;

作用说明:1M flash,BT使用时间分区地址;

CFG_ADR_SYS_USER_BASE_1M_FLASH:

默认值:0xEB000;

作用说明:1M flash,配对信息存放地址;

CFG_ADR_USER_DEF_CONFIG_TABLE_1M_FLASH:

默认值:0xFC000;

作用说明:1M flash,配置信息存放地址;

CFG_ADR_CALIBRATION_1M_FLASH:

默认值:0xFE000;

作用说明:1M flash,校准信息存放地址;

CFG_ADR_MAC_1M_FLASH:

默认值:0xFF000;

作用说明:1M flash,MAC地址存放地址;

CFG_ADR_MAC_1M_FLASH_LOCK:

默认值:0xDF000;

作用说明:1M flash,MAC地址 flash lock存放地址;

CFG_ADR_CAP_FRQ_OFT_1M_FLASH:

默认值:0xDD000;

作用说明:1M flash,RF CAPTURE信息存放地址;

CFG_ADR_BT_USE_TIME_2M_FLASH:

默认值:0x1EA000;

作用说明:2M flash,BT使用时间分区地址;

CFG_ADR_SYS_USER_BASE_2M_FLASH:

默认值:0x1EB000;

作用说明:2M flash,配对信息存放地址;

CFG_ADR_USER_DEF_CONFIG_TABLE_2M_FLASH:

默认值:0x1FC000;

作用说明:2M flash,配置信息存放地址;

CFG_ADR_CALIBRATION_2M_FLASH:

默认值:0x1FE000;

作用说明:2M flash,校准信息存放地址;

CFG_ADR_MAC_2M_FLASH:

默认值:0x1FF000;

作用说明:2M flash,MAC地址存放地址;

CFG_ADR_MAC_2M_FLASH_LOCK:

默认值:0x1DF000;

作用说明:2M flash,MAC地址 flash lock存放地址;

CFG_ADR_CAP_FRQ_OFT_2M_FLASH:

默认值:0x1DD000;

作用说明:2M flash,RF CAPTURE信息存放地址;

FLASH_PROTECT_EN:

默认值:0;

作用说明:flash 写保护使能;

CONFIG_CHECK_ENABLE:

默认值:0;

作用说明:配置信息校验使能;

USB配置

FLAG_PRINTER_DEBUG:

默认值:1;

作用说明:USB PRINTER功能值;

FLAG_USB_HID:

默认值:8;

作用说明:USB HID功能值;

APP_MODE_DEBUG_ONLY:

默认值:FLAG_PRINTER_DEBUG;

作用说明:ONLY USB PRINTER;

APP_MODE_DEBUG_HID:

默认值:(FLAG_PRINTER_DEBUG | FLAG_USB_HID);

作用说明:USB HID + USB PRINTER;

APP_MODE:

默认值:APP_MODE_DEBUG_ONLY;

作用说明:USB 模式设置;

MODULE_USB_ENABLE:

默认值:0;

作用说明:USB 模块使能;

USB_SPEAKER_ENABLE:

默认值:0;

作用说明:USB SPEAKER 功能使能;

USB_MIC_ENABLE:

默认值:0;

作用说明:USB MIC功能使能;

USB_HID_NOT_SUBCLASS:

默认值:1;

作用说明:USB 设置NOT SUBCLASS;

USB_CUSTOM_HID_REPORT:

默认值:1;

作用说明:HID定制report;

MIC_CHANNLE_COUNT:

默认值:1;

作用说明:MIC channel数;

VCD_EN:

默认值:1;

作用说明:vcd调试使能;

SL_ASYNC_EN:

默认值:0;

作用说明:音频通路相关 VCD调试使能;

SL_TASK_EN:

默认值:1;

作用说明:各task相关 VCD调试使能;

SL_APP_EN:

默认值:0;

作用说明:APP VCD调试使能;

SL_BLE_EN:

默认值:1;

作用说明:RF流程 VCD调试使能;

SL_CONNECT_EN:

默认值:1;

作用说明:连接流程 VCD调试使能;

MCU

程序启动流程介绍

sdk支持1M Flash和2M Flash自适应,默认按照1M Flash内存分配。

TX Flash内存分配

1M Flash内存分配

2M Flash内存分配

RX Flash内存分配

1M Flash内存分配

2M Flash内存分配

1M Flash和2M Flash内存分配基本架构一致,只是地址分配有些许不同,所以就只对1M Flash的地址分配进行介绍。

Boot: Flash 0x00地址开始存放的是boot程序,MCU上电后会先执行boot程序,然后再跳转到APP程序。

Header1: Flash 0x8000地址开始存放的是APP1的一些信息,如APP1程序存放的flash首地址、APP1 bin size、APP1 CRC 校验码。Boot程序会根据Header1存放的信息对APP1 进行CRC check,以此判断APP1程序是否完整。

APP1: Flash 0x9000地址开始存放的是APP1程序,Boot程序检查 APP1是否完整,如果完整会直接跳转到flash 0x9000地址开始执行APP1程序。

OTA_FW: Flash 0x40000地址开始存放的是备份的FW,如果在boot里检测到APP不完整,会从OTA_FW中load新的FW到APP。如果用户没开启APP切换功能,0x40000~0xEB000都可用作备份FW区域。

Header2: 如果用户开启了APP功能切换,那么Flash 0xC0000地址开始存放的是APP2的一些信息,如APP2程序存放的flash首地址、APP2 bin size、APP2 CRC 校验码。Boot程序会根据Header2存放的信息对APP2 进行CRC check,以此判断APP2程序是否完整。

APP2: 如果用户开启了APP功能切换,那么Flash 0xC1000地址开始存放的是APP2的程序,用户在APP工程中将PROJ_APP_ENABLE置为1以后,可以在APP中通过usb指令或者按键进行应用软件切换,MCU首先会回到Boot程序检查完APP2是否完整,如果完整会直接跳转到flash 0xC1000地址开始执行APP2 程序。Header2和APP2的起始地址可根据需要进行修改,该功能详情请见后续APP功能切换章节。

Pair info: Flash 0xEB000地址开始存放的是配对信息,无线模组根据配对信息进行回连。

Configure : Flash 0xFC000地址存放的是configure bin,APP会根据配置表来判断当前运行的是什么系列的Soundbar产品,在配对阶段也会检查tx和rx是否是同一个系列,如果不是同一个系列不允许配对。

Calibration: Flash 0xFE000地址存放的是calibration值,MCU上电时会根据calibration值来调整芯片CAP值。

Mac address: Flash 0xFF000地址存放的是Mac 地址,一共6个byte。无线模组利用TX MAC地址计算的access code进行通信。

MCU启动流程介绍

MCU启动流程

根据flash内存分配图可知,0x00地址放的Boot程序,每次上电都从Boot中启动。Header中存放的是APP的首地址、bin size以及CRC 校验码。MCU从Boot启动后,会根据Header中存放的APP信息进行CRC check,以此判断APP是否完整。如果CRC Check失败会判断是否有新的固件可供升级,若没有则停留在boot,若有新的固件则会把其先搬运到flash 0x9000起始位置,然后reboot MCU重新走一遍上述流程直到APP CRC check成功。APP CRC check成功后,MCU会跳转到flash 0x9000地址执行App。

Bin文件介绍

用户在第一次编译时一定要先编译boot工程,再编译soundbar工程,这时会将soundbar app bin与boot bin进行合并,产生一个新的bin,用户在调试或者给芯片第一次烧录时需要烧录这个新的bin即可,这个新的bin结构如下图所示:

bin结构

举个例子:在第一次编译soundbar_4p1_tx工程时,用户需要先编译boot dongle工程,然后再编译soundbar_4p1_tx工程,第一次烧录固件时烧录带有img标志的固件。同理在第一次编译rx工程时,记得需要先编译boot device工程。详情如下图所示:

编译soundbar_4p1_tx工程详情

APP功能切换

APP功能切换原理介绍

app正常运行的情况下,收到特定指令后会调用函数void my_switch_boot_mode(int mode)让app复位进入boot,boot会根据该函数的参数mode选择app的起始地址,来进行app1和app2的切换。

APP起始地址、APP Header起始地址介绍

(1)APP1 Header默认起始地址为0x8000,APP2 Header默认起始地址为0xC0000,用户可以根据bin文件大小修改默认APP Header起始地址,特别是使用2M flash的时候,0xD0000开始存放OTA升级文件,那么APP2能使用的空间只有0x10000,用户需要根据项目需求修改APP2 Header的起始地址,修改的位置如下:

修改位置1

(2)APP1起始地址默认为0x9000,APP2起始地址默认为0xC1000,该起始地址分别存储于APP1 Header和APP2 Header的前4个bytes,用于进行跳转。用户可以根据bin文件大小修改默认APP起始地址,修改的位置如下:

修改位置2

APP功能切换示例演示

(1)用soundbar_4p1_tx工程演示,app功能切换在sdk中默认是关闭的,客户可以根据需求通过修改工程配置文件,将PROJ_APP_ENABLE置1来开启该功能,具体位置如下图所示:

修改位置3

(2)修改完后需要重新对整个工程进行编译,编译后选择带img头的bin作为固件1,它包含boot、app1 header和app1。

(3)同理使用sdk中其它的工程采用同样的方法编译后,选择不带img头的bin,它不包含boot和header,并使用App2AddHeader工具手动添加上header,APP2 flash address填写APP2 Header起始地址(如下图),点击output生成带有crc32后缀的文件,在同路径下找到它,只需要将crc32后缀去掉即可得到我们所需要的固件2。

软件界面

(4)然后通过BDT工具将固件1和固件2分别烧录到TX板0x00000和0xC0000的Flash位置,如下图所示:

烧录配置

(5)TX跑起来后会先运行app1,用户可以通过rsic-v工具发送11 01指令切换到app2,再发送11 00指令可以切回app1。或者通过短按SW2按键也可以从app1切换到app2,具体代码实现如下:

具体代码实现

芯片级联方案介绍

Soundbar sdk介绍了多个应用demo,由于MCU资源限制,按照Tx module mcu数量来分主要有1p1(1个mcu)、2p1(2个mcu)、4p1(3个mcu)。

以4p1 demo为例:

4p1 demo需要传输4.1 chn的音频,需要三路i2s data。B91芯片只有一个i2s 模块,只支持一路i2s data。

另外,B91芯片主频最大可以跑96MHz,如果对4.1 chn的音频进行编码(5ms帧长),算力达不到。

因此选用3颗芯片(示意图如下),通过级联的方式并行工作,完成4.1 chn的音频编码,以及RF 发射。

级联示意图

从芯片工作方式简介

上面提到4p1 demo tx端是通过3颗芯片级联的方式并行工作的,主芯片有内置flash,从芯片没有内置flash。主芯片内置有flash,上电后从flash启动,从芯片没有flash,只能从sram启动。

主芯片从flash启动时,会将所有数据搬到iram和dram,包括代码段。主芯片在执行到main函数时,会通过GPIO口输出24MHz时钟给从芯片提供时钟源,然后主芯片会将iram和dram内容通过single wire烧录方式download到从芯片sram中。download fw时,由于两颗从芯片默认ID都是0,可以同时进行。download fw结束后,主芯片通过reset脚先reset其中一个从芯片,然后给另一个从芯片配置通信ID。同样的方法,所有从芯片ID配置好后,主芯片就可以通过不同ID来访问对应从芯片配置好ID后,主芯片会对从芯片进行软件复位,从芯片从PC 0指针开始运行。

从芯片在执行到main函数时,会先进行代码段crc自校验,确认download fw是否正常。

从芯片自校验结束后,主芯片会toggle sync gpio,从芯片检测到gpio中断后,可以同步主芯片的时序。

主从芯片时序同步后,主芯片就会在特定slot里去读取从芯片编码后的数据,然后打包一起发送。主从芯片可以理解运行的是相同的代码,所以变量的地址两边是一致的,这样方便主芯片读写从芯片。

另外由于从芯片的24M crystal时钟由主芯片提供,主从芯片时钟同源,这样能避免时钟产生偏差。

24MHz clk介绍

关于主芯片到从芯片的24M时钟部分设计芯片内部最高电压要求是<1.2V,所以外部对3.3V进行电路分压处理。9805端有一个2.2k和330R的分压是给芯片内部buffer提供一个共模电平0.3V ~ 0.4V。另外主从芯片时钟同源。参考设计电路如下:

从芯片设计电路

主芯片设计电路

关于24MHz时钟的占空比以及波形要求说明:

(1)芯片内部PLL对输入进来的波形没有具体的要求,电路是边沿触发,只要有上升沿就行;

(2)内部PLL对进去的clk没有具体的要求,20%都可以,内部baseband pll会重新调整占空比;

(3)主芯片通过GPIO 输出的24MHz时钟占空比在40%左右。时钟输出加了电阻分压,会增加一些寄生电容,另外加上示波器探头影响会导致实际的占空比在40%左右。9805只是跑音频编解码,而这个40%的占空比已经完全满足我们对时钟的需求。

Single wire简介

Single wire download fw介绍:

Swire通信是Telink私有的一种单总线通信协议,基本通信原则是按照高低电平的比例关系,低高为4:1表示一个bit的1,低高为1:4表示一个bit的0。

swire协议

swire通信之前,swm端需要先发一段特殊波形,通知sws端进行握手,然后就可以按照协议要求进行读写操作。

swm端在download fw时,clk配置为8MHz,因为此时从芯片主时钟为24MHz RC时钟(Hclk也是24MHz),swm clk配置为8MHz满足采样要求。

由于同时给两颗slave芯片download fw,所以这个过程只能写,不能读,不然两个slave同时回应,读取的内容不可靠。

当主从芯片都正常跑起来后,hclk都是48MHz,此时single wire clk会配置为16MHz,减小主从之间通信时间。

需要注意的是,在类似的应用中,不要通过swm 去配置从芯片时钟相关的寄存器,因为这有可能会导致从芯片的时钟配置异常,sws模块工作异常,从而导致主从芯片工作异常。

I2C协议

Soundbar sdk中,提供了Telink MCU与外部主控进行硬件IIC通信的demo,Telink MCU为I2C slave,用户可以根据需求进行移植。

I2C协议说明

(1) 默认读写的Length都是1。

(a) 支持的写命令如下:

\qquad \textbf{ID(7 bit) + W(1 bit) + Cmd(1 byte) + Data(1 byte)}

(b) 支持的读命令如下:

\qquad \textbf{ID(7 bit) + W(1 bit) + Cmd(1 byte) + ID(7 bit) + R(1 bit) + Data (1 byte)}

(c) 默认情况下I2C write采用ndma方式,trigger level长度为1,当收到一个有效数据,就会产生一次中断。在升级时I2C write 采用dma方式,length为133 Bytes。

(d) SDK中I2C 中断优先级为2,Stimer中断优先级为3。Telink I2C Slave支持Stretch功能,当I2C中断不能及时处理时,stretch功能会打开,以此来通知I2C Master当前处于busy,不能再接收新的数据。SDK中只要中断优先级高于2,在中断处理函数入口就要将stretch功能打开,在中断处理函数出口将stretch功能关闭。关闭全局中断和打开全局中断也需要相同的操作,详情可以直接参考sdk 代码。

读命令流程如下图所示(往寄存器地址0x20写一个byte,值为0x01):

寄存器地址0x20

读命令流程

写命令流程如下图所示(读寄存器地址为0x04的值,值为0xE3):

寄存器地址0x04

写命令流程

(2) 固件升级时发一帧特殊写命令:0xff 0x01;下一帧写数据,Master往固定地址0x6b写0x85长度的data,之后恢复到默认状态,详细协议可以参考I2C 协议说明文档。格式如下:

ID(7 bit) + W(1 bit) + Cmd(0xff) + Data(0x01)

ID(7 bit) + W(1 bit) + Crc(2 byte) + Seq_num(3 byte) + Data(128 byte)

固件升级时的写命令

固件升级时的写命令

当发送长数据时,i2c slave 采用的是dma方式,当收完一帧数据后才会产生一次中断,在中断处理函数中处理数据校验等。

(3) 当master传送完固件后,master会发送128bytes大小的0x5A通知slave固件已传送结束。slave进行本地固件升级完成时,会通过uart Tx来通知master当前事件状态。

I2C固件传输流程

Step 1: Master 发送 0x27 0x01开始固件升级;

Step 2: Master 发送 0xff 0x01,通知slave下一帧数据是个长数据;

Step 3: Master 发送固件包,如上图所示;

Step 4: Master重复Step 3流程,直到固件升级结束;

Step 5: 固件升级结束后,master会发送128bytes大小的0x5A通知slave,固件包传送结束。

Step 6: Slave收到最后的结束固件包,会解析固件包,然后进行固件升级。

I2C命令说明

Telink提供丰富的I2C命令来与外部主控交互,用户可以根据需求裁剪。命令如下表格所示:

(1)Basic info:提供基本信息的查询命令,用于查询TX/SUB/SOD_L/SOD_R Version、TX Mac address、信号强度RSSI。

Basic info命令

(2)Basic control:提供基本的控制命令,常用的有配对功能、暂停/播放音乐、进入standby模式、uart打印信息等等。

Basic control命令

(3)Firmware upgrade:提供固件升级状态查询等等。

Firmware upgrade命令

MasterIIC传输固件示例演示

用Telink EVB开发板作为master板,用来模拟外部主控通过IIC接口向TX传输OTA文件,具体步骤如下:

(1)首先需要编译_proj_master_iic工程得到master的bin,然后通过第九章combine_tool, 合成带checksum的OTA文件,如下图所示:

所需固件

(2)然后将ota文件和master iic的bin文件通过Telink BDT工具烧录到master板里,地址分别为:0x00000和0x80000,如下图所示:

配置界面

(3)打开Telink RSIC-V工具,并选择master iic工程的配置文件,用USB线连接master 板和电脑,连接正常后工具左上角会显示Found,如下图:

操作界面

(4)通过rsic-v工具发送11 44指令给master板,触发master板向TX的0x40000地址发送OTA文件。

(5)OTA文件传输完成后,连接master 板的rsic-v工具会打印“master iic transmit completed:"信息。所下图所示:

操作示意图

注意

  • 如果IIC传输OTA文件失败,提供以下思路进行解决。
  • IIC管脚需要接4.7k的上拉电阻、IIC管脚是否有被复用、Combine_bin_App工具是否有正确写入ota升级版本号、master板和TX板要共地。

OTA

OTA简介

OTA功能实现在boot里,其中TX对应_proj_boot_dongle_工程(包括Remote OTA和Local OTA),SOD和SUB对应_proj_boot_device_工程。上节已讲述master通过I2C将OTA升级包传输到TX的0x40000地址,接下来TX会开启First OTA,将变量first_ota_en置1,并进行Local OTA和Remote OTA。

如果升级失败,当TX和RX建立连接的情况下进入standby mode后,TX会读取RX版本号,若与OTA版本不一致则进入Standby OTA升级流程,其流程与Remote OTA一致。用户可以通过外部主控发送IIC命令或者其它方式来进入standby mode,可以关注函数i2c_standby_control中app_i2c_ctr.standby_chg变量。

OTA流程

Local OTA

当OTA固件通过IIC传到TX后,TX会开启First OTA流程,调用函数void my_switch_boot_mode(int mode)让app复位进入boot完成对自己的升级(不过此时其所带参数为0x4b,与app功能切换的调用此函数所带参数不一样,开发者需要注意区分)。用户可以关注boot里面的async_dfu_tx_local_upgrade函数,以下是TX Local OTA的示意图:

TX Local OTA

TX Local OTA

Remote OTA

TX完成对自己的升级后,退出boot进入app,然后通知RX进入boot,TX便再次进入boot,两个进入boot后重新建立连接,TX将对应的OTA Firmware包传给RX,然后TX跳回app,RX在boot中将新的OTA Firmware从0x40000搬到0x8000,然后退出boot。这时OTA升级完成。以下是Remote OTA示意图:

Remote OTA

Remote OTA

其他注意事项:

  • OTA流程,在发送Rx固件时,进入Boot阶段,会使用固定 ACCESS CODE与Rx协商出私有 ACCESS CODE,所以不建议多台设备同时OTA,因为使用的是固定ACCESS CODE,可能导致升级出错。
  • 公版SDK V1.2.0版本以后对OTA流程做了优化,将协商ACCESS CODE换成待升级的Rx ACCESS CODE,为了尽可能解决上述问题。

LinkLayer

LinkLayer作为RF收发的物理层,在soundbar应用中,采用的LE 2M Phy,该物理层传输速率为2M bit/s,即传输一个byte时间为4us。理解LinkLayer用户需要对telink的RF driver有一定了解,由于RF外设内容较多,本章只概述soundbar中用到的RF接口函数,其他的用户可通过telink的wiki参考driver handbook。

整个数据流带ACK机制,以每5ms为一帧数据,在每帧数据里再划分N个slot间隔进行收发包,不同demo N值不同,如4P1 demo N为4。Rx端调用的RF端口为srx2tx,在Rx收到正确的crc包时,会自动给Tx发包,编解码时,Rx会在固定slot对前面收到音频数据包进行解码,Tx在固定slot对当前的音频数据包进行编码,这样可以确保整个音频数据流的传输延迟不变。

(1) 正常数据流

正常数据流

在正常工作时, 每5ms的一帧数据里,Bar[Tx]给Sub[Rx]进行发包,Sub[Rx]收到包时会对Bar[Tx]进行ACK。

VCD时序(生成VCD参考Debug 章节):

以0P1为例:

Bar[Tx]给Sub[Rx]进行发包:

正常数据流TX VCD时序

Sub[Rx]收到包时对Bar[Tx]进行ACK:

正常数据流RX VCD时序

(2) 丢包和重传

丢包和重传

在一帧的数据周期里,若Rx没收到Tx发来的数据包或者收到错包出现CRC ERR时,则Rx不会给Tx回ACK,Tx没收到Rx的ACK,会对数据进行重发,若收到Rx端发来的ACK数据包,则结束本周期内发包。

VCD时序(生成VCD参考Debug 章节):

以0P1为例:

丢包和重传TX VCD时序

红框1:为一个周期。

红框2:tx没有收到rx发来的ACK数据包。

红框3:tx重传数据包并收到rx发来的ACK数据包。

红框4:结束本周期内发包。

(3) 完全丢包导致断连

完全丢包导致断连

在一帧的数据周期里,若Rx一直没收到Tx端数据包或收到错包,则Tx会对数据包进行重传,重传次数最大为10次。

VCD时序(生成VCD参考Debug 章节):

完全丢包导致断连TX VCD时序

红框1:为一个周期。

红框2:tx没有收到rx发来的ACK数据包。

红框3:tx没有收到rx发来的ACK数据包。

红框4:在一帧数据周期内里都没有收到rx发来的ACK数据包。

红框5:一个周期未回复ACK判断丢包。

Demo简介

下面分别以2p1、4p1 demo简单介绍下音频传输细节:

2p1 demo:

只传输一路低音炮,两路全频段环绕音。48kHz采样率,5ms帧长,16bit data,每帧5个slot。

Subwoofer通路通过重采样方式处理,传输200Hz以内低频信号。surround通路,通过LC3Plus进行编码后传输。

2P1传输

VCD时序(生成VCD参考Debug 章节):

2P1传输TX VCD时序

4p1 demo:

只传输一路低音炮,和四路全频段环绕音。48Khz采样率,5ms帧长,16bit data,每帧4个slot。

Subwoofer通路通过重采样方式处理,传输200Hz以内低频信号。surround通路,通过LC3Plus进行编码后传输。

4P1传输

VCD时序(生成VCD参考Debug 章节):

4P1传输TX VCD时序

1TX&3RX

SDK支持最多1对3连接(1TX&3RX),RX在和TX建立连接时,会根据先后顺序分配好role,如master、slave、listener。每个role会根据当前的连接情况进行自动转换。

1对3连接示意图

1Tx3Rx ACK机制介绍(以4p1为例):

ACK机制

注意

  • 相同颜色代表同一笔包,备注Tx的代表是发射端,备注Rx的代表接收端。一个tx包,有可能有多个Rx设备同时接收。

Tx在发音频包或者普通命令包时,三个Rx都会处于听包状态。Tx发完包后,会处于收包状态,准备接收Rx回的ACK包。Master role设备会先回ACK给Tx,Slave role设备后面紧跟着给Tx回ACK。在Master role设备回ACK时隙内,Listener role设备先将ACK发给Slave role设备。Slave role设备回ACK包时,会将listener role设备的状态一并返回给Tx设备。

VCD时序(生成VCD参考Debug 章节):

4p1 Tx:

Tx VCD时序

Tx VCD时序细节

红框1:发送音频或者普通命令包。

红框2:发完包后,处于收包状态,接收Rx回的ACK包。

红框3:Master role和Slave role的ACK包。

红框4:周期内收到所有的ACK包。

4p1 Master role:

Master role VCD时序

Master role VCD时序细节

红框1:听包状态。

红框2:收包有效回复ACK给Tx。

4p1 Slave role:

Slave role VCD时序

Slave role VCD时序细节

红框1:听包状态。

红框2:收到Listener role 回复的ACK。

红框3:将自身及listener role设备的状态一并返回给Tx。

4p1 Listener role:

Listener role VCD时序

Listener role VCD时序细节

红框1:听包状态。

红框2:将ACK发给Slave role设备。

红框3:收到Slave role返回Tx的ACK。

配对和回连

配对

Soundbar sdk中,提供了1对1配对和1对3配对两种方式,可通过宏(ALL_PAIR_TOGETHER)进行切换,当ALL_PAIR_TOGETHER为0时,即为1对1配对,当ALL_PAIR_TOGETHER为1时,即为1对3配对。

触发配对可以通过按键或者usb指令。TX短按SW3按键,RX短按SW9即可通过按键进入配对模式。通过rsic-v工具分别给TX,RX发送11 31 15指令即可通过usb指令进入配对模式。用户可以特别关注函数 async_enable_pairing。

1对1配对

1对1配对方式流程如下,需要提前写入MAC地址(1M flash地址0xff000的连续6个byte)。

配对流程

整个配对流程涉及到TX和RX的信息交互,需要RX和TX同时进入配对模式,且在同一个chn和access code上,上面流程图标示出的为TX端先发起配对请求(ASYNC_CMD_PAIR_REQ),配对请求包中带有TX端的MAC Address。RX收到配对请求后,会进行配对回应(ASYNC_CMD_PAIR_RSP),配对回应包中带有RX端的device id、product id、TX的MAC、RX的MAC。

TX收到RX的配对回应包后,会比对RX发过来的TX MAC、product id、device id。如果TX MAC不对,则忽略该配对回应包继续收包,若是product id和device id有误,则TX发送配对拒绝包(ASYNC_CMD_PAIR_REJECT)给RX,终止配对流程,反之信息无误,TX发送配对确认包(ASYNC_CMD_PAIR_CFM)给RX。

RX收到TX的配对确认包后,也会比对TX发过来的MAC、device id和product id,通过后RX也会发送配对确认包(ASYNC_CMD_PAIR_CFM_TX)给TX,并延时1s后退出配对模式。TX收到包经过信息比对无误后,也退出配对模式,配对成功。

关于配对的连接具体命令交互,TX在async_tx_data_parse(),RX在async_rx_data_parse()中,交互命令如下:

Cmd                      opcode
ASYNC_CMD_PAIR_REJECT   = 0x0f,
ASYNC_CMD_PAIR_REQ      = 0x10,
ASYNC_CMD_PAIR_RSP      = 0x11,
ASYNC_CMD_PAIR_CFM      = 0x12,
ASYNC_CMD_PAIR_CFM_TX   = 0x13,

1对3配对

1对3配对方式,即3个RX进入配对模式后,在设置配对的时间内,TX只用进一次配对模式即可和3个RX配对上,3个RX的配对chn和access code(后面用ac代替)会根据配置文件中的device id来改变,TX则在配对时会每隔1s切换一次配对chn和ac来分别与3个RX配对交互,直到3个RX配对完成或者配对超时。这个和1对1配对方式中3个RX的chn,ac都保持一样有所不同,但其中的配对流程都是一样的。

另外需要注意的是在配对之前,一定要保证配置表烧录正确,mac address烧录成功,否则会影响到配对。另外删除配对时也需要注意,最好两边都要删除配对信息,然后再进行配对。

配对流程

配对记录

1M flash的情况下,EB000位置会拷贝存储在FF000的mac地址,启动时当发现EB000存储的mac地址与FF000位置的不同时,会清除当前的配对记录,保证配对记录的有效性。

1M flash的情况下,配对记录会从0xEB010的位置开始存储,每个配对记录占用10字节,TX的配对记录如下图所示:

配对记录

我们以上图画红框的记录为例进行说明:

- ff 代表改配对记录有效,如果无效,设备会将ff修改为aa;
- 01 表示配对的设备类型(sub为01,sodl为02,sodr为03);
- 07 表示该设备类型是第几个配对上的,例如这是第7个配对上的sub设备;
- ff 我们可以不用关注
- 83 29 06 12 23 34 为配对设备的mac地址。

RX的配对记录结构和TX基本一样,只是第四个字节RX是00,而TX是ff。

回连

重新上电后,如果没有配对信息,那么可以通过按键或者usb指令进行配对,如果有配对信息,则进入回连。

在RX保存TX配对信息的时候,RX可以快速与TX连接。流程如下:

TX在未连接的时候会在每一个包的末尾添加自己的回连信息,信息包括配对上RX的id_num,device_id以及TX自身的MAC,RX如果与TX配对过,Access code使用和TX一致,所以能收到TX收到的包,收到包后会对包的内容进行校对,校对通过后RX会和TX建立连接。

CRC init

V1.2.0版本之后新加入CRC init机制,收发包会通过硬件CRC校验数据包的完整性,CRC算法中会有初始值,初始值对于结果的影响主要在于影响校验的性能和校验码的生成,相同的数据包如果CRC初始值不同最后生成的CRC校验码也不同,对于回连来说,增加CRC init有效的减少了ACCESS CODE相同时,异常回连的问题。

生成CRC初始值的实现:

/**
 * @brief       This function servers to get CRC inital value from MAC
 * @param[in]   mac - mac address
 * @return      u32
 */
u32 tsync_get_crc_init_from_mac (unsigned char *mac)
{
    u32 c;
    u32 *m = (u32*) mac;
    c = MAC_2_CRC_INIT_XOR_VALUE ^ (m[0]& 0x00FFFFFF);
    if(c == DEFAULT_CRC_INIT_VALUE) {
        c = (c + 1) & 0x00FFFFFF;
    }
    return c;
}

回连流程

角色分配

在1对3(1TX & 3RX)中,RX在和TX建⽴连接时,会根据先后顺序分配role,依次为master、slave、listener。

(1) RX如果与TX配对过,TX在未连接时,三个RX状态一致,会在同一个通道发起ASYNC_CMD_CONNECT_REQ请求,TX接收到后,会与首个进行连接,分配master role;

(2) TX会进入连接状态,给master发送音频包的空闲时间,会根据fno切换回连通道,发包告知RX回连,RX收到后,会发起ASYNC_CMD_CONNECT_REQ请求,TX接收到后,与首个进行连接,分配slave role;

(3) TX继续发包告知最后一个RX回连,RX收到后,会发起ASYNC_CMD_CONNECT_REQ请求,slave接收到ASYNC_CMD_CONNECT_REQ请求,会分配给它listener role,并通过slave RX回复的包中告知TX。

回连分配role流程

角色切换

在连接过程中,若有设备断连,因为角色不同,有时需要进行角色切换,保证其他的设备可以正常保持连接。

TX会根据发送给对端以下两个标志位告知当前的master和slave的连接状态:

ASYNC_FLOW_DEV0     = 0x40, //master
ASYNC_FLOW_DEV1     = 0x80, //slave

(1) 当listener role断开,其他角色不会变化;

(2) 当slave role断开,listener role会从收到的包中检查到ASYNC_FLOW_DEV1为空会将自己的角色置为slave,并通知TX;

(3) 当master role断开,slave role会从收到的包中检查到ASYNC_FLOW_DEV0为空会将自己的角色置为master,并通知TX,listener role会从收到的包中检查到ASYNC_FLOW_DEV1为空会将自己的角色置为slave,并通知TX。

连接心跳包

Soundbar SDK的TX与RX配对后,两边都会使用TX的mac地址生成的access code通信,RX会通过读取配置记录来设置自身的access code,只要access code相同两边就能正常收发包。

如果有一台SUB与TX配对之后,断电这台SUB后,让TX与另一台SUB配对,此时前一台SUB还保留之前TX的配对记录,所以上电依旧可以与TX正常收发包。

为了避免这种情况,我们通过心跳包的方式,每隔2s秒,让RX将接收到的心跳包与本地的配对记录做校验,让校验失败的RX主动断开连接。

    u8 data[13] = {0};
    data[0] = 0x07;
    data[1] = flash_user_data.id_num[0];
    data[2] = flash_user_data.id_num[1];
    data[3] = flash_user_data.id_num[2];
    data[4] = flash_user_data.paired_id_flag;

    memcpy(&data[5],&flash_user_data.const_addr,6);
    for(int i= 0;i<11;i++){
        data[11] += data[i];
        data[12] = (u8)(((u16)(data[12] + data[i]))>>8);
    }
    app_push_cmd (ASYNC_CMD_CONNECT_CHECK, data, 13, 0);

从上面代码可以看到,心跳包包括id_num(各个RX的配对次数)、paired_id_flag(各个RX是否配对的标志)、TX mac、checksum, RX端会check心跳包,若校验失败则主动断开连接。

Debug

可以使用TDB工具来打印USB信息来Debug、使用VCD查看信号。

工具下载路径:

http://wiki.telink-semi.cn/tools_and_sdk/Tools/BDT/BDT.zip

打开RISC-V TDB

TDB工具界面

USB打印函数说明

(1) 下面函数void _usb_send_str_data__()中,str为你要打印的字符串,ph为你要打印的数据,n代表字节长度。如果只需要打印字符串或者数据,可以把不需要的参数写0.

void usb_send_str_data (char *str, u8 *ph, int n)
e.g. usb_send_str_data("led_set_clear_dev_info_state",&led_state,1); //led_state为char类型。

(2) 下面几个函数是基于void _usb_send_str_data__()函数的变形,以实现更方便的调用。

##define    usb_send_str(s) usb_send_str_data(s, 0, 0)
e.g. usb_send_str("led_set_clear_dev_info_state")

##define    usb_send_data(p,n) usb_send_str_data(0,p,n)
e.g. usb_send_data(&led_state,1)

##define my_dump_str_data(en,s,p,n)     if(en){usb_send_str_data(s,(u8*)(p),n);}
e.g. my_dump_str_data(1,"reconnect_check_data",&spec_cmd_rcv.ctr_id,8);

##define my_dump_str_u32s(en,s,d0,d1,d2,d3) //打印字符串以及4个32位的数据   if(en){usb_send_str_u32s(s,(u32)(d0),(u32)(d1),(u32)(d2),(u32)(d3));}
void usb_send_str_u32s (char *str, u32 d0, u32 d1, u32 d2, u32 d3)
{
    u32 d[4];
    d[0] = d0;
    d[1] = d1;
    d[2] = d2;
    d[3] = d3;
    usb_send_str_data (str, (u8*)d, 16);
}
e.g. my_dump_str_u32s (1, "device id", async.dev_id,device_slot, ap_last_slot, ap_frame_bits);

VCD调试信号函数说明

VCD基础知识

Value Change Dump (VCD) ,是一种基于ASCII的格式,用于由EDA 逻辑仿真工具生成的转储文件。1996 年,IEEE标准1364-1995与Verilog硬件描述语言一起定义了标准的四值VCD 格式。六年后,IEEE 标准1364-2001 中定义的扩展VCD 格式支持信号强度和方向性的记录. VCD 格式的简单而紧凑的结构使它的使用变得无处不在并扩展到非Verilog 工具中,例如VHDL模拟器 GHDL和各种内核跟踪器。格式的一个限制是它不能在存储器中记录数值。

VCD文件内容分为标题段、变量定义段、变量初始化段、value change段。标题部分包括时间戳、模拟器版本号和时间刻度,它将值更改部分中列出的时间增量映射到模拟时间单位。变量定义部分包含范围信息以及在给定范围内实例化的信号列表。初始化部分包含所有转储变量的初始值。value change部分包含给定仿真模型中信号的一系列按时间顺序的值变化。

需要得到VCD文件,主要是对value change进行编写,下面介绍本SDK的VCD功能。

VCD调试配置方法

(1) 打开GPIO口定义

##define PA5_FUNC       AS_USB_DM
##define PA6_FUNC       AS_USB_DP
##define PA5_INPUT_ENABLE   1
##define PA6_INPUT_ENABLE   1

使用前需要把上面两个宏定义写1.

(2) 信号量说明

//event: 0 for time stamp; 1 reserved; eid2 - eid31 (event类型变量)
##define  SLEV_timestamp 0
##define  SLEV_reserved  1

// event with tick: 0 – 31 (event with tick 变量)
##define  SLET_timestamp  0
##define  SLET_RX_SYNC    1

// 1-bit data: 0/1 for hardware signal: PA4/PB1; bid2 - bid31    (1bit data 类型变量)
##define  SL01_TX_EN  0
##define  SL01_RX_EN  1

// 8-bit data: cid0 - cid63 (8bit data 类型变量)
##define  SL08_lmp_rx_code  0
##define  SL08_lmp_esc4     1

// 16-bit data: sid0 - sid63 (16bit data 类型变量)
##define  SL16_bt_CLKN_HS  0
##define  SL16_bt_FCNT     1

上面分别是event、event with tick、1bit data、8bit data、16bit data类型的部分变量,在./common/usb_dbg/log_def_stack.h可以查看所有变量。不同变量结合不同的函数使用,可以得到不同的VCD文件的数据。下面介绍几个不同的函数及其用法。

(3) 函数说明

(a) 打印事件:此函数会反转两次变量的值,及形成一个脉冲  。此函数ID必须为event类型变量,其函数只会输出值变化的信息,不会输出时间信息,它的值变化会跟在最近的一个时间戳之后。

log_event(en,id)
e.g. log_event(1, SLET_timestamp)  //会反转两次SLEV_reserved的值,0->1,1->0.

(b) 打印事件和时间:此函数会反转两次变量的值,及形成一个脉冲  。此函数ID必须为event with tick类型变量,其函数会输出值变化和时间的信息。

log_tick(en,id)
e.g. log_tick(1, SLET_timestamp)

(c) 打印数据:下面三个函数分别为打印1/8/16bit数据。en为使能,id为变量名(上一小节的信号量,需要使用1/8/16bit data类型的变量名),b为改变的值。它会把变量的值变化和当前的时间写入VCD文件。

log_task(en,id,b) //print 1bit data
e.g. log_task(1, SL01_TX_EN,1)   //把SLET_timestamp的值在当前时间点改为1
log_task(1, SL01_TX_EN,0)   //把SLET_timestamp的值在当前时间点改为0

log_b8(en,id,d)   //print 8bit data
e.g. log_ b8 (1, SL08_lmp_rx_code,1)
log_b16(en,id,d)  //print 16bit data
e.g. log_ b16 (1, SL16_bt_CLKN_HS,1)

生成VCD文件查看时序

(1) 设置工具相关配置路径

打开工具的ini配置文件,将vcdviewer下面的路径设置为用户实际存放的gtkwave.exe的绝对路径。

配置文件修改

配置vcddef的路径,该路径可以通过ini文件里进行修改,也可通过工具本身的选项进行查找log_def_stack.h,如下图所示。

vcddef路径配置

(2) 开始生成vcd时序文件

点击start选项。

生成vcd时序

抓取完毕后,点击stop。

生成vcd时序

(3) 打开vcd时序文件

最后选择view,可以打开设置路径下的gtkwave.exe,并且同步打开vcd文件。

查看vcd时序

整个gtkwave工具页面如下:

vcd时序窗口

  • 窗口1:点击EVENT

  • 窗口2:显示抓取的信号;

  • 窗口3:输入字符可以方便查找信号;

  • 窗口4:显示的信号(在窗口2双击需要显示的信号即可);

  • 窗口5:整个信号在时序上的显示。

版本号功能

tl_version.h介绍

MAKE_VER(major, minor, revision):用于配置24位的版本号,如0.0.0

MAKE_VER_32(year, week, day, revision) :用于配置32位的固件版本号,如0.0.0.0

TL_VS_SDK_NAME(str):用于指代sdk,必须引用,否则报错。

TL_VS_VER(name, value):用于给模块配置版本号,可选,一般用于算法模块,编解码模块版本号的定义。

TL_VS_STRING(name, str):用于配置字符串,可选。

TL_VS_INT(name, value) :用于配置十进制变量,可选。

TL_VS_HEX(name, value):用于配置十六进制变量,可选。

TL_VS_BYTE_ARRAY(name, ...) :用于配置数组变量,用逗号分隔,可选。

应用

任意工程中的main.c文件中添加下列代码:

TL_VS_SDK_NAME("b91_ll_soundbar_sdk");

TL_VS_VER(4p_1_tx, MAKE_VER(1, 0, 0));

TL_VS_VER(bin, MAKE_VER_32(22, 47, 2, 1));

TL_VS_VER(driver, MAKE_VER(1, 2, 0));

TL_VS_VER(lc3_plus, MAKE_VER(1, 4, 2));

TL_VS_VER(lc3_a, MAKE_VER(1, 4, 2));

TL_VS_VER(plc, MAKE_VER(1, 2, 1));

TL_VS_VER(asrc, MAKE_VER(1, 0, 0));

TL_VS_STRING(Serial_Number, "cky24-q8qrh-x3kmr-c6bcy-t847y Soundbar2022");

TL_VS_INT(Rx_Num, 3);

TL_VS_HEX(Tx_Type, 15);

TL_VS_BYTE_ARRAY(rf, 1,2,3,4,5,6,7,8,9);

编译后,可在编译选项框显示版本相关信息

版本相关信息

示例

打开生成的bin文件如_img_proj_low_latency_soundbar_4p1_tx_.bin,hex视图的尾部地址如下,会发现版本相关信息都存储到bin文件的尾部。

其bin文件的Hex显示

使用版本号上位机软件VersionViewerTool.exe,打开bin文件,如图所示

操作流程

版本输出

Tools

Combine_bin_tool

简介

该工具为合成bin文件工具,对用于ota升级时的bin文件打包,分为UI版本、命令行版本两种。

命令行版本说明

命令行版本实际上是读取当前目录名,及文件名进行识别后,执行指定版本的OTA合成操作。

对于用户,需要按照一定规则创建好目录,并将所需要的文件及合并工具一并复制到此目录中,后续用户只需要双击工具exe即可。

目录规则:

Soundbar_[project_name]_wireless_v[version_number]

如:

Soundbar_0p1_24_wireless_v22.47.5.1

对于命令行工具,还可以首先在对应的IDE编译指定工程后,执行复制脚本,复制脚本自动创建目录。(复制脚本需要依赖python,建议安装3.8版本以上的python环境)

复制工具见下图:

复制工具目录

(1) 流程样例

Step1: 编译好指定的工程:

编译后的工程目录

Step2: 填写复制脚本config文件:

复制脚本的config文件

copy_tool_path:当前合并拷贝工具根目录

project_path:项目路径

version_number:编译的版本号

project_name:编译的工程,目前有: 0p1、0p1_24、2p0、2p0_24、2p1、2p1_24、4p1、4p1_24

Step3: 执行拷贝批处理文件(将指定项目路径下的bin文件拷贝到创建的文件夹):

批处理文件

拷贝成功:

拷贝成功

自动创建的文件夹:

创建的文件夹

Step4: 执行combine_tool命令行工具:

执行combine_tool

得到所需的合并后的文件:

得到的OTA文件

UI版本说明

工具界面

整个UI总共划分了三个部分,第一个部分为填写合成的固件版本号,第二个部分为导入需要合成的bin文件,第三个部分为合成bin文件按钮和生成带checksum bin文件的勾选框。

(1) 流程说明

Step1: 填写版本号

填写版本号

根据需要选择填写或不填,默认为1.2.0.0,前三个框为SDK版本号(用户一般不需要填写),最后一个框代表为固件的迭代次数。

Step2: 导入待合成的bin文件

导入待合成的bin文件

该部分会根据rx_2的勾选进行高亮或灰色显示,高亮代表可导入,灰色为不可选择,该步骤下用户选择按钮导入相应的bin文件即可,其中rx_1_bin为sub固件,rx_2_bin为sod固件。

Step3: 输出bin文件

输出bin

选择Output按钮,若成功合成bin文件,则界面会提示success,用户可在其软件目录下找到生成的bin文件,选择勾选checksum选项,会生成在header中增加checksum的bin文件,若成功生成bin文件,则界面会提示success,用户可在其软件目录下找到生成的bin文件,生成的文件如下:

生成的文件

EMI ⼯具

EMI测试⼯具简介:基于USB HID,需要将APP_MODE配置为APP_MODE_DEBUG_HID(编者这⾥采⽤该模式,从⽽结合log进⾏讲解)或APP_MODE_AUDIO_AUTO,同时开启EMI_TEST_ENABLE宏,以使能EMI测试功能。

流程说明

Step1: 打开工具

打开emi_test_hid_tool⼯具,显⽰USB Connected即说明连接成功。

工具界面

默认pid为9218,若待测设备的pid有变化,可在pid框中输⼊对应的pid并点击Set Pid。

Step2: Enter EMI

配置EMI参数,点击Enter EMI,如图所⽰在RISC-V TDB⼯具中会打印EMI测试已进⼊,并打印对应的配置参数。

Enter EMI

Step3: Set/Get Freq Offset Cap

设置/获取频偏的Cap值。

设置/获取频偏的Cap值

Step4: Read/Write FLASH Freq Offset Cap

读取/写入flash中的频偏Cap值。

读取/写入 flash中的频偏Cap值

Step5: Exit EMI

点击Exit EMI即可退出EMI模式。(注:修改配置,需要点击Exit EMI先退出EMI模式,再点击Enter EMI重新进⼊EMI,从⽽实现配置的修改)

Exit EMI

音频延时工具

概述

本文主要说明Python脚本的使用方法和使用时的注意事项。该脚本的主要功能是将逻辑分析仪抓取到的i2s数据转换为可以播放的pcm格式文件,并通过pcm格式文件相同音频段来测量延时。

注意

  • 对于 Soundbar handbook中的延时测试指标,都是i2s输入输出模式(Lineout延迟会增加约 1.5ms),使用 Audio Precision(AP525)测试仪器进行的测试,如果没有 AP,也可以使用逻辑分析仪来测量延迟。

  • 通过 app_config.h 中的 AUDIO_INTERFACE 宏配置相关输入输出接口,可选项:

    AUDIO_I2S_CODEC:

    作用说明:Audio驱动模式 codec,输入输出接口为line in、lineout;

    AUDIO_I2S_GPIO:

    作用说明:Audio驱动模式 gpio,输入输出接口为i2s in、i2s out;

(1) 目录结构

Bulk_Delay_16kHz.wav: 测试音频

parse_i2s.py: 脚本本体

DirectoryStructure

(2) 脚本执行

执行命令:

python [脚本名] [逻辑分析仪导出的数据文本文件]

ScriptExecution

(3) 硬件连接

如果需要测量SoundbarSDK上下行的延时,那么就要对i2s上下行同时抓取数据,即逻辑分析仪最少要抓取六条线(TxBCK、TxLRCLK、TxDATA、RxBCK、RxLR、RxDATA)上的数据,同时接多几个地。

(4) 使用步骤

1、通过逻辑分析仪抓取数据

由于不同逻辑分析仪导出的数据格式不尽相同,本脚本是基于(Saleae Logic16)导出数据的格式设计的,应该需要使用Saleae Logic16来抓取需要的数据。首先需要Saleae Logic16逻辑分析仪,然后访问其官网 https://support.saleae.com 去下载对应平台的上位机软件。以下是抓取i2s时需要的配置:

Logic2

导出数据:

配置好设置后,在程序根目录下找到Bulk_Delay_16kHz.wav,播放这个音频作为输入(通过i2s),然后用逻辑分析仪上位机软件开始抓取6线上的数据(抓取2~6秒即可)。抓取完成后需要对抓取的数据进行导出,相关操作如下:

(1)首先选中解析器的设置图标,如下图所示:

Export1

(2)然后选择文本文件(*.txt)格式导出,如下图所示:

Export2

2、运行脚本生成数据 将上述导出的文件放在程序根目录下,运行脚本生成数据:

python parse_i2s.py Tx.txt
python parse_i2s.py Rx.txt

主要生成文件如下所示:

Pcm

文件Tx.txt.pcm32是转换i2s in数据后生成的Pcm音频(在原来导出的数据文本文件Tx.txt增加.pcm32后缀);

文件Rx.txt.pcm32是转换i2s out数据后生成的Pcm音频(在原来导出的数据文本文件Rx.txt增加.pcm32后缀)。

脚本说明:

功能是通过Python的字符串操作,将导出的数据文本文件中的音频数据提取出来,转换成pcm文件。

导出的数据文本文件:

LogicData

通过字符串操作将Value值提取出来(不同逻辑分析仪,可能需要根据到处的数据文本文件修改脚本), 并将字符串转成二进制数据,输出到Pcm文件中:

Script

3、查看Pcm文件并比较

打开Audacity,把对应音频导入、配置,如下图所示:

Audacity1

Audacity2

这里以Tx.txt.pcm和Rx.txt.pcm为例,如下图所示:

Audacity3

点击音频右键选择以波形显示(不同版本的audacity右键菜单选项可能不一致,让数据以波形显示即可),如下图所示:

Audacity4

滚动鼠标滚轮放大音频,对相似部分进行对比,选中两端音频的差距并查看时间差,如下图所示:

Audacity5