Beispiel #1
0
//*****************************************************************************
//
//! 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);
}
Beispiel #3
0
//*****************************************************************************
//
//! 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);
}