firmware/src/platform/std_periph/src/stm32f4xx_spi.c
/**
  * @brief  Initializes the SPIx peripheral according to the specified 
  *         parameters in the I2S_InitStruct.
  * @param  SPIx: where x can be  2 or 3 to select the SPI peripheral (configured in I2S mode).
  * @param  I2S_InitStruct: pointer to an I2S_InitTypeDef structure that
  *         contains the configuration information for the specified SPI peripheral
  *         configured in I2S mode.
  *           
  * @note   The function calculates the optimal prescaler needed to obtain the most 
  *         accurate audio frequency (depending on the I2S clock source, the PLL values 
  *         and the product configuration). But in case the prescaler value is greater 
  *         than 511, the default value (0x02) will be configured instead.    
  * 
  * @note   if an external clock is used as source clock for the I2S, then the define
  *         I2S_EXTERNAL_CLOCK_VAL in file stm32f4xx_conf.h should be enabled and set
  *         to the value of the source clock frequency (in Hz).
  *  
  * @retval None
  */
@brief  Initializes the SPIx peripheral according to the specified
parameters in the I2S_InitStruct.
@param  SPIx: where x can be  2 or 3 to select the SPI peripheral (configured in I2S mode).
@param  I2S_InitStruct: pointer to an I2S_InitTypeDef structure that
contains the configuration information for the specified SPI peripheral
configured in I2S mode.

@note   The function calculates the optimal prescaler needed to obtain the most
accurate audio frequency (depending on the I2S clock source, the PLL values
and the product configuration). But in case the prescaler value is greater
than 511, the default value (0x02) will be configured instead.

@note   if an external clock is used as source clock for the I2S, then the define
I2S_EXTERNAL_CLOCK_VAL in file stm32f4xx_conf.h should be enabled and set
to the value of the source clock frequency (in Hz).

@retval None
@brief Initializes the SPIx peripheral according to the specified parameters in the I2S_InitStruct . @param SPIx : where x can be 2 or 3 to select the SPI peripheral ( configured in I2S mode ) . @param I2S_InitStruct : pointer to an I2S_InitTypeDef structure that contains the configuration information for the specified SPI peripheral configured in I2S mode . @note The function calculates the optimal prescaler needed to obtain the most accurate audio frequency ( depending on the I2S clock source the PLL values and the product configuration ) . But in case the prescaler value is greater than 511 the default value ( 0x02 ) will be configured instead . @note if an external clock is used as source clock for the I2S then the define I2S_EXTERNAL_CLOCK_VAL in file stm32f4xx_conf . h should be enabled and set to the value of the source clock frequency ( in Hz ) . @retval None
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct)
{
  uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
  uint32_t tmp = 0, i2sclk = 0;
#ifndef I2S_EXTERNAL_CLOCK_VAL
  uint32_t pllm = 0, plln = 0, pllr = 0;
#endif 
  assert_param(IS_SPI_23_PERIPH(SPIx));
  assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode));
  assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard));
  assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat));
  assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput));
  assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq));
  assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL));  
  SPIx->I2SCFGR &= I2SCFGR_CLEAR_MASK; 
  SPIx->I2SPR = 0x0002;
  tmpreg = SPIx->I2SCFGR;
  if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default)
  {
    i2sodd = (uint16_t)0;
    i2sdiv = (uint16_t)2;   
  }
  else
  {
    if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b)
    {
      packetlength = 16;
    }
    else
    {
      packetlength = 32;
    }
    if(I2S_InitStruct->I2S_Standard <= I2S_Standard_LSB)
    {
      packetlength = packetlength * 2;
    }
  #ifdef I2S_EXTERNAL_CLOCK_VAL     
    if ((RCC->CFGR & RCC_CFGR_I2SSRC) == 0)
    {
      RCC->CFGR |= (uint32_t)RCC_CFGR_I2SSRC;
    }
    i2sclk = I2S_EXTERNAL_CLOCK_VAL;
  #else 
    if ((RCC->CFGR & RCC_CFGR_I2SSRC) != 0)
    {
      RCC->CFGR &= ~(uint32_t)RCC_CFGR_I2SSRC;
    }    
    plln = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & \
                      (RCC_PLLI2SCFGR_PLLI2SN >> 6));
    pllr = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & \
                      (RCC_PLLI2SCFGR_PLLI2SR >> 28));
    pllm = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM);
    if((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)
    {
      i2sclk = (uint32_t)(((HSE_VALUE / pllm) * plln) / pllr);
    }
    else
    { 
      i2sclk = (uint32_t)(((HSI_VALUE / pllm) * plln) / pllr);
    }
  #endif 
    if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable)
    {
      tmp = (uint16_t)(((((i2sclk / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5);
    }
    else
    {
      tmp = (uint16_t)(((((i2sclk / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5);
    }
    tmp = tmp / 10;  
    i2sodd = (uint16_t)(tmp & (uint16_t)0x0001);
    i2sdiv = (uint16_t)((tmp - i2sodd) / 2);
    i2sodd = (uint16_t) (i2sodd << 8);
  }
  if ((i2sdiv < 2) || (i2sdiv > 0xFF))
  {
    i2sdiv = 2;
    i2sodd = 0;
  }
  SPIx->I2SPR = (uint16_t)((uint16_t)i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput));
  tmpreg |= (uint16_t)((uint16_t)SPI_I2SCFGR_I2SMOD | (uint16_t)(I2S_InitStruct->I2S_Mode | \
                  (uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \
                  (uint16_t)I2S_InitStruct->I2S_CPOL))));
#if defined(SPI_I2SCFGR_ASTRTEN)
  if((I2S_InitStruct->I2S_Standard  == I2S_Standard_PCMShort) || (I2S_InitStruct->I2S_Standard  == I2S_Standard_PCMLong))
  {
    SPIx->I2SCFGR = tmpreg | SPI_I2SCFGR_ASTRTEN;
  }
#else
  SPIx->I2SCFGR = tmpreg ;
#endif 
}
void I2S_Init ( SPI_TypeDef * SPIx , I2S_InitTypeDef * I2S_InitStruct ) { uint16_t tmpreg = 0 , i2sdiv = 2 , i2sodd = 0 , packetlength = 1 ; uint32_t tmp = 0 , i2sclk = 0 ; #ifndef I2S_EXTERNAL_CLOCK_VAL uint32_t pllm = 0 , plln = 0 , pllr = 0 ; #endif assert_param ( IS_SPI_23_PERIPH ( SPIx ) ) ; assert_param ( IS_I2S_MODE ( I2S_InitStruct -> I2S_Mode ) ) ; assert_param ( IS_I2S_STANDARD ( I2S_InitStruct -> I2S_Standard ) ) ; assert_param ( IS_I2S_DATA_FORMAT ( I2S_InitStruct -> I2S_DataFormat ) ) ; assert_param ( IS_I2S_MCLK_OUTPUT ( I2S_InitStruct -> I2S_MCLKOutput ) ) ; assert_param ( IS_I2S_AUDIO_FREQ ( I2S_InitStruct -> I2S_AudioFreq ) ) ; assert_param ( IS_I2S_CPOL ( I2S_InitStruct -> I2S_CPOL ) ) ; SPIx -> I2SCFGR &= I2SCFGR_CLEAR_MASK ; SPIx -> I2SPR = 0x0002 ; tmpreg = SPIx -> I2SCFGR ; if ( I2S_InitStruct -> I2S_AudioFreq == I2S_AudioFreq_Default ) { i2sodd = ( uint16_t ) 0 ; i2sdiv = ( uint16_t ) 2 ; } else { if ( I2S_InitStruct -> I2S_DataFormat == I2S_DataFormat_16b ) { packetlength = 16 ; } else { packetlength = 32 ; } if ( I2S_InitStruct -> I2S_Standard <= I2S_Standard_LSB ) { packetlength = packetlength * 2 ; } #ifdef I2S_EXTERNAL_CLOCK_VAL if ( ( RCC -> CFGR & RCC_CFGR_I2SSRC ) == 0 ) { RCC -> CFGR |= ( uint32_t ) RCC_CFGR_I2SSRC ; } i2sclk = I2S_EXTERNAL_CLOCK_VAL ; #else if ( ( RCC -> CFGR & RCC_CFGR_I2SSRC ) != 0 ) { RCC -> CFGR &= ~ ( uint32_t ) RCC_CFGR_I2SSRC ; } plln = ( uint32_t ) ( ( ( RCC -> PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN ) >> 6 ) & ( RCC_PLLI2SCFGR_PLLI2SN >> 6 ) ) ; pllr = ( uint32_t ) ( ( ( RCC -> PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR ) >> 28 ) & ( RCC_PLLI2SCFGR_PLLI2SR >> 28 ) ) ; pllm = ( uint32_t ) ( RCC -> PLLCFGR & RCC_PLLCFGR_PLLM ) ; if ( ( RCC -> PLLCFGR & RCC_PLLCFGR_PLLSRC ) == RCC_PLLCFGR_PLLSRC_HSE ) { i2sclk = ( uint32_t ) ( ( ( HSE_VALUE / pllm ) * plln ) / pllr ) ; } else { i2sclk = ( uint32_t ) ( ( ( HSI_VALUE / pllm ) * plln ) / pllr ) ; } #endif if ( I2S_InitStruct -> I2S_MCLKOutput == I2S_MCLKOutput_Enable ) { tmp = ( uint16_t ) ( ( ( ( ( i2sclk / 256 ) * 10 ) / I2S_InitStruct -> I2S_AudioFreq ) ) + 5 ) ; } else { tmp = ( uint16_t ) ( ( ( ( ( i2sclk / ( 32 * packetlength ) ) * 10 ) / I2S_InitStruct -> I2S_AudioFreq ) ) + 5 ) ; } tmp = tmp / 10 ; i2sodd = ( uint16_t ) ( tmp & ( uint16_t ) 0x0001 ) ; i2sdiv = ( uint16_t ) ( ( tmp - i2sodd ) / 2 ) ; i2sodd = ( uint16_t ) ( i2sodd << 8 ) ; } if ( ( i2sdiv < 2 ) || ( i2sdiv > 0xFF ) ) { i2sdiv = 2 ; i2sodd = 0 ; } SPIx -> I2SPR = ( uint16_t ) ( ( uint16_t ) i2sdiv | ( uint16_t ) ( i2sodd | ( uint16_t ) I2S_InitStruct -> I2S_MCLKOutput ) ) ; tmpreg |= ( uint16_t ) ( ( uint16_t ) SPI_I2SCFGR_I2SMOD | ( uint16_t ) ( I2S_InitStruct -> I2S_Mode | ( uint16_t ) ( I2S_InitStruct -> I2S_Standard | ( uint16_t ) ( I2S_InitStruct -> I2S_DataFormat | ( uint16_t ) I2S_InitStruct -> I2S_CPOL ) ) ) ) ; #if defined ( SPI_I2SCFGR_ASTRTEN ) if ( ( I2S_InitStruct -> I2S_Standard == I2S_Standard_PCMShort ) || ( I2S_InitStruct -> I2S_Standard == I2S_Standard_PCMLong ) ) { SPIx -> I2SCFGR = tmpreg | SPI_I2SCFGR_ASTRTEN ; } #else SPIx -> I2SCFGR = tmpreg ; #endif }
@brief  Initializes the SPIx peripheral according to the specified
         parameters in the I2S_InitStruct.
@brief Initializes the SPIx peripheral according to the specified parameters in the I2S_InitStruct .
/* I2S_EXTERNAL_CLOCK_VAL */ /* Check the I2S parameters */ /*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/ /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ /* Get the I2SCFGR register value */ /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ /* If the requested audio frequency is not the default, compute the prescaler */ /* Check the frame length (For the Prescaler computing) *******************/ /* Packet length is 16 bits */ /* Packet length is 32 bits */ /* In I2S standard packet length is multiplied by 2 */ /* Get I2S source Clock frequency  ****************************************/ /* If an external I2S clock has to be used, this define should be set  
       in the project configuration or in the stm32f4xx_conf.h file */ /* Set external clock as I2S clock source */ /* Set the I2S clock to the external clock  value */ /* There is no define for External I2S clock source */ /* Set PLLI2S as I2S clock source */ /* Get the PLLI2SN value */ /* Get the PLLI2SR value */ /* Get the PLLM value */ /* Get the I2S source clock value */ /* Get the I2S source clock value */ /* I2S_EXTERNAL_CLOCK_VAL */ /* Compute the Real divider depending on the MCLK output state, with a floating point */ /* MCLK output is enabled */ /* MCLK output is disabled */ /* Remove the flatting point */ /* Check the parity of the divider */ /* Compute the i2sdiv prescaler */ /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ /* Test if the divider is 1 or 0 or greater than 0xFF */ /* Set the default values */ /* Write to SPIx I2SPR register the computed value */ /* Configure the I2S with the SPI_InitStruct values */ /* Write to SPIx I2SCFGR */ /* Write to SPIx I2SCFGR */