android_alsa_audio

来源:互联网 发布:mac国内网游 编辑:程序博客网 时间:2024/05/29 08:40

1. pcm

 http://wenku.baidu.com/view/7691023331126edb6f1a109f.html 

2. http://www.amobbs.com/thread-3901903-1-1.html telechips  资料


http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3212045&bbs_page_no=2&bbs_id=1000



一种使用SPI连接I2S接口的音频DAC的方法


年前搞了个LPC2148最小板,写了些简单的程序后,打算做一个WAV播放器玩玩。结果发现LPC2148不带I2S接口,而非I2S接口的音频DAC基本没有,这下有些后悔买的是不带I2S的片子。后来在网上转啊转,终于发现有人成功用SPI接口模拟I2S的:


1
http://www.k9spud.com/traxmod/


下了源代码后读了半天始终没搞懂SPICS信号是怎么控制的,而且PCM1770我这里还买不到。
2
、坛子里面有人用LPC2136连接PCM1716,不过据作者本人说只能有一个声道有声音
……
最后只好自己搞,研究了两个礼拜,终于成功搞了出来。

NXP的网站上可以找到I2S接口的说明书,分析一下I2S总线特点:1、数据不能断流;2、时序上有严格的要求。这两条决定了如果我打算用没有FIFOSPI接口模拟I2S总线,SPI就不可能工作在主机方式,事实上两面两个成功的例子当中SPI也都是工作在从机方式的。I2S总线上的数据位可以从16bit-24
bit
不等,为了使SPI就口有足够的时间装填数据,因此选择24bit的数据格式。剩下的就是如何产生I2S总线的2个信号BCLKLRCK,音频DAC的工作信号MCLKSPI接口的CS信号的问题了。起初打算用LPC2148自己产生这些信号,结果发现不行,因为没有足够的PWM通道。最后想了一个不太经济的方法,就是用单片机产生这些信号。起初用的是tiny2331 — 两路独立的PWMBCLKLRCK) 系统时钟输出(MCLK),但是CS的时序时钟调不好;后来打算换成mega8 — 三路独立的PWMBCLKLRCKCS) + 74HC04MCLK);在查找手册的时候发现mega48tiny2313一样有系统时钟输出功能,重要的是mega48时可以跑20MHz的,正好手头有一片mega48,就用它了。

整理一下方案:
I2S
数据输出使用LPC2148SPI接口,16-bit从机方式,MISO输出I2S数据,在中断中加载下一输出数据;
mega48
工作在16.9344.MHz,分别由PB0(设置熔丝位)、PD6PB1PB3输出MCLKLRCKBCLKCS,程序比较简单如下

#include <avr\io.h>
#include <util\delay.h>

#define SYS_LED     PD1

#define SET_LED  PORTD &= ~_BV(SYS_LED)
#define CLR_LED  PORTD |=  _BV(SYS_LED)

#define NOP __asm__ __volatile__("nop")

int main(void){
CLR_LED;
DDRB = _BV(PB0) | _BV(PB1) | _BV(PB3);
DDRD = _BV(PD6);

_delay_ms(10);

/* use Timer0 to generate LRCK : CTC mode, TOP = OCR0A, OCR0A toggle */
OCR0A  = 192 - 1;
TCCR0A = 0x42;

/* use Timer1 to generate SSEL : fast PWM mode, TOP = ICR1, OCR1A set on match and clear on TOP */
ICR1H = 0;
ICR1L = 192 - 1;
OCR1AH = 0;
OCR1AL = 128 - 1 - 2;
TCCR1A = 0xC2;

/* use Timer2 to generate BCLK : CTC mode, TOP = OCR2A, OCR1A toggle */
OCR2A  = 4 - 1;
TCCR2A = 0x42;

TCCR2B = 0x01;  // BCLK start
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
TCCR0B = 0x01;  // LRCK start
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
NOP;
TCCR1B = 0x19;  // SSEL start

SET_LED;
while(1);

return 0;
}

用上述方法连接CS4334成功,两个声道均能正常发生;LPC2148中开两个1K(小了没试过)的Buffer可以流畅播放44.1KHz 16bitWAV文件(经过FAT系统,用fatgetc读取数据)。

不过用此法连接PCM1742的时候,输出有极大的噪音,不知道是DAC输出部分没搞好还是芯片有问题。有兴趣的朋友可以交流一下


SD卡看下图。模拟的难点不是产生BCLKLRCK,而是SPICS信号;因为这个CS信号并不是在LRCK跳变的时候变低的,而是在跳变之后的一个SCLK周期之后变低的,而且16SCLK周期之后要变高。也就是说CS信号的周期是LRCK的二倍,占空比低:高 = 21,与LRCK有固定“相位差”。我之前用LPC2148的定时器捕获SCLK然后产生CS信号,没能成功,主要是同步调不好,后来干脆这部分就全用单片机处理


以我做的为例:WAV音频文件的采样率是44.1KHz,也就是说LRCK的频率就是44.1KHz(高电平一个声道,低电平另一个声道),这个频率也称为fs;一般音频DAC要求MCLK256倍或者384倍的fs,我这里i2s采用的是24-bit格式,为了使MCLK能整除因此采用的是MCLK=384*fs,也就是16.9344MHz;而BCLK=fs*i2s位数*2=2.1168MHz。综上,采用mega48工作在16.9344MHzPB0输出系统时钟;一个定时器工作在CTC模式、不分频、计时192-1输出一翻转,这样得到LRCK;一个定时器工作在CTC模式、不分频、计时4-1输出一翻转,这样得到BCLK;一个定时器工作在PWM模式,周期192-1清零、比较匹配128-1-2(略小于16BCLK周期)时置位,这样得到SPI的片选信号。

你的意思是mega48SPI设置成主机向DAC送信号吧,这样做你的BCLK是不连续的,会出现问题


给大家一个技术参考,timsp430i2spdf
一直没找到焊接TLV320AIC23B的转接板,心痒了好久
这个资料应该很有用

另外TLV320AIC23B还有一个dsp模式
nxp
luminaryssp接口(估计他们的ip核是一样的)都有一个ti serial模式,
23b可以非常方便的连接.(时序也有少许不同,但更好处理)


原创粉丝点击