AnsweredAssumed Answered

STM32F4Discovery read I2S2 data, delay it, and send to I2S3

Question asked by karpavicius.linas on Jul 9, 2016
Latest reply on Jul 12, 2016 by markt
Hello
I am trying to delay audio sygnal before it is send to I2S dac.

DAC is working, can get Sinus waveform without problem.

Question is, what is the correct way to take 48Ksps 16b data from I2S2, and send it to I2S3?

This is my code, i hear lot of metallic sound, and it looks like only SD and CK (PB15 and PB13) does effect sound, and LRCK, BCK does nothing to sound (connected or unconnected PC9 and PB12)

If any one can spot the problem, please help me :)

#include "main.h"
#include "math.h"
 
 
float NOTEFREQUENCY =0.015;     //frequency of saw wave: f0 = 0.5 * NOTEFREQUENCY * 48000 (=sample rate)
float NOTEAMPLITUDE =18000.0;      
 
int16_t sinusas[2400];
void PINS(void);
uint32_t cnt = 0;
int16_t data = 0;
int main(void)
{
  SystemInit();
  PINS();
  int i = 0;
  while(i<2400)
  {
    sinusas[i]=(int)(NOTEAMPLITUDE*sinf((2.0f*3.14f*i)/(2400.0f)));
    i++;
  }
 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
 
  codec_init();
  codec_ctrl_init();
 
  I2S_Cmd(CODEC_I2S, ENABLE);
  I2S_Cmd(SPI2, ENABLE);
  while(1)
  {
        if (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE))
    {
   if(cnt & 0x00000001)
  {
 
      data = (int16_t)SPI_I2S_ReceiveData(SPI2);
   
       
    }
    if (SPI_I2S_GetFlagStatus(CODEC_I2S, SPI_I2S_FLAG_TXE))
    {
      SPI_I2S_SendData(CODEC_I2S, data/10);
    }
  }
  cnt++;
     
     
  }
    
    while(1)
    {
 
        if (SPI_I2S_GetFlagStatus(CODEC_I2S, SPI_I2S_FLAG_TXE))
        {
            SPI_I2S_SendData(CODEC_I2S, (int16_t)sinusas[i]);
 
            //only update on every second sample to insure that L & R ch. have the same sample value
            /*if (sampleCounter & 0x00000001)
            {
                sawWave += NOTEFREQUENCY;
                if (sawWave > 1.0)
                    sawWave -= 2.0;
 
                filteredSaw = updateFilter(&filt, sawWave);
 
                sample = (int16_t)sinusas[sampleCounter];//[(NOTEAMPLITUDE*filteredSaw);
            }*/
            sampleCounter++;
        }
        i++;
        if(i>2399)
          i=0;
 
        if (sampleCounter==48000)
        {
            LED_BLUE_OFF;
 
        }
        else if (sampleCounter == 2399)
        {
            LED_BLUE_ON;
            sampleCounter = 0;
        }
 
    }
}
 
void PINS(void)
{
    GPIO_InitTypeDef PinInitStruct;
    GPIO_StructInit(&PinInitStruct);
    I2S_InitTypeDef I2S_InitType;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB, ENABLE);
         
    RCC_I2SCLKConfig(RCC_I2S2CLKSource_Ext);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    RCC_PLLI2SCmd(ENABLE);
 
    PinInitStruct.GPIO_Mode = GPIO_Mode_AF;
    PinInitStruct.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_Init(GPIOB, &PinInitStruct);
    PinInitStruct.GPIO_Pin = GPIO_Pin_9;
    GPIO_Init(GPIOC, &PinInitStruct);
 
    //prepare output ports for alternate function
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2); //WS LR CLK
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); //CK
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); //SDIN
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource9,  GPIO_AF_SPI2);  //I2S2_CKIN
    // configure I2S port
    SPI_I2S_DeInit(SPI2);
    I2S_InitType.I2S_AudioFreq = I2S_AudioFreq_48k;
    I2S_InitType.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
    I2S_InitType.I2S_DataFormat = I2S_DataFormat_16b;
    I2S_InitType.I2S_Mode = I2S_Mode_SlaveRx;
    I2S_InitType.I2S_Standard = I2S_Standard_Phillips;
    I2S_InitType.I2S_CPOL = I2S_CPOL_High;
         
    I2S_Init(SPI2, &I2S_InitType);
        I2S_Cmd(SPI2, ENABLE);
}

Outcomes