wince音频驱动---1
来源:互联网 发布:公司网络宣传制度 编辑:程序博客网 时间:2024/05/17 00:14
http://blog.csdn.net/xumercury/article/details/3454243
/////////////////////////////////////////////////////////////
//Author:Mercury Xu
//Date:2008-12-05
//Descrption:聲音作為WinCE系統中一個比較基礎的配置大家已經都不會陌生。
// 本文主要是總結下作者在調試WM9715聲卡驅動芯片
// 過程中遇到的一些問題
//OS:WinCE5.0
/////////////////////////////////////////////////////////////
正文:
最近一直在調試關於WM9715的東東,整體調試下來感覺9715的確是個很好很強大的芯片。下面我們按照我的開發思路來整理下關於9715開發的一些心得體會。
首先我們來看下WinCE的聲音處理部分的一些基礎知識。如果您對這一部分已經爛熟於心了,請跳到下一個segment。如果您對WM971X系列爛熟於心了。。I'm sorry。看我的文实在是浪费您的时间了。
另外。大家可以参考下《Windows CE实用开发技术》之 8.10 驱动程序实例分析,這裡張老師已經將驅動的結構講的非常清晰了。大家可以參考下。張老師的書中所提及的是ES1371,我以下的文章針對芯片為WM9715.關於9715的datasheet,大家可以參考wolfson的官方站上的datasheet。
Segment I: WinCE的声音驱动部分
WinCE的声音驱动其实很清晰的给了我们大家。以samsung24X0系来说。你会在X:/WINCE500/PUBLIC/COMMON/OAK/CSP/ARM/SAMSUNG/S3C2410X/WAVEDEV类似的目录下找到他们。以下为我Tree以后他的文件结构
- 文件夹 PATH 列表
- 卷序列号码为 000028F4 409E:08D7
- C:.
- │ audiosys.h
- │ devctxt.cpp
- │ devctxt.h
- │ hwctxt.cpp
- │ hwctxt.h
- │ i2s.cpp
- │ i2s.h
- │ input.cpp
- │ makefile
- │ midinote.cpp
- │ midistrm.cpp
- │ midistrm.h
- │ mixerdrv.cpp
- │ mixerdrv.h
- │ output.cpp
- │ sources
- │ strmctxt.cpp
- │ strmctxt.h
- │ wavemain.cpp
- │ wavemain.h
- │ wavepdd.h
- │ wfmtmidi.h
- │
- └─obj
- └─ARMV4I
- └─retail
- devctxt.obj
- hwctxt.obj
- i2s.obj
- input.obj
- midinote.obj
- midistrm.obj
- mixerdrv.obj
- output.obj
- strmctxt.obj
- wavemain.obj
- _objects.mac
很清晰的程序结构。其实很多公司的都是参照这个结构来定制自己声音部分的程式代码。而我们需要注意的这是以下几个文件:
- │ hwctxt.cpp
- │ hwctxt.h
- │ wavemain.cpp
- │ wavemain.h
这几个基本上算是做好了对声音驱动部分的所有接口。如果您要基于WinCE5.0开发一些声音控制方面的App.第一个方法您可以对注册表的一些键值进行修改。比如说触摸屏按键音,音频音量等等。另外,你也可以通过操作以上提及到的文件中的一些接口来对声音处理芯片进行控制,已实现我们所要实现的效果。这里我只分析下我说到的几个文件。其他的例如I2S之类的大家可以看一下。(I2S是一种通讯方式,数字音频传输采用这种方式来处理,WM9715就是I2S来传送系统部分的声音。)
我们先看看HWCTXT.h文件中的一些信息,直接了解他的接口部分内容。
- class HardwareContext
- {
- public:
- static BOOL CreateHWContext(DWORD Index);
- HardwareContext();
- ~HardwareContext();
- void Lock() {EnterCriticalSection(&m_Lock);}
- void Unlock() {LeaveCriticalSection(&m_Lock);}
- DWORD GetNumInputDevices() {return 1;}
- DWORD GetNumOutputDevices() {return 1;}
- DWORD GetNumMixerDevices() {return 1;}
- DeviceContext *GetInputDeviceContext(UINT DeviceId)
- {
- return &m_InputDeviceContext;
- }
- DeviceContext *GetOutputDeviceContext(UINT DeviceId)
- {
- return &m_OutputDeviceContext;
- }
- BOOL Init(DWORD Index);
- BOOL Deinit();
- void PowerUp();
- void PowerDown();
- BOOL StartInputDMA();
- BOOL StartOutputDMA();
- void StopInputDMA();
- void StopOutputDMA();
- void InterruptThread();
- DWORD GetOutputGain (void);
- MMRESULT SetOutputGain (DWORD dwVolume);
- DWORD GetInputGain (void);
- MMRESULT SetInputGain (DWORD dwVolume);
- BOOL GetOutputMute (void);
- MMRESULT SetOutputMute (BOOL fMute);
- BOOL GetInputMute (void);
- MMRESULT SetInputMute (BOOL fMute);
- protected:
- DWORD m_dwOutputGain;
- DWORD m_dwInputGain;
- BOOL m_fInputMute;
- BOOL m_fOutputMute;
- DWORD m_MicrophoneRouting;
- DWORD m_SpeakerRouting;
- DWORD m_InternalRouting;
- DWORD m_MasterOutputGain;
- BOOL InitInterruptThread();
- BOOL InitInputDMA();
- BOOL InitOutputDMA();
- BOOL Codec_channel();
- BOOL InitCodec();
- BOOL MapRegisters();
- BOOL UnmapRegisters();
- BOOL MapDMABuffers();
- BOOL UnmapDMABuffers();
- ULONG TransferInputBuffer(ULONG NumBuf);
- ULONG TransferOutputBuffer(ULONG NumBuf);
- ULONG TransferInputBuffers(DWORD dwDCSR);
- ULONG TransferOutputBuffers(DWORD dwDCSR);
- DWORD GetInterruptThreadPriority();
- DWORD m_DriverIndex;
- CRITICAL_SECTION m_Lock;
- BOOL m_Initialized;
- BOOL m_InPowerHandler;
- DWORD m_dwSysintrOutput;
- DWORD m_dwSysintrInput;
- InputDeviceContext m_InputDeviceContext;
- OutputDeviceContext m_OutputDeviceContext;
- PBYTE m_Input_pbDMA_PAGES[2];
- PBYTE m_Output_pbDMA_PAGES[2];
- BOOL m_InputDMARunning;
- BOOL m_OutputDMARunning;
- ULONG m_OutBytes[2];
- ULONG m_InBytes[2];
- WORD m_nOutputVolume; // Current HW Playback Volume
- WORD m_nInputVolume; // Current HW Input (Microphone) Volume
- HANDLE m_hAudioInterrupt; // Handle to Audio Interrupt event.
- HANDLE m_hAudioInterruptThread; // Handle to thread which waits on an audio interrupt event.
- //----------------------- Platform specific members ----------------------------------
- DWORD m_OutputDMAStatus; // Output DMA channel's status
- DWORD m_InputDMAStatus; // Input DMA channel's status
- BOOL AudioMute(DWORD channel, BOOL bMute);
- //------------------------------------------------------------------------------------
- };
- void CallInterruptThread(HardwareContext *pHWContext);
- //----------------------------------- Helper Functions and Macros ----------------------------------------
- //======== Record =========
- #define ioRecordPointerLow (g_pDMAregs->DIDST1)
- #define ioRecordPointerHigh (g_pDMAregs->DIDST1)
- #define RECORD_DMA_BUFFER_PHYS (g_PhysDMABufferAddr.LowPart + 2 * AUDIO_DMA_PAGE_SIZE)
- #define AUDIO_RESET_RECORD_POINTER() {ioRecordPointerLow = (RECORD_DMA_BUFFER_PHYS); /
- ioRecordPointerHigh = (RECORD_DMA_BUFFER_PHYS+ AUDIO_DMA_PAGE_SIZE); }
- #define AUDIO_IN_CLEAR_INTERRUPTS() (g_pDMAregs->DCON1 = g_pDMAregs->DCON1)
- #define AUDIO_IN_DMA_ENABLE() { g_pDMAregs->DMASKTRIG1 = ENABLE_DMA_CHANNEL; /
- g_pDMAregs->DMASKTRIG1 &= STOP_DMA_TRANSFER; /
- g_pIISregs->IISFCON |= ( RECEIVE_FIFO_ACCESS_DMA | RECEIVE_FIFO_ENABLE); /
- g_pIISregs->IISCON |= RECEIVE_DMA_REQUEST_ENABLE; }
- #define AUDIO_IN_DMA_DISABLE() { StopI2SClock(); /
- g_pIISregs->IISCON &= ~RECEIVE_DMA_REQUEST_ENABLE; /
- g_pIISregs->IISFCON &= ( RECEIVE_FIFO_ACCESS_DMA | RECEIVE_FIFO_ENABLE); /
- g_pDMAregs->DMASKTRIG1 |= STOP_DMA_TRANSFER; }
- #define SELECT_AUDIO_DMA_INPUT_BUFFER_A() (g_pDMAregs->DIDST1 = (int)(g_PhysDMABufferAddr.LowPart+2*AUDIO_DMA_PAGE_SIZE) )
- #define SELECT_AUDIO_DMA_INPUT_BUFFER_B() (g_pDMAregs->DIDST1 = (int)(g_PhysDMABufferAddr.LowPart+3*AUDIO_DMA_PAGE_SIZE) )
- //======== Playback =========
- #define ioPlaybackPointerLow (g_pDMAregs->DISRC2)
- #define ioPlaybackPointerHigh (g_pDMAregs->DISRC2)
- #define AUDIO_RESET_PLAYBACK_POINTER() {ioPlaybackPointerLow = (g_PhysDMABufferAddr.LowPart); /
- ioPlaybackPointerHigh = (g_PhysDMABufferAddr.LowPart + AUDIO_DMA_PAGE_SIZE); }
- #define AUDIO_OUT_CLEAR_INTERRUPTS() (g_pDMAregs->DCON2 = g_pDMAregs->DCON2)
- #define AUDIO_OUT_DMA_ENABLE() { StartI2SClock(); /
- g_pDMAregs->DMASKTRIG2 |= ENABLE_DMA_CHANNEL; }
- #define AUDIO_OUT_DMA_DISABLE() { StopI2SClock(); g_pDMAregs->DMASKTRIG2 &= ~ENABLE_DMA_CHANNEL; }
- #define SELECT_AUDIO_DMA_OUTPUT_BUFFER_A() (g_pDMAregs->DISRC2 = (int)(g_PhysDMABufferAddr.LowPart) )
- #define SELECT_AUDIO_DMA_OUTPUT_BUFFER_B() (g_pDMAregs->DISRC2 = (int)(g_PhysDMABufferAddr.LowPart+AUDIO_DMA_PAGE_SIZE) )
- //------------------------------------------ Externs ----------------------------------------------
- extern HardwareContext *g_pHWContext;
好了,到這裡大家估計已經基本上暈了,我來給大家刪除點東西。大家就能看的非常清晰
- class HardwareContext
- {
- public:
-
- //通用接口部分
- protected:
-
//保护接口部分 - //----------------------- Platform specific members ----------------------------------
- //成员
- //------------------------------------------------------------------------------------
- };
- void CallInterruptThread(HardwareContext *pHWContext);
- //----------------------------------- Helper Functions and Macros ----------------------------------------
- //======== Record =========
- //------------------------------------------ Externs ----------------------------------------------
- extern HardwareContext *g_pHWContext;
好了。通用接口部分我们可以自由使用,接口再wavemain.cpp中都已经给我们做好了流式驱动通用的接口。大家只要简单的了解下格式就可以很容易的去使用他。
现在,我们准备自由发挥了。在自由发挥前,我们再做个热身运动,看一看wavemain.cpp.
- BOOL CALLBACK DllMain(HANDLE hDLL,
- DWORD dwReason,
- LPVOID lpvReserved)
- {
- switch (dwReason) {
- case DLL_PROCESS_ATTACH :
- DEBUGREGISTER((HINSTANCE)hDLL);
- DisableThreadLibraryCalls((HMODULE) hDLL);
- break;
- case DLL_PROCESS_DETACH :
- break;
- case DLL_THREAD_DETACH :
- break;
- case DLL_THREAD_ATTACH :
- break;
- default :
- break;
- }
- return TRUE;
- }
- // -----------------------------------------------------------------------------
- //
- // @doc WDEV_EXT
- //
- // @topic WAV Device Interface | Implements the WAVEDEV.DLL device
- // interface. These functions are required for the device to
- // be loaded by DEVICE.EXE.
- //
- // @xref <nl>
- // <f WAV_Init>, <nl>
- // <f WAV_Deinit>, <nl>
- // <f WAV_Open>, <nl>
- // <f WAV_Close>, <nl>
- // <f WAV_Read>, <nl>
- // <f WAV_Write>, <nl>
- // <f WAV_Seek>, <nl>
- // <f WAV_PowerUp>, <nl>
- // <f WAV_PowerDown>, <nl>
- // <f WAV_IOControl> <nl>
- //
- // -----------------------------------------------------------------------------
- //
- // @doc WDEV_EXT
- //
- ---------
- extern "C" DWORD WAV_Init(DWORD Index)
- {
- return((DWORD)HardwareContext::CreateHWContext(Index));
- }
- extern "C" BOOL WAV_Deinit(DWORD dwData)
- {
- return(g_pHWContext->Deinit());
- }
- extern "C" PDWORD WAV_Open( DWORD dwData,
- DWORD dwAccess,
- DWORD dwShareMode)
- {
- // allocate and return handle context to efficiently verify caller trust level
- return new DWORD(NULL); // assume untrusted. Can't tell for sure until WAV_IoControl
- }
- extern "C" BOOL WAV_Close(PDWORD pdwData)
- {
- // we trust the device manager to give us a valid context to free.
- delete pdwData;
- return(TRUE);
- }
- extern "C" DWORD WAV_Read(DWORD dwData,
- LPVOID pBuf,
- DWORD Len)
- {
- // Return length read
- return(0);
- }
- extern "C" DWORD WAV_Write(DWORD dwData,
- LPCVOID pBuf,
- DWORD Len)
- {
- // return number of bytes written (or -1 for error)
- return(0);
- }
- extern "C" DWORD WAV_Seek(DWORD dwData,
- long pos,
- DWORD type)
- {
- // return an error
- return((DWORD)-1);
- }
- extern "C" VOID WAV_PowerUp(VOID)
- {
- g_pHWContext->PowerUp();
- return;
- }
- extern "C" VOID WAV_PowerDown(VOID)
- {
- g_pHWContext->PowerDown();
- return;
- }
- BOOL HandleWaveMessage(PMMDRV_MESSAGE_PARAMS pParams, DWORD *pdwResult)
- {
- // set the error code to be no error first
- SetLastError(MMSYSERR_NOERROR);
- UINT uMsg = pParams->uMsg;
- UINT uDeviceId = pParams->uDeviceId;
- DWORD dwParam1 = pParams->dwParam1;
- DWORD dwParam2 = pParams->dwParam2;
- DWORD dwUser = pParams->dwUser;
- StreamContext *pStreamContext = (StreamContext *)dwUser;
- DWORD dwRet;
- g_pHWContext->Lock();
- switch (uMsg)
- {
- //很多个CASE,我们就省略掉了,大家自己看看找到自己要用的
- default:
- dwRet = MMSYSERR_NOTSUPPORTED;
- }
- g_pHWContext->Unlock();
- // Pass the return code back via pBufOut
- //这个地方的处理很奇妙哦。很好的方法。
- if (pdwResult)
- {
- *pdwResult = dwRet;
- }
- return(TRUE);
- }
- extern "C" BOOL WAV_IOControl(PDWORD pdwOpenData,
- DWORD dwCode,
- PBYTE pBufIn,
- DWORD dwLenIn,
- PBYTE pBufOut,
- DWORD dwLenOut,
- PDWORD pdwActualOut)
- {
- // check caller trust. if context hasn't been initialized, load from CeGetCallerTrust.
- if (*pdwOpenData != OEM_CERTIFY_TRUST) {
- if (OEM_CERTIFY_TRUST != (*pdwOpenData = CeGetCallerTrust())) {
- PRINTMSG(ZONE_WARN, (TEXT("WAV_IoControl: untrusted process/r/n")));
- SetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
- }
- //以下为无敌的出错处理部分,非常指的我们学习的。
- _try
- {
- switch (dwCode)
- {
- case IOCTL_MIX_MESSAGE:
- return HandleMixerMessage((PMMDRV_MESSAGE_PARAMS)pBufIn, (DWORD *)pBufOut);
- case IOCTL_WAV_MESSAGE:
- return HandleWaveMessage((PMMDRV_MESSAGE_PARAMS)pBufIn, (DWORD *)pBufOut);
- }
- }
- _except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- RETAILMSG(1, (TEXT("EXCEPTION IN WAV_IOControl!!!!/r/n")));
- SetLastError(E_FAIL);
- }
以上的部分就是我们做APP程序最终的接口部分了。我们会用到WAV_IOControl作为最后的app调用的入口来对那些看的眼花缭乱的case进行调用操作。关于CASE和case所对应的函数就是针对不同的芯片处理的不同功能,针对不同的芯片有不同的处理函数实现,这个需要大家静下心来仔细阅读芯片的datasheet了。
- wince音频驱动---1
- Wince音频驱动(1)
- WinCE音频驱动
- WinCE音频驱动
- WinCE音频驱动(转)
- WinCE音频驱动
- wince音频驱动分类
- wince音频驱动
- wince IIS 音频驱动
- wince音频驱动-2
- wince音频驱动模型
- WinCE音频驱动
- WinCE音频驱动
- WinCE音频驱动(二)转
- WINCE 音频驱动之一:分类
- WINCE 音频驱动之一:分类
- wince音频驱动--PCM文件格式
- wince音频驱动---wav格式
- 汇编文件后缀 .s 与 .S
- Linux设备驱动之内存映射
- 多线程--条件变量
- 数据结构基本算法java实现
- 输出文件中不包含指定的多个排除词的行内容(双重遍历)
- wince音频驱动---1
- 那两年炼就的Android内功修养
- 你还认为自己是个程序员?18个有趣的事实
- 杀掉所有newlisp进程
- 图像检索:基于形状特征的算法
- Web测试基于实际测试的功能测试点总结(转)
- Android学习之AndroidManifest.xml清单之<uses-feature>
- java异步判断数据库是否有重复字段值
- 黑马程序员-----程序员之路_____Java基础