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

📄 i2s_codec.c

📁 stm32.rar
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************** (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 + -