解码-VS1053B简解及实现(三)

定义:

VS1053是荷兰VLSI公司推出的一款高性能编解码芯片。

该芯片可以实现对MP3/OGG/WMA/FLAC/WAV/AAC/MIDI等音频格式的解码。

同时还可以支持ADPCM/OGG等格式的编码。

 

特点:

VS1053芯片内部还带了一个可变采样率的立体声ADC(支持咪头或线路输入)、一个高性能立体声DAC及音频耳机放大器。

 

●支持音量调节、高低音控制和EarSpeaker空间效果。

●低功耗 。

 

接口:

VS1053通过SPI接口来接受输入的音频数据流,它可以是一个系统的从机,也可以作为独立的主机。本例程,我们把它当成从机使用。我们通过SPI口向VS1053不停的输入音频数据,它就会自动帮我们解码了,然后从输出通道输出音乐,这时我们接上耳机就能听到所播放的歌曲了。

 

VS1053SPI数据传送,分为SDISCI,分别用来传输数据/命令。SDI采用SPI协议,不过,数据传输受DREQ控制,主机在判断DREQ有效(高电平)之后,直接发送数据即可(一次可以发送32个字节)。

 

SCI 寄存器,重点研究 MODE 等七个寄存器。

 

 

基本设置:

    • MODE寄存器(0X00

SM_RESET软件复位,建议在每播放一首歌曲之后,软复位一次。

SM_SDINEW模式设置位,设置为1,选择VS1002新模式(本地模式)

 

    • BASS寄存器(0X02

声音设置:

高低音设置用BASS寄存器。

EarSpeaker MODE来设置。

 

    • CLOCKF寄存器(0X03

CLOCKF,一般设置此寄存器的值为0X9800,表示外部时钟是12.288M,内部时钟频率为输入时钟频率的3倍,倍频增量为1.5倍。

 

    • DECODE_TIME寄存器(0X04

它是一个累计时间,在每首歌播放之前,需要把它清空一下(给寄存器写0),以得到这首歌的准确解码时间。

 

    • HDAT0&HDAT1寄存器(0X08&0X09

这两个寄存器,是数据流头寄存器,不同的音频文件,读出来的值意义不一样,我们可以通过这两个寄存器来获取音频文件的码率,从而可以计算音频文件的总长度。

    • VOL寄存器(0X0B

该寄存器用于控制VS1053的输出音量,该寄存器可以分别控制左右声道的音量,每个声道的控制范围为0~254,每个增量代表0.5db的衰减,所以该值越小,代表音量越大。比如设置为0X0000则音量最大,而设置为0XFEFE则音量最小。

       注意:如果设置VOL的值为0XFFFF,将使芯片进入掉电模式!

 

VS1053初始化步骤

①复位VS1053

      包括硬复位和软复位,让VS1053恢复初始状态,准备解码下一首歌曲。在每首歌曲播放之前都可以执行一次硬件复位和软件复位(推荐每首歌播放之前,只进行软件复位,硬件复位一次,会呲呲呲的响,出现大的问题,可以进行硬件复位。),以便更好的播放音乐。

②配置VS1053的相关寄存器

       这里我们配置的寄存器包括VS1053的模式寄存器(MODE)、时钟寄存器(CLOCKF)、音调寄存器(BASS)、音量寄存器(VOL)等。

③发送音频数据

       经过以上配置以后,我们剩下来要做的事情,就是往VS1053里面发送音频数据,只要是VS1053支持的音频格式,直接往里面丢就可以了,VS1053会自动识别,并进行播放。不过,发送数据要在DREQ信号的控制下有序的进行,不能乱发。这个规则很简单:只要DREQ变高,就向VS1053发送32个字节。然后继续等待DREQ变高,直到音频数据发送完。

 

暂停:                       

就算DREQ来了,也不传输数据。

快进/后退: 偏移之后,再传输数据。

 

SPI速率的确认:

 SCI 读取的时候,SPI 不能超过4M.

  SCI 和 SDI 写入的时候,SPI 不能超过9M.

 CLK的值 12.28 *3  约等于 36M. (外部时钟是12.28M,内部时钟频率为输入时钟频率的3倍,所以clk = 12 * 3)

 

获取码率:

根据HDAT0&HDAT1的值,可以获取码率值,从而知道音频的播放时长。

对于WAV , MIDI等格式。因为HDAT0的位长是16位,所以表示的最大值是 65535,那速率65535 * 8 = 524280 = 524K,速率超过524Kbps的就码率就准确了,算的时长就不正确了。

对于mp3,因为它的速率是根据查表法得到的,不是根据 HDAT0 得到的,所以它的时长计算,比较准确。

 

装载patch:

VLSI VS10XX 系列芯片都会有一些 patch(插件),用于修复芯片存在的 bug,或者

用于增加新的功能。 VS10XX patch 其实就是一段可以在 VS10XX 芯片上面执行的代码,

VLSI 官方提供, 可以在: http://www.vlsi.fi/en/support/software/vs10xxpatches.html 这个地

址下载到。

patch 一般有 2 种格式:一种是采用 16 位无符号数组存储的, 是采用了游程编码(RLE

压缩算法,进行过压缩的格式。另外一种,是直接采用 2 8 位数组存储的, 没有进行压缩

的格式。

推荐采用 16 位无符号存储格式的 patch,更省空间。 VS1053 采用的 16 RLE 压缩编

码规则如下:

1, 首先读寄存器地址 addr(第 1 个数据)和重复数 n(第 2 个数据)。

2, 如果 n&0X8000 为真,那么将下一个数据(第 3 个数据)重复写 n 次到寄存器 addr

3, 如果 n&0X8000 为假,则写接下来的(第 3 个数据开始) n 个数据到寄存器 addr

4, 重复以上 3 步,直到数组结束。

VS1053WAV 录音无数据输出的 bug,修正 patch 如下:

//VS1053 WAV 录音有 bug,这个 plugin 可以修正这个问题

const u16 wav_plugin[40]=/* Compressed plugin */

{

0x0007, 0x0001, 0x8010, 0x0006, 0x001c, 0x3e12, 0xb817, 0x3e14, /* 0 */

0xf812, 0x3e01, 0xb811, 0x0007, 0x9717, 0x0020, 0xffd2, 0x0030, /* 8 */

0x11d1, 0x3111, 0x8024, 0x3704, 0xc024, 0x3b81, 0x8024, 0x3101, /* 10 */

0x8024, 0x3b81, 0x8024, 0x3f04, 0xc024, 0x2808, 0x4800, 0x36f1, /* 18 */

0x9811, 0x0007, 0x0001, 0x8028, 0x0006, 0x0002, 0x2a00, 0x040e,

};

根据前面提到的原则,得到: addr=0X0007n=0X0001,即将接下来的 0X8010 写入寄

存器 0X0007 即可,之后: addr=0X0006n=0X001C,即将接下来的 28 个数据,写入寄存

0X0006。后续的以此类推。

因此,我们可以得出 patch 加载函数(即 RLE 解压):

//vs10xx 装载 patch.

//patchpatch 首地址

//lenpatch 长度

void VS_Load_Patch(u16 *patch,u16 len)

{

u16 i; u16 addr, n, val;

for(i=0;i<len;)

{

addr = patch[i++];

n = patch[i++];

if(n & 0x8000U) //RLE run, replicate n samples

{

n &= 0x7FFF;

val = patch[i++];

while(n--)VS_WR_Cmd(addr, val);//重复写入 N

}else //copy run, copy n sample

{

while(n--) //写入接下来的 N 个数据

{

val = patch[i++];

VS_WR_Cmd(addr, val);

}

}

}

}

我们只需要将 patch 存储在程序里面,然后调用 VS_Load_Patch,就可以将 patch 加载

VS1053 里面,这样便可以修复 VS1053 bug(如: WAV 录音的时候,不输出数据流的

bug),或者添加新的功能(如:支持播放 flach、支持频谱显示等)。

 

得到MP3的播放时间 n sec:

u16 n = VS_RD_Reg(SPI_DECODE_TIME);

n是个累加值

可以通过写0,重设解码时间:

void VS_Reset_DecodeTime(void)

{

VS_WR_Cmd(SPI_DECODE_TIME,0x0000);

VS_WR_Cmd(SPI_DECODE_TIME,0x0000);//操作两次

}

我们需要在每首歌播放之前把它清空一下,以得到这首歌的准确

解码时间

 

读取VS1053B ram 值的方法:

    • 先把地址写到 SPI_WRAMADDR里,
    • 再从SPI_WRAM读取数据。即是从ram 的 addr 出读取数据。

 

VS_WR_Cmd(SPI_WRAMADDR, addr);

res=VS_RD_Reg(SPI_WRAM);

 

设置音频的播放速度:

//设置播放速度

//t:0,1,正常速度;2,2倍速度;3,3倍速度;4,4倍速

void VS_Set_Speed(u8 t)

{

VS_WR_Cmd(SPI_WRAMADDR,0X1E04);        //速度控制地址 

while(VS_DQ==0);                                 //等待空闲          

VS_WR_Cmd(SPI_WRAM,t);                         //写入播放速度

}

 

正弦测试:

    • 硬件复位
    • 设置音量
    • 设置测试模式
    • 发送测试指令 0x53 0xef 0x6e n 0x00 0x00 0x00 0x00
    • 发送退出测试指令 0x45 0x78 0x69 0x74 0x00 0x00 0x00 0x00

 

Ram 测试:

    • 硬件复位
    • 设置音量
    • 设置测试模式
    • 发送测试指令 0x4d 0xea 0x6d 0x54 0x00 0x00 0x00 0x00
    • 读取 SPI_HDAT0的值, 如果值为0x83FF,则表明RAM完好。

 

 

 

 

VS1053B要实现的功能:

获取码率,获取歌曲的时长。

切换歌曲(datasheet 取消播放)

设置功能:设置音量,设置高低频率,高低增益,空间效果等等。

装载patch

 

总结:VS1053是一款高性能编解码芯片。可解码,也可编码。

通过SPI 传输音频数据 和 命令。

传输数据的时候,使用的是SDI协议格式,

传输命令的时候,使用的是SCI传输格式。

通过SCI传输一些命令,能更改SCI的7个寄存器的值,从而修改这颗芯片的工作模式,工作时钟,功能模式(高低音,音效,音量等等。),读取ram的值,获取音频速率等等。

通过SDI模式,发送音频数据。

VS1053B工作的流程:

1.复位VS1053B

2.配置SCI的寄存器。比如音量,音效,时钟,模式等等。

3. 打需要的补丁。

4. 在DREQ为高有效的时候,进行ram ,正弦的测试。测试通过后,开始发送音频数据。

只要通过SPI接口给VS1053B传输音频数据,它就可以自动的完成解码功能。具体细节查看datasheet.

使用解码芯片需要注意的点:

  1. 驱动音频接口,去传输音频。

  2. 驱动控制接口去,配置解码芯片。(音频和控制接口,有可能硬件口是一个。有可能是分开的。)

  3. 配置解码芯片的项目:音量,音效等等。

  4. 获取信息:获取一首歌的总时间 和 播放时间等等

  5. 测试:通过一些测试项,去测试硬件。

 

 

发布了105 篇原创文章 · 获赞 30 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/happygrilclh/article/details/101943202