📄 audiodrv.c
字号:
#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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -