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

📄 audiodrv.c

📁 2440 开发板的测试程序。包括uart,iic,lcd
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "def.h"
#include "2440addr.h"
#include "2440lib.h"
#include "AudioDrv.h"
#include "dma.h"

#define	AUDIO_PLAY_DEV	0x100
#define	AUDIO_REC_DEV	0x101

#define	DEVICE_REC	2
#define	DEVICE_PLAY	1
#define	DEVICE_FREE	0	
#define	PLAY	0
#define	RECORD	1

#define	PLAY_DMA_ATTR	((AUDIO_PLAY_DEV<<16)|SRC_LOC_AHB|SRC_ADDR_INC|DST_LOC_APB|DST_ADDR_FIXED|REQ_IISDO)
#define	PLAY_DMA_MODE	(HANDSHAKE_MODE|SYNC_APB|DONE_GEN_INT|TSZ_UNIT|SINGLE_SVC|HW_TRIG|RELOAD_OFF|DSZ_16b)
#define	REC_DMA_ATTR	((AUDIO_REC_DEV<<16)|SRC_LOC_APB|SRC_ADDR_FIXED|DST_LOC_AHB|DST_ADDR_INC|REQ_IISDI)
#define	REC_DMA_MODE	(HANDSHAKE_MODE|SYNC_APB|DONE_GEN_INT|TSZ_UNIT|SINGLE_SVC|HW_TRIG|RELOAD_OFF|DSZ_16b)

static void IIS_PortSetting( void );
static void _WrL3Addr( U8 data );
static void _WrL3Data( U8 data , int halt );
static void Init1341( char mode );
static void AdjVolume( U16 volume );
static void PlayPause( U8 mode );
//static void Muting(void);
static void StartPlay( void );
static void __irq PlayDMA2Done( void );

static LPWAVEHDR lpPlayFstBlk, lpRecFstBlk;
static LPWAVEHDR lpPlayLstBlk, lpRecLstBlk;
static LPWAVEHDR lpPlayCurBlk, lpRecCurBlk;
static U32 PlayTotBlks, RecTotBlks;

static U32 save_MPLLCON;

static struct
{
	U16 Freq;
	U32 MPLL;
	U16 PreScaler;
	U8 ofs;
}CodecPara[7] =
{
	{8000,( 123 << 12 ) | ( 6 << 4 ) | 0,( 23 << 5 ) | 23,0}, {11025,( 229 << 12 ) | ( 5 << 4 ) | 1,( 11 << 5 ) | 11,1},
				{16000,( 123 << 12 ) | ( 6 << 4 ) | 0,( 11 << 5 ) | 11,0},
				{22050,( 229 << 12 ) | ( 5 << 4 ) | 1,( 5 << 5 ) | 5,1},
	//{22050,(0x96<<12)|(5<<4)|1,(5<<5)|5,0},
	{32000,( 123 << 12 ) | ( 6 << 4 ) | 0,( 5 << 5 ) | 5,0}, {44100,( 229 << 12 ) | ( 5 << 4 ) | 1,( 2 << 5 ) | 2,1},
				{48000,( 123 << 12 ) | ( 6 << 4 ) | 0,( 3 << 5 ) | 3,0}
};

static struct
{
	HWAVEOUT handle;		
	U16 wFormatTag;
	U16 nChannels;	
	U16 wBitsPerSample;
	CallBackProc CallBack;
	U32 CallBackInst;	
	U8 FsIdx;
	U32 DevReq;	
	U8 Status;
}PlayStatus, RecStatus; 						   	

static U16 PlayVolume = 0xffff;
//static U8 inner_buf[32*1024];

void DbgChgUartDiv( void )
{
	Uart_Init( 0 , 115200 );
}

static void SetSysFclk( U32 MPLL )
{
	U32 mdiv, pdiv, sdiv, val;
	U32 mclk;

	mdiv = ( MPLL >> 12 ) & 0xff;
	pdiv = ( MPLL >> 4 ) & 0xff;
	sdiv = MPLL & 0xf;

	val = 1;
	while ( sdiv-- )
	{
		val *= 2;
	}

	mclk = ( ( mdiv + 8 ) * 12000000 ) / ( ( pdiv + 2 ) * val ) ;			
	Uart_Init( mclk >> 2 , 115200 ) ;
}

/************************* Play Function ***********************/
MMRESULT waveOutOpen( LPHWAVEOUT phwo , UINT uDeviceID , LPWAVEFORMATEX pwfx , DWORD dwCallback ,
	DWORD dwCallbackInstance , DWORD fdwOpen )
{
	U8 i;
	U8 err = 0;	

	if ( pwfx->wFormatTag != WAVE_FORMAT_PCM )	//only support PCM
		err = 1;
	if ( pwfx->nChannels != 2 )					//must be stero
		err = 1;
	if ( pwfx->wBitsPerSample % 8 )				//8 or 16 bits
		err = 1;
	for ( i = 0; i < 7; i++ )
		if ( pwfx->nSamplesPerSec == CodecPara[i].Freq )
			break;
	if ( i == 7 )
		err = 1;		
	if ( ( pwfx->nChannels * pwfx->wBitsPerSample ) / 8 != pwfx->nBlockAlign )
		err = 1;
	if ( pwfx->nAvgBytesPerSec != pwfx->nSamplesPerSec * pwfx->nBlockAlign )
		err = 1;		
	if ( err )
		return WAVERR_BADFORMAT;	//check format parameters

	if ( PlayStatus.Status != DEVICE_FREE )
		return MMSYSERR_BADDEVICEID;
	PlayStatus.DevReq = RequestDMA( PLAY_DMA_ATTR , PLAY_DMA_MODE );				
	if ( PlayStatus.DevReq == REQUEST_DMA_FAIL )
		return MMSYSERR_BADDEVICEID;						

	PlayStatus.handle = *phwo; 
	PlayStatus.wFormatTag = pwfx->wFormatTag;
	PlayStatus.nChannels = pwfx->nChannels;	
	PlayStatus.wBitsPerSample = pwfx->wBitsPerSample;
	PlayStatus.FsIdx = i;
	PlayStatus.CallBack = ( CallBackProc ) dwCallback;
	PlayStatus.CallBackInst = dwCallbackInstance;
	PlayStatus.Status = DEVICE_PLAY;

	save_MPLLCON = rMPLLCON;		//save MPLLCON value
	//rMPLLCON = CodecPara[PlayStatus.FsIdx].MPLL;
	SetSysFclk( CodecPara[PlayStatus.FsIdx].MPLL );
	rCLKCON |= 0x20000;				//enable IIS clock	

	DbgChgUartDiv();		

	//	ChangeClockDivider(1,1);		//1:2:4
	//	ChangeMPllValue(0x96,0x5,0x1);  //FCLK=135.428571MHz (PCLK=33.857142MHz)		
	//		Uart_Init(33857142,115200); 

	IIS_PortSetting();		
	pISR_DMA2 = ( U32 ) PlayDMA2Done;
	EnableIrq( BIT_DMA2 );
	PlayTotBlks = 0;
	Init1341( PLAY );
	waveOutSetVolume( PlayStatus.handle , PlayVolume );

	return MMSYSERR_NOERROR;
}

MMRESULT waveOutClose( HWAVEOUT hwo )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;		

	rIISCON = 0x0;				//IIS Interface stop	
	rIISFCON = 0x0; 			//For FIFO flush
	rCLKCON &= ~0x20000;		//disable IIS colock
	//rMPLLCON	 = save_MPLLCON;	//restore MPLLCON value
	SetSysFclk( save_MPLLCON );
	PlayStatus.Status = DEVICE_FREE;	
	ReleaseDMA( PlayStatus.DevReq );		
	DisableIrq( BIT_DMA2 );

	return MMSYSERR_NOERROR;
}

MMRESULT waveOutPrepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	pwh->lpNext = 0;
	pwh->dwBytesRecorded = 0;
	pwh->dwUser = 0;
	pwh->dwFlags = 0;	
	return MMSYSERR_NOERROR;
}

MMRESULT waveOutUnprepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	return MMSYSERR_NOERROR;
}

MMRESULT waveOutWrite( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	if ( !PlayTotBlks )
	{
		lpPlayFstBlk = pwh;
		lpPlayCurBlk = lpPlayFstBlk;
		StartPlay();
	}
	else
	{
		lpPlayLstBlk -> lpNext = pwh ;
	}

	lpPlayLstBlk = pwh;
	pwh->lpNext = 0;
	PlayTotBlks++;		

	return MMSYSERR_NOERROR;
}

MMRESULT waveOutSetVolume( HWAVEOUT hwo , DWORD dwVolume )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	PlayVolume = dwVolume & 0xffff;
	AdjVolume( PlayVolume );			

	return MMSYSERR_NOERROR;
}	

MMRESULT waveOutGetVolume( HWAVEOUT hwo , LPDWORD pdwVolume )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	*pdwVolume = PlayVolume; 
	return MMSYSERR_NOERROR;
}

MMRESULT waveOutPause( HWAVEOUT hwo )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	PlayPause( 1 );
	return MMSYSERR_NOERROR;
}

MMRESULT waveOutRestart( HWAVEOUT hwo )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	PlayPause( 0 );
	return MMSYSERR_NOERROR;
}

MMRESULT waveOutReset( HWAVEOUT hwo )
{
	if ( ( PlayStatus.handle != hwo ) || ( PlayStatus.Status != DEVICE_PLAY ) )
		return MMSYSERR_INVALHANDLE;

	return MMSYSERR_NOERROR;
}

//==========================================================
static __inline void SetPlayDma( void )
{
	//	WrUTXH0('@');
	SetDMARun( PlayStatus.DevReq | DMA_START , ( U32 ) lpPlayCurBlk->lpData , ( U32 ) IISFIFO ,
		lpPlayCurBlk->dwBufferLength / 2 );
}

static void StartPlay( void )
{
	SetPlayDma();	   			

	rIISPSR = CodecPara[PlayStatus.FsIdx].PreScaler;
	rIISCON = ( 1 << 5 ) + ( 0 << 4 ) + ( 0 << 3 ) + ( 1 << 2 ) + ( 1 << 1 );	//Tx DMA enable[5], Rx idle[2], Prescaler enable[1]	
	rIISMOD = ( 0 << 8 ) +
		( 2 << 6 ) +
		( 0 << 5 ) +
		( 1 << 4 ) +
		( ( PlayStatus.wBitsPerSample >> 4 ) << 3 ) +
		( CodecPara[PlayStatus.FsIdx].ofs << 2 ) +
		( 1 << 0 );	
	rIISFCON = ( 1 << 15 ) + ( 1 << 13 );    
	rIISCON |= 0x1;
}

static void __irq PlayDMA2Done( void )
{
	ClearPending( BIT_DMA2 );     //Clear pending bit

	lpPlayCurBlk->dwLoops--;			
	if ( lpPlayCurBlk->lpNext )
	{
		lpPlayCurBlk = lpPlayCurBlk->lpNext;
	}
	else
	{
		lpPlayCurBlk = lpPlayFstBlk;
	}    
	SetPlayDma();
}

/************************* Record Function *********************/
static __inline void SetRecDma( void )
{
	//	WrUTXH0('.');		
	SetDMARun( RecStatus.DevReq | DMA_START , ( U32 ) IISFIFO , ( U32 ) lpRecCurBlk->lpData ,
		lpRecCurBlk->dwBufferLength / 2 );
}

static void __irq RecDMADone( void )
{
	if ( ( RecStatus.DevReq & 0xff ) == 0x12 )
		ClearPending( BIT_DMA1 );     //Clear pending bit
	if ( ( RecStatus.DevReq & 0xff ) == 0x21 )
		ClearPending( BIT_DMA2 );		

	lpRecCurBlk->dwBytesRecorded = lpRecCurBlk->dwBufferLength;

	if ( lpRecCurBlk->lpNext )
	{
		lpRecCurBlk = lpRecCurBlk->lpNext;
	}
	else
	{
		lpRecCurBlk = lpRecFstBlk;
	}
	SetRecDma();
}

MMRESULT waveInOpen( LPHWAVEIN phwi , UINT uDeviceID , LPWAVEFORMATEX pwfx , DWORD dwCallback ,
	DWORD dwCallbackInstance , DWORD fdwOpen )
{
	U8 i;
	U8 err = 0;	

	if ( pwfx->wFormatTag != WAVE_FORMAT_PCM )	//only support PCM
		err = 1;
	if ( pwfx->nChannels != 2 )					//must be stero
		err = 2;
	if ( pwfx->wBitsPerSample % 8 )				//8 or 16 bits
		err = 3;
	for ( i = 0; i < 7; i++ )
		if ( pwfx->nSamplesPerSec == CodecPara[i].Freq )
			break;
	if ( i == 7 )
		err = 4;		
	if ( ( pwfx->nChannels * pwfx->wBitsPerSample ) / 8 != pwfx->nBlockAlign )
		err = 5;
	if ( pwfx->nAvgBytesPerSec != pwfx->nSamplesPerSec * pwfx->nBlockAlign )
		err = 6;		
	if ( err )
	{
		//printf("check err = %d\n", err);											
		return WAVERR_BADFORMAT;	//check format parameters
	}

	if ( RecStatus.Status != DEVICE_FREE )
		return MMSYSERR_BADDEVICEID;
	RecStatus.DevReq = RequestDMA( REC_DMA_ATTR , REC_DMA_MODE );			
	if ( RecStatus.DevReq == REQUEST_DMA_FAIL )
		return MMSYSERR_BADDEVICEID;											

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -