📄 dac_codec.c
字号:
/*----------------------------------------------------------------------------
* Name: DAC_CODEC.c
* Purpose: Speaker driver using DAC
* Version: V1.00
*----------------------------------------------------------------------------
* This file is part of the uVision/ARM development tools.
* This software may only be used under the terms of a valid, current,
* end user licence from KEIL for a compatible version of KEIL software
* development tools. Nothing else gives you the right to use this software.
*
* Copyright (c) 2005-2008 Keil Software. All rights reserved.
*---------------------------------------------------------------------------*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "spi_flash.h"
#include "DAC_CODEC.h"
/* Private typedef -----------------------------------------------------------*/
typedef enum
{
LittleEndian,
BigEndian
}Endianness;
/* Private define ------------------------------------------------------------*/
/* Audio file header size */
#define HEADER_SIZE 100
/* Uncomment this line to enable verifying data sent to codec after each write opeation */
//#define VERIFY_WRITTENDATA
/* 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_11025 16000
#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 dacaudiofreq = SampleRate_8000;
/* 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 vu16 TIM2ARRValue = 0x00;
static vu32 AudioReplay = 0xFFFF;
static u32 AudioReplayCount = 0xFFFF;
static vu32 SendDummyData = 0;
static vu32 AudioPlayStatus = AudioPlayStatus_STOPPED;
static u8 CurrentVolume = DEFAULT_VOL;
static u32 errorcode = 0xFF;
static vu32 monovar = 0, tmpvar = 0;
u8 AudioDataBuffer[32];
/* 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 DAC_GPIO_Config(void);
static void DAC_Config(u16 AudioFreq);
static u32 ReadUnit(u8 NbrOfBytes, Endianness BytesFormat);
u32 AudioFile_Init(void);
/*******************************************************************************
* Function Name : DAC_CODEC_Init
* Description : Initializes the DAC audio codec.
* Input : - 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 DAC_CODEC_Init(u32 Address)
{
u32 count = 0;
/* Set the audio file address */
AudioFileAddress = (vu32) Address;
/* Configure I2S interrupt Channel */
NVIC_Config();
/* Configure the DAC pin (PA4) */
DAC_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 PB.09 */
GPIO_SetBits(GPIOB, GPIO_Pin_9);
return errorcode;
}
/* Configure the DAC peripheral */
DAC_Config(dacaudiofreq);
if (count != 0)
{
/* Turn on LD1 connected to PB.08 */
GPIO_SetBits(GPIOB, GPIO_Pin_8);
return 3;
}
/* Turn on LD4 connected to PB.11 */
GPIO_SetBits(GPIOB, GPIO_Pin_11);
return 0; /* Configuration is OK */
}
/*******************************************************************************
* Function Name : DAC_CODEC_ReplayConfig
* Description : Set AudioReplay variable value .
* Input : Repetions: Number of repetitions
* Output : None
* Return : None
*******************************************************************************/
void DAC_CODEC_ReplayConfig(u32 Repetions)
{
/* Audio Replay number set by user */
AudioReplay = Repetions;
/* Audio Replays number remaining (if AudioReplay != 0) */
AudioReplayCount = Repetions;
}
/*******************************************************************************
* Function Name : DAC_CODEC_Play
* Description : Plays the audio file.
* Input : - AudioStartPosition: Adress from which the wave data begin
* Output : None
* Return : AudioDataIndex value.
*******************************************************************************/
u32 DAC_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);
/* Set autoreload value */
TIM_SetAutoreload(TIM2, TIM2ARRValue);
/* Start TIM2 */
TIM_Cmd(TIM2, ENABLE);
/* Enable TIM2 interrupt used for sound wave amplitude update */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
return AudioDataIndex;
}
/*******************************************************************************
* Function Name : DAC_CODEC_Pause
* Description : Pause playing the audio file.
* Input : None
* Output : None
* Return : Current Position.
*******************************************************************************/
u32 DAC_CODEC_Pause()
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
/* Disable TIM2 update interrupt */
TIM_ITConfig(TIM2, TIM_IT_Update, 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 : DAC_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 DAC_CODEC_Stop()
{
/* Disable TIM2 update interrupt */
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
/* Disable TIM2 */
TIM_Cmd(TIM2, DISABLE);
/* Reinitialize the audio data pointer */
AudioDataIndex = 0;
/* 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 : DAC_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 DAC_CODEC_ControlVolume(u32 direction, u8 Volume)
{
if (direction == VolumeDirection_HIGH)
{
/* Check if the volume high limit is reached */
if (CurrentVolume < VOLStep)
{
CurrentVolume = 0;
}
else
{
/* Save the current volume level */
CurrentVolume -= Volume;
}
}
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 += Volume;
}
}
else if (direction == VolumeDirection_LEVEL)
{
CurrentVolume = Volume;
}
else
{
return 0xFF; //Error verifying the Codec registers
}
return 0;
}
/*******************************************************************************
* Function Name : DAC_CODEC_ForwardPlay
* Description : Forward function.
* Input : - Step: number of steps forward
* Output : None.
* Return : None.
*******************************************************************************/
void DAC_CODEC_ForwardPlay(u32 Step)
{
/* Pause Playing the audio file */
DAC_CODEC_Pause();
/* Increment the Audio pointer */
IncrementVar_AudioDataIndex((AudioDataLength / 100) * Step);
/* Insure the index parity */
AudioDataIndex &= 0xFFFFFFFE;
/* Resume playing from the new position */
DAC_CODEC_Play((GetVar_AudioDataIndex()));
}
/*******************************************************************************
* Function Name : DAC_CODEC_RewindPlay
* Description : Rewind function.
* Input : - Step: number of steps back
* Output : None.
* Return : None.
*******************************************************************************/
void DAC_CODEC_RewindPlay(u32 Step)
{
/* Pause Playing the audio file */
DAC_CODEC_Pause();
/* Increment the Audio pointer */
DecrementVar_AudioDataIndex((AudioDataLength / 100) * Step);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -