📄 i2s_codec.c
字号:
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
* File Name : i2s_codec.c
* Author : MCD Application Team
* Version : V1.1.1
* Date : 06/13/2008
* Description : This file includes the I2S Codec driver for AK4343
* Audio Codec.
********************************************************************************
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2s_codec.h"
/* Private typedef -----------------------------------------------------------*/
typedef enum
{
LittleEndian,
BigEndian
}Endianness;
/* Private define ------------------------------------------------------------*/
/* Audio file header size */
#define HEADER_SIZE 100
/* EvalBoard pins related to the Codec */
#define Codec_PDN_GPIO GPIOG
#define Codec_PDN_Pin GPIO_Pin_11
/* Uncomment this line to enable verifying data sent to codec after each write opeation */
//#define VERIFY_WRITTENDATA
/* The 7 bits Codec adress mask */
#define CODEC_ADDRESS 0x27 /* b00100111 */
/* Audio Parsing Constants */
#define ChunkID 0x52494646 /* correspond to the letters 'RIFF' */
#define FileFormat 0x57415645 /* correspond to the letters 'WAVE' */
#define FormatID 0x666D7420 /* correspond to the letters 'fmt ' */
#define DataID 0x64617461 /* correspond to the letters 'data' */
#define FactID 0x66616374 /* correspond to the letters 'fact' */
#define WAVE_FORMAT_PCM 0x01
#define FormatChunkSize 0x10
#define Channel_MONO 0x01
#define Channel_STEREO 0x02
#define SampleRate_8000 8000
#define SampleRate_16000 16000
#define SampleRate_22050 22050
#define SampleRate_44100 44100
#define SampleRate_48000 48000
#define Bits_Per_Sample_8 8
#define Bits_Per_Sample_16 16
#define DUMMY_DATA 0x1111
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Audio Frequency value */
u16 i2saudiofreq = I2S_AudioFreq_8k;
/* Header Table containing the audio file information */
u8 HeaderTabIndex = 0;
u8 AudioFileHeader[HEADER_SIZE];
/* Audio Codec variables */
vu32 AudioFileAddress = AUDIO_FILE_ADDRESS;
u32 AudioDataLength = 0;
u32 DataStartAddr = 0x0;
vu32 AudioDataIndex = 0;
static vu32 AudioReplay = 0xFFFF;
static u32 AudioReplayCount = 0xFFFF;
static vu32 SendDummyData = 0;
static vu32 AudioPlayStatus = AudioPlayStatus_STOPPED;
static u32 CurrentOutputDevice = OutputDevice_HEADPHONE;
static u8 CurrentVolume = DEFAULT_VOL;
static u32 errorcode = 0xFF;
static vu32 monovar = 0, tmpvar = 0;
/* Wave details names table */
WAVE_FormatTypeDef WAVE_Format;
volatile ErrorCode WaveFileStatus = Unvalid_RIFF_ID;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static void NVIC_Config(void);
static void I2S_GPIO_Config(void);
static void I2C_Config(void);
static void I2S_Config(u16 Standard, u16 MCLKOutput, u16 AudioFreq);
static u32 CODEC_Config(u16 AudioOutput, u16 I2S_Standard, u16 I2S_MCLKOutput, u8 Volume);
static u32 CODEC_WriteRegister(u32 RegisterAddr, u32 RegisterValue);
static u32 CODEC_ReadRegister(u32 RegisterAddr);
static u32 ReadUnit(u8 NbrOfBytes, Endianness BytesFormat);
u32 AudioFile_Init(void);
/*******************************************************************************
* Function Name : I2S_CODEC_Init
* Description : Initializes the I2S audio codec according parameters configured
* by I2S_CODEC_Config function.
* Input : - OutputDevice: Could be OutoutDevice_SPEAKER or
* OutoutDevice_HEADPHONE.
* - Address: Specifies the location of the audio file in the memory.
* Output : None
* Return : - 0: if all initializations are OK.
* - 1: if memory initialization failed (LD2 is turned on).
* - 2: if audio file initialization failed (LD2 is turned on).
* - 3: if Codec initialization failed (LD1 is turned on).
*******************************************************************************/
u32 I2S_CODEC_Init(u32 OutputDevice, u32 Address)
{
u32 count = 0;
/* Set the audio file address */
AudioFileAddress = (vu32) Address;
/* Configure I2S interrupt Channel */
NVIC_Config();
/* Configure the I2S2, I2C1 and GPIOF pins */
I2S_GPIO_Config();
/* Read the Audio file to extract the audio data length and frequency */
errorcode = AudioFile_Init();
if (errorcode < 3)
{
/* Turn on LD2 connected to PF.07 */
GPIO_SetBits(GPIOF, GPIO_Pin_7);
return errorcode;
}
/* Configure the SPI2 peripheral in I2S mode */
I2S_Config(I2S_STANDARD, I2S_MCLKOUTPUT, i2saudiofreq);
/* Set the current output device */
CurrentOutputDevice = OutputDevice;
/* Codec Configuration via I2C interface */
count = CODEC_Config(OutputDevice, I2S_STANDARD, I2S_MCLKOUTPUT, DEFAULT_VOL);
if (count != 0)
{
/* Turn on LD1 connected to PF.06 */
GPIO_SetBits(GPIOF, GPIO_Pin_6);
return 3;
}
/* Turn on LD4 connected to PF.09 */
GPIO_SetBits(GPIOF, GPIO_Pin_9);
return 0; /* Configuration is OK */
}
/*******************************************************************************
* Function Name : I2S_CODEC_ReplayConfig
* Description : Set AudioReplay variable value .
* Input : Repetions: Number of repetitions
* Output : None
* Return : None
*******************************************************************************/
void I2S_CODEC_ReplayConfig(u32 Repetions)
{
/* Audio Replay number set by user */
AudioReplay = Repetions;
/* Audio Replays number remaining (if AudioReplay != 0) */
AudioReplayCount = Repetions;
}
/*******************************************************************************
* Function Name : I2S_CODEC_Play
* Description : Plays the audio file.
* Input : - AudioStartPosition: Adress from which the wave data begin
* Output : None
* Return : AudioDataIndex value.
*******************************************************************************/
u32 I2S_CODEC_Play(u32 AudioStartPosition)
{
/* Send the read command to the media */
Media_StartReadSequence(AudioFileAddress + AudioStartPosition + 1);
/* Set Playing status to inform other modules about the codec status */
SetVar_AudioPlayStatus(AudioPlayStatus_PLAYING);
/* Enable the I2S2 TXE Interrupt => Generate the clocks*/
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
return AudioDataIndex;
}
/*******************************************************************************
* Function Name : I2S_CODEC_Pause
* Description : Pause playing the audio file.
* Input : None
* Output : None
* Return : Current Position.
*******************************************************************************/
u32 I2S_CODEC_Pause()
{
/* Disable the I2S2 TXE Interrupt => stop the clocks*/
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
/* Set Paused status to inform other modules about the codec status */
SetVar_AudioPlayStatus(AudioPlayStatus_PAUSED);
/* Reset local variables */
monovar = 0;
tmpvar = 0;
if (WAVE_Format.NumChannels == Channel_MONO)
{
/* Force the parity of the address */
AudioDataIndex &= 0xFFFFFFFE;
}
/* Return the current data pointer position */
return AudioDataIndex;
}
/*******************************************************************************
* Function Name : I2S_CODEC_Stop
* Description : Stop playing the audio file, reset the pointer and power off
* : the Codec.
* Input : None
* Output : None
* Return : 0 if operation complete.
*******************************************************************************/
u32 I2S_CODEC_Stop()
{
/* Disable the I2S2 TXE Interrupt => stop the clocks */
SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE);
/* Reinitialize the audio data pointer */
AudioDataIndex = 0;
/* Power off the Codec to save power and protect the Codec itself */
I2S_CODEC_PowerDown(CodecPowerDown_SW);
/* Set Paused status to inform other modules about the codec status */
SetVar_AudioPlayStatus(AudioPlayStatus_STOPPED);
/* Reset local variables */
monovar = 0;
tmpvar = 0;
return 0;
}
/*******************************************************************************
* Function Name : I2S_CODEC_ControlVolume
* Description : Controls the audio volume.
* Input : - direction: VolumeDirection_HIGH (0xF) to increase the volume,
* : VolumeDirection_LOW (0xA) to decrease the volume or
* : VolumeDirection_LEVEL (0x0) to set a defined level of volume.
* : - Volume: the step of volume increqing/decreasing (when direction == 0)
* : or the volume level to be set (when direction != 0).
* Output : None
* Return : 0-> correct communication, else wrong communication
*******************************************************************************/
u32 I2S_CODEC_ControlVolume(u32 direction, u8 Volume)
{
u32 counter = 0;
if (direction == VolumeDirection_HIGH)
{
/* Check if the volume high limit is reached */
if (CurrentVolume < VOLStep)
{
CurrentVolume = 0;
}
else
{
/* Save the current volume level */
CurrentVolume = CODEC_ReadRegister(0x0A) - Volume;
}
/* Set the new volume */
counter += CODEC_WriteRegister(0x0A, CurrentVolume);
}
else if (direction == VolumeDirection_LOW)
{
/* Check if the volume low limit is reached */
if (CurrentVolume > (0xFF - VOLStep))
{
CurrentVolume = 0xFF;
}
else
{
/* Save the current volume level */
CurrentVolume = CODEC_ReadRegister(0x0A) + Volume;
}
/* Set the new volume */
counter += CODEC_WriteRegister(0x0A, CurrentVolume);
}
else if (direction == VolumeDirection_LEVEL)
{
CurrentVolume = Volume;
/* Set the new volume */
counter += CODEC_WriteRegister(0x0A, Volume);
}
else
{
return 0xFF; //Error verifying the Codec registers
}
return counter;
}
/*******************************************************************************
* Function Name : I2S_CODEC_Mute
* Description : Enable or disable the MUTE mode by software
* Input : - Command: could be MUTEON to mute sound or MUTEOFF to restore volume
* Output : None.
* Return : None.
*******************************************************************************/
void I2S_CODEC_Mute(u32 Command)
{
u32 tmp = 0;
/* Read the current value of the config register number 0x0E */
tmp = CODEC_ReadRegister(0x0E);
/* Set the Mute mode */
if (Command == MUTE_ON)
{
tmp |= 0x20;
}
else /* MUTE_OFF Disable the Mute */
{
tmp &= 0xD1;
}
/* Write back the CODEC config register w/the new value */
CODEC_WriteRegister(0x0E, tmp);
}
/*******************************************************************************
* Function Name : I2S_CODEC_ForwardPlay
* Description : Forward function.
* Input : - Step: number of steps forward
* Output : None.
* Return : None.
*******************************************************************************/
void I2S_CODEC_ForwardPlay(u32 Step)
{
/* Pause Playing the audio file */
I2S_CODEC_Pause();
/* Increment the Audio pointer */
IncrementVar_AudioDataIndex((AudioDataLength / 100) * Step);
/* Insure the index parity */
AudioDataIndex &= 0xFFFFFFFE;
/* Resume playing from the new position */
I2S_CODEC_Play((GetVar_AudioDataIndex()));
}
/*******************************************************************************
* Function Name : I2S_CODEC_RewindPlay
* Description : Rewind function.
* Input : - Step: number of steps back
* Output : None.
* Return : None.
*******************************************************************************/
void I2S_CODEC_RewindPlay(u32 Step)
{
/* Pause Playing the audio file */
I2S_CODEC_Pause();
/* Increment the Audio pointer */
DecrementVar_AudioDataIndex((AudioDataLength / 100) * Step);
/* Insure the index parity */
AudioDataIndex &= 0xFFFFFFFE;
/* Resume playing from the new position */
I2S_CODEC_Play((GetVar_AudioDataIndex()));
}
/*******************************************************************************
* Function Name : I2S_CODEC_PowerDown
* Description : Power down the Audio Codec.
* Input : - CodecPowerDown_Mode: could be CodecPowerDown_SW for power down
* : after communication, CodecPowerDown_HW simply shut down the codec
* Output : None
* Return : None
*******************************************************************************/
void I2S_CODEC_PowerDown(u32 CodecPowerDown_Mode)
{
if (CodecPowerDown_Mode == CodecPowerDown_SW)
{
/* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/
(void)CODEC_WriteRegister(0x00, 0x40);
/* Power down the VCOM*/
(void)CODEC_WriteRegister(0x00, 0x00);
}
else /* CodecPowerDown_HW */
{
/* Power Down the Codec */
GPIO_ResetBits(Codec_PDN_GPIO, Codec_PDN_Pin);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -