⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2saudio.cpp

📁 CIRRUS 公司EP93XX系列CPU的WINCE下的BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    if((m_ulCodec != 4228) && (m_ulCodec != 4271))
    {

        //
        // Use a default.
        //
        m_ulCodec = 4228;
    }

    if(m_ulCodec == 4228)
    {
        RETAILMSG(1, (TEXT("Audio configuring for CS4228\r\n")));
    }
    else if(m_ulCodec == 4271)
    {
        RETAILMSG(1, (TEXT("Audio configuring for CS4271\r\n")));
    }
    else
    {
        RETAILMSG(1, (TEXT("Audio has unknown codec setting!\r\n")));
    }

    //
    // Set the sample rate at 441Khz.  Need to set the sample rate in order to
    // talk to the CS4228.
    //
    mmRet = SetSampleRate(44100, 0);

    //
    // Set up the I2S audio to use the AC97 port EGPIO for secondary I2S 
    // channels.
    //
    HalWriteCommonReg
    (
        CSC_DEVCFG, 
        DEVCFG_I2SONSSP | DEVCFG_I2SONAC97,
        DEVCFG_I2SONAC97
    );

    //
    // Disable all transmit audio channels.
    // Disable all recieve audio channels.
    // Set the global configuration register to Disable PCLK to it.
    //
    *SAI_TX0_EN = *SAI_TX1_EN =* SAI_TX2_EN   = 0;
    *SAI_RX0_EN = *SAI_RX1_EN =* SAI_RX2_EN   = 0;
    *SAI_GCR                                  = 0;

    //
    // Initialize the SAI interface. 
    //
    *SAI_TX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_POLARITY;
    *SAI_RX_CLKCFG = CLKCFG_MST | CLKCFG_TREL | CLKCFG_NBCG | CLKCFG_POLARITY;

    //
    // Left justified, MSB first, Repeat zero if underflow.
    // Outputing zero's will cause the dac to mute.
    //
//    *SAI_TX_LCR     = TX_LCR_UNDERFLOW_ZERO;
    *SAI_TX_LCR     = 0;
    
    //
    // Generate a Interrupt on Halfempty
    // (Don't think this makes a difference for DMA.)
    //
    *SAI_TX_CR     = TX_CR_TXUFIE;

    //
    // Transmit word length. I don't think this matters in Left Justified
    // mode.
    //
    *SAI_TX_WL      = WL_24BIT;

    //
    // Left justified, MSB first.
    //
    *SAI_RX_LCR     = 0;

    //
    // Generate a Interrupt on Half full
    // (Don't think this makes a difference for DMA.)
    //
    *SAI_RX_CR     = RX_CR_OVERFLOW_INT;

    //
    // Receive word length. I don't think this matters in Left Justified
    // mode.
    //
    *SAI_RX_WL      = WL_24BIT;

    //
    // Set the global configuration register to enable PCLK to it.
    //
    *SAI_GCR        = GCR_PCLK;

    //
    // Get the Performance counter.
    //
    bRet = QueryPerformanceFrequency(&m_PerfFreq);    
    ASSERT(bRet);


    if(m_bTwoWire)
    {
        //
        // Sleep for a couple milliseconds to wait for the codec to power up.
        //
        Sleep(4);    

        if(m_ulCodec == 4228)
        {
            //
            // Using the CS4228 codec.
            //

            //
            // Unmute the three DACs. Perform auto mute if the samples are zero.
            //
            WriteCodecReg(CS4228_DAC_MUTE2, MUTE2_MUTEZ);

            //
            // Set up clock ratios. MCLK = 4 * SCLK
            //                      MCLK = 4 * 64 *LRCLK = 128
            //
            WriteCodecReg(CS4228_CLOCK_MODE, CLOCK_MODE_BASERATE_256);

            //
            // Power up the chip - all dacs and the adc powered up.
            //
            WriteCodecReg(CS4228_CHIP_CNTL, CHIP_CNTL_NDIGPN);

            //
            // Unmute the three DACs
            //
            WriteCodecReg(CS4228_DAC_MUTE1, 0);

            //
            // Set ADC serial mode.
            //
            // SCLK = 64 * LRCLK 
            // Put the EP9312 as the master.
            // Put in 24 bit left I2S mode.
            //
            WriteCodecReg
            (
                CS4228_SERIAL_MODE, 
                SERIAL_MODE_DCK_B64 | SERIAL_MODE_DMS_SLAVE | SERIAL_MODE_DDF_I2S_24BIT
            );
        }
        else
        {
            //
            // The driver supports CS4228 and CS4271.  So, treat this as a CS4271.
            //
            //
            // Write to the control port, setting the enable control port bit
            // so that we can write to the control port...
            //
            WriteCodecReg
            (
                CS4271_MODE_CNTL2,
                0x02
            );

            //
            // Select slave, 24Bit I2S
            //
            WriteCodecReg
            (
                CS4271_MODE_CNTL,
                0x01
            );

            //
            // Select 24Bit I2S
            //
            WriteCodecReg
            (
                CS4271_ADC_CNTL,
                0x10
            );
        }


        ReadAllCodecReg();
    }
    else
    {
        //
        // Reconfigure the SPI so that we can setup our codec
        //
        SetSPIToI2S(m_ulCodec);

        if(m_ulCodec == 4228)
        {
            //
            // Using the CS4228 codec.
            //

            //
            // Unmute the three DACs. Perform auto mute if the samples are zero.
            //
            WriteCodecRegSPI(CS4228_DAC_MUTE2, MUTE2_MUTEZ);

            //
            // Set up clock ratios. MCLK = 4 * SCLK
            //                      MCLK = 4 * 64 *LRCLK = 128
            //
            WriteCodecRegSPI(CS4228_CLOCK_MODE, CLOCK_MODE_BASERATE_256);

            //
            // Power up the chip - all dacs and the adc powered up.
            //
            WriteCodecRegSPI(CS4228_CHIP_CNTL, CHIP_CNTL_NDIGPN);

            //
            // Unmute the three DACs
            //
            WriteCodecRegSPI(CS4228_DAC_MUTE1, 0);

            //
            // Set ADC serial mode.
            //
            // SCLK = 64 * LRCLK 
            // Put the EP9312 as the master.
            // Put in 24 bit I2S mode.
            //
            WriteCodecRegSPI
            (
                CS4228_SERIAL_MODE, 
                SERIAL_MODE_DCK_H32 | SERIAL_MODE_DMS_SLAVE | SERIAL_MODE_DDF_I2S_24BIT
 //               SERIAL_MODE_DCK_B64 | SERIAL_MODE_DMS_SLAVE | SERIAL_MODE_DDF_I2S_24BIT
            );
        }
        else
        {
            //
            // The driver supports CS4228 and CS4271.  So, treat this as a CS4271.
            //

			//
            // For the 4271 (on the 930x boards), we need to reset the codec 
            // so we can bring it out of standalone mode and configure it.
            // First, clear bit 1 of the data register
			//
            HalWriteCommonReg
            (
                GPIO_PADR,
                0x02,
                0x00
            );
			
			//
            // Set bit 1 of the DDR to set it to output
            // Now we are driving the reset pin low.
			//
            HalWriteCommonReg
            (
                GPIO_PADDR,
                0x02,
                0x02
            );

            Sleep(2);

			//
            // Set bit 1 of the data reg.  Now we drive the reset pin high.
			//
            HalWriteCommonReg
            (
                GPIO_PADR,
                0x02,
                0x02
            );
             
			Sleep(1);

            //
            // Write to the control port, setting the enable control port bit
            // and the PDN bit - so that we can write to the control port...
            //
            WriteCodecRegSPI
            (
                CS4271_MODE_CNTL2,
                0x03
            );

            //
            // Select slave, 24Bit I2S
            //
            WriteCodecRegSPI
            (
                CS4271_MODE_CNTL,
                0x01
            );

            //
            // Select 24Bit I2S
            //
            WriteCodecRegSPI
            (
                CS4271_ADC_CNTL,
                0x10
            );

			//
			// Ummute and set volumes to mid-range
			//
	        WriteCodecRegSPI
            (
                CS4271_DACA_VOL,
                0x40
            );

            WriteCodecRegSPI
            (
                CS4271_DACB_VOL,
                0x40
            );

            //
            // Clear the PDN bit and bring the codec up with our changes
            //
            WriteCodecRegSPI
            (
                CS4271_MODE_CNTL2,
                0x02
            );

        }

        //
        // Done with setup, configure SPI to handle PS2
        //
        SetSPIToPS2(m_ulCodec);
    }

    FUNC_I2S((L"-I2SCodec::Initialize\r\n"));
    return (MMSYSERR_NOERROR);
}


//****************************************************************************
// I2SCodec::SetRecordSampleRate
//****************************************************************************
// Sets the Record Sample Rate.
//
// ulFreq       - Sample Rate
// ulChannel    - Setting the Sample Rate for a specific channel.
//

MMRESULT  I2SCodec::SetRecordSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
    //
    // Check to see if we are playing audio.
    //
    if( m_ulCurrentFreq != ulFrequency)
    {
        return MMSYSERR_ALLOCATED;
    }

    return (MMSYSERR_NOERROR);
}

//****************************************************************************
// I2SCodec::SetPlaybackSampleRate
//****************************************************************************
// Sets the Sample Rate.
//
// ulFreq       - Sample Rate
// ulChannel    - Setting the Sample Rate for a specific channel.
//
MMRESULT  I2SCodec::SetPlaybackSampleRate(ULONG ulFrequency, ULONG ulChannel) 
{
    //
    // Check to see if we are playing audio.
    //
    if( m_ulCurrentFreq != ulFrequency)
    {
        return MMSYSERR_ALLOCATED;
    }

    return (MMSYSERR_NOERROR);
}




//****************************************************************************
// I2SCodec::SetSampleRate
//****************************************************************************
// Sets the Sample Rate.
//
// ulFreq       - Sample Rate
// ulChannel    - Setting the Sample Rate for a specific channel.
//
MMRESULT I2SCodec::SetSampleRate(ULONG ulFrequency, ULONG ulChannel)
{
    ULONG ulRequestedMClkFreq;
    ULONG ulMClkFreq1, ulMClkFreq2;
    ULONG ulI2SDiv, ulI2SDiv1, ulI2SDiv2;

    FUNC_I2S((L"+I2SCodec::SetSampleRate\r\n"));
    
    ulRequestedMClkFreq = ( ulFrequency * m_ulM2SClock * m_ulS2LRClock);


    CalculateClosestFreq
    (
        PLL1_CLOCK, 
        ulRequestedMClkFreq,
        &ulMClkFreq1,
        &ulI2SDiv1
    );
    CalculateClosestFreq
    (
        PLL2_CLOCK, 
        ulRequestedMClkFreq,
        &ulMClkFreq2,
        &ulI2SDiv2
    );

    //
    // See which is closer, MClk rate 1 or MClk rate 2.
    //
    if(abs(ulMClkFreq1 - ulRequestedMClkFreq) < abs(ulMClkFreq2 -ulRequestedMClkFreq))
    {
        ulI2SDiv       = ulI2SDiv1;
        m_ulActualFreq = ulMClkFreq1/ (m_ulM2SClock * m_ulS2LRClock);
    }
    else
    {
        ulI2SDiv = ulI2SDiv2 | I2SDIV_PSEL;;
        m_ulActualFreq = ulMClkFreq1 / (m_ulM2SClock * m_ulS2LRClock);
    }

    //
    // Calculate the new I2S rate.
    //
    HalWriteCommonReg
    (
        CSC_I2SDIV, 
        0xFFFFFFFF,
        ulI2SDiv |I2SDIV_SENA |  I2SDIV_ORIDE | I2SDIV_SPOL| 
        I2SDIV_LRDIV_64 | I2SDIV_SDIV |  I2SDIV_MENA | I2SDIV_ESEL
    );

    //
    // Save off the requested frequency.
    //
    m_ulCurrentFreq = ulFrequency;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -