/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f0xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f0xx.c file
  */
  /* I2S peripheral Configuration */
  I2S_Config();

  /* Enable the Tamper button */
  STM_EVAL_PBInit(BUTTON_TAMPER, BUTTON_MODE_GPIO);

  /* Initialize the LEDs */
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDInit(LED1);

#if defined (I2S_MASTER_TRANSMITTER) 
  while (STM_EVAL_PBGetState(BUTTON_TAMPER) != RESET)
  {}
  
  /* Enable the I2S1 TX Interrupt */
  SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);

  /* Enable the I2S */
  I2S_Cmd(SPI1, ENABLE);

  while(TxIdx < 32);

#elif defined (I2S_SLAVE_RECEIVER)
  /* Enable the I2S1 RXNE Interrupt */
  SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
  /* Enable the I2S */
  I2S_Cmd(SPI1, ENABLE);
  /* Wait the end of communication */
  while (RxIdx < 32);

  /* Check if the data transmitted from Master Board and received by
  Slave Board are the same */
  TransferStatus = Buffercmp(I2S_Buffer_Rx, (uint16_t*)I2S_Buffer_Tx, 32);

  if (TransferStatus == PASSED) /* successful transfer */ 
  {
    /* Green Led On */
    STM_EVAL_LEDOn(LED1);
    STM_EVAL_LEDOff(LED3);
  }
  else /* unsuccessful transfer */
  {
    /* Red Led On */
    STM_EVAL_LEDOn(LED3);
    STM_EVAL_LEDOff(LED1);
  }
#endif

  /* Infinite loop */
  while (1)
  {}
}
Example #2
0
//*----------------------------------------------------------------------------
//* Function Name       : I2S_Block_Process
//* Object              :
//* Object              :
//* Input Parameters    :
//* Output Parameters   :
//* Functions called    :
//*----------------------------------------------------------------------------
void I2S_Block_Process(uint32_t txAddr, uint32_t rxAddr, uint32_t Size)
{
	txbuf = txAddr;
	rxbuf = rxAddr;
	szbuf = Size;
	
	// Configure the tx buffer address and size
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)txAddr;
	DMA_InitStructure.DMA_BufferSize = (uint32_t)Size;

	// Configure the DMA Stream with the new parameters
	DMA_Init(AUDIO_I2S_DMA_STREAM, &DMA_InitStructure);

	// Configure the rx buffer address and size
	DMA_InitStructure2.DMA_Memory0BaseAddr = (uint32_t)rxAddr;
	DMA_InitStructure2.DMA_BufferSize = (uint32_t)Size;

	// Configure the DMA Stream with the new parameters
	DMA_Init(AUDIO_I2S_EXT_DMA_STREAM, &DMA_InitStructure2);

	// Enable the I2S DMA Streams
	DMA_Cmd(AUDIO_I2S_DMA_STREAM, ENABLE);   
	DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, ENABLE);   

	// If the I2S peripheral is still not enabled, enable it
	if ((CODEC_I2S->I2SCFGR & 0x0400) == 0)
	{
		I2S_Cmd(CODEC_I2S, ENABLE);
	}

	if ((CODEC_I2S_EXT->I2SCFGR & 0x0400) == 0)
	{
		I2S_Cmd(CODEC_I2S_EXT, ENABLE);
	}
}
Example #3
0
void I2S_Enable(){
  /* If the I2S peripheral is still not enabled, enable it */
  if ((CODEC_I2S->I2SCFGR & 0x0400) == 0){
    I2S_Cmd(CODEC_I2S, ENABLE);
  }
  if ((CODEC_I2S_EXT->I2SCFGR & 0x0400) == 0){
    I2S_Cmd(CODEC_I2S_EXT, ENABLE);
  }
}
Example #4
0
//*----------------------------------------------------------------------------
//* Function Name       : I2S_Block_Stop
//* Object              :
//* Object              :
//* Input Parameters    :
//* Output Parameters   :
//* Functions called    :
//*----------------------------------------------------------------------------
void I2S_Block_Stop(void)
{
	I2S_Cmd(CODEC_I2S_EXT, DISABLE);
	I2S_Cmd(CODEC_I2S,     DISABLE);

	DMA_Cmd(AUDIO_I2S_EXT_DMA_STREAM, DISABLE);
	DMA_Cmd(AUDIO_I2S_DMA_STREAM,     DISABLE);

	SPI_I2S_DMACmd(CODEC_I2S_EXT, SPI_I2S_DMAReq_Rx, DISABLE);

	NVIC_DisableIRQ(AUDIO_I2S_EXT_DMA_IRQ);

	DMA_ITConfig(AUDIO_I2S_EXT_DMA_STREAM, DMA_IT_TC | DMA_IT_HT, DISABLE);
}
Example #5
0
/*******************************************************************************
* Function Name  : INTR_RXSTSQLVL_ISODU_Callback
* Description    : Rx FIFO Status Queue Level, Data Update interrupt callback routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void INTR_RXSTSQLVL_ISODU_Callback(void)
{
  /* Check if the USB transfer has reached the half of the global buffer */
  if(IsocBufferIdx == (NUM_SUB_BUFFERS / 2))
  {
    /* Check if the DMA is already enabled or not */
    if ((DMA1_Channel5->CCR & 0x1) == 0x0)
    {   
      /* Re-Initialize the number of data to be transferred */
      DMA1_Channel5->CNDTR = (uint16_t)((ISOC_BUFFER_SZE * NUM_SUB_BUFFERS) / 2);
      
      /* Enable DMA1 Channel5 */
      DMA_Cmd(DMA1_Channel5, ENABLE);  
      
      /* Enable I2S DMA request for TX */
      SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); 
      /* Enable the I2S cell */
      I2S_Cmd(SPI2, ENABLE);  
    }

    /* Wait till the TC flag is ON (direct register access to optimize time) */
    while (((DMA1->ISR & (uint32_t)0x00020000) == 0))
    {}
    
    /* Clear All DMA1 channel 5 flags */
    DMA_ClearFlag(DMA1_FLAG_GL5);
  } 
}
Example #6
0
/**
  * @brief  Starts playing audio stream from the audio Media.
  * @param  None
  * @retval None
  */
void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
{         
  if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
  {
    /* Configure the buffer address and size */
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
    DMA_InitStructure.DMA_BufferSize = (uint32_t)Size/2;
    
    /* Configure the DMA Stream with the new parameters */
    DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
    
    /* Enable the I2S DMA Stream*/
    DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);   
  }
#ifndef DAC_USE_I2S_DMA
  else
  {
    /* Configure the buffer address and size */
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
    DMA_InitStructure.DMA_BufferSize = (uint32_t)Size;
    
    /* Configure the DMA Stream with the new parameters */
    DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
    
    /* Enable the I2S DMA Stream*/
    DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
  }
#endif /* DAC_USE_I2S_DMA */
  
  /* If the I2S peripheral is still not enabled, enable it */
  if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
  {
    I2S_Cmd(CODEC_I2S, ENABLE);
  }
}
Example #7
0
/**
  * @brief  Pauses or Resumes the audio stream playing from the Media.
  * @param  Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
  *              from 0) to resume. 
  * @param  Addr: Address from/at which the audio stream should resume/pause.
  * @retval None
  */
static void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr)
{
  /* Pause the audio file playing */
  if (Cmd == AUDIO_PAUSE)
  {   
    /* Disable the I2S DMA request */
    SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, DISABLE);

    /* Pause the I2S DMA Stream 
        Note. For the STM32F40x devices, the DMA implements a pause feature, 
              by disabling the stream, all configuration is preserved and data 
              transfer is paused till the next enable of the stream.
              This feature is not available on STM32F40x devices. */
    DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
  }
  else /* AUDIO_RESUME */
  {
    /* Enable the I2S DMA request */
    SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);
  
    /* Resume the I2S DMA Stream 
        Note. For the STM32F40x devices, the DMA implements a pause feature, 
              by disabling the stream, all configuration is preserved and data 
              transfer is paused till the next enable of the stream.
              This feature is not available on STM32F40x devices. */
    DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
    
    /* If the I2S peripheral is still not enabled, enable it */
    if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
    {
      I2S_Cmd(CODEC_I2S, ENABLE);
    }    
  } 
}
Example #8
0
/*******************************************************************************
* Function Name  : I2S_Config
* Description    : Configure the I2S Peripheral.
* Input          :  - Standard: I2S_Standard_Phillips, I2S_Standard_MSB or I2S_Standard_LSB
*                   - MCLKOutput: I2S_MCLKOutput_Enable or I2S_MCLKOutput_Disable
*                   - AudioFreq: I2S_AudioFreq_8K, I2S_AudioFreq_16K, I2S_AudioFreq_22K,
*                                I2S_AudioFreq_44K or I2S_AudioFreq_48K
* Output         : None
* Return         : None
*******************************************************************************/
static void I2S_Config(uint16_t Standard, uint16_t MCLKOutput, uint16_t AudioFreq)
{
    I2S_InitTypeDef I2S_InitStructure;

    /* Enable I2S2 APB1 clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

    /* Deinitialize SPI2 peripheral */
    SPI_I2S_DeInit(SPI2);

    /* I2S2 peripheral configuration */
    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
    I2S_InitStructure.I2S_Standard = Standard;
    I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
    I2S_InitStructure.I2S_MCLKOutput = MCLKOutput;
    I2S_InitStructure.I2S_AudioFreq = AudioFreq;
    I2S_InitStructure.I2S_CPOL = I2S_CPOL_High;
    I2S_Init(SPI2, &I2S_InitStructure);

    /* Disable the I2S2 TXE Interrupt */
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);

    /* Enable the SPI2/I2S2 peripheral */
    I2S_Cmd(SPI2, ENABLE);
    printf("\n\r I2S peripheral Config finished");
}
Example #9
0
/**
  * @brief  I2S_Stop 停止iis总线
  * @param  none
  * @retval none
  */
void I2S_Stop(void)
{		
	/* 禁能 SPI2/I2S2 外设 */
	//SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);
	I2S_Cmd(SPI2, DISABLE);	

	DMA_Cmd(DMA1_Channel5, DISABLE);
}
Example #10
0
/*******************************************************************************
* Function Name  : INTR_SOFINTR_Callback
* Description    : Start of frame callback function.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void INTR_SOFINTR_Callback(void)
{
  static __IO uint32_t EmptyFrameCounter = 0;
 
  /* If frame hasn't changed and the DMA is enabled */
  if (IsocBufferIdx == PrevFrame) 
  {
    /* Empty packet state */
    EmptyFrameCounter++;
  }
  else 
  {
    /* Update status */
    PrevFrame = IsocBufferIdx;
    /* Streaming Active state */
    EmptyFrameCounter = 0;
  }
 
  /* Stream Inactive state */
  if (EmptyFrameCounter == 5)
  {  
    /* Mute the audio codec to avoid spurious noise */
    CODEC_Mute(MUTE_ON);
    
    /* Disable the I2S and the DMA request */
    SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);
    I2S_Cmd(SPI2, DISABLE);
    
    /* Disable the DMA channel and clear all its flags*/
    DMA1_Channel5->CCR &= 0xFFFFFFFE;   
    DMA_ClearFlag(DMA1_FLAG_GL5);
    
    /* Enable the I2S interrupt to continue generating the clocks for the audio codec
    otherwise there will be a noise on the line when no file is played */
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE); 
    I2S_Cmd(SPI2, ENABLE);
        
    /* Reset counters */
    IsocBufferIdx = 0;
    PrevFrame = 0;  
    
    /* Idle state */
    EmptyFrameCounter ++;
  }
}
Example #11
0
static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag)
{
#if !CODEC_MASTER_MODE
    /* enable I2S */
    I2S_Cmd(CODEC_I2S_PORT, ENABLE);
#endif

    return RT_EOK;
}
Example #12
0
/*******************************************************************************
* Function Name  : EP1_OUT_Callback
* Description    : Endpoint 1 out callback routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void EP1_OUT_Callback(void)
{
  DMA_InitTypeDef DMA_InitStructure;

#ifdef USE_STM3210C_EVAL
  /* Get the Endpoint descriptor pointer */
  ep = PCD_GetOutEP(ENDP1 & 0x7F);

  /* Enable the Endpoint transfer (since the the Read Endpoint function is 
     not called) */
  OTGD_FS_EPStartXfer(ep);
  
  /* Toggle the data PID */
  if (ep->even_odd_frame != 0)
  {
    ep->even_odd_frame = 0;
  }
  else
  {
    ep->even_odd_frame = 1;    
  }
  
  /* If Half of global buffer has been filled and DMA is still not enabled, 
     Re-configure the DMA and unMute the codec */
#if (NUM_SUB_BUFFERS == 2)
  if (((DMA1_Channel5->CCR & 0x1) == 0) && (IsocBufferIdx == 1))
#else
  if (((DMA1_Channel5->CCR & 0x1) == 0) && (IsocBufferIdx == ((NUM_SUB_BUFFERS / 2) - 1)))
#endif /* NUM_SUB_BUFFERS */    
  {       
    /* Disable the mute mode */
    CODEC_Mute(MUTE_OFF);    
    
    /* Disable the I2S before starting configuration to avoid spurious transfer */
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
    I2S_Cmd(SPI2, DISABLE);
    
    /* Initialize the DMA1 Channel5 to its default values */
    DMA_DeInit(DMA1_Channel5);
    
    /* Configure the DMA parameters */
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)((uint16_t*)IsocBuff);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI2_DR_Address;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = (ISOC_BUFFER_SZE * NUM_SUB_BUFFERS) / 2; /* Divided by 2 because USB data are 8 bit and I2S buffer is 16 bit */
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;        
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  }  
#endif /* USE_STM3210C_EVAL */
}
Example #13
0
//???????????
void Audio_MAL_Play(u32 Addr, u32 Size)
{	
  	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr;//??????????
  	DMA_InitStructure.DMA_BufferSize = (uint32_t)Size/2;
  	DMA_Init(DMA1_Channel5, &DMA_InitStructure);
  	DMA_Cmd(DMA1_Channel5, ENABLE);//I2S DMA??   
	
  	if ((SPI2->I2SCFGR & I2S_ENABLE_MASK) == 0)
		I2S_Cmd(SPI2, ENABLE);//?I2S?????,???
}
/**
  * @brief Restores the Audio Codec audio interface to its default state.
  * @param  None.
  * @retval None.
  */
static void Codec_AudioInterface_DeInit(void)
{
  /* Disable the CODEC_I2S peripheral (in case it hasn't already been disabled) */
  I2S_Cmd(CODEC_I2S, DISABLE);
  
  /* Deinitialize the CODEC_I2S peripheral */
  SPI_I2S_DeInit(CODEC_I2S);
  
  /* Disable the CODEC_I2S peripheral clock */
  RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, DISABLE); 
}
Example #15
0
/*******************************************************************************
* Function Name  : I2S_Config
* Description    : Initializes the I2S peripheral.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
static void I2S_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  I2S_InitTypeDef I2S_InitStructure;  

  /* Enable GPIOB, GPIOC and AFIO clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
                         RCC_APB2Periph_AFIO, ENABLE);

  /* I2S2 SD, CK and WS pins configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* I2S2 MCK pin configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  
  /* Enable I2S2 APB1 clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

  /* Deinitialize SPI2 peripheral */
  SPI_I2S_DeInit(SPI2);
  /* I2S2 peripheral configuration */
  I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
  I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
  I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
  I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
#ifdef AUDIO_FREQ_96K
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_96k;
#elif defined (AUDIO_FREQ_48K)
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_48k;
#elif defined (AUDIO_FREQ_44K) 
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_44k;
#elif defined (AUDIO_FREQ_32K) 
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_32k;
#elif defined (AUDIO_FREQ_22K)  
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_22k;
#elif defined  (AUDIO_FREQ_16K) 
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_16k;
#elif defined  (AUDIO_FREQ_11K) 
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_11k;
#elif defined  (AUDIO_FREQ_8K) 
  I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_8k;  
#endif /* AUDIO_FREQ_96K */  
  I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
  I2S_Init(SPI2, &I2S_InitStructure);
  
  /* Enable the SPI2/I2S2 peripheral */
  I2S_Cmd(SPI2, ENABLE);  
  
}
Example #16
0
/**
  * @brief  I2S_Bus_Init 初始化iis总线
  * @param  none
  * @retval none
  */
void I2S_Bus_Init(void)
{
	
	/* 配置I2S GPIO用到的引脚 */
	I2S_GPIO_Config(); 

	/* 配置I2S工作模式 */
	I2S_Mode_Config();

	I2S_Cmd(SPI2, DISABLE);

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}
Example #17
0
/**
  * @brief  Stops audio stream playing on the used Media.
  * @param  None
  * @retval None
  */
static void Audio_MAL_Stop(void)
{
  /* Stop the Transfer on the I2S side: Stop and disable the DMA channel */
  DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE);

  /* Clear all the DMA flags for the next transfer */
  DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_TC |AUDIO_MAL_DMA_FLAG_HT | AUDIO_MAL_DMA_FLAG_TE);

  /*
  The I2S DMA requests are not disabled here.
  */
  /* In all modes, disable the I2S peripheral */
  I2S_Cmd(CODEC_I2S, DISABLE);
}
/**
  * @brief  Starts playing audio stream from the audio Media.
  * @param  Addr: Pointer to the audio stream buffer
  * @param  Size: Number of data in the audio stream buffer
  * @retval None.
  */
void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
{   
#ifndef AUDIO_USE_MACROS 
  /* Enable the I2S DMA Stream*/
  DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
  
  /* Clear the Interrupt flag */
  DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC); 
  
  /* Wait the DMA Stream to be effectively disabled */
  while (DMA_GetCmdStatus(AUDIO_MAL_DMA_STREAM) != DISABLE)
  {}

  /* Configure the buffer address and size */
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
  DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2);

  /* Configure the DMA Stream with the new parameters */
  DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
  
  /* Enable the I2S DMA Stream*/
  DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);

  /* If the I2S peripheral is still not enabled, enable it */
  if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
  {
    I2S_Cmd(CODEC_I2S, ENABLE);
  }   
#else
  /* Disable the I2S DMA Stream*/
  AUDIO_MAL_DMA_STREAM->CR &= ~(uint32_t)DMA_SxCR_EN;
  
  /* Clear the Interrupt flag */
  AUDIO_MAL_DMA->AUDIO_MAL_DMA_IFCR = (uint32_t)(AUDIO_MAL_DMA_FLAG_TC & 0x0F7D0F7D);
  
  /* Wait the DMA Stream to be effectively disabled */
  while ((AUDIO_MAL_DMA_STREAM->CR & (uint32_t)DMA_SxCR_EN) != 0)
  {}
 
  /* Configure the buffer address and size */
  AUDIO_MAL_DMA_STREAM->M0AR = (uint32_t)Addr;
  AUDIO_MAL_DMA_STREAM->NDTR = (uint32_t)(Size*2);
  
  /* Enable the I2S DMA Stream*/
  AUDIO_MAL_DMA_STREAM->CR |= (uint32_t)DMA_SxCR_EN;

  /* If the I2S peripheral is still not enabled, enable it */
  CODEC_I2S->I2SCFGR |= SPI_I2SCFGR_I2SE;
#endif /* AUDIO_USE_MACROS */
}
Example #19
0
void Codec_AudioInterface_Init(uint32_t AudioFreq)
{
	//Setup I2C comms to codec
	Codec_GPIO_Init();
	I2C_Cntrl_Init();

	//Bring Up Codec via the I2C comms
	Codec_Init();

	//Invoke I2S Pin connections
	I2S_GPIO_Init();

	//Now, get down to defining I2S, Full Duplex, Codec Master Configuration
	I2S_InitTypeDef I2S_InitStructure;

	/* Enable the CODEC_I2S peripheral clock */
	RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE);

	/* CODEC_I2S peripheral configuration */
	I2S_InitStructure.I2S_AudioFreq = AudioFreq;
	I2S_InitStructure.I2S_Standard = I2S_Standard_MSB;
	I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
	I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
	I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx;

	I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;

	/* Initialize the I2S peripheral with the structure above */
	I2S_Init(CODEC_I2S, &I2S_InitStructure);
	I2S_FullDuplexConfig(I2S3ext, &I2S_InitStructure);

	//Turn on the I2S interface
	I2S_Cmd(CODEC_I2S, ENABLE);
	I2S_Cmd(I2S3ext, ENABLE);

}
Example #20
0
/**
  * @brief  I2S_Freq_Config 根据采样频率配置iis总线,在播放音频文件时可从文件中解码获取
  * @param  SampleFreq 采样频率
  * @retval none
  */
void I2S_Freq_Config(uint16_t SampleFreq)
{
	I2S_InitTypeDef I2S_InitStructure;

	I2S_Stop();
	I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;						// 配置I2S工作模式
	I2S_InitStructure.I2S_Standard = I2S_Standard_LSB;				// 接口标准 
	I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;		// 数据格式,16bit 
	I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;	// 主时钟模式 
	I2S_InitStructure.I2S_AudioFreq = SampleFreq;							// 音频采样频率 
	I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;  			
	I2S_Init(SPI2, &I2S_InitStructure);
	
	I2S_Cmd(SPI2, ENABLE);																		//使能iis总线
}
/**
  * @brief  Stop audio recording
  * @param  None
  * @retval None
  */
uint32_t MicListenerStop(void)
{
  /* Check if the interface has already been initialized */
  if (AudioMicInited)
  {

    /* Stop conversion */
    I2S_Cmd(SPI2, DISABLE);

    /* Return 0 if all operations are OK */
    return 0;
  }
  else
  {
    /* Cannot perform operation */
    return 1;
  }
}
Example #22
0
//参数I2S_Standard:  @ref SPI_I2S_Standard  I2S标准,
//I2S_Standard_Phillips,飞利浦标准;
//I2S_Standard_MSB,MSB对齐标准(右对齐);
//I2S_Standard_LSB,LSB对齐标准(左对齐);
//I2S_Standard_PCMShort,I2S_Standard_PCMLong:PCM标准
//参数I2S_Mode:  @ref SPI_I2S_Mode  I2S_Mode_SlaveTx:从机发送;I2S_Mode_SlaveRx:从机接收;I2S_Mode_MasterTx:主机发送;I2S_Mode_MasterRx:主机接收;
//参数I2S_Clock_Polarity   @ref SPI_I2S_Clock_Polarity:  I2S_CPOL_Low,时钟低电平有效;I2S_CPOL_High,时钟高电平有效
//参数I2S_DataFormat: @ref SPI_I2S_Data_Format :数据长度,I2S_DataFormat_16b,16位标准;I2S_DataFormat_16bextended,16位扩展(frame=32bit);I2S_DataFormat_24b,24位;I2S_DataFormat_32b,32位.
void I2S2_Init(u16 I2S_Standard,u16 I2S_Mode,u16 I2S_Clock_Polarity,u16 I2S_DataFormat)
{ 
  I2S_InitTypeDef I2S_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//使能SPI2时钟
	
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE); //复位SPI2
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//结束复位
  
	I2S_InitStructure.I2S_Mode=I2S_Mode;//IIS模式
	I2S_InitStructure.I2S_Standard=I2S_Standard;//IIS标准
	I2S_InitStructure.I2S_DataFormat=I2S_DataFormat;//IIS数据长度
	I2S_InitStructure.I2S_MCLKOutput=I2S_MCLKOutput_Disable;//主时钟输出禁止
	I2S_InitStructure.I2S_AudioFreq=I2S_AudioFreq_Default;//IIS频率设置
	I2S_InitStructure.I2S_CPOL=I2S_Clock_Polarity;//空闲状态时钟电平
	I2S_Init(SPI2,&I2S_InitStructure);//初始化IIS

 
	SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);//SPI2 TX DMA请求使能.
  I2S_Cmd(SPI2,ENABLE);//SPI2 I2S EN使能.	
} 
/**
  * @brief  Starts playing audio stream from the audio Media.
  * @param  None
  * @retval None
  */
static void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
{
#ifndef I2S_INTERRUPT
	if (CurrAudioInterface == AUDIO_INTERFACE_I2S) {
		/* Configure the buffer address and size */
		DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) Addr;
		DMA_InitStructure.DMA_BufferSize = (uint32_t) Size;

		/* Configure the DMA Channel with the new parameters */
		DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure);

		/* Enable the I2S DMA Channel */
		DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE);
	}
#else
	/* If the I2S peripheral is still not enabled, enable it */
	if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0) {
		I2S_Cmd(CODEC_I2S, ENABLE);
	}
#endif /* I2S_INTERRUPT */
}
Example #24
0
void audioInit()
{
    I2S_InitTypeDef I2S_InitStructure;

    Audio_GPIO_Init();

    /*CONFIG the I2S_RCC ,MUST before enabling the I2S APB clock*/
    //PLLI2SN 302,PLLI2SR 2,I2SDIV 53,I2SODD 1,FS 44.1KHZ,16bit,Error 0.0011%
    RCC_PLLI2SConfig(302,2);
    RCC_PLLI2SCmd(ENABLE);
    RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);

    /* Enable the CODEC_I2S peripheral clock */
    RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE);
    /* CODEC_I2S peripheral configuration */
    SPI_I2S_DeInit(CODEC_I2S);
    I2S_InitStructure.I2S_AudioFreq = AudioFreq;
    I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
    I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
    I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;//clk 0 when idle state
    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
#ifdef CODEC_MCLK_ENABLED
    I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
#elif defined(CODEC_MCLK_DISABLED)
    I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
#else
    #error "No selection for the MCLK output has been defined !"
#endif /* CODEC_MCLK_ENABLED */

    /* Initialize the I2S peripheral with the structure above */
    I2S_Init(CODEC_I2S, &I2S_InitStructure);
    I2S_Cmd(CODEC_I2S, ENABLE);
    //interrupt
#ifdef CODEC_USE_INT
    SPI_I2S_ITConfig(CODEC_I2S,SPI_I2S_IT_TXE,ENABLE);
#elif defined(CODEC_USE_DMA)
#error "DMA is not initialized"
#endif
}
Example #25
0
/**
  * @brief  Start audio recording
  * @param  pbuf: pointer to a buffer
  * @retval None
  */
uint8_t WaveRecorderStart(uint16_t* pbuf)
{
/* Check if the interface has already been initialized */
  if (AudioRecInited)
  {
    /* Store the location and size of the audio buffer */
    pAudioRecBuf = pbuf;
    
    /* Enable the Rx buffer not empty interrupt */
    SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);
    /* The Data transfer is performed in the SPI interrupt routine */
    /* Enable the SPI peripheral */
    I2S_Cmd(SPI2, ENABLE); 
   
    /* Return 0 if all operations are OK */
    return 0;
  }
  else
  {
    /* Cannot perform operation */
    return 1;
  }
}
/**
  * @brief  Pauses or Resumes the audio stream playing from the Media.
  * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
  *        from 0) to resume. 
  * @param Addr: Address from/at which the audio stream should resume/pause.
  * @param Size: Number of data to be configured for next resume.
  * @retval None.
  */
void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr, uint32_t Size)
{
  /* Pause the audio file playing */
  if (Cmd == AUDIO_PAUSE)
  {      
    /* Stop the current DMA request by resetting the I2S cell */
    Codec_AudioInterface_DeInit();
    
    /* Re-configure the I2S interface for the next resume operation */
    Codec_AudioInterface_Init(I2S_InitStructure.I2S_AudioFreq);

    /* Disable the DMA Stream */
    DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE);
        
    /* Clear the Interrupt flag */
    DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_ALL);  
  }
  else /* AUDIO_RESUME */
  {   
    /* Configure the buffer address and size */
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr;
    DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2);
    
    /* Configure the DMA Stream with the new parameters */
    DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure);
    
    /* Enable the I2S DMA Stream*/
    DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE);     
  
    /* If the I2S peripheral is still not enabled, enable it */
    if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
    {
      I2S_Cmd(CODEC_I2S, ENABLE);
    } 
  }  
}
/**
  * @brief  Starts playing audio stream from the audio Media.
  * @param  Addr: Pointer to the audio stream buffer
  * @param  Size: Number of data in the audio stream buffer
  * @retval None.
  */
void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
{   
  /* Enable the I2S DMA Stream*/
  DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, DISABLE);
  
  /* Clear the Interrupt flag */
  DMA_ClearFlag(AUDIO_MAL_DMA_FLAG_TC); 
  
  /* Configure the buffer address and size */
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Addr;
  DMA_InitStructure.DMA_BufferSize = (uint32_t)(Size*2);

  /* Configure the DMA Stream with the new parameters */
  DMA_Init(AUDIO_MAL_DMA_CHANNEL, &DMA_InitStructure);
  
  /* Enable the I2S DMA Stream*/
  DMA_Cmd(AUDIO_MAL_DMA_CHANNEL, ENABLE);

  /* If the I2S peripheral is still not enabled, enable it */
  if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
  {
    I2S_Cmd(CODEC_I2S, ENABLE);
  }
}
Example #28
0
/**
  * @brief  Options control function.
  * @param  cmd: pointer to the command/option buffer.
  * @param  size: Size of the command/option buffer.
  * @retval Value of the current audio sampling rate.
  */
static uint32_t  OptionCtrl   (uint8_t* cmd, uint32_t size)
{
  uint32_t freq = 48000;
  
  /* Decode the audio frequency */
  freq = (uint32_t)(*(uint8_t*)(cmd) | (*(uint8_t*)(cmd + 1) << 8) | (*(uint8_t*)(cmd + 2) << 16));

  /* Check ff the requested audio frequency is not supported */
  if ((freq > MAX_AUDIO_FREQ) || (freq < MIN_AUDIO_FREQ))
  {
    /* Set the default audio frequency */
    freq = DEFAULT_OUT_AUDIO_FREQ;
  }

#ifdef USE_SYNCHRONIZATION  
  /* If the external clock is used, reconfigure the clock synthesizer sub-system */
  AUDIO_CORR_Out_Update(freq, 0, 0, 0);
#endif /* USE_SYNCHRONIZATION */
  
  /* If the I2S peripheral is still not enabled, enable it */
  I2S_Cmd(CODEC_I2S, ENABLE);
    
  return freq;
}
Example #29
0
void CS43L22_Config() {
	  // configure STM32F4Discovery I2S pins

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD, ENABLE);

	GPIO_InitTypeDef GPIO_InitStructure;
	  GPIO_StructInit(&GPIO_InitStructure);
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

	  GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_WS_PIN;
	  GPIO_Init(STM32F4D_I2S_WS_PORT, &GPIO_InitStructure);
	  GPIO_PinAFConfig(STM32F4D_I2S_WS_PORT, STM32F4D_I2S_WS_PINSRC, GPIO_AF_SPI3);

	  GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_CK_PIN;
	  GPIO_Init(STM32F4D_I2S_CK_PORT, &GPIO_InitStructure);
	  GPIO_PinAFConfig(STM32F4D_I2S_CK_PORT, STM32F4D_I2S_CK_PINSRC, GPIO_AF_SPI3);

	  GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_SD_PIN;
	  GPIO_Init(STM32F4D_I2S_SD_PORT, &GPIO_InitStructure);
	  GPIO_PinAFConfig(STM32F4D_I2S_SD_PORT, STM32F4D_I2S_SD_PINSRC, GPIO_AF_SPI3);

	  GPIO_InitStructure.GPIO_Pin = STM32F4D_I2S_MCLK_PIN;
	  GPIO_Init(STM32F4D_I2S_MCLK_PORT, &GPIO_InitStructure);
	  GPIO_PinAFConfig(STM32F4D_I2S_MCLK_PORT, STM32F4D_I2S_MCLK_PINSRC, GPIO_AF_SPI3);

	  // configure I2C pins to access the CS43L22 configuration registers

	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	  GPIO_InitStructure.GPIO_Pin = CODEC_I2C_SCL_PIN;
	  GPIO_Init(CODEC_I2C_SCL_PORT, &GPIO_InitStructure);
	  GPIO_PinAFConfig(CODEC_I2C_SCL_PORT, GPIO_PinSource6, GPIO_AF_I2C1);

	  GPIO_InitStructure.GPIO_Pin = CODEC_I2C_SDA_PIN;
	  GPIO_Init(CODEC_I2C_SDA_PORT, &GPIO_InitStructure);
	  GPIO_PinAFConfig(CODEC_I2C_SDA_PORT, GPIO_PinSource9, GPIO_AF_I2C1);

	  // CS43L22 reset pin
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	  GPIO_InitStructure.GPIO_Pin = CODEC_RESET_PIN;
	  GPIO_Init(CODEC_RESET_PORT, &GPIO_InitStructure);

	  GPIO_ResetBits(CODEC_RESET_PORT, CODEC_RESET_PIN); // activate reset

	  // I2S initialisation
	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
	  RCC_PLLI2SCmd(ENABLE); // new for STM32F4: enable I2S PLL
	  SPI_I2S_DeInit(SPI3);
	  I2S_InitTypeDef I2S_InitStructure;
	  I2S_StructInit(&I2S_InitStructure);
	  I2S_InitStructure.I2S_Standard = STM32F4D_I2S_STANDARD;
	  I2S_InitStructure.I2S_DataFormat = STM32F4D_I2S_DATA_FORMAT;
	  I2S_InitStructure.I2S_MCLKOutput = STM32F4D_I2S_MCLK_ENABLE ? I2S_MCLKOutput_Enable : I2S_MCLKOutput_Disable;
	  I2S_InitStructure.I2S_AudioFreq  = (u16)(STM32F4D_I2S_AUDIO_FREQ);
	  I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; // configuration required as well?
	  I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
	  I2S_Init(SPI3, &I2S_InitStructure);
	  I2S_Cmd(SPI3, ENABLE);

	  // DMA Configuration for SPI Tx Event
	  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

	  DMA_InitTypeDef DMA_InitStructure;
	  DMA_StructInit(&DMA_InitStructure);

	  DMA_Cmd(DMA1_Stream5, DISABLE);
	  DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5 | DMA_FLAG_FEIF5);
	  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
	  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR;
	  //  DMA_InitStructure.DMA_MemoryBaseAddr = ...; // configured in CS43L22_Start
	  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
	  //  DMA_InitStructure.DMA_BufferSize = ...; // configured in CS43L22_Start
	  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
	  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
	  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
	  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
	  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
	  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

	  DMA_Init(DMA1_Stream5, &DMA_InitStructure);
	  // DMA_Cmd(DMA1_Stream5, ENABLE); // done on CS43L22_Start

	  DMA_ITConfig(DMA1_Stream5, DMA_IT_TE | DMA_IT_FE, DISABLE);
	  // trigger interrupt when transfer half complete/complete
	  DMA_ITConfig(DMA1_Stream5, DMA_IT_HT | DMA_IT_TC, ENABLE);

	  // enable SPI interrupts to DMA
	  SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);

	  // Configure and enable DMA interrupt
	  /* Configure the DMA IRQ handler priority */
	  NVIC_SetPriority(DMA1_Stream5_IRQn, 0x0);
	  NVIC_EnableIRQ(DMA1_Stream5_IRQn);

	  // configure I2C
	  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	  I2C_DeInit(CODEC_I2C);
	  I2C_InitTypeDef I2C_InitStructure;
	  I2C_StructInit(&I2C_InitStructure);
	  I2C_InitStructure.I2C_ClockSpeed = 100000;
	  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	  I2C_InitStructure.I2C_OwnAddress1 = CORE_I2C_ADDRESS;
	  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

	  I2C_Cmd(CODEC_I2C, ENABLE);
	  I2C_Init(CODEC_I2C, &I2C_InitStructure);

	  codec_init();
}
Example #30
0
void codec_dma_isr(void)
{
    /* switch to next buffer */
    rt_uint16_t next_index;
    void* data_ptr;

    next_index = codec.read_index + 1;
    if (next_index >= DATA_NODE_MAX)
        next_index = 0;

    /* save current data pointer */
    data_ptr = codec.data_list[codec.read_index].data_ptr;

#if !CODEC_MASTER_MODE
    if (codec_sr_new)
    {
        I2S_Configuration(codec_sr_new);
        I2S_Cmd(CODEC_I2S_PORT, ENABLE);
        codec_sr_new = 0;
    }
#endif

    codec.read_index = next_index;
    if (next_index != codec.put_index)
    {
        /* enable next dma request */
        DMA_Configuration((rt_uint32_t) codec.data_list[codec.read_index].data_ptr, codec.data_list[codec.read_index].data_size);

#if CODEC_MASTER_MODE
        if ((r06 & MS) == 0)
        {
            CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE;
            r06 |= MS;
            codec_send(r06);
        }
#endif
    }
    else
    {
#if CODEC_MASTER_MODE
        if (r06 & MS)
        {
            CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN;
            while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0);
            while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0);
            CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE;

            r06 &= ~MS;
            codec_send(r06);
        }
#endif

        rt_kprintf("*\n");
    }

    /* notify transmitted complete. */
    if (codec.parent.tx_complete != RT_NULL)
    {
        codec.parent.tx_complete(&codec.parent, data_ptr);
    }
}