📄 audio_class.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2007
*
* File name : audio_class.c
* Description : Audio Interface Class module
*
* History :
* 1. Date : February 3, 2007
* Author : Stanimir Bonev
* Description : Create
*
* $Revision: 18137 $
**************************************************************************/
#include "audio_class.h"
volatile Boolean SempEna;
volatile Int32U SempCount,Delta;
Int32U SempPeriod;
volatile pInt16S pSpkData;
volatile Int32U SempPerCurrHold,DeltaPer;
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 segment="USB_DMA_RAM"
#pragma location="USB_DMA_RAM"
#pragma data_alignment=4
__no_init Int16S AudioSpkData[SempRerFrame * 3];
#pragma location="USB_DMA_RAM"
#pragma data_alignment=4
__no_init DmaIsoPacket_t DmaSpkIsoPacket;
#pragma data_alignment=4
Int8U AudioBuf[2];
Int8U AudioRequest,AudioCS,AudioCN,AudioId;
Int16U AudioDataSize;
Int16S AudioFeat1Vol;
Int32U AudioSpkVolMul;
Boolean AudioFeat1Mute;
/*************************************************************************
* Function Name: AudioClassInit
* Parameters: none
*
* Return: none
*
* Description: USB Class Audio Init
*
*************************************************************************/
void AudioClassInit (void)
{
// Init Audio Class variables
SempEna =\
AudioFeat1Mute = FALSE;
SempCount =\
AudioFeat1Vol = 0;
pSpkData = AudioSpkData;
SempPerCurrHold = SempPeriod;
// Registered The Class Request
USB_UserFuncRegistering(UsbClassAudioRequest,UsbUserClass);
// Registered User Ep0 Data receive
USB_UserFuncRegistering(UsbClassAudioData,UsbClassEp0OutPacket);
// Init I2S and HT82V731 I2S DAC
// Set I2S CLK Fcckl/1
PCLKSEL1_bit.PCLK_I2S = 1;
// enable I2S in the PCONP register. I2S is disabled on reset*/
PCONP |= (1 << 27);
// connect the I2S sigals to port pins
// P0.7 - TX_CLK, P0.8 - TX_WS, P0.9 - TX_SDA
PINSEL0_bit.P0_7 = 1;
PINSEL0_bit.P0_8 = 1;
PINSEL0_bit.P0_9 = 1;
// For all the test program assuming USB is used, the CCLK is set to
// 48Mhz while all the PCLK are the same, 1/2 of CCLK = 16Mhz. It also
// applys to I2S. To generate 48khz sample rate for 16-bit stereo data
// requires a bit rate of 48,000 x 16 x 2 = 1.536Mhz, the TX and RX clock rate
// register should be Pclk / 1536000 = 18.75=0x13
// Please note, in order to generate accurate TX/RX clock rate for I2S,
// PCLK and CCLK needs to be carefully reconsidered.
// But I prefere oversampling.
I2STXRATE = 2;
/* Audio output is the master, audio input is the slave, */
I2SDAO_bit.RESET = 1; // reset FIFIO
I2SDAO_bit.WORS_WIDTH = 1; // 16 bits
I2SDAO_bit.MONO = 0; // Stereo
I2SDAO_bit.WS_SEL = 0; // Master mode
I2SDAO_bit.WS_SEL = 0; // Master mode
I2SDAO_bit.WS_HALFPERIOD = 16;
I2SDAO_bit.RESET = 0; // release reset
I2SDAO_bit.MUTE = 0; // release mute
I2SDAO_bit.STOP = 0; // start I2S
// Init System Timer - Timer0
// Init Time0
PCONP_bit.PCTIM0 = 1; // Enable TMR0 clk
T0TCR_bit.CE = 0; // counting disable
T0TCR_bit.CR = 1; // set reset
T0TCR_bit.CR = 0; // release reset
T0CTCR_bit.CTM = 0; // Timer Mode: every rising PCLK edge
T0MCR_bit.MR0I = 1; // Enable Interrupt on MR0
T0MCR_bit.MR0R = 1; // Enable reset on MR0
T0MCR_bit.MR0S = 0; // Disable stop on MR0
// set timer 0 period
T0PR = 1-1;
SempPeriod = (SYS_GetFpclk(TIMER0_PCLK_OFFSET))/SampFreq;
DeltaPer = SempPeriod/(SempRerFrame*2);
T0MR0 = SempPeriod;
// init timer 0 interrupt
T0IR_bit.MR0INT = 1; // clear pending interrupt
// Timer 0 interrupt is assign to the FIQ interrupt line
VICINTSELECT = 1<<VIC_TIMER0;
VICINTENABLE |= 1UL << VIC_TIMER0;
T0TCR_bit.CE = 1; // counting Enable
}
/*************************************************************************
* Function Name: UsbClassAudioConfigure
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB Class Audio configure
*
*************************************************************************/
void * UsbClassAudioConfigure (void * pArg)
{
UsbDevCtrl_t * pUsbDevCtrl = (UsbDevCtrl_t *)pArg;
if(pUsbDevCtrl == NULL)
{
if(UsbCoreReq(UsbCoreReqConfiquration) != 0)
{
// disable all class EPs
USB_RealizeEp((USB_Endpoint_t)SpkEp,FALSE,0,FALSE);
USB_UserFuncRegistering(NULL,SpkEp);
}
}
else
{
if((pUsbDevCtrl->Configuration == 1))
{
if(pUsbDevCtrl->Interface == 1)
{
if(pUsbDevCtrl->AlternateSetting == 0)
{
USB_RealizeEp((USB_Endpoint_t)SpkEp,FALSE,0,FALSE);
USB_UserFuncRegistering(NULL,SpkEp);
}
else if (pUsbDevCtrl->AlternateSetting == 1)
{
// Realize Class EPs
USB_UserFuncRegistering(AudioInHadler,SpkEp);
USB_RealizeEp((USB_Endpoint_t)SpkEp,FALSE,SpkEpMaxSize,FALSE);
USB_DmaInitTransfer((USB_Endpoint_t)SpkEp,
SpkDDInd,
(pInt32U)AudioSpkData,
0,
1,
&DmaSpkIsoPacket,
TRUE);
}
}
}
}
return(NULL);
}
/*************************************************************************
* Function Name: AudioInHadler
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB Class Audio Out EP handler
*
*************************************************************************/
void * AudioInHadler (void *Arg)
{
Int32U save;
pUSB_DmaDesc_t pSpkDD = USB_DmaGetDesc(SpkDDInd);
Int32U ReceievedBytes = DmaSpkIsoPacket.PacketLength;
if(ReceievedBytes)
{
pSpkData += ReceievedBytes/sizeof(Int16U);
if(pSpkData >= AudioSpkData + sizeof(AudioSpkData)/sizeof(Int16S))
{
pSpkData = AudioSpkData;
}
if(SempEna)
{
// Adapt sample rate
if (Delta > (SempRerFrame * SubFrameSize))
{
SempPerCurrHold = SempPeriod - DeltaPer;
}
else if (Delta < (SempRerFrame * SubFrameSize))
{
SempPerCurrHold = SempPeriod + DeltaPer;
}
else
{
SempPerCurrHold = SempPeriod;
}
}
else
{
if(pSpkData >= (AudioSpkData + (2*sizeof(AudioSpkData))/(3*sizeof(Int16S))))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -