//***************************************************************************** // // i2s.c - Driver for the I2S controller. // // Copyright (c) 2008-2010 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 6459 of the Stellaris Peripheral Driver Library. // //***************************************************************************** //***************************************************************************** // //! \addtogroup i2s_api //! @{ // //***************************************************************************** #include "inc/hw_i2s.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/debug.h" #include "driverlib/i2s.h" #include "driverlib/interrupt.h" //***************************************************************************** // //! Enables the I2S transmit module for operation. //! //! \param ulBase is the I2S module base address. //! //! This function enables the transmit module for operation. The module //! should be enabled after configuration. When the module is disabled, //! no data or clocks will be generated on the I2S signals. //! //! \return None. // //***************************************************************************** void I2STxEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Enable the tx FIFO service request. // HWREG(ulBase + I2S_O_TXISM) = I2S_TXISM_FFM; // // Read-modify-write the enable bit. // HWREG(ulBase + I2S_O_CFG) |= I2S_CFG_TXEN; } //***************************************************************************** // //! Disables the I2S transmit module for operation. //! //! \param ulBase is the I2S module base address. //! //! This function disables the transmit module for operation. The module //! should be disabled before configuration. When the module is disabled, //! no data or clocks will be generated on the I2S signals. //! //! \return None. // //***************************************************************************** void I2STxDisable(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Read-modify-write the enable bit. // HWREG(ulBase + I2S_O_CFG) &= ~I2S_CFG_TXEN; } //***************************************************************************** // //! Writes data samples to the I2S transmit FIFO with blocking. //! //! \param ulBase is the I2S module base address. //! \param ulData is the single or dual channel I2S data. //! //! This function writes a single channel sample or combined left-right //! samples to the I2S transmit FIFO. The format of the sample is determined //! by the configuration that was used with the function I2STxConfigSet(). //! If the transmit mode is I2S_MODE_DUAL_STEREO then the \e ulData parameter //! contains either the left or right sample. The left and right sample //! alternate with each write to the FIFO, left sample first. If the transmit //! mode is I2S_MODE_COMPACT_STEREO_16 or I2S_MODE_COMPACT_STEREO_8, then the //! \e ulData parameter contains both the left and right samples. If the //! transmit mode is I2S_MODE_SINGLE_MONO then the \e ulData parameter //! contains the single channel sample. //! //! For the compact modes, both the left and right samples are written at //! the same time. If 16-bit compact mode is used, then the least significant //! 16 bits contain the left sample, and the most significant 16 bits contain //! the right sample. If 8-bit compact mode is used, then the lower 8 bits //! contain the left sample, and the next 8 bits contain the right sample, //! with the upper 16 bits unused. //! //! If there is no room in the transmit FIFO, then this function will wait //! in a polling loop until the data can be written. //! //! \return None. // //***************************************************************************** void I2STxDataPut(unsigned long ulBase, unsigned long ulData) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Wait until there is space. // while(HWREG(ulBase + I2S_O_TXLEV) >= 16) { } // // Write the data to the I2S. // HWREG(ulBase + I2S_O_TXFIFO) = ulData; } //***************************************************************************** // //! Writes data samples to the I2S transmit FIFO without blocking. //! //! \param ulBase is the I2S module base address. //! \param ulData is the single or dual channel I2S data. //! //! This function writes a single channel sample or combined left-right //! samples to the I2S transmit FIFO. The format of the sample is determined //! by the configuration that was used with the function I2STxConfigSet(). //! If the transmit mode is I2S_MODE_DUAL_STEREO then the \e ulData parameter //! contains either the left or right sample. The left and right sample //! alternate with each write to the FIFO, left sample first. If the transmit //! mode is I2S_MODE_COMPACT_STEREO_16 or I2S_MODE_COMPACT_STEREO_8, then the //! \e ulData parameter contains both the left and right samples. If the //! transmit mode is I2S_MODE_SINGLE_MONO then the \e ulData parameter //! contains the single channel sample. //! //! For the compact modes, both the left and right samples are written at //! the same time. If 16-bit compact mode is used, then the least significant //! 16 bits contain the left sample, and the most significant 16 bits contain //! the right sample. If 8-bit compact mode is used, then the lower 8 bits //! contain the left sample, and the next 8 bits contain the right sample, //! with the upper 16 bits unused. //! //! If there is no room in the transmit FIFO, then this function will return //! immediately without writing any data to the FIFO. //! //! \return The number of elements written to the I2S transmit FIFO (1 or 0). // //***************************************************************************** long I2STxDataPutNonBlocking(unsigned long ulBase, unsigned long ulData) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Check for space to write. // if(HWREG(ulBase + I2S_O_TXLEV) < 16) { HWREG(ulBase + I2S_O_TXFIFO) = ulData; return(1); } else { return(0); } } //***************************************************************************** // //! Configures the I2S transmit module. //! //! \param ulBase is the I2S module base address. //! \param ulConfig is the logical OR of the configuration options. //! //! This function is used to configure the options for the I2S transmit //! channel. The parameter \e ulConfig is the logical OR of the following //! options: //! //! - \b I2S_CONFIG_FORMAT_I2S for standard I2S format, //! \b I2S_CONFIG_FORMAT_LEFT_JUST for left justified format, or //! \b I2S_CONFIG_FORMAT_RIGHT_JUST for right justified format. //! - \b I2S_CONFIG_SCLK_INVERT to invert the polarity of the serial bit clock. //! - \b I2S_CONFIG_MODE_DUAL for dual channel stereo, //! \b I2S_CONFIG_MODE_COMPACT_16 for 16-bit compact stereo mode, //! \b I2S_CONFIG_MODE_COMPACT_8 for 8-bit compact stereo mode, or //! \b I2S_CONFIG_MODE_MONO for single channel mono format. //! - \b I2S_CONFIG_CLK_MASTER or \b I2S_CONFIG_CLK_SLAVE to select whether //! the I2S transmitter is the clock master or slave. //! - \b I2S_CONFIG_SAMPLE_SIZE_32, \b _24, \b _20, \b _16, or \b _8 //! to select the number of bits per sample. //! - \b I2S_CONFIG_WIRE_SIZE_32, \b _24, \b _20, \b _16, or \b _8 //! to select the number of bits per word that are transferred on the data //! line. //! - \b I2S_CONFIG_EMPTY_ZERO or \b I2S_CONFIG_EMPTY_REPEAT to select whether //! the module transmits zeroes or repeats the last sample when the FIFO is //! empty. //! //! \return None. // //***************************************************************************** void I2STxConfigSet(unsigned long ulBase, unsigned long ulConfig) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulConfig & (I2S_CONFIG_FORMAT_MASK | I2S_CONFIG_MODE_MASK | I2S_CONFIG_EMPTY_MASK | I2S_CONFIG_CLK_MASK | I2S_CONFIG_SAMPLE_SIZE_MASK | I2S_CONFIG_WIRE_SIZE_MASK)) == ulConfig); // // Check to see if a compact mode is used. // if((ulConfig & I2S_CONFIG_MODE_MASK) == I2S_CONFIG_MODE_COMPACT_8) { // // If compact 8 mode is used, then need to adjust some bits // before writing the config register. Also set the FIFO // config register for 8 bit compact samples. // ulConfig &= ~I2S_CONFIG_MODE_MONO; HWREG(ulBase + I2S_O_TXFIFOCFG) = I2S_TXFIFOCFG_CSS; } else { // // If compact 8 mode is not used, then set the FIFO config // register for 16 bit. This is okay if a compact mode is // not used. // HWREG(ulBase + I2S_O_TXFIFOCFG) = 0; } // // Write the configuration register. Since all the fields are // specified by the configuration parameter, it is not necessary // to do a read-modify-write. // HWREG(ulBase + I2S_O_TXCFG) = ulConfig; } //***************************************************************************** // //! Sets the FIFO level at which a service request is generated. //! //! \param ulBase is the I2S module base address. //! \param ulLevel is the FIFO service request limit. //! //! This function is used to set the transmit FIFO fullness level at which //! a service request will occur. The service request is used to generate //! an interrupt or a DMA transfer request. The transmit FIFO will //! generate a service request when the number of items in the FIFO is //! less than the level specified in the \e ulLevel parameter. For example, //! if \e ulLevel is 8, then a service request will be generated when //! there are less than 8 samples remaining in the transmit FIFO. //! //! For the purposes of counting the FIFO level, a left-right sample pair //! counts as 2, whether the mode is dual or compact stereo. When mono //! mode is used, internally the mono sample is still treated as a sample //! pair, so a single mono sample counts as 2. Since the FIFO always deals //! with sample pairs, the level must be an even number from 0 to 16. The //! maximum value is 16, which will cause a service request when there //! is any room in the FIFO. The minimum value is 0, which disables the //! service request. //! //! \return None. // //***************************************************************************** void I2STxFIFOLimitSet(unsigned long ulBase, unsigned long ulLevel) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT(ulLevel <= 16); // // Write the FIFO limit // HWREG(ulBase + I2S_O_TXLIMIT) = ulLevel; } //***************************************************************************** // //! Gets the current setting of the FIFO service request level. //! //! \param ulBase is the I2S module base address. //! //! This function is used to get the value of the transmit FIFO service //! request level. This value is set using the I2STxFIFOLimitSet() //! function. //! //! \return Returns the current value of the FIFO service request limit. // //***************************************************************************** unsigned long I2STxFIFOLimitGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Read and return the FIFO limit // return(HWREG(ulBase + I2S_O_TXLIMIT)); } //***************************************************************************** // //! Gets the number of samples in the transmit FIFO. //! //! \param ulBase is the I2S module base address. //! //! This function is used to get the number of samples in the transmit //! FIFO. For the purposes of measuring the FIFO level, a left-right sample //! pair counts as 2, whether the mode is dual or compact stereo. When mono //! mode is used, internally the mono sample is still treated as a sample //! pair, so a single mono sample counts as 2. Since the FIFO always deals //! with sample pairs, normally the level will be an even number from 0 to //! 16. If dual stereo mode is used and only the left sample has been //! written without the matching right sample, then the FIFO level will be an //! odd value. If the FIFO level is odd, it indicates a left-right sample //! mismatch. //! //! \return Returns the number of samples in the transmit FIFO, which will //! normally be an even number. // //***************************************************************************** unsigned long I2STxFIFOLevelGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Read and return the transmit FIFO level. // return(HWREG(ulBase + I2S_O_TXLEV)); } //***************************************************************************** // //! Enables the I2S receive module for operation. //! //! \param ulBase is the I2S module base address. //! //! This function enables the receive module for operation. The module //! should be enabled after configuration. When the module is disabled, //! no data will be clocked in regardless of the signals on the I2S interface. //! //! \return None. // //***************************************************************************** void I2SRxEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Enable the tx FIFO service request. // HWREG(ulBase + I2S_O_RXISM) = I2S_RXISM_FFM; // // Read-modify-write the enable bit. // HWREG(ulBase + I2S_O_CFG) |= I2S_CFG_RXEN; } //***************************************************************************** // //! Disables the I2S receive module for operation. //! //! \param ulBase is the I2S module base address. //! //! This function disables the receive module for operation. The module //! should be disabled before configuration. When the module is disabled, //! no data will be clocked in regardless of the signals on the I2S interface. //! //! \return None. // //***************************************************************************** void I2SRxDisable(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Read-modify-write the enable bit. // HWREG(ulBase + I2S_O_CFG) &= ~I2S_CFG_RXEN; } //***************************************************************************** // //! Reads data samples from the I2S receive FIFO with blocking. //! //! \param ulBase is the I2S module base address. //! \param pulData points to storage for the returned I2S sample data. //! //! This function reads a single channel sample or combined left-right //! samples from the I2S receive FIFO. The format of the sample is determined //! by the configuration that was used with the function I2SRxConfigSet(). //! If the receive mode is I2S_MODE_DUAL_STEREO then the returned value //! contains either the left or right sample. The left and right sample //! alternate with each read from the FIFO, left sample first. If the receive //! mode is I2S_MODE_COMPACT_STEREO_16 or I2S_MODE_COMPACT_STEREO_8, then the //! returned data contains both the left and right samples. If the //! receive mode is I2S_MODE_SINGLE_MONO then the returned data //! contains the single channel sample. //! //! For the compact modes, both the left and right samples are read at //! the same time. If 16-bit compact mode is used, then the least significant //! 16 bits contain the left sample, and the most significant 16 bits contain //! the right sample. If 8-bit compact mode is used, then the lower 8 bits //! contain the left sample, and the next 8 bits contain the right sample, //! with the upper 16 bits unused. //! //! If there is no data in the receive FIFO, then this function will wait //! in a polling loop until data is available. //! //! \return None. // //***************************************************************************** void I2SRxDataGet(unsigned long ulBase, unsigned long *pulData) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Wait until there is data available. // while(HWREG(ulBase + I2S_O_RXLEV) == 0) { } // // Read data from the I2S receive FIFO. // *pulData = HWREG(ulBase + I2S_O_RXFIFO); } //***************************************************************************** // //! Reads data samples from the I2S receive FIFO without blocking. //! //! \param ulBase is the I2S module base address. //! \param pulData points to storage for the returned I2S sample data. //! //! This function reads a single channel sample or combined left-right //! samples from the I2S receive FIFO. The format of the sample is determined //! by the configuration that was used with the function I2SRxConfigSet(). //! If the receive mode is I2S_MODE_DUAL_STEREO then the received data //! contains either the left or right sample. The left and right sample //! alternate with each read from the FIFO, left sample first. If the receive //! mode is I2S_MODE_COMPACT_STEREO_16 or I2S_MODE_COMPACT_STEREO_8, then the //! received data contains both the left and right samples. If the //! receive mode is I2S_MODE_SINGLE_MONO then the received data //! contains the single channel sample. //! //! For the compact modes, both the left and right samples are read at //! the same time. If 16-bit compact mode is used, then the least significant //! 16 bits contain the left sample, and the most significant 16 bits contain //! the right sample. If 8-bit compact mode is used, then the lower 8 bits //! contain the left sample, and the next 8 bits contain the right sample, //! with the upper 16 bits unused. //! //! If there is no data in the receive FIFO, then this function will return //! immediately without reading any data from the FIFO. //! //! \return The number of elements read from the I2S receive FIFO (1 or 0). // //***************************************************************************** long I2SRxDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Check for available samples. // if(HWREG(ulBase + I2S_O_RXLEV) != 0) { *pulData = HWREG(ulBase + I2S_O_RXFIFO); return(1); } else { return(0); } } //***************************************************************************** // //! Configures the I2S receive module. //! //! \param ulBase is the I2S module base address. //! \param ulConfig is the logical OR of the configuration options. //! //! This function is used to configure the options for the I2S receive //! channel. The parameter \e ulConfig is the logical OR of the following //! options: //! //! - \b I2S_CONFIG_FORMAT_I2S for standard I2S format, //! \b I2S_CONFIG_FORMAT_LEFT_JUST for left justified format, or //! \b I2S_CONFIG_FORMAT_RIGHT_JUST for right justified format. //! - \b I2S_CONFIG_SCLK_INVERT to invert the polarity of the serial bit clock. //! - \b I2S_CONFIG_MODE_DUAL for dual channel stereo, //! \b I2S_CONFIG_MODE_COMPACT_16 for 16-bit compact stereo mode, //! \b I2S_CONFIG_MODE_COMPACT_8 for 8-bit compact stereo mode, or //! \b I2S_CONFIG_MODE_MONO for single channel mono format. //! - \b I2S_CONFIG_CLK_MASTER or \b I2S_CONFIG_CLK_SLAVE to select whether //! the I2S receiver is the clock master or slave. //! - \b I2S_CONFIG_SAMPLE_SIZE_32, \b _24, \b _20, \b _16, or \b _8 //! to select the number of bits per sample. //! - \b I2S_CONFIG_WIRE_SIZE_32, \b _24, \b _20, \b _16, or \b _8 //! to select the number of bits per word that are transferred on the data //! line. //! //! \return None. // //***************************************************************************** void I2SRxConfigSet(unsigned long ulBase, unsigned long ulConfig) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulConfig & (I2S_CONFIG_FORMAT_MASK | I2S_CONFIG_MODE_MASK | I2S_CONFIG_CLK_MASK | I2S_CONFIG_SAMPLE_SIZE_MASK | I2S_CONFIG_WIRE_SIZE_MASK)) == ulConfig); // // Clear out any prior config of the RX FIFO config register. // HWREG(ulBase + I2S_O_RXFIFOCFG) = 0; // // If mono mode is used, then the FMM bit needs to be set. // if((ulConfig & I2S_CONFIG_MODE_MASK) == I2S_CONFIG_MODE_MONO) { HWREG(ulBase + I2S_O_RXFIFOCFG) |= I2S_RXFIFOCFG_FMM; } // // If a compact mode is used, then the CSS bit needs to be set. // else if((ulConfig & I2S_CONFIG_MODE_MASK) == I2S_CONFIG_MODE_COMPACT_8) { HWREG(ulBase + I2S_O_RXFIFOCFG) |= I2S_RXFIFOCFG_CSS; } // // The "mono" bits needs to be removed from the configuration word // prior to writing to hardware, because the RX configuration register // does not actually use these bits. // ulConfig &= ~I2S_CONFIG_MODE_MONO; // // Write the configuration register. Since all the fields are // specified by the configuration parameter, it is not necessary // to do a read-modify-write. // HWREG(ulBase + I2S_O_RXCFG) = ulConfig; } //***************************************************************************** // //! Sets the FIFO level at which a service request is generated. //! //! \param ulBase is the I2S module base address. //! \param ulLevel is the FIFO service request limit. //! //! This function is used to set the receive FIFO fullness level at which //! a service request will occur. The service request is used to generate //! an interrupt or a DMA transfer request. The receive FIFO will //! generate a service request when the number of items in the FIFO is //! greater than the level specified in the \e ulLevel parameter. For example, //! if \e ulLevel is 4, then a service request will be generated when //! there are more than 4 samples available in the receive FIFO. //! //! For the purposes of counting the FIFO level, a left-right sample pair //! counts as 2, whether the mode is dual or compact stereo. When mono //! mode is used, internally the mono sample is still treated as a sample //! pair, so a single mono sample counts as 2. Since the FIFO always deals //! with sample pairs, the level must be an even number from 0 to 16. The //! minimum value is 0, which will cause a service request when there //! is any data available in the FIFO. The maximum value is 16, which //! disables the service request (because there cannot be more than 16 //! items in the FIFO). //! //! \return None. // //***************************************************************************** void I2SRxFIFOLimitSet(unsigned long ulBase, unsigned long ulLevel) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT(ulLevel <= 16); // // Write the FIFO limit // HWREG(ulBase + I2S_O_RXLIMIT) = ulLevel; } //***************************************************************************** // //! Gets the current setting of the FIFO service request level. //! //! \param ulBase is the I2S module base address. //! //! This function is used to get the value of the receive FIFO service //! request level. This value is set using the I2SRxFIFOLimitSet() //! function. //! //! \return Returns the current value of the FIFO service request limit. // //***************************************************************************** unsigned long I2SRxFIFOLimitGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Read and return the FIFO limit. The lower bit is masked // because it always reads as 1, and has no meaning. // return(HWREG(ulBase + I2S_O_RXLIMIT) & 0xFFFE); } //***************************************************************************** // //! Gets the number of samples in the receive FIFO. //! //! \param ulBase is the I2S module base address. //! //! This function is used to get the number of samples in the receive //! FIFO. For the purposes of measuring the FIFO level, a left-right sample //! pair counts as 2, whether the mode is dual or compact stereo. When mono //! mode is used, internally the mono sample is still treated as a sample //! pair, so a single mono sample counts as 2. Since the FIFO always deals //! with sample pairs, normally the level will be an even number from 0 to //! 16. If dual stereo mode is used and only the left sample has been //! read without reading the matching right sample, then the FIFO level will //! be an odd value. If the FIFO level is odd, it indicates a left-right //! sample mismatch. //! //! \return Returns the number of samples in the transmit FIFO, which will //! normally be an even number. // //***************************************************************************** unsigned long I2SRxFIFOLevelGet(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Read and return the receive FIFO level. // return(HWREG(ulBase + I2S_O_RXLEV)); } //***************************************************************************** // //! Enables the I2S transmit and receive modules for operation. //! //! \param ulBase is the I2S module base address. //! //! This function simultaneously enables the transmit and receive modules for //! operation, providing a synchronized SCLK and LRCLK. The module should be //! enabled after configuration. When the module is disabled, no data or //! clocks will be generated on the I2S signals. //! //! \return None. // //***************************************************************************** void I2STxRxEnable(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Enable the Tx FIFO service request. // HWREG(ulBase + I2S_O_TXISM) = I2S_TXISM_FFM; // // Enable the Rx FIFO service request. // HWREG(ulBase + I2S_O_RXISM) = I2S_RXISM_FFM; // // Enable the transmit and receive modules. // HWREG(ulBase + I2S_O_CFG) |= I2S_CFG_TXEN | I2S_CFG_RXEN; } //***************************************************************************** // //! Disables the I2S transmit and receive modules. //! //! \param ulBase is the I2S module base address. //! //! This function simultaneously disables the transmit and receive modules. //! When the module is disabled, no data or clocks will be generated on the I2S //! signals. //! //! \return None. // //***************************************************************************** void I2STxRxDisable(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Disable the transmit and receive modules. // HWREG(ulBase + I2S_O_CFG) &= ~(I2S_CFG_TXEN | I2S_CFG_RXEN); } //***************************************************************************** // //! Configures the I2S transmit and receive modules. //! //! \param ulBase is the I2S module base address. //! \param ulConfig is the logical OR of the configuration options. //! //! This function is used to configure the options for the I2S transmit and //! receive channels with identical parameters. The parameter \e ulConfig is //! the logical OR of the following options: //! //! - \b I2S_CONFIG_FORMAT_I2S for standard I2S format, //! \b I2S_CONFIG_FORMAT_LEFT_JUST for left justified format, or //! \b I2S_CONFIG_FORMAT_RIGHT_JUST for right justified format. //! - \b I2S_CONFIG_SCLK_INVERT to invert the polarity of the serial bit clock. //! - \b I2S_CONFIG_MODE_DUAL for dual channel stereo, //! \b I2S_CONFIG_MODE_COMPACT_16 for 16-bit compact stereo mode, //! \b I2S_CONFIG_MODE_COMPACT_8 for 8-bit compact stereo mode, or //! \b I2S_CONFIG_MODE_MONO for single channel mono format. //! - \b I2S_CONFIG_CLK_MASTER or \b I2S_CONFIG_CLK_SLAVE to select whether //! the I2S transmitter is the clock master or slave. //! - \b I2S_CONFIG_SAMPLE_SIZE_32, \b _24, \b _20, \b _16, or \b _8 //! to select the number of bits per sample. //! - \b I2S_CONFIG_WIRE_SIZE_32, \b _24, \b _20, \b _16, or \b _8 //! to select the number of bits per word that are transferred on the data //! line. //! - \b I2S_CONFIG_EMPTY_ZERO or \b I2S_CONFIG_EMPTY_REPEAT to select whether //! the module transmits zeroes or repeats the last sample when the FIFO is //! empty. //! //! \return None. // //***************************************************************************** void I2STxRxConfigSet(unsigned long ulBase, unsigned long ulConfig) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulConfig & (I2S_CONFIG_FORMAT_MASK | I2S_CONFIG_MODE_MASK | I2S_CONFIG_EMPTY_MASK | I2S_CONFIG_CLK_MASK | I2S_CONFIG_SAMPLE_SIZE_MASK | I2S_CONFIG_WIRE_SIZE_MASK)) == ulConfig); // // Clear out any prior configuration of the FIFO config registers. // HWREG(ulBase + I2S_O_TXFIFOCFG) = 0; HWREG(ulBase + I2S_O_RXFIFOCFG) = 0; // // If mono mode is used, then the FMM bit needs to be set. // if((ulConfig & I2S_CONFIG_MODE_MASK) == I2S_CONFIG_MODE_MONO) { HWREG(ulBase + I2S_O_RXFIFOCFG) |= I2S_RXFIFOCFG_FMM; ulConfig &= ~(I2S_CONFIG_MODE_MONO); } // // If a compact mode is used, then the CSS bit needs to be set. // if((ulConfig & I2S_CONFIG_MODE_MASK) == I2S_CONFIG_MODE_COMPACT_8) { HWREG(ulBase + I2S_O_TXFIFOCFG) |= I2S_TXFIFOCFG_CSS; HWREG(ulBase + I2S_O_RXFIFOCFG) |= I2S_RXFIFOCFG_CSS; } // // Write the configuration register. Since all the fields are specified by // the configuration parameter, it is not necessary to do a // read-modify-write. // HWREG(ulBase + I2S_O_TXCFG) = ulConfig; HWREG(ulBase + I2S_O_RXCFG) = ulConfig; } //***************************************************************************** // //! Selects the source of the master clock, internal or external. //! //! \param ulBase is the I2S module base address. //! \param ulMClock is the logical OR of the master clock configuration //! choices. //! //! This function selects whether the master clock is sourced from the device //! internal PLL, or comes from an external pin. The I2S serial bit clock //! (SCLK) and left-right word clock (LRCLK) are derived from the I2S master //! clock. The transmit and receive modules can be configured independently. //! The \e ulMClock parameter is chosen from the following: //! //! - one of \b I2S_TX_MCLK_EXT or \b I2S_TX_MCLK_INT //! - one of \b I2S_RX_MCLK_EXT or \b I2S_RX_MCLK_INT //! //! \return Returns None. // //***************************************************************************** void I2SMasterClockSelect(unsigned long ulBase, unsigned long ulMClock) { unsigned long ulConfig; // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulMClock & (I2S_TX_MCLK_EXT | I2S_RX_MCLK_EXT)) == ulMClock); // // Set the clock selection bits in the configuation word. // ulConfig = HWREG(ulBase + I2S_O_CFG) & ~(I2S_TX_MCLK_EXT | I2S_RX_MCLK_EXT); HWREG(ulBase + I2S_O_CFG) = ulConfig | ulMClock; } //***************************************************************************** // //! Enables I2S interrupt sources. //! //! \param ulBase is the I2S module base address. //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled. //! //! This function enables the specified I2S sources to generate interrupts. //! The \e ulIntFlags parameter can be the logical OR of any of the following //! values: //! //! - \b I2S_INT_RXERR for receive errors //! - \b I2S_INT_RXREQ for receive FIFO service requests //! - \b I2S_INT_TXERR for transmit errors //! - \b I2S_INT_TXREQ for transmit FIFO service requests //! //! \return Returns None. // //***************************************************************************** void I2SIntEnable(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulIntFlags & (I2S_INT_RXERR | I2S_INT_RXREQ | I2S_INT_TXERR | I2S_INT_TXREQ)) == ulIntFlags); // // Enable the specified interrupts. // HWREG(ulBase + I2S_O_IM) |= ulIntFlags; } //***************************************************************************** // //! Disables I2S interrupt sources. //! //! \param ulBase is the I2S module base address. //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled. //! //! This function disables the specified I2S sources for interrupt //! generation. The \e ulIntFlags parameter can be the logical OR //! of any of the following values: \b I2S_INT_RXERR, \b I2S_INT_RXREQ, //! \b I2S_INT_TXERR, or \b I2S_INT_TXREQ. //! //! \return Returns None. // //***************************************************************************** void I2SIntDisable(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulIntFlags & (I2S_INT_RXERR | I2S_INT_RXREQ | I2S_INT_TXERR | I2S_INT_TXREQ)) == ulIntFlags); // // Enable the specified interrupts. // HWREG(ulBase + I2S_O_IM) &= ~ulIntFlags; } //***************************************************************************** // //! Gets the I2S interrupt status. //! //! \param ulBase is the I2S module base address. //! \param bMasked is set \b true to get the masked interrupt status, or //! \b false to get the raw interrupt status. //! //! This function returns the I2S interrupt status. It can return either //! the raw or masked interrupt status. //! //! \return Returns the masked or raw I2S interrupt status, as a bit field //! of any of the following values: \b I2S_INT_RXERR, \b I2S_INT_RXREQ, //! \b I2S_INT_TXERR, or \b I2S_INT_TXREQ // //***************************************************************************** unsigned long I2SIntStatus(unsigned long ulBase, tBoolean bMasked) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Return either the interrupt status or the raw interrupt status as // requested. // if(bMasked) { return(HWREG(ulBase + I2S_O_MIS)); } else { return(HWREG(ulBase + I2S_O_RIS)); } } //***************************************************************************** // //! Clears pending I2S interrupt sources. //! //! \param ulBase is the I2S module base address. //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared. //! //! This function clears the specified pending I2S interrupts. This must //! be done in the interrupt handler to keep the handler from being called //! again immediately upon exit. The \e ulIntFlags parameter can be the //! logical OR of any of the following values: \b I2S_INT_RXERR, //! \b I2S_INT_RXREQ, \b I2S_INT_TXERR, or \b I2S_INT_TXREQ. //! //! \note Since there is a write buffer in the Cortex-M3 processor, it may take //! several clock cycles before the interrupt source is actually cleared. //! Therefore, it is recommended that the interrupt source be cleared early in //! the interrupt handler (as opposed to the very last action) to avoid //! returning from the interrupt handler before the interrupt source is //! actually cleared. Failure to do so may result in the interrupt handler //! being immediately reentered (since NVIC still sees the interrupt source //! asserted). //! //! \return Returns None. // //***************************************************************************** void I2SIntClear(unsigned long ulBase, unsigned long ulIntFlags) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT((ulIntFlags & (I2S_INT_RXERR | I2S_INT_RXREQ | I2S_INT_TXERR | I2S_INT_TXREQ)) == ulIntFlags); // // Clear the requested interrupt sources. // HWREG(ulBase + I2S_O_IC) = ulIntFlags; } //***************************************************************************** // //! Registers an interrupt handler for the I2S controller. //! //! \param ulBase is the I2S module base address. //! \param pfnHandler is a pointer to the function to be called when the //! interrupt is activated. //! //! This sets and enables the handler to be called when the I2S controller //! generates an interrupt. Specific I2S interrupts must still be enabled //! with the I2SIntEnable() function. It is the responsibility of the //! interrupt handler to clear any pending interrupts with I2SIntClear(). //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void I2SIntRegister(unsigned long ulBase, void (*pfnHandler)(void)) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); ASSERT(pfnHandler); // // Register the interrupt handler. // IntRegister(INT_I2S0, pfnHandler); // // Enable the I2S interface interrupt. // IntEnable(INT_I2S0); } //***************************************************************************** // //! Unregisters an interrupt handler for the I2S controller. //! //! \param ulBase is the I2S module base address. //! //! This function will disable and clear the handler to be called when the //! I2S interrupt occurs. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void I2SIntUnregister(unsigned long ulBase) { // // Check the arguments. // ASSERT(ulBase == I2S0_BASE); // // Disable the I2S interface interrupt. // IntDisable(INT_I2S0); // // Unregister the interrupt handler. // IntUnregister(INT_I2S0); } //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************