tanglin1988 发表于 2013-3-31 20:50:49

S3C2440 IIS在线放音(边录边放有问题,求高手指点)

本帖最后由 tanglin1988 于 2013-4-1 10:51 编辑


   使用MICRO2440开发板上自带的UDA1341作为声卡芯片,播放我用AD1974采集到的音频数据,AD与声卡之间用FPGA构建了一个16KB的FIFO,目前我已经实现了先路音一段时间,AD通过FPGA把数据传给ARM保存起来再通过IIS接口给UDA1341播放。

    先录后放没有问题,但是我边录边放(在线模式)的时候确出现了以下问题,百思不得其解,现把问题细细阐述如下,望得高手指点。
    在线模式跟先录音后放音的原理其实是相差不大的,唯一的差别就在于ARM一次性给IIS的数据量不一样,先录后放可能是一次给几十秒的数据,而边录边放就是ARM从FPGA那取几十字节的数就丢给IIS,利用IIS播放这几十字节的时间再去去下一组数据回来,当然AD的采样频率跟IIS播放频率我都是设置成8K的。现在的问题就是:每次边录边放只有前几秒是正常的,后面就会出现严重的声音失真,我用信号源产生正弦波进去再播放出来就能明显看到明显的失真,我怀疑过数据的问题,但是后来做了一个实验,我设置一个循环,取十个数就丢给IIS播放十个数,同时把这十个数保存在一个数组里,这样循环执行8000次,就相当于在线播放了8秒,同时我也保存了这八秒的数据,再一次性给IIS播放出来。我在示波器上看到的现象就是,前面边录音边放音那八秒一半是对的,后半部分波形就出现了失真,最后我把保存的数据一次性给IIS播放,结果就完全是正确的。我就很不明白,数据是一样的数据,为什么前面在线模式下播放就有问题,一次性播放出来就错了呢??希望高手指点一下,在此拜谢了。

现贴上程序执行流程,核心代码和测试图片:
   rGPJDAT = rGPJDAT | 0x0efff;       //RESET=0
    while(rGPJDAT & 0x0400);//等待READY
    Delay(100);
    Uart_Printf("start record and play\n");   

    while(1)
    {
    j=0;
    while(rGPJDAT & 0x200);//等待EF
    temp_size=8;
    while(temp_size--)
    {
   rGPGDAT ^= 0x01;    //从机片选有效
      
   spi_rec = spi_read()<<8;
   spi_rec = spi_read() | spi_rec;//左1声道
   spi_rec = spi_rec&0x0fffc;    //屏蔽最低两位(通道号)
   j++;
      
   spi_rec = spi_read()<<8;
   spi_rec = spi_read() | spi_rec;//右1声道
   spi_rec = spi_rec&0x0fffc;
   j++;
   
   spi_rec = spi_read()<<8;
   spi_rec = spi_read() | spi_rec;//左2声道
   spi_rec = spi_rec&0x0fffc;
   j++;
      
   spi_rec = spi_read()<<8;
   spi_rec = spi_read() | spi_rec;//右2声道
   spi_rec = spi_rec&0x0fffc;
   j++;
   rGPGDAT ^= 0x01;      //从机片选无效
    }   
//Uart_Printf("start play\n");   
    s=2;
    j=8;
       
        //检测输出缓冲区里的数据个数                       
        while(z_IISFCON & (1 << 10));//若I2SFIFO里面数据个数小于16则将取回来的其中两个通道的数一次性丢给FIFO,8*2*16bit不会溢出
        while(j)
           {
                                z_IISFIFO_DATA = spi_rec;
                                s++;                       
                                z_IISFIFO_DATA = spi_rec;
                                j--;
                                s=s+3;               
           }
        }

aozima 发表于 2013-3-31 21:15:41

初步怀疑是数据断流引起的,建议加双缓冲。

aozima 发表于 2013-3-31 21:21:56

AD1974采集到的音频数据,AD与声卡之间用FPGA构建了一个16KB的FIFO。
这里看似没有问题,但ARM从FPGA中怎么读取数据呢?

建议贴一下整个流程以便分析。
另外,可以用逻辑分析仪抓一下实际数据。

aozima 发表于 2013-3-31 21:50:57

本帖最后由 aozima 于 2013-3-31 21:53 编辑

I2S驱动改进建议:
I2S的驱动中按块传输数据,数据块可以根据实际情况设计,至少也得是I2S FIFO的N倍。
I2S的驱动中内建M个数据块,形成1个环形缓冲区。
I2S使用DMA传输数据,以I2S FIFO非满为触发条件,当1块数据传输完成,进入中断,马上启动下一1块的传输。
因为I2S本身有FIFO,所以这个过程不会造成数据断流。

当DMA中断后,发现所有数据块都无效,可以停止传输或播放填充数据,并给出指示。
如果在过程中收到指示就收明是应用程序给数据的速度不够快。
页: [1]
查看完整版本: S3C2440 IIS在线放音(边录边放有问题,求高手指点)