/////////////////////////////////////////////////////////////
//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:
-
- //通用接口部分
- protected:
-
//保护接口部分
-
- //成员
-
- };
- void CallInterruptThread(HardwareContext *pHWContext);
- 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;
- }
- 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)
- {
-
- return new DWORD(NULL);
- }
- extern "C" BOOL WAV_Close(PDWORD pdwData)
- {
-
- delete pdwData;
- return(TRUE);
- }
- extern "C" DWORD WAV_Read(DWORD dwData,
- LPVOID pBuf,
- DWORD Len)
- {
-
- return(0);
- }
- extern "C" DWORD WAV_Write(DWORD dwData,
- LPCVOID pBuf,
- DWORD Len)
- {
-
- return(0);
- }
- extern "C" DWORD WAV_Seek(DWORD dwData,
- long pos,
- DWORD type)
- {
-
- 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)
- {
-
- 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();
-
- 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)
- {
-
- 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了。
下一篇我们就来一起看看WM9715这个传说中的芯片。很牛X的。