關於基於WinCE下的聲音系統調試的一些經驗總結之驱动程式部分(二)

/
//Author:Mercury Xu
//Date:2008-12-08
//Descrption:聲音作為WinCE系統中一個比較基礎的配置大家已經都不會陌生。
//           本文主要是總結下作者在調試WM9715聲卡驅動芯片
//           過程中遇到的一些問題
//OS:WinCE5.0
/
正文
好了。以下是Segment II,跳过来的朋友和读过来的朋友都要准备好了。我们要开始耍WM9715了。

首先我们还是来热身下,热身我们要准备以下两个东西

1.应用层的一些小知识。
2.WM9715 datasheet。

我们先来看第一个,做流式驱动调用的时候我们知道,有一个XXX_IOCONTROL之类的函数一般在最后,我们再WM9715的WAV驱动的地方也有个。 WAV_IOControl。我们在应用层怎么去调用他呢?
其实很简单。大家先看看MSDN的这个文档:
http://msdn.microsoft.com/en-us/library/aa363216(VS.85).aspx

BOOL WINAPI DeviceIoControl(
__in HANDLE hDevice, //句柄一个,定义一个HANDLE的句柄,在初始化的时候就好了
__in DWORD dwIoControlCode,//这个一般无关痛痒,Null掉了
__in_opt LPVOID lpInBuffer,//这个就比较重要了,输入数据的接口,要和你定义好的case数值匹配好哦!
__in DWORD nInBufferSize,//这个长度一般都直接用sizeof处理掉了。
__out_opt LPVOID lpOutBuffer,//这个也是比较重要的,返回值,在上一篇文章里面case最后有个比较精彩的程序段,
//给了这个变量值,大家可以回头过去看看。   
__in DWORD nOutBufferSize,//这个也直接sizeof了。
__out_opt LPDWORD lpBytesReturned,//这个我们都Null
__inout_opt LPOVERLAPPED lpOverlapped ///这个也NULL了
);
好了。不多说了,看懂了吧。这里再提醒下,case的值一定不能搞错了,搞错了怎么样都是出不了的。

接下来还有个难度稍微大一点点的。我们再上一篇文章应该有看到在try的里面有个很长的结构体,叫PMMDRV_MESSAGE_PARAMS
这个结构体再APP不管你用EVC还是VS2005都是没有给出初始化定义的。所以,接下来我们给出他的定义
  1. BOOL WAV_IOControl(DWORD  dwOpenData,
  2.                    DWORD  dwCode,
  3.                    PBYTE  pBufIn,
  4.                    DWORD  dwLenIn,
  5.                    PBYTE  pBufOut,
  6.                    DWORD  dwLenOut,
  7.                    PDWORD pdwActualOut)
  8. You can use pBufIn pass its parameter, and pBufIn is defined with 
  9.     typedef struct {
  10.             UINT uDeviceId;
  11.             UINT uMsg;
  12.             DWORD dwUser;
  13.             DWORD dwParam1;
  14.             DWORD dwParam2;
  15.     } MMDRV_MESSAGE_PARAMS, *PMMDRV_MESSAGE_PARAMS;
  16. and you can use pBufOut to get return value, it is definded with
  17. (DWORD *)

  18. (PMMDRV_MESSAGE_PARAMS)pBufIn, (DWORD *)pBufOut

  19. WRITE REGISTER
  20. dwCode:   IOCTL_WAV_MESSAGE
  21. uMsg:     WODM_WRITE_AC97 
  22. dwParam1: AC97 register's ID, it should be even, please read AC'97 specification
  23. dwParam2: pass value(write), the value shoud be an 16-bits 
  24.           number.
  25.           
  26. READ REGISTER
  27. dwCode:   IOCTL_WAV_MESSAGE
  28. uMsg:     WIDM_READ_AC97 
  29. dwParam1: AC97 register's ID, it should be even, please read AC'97 specification
  30. pBufOut:  RETURN VALUE 

这下眼前一亮了吧。我顺带将9715的两个东东也带出来了。关于9715的操作我们接下来就开始给大家说说,刺激的地方要开始了。

下面我们开始比较刺激的地方了。看看WM9715的结构以及驱动的地方怎么去处理。

对于芯片的操作,无非就是两个,读寄存器,写寄存器,首先我们看看WM9715的datasheet

http://www.wolfsonmicro.jp/uploads/documents/cn/WM9715L_Rev3.9.pdf

我们先看下他的功能

rel="File-List" href="file:///C:%5CDOCUME%7E1%5CMERCUR%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml">

AC’97 Rev 2.2 compatible stereo codec

AC’97 Rev2.2 兼容立体声解码

- DAC SNR 90dB, THD –86dB

- ADC SNR 88dB, THD –88dB

- Variable Rate Audio, supports all WinCE sample rates

  多频率音频,支持所有WinCE采样率

- Tone Control, Bass Boost and 3D Enhancement

  音调控制,重音控制以及3D环绕控制

On-chip 45mW headphone driver

   片载45毫瓦耳机驱动

On-chip 400mW mono speaker driver

   片载400毫瓦单声道喇叭驱动

Stereo, mono or differential microphone input

   立体声,单声道或者混合麦克风输入

- Automatic Level Control (ALC)

   自动等级控制

Auxiliary mono DAC (ring tone or DC level generation)

   辅助单DAC

Seamless interface to wireless chipset

   无线连接接口

Resistive touchpanel interface

   电阻丝触摸板接口

- Supports 4-wire and 5-wire panels

    支持4线和5线触摸板

- 12-bit resolution, INL ±3 LSBs (<0.5 pixels)

    12位协议,INL ±LSBs (<0.5 pixels)

- X, Y and touch-pressure (Z) measurement

    X,Y以及触摸压力测量

- Pen-down detection supported in Sleep Mode

    休眠模式下触摸笔下压侦测

2 comparator inputs for battery monitoring

   2个电源侦测比较输入端口

Up to 4 auxiliary ADC inputs

   4个辅助ADC输入

1.8V to 3.6V supplies

   1.8V 3.6v 电压支持

7x7mm QFN

   7* 7mm QFN封装


好了,如果你还是不放心,看到

- Variable Rate Audio, supports all WinCE sample rates

  多频率音频,支持所有WinCE采样率

这句话你应该可以放心大胆的来玩这颗芯片了。

首先,我们需要知道,系统的声音是一个数据音频,所有,系统走的方式是通过I2S来的。这一块一般再BSP包中都会有写好了。大家都不用去修改。直接用就好了

其次,其他的声音输入采用的方式基本上是通过9715的几个音频输入口,比如MIC LINEIN这几个来实现的。首先你要检查下硬件上都是OK,输入一些音频的模拟信号进去,确认已经进入到了芯片里。

最后我们开始来看这个DATASHEET里面的最神奇的图。Audio paths overview。。。大概在14页图片1

这个图太神奇了。。想起了小时玩红白机三国志里面选角色的情景,走线路判断后选人。怀念啊。。。。
这里我们就拿LINEINL这一路来看PIN23蓝色的线走下去。

1.我们先碰到了10H这个寄存器他是控制输入音量的,我们先要使能,然后选择最大音量,这里有个小尝试,+的dB是音量最大啊!!!(众人,地球人都知道。。。)
2.接下来我们看到了个MIXER.不鸟他
3.然后我们看到我们要使能的寄存位了10H:15我们很开心的把它做成1,使能了。
4.headphone mix是个大关,混合了下音以后送出来
5.接下来有个选择器,我们直接过去,上面有个转向器,我们也不用鸟他了02H的转向器
6.最后一个BOSS来了02H首先你要他处于可以放的状态,也就是非MUTE状态,我们仔细一看,02H:7.好了。我们很开心的把它弄成了1.
7.最后的最后我们来弄个音量,也弄个最大音量就好了。

以上就是一套路线打通的方法,其他路线打通的方法大同小异。大家一路跟下去就OK了。

至于如可写寄存器如何读寄存器,下面我们简单说下,因为不同的ARM可能对这个处理的方式不太一样。但是总体上是类似。

上面我们很开心的将一些寄存器位设计为高,我们通过写寄存器的方式实现。下面我给一个参考给大家


  1. BOOL WriteAC97Reg(USHORT RegIndex, USHORT RegValue)
  2. {
  3.     ULONG timeout = 0;
  4.     GRABMUTEX();
  5.     IOW_REG_SET(struct ac97Ctrl1Bits, &v_pCodecReg->ac97ctrl1, (RegValue << 16) | ((RegIndex & 0x7f) << 8));        //  CODEC_AC97_CMD = (RegValue << 16) | RegIndex; 
  6.     IOW_REG_OR(struct ac97Ctrl0Bits, &v_pCodecReg->ac97ctrl0, 0xe000);      //  CODEC_AC97_CTRL |= 0xe000; 
  7.     while ((v_pCodecReg->ac97ctrl0.ac97_write_tagh & AC97_WRITE_SLOT1_VALID) && (timeout++ < TIMEOUT_LOOPS));
  8.     if(timeout >= TIMEOUT_LOOPS)
  9.     {
  10.         RETAILMSG(1, (TEXT("Timeout in write ac97")));
  11.     }
  12.     usWait(5);
  13.     RELEASEMUTEX();
  14.     return (timeout < TIMEOUT_LOOPS);
  15. }
  1. // AC97_CONTROL_0 -0X01C R/W
  2. struct ac97Ctrl0Bits {
  3.     unsigned da_channel        :2;// da channel enable, bit1 left channel, bit0 right channel; 1= channel enable;0=channel disable
  4.     unsigned ad_channel        :2;// ad channel enable
  5.     unsigned warm_wake        :1;// Warm wake codec 1= warm wake   0= exit warm wake-up mode.
  6.     unsigned ac97_start        :1;// ac97 interface start 1= ac97 interface start  0= stop
  7.     unsigned rsvd0            :5;// reserved
  8.     unsigned ac97_write_tagh    :5;// AC-link output frame tag setting
  9.     unsigned rsvd1            :16;// reserved
  10. };
  11. // AC97_STATUS_0 -0X024 R
  12. struct ac97Status0Bits {
  13.     unsigned ac97_slot_rq        :8;    // ac97 slot request
  14.     unsigned ac97_read_tagh        :8;  // ac97 input frame status bit15 codec ready, bit14 solt1 valid, bit13 slot2....
  15.     unsigned rsvd0            :16;
  16. };
 

1.IOW_REG_SET和 IOW_REG_OR这两个函数大家根据自己的芯片进行定义就好了,其他都是很常用的。在这里就不多说了。
2. ac97Ctrl1Bits和0是对WM9715你自身ARM控制的一些操作。这个你按照你自己的来就好了。
3.最后两个是赋值了。

基本的思路是上面的。大家还是要根据不同的芯片来不同处理。
那今天驱动部分我们就介绍完了。关于应用层,明天我们再聊。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值