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

📄 hwctxt.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 5 页
字号:



//-----------------------------------------------------------------------------
//
//  Function: BSPAudioInitSsi
//
//  This function initializes the specified audio port for input/output.
//
//  Parameters:
//      bus	- Audio SSI bus to use SSI1 / SSI2
//	  pSSI	- Pointer to the SSI base.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
void HardwareContext::BSPAudioInitSsi(AUDIO_BUS bus, PCSP_SSI_REG pSSI)
{
    // These are the only SSI configuration parameters that are different
    // between the network and I2S modes. We just default to setting up for
    // network mode and then adjust the settings if I2S mode was actually
    // selected.
	UNREFERENCED_PARAMETER(bus);
    UINT32 SSI_i2s_Mode        = SSI_SCR_I2S_MODE_NORMAL;
    UINT32 SSI_stcr_tsckp_Mode = SSI_STCR_TSCKP_RISING_EDGE;
    UINT32 SSI_stcr_tfsi_Mode  = SSI_STCR_TFSI_ACTIVE_HIGH;
    UINT32 SSI_stccr_dc_Mode   = 1;
    UINT32 SSI_scr_net_Mode    = SSI_SCR_NET_ENABLE;
    UINT32 SSI_stcr_tfsl_Mode  = SSI_STCR_TFSL_1BIT;
    UINT32 SSI_stccr_wl        = SSI_STCCR_WL_8BIT;
	UINT8 size = sizeof(HWSAMPLE);

    if (size == sizeof(INT16))
    {
        SSI_stccr_wl = SSI_STCCR_WL_16BIT;
    }
    else if (size == sizeof(INT32))
    {
        // The SSI only supports a maximum transfer size of 24 bits/word.
        SSI_stccr_wl = SSI_STCCR_WL_24BIT;
    }

    // Reconfigure the SSI to use the I2S mode instead if that was what was
    // selected.
    //
    // The required SSI configuration changes consist of the following:
    //
    //     * Either I2S master/slave mode.
    //     * The transmit data clocked at the falling edge.
    //     * Transmit frame sync is active low.
    //     * Select 2 words/frame.
    //

	PMIC_AUDIO_BUS_PROTOCOL stereo = STEREO_DAC_BUS_MODE;
    PMIC_AUDIO_BUS_PROTOCOL voice = VOICE_CODEC_BUS_MODE;
    if (((stereo == I2S_MODE)  && (pSSI == STEREO_DAC_SSI)) ||
        ((voice == I2S_MODE) && (pSSI == VOICE_CODEC_SSI)))

    {
        SSI_i2s_Mode = (((pSSI == m_pSSI1) && (BSP_SSI1_MASTER_BOOL)) ||
                        ((pSSI == m_pSSI2) && (BSP_SSI2_MASTER_BOOL))) ?
                           SSI_SCR_I2S_MODE_MASTER : SSI_SCR_I2S_MODE_SLAVE;
        SSI_stcr_tsckp_Mode = SSI_STCR_TSCKP_FALLING_EDGE;
        SSI_stcr_tfsi_Mode  = SSI_STCR_TFSI_ACTIVE_LOW;
        SSI_stccr_dc_Mode   = 1;                        // 2 words/frame
        SSI_scr_net_Mode    = SSI_SCR_NET_DISABLE;      // disable NETWORK mode
        SSI_stcr_tfsl_Mode  = SSI_STCR_TFSL_1WORD;      // 1-word long framesync
    }

     // Enable SSI clocks before we access the SSI registers.
    DDKClockSetGatingMode((pSSI == m_pSSI1) ?  DDK_CLOCK_GATE_INDEX_SSI1:
                                              	DDK_CLOCK_GATE_INDEX_SSI2,
                          				DDK_CLOCK_GATE_MODE_ENABLE);

    // Disable the SSI transmitter and receiver.
    CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_RE) | CSP_BITFMASK(SSI_SCR_TE));

    // Also mask all transmitter and receiver timeslots until we are ready
    // to begin a new audio I/O operation.
    OUTREG32(&pSSI->STMSK, 0xffffffff);
    OUTREG32(&pSSI->SRMSK, 0xffffffff);

    // Next disable the SSI so that we can reconfigure the items that
    // can only be changed when the SSI is disabled.
    //
    // We should do this as a separate write from disabling the SSI
    // transmitter and receiver in order to give the SSI sufficient
    // time to properly complete the previous operation.
    CLRREG32(&pSSI->SCR, CSP_BITFMASK(SSI_SCR_SSIEN));

    // Disable all SSI interrupts and DMA requests.
    OUTREG32(&pSSI->SIER, 0);

    // Also disable the transmit and receive FIFOs so that we can configure
    // the DMA watermark levels later.
    OUTREG32(&pSSI->STCR, 0);
    OUTREG32(&pSSI->SRCR, 0);

    // We can now begin reconfiguring the SSI for synchronous 4-wire mode.
    // Since we are using synchronous mode, we only need to configure the
    // SSI transmitter clock in the following stages and there is no need to
    // separately set the SSI receiver clock configuration.
    //
    // The SSI is configured for I2S master/slave mode here or just "normal"
    // mode if NETWORK_MODE was selected for the audio bus above. All clock
    // configuration settings for the selected master/slave mode will be done
    // later.
    //
    // The SSI SYS_CLK clock output is also disabled here since we do not need
    // it (even if the SSI is operated in master mode since the slave device
    // just needs to receive the framesync and bitclock signals).
    //
    // We never use 2-channel mode (where both FIFO0 and FIFO1 are active) so
    // that is disabled here as well.


    OUTREG32(&pSSI->SCR,
        CSP_BITFVAL(SSI_SCR_CLK_IST, SSI_SCR_CLK_IST_HIGH)      |
        CSP_BITFVAL(SSI_SCR_TCH_EN, SSI_SCR_TCH_EN_2CHAN_OFF)   |
        CSP_BITFVAL(SSI_SCR_SYS_CLK_EN, SSI_SCR_SYS_CLK_EN_OFF) |
        CSP_BITFVAL(SSI_SCR_I2S_MODE, SSI_i2s_Mode)             |
        CSP_BITFVAL(SSI_SCR_SYN, SSI_SCR_SYN_SYNC)              |
        CSP_BITFVAL(SSI_SCR_NET, SSI_scr_net_Mode));

    // Next, continue with the configuration of the SSI transmitter for
    // audio output/playback.
    //
    // To match the PMIC's capabilities, the SSI transmitter must transmit
    // 16-bit words MSB-first. Only FIFO0 is needed for single channel
    // operation but we leave it disabled until we are actually ready to
    // start an audio I/O operation.
    //
    // Also, the SSI transmitter's clock and framesync signals are configured
    // here for the slave mode of operation. We will change this later if it
    // turns out that the SSI is to be operated in bus master mode.
    //
    // Note that we must configure the transmitter's clock settings even if we
    // never use this SSI for audio playback because we are using synchronous
    // mode where the receiver shares the same clock configuration as the
    // transmitter.

    OUTREG32(&pSSI->STCR,
        CSP_BITFVAL(SSI_STCR_TXBIT0, SSI_STCR_TXBIT0_LSB_ALIGNED) |
        CSP_BITFVAL(SSI_STCR_TFEN1,  SSI_STCR_TFEN1_DISABLE)      |
        CSP_BITFVAL(SSI_STCR_TFEN0,  SSI_STCR_TFEN0_DISABLE)      |
        CSP_BITFVAL(SSI_STCR_TFDIR,  SSI_STCR_TFDIR_EXTERNAL)     |
        CSP_BITFVAL(SSI_STCR_TXDIR,  SSI_STCR_TXDIR_EXTERNAL)     |
        CSP_BITFVAL(SSI_STCR_TSHFD,  SSI_STCR_TSHFD_MSB_FIRST)    |
        CSP_BITFVAL(SSI_STCR_TSCKP,  SSI_stcr_tsckp_Mode)         |
        CSP_BITFVAL(SSI_STCR_TFSI,   SSI_stcr_tfsi_Mode)          |
        CSP_BITFVAL(SSI_STCR_TFSL,   SSI_stcr_tfsl_Mode)          |
        CSP_BITFVAL(SSI_STCR_TEFS,   SSI_STCR_TEFS_EARLY)
    );

    // Now configure the SSI receiver for audio input/recording.
    //
    // To match the PMIC's capabilities, the SSI receiver must receive
    // 16-bit words MSB-first. Only FIFO0 is needed for single channel
    // operation but we leave it disabled until we are actually ready to
    // start an audio I/O operation.
    //
    // Also, we skip configuring the SSI receiver's clock settings here because
    // we're using synchronous mode and we've already configured the SSI's
    // transmitter clock configuration above. The receiver will simply share
    // the same clock configuration as the transmitter.
    //
    // Note that it is harmless to also configure the SSI receiver even if we
    // never use this SSI for audio recording.
    OUTREG32(&pSSI->SRCR,
        CSP_BITFVAL(SSI_SRCR_RXBIT0, SSI_SRCR_RXBIT0_LSB_ALIGNED) |
        CSP_BITFVAL(SSI_SRCR_RFEN1,  SSI_SRCR_RFEN1_DISABLE)      |
        CSP_BITFVAL(SSI_SRCR_RFEN0,  SSI_SRCR_RFEN0_DISABLE)      |
        CSP_BITFVAL(SSI_SRCR_RSHFD,  SSI_SRCR_RSHFD_MSB_FIRST)
    );

    // Set the Receive FIFO empty and Transmit FIFO full watermark levels.
    //
    // We set the watermark levels for both FIFO0 and FIFO1 here even though
    // we will only use FIFO0 because all of the watermark levels must be set
    // to a valid value (regardless of whether the FIFO is used or not) in
    // order for the SSI to operate properly.
    OUTREG32(&pSSI->SFCSR,
        CSP_BITFVAL(SSI_SFCSR_RFWM0, SSI_SFCSR_RX_WATERMARK) |
        CSP_BITFVAL(SSI_SFCSR_TFWM0, SSI_SFCSR_TX_WATERMARK) |
        CSP_BITFVAL(SSI_SFCSR_RFWM1, SSI_SFCSR_RX_WATERMARK) |
        CSP_BITFVAL(SSI_SFCSR_TFWM1, SSI_SFCSR_TX_WATERMARK));

    BOOL bSSI1 = BSP_SSI1_MASTER_BOOL;
    BOOL bSSI2 = BSP_SSI2_MASTER_BOOL;

    if (((pSSI == m_pSSI1) && bSSI1) ||
        ((pSSI == m_pSSI2) && bSSI2))
    {
        // First configure the Clock Control Module to route the correct
        // system clock signal to the SSI.
#ifdef AUDIO_RECORDING_ENABLED
        if (pSSI == VOICE_CODEC_SSI)
        {
            // We want a 16 kHz sampling rate from the SSI for the Voice CODEC.
            //
            // The calculation of the appropriate SSI clock divider constants
            // is as follows:
            //
            //    Ideal Sampling Rate  = 16 kHz
            //    Oversampling Rate    = 384
            //    Ideal MCLK Frequency = 16 kHz * 384 = 6.144 MHz
            //    Serial PLL Frequency = 220.1472 MHz
            //
            //    SSI Divider = 220.1472 / 6.144 = 35.83125
            //                = 36 (rounded up)
            //
            // So that means we can set the predivider to divide-by-one (by
            // just writing 0) and the postdivider to divide-by-thirty-six
            // (which actually means writing a 35 to the postdivider control
            // register).
            DDKClockConfigBaud((pSSI == m_pSSI1) ? DDK_CLOCK_SIGNAL_SSI1 :
                                                   DDK_CLOCK_SIGNAL_SSI2,
                               (pSSI == m_pSSI1) ? SSI1_MASTER_CLOCK_SOURCE :
                                                   SSI2_MASTER_CLOCK_SOURCE,
                               35);

            // The associated SSI internal clock divider constants are:
            //
            //    Ideal Sampling Rate          = 16 kHz
            //    Bits/Word                    = 16
            //    Words/Frame                  = 4
            //    Ideal Bit Clock Frequency    = 16 kHz * 16 * 4 = 1.024 MHz
            //    SSI Internal Clock Frequency = 6.144 MHz (from above)
            //    SSI Internal Divider         = 6.144 / 1.024 = 6
            //
            // An internal divider value of 6 can be achieved by setting the
            // following:
            //
            //    DIV2 = 0
            //    PSR  = 0
            //    PM   = 2
            //
            // We also set the following to configure for bits/word and
            // words/frame:
            //
            //    DC = 3  (for network mode with 4 words/frame)
            //       = 1  (for I2S mode with 2 words/frame)
            //    WL = 3  (for 8 bits/word)
            //       = 7  (for 16 bits/word)
            //       = 11 (for 24 bits/word)
            //
            OUTREG32(&pSSI->STCCR,
                CSP_BITFVAL(SSI_STCCR_DIV2, SSI_STCCR_DIV2_BYPASS)    |
                CSP_BITFVAL(SSI_STCCR_PSR, SSI_STCCR_PSR_DIV8_BYPASS) |
                CSP_BITFVAL(SSI_STCCR_WL, SSI_stccr_wl)               |
                CSP_BITFVAL(SSI_STCCR_DC, SSI_stccr_dc_Mode)          |
                CSP_BITFVAL(SSI_STCCR_PM, 2));
        }
        else
#endif
		if (pSSI == STEREO_DAC_SSI)
        {
            // We want a 44.1 kHz sampling rate from the SSI for the Stereo DAC.
            //
            // The calculation of the appropriate SSI clock divider constants
            // is done as follows:
            //
            //    Ideal Sampling Rate  = 44.1 kHz
            //    Oversampling Rate    = 384
            //    Ideal MCLK Frequency = 44.1 kHz * 384 = 16.9344 MHz
            //    Serial PLL Frequency = 220.1472 MHz
            //
            //    SSI Divider = 220.1472 / 16.9344 = 13
            //
            // So that means we can set the predivider to divide-by-one (by
            // just writing 0) and the postdivider to divide-by-thirteen
            // (which actually means writing a 12 to the postdivider control
            // register).
            //
            // This will produce the exact 16.9344 MHz clock that we need
            // as the input to the SSI.
            DDKClockConfigBaud((pSSI == m_pSSI1) ? DDK_CLOCK_SIGNAL_SSI1 :
                                                   DDK_CLOCK_SIGNAL_SSI2,
                               (pSSI == m_pSSI1) ? SSI1_MASTER_CLOCK_SOURCE :
                                                   SSI2_MASTER_CLOCK_SOURCE,
                               12);

            // The associated SSI internal clock divider constants are
            // calculated as follows:
            //
            //    Ideal Sampling Rate              = 44.1 kHz
            //
            //    For NETWORK mode only:
            //        Bits/Word                    = 16
            //        Words/Frame                  = 4
            //        Ideal Bit Clock Frequency    = 44.1 kHz * 16 * 4
            //                                     = 2.8224 MHz
            //        SSI Internal Clock Frequency = 16.9344 MHz (from above)
            //        SSI Internal Divider         = 16.9344 / 2.8224 = 6
            //
            //    For I2S mode only:
            //        Bits/Word                    = 32
            //        Words/Frame                  = 2
            //        Ideal Bit Clock Frequency    = 44.1 kHz * 32 * 2
            //                                     = 2.8224 MHz
            //        SSI Internal Clock Frequency = 16.9344 MHz (from above)
            //        SSI Internal Divider         = 16.9344 / 2.8224 = 6
            //
            // The corresponding SSI internal divider settings are as follows:
            //
            //    For both NETWORK and I2S modes:
            //        DIV2 = 0
            //        PSR  = 0
            //        PM   = 2
            //
            // We also set the following to configure for bits/word and
            // either 4 or 2 words/frame:
            //
            //    DC = 3 (for network mode with 4 words/frame)
            //       = 1 (for I2S mode 2 words/frame)
            //    WL = 3  (for 8 bits/word)
            //       = 7  (for 16 bits/word)
            //       = 11 (for 24 bits/word)
            //
            // Note that for the I2S mode, the word length is fixed at 32
            // bits/word and the WL value only serves to indicate how many
            // out of the 32 bits/word are actually valid.
            OUTREG32(&pSSI->STCCR,
                CSP_BITFVAL(SSI_STCCR_DIV2, SSI_STCCR_DIV2_BYPASS)    |
                CSP_BITFVAL(SSI_STCCR_PSR, SSI_STCCR_PSR_DIV8_BYPASS) |
                CSP_BITFVAL(SSI_STCCR_WL, SSI_stccr_wl)               |
                CSP_BITFVAL(SSI_STCCR_DC, SSI_stccr_dc_Mode)          |
                CSP_BITFVAL(SSI_STCCR_PM, 2));
        }

        // Also set the SSI transmitter to use it's internal clock source to
        // generate the bit clock and framesync signals for master mode.
        SETREG32(&pSSI->STCR, CSP_BITFMASK(SSI_STCR_TXDIR));
        SETREG32(&pSSI->STCR, CSP_BITFMASK(SSI_STCR_TFDIR));
    }
    else
    {
        // Configure the SSI transmit clock for slave mode operation where
        // the internal divider and prescaler parameters are irrelevant. The
        // key settings are DC to select words/frame and WL for bits/word to
        // match the PMIC's configuration.
        OUTREG32(&pSSI->STCCR,
            CSP_BITFVAL(SSI_STCCR_DIV2, SSI_STCCR_DIV2_BYPASS)    |
            CSP_BITFVAL(SSI_STCCR_PSR, SSI_STCCR_PSR_DIV8_BYPASS) |
            CSP_BITFVAL(SSI_STCCR_WL, SSI_stccr_wl)               |
            CSP_BITFVAL(SSI_STCCR_DC, SSI_stccr_dc_Mode)          |
            CSP_BITFVAL(SSI_STCCR_PM, 0));
        // We have already configured the SSI transmitter to use an external
        // clock and framesync so nothing needs to be done here.
    }

#ifdef SSI_DEBUG
    OUTREG32(&pSSI->STR, 0x1111);
#endif

    // Leave the SSI in a disabled state until we are actually ready to perform
    // audio playback or recording.
    //
    // Also note that we leave all of the transmit and receive timeslots masked
    // at this time and only unmask the required timeslots when we call either
    // BSPAudioStartSsiOutput() or BSPAudioStartSsiInput().

    // Disable SSI clocks to minimize power consumption.

   BSPSSIConfigGPIO(CSP_BASE_REG_PA_SSI2, TRUE);

#ifdef AUDIO_RECORDING_ENABLED
   BSPSSIConfigGPIO(CSP_BASE_REG_PA_SSI1, TRUE);
#endif

    DDKClockSetGatingMode((pSSI == m_

⌨️ 快捷键说明

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