📄 i2s_codec.c
字号:
}
}
}
/*******************************************************************************
* Function Name : GetVar_CurrentOutputDevice
* Description : Get the current output device selected .
* Input : None
* Output : None
* Return : None
*******************************************************************************/
u32 GetVar_CurrentOutputDevice(void)
{
return CurrentOutputDevice;
}
/*******************************************************************************
* Function Name : GetVar_AudioDataLength
* Description : Get the current audio file data length .
* Input : None
* Output : None
* Return : None
*******************************************************************************/
u32 GetVar_AudioDataLength(void)
{
return AudioDataLength;
}
/*******************************************************************************
* Function Name : GetVar_i2saudiofreq
* Description : Get the current audio frequency .
* Input : None
* Output : None
* Return : None
*******************************************************************************/
u16 GetVar_i2saudiofreq(void)
{
return i2saudiofreq;
}
/*******************************************************************************
* Function Name : AudioFile_Init
* Description : Initializes the SPI_Flsh and returns the Wavadatalength variable.
* Input : None
* Output : None
* Return : - The length of the wave file read from the SPI_Flash
* - 1 if an error occured when initializing the memory.
* - 2 if an error occured on the audio file intialization.
*******************************************************************************/
u32 AudioFile_Init(void)
{
u32 err = 0;
/* Initialize the media support */
err = Media_Init();
/* Check if Memory initialization is OK */
if (err != 0)
{
return 1;
}
/* Read a Byte buffer and store it in the Header table*/
Media_BufferRead(AudioFileHeader, AudioFileAddress, HEADER_SIZE);
/* Read and check the audio file Header */
WaveFileStatus = I2S_CODEC_WaveParsing(AudioFileHeader);
/* Check if the selected file is a correct wave file */
if(WaveFileStatus == Valid_WAVE_File)
{
/* Read and set the audio data length (/!\ data are counted as BYTES /!\) */
AudioDataLength = WAVE_Format.DataSize ;
/* Read and set the audio frequency */
i2saudiofreq = (u16)WAVE_Format.SampleRate;
/* Return the audio file length */
return AudioDataLength;
}
else /* Wrong wave file */
{
return 2;
}
}
/*******************************************************************************
* Function Name : NVIC_Config
* Description : Configure the I2Ss NVIC channel.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* SPI2 IRQ Channel configuration */
NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*******************************************************************************
* Function Name : I2S_GPIO_Config
* Description : Initializes the GPIO pins used by the codec application.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void I2S_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOB, GPIOC and AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOG |
RCC_APB2Periph_GPIOF | RCC_APB2Periph_AFIO, ENABLE);
/* I2S2 SD, CK and WS pins configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* I2S2 MCK pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* LEDs pins configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* I2C1 SCL PB6 and SDA PB7 pins configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Enable the I2C1 APB1 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Turn Off All LEDs */
GPIO_ResetBits(GPIOF, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
GPIO_ResetBits(Codec_PDN_GPIO, Codec_PDN_Pin);
/* Configure the Codec PDN pin as output PushPull */
GPIO_InitStructure.GPIO_Pin = Codec_PDN_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(Codec_PDN_GPIO, &GPIO_InitStructure);
}
/*******************************************************************************
* Function Name : I2S_Config
* Description : Configure the I2S Peripheral.
* Input : - Standard: I2S_Standard_Phillips, I2S_Standard_MSB or I2S_Standard_LSB
* - MCLKOutput: I2S_MCLKOutput_Enable or I2S_MCLKOutput_Disable
* - AudioFreq: I2S_AudioFreq_8K, I2S_AudioFreq_16K, I2S_AudioFreq_22K,
* I2S_AudioFreq_44K or I2S_AudioFreq_48K
* Output : None
* Return : None
*******************************************************************************/
static void I2S_Config(u16 Standard, u16 MCLKOutput, u16 AudioFreq)
{
I2S_InitTypeDef I2S_InitStructure;
/* Enable I2S2 APB1 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
/* Deinitialize SPI2 peripheral */
SPI_I2S_DeInit(SPI2);
/* I2S2 peripheral configuration */
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
I2S_InitStructure.I2S_Standard = Standard;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_MCLKOutput = MCLKOutput;
I2S_InitStructure.I2S_AudioFreq = AudioFreq;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S_Init(SPI2, &I2S_InitStructure);
/* Disable the I2S2 TXE Interrupt */
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
/* Enable the SPI2/I2S2 peripheral */
I2S_Cmd(SPI2, ENABLE);
}
/*******************************************************************************
* Function Name : I2C_Config
* Description : Configure the I2C1 Peripheral.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void I2C_Config(void)
{
I2C_InitTypeDef I2C_InitStructure;
/* I2C1 configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x33;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 200000;
I2C_Init(I2C1, &I2C_InitStructure);
}
/*******************************************************************************
* Function Name : CODEC_Config
* Description : Configure the Codec in Headphone mode.
* Input : - OutputDevice: OutputDeviceHEADPHONE or OutputDeviceSPEAKER
* : - I2S_Standard: I2S communication standard could be I2S_Standard_Phillips
* : I2S_Standard_MSB or I2S_Standard_LSB.
* : - I2S_MCLKOutput: could be I2S_MCLKOutput_
* : - Volume:
* Output : None
* Return : 0-> correct communication, else wrong communication
*******************************************************************************/
u32 CODEC_Config(u16 OutputDevice, u16 I2S_Standard, u16 I2S_MCLKOutput, u8 Volume)
{
u32 Standard =0, counter = 0, PLLMode = 0;
/* Command the sending of dummy data */
ResetVar_SendDummyData();
/* Reset the Codec Registers */
I2S_CODEC_Reset();
/* Determine the I2S standard used */
switch (I2S_Standard)
{
case I2S_Standard_Phillips: Standard = 0x03; break;
case I2S_Standard_MSB: Standard = 0x02; break;
default : Standard = 0x01; break;
}
/* HEADPHONE codec configuration */
if ((OutputDevice & OutputDevice_HEADPHONE) != 0)
{
/* PLL Slave SD/WS reference mode ----------------------*/
if (I2S_MCLKOutput == I2S_MCLKOutput_Disable)
{
/* set the PLLMode variable */
PLLMode = 0x1;
/* Phillips(0x03)/MSB(0x02)/LSB(0x01) mode with PLL */
counter += CODEC_WriteRegister(0x04, (Standard | 0x20));
/* MCKI input frequency = 256.Fs */
counter += CODEC_WriteRegister(0x05, 0x03);
/* VCOM Power up (PMVCM bit)*/
counter += CODEC_WriteRegister(0x00, 0x40);
/* Enable PLL*/
counter += CODEC_WriteRegister(0x01, 0x01);
}
/* Ext Slave mode with no PLL --------------------------*/
else
{
/* Reset the PLL mode variable */
PLLMode = 0;
/* Phillips(0x03)/MSB(0x02)/LSB(0x01) mode with no PLL */
counter += CODEC_WriteRegister(0x04, Standard);
/* MCKI input frequency = 256.Fs */
counter += CODEC_WriteRegister(0x05, 0x00);
/* VCOM Power up (PMVCM bit)*/
counter += CODEC_WriteRegister(0x00, 0x40);
}
/* Command the sending of dummy data */
SetVar_SendDummyData();
/* Enable the I2S2 TXE Interrupt => Generate the clocks*/
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
/* Extra Configuration (of the ALC) */
counter += CODEC_WriteRegister(0x06, 0x3C );
counter += CODEC_WriteRegister(0x08, 0xE1 );
counter += CODEC_WriteRegister(0x0B, 0x00 );
counter += CODEC_WriteRegister(0x07, 0x20 );
counter += CODEC_WriteRegister(0x09, 0xC1 );
counter += CODEC_WriteRegister(0x0C, 0xC1 );
/* Uncomment these lines and set the correct filters values to use the
codec digital filters (for more details refer to the codec datasheet) */
// /* Filter 1 programming as High Pass filter (Fc=500Hz, Fs=8KHz, K=20, A=1, B=1) */
// counter += CODEC_WriteRegister(0x1C, 0x01);
// counter += CODEC_WriteRegister(0x1D, 0x80);
// counter += CODEC_WriteRegister(0x1E, 0xA0);
// counter += CODEC_WriteRegister(0x1F, 0x0B);
// /* Filter 3 programming as Low Pass filter (Fc=20KHz, Fs=8KHz, K=40, A=1, B=1) */
// counter += CODEC_WriteRegister(0x1C, 0x01);
// counter += CODEC_WriteRegister(0x1D, 0x00);
// counter += CODEC_WriteRegister(0x1E, 0x01);
// counter += CODEC_WriteRegister(0x1F, 0x01);
// /* Equilizer programming BP filter (Fc1=20Hz, Fc2=2.5KHz, Fs=44.1KHz, K=40, A=?, B=?, C=?) */
// counter += CODEC_WriteRegister(0x16, 0x00);
// counter += CODEC_WriteRegister(0x17, 0x75);
// counter += CODEC_WriteRegister(0x18, 0x00);
// counter += CODEC_WriteRegister(0x19, 0x01);
// counter += CODEC_WriteRegister(0x1A, 0x00);
// counter += CODEC_WriteRegister(0x1B, 0x51);
/* MCKI is 256.Fs with no PLL */
counter += CODEC_WriteRegister(0x05, 0x00 );
/* Switch control from DAC to Headphone */
counter += CODEC_WriteRegister(0x0F, 0x09 );
/* Bass Boost and Demphasis enable */
counter += CODEC_WriteRegister(0x0E, 0x18 );
/* Left Channel Digital Volume control */
counter += CODEC_WriteRegister(0x0A, Volume);
/* Right Channel Digital Volume control */
counter += CODEC_WriteRegister(0x0D, Volume);
/* Power up MIN and DAC (PMMIN and PMDAC bits)*/
counter += CODEC_WriteRegister(0x00, 0x74);
/* Enable Slave mode and Left/Right HP lines*/
counter += CODEC_WriteRegister(0x01, (0x30 | PLLMode));
/* Exit HP mute mode */
counter += CODEC_WriteRegister(0x01, (0x70 | PLLMode));
}
/* SPEAKER codec configuration */
if ((OutputDevice & OutputDevice_SPEAKER) != 0)
{
/* PLL Slave SD/WS reference mode ----------------------*/
if (I2S_MCLKOutput == I2S_MCLKOutput_Disable)
{
/* Phillips(0x03)/MSB(0x02)/LSB(0x01) mode with no PLL */
counter += CODEC_WriteRegister(0x04, (Standard | 0x20));
/* MCKI input frequency = 256.Fs */
counter += CODEC_WriteRegister(0x05, 0x03);
/* VCOM Power up (PMVCM bit)*/
counter += CODEC_WriteRegister(0x00, 0x40);
/* Enable PLL*/
counter += CODEC_WriteRegister(0x01, 0x01);
}
/* Ext Slave mode with no PLL --------------------------*/
else
{
/* Phillips(0x03)/MSB(0x02)/LSB(0x01) mode with no PLL */
counter += CODEC_WriteRegister(0x04, Standard);
/* MCKI input frequency = 256.Fs */
counter += CODEC_WriteRegister(0x05, 0x00);
/* VCOM Power up (PMVCM bit)*/
counter += CODEC_WriteRegister(0x00, 0x40);
}
/* Command the sending of dummy data */
SetVar_SendDummyData();
/* Enable the I2S2 TXE Interrupt => Generate the clocks*/
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
/* ReSelect the MCKI frequency (FS0-1 bits): 256.Fs */
counter += CODEC_WriteRegister(0x05, 0x02 );
/* Set up the path "DAC->Speaker-Amp" with no power save (DACS and SPPSN bits) */
counter += CODEC_WriteRegister(0x02, 0x20 );
/* Speaker Gain (SPKG0-1 bits): Gain=+10.65dB(ALC off)/+12.65(ALC on) */
counter += CODEC_WriteRegister(0x03, 0x10);
/* Extra Configuration (of the ALC) */
counter += CODEC_WriteRegister(0x06, 0x3C );
counter += CODEC_WriteRegister(0x08, 0xE1 );
counter += CODEC_WriteRegister(0x0B, 0x00 );
counter += CODEC_WriteRegister(0x07, 0x20 );
counter += CODEC_WriteRegister(0x09, 0x91 );
counter += CODEC_WriteRegister(0x0C, 0x91 );
/* Left Channel Digital Volume control */
counter += CODEC_WriteRegister(0x0A, Volume);
/* Right Channel Digital Volume control */
counter += CODEC_WriteRegister(0x0D, Volume);
/* Power up Speaker and DAC (PMSPK and PMDAC bits)*/
counter += CODEC_WriteRegister(0x00, 0x54);
/* Set up the path "DAC -> Speaker-Amp" with no power save */
counter += CODEC_WriteRegister(0x02, 0xA0 /*0xA1*/);
}
/* Disable the I2S2 TXE Interrupt */
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
/* Disable the sending of Dummy data */
ResetVar_SendDummyData();
/* Return the counter value */
return counter;
}
/*******************************************************************************
* Function Name : CODEC_WriteRegister
* Description : Writes a value in a register of the audio Codec through I2C.
* Input : - RegisterAddr: The target register adress (between 00x and 0x24)
* : - RegisterValue: The target register value to be written
* : - Verify: 0-> Don't verify the written data, 1-> Verify the written data
* Output : None
* Return : - 0 -> Correct write operation
* : - !0 -> Incorrect write operation
*******************************************************************************/
u32 CODEC_WriteRegister(u32 RegisterAddr, u32 RegisterValue)
{
u32 read_verif = 0;
/* Reset all I2C2 registers */
I2C_SoftwareResetCmd(I2C1, ENABLE);
I2C_SoftwareResetCmd(I2C1, DISABLE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -