//***************************************************************************** // //! Configures the I2S peripheral for the given audio data format. //! //! \param ulSampleRate is the sample rate of the audio to be played in //! samples per second. //! \param usBitsPerSample is the number of bits in each audio sample. //! \param usChannels is the number of audio channels, 1 for mono, 2 for stereo. //! //! This function configures the I2S peripheral in preparation for playing //! and recording audio data of a particular format. //! //! \note This function has a work around for the I2SMCLKCFG register errata. //! This errata limits the low end of the MCLK at some bit sizes. The absolute //! limit is a divide of the System PLL by 256 or an MCLK minimum of //! 400MHz/256 or 1.5625MHz. This is overcome by increasing the number of //! bits shifted out per sample and thus increasing the MCLK needed for a given //! sample rate. This uses the fact that the I2S codec used on the development //! board s that will toss away extra bits that go to or from the codec. //! //! \return None. // //***************************************************************************** void SoundSetFormat(unsigned long ulSampleRate, unsigned short usBitsPerSample, unsigned short usChannels) { unsigned long ulFormat; unsigned long ulDMASetting; unsigned long ulI2SErrata; // // Save these values for use when configuring I2S. // g_usChannels = usChannels; g_usBitsPerSample = usBitsPerSample; I2SMasterClockSelect(I2S0_BASE, 0); // // Always use have the controller be an I2S Master. // ulFormat = I2S_CONFIG_FORMAT_I2S | I2S_CONFIG_CLK_MASTER; // // Check if the missing divisor bits need to be taken into account. // if(CLASS_IS_TEMPEST && REVISION_IS_B1) { ulI2SErrata = 1; } else { ulI2SErrata = 0; } // // Mono or Stereo formats. // if(g_usChannels == 1) { // // 8 bit formats. // if(g_usBitsPerSample == 8) { // // On Tempest class devices rev B parts the divisor is // limited for lower samples rates (see errata). // if((ulI2SErrata != 0) && (ulSampleRate < 24400)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_8; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_8 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_8; } } else if(g_usBitsPerSample == 16) { // // On Tempest class devices rev B parts the divisor is // limited for lower samples rates (see errata). // if((ulI2SErrata != 0) && (ulSampleRate < 12200)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_16; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_16 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_16; } } else if(g_usBitsPerSample == 24) { ulFormat |= (I2S_CONFIG_WIRE_SIZE_24 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_24); } else { ulFormat |= (I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_32); } } else { if(g_usBitsPerSample == 8) { // // On Tempest class devices rev B parts the divisor is // limited for lower samples rates (see errata). // if((ulI2SErrata != 0) && (ulSampleRate < 12200)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_COMPACT_8 | I2S_CONFIG_SAMPLE_SIZE_8; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_8 | I2S_CONFIG_MODE_COMPACT_8 | I2S_CONFIG_SAMPLE_SIZE_8; } } else if(g_usBitsPerSample == 16) { if((ulI2SErrata != 0) && (ulSampleRate < 12200)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_COMPACT_16 | I2S_CONFIG_SAMPLE_SIZE_16; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_16 | I2S_CONFIG_MODE_COMPACT_16 | I2S_CONFIG_SAMPLE_SIZE_16; } } else if(g_usBitsPerSample == 24) { ulFormat |= (I2S_CONFIG_WIRE_SIZE_24 | I2S_CONFIG_MODE_DUAL | I2S_CONFIG_SAMPLE_SIZE_24); } else { ulFormat |= (I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_DUAL | I2S_CONFIG_SAMPLE_SIZE_32); } } // // Configure the I2S TX format. // I2STxConfigSet(I2S0_BASE, ulFormat); // // This is needed on Rev B parts due to errata. // if(ulI2SErrata) { ulFormat = (ulFormat & ~I2S_CONFIG_FORMAT_MASK) | I2S_CONFIG_FORMAT_LEFT_JUST; } // // Configure the I2S RX format. // I2SRxConfigSet(I2S0_BASE, ulFormat); // // Internally both are masters but the pins may not be driven out. // I2SMasterClockSelect(I2S0_BASE, I2S_TX_MCLK_INT | I2S_RX_MCLK_INT); // // Set the MCLK rate and save it for conversion back to sample rate. // The multiply by 8 is due to a 4X oversample rate plus a factor of two // since the data is always stereo on the I2S interface. // g_ulSampleRate = SysCtlI2SMClkSet(0, ulSampleRate * usBitsPerSample * 8); // // Convert the MCLK rate to sample rate. // g_ulSampleRate = g_ulSampleRate / (usBitsPerSample * 8); // // Configure the I2S TX DMA channel to use high priority burst transfer. // uDMAChannelAttributeEnable(UDMA_CHANNEL_I2S0TX, UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY); // // Set the DMA channel configuration. // if(g_usChannels == 1) { // // Handle Mono formats. // if(g_usBitsPerSample == 8) { // // The transfer size is 8 bits from the TX buffer to the TX FIFO. // ulDMASetting = (UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_2); } else { // // The transfer size is 16 bits from the TX buffer to the TX FIFO. // ulDMASetting = (UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_2); } } else { // // Handle Stereo formats. // if(g_usBitsPerSample == 8) { // // The transfer size is 16 bits(stereo 8 bits) from the TX buffer // to the TX FIFO. // ulDMASetting = (UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_2); } else { // // The transfer size is 32 bits(stereo 16 bits) from the TX buffer // to the TX FIFO. // ulDMASetting = (UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_NONE | UDMA_ARB_2); } } // // Configure the DMA settings for this channel. // uDMAChannelControlSet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT, ulDMASetting); uDMAChannelControlSet(UDMA_CHANNEL_I2S0TX | UDMA_ALT_SELECT, ulDMASetting); // // Set the DMA channel configuration. // if(g_usChannels == 1) { // // Handle stereo recording. // if(g_usBitsPerSample == 8) { // // The transfer size is 8 bits from the RX FIFO to // RX buffer. // ulDMASetting = (UDMA_SIZE_8 | UDMA_DST_INC_8 | UDMA_SRC_INC_NONE | UDMA_ARB_2); // // Only read the most significant byte of the I2S FIFO. // g_pvFIFORecord = (void *)(I2S0_BASE + I2S_O_RXFIFO + 3); } else { // // The transfer size is 16 bits from the RX FIFO to // RX buffer. // ulDMASetting = (UDMA_SIZE_16 | UDMA_DST_INC_16 | UDMA_SRC_INC_NONE | UDMA_ARB_2); // // Only read the most significant 16 bits of the I2S FIFO. // g_pvFIFORecord = (void *)(I2S0_BASE + I2S_O_RXFIFO + 2); } } else { // // Handle stereo recording. // if(g_usBitsPerSample == 8) { // // The transfer size is 16 bits(stereo 8 bits) from the RX FIFO to // RX buffer. // ulDMASetting = (UDMA_SIZE_16 | UDMA_DST_INC_16 | UDMA_SRC_INC_NONE | UDMA_ARB_2); // // Only read the most significant 16 bits of the I2S FIFO. // g_pvFIFORecord = (void *)(I2S0_BASE + I2S_O_RXFIFO); } else { // // The transfer size is 32 bits(stereo 16 bits) from the RX FIFO to // RX buffer. // ulDMASetting = (UDMA_SIZE_32 | UDMA_DST_INC_32 | UDMA_SRC_INC_NONE | UDMA_ARB_2); // // Only read the most significant byte of the I2S FIFO. // g_pvFIFORecord = (void *)(I2S0_BASE + I2S_O_RXFIFO); } } // // Configure the DMA settings for this channel. // uDMAChannelControlSet(UDMA_CHANNEL_I2S0RX | UDMA_PRI_SELECT, ulDMASetting); uDMAChannelControlSet(UDMA_CHANNEL_I2S0RX | UDMA_ALT_SELECT, ulDMASetting); }
//***************************************************************************** // //! Configures the I2S peripheral for the given audio data format. //! //! \param ulSampleRate is the sample rate of the audio to be played in //! samples per second. //! \param usBitsPerSample is the number of bits in each audio sample. //! \param usChannels is the number of audio channels, 1 for mono, 2 for stereo. //! //! This function configures the I2S peripheral in preparation for playing //! audio data of a particular format. //! //! \return None. // //***************************************************************************** void SoundSetFormat(unsigned long ulSampleRate, unsigned short usBitsPerSample, unsigned short usChannels) { unsigned long ulFormat; // // Save these values for use when configuring I2S. // g_ulSampleRate = ulSampleRate; g_usChannels = usChannels; g_usBitsPerSample = usBitsPerSample; I2SMasterClockSelect(I2S0_BASE, 0); // // Set the sample rate. // switch(g_ulSampleRate) { case 48000: { HWREG(SYSCTL_I2SMCLKCFG) = I2S_TX_8MHZ_48KHZ | I2S_RX_8MHZ_48KHZ; break; } case 44100: { HWREG(SYSCTL_I2SMCLKCFG) = I2S_TX_8MHZ_44KHZ | I2S_RX_8MHZ_44KHZ; break; } case 22222: case 22050: { HWREG(SYSCTL_I2SMCLKCFG) = I2S_TX_8MHZ_22KHZ | I2S_RX_8MHZ_22KHZ; break; } default: case 11025: { HWREG(SYSCTL_I2SMCLKCFG) = I2S_TX_8MHZ_11KHZ | I2S_RX_8MHZ_11KHZ; break; } } ulFormat = I2S_CONFIG_FORMAT_I2S | I2S_CONFIG_CLK_MASTER | I2S_CONFIG_EMPTY_ZERO | I2S_CONFIG_WIRE_SIZE_32; if(g_usChannels == 1) { if(g_usBitsPerSample == 8) { ulFormat |= I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_8; } else { ulFormat |= I2S_CONFIG_MODE_COMPACT_16 | I2S_CONFIG_SAMPLE_SIZE_16; } } else { if(g_usBitsPerSample == 8) { ulFormat |= I2S_CONFIG_MODE_COMPACT_8 | I2S_CONFIG_SAMPLE_SIZE_8; } else { ulFormat |= I2S_CONFIG_MODE_COMPACT_16 | I2S_CONFIG_SAMPLE_SIZE_16; } } // // Configure the I2S TX and RX blocks. // I2STxConfigSet(I2S0_BASE, ulFormat); I2SRxConfigSet(I2S0_BASE, ulFormat); I2SMasterClockSelect(I2S0_BASE, I2S_TX_MCLK_INT | I2S_RX_MCLK_INT); }
//***************************************************************************** // //! Configures the I2S peripheral to play audio in a given format. //! //! \param ulSampleRate is the sample rate of the audio to be played in //! samples per second. //! \param usBitsPerSample is the number of bits in each audio sample. //! \param usChannels is the number of audio channels, 1 for mono, 2 for stereo. //! //! This function configures the I2S peripheral in preparation for playing //! or recording audio data in a particular format. //! //! \return None. // //***************************************************************************** void SoundSetFormat(unsigned long ulSampleRate, unsigned short usBitsPerSample, unsigned short usChannels) { unsigned long ulFormat; unsigned long ulDMASetting; unsigned long ulI2SErrata; // // Save these values for use when configuring I2S. // g_usChannels = usChannels; g_usBitsPerSample = usBitsPerSample; // // Configure the I2S master clock for internal. // I2SMasterClockSelect(I2S0_BASE, I2S_TX_MCLK_INT); // // Configure the I2S to be a master. // ulFormat = I2S_CONFIG_FORMAT_I2S | I2S_CONFIG_CLK_MASTER; // // Check if the missing divisor bits need to be taken into account. // if(CLASS_IS_TEMPEST && REVISION_IS_B1) { ulI2SErrata = 1; } else { ulI2SErrata = 0; } // // Mono or Stereo formats. // if(g_usChannels == 1) { // // 8 bit formats. // if(g_usBitsPerSample == 8) { // // On Tempest class devices rev B parts the divisor is // limited for lower samples rates (see erratum). // if((ulI2SErrata != 0) && (ulSampleRate < 24400)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_8; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_8 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_8; } } // // 16-bit format // else if(g_usBitsPerSample == 16) { // // On Tempest class devices rev B parts the divisor is // limited for lower samples rates (see errata). // if((ulI2SErrata != 0) && (ulSampleRate < 12200)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_16; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_16 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_16; } } // // 24-bit format // else if(g_usBitsPerSample == 24) { ulFormat |= I2S_CONFIG_WIRE_SIZE_24 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_24; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_MONO | I2S_CONFIG_SAMPLE_SIZE_32; } } // // Stereo formats // else { // // 8-bit format // if(g_usBitsPerSample == 8) { // // On Tempest class devices rev B parts the divisor is // limited for lower samples rates (see errata). // if((ulI2SErrata != 0) && (ulSampleRate < 12200)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_COMPACT_8 | I2S_CONFIG_SAMPLE_SIZE_8; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_8 | I2S_CONFIG_MODE_COMPACT_8 | I2S_CONFIG_SAMPLE_SIZE_8; } } // // 16-bit format // else if(g_usBitsPerSample == 16) { if((ulI2SErrata != 0) && (ulSampleRate < 12200)) { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_COMPACT_16 | I2S_CONFIG_SAMPLE_SIZE_16; usBitsPerSample = 32; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_16 | I2S_CONFIG_MODE_COMPACT_16 | I2S_CONFIG_SAMPLE_SIZE_16; } } // // 24-bit format // else if(g_usBitsPerSample == 24) { ulFormat |= I2S_CONFIG_WIRE_SIZE_24 | I2S_CONFIG_MODE_DUAL | I2S_CONFIG_SAMPLE_SIZE_24; } else { ulFormat |= I2S_CONFIG_WIRE_SIZE_32 | I2S_CONFIG_MODE_DUAL | I2S_CONFIG_SAMPLE_SIZE_32; } } // // Configure the I2S TX format. // I2STxConfigSet(I2S0_BASE, ulFormat); // // Set the MCLK rate and save it for conversion back to sample rate. // The multiply by 8 is due to a 4X oversample rate plus a factor of two // since the data is always stereo on the I2S interface. // g_ulSampleRate = SysCtlI2SMClkSet(0, (ulSampleRate * usBitsPerSample * 8)); // // Convert the MCLK rate to sample rate. // g_ulSampleRate = g_ulSampleRate / (usBitsPerSample * 8); // // Configure the I2S TX DMA channel to use high priority burst transfer. // uDMAChannelAttributeEnable(UDMA_CHANNEL_I2S0TX, (UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY)); // // Set the DMA channel configuration. // if(g_usChannels == 1) { // // Handle Mono formats. // if(g_usBitsPerSample == 8) { // // The transfer size is 8 bits from the TX buffer to the TX FIFO. // ulDMASetting = UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_2; } else { // // The transfer size is 16 bits from the TX buffer to the TX FIFO. // ulDMASetting = UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_2; } } else { // // Handle Stereo formats. // if(g_usBitsPerSample == 8) { // // The transfer size is 16 bits(stereo 8 bits) from the TX buffer // to the TX FIFO. // ulDMASetting = UDMA_SIZE_16 | UDMA_SRC_INC_16 | UDMA_DST_INC_NONE | UDMA_ARB_2; } else { // // The transfer size is 32 bits(stereo 16 bits) from the TX buffer // to the TX FIFO. // ulDMASetting = UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_NONE | UDMA_ARB_2; } } // // Configure the DMA settings for this channel. // uDMAChannelControlSet(UDMA_CHANNEL_I2S0TX | UDMA_PRI_SELECT, ulDMASetting); uDMAChannelControlSet(UDMA_CHANNEL_I2S0TX | UDMA_ALT_SELECT, ulDMASetting); }