📄 audio_class.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2007
*
* File name : audio_class.c
* Description : AUDIO CLASS module
*
* History :
* 1. Date : 18, October 2007
* Author : Stanimir Bonev
* Description : Create
*
* $Revision: 1.4 $
**************************************************************************/
#include "audio_class.h"
volatile Boolean SempEna,MicEna;
Int32U SempPeriod,DeltaPer,MicCurrBuffer;
volatile pInt16S pSpkData,pMicData;
volatile Int32U SempPerCurrHold,Delta,MicSempCount,SempCount;
static union _Val
{
Int32S Data;
struct
{
Int16U DataLo;
Int16S DataHi;
};
} Val = {0x02000000};
const Int32U VolumeMul [] =
{
// 256 - 0
//-48dB- 0x0
261,
//-47dB- 0x1
293,
//-46dB- 0x2
328,
//-45dB- 0x3
369,
//-44dB- 0x4
414,
//-43dB- 0x5
464,
//-42dB- 0x6
521,
//-41dB- 0x7
584,
//-40dB- 0x8
655,
//-39dB- 0x9
735,
//-38dB- 0xA
825,
//-37dB- 0xB
926,
//-36dB- 0xC
1039,
//-35dB- 0xD
1165,
//-34dB- 0xE
1308,
//-33dB- 0xF
1467,
//-32dB- 0x10
1646,
//-31dB- 0x11
1847,
//-30dB- 0x12
2072,
//-29dB- 0x13
2325,
//-28dB- 0x14
2609,
//-27dB- 0x15
2927,
//-26dB- 0x16
3285,
//-25dB- 0x17
3685,
//-24dB- 0x18
4135,
//-23dB- 0x19
4640,
//-22dB- 0x1A
5206,
//-21dB- 0x1B
5841,
//-20dB- 0x1C
6554,
//-19dB- 0x1D
7353,
//-18dB- 0x1E
8250,
//-17dB- 0x1F
9257,
//-16dB- 0x20
10387,
//-15dB- 0x21
11654,
//-14dB- 0x22
13076,
//-13dB- 0x23
14672,
//-12dB- 0x24
16462,
//-11dB- 0x25
18471,
//-10dB- 0x26
20724,
//-9dB - 0x27
23253,
//-8dB - 0x28
26090,
//-7dB - 0x29
29274,
//-6dB - 0x2A
32846,
//-5dB - 0x2B
36854,
//-4dB - 0x2C
41350,
//-3dB - 0x2D
46396,
//-2dB - 0x2E
52057,
//-1dB - 0x2F
58409,
// 0dB - 0x30
65536,
// 1dB - 0x31
73533,
// 2dB - 0x32
82505,
// 3dB - 0x33
92572,
// 4dB - 0x34
103868,
// 5dB - 0x35
116541,
// 6dB - 0x36
130762,
};
#pragma data_alignment=4
__no_init Int16S AudioSpkData[SampRerFrame * 3];
#pragma data_alignment=4
__no_init Int16S AudioMicData1[SampRerFrame * 2];
#pragma data_alignment=4
__no_init Int16S AudioMicData2[SampRerFrame * 2];
#pragma data_alignment=4
Int8U AudioBuf[2];
Int8U AudioRequest,AudioCS,AudioCN,AudioId;
Int16U AudioDataSize;
Int16S AudioFeat1Vol;
Int32U AudioSpkVolMul;
Boolean AudioFeat1Mute;
Int16S AudioFeat2Vol;
Int32U AudioMicVolMul;
Boolean AudioFeat2Mute;
/*************************************************************************
* Function Name: UsbAudioClassInit
* Parameters: none
*
* Return: none
*
* Description: USB Class Audio Init
*
*************************************************************************/
void UsbAudioClassInit (void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_ClocksTypeDef RCC_Clocks;
NVIC_InitTypeDef NVIC_InitStructure;
TIM1_TimeBaseInitTypeDef TIM1_TimeBaseInitStruct;
TIM1_OCInitTypeDef TIM1_OCInitStructure;
// Init Audio Class variables
SempEna =\
AudioFeat1Mute =\
AudioFeat2Mute = FALSE;
SempCount =\
AudioFeat1Vol =\
AudioFeat2Vol = 0;
pSpkData = AudioSpkData;
SempPerCurrHold = SempPeriod;
// Get different on chips' clocks.
RCC_GetClocksFreq(&RCC_Clocks);
// PWM DAC (TIM2) 10 bit PA8
// Enable GPIO clock and release reset
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,
ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA,
DISABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// Init PWM TIM1
// Enable Timer1 clock and release reset
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1,DISABLE);
// Time base configuration
TIM1_TimeBaseInitStruct.TIM1_Prescaler = 0; // Max frequency
TIM1_TimeBaseInitStruct.TIM1_CounterMode = TIM1_CounterMode_Up;
TIM1_TimeBaseInitStruct.TIM1_Period = 0x3FF; // 10 bit resolution
TIM1_TimeBaseInitStruct.TIM1_ClockDivision = 0;
TIM1_TimeBaseInitStruct.TIM1_RepetitionCounter = 0;
TIM1_TimeBaseInit(&TIM1_TimeBaseInitStruct);
// Channel 1 Configuration in PWM mode
TIM1_OCInitStructure.TIM1_OCMode = TIM1_OCMode_PWM1;
TIM1_OCInitStructure.TIM1_OutputState = TIM1_OutputState_Enable;
TIM1_OCInitStructure.TIM1_OutputNState = TIM1_OutputNState_Enable;
TIM1_OCInitStructure.TIM1_Pulse = 0x200;
TIM1_OCInitStructure.TIM1_OCPolarity = TIM1_OCPolarity_Low;
TIM1_OCInitStructure.TIM1_OCNPolarity = TIM1_OCNPolarity_High;
TIM1_OCInitStructure.TIM1_OCIdleState = TIM1_OCIdleState_Set;
TIM1_OCInitStructure.TIM1_OCNIdleState = TIM1_OCIdleState_Reset;
TIM1_OC1Init(&TIM1_OCInitStructure);
// Double buffered
TIM1_ARRPreloadConfig(ENABLE);
// TIM1 counter enable
TIM1_Cmd(ENABLE);
// TIM1 Main Output Enable
TIM1_CtrlPWMOutputs(ENABLE);
// ADC init PA1
// Enable ADC clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// ADC Deinit
ADC_DeInit(ADC1);
// Assign PA1 to ADC ch 1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = (GPIOSpeed_TypeDef)0;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// ADC Structure Initialization
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// Enable the ADC
ADC_Cmd(ADC1, ENABLE);
// ADC calibration
// Enable ADC1 reset calibration register
ADC_ResetCalibration(ADC1);
// Check the end of ADC1 reset calibration register
while(ADC_GetResetCalibrationStatus(ADC1) == SET);
// Start ADC1 calibration
ADC_StartCalibration(ADC1);
// Check the end of ADC1 calibration
while(ADC_GetCalibrationStatus(ADC1) == SET);
// Configure channel
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_13Cycles5);
// Init Sample Timer - Timer2
// TIM2 clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// Reset TIM2
TIM_DeInit(TIM2);
// Time base configuration
SempPeriod = RCC_Clocks.PCLK2_Frequency/SampFreq;
DeltaPer = (SempPeriod/(SampRerFrame*2)) + 1;
TIM_TimeBaseStructure.TIM_Period = SempPeriod;
TIM_TimeBaseStructure.TIM_Prescaler = 0; // max resolution
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// Disable double buffer of the APR register
TIM_ARRPreloadConfig(TIM2, ENABLE);
// Clear update interrupt bit
TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
// Enable update interrupt
TIM_ITConfig(TIM2,TIM_FLAG_Update,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = USB_INTR_AUDIO_SAMP_TIMER_PRIORITY; // max priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// TIM2 enable counter
TIM_Cmd(TIM2, ENABLE);
UsbClassAudioConfigure(NULL);
UsbCoreInit();
}
/*************************************************************************
* Function Name: UsbClassAudioConfigure
* Parameters: pUsbDevCtrl_t pDev
*
* Return: none
*
* Description: USB Class Audio configure
*
*************************************************************************/
void UsbClassAudioConfigure (pUsbDevCtrl_t pDev)
{
if(pDev == NULL)
{
if(UsbCoreReq(UsbCoreReqConfiquration) != 0)
{
SempEna = MicEna = FALSE;
}
}
else
{
if((pDev->Configuration == 1))
{
if (pDev->AlternateSetting[USB_SPK_INTERFACE] == 1)
{
pSpkData = AudioSpkData;
Delta = 0;
USB_IO_Data(SpkEp,(pInt8U)pSpkData,SpkEpMaxSize,(void*)AudioInHadler);
}
if (pDev->AlternateSetting[USB_MIC_INTERFACE] == 1)
{
MicEna = FALSE;
pMicData = AudioMicData1;
MicCurrBuffer = 0;
// Send microphone output buffer
USB_IO_Data( MicEp,
NULL,
0,
NULL);
USB_IO_Data( MicEp,
NULL,
0,
NULL);
USB_IO_Data( MicEp,
NULL,
0,
(void*)AudioOutHadler);
}
else
{
MicEna = FALSE;
}
}
}
}
/*************************************************************************
* Function Name: AudioInHadler
* Parameters: USB_Endpoint_t EP
*
* Return: none
*
* Description: USB Class Audio Out EP handler
*
*************************************************************************/
static
void AudioInHadler (USB_Endpoint_t EP)
{
assert(SpkEp == EP);
if (EpCnfg[EP].Status == COMPLETE)
{
pSpkData += EpCnfg[EP].Size/sizeof(Int16U);
if(pSpkData >= AudioSpkData + sizeof(AudioSpkData)/sizeof(Int16U))
{
pSpkData = AudioSpkData;
}
if(SempEna)
{
// Adapt sample rate
if (Delta > (SampRerFrame * SubFrameSize))
{
SempPerCurrHold = SempPeriod - DeltaPer;
}
else if (Delta < (SampRerFrame * SubFrameSize))
{
SempPerCurrHold = SempPeriod + DeltaPer;
}
else
{
SempPerCurrHold = SempPeriod;
}
}
else
{
if(pSpkData >= (AudioSpkData + (2*sizeof(AudioSpkData))/(3*sizeof(Int16U))))
{
// Enable output
SempCount = 0;
SempEna = TRUE;
}
}
ENTR_CRT_SECTION();
Delta += EpCnfg[EP].Size;
EXT_CRT_SECTION();
}
else
{
// reset all
pSpkData = AudioSpkData;
SempCount = 0;
SempEna = FALSE;
SempPerCurrHold = SempPeriod;
Delta = 0;
}
USB_IO_Data(SpkEp,(pInt8U)pSpkData,SpkEpMaxSize,(void*)AudioInHadler);
}
/*************************************************************************
* Function Name: AudioOutHadler
* Parameters: USB_Endpoint_t EP
*
* Return: none
*
* Description: USB Class Audio In EP handler
*
*************************************************************************/
static
void AudioOutHadler (USB_Endpoint_t EP)
{
Int32U PacketLength;
ENTR_CRT_SECTION();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -