/*! \brief I2S parameter configuration \param[in] spi_periph: SPIx(x=0,1,2,3,4) \param[in] i2s_mode: \arg I2S_MODE_SLAVETX : I2S slave transmit mode \arg I2S_MODE_SLAVERX : I2S slave receive mode \arg I2S_MODE_MASTERTX : I2S master transmit mode \arg I2S_MODE_MASTERRX : I2S master receive mode \param[in] i2s_std: \arg I2S_STD_PHILLIPS : I2S phillips standard \arg I2S_STD_MSB : I2S MSB standard \arg I2S_STD_LSB : I2S LSB standard \arg I2S_STD_PCMSHORT : I2S PCM short standard \arg I2S_STD_PCMLONG : I2S PCM long standard \param[in] i2s_ckpl: \arg I2S_CKPL_LOW : I2S clock polarity low level \arg I2S_CKPL_HIGH : I2S clock polarity high level \param[out] none \retval none */ void i2s_init(uint32_t spi_periph, uint32_t i2s_mode, uint32_t i2s_standard, uint32_t i2s_ckpl) { uint32_t reg= 0U; reg = SPI_I2SCTL(spi_periph); reg &= I2S_INIT_MASK; /* enable I2S mode */ reg |= (uint32_t)SPI_I2SCTL_I2SSEL; /* select I2S mode */ reg |= (uint32_t)i2s_mode; /* select I2S standard */ reg |= (uint32_t)i2s_standard; /* select I2S polarity */ reg |= (uint32_t)i2s_ckpl; /* write to SPI_I2SCTL register */ SPI_I2SCTL(spi_periph) = (uint32_t)reg; }
/*! \brief disable I2S \param[in] spi_periph: SPIx(x=1,2) \param[out] none \retval none */ void i2s_disable(uint32_t spi_periph) { SPI_I2SCTL(spi_periph) &= (uint32_t)(~SPI_I2SCTL_I2SEN); }
/*! \brief enable I2S \param[in] spi_periph: SPIx(x=1,2) \param[out] none \retval none */ void i2s_enable(uint32_t spi_periph) { SPI_I2SCTL(spi_periph) |= (uint32_t)SPI_I2SCTL_I2SEN; }
/*! \brief configure I2S prescale \param[in] spi_periph: SPIx(x=1,2) \param[in] i2s_audiosample: I2S audio sample rate only one parameter can be selected which is shown as below: \arg I2S_AUDIOSAMPLE_8K: audio sample rate is 8KHz \arg I2S_AUDIOSAMPLE_11K: audio sample rate is 11KHz \arg I2S_AUDIOSAMPLE_16K: audio sample rate is 16KHz \arg I2S_AUDIOSAMPLE_22K: audio sample rate is 22KHz \arg I2S_AUDIOSAMPLE_32K: audio sample rate is 32KHz \arg I2S_AUDIOSAMPLE_44K: audio sample rate is 44KHz \arg I2S_AUDIOSAMPLE_48K: audio sample rate is 48KHz \arg I2S_AUDIOSAMPLE_96K: audio sample rate is 96KHz \arg I2S_AUDIOSAMPLE_192K: audio sample rate is 192KHz \param[in] i2s_frameformat: I2S data length and channel length only one parameter can be selected which is shown as below: \arg I2S_FRAMEFORMAT_DT16B_CH16B: I2S data length is 16 bit and channel length is 16 bit \arg I2S_FRAMEFORMAT_DT16B_CH32B: I2S data length is 16 bit and channel length is 32 bit \arg I2S_FRAMEFORMAT_DT24B_CH32B: I2S data length is 24 bit and channel length is 32 bit \arg I2S_FRAMEFORMAT_DT32B_CH32B: I2S data length is 32 bit and channel length is 32 bit \param[in] i2s_mckout: I2S master clock output only one parameter can be selected which is shown as below: \arg I2S_MCKOUT_ENABLE: I2S master clock output enable \arg I2S_MCKOUT_DISABLE: I2S master clock output disable \param[out] none \retval none */ void i2s_psc_config(uint32_t spi_periph, uint32_t i2s_audiosample, uint32_t i2s_frameformat, uint32_t i2s_mckout) { uint32_t i2sdiv = 2U, i2sof = 0U; uint32_t clks = 0U; uint32_t i2sclock = 0U; #ifndef I2S_EXTERNAL_CLOCK_IN uint32_t plli2sm = 0U, plli2sn = 0U, plli2sr = 0U; #endif /* I2S_EXTERNAL_CLOCK_IN */ /* deinit SPI_I2SPSC register */ SPI_I2SPSC(spi_periph) = SPI_I2SPSC_DEFAULT_VALUE; #ifdef I2S_EXTERNAL_CLOCK_IN rcu_i2s_clock_config(RCU_I2SSRC_I2S_CKIN); /* set the I2S clock to the external clock input value */ i2sclock = I2S_EXTERNAL_CLOCK_IN; #else /* turn on the oscillator HXTAL */ rcu_osci_on(RCU_HXTAL); /* wait for oscillator stabilization flags is SET */ rcu_osci_stab_wait(RCU_HXTAL); /* turn on the PLLI2S */ rcu_osci_on(RCU_PLLI2S_CK); /* wait for PLLI2S flags is SET */ rcu_osci_stab_wait(RCU_PLLI2S_CK); /* configure the I2S clock source selection */ rcu_i2s_clock_config(RCU_I2SSRC_PLLI2S); /* get the RCU_PLL_PLLPSC value */ plli2sm = (uint32_t)(RCU_PLL & RCU_PLL_PLLPSC); /* get the RCU_PLLI2S_PLLI2SN value */ plli2sn = (uint32_t)((RCU_PLLI2S & RCU_PLLI2S_PLLI2SN) >> 6); /* get the RCU_PLLI2S_PLLI2SR value */ plli2sr = (uint32_t)((RCU_PLLI2S & RCU_PLLI2S_PLLI2SR) >> 28); if ((RCU_PLL & RCU_PLL_PLLSEL) == RCU_PLLSRC_HXTAL) { /* get the I2S source clock value */ i2sclock = (uint32_t)(((HXTAL_VALUE / plli2sm) * plli2sn) / plli2sr); } else { /* get the I2S source clock value */ i2sclock = (uint32_t)(((IRC16M_VALUE / plli2sm) * plli2sn) / plli2sr); } #endif /* I2S_EXTERNAL_CLOCK_IN */ /* config the prescaler depending on the mclk output state, the frame format and audio sample rate */ if (I2S_MCKOUT_ENABLE == i2s_mckout) { clks = (uint32_t)(((i2sclock / 256U) * 10U) / i2s_audiosample); } else { if (I2S_FRAMEFORMAT_DT16B_CH16B == i2s_frameformat) { clks = (uint32_t)(((i2sclock / 32U) * 10U) / i2s_audiosample); } else { clks = (uint32_t)(((i2sclock / 64U) * 10U) / i2s_audiosample); } } /* remove the floating point */ clks = (clks + 5U) / 10U; i2sof = (clks & 0x00000001U); i2sdiv = ((clks - i2sof) / 2U); i2sof = (i2sof << 8U); /* set the default values */ if ((i2sdiv < 2U) || (i2sdiv > 255U)) { i2sdiv = 2U; i2sof = 0U; } /* configure SPI_I2SPSC */ SPI_I2SPSC(spi_periph) = (uint32_t)(i2sdiv | i2sof | i2s_mckout); /* clear SPI_I2SCTL_DTLEN and SPI_I2SCTL_CHLEN bits */ SPI_I2SCTL(spi_periph) &= (uint32_t)(~(SPI_I2SCTL_DTLEN | SPI_I2SCTL_CHLEN)); /* configure data frame format */ SPI_I2SCTL(spi_periph) |= (uint32_t)i2s_frameformat; }