2009年4月22日星期三

GSM系统语音编码器综述

原文来源于

http://www.eetchina.com/ART_8800350559_480101_TA_2e2efabc.HTM

http://www.mc21st.com/TechArticle413.html

GSM系统语音编码器综述

脉冲编码调制PCM和增量调制AM是波形编码的代表,波形编码直接对模拟语音取样、量化,并用代码表示。波形编码的比特率一般在16kbit/s至64kbit/s之间,它有较好的话音质量与成熟的技术实现方法。

参量编码又称声源编码,它是以发音机制的模型作为基础,用一套模拟声带频谱特性的滤波器系数和若干声源参数来描述这个模型,在发送端从模拟语音信号中提取各个特征参量并进行量化编码。这种编码的特点是语音编码速率较低,基本上在2kbit/s---4.8kbit/s之间,语音的可懂度较好,但有明显的失真。

混合编码是近年来提出的一类新的语音编码技术,它将波形编码和参量编码结合起来,力 图保持波形编码话音的高质量与参量编码话码的低速率。混合编码数字语音信号中既包括若 干语音特征参量又包括部分波形编码信息。其比特率一般在4kbit/s---16kbit/s。
那么,什么样的语音编码技术适用于无线移动通信呢? 这主要取决于无线移动信道的条件。由于频率资源十分有限,所以要求编码信号的速率较低,由于移动信道的传播条件恶劣,因而编码算法应有较好的抗误码能力。另外,从用户的角度出发,还应有较好的语音质量和较短的时延。归纳起来,移动通信对数字语音编码的要求如下:
速率较低,纯编码速率应低于16kbit/S;
在一定编码速率下音质应尽可能高;
编码时延应较短,控制在几十毫秒以内;
在强噪声环境中,算法应具有较好的抗误码性能,以保持较好的话音质量;
算法复杂程度适中,易于大规模集成。

GSM所用的语音编码是(RPE—LTP),规则码激励长期预测编码就是一种混合编码技术,其纯码速率为13kbit/S,语音质量MOS得分可达4.0。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

信号处理内核的发展促进了GSM系统语音编解码器的增强。目前更为密集的分析加合成方法已用于在常见的EFR 及AMR语音编码器中,以在容量有限且容易出错的空中接口上提供最高质量的语音传输。

以当前对高速分组数据传输的关注程度,人们很容易忘记GSM数字电信系统的最初主要目的是传输语音。总的感觉是整个系统的复杂性与传输链路的管理有关,但也有很大部分与麦克风捕捉到的音频压缩与解压缩复杂性有关。

为满足这一主要目的的需求,必须以足够高的采样及分辨率来捕获语音,以清楚地再现原始声音,并用一种可在比特率有限及容易出错的无线传输信道上保持音频高保真度的方式来压缩语音。

这一需求很具体,其目的是传输语音,故载荷的频率范围及声音质量均为已知。人类听觉系统的工作方式允许编码器在手机耳机上产生出类似自然声音的听觉效果。GSM系统中所使用的语音编码器的主要原理是对人类音域的数学建模,从而产生出一种用于传输语音的有效压缩方法。术语“声码器”或“语音编码器”专门用来描述这些专门执行语音压缩的系统。

GSM系统对用于传输语音的信道具有一组固定的物理要求。首先,它具有最大22.8kbps的原始数据速率;其次,帧可以被“偷窃”以及用于信令,且语音编码系统对这种情况必须很稳健,尽管存在对可偷窃语音帧的频率及时序的一定限制。

信道容量与编码

GSM物理层是FDMA与TDMA的组合。无线信道在整个GSM频段被分成相隔200kHz的多个信道,这些FDMA信道又被分成8个时隙。GSM物理信道被定义为单个“绝对无线频率信道号”(ARFCN)上的单个时隙--故每一频率均可包含有8个独立物理信道。

“猝发”是指GSM系统中的无线传输量,且包含以周期577(s发送的114位原始信息。由于语音流量信道传输的多帧结构,故每26次猝发最多有24次可包含语音数据(其余2次猝发用于空闲周期或传输信令信息)。因此合计能给出22.8kbps的原始信道容量。

原始信道容量是完美传输条件下的最大用户数据(编码语音)吞吐量。在真实世界中,无线传输并不稳健而且需要为数据增加保护。

增加冗余信息后,GSM系统中的全速率语音信道用于编码语音的容量为13kbps。

语音编解码器

如果以8 kHz采样率及13位精度来对出自GSM蜂窝手机麦克风的音频数据进行采样,则可得到104kbps的源数据速率。GSM系统中有四种编解码器,分别执行:全速率、增强型全速率(EFR)、自适应多速率(AMR)及半速率语音压缩。表1给出了一些声码器的参数比较。

全速率

全速率语音编解码器是改良的线性预测编码器(LPC),它将人类声域建模成一系列不同宽度的圆柱体。通过迫使空气通过这些柱体,即可产生语音。LPC编码器用一组联立方程来进行建模。

标准LPC编码器不能提供电话系统所需的话音质量(虽能听清语句,但很难或不可能分辨出说话的人)。GSM系统中采用两种技术来提高LPC编码器的质量,即:长期预测(LTP)与规则脉冲激励(RPE),而全速率编解码器就被称为RPE-LTP线性预测编码器。

输入至RPE-LTP编码器的数据为包括160个采样值的20ms语音,每一个采样值都拥有13位精度。数据首先通过预加重滤波器来提高信号的高频分量,以获得更好的传输效率。滤波器一般还消除信号上的任何偏移以简化进一步的计算。

正如前面所提到的,语音产生模型可看成是空气通过一组不同大小的圆柱体。短期分析级采用自动相关来计算与模型所用的8个圆柱体有关的8个反射系数,同时采用一种称为Schur递归的技术来有效地求解所得到的方程组。参数被变换成可以更少的位数来进行更佳量化的LAR(log-area ratio)。这些是传输流的前8个参数。

然后再将编码后的LAR解码成系数,并用来对输入采样值进行滤波。解码LAR的原因是为了确保编码器使用解码器上的相同信息来进行滤波。这一级上的其余采样值用于编解码器的LTP级。

160个采样值被分成4个子窗口,每一个子窗口都拥有40个采样值。长期预测器为每一子窗口产生2个参数:滞后与增益。滞后由当前帧与后两帧之间的交叉相关峰值确定,而增益则由归一化交叉相关系数决定。滞后与增益参数被应用到长期滤波器上,同时对现有短期剩余信号进行预测。

RPE级通过十取一及交错将40个剩余采样值转换成13个参数,并用APCM将所得出的13个值编码,其中最大值用对数编码成6位,然后再将13个参数均表示成3位,总共45位。

最后一级是从计算出的长期剩余及分析信号来更新短期剩余信号,然后再用此数据来计算下一帧。

增强型全速率

全速率编解码器是一种用来传输语音并在计算上相当有效的方法,但通过使用更为密集的算法,语音质量还能提高。全速率编解码器首先在1990年代初的DSP上实现,当时在经济上虽不能采用质量更好的编码器但却是一种更为密集的算法。

至1990年代中,功能更强的DSP内核的可用性已不再是一个问题,因此增强型全速率编解码器开始在手机中出现。

EFR声码器是一种代数码激励线性预测(ACELP)编码器,且不同于采用分析加合成方法的全速率系统。它计算虽更加密集但能在输出端得到更为精确的结果。预处理级由80Hz高通滤波器及一些缩减电路组成,以使实现更为容易。每帧进行两次短期分析,由与两个30mS(1.5个语音帧)、长度集中在不同子帧上的不同非对称窗口自动关联。所得到的系数被变换成线谱对(line spectral pairs)并被量化成38位,以获得更好的传输效率。

同时执行开环间隔(pitch)分析来计算每帧的间隔滞后估计值,然后再用此估计值启动闭环搜索(以得出更快的结果)。再将所得到的闭环值应用于合成器及与非量化输入比较后的结果上(即分析加合成),最小的加权误差从自适应编码本(codebook)上得出并被编码成每子帧35位。

然后再用代数(固定) 编码本、并再一次用分析加合成方法来对量化后余下的剩余信号进行建模。所得到的编码本增益被编码成每子帧5位。

最后,正如全速率声码器中一样,针对下一帧将存储器刷新。

EFR声码器的12.2kbps输出等于每帧244位。但编码语音是通过拥有260位容量的常规GSM全速率空中信道来传输,其余16位被填以CRC以及重复一些用于冗余的最重要编解码器参数。

自适应多速率

当全部参数均能解码时,全速率及EFR编解码器可实现良好的语音再现。由于传输信道的冗余(请记住,原始信道容量比数据载荷大10kbps),故许多原始位可以出错且参数仍能恢复。

但当参数丢失或错误时,所接收信号的质量将迅速下降(参见图3中的最右侧黑色曲线)。

这也是AMR编解码器组所试图解决的问题。通过指定8个全都共享公共数学算法的声码器组,可改变信道的冗余量。以此种方式,语音传输的质量可能会由于降至更低的编码速率上而稍微有所下降,但覆盖编码参数的信心则得以提高。

结果是在载波干扰增加的情况下可获得感觉更好的语音信号质量(如图3)。

AMR编解码器组由速率从12.2kbps至4.75kbps的ACELP声码器组成,故可提供87%至480%的冗余。在一种很糟的情况下,即全速率及EFR帧丢失很久后,4.75kbps编解码器数据仍能恢复。

半速率

GSM所采用的空中接口允许使用两个完全独立的半速率子信道,故能使蜂窝单元的语音容量加倍。半速率声码器采用矢量和激励线性预(VSELP)编码器,它以一种类似EFR及AMR编解码器的分析加合成方式工作,速率为5.7kbps。

半速率声码器的输出帧包含用来指示帧声音内容的2个位。该声码器工作方式在每种模式下略微有些不同,故可获得最佳的音频数据再现质量。

人们对半速率语音的感觉普遍不佳,所以今天一般不采用此项技术。但以其自适应模式,AMR声码器的6种较低速率将适合半速率空中信道的可用容量,结果是采用带AMR的半速率信道将在高流量领域变得更为普遍。

非连续传输

在典型的谈话过程中,语音仅占总时间的大约40%。为减少对无线接口的干扰,可采用非连续传输(DTX),即移动电话仅在有语音信号时才进行传输。此功能要求有如下几项内容,即:语音活动检测(VAD)、用于空中接口的静寂描述符(SID)帧及舒适噪音产生等。

为减少猝发传输的总时间,语音解码器必须能确定什么时候有语音。由于编码的自然特性,可通过分析中间参数来精确确定是否有语音。重要的是要保证阈值合适,太灵敏会由于无线传输次数太多而对空中接口不利,而灵敏度不够则会切断语音并使声音质量严重下降。

尽管在理论上VAD是实现DTX所需的全部,但来自接收器的完全静寂降低整体感觉质量。为解决此问题,接收器采用了“舒适噪音”功能,即利用SID帧参数的逐渐衰减来产生类似发射器背景噪音的声音。

当VAD确定没有语音时,在空中接口上不进行传输(实际情况比这更复杂一些,但其基本原理一样)。经过一段预定时间间隔后,再发送一个包含一组参数的SID帧,这些参数用于接收器舒适噪音产生功能。

最佳实现

语音编码功能可解释为像卷积这样的数学密集型处理,在带有处理这类计算指令(例如乘法-累加指令)的专用DSP上能得到最佳实现。尽管这可以在通用处理器上实现,但要求有更高数量级的时钟速度来与同样的执行速度相匹配。

不同处理内核中所实现的EFR及全速率声码器执行速度不同。作为一种与时钟速度有关的比较,DSP全速率实现的速度大约要比奔腾处理器实现的速度快3.5倍,而经彻底优化后的SC140实现的速度要比奔腾处理器实现的速度整整快18倍。

在语音编解码器中采用了许多优化技术。最初一般将数据偏移以使计算更加容易并能再利用存储器空间。例如,用剩余滤波器写入输入阵列而不使用新存储器空间。

处理器可采用定制浮点实现来在内核中提供浮点支持。这些实现不是位精确的,这意味着它们不能得出像定点参考实现一样精确的数学结果。但通过软硬件中针对这类数学算法的优化,速度可明显提高。而输出参数,当被送入定点解码器时,将产生感觉上一样的声音帧。

测试位序列

为检验依从性,ETSI颁布了一组全面的测试位序列。它们由输入文件(160个13位采样值)、编码文件(通过解码器的结果)、一些解码文件(用于直接提供给解码器)以及输出文件(代表来自输出的160个采样值)组成。

而像VAD及舒适噪音产生等额外功能,则用各种序列进行隐含测试。同时也对不同输入压缩扩展方案(A-law和(-law)进行测试。

浮点实现一般不遵循ETSI位序列,但能产生一组感觉上与定点编码器及解码器相兼容的参数。

对语音编码器实现的定性评价,可用Racal仪器公司带VQA的AIME系统来测试。这种系统允许建立原始流量信道(无需完全的GSM协议实现),且能执行全速率的空中传输双向语音编码。

作者:Richard Meston

高级软件工程师

Racal仪器公司无线解决方案部

2009年4月20日星期一

控制信道(CCH)传输各种信令信息

控制信道(CCH)传输各种信令信息

控制信道分为三类:

1)广播信息(BCH)是一种“一点对多点”的单方向控制信道,用于基站向所有移 动台广播公用信息。传输的内容是移动台入网和呼叫建立所需要的各种信息。其中又分 为:

a、频率校正信道(FCCH):传输供移动台校正其工作频率的信息;

b、同步信道(SCH):传输供移动台进行同步和对基站进行识别的信息;

c、广播控制信道(BCCH):传输通用信息,用于移动台测量信号强度和识别小区 标志等。

2)公共控制信道(CCCH)是一种“一点对多点”的双向控制信道,其用途是在呼 叫接续阶段,传输链路连接所需要的控制信令与信息。其中又分为:

a、寻呼信道(PCH):传输基站寻呼移动台的信息;

b、随机接入信道(RACH):移动台申请入网时,向基站发送入网请求信息;

c、准许接入信道(AGCH):基站在呼叫接续开始时,向移动台发送分配专用控制 信道的信令。

3)专用控制信道(DCCH)是一种“点对点”的双向控制信道,其用途是在呼叫接 续阶段和在通信进行当中,在移动台和基站之间传输必需的控制信息。其中又分为:
a、独立专用控制信道(SDCCH):传输移动台和基站连接和信道分配的信令;

b、慢速辅助控制信道(SACCH):在移动台和基站之间,周期地传输一些特定的信 息,如功率调整、帧调整和测量数据等信息;SACCH是安排在业务信道和有关的控制信 道中,以复接方式传输信息。安排在业务信道时,以SACCH/T表示,安排在控制信道时, 以SACCH/C表示,SACCH/常与SDCCH联合使用。

c、快速辅助控制信道(FACCH):传送与SDCCH相同的信息。使用时要中断业务信 息(4帧),把FACCH插入,不过,只有在没有分配SDCCH的情况下,才使用这种控制信 道。这种控制信道的传输速率较快,每次占用4帧时间,约18.5ms。

由此可见,GSM通信系统为了传输所需的各种信令,设置了多种专门的控制信道。 这样做,除因为数字传输为设置多各逻辑信道提供了可能外,主要是为了增强系统的控 制功能(比如后面将要提到的,为提高过境切换的速度而采用移动台辅助切换技术), 也为了保证话音通信质量,在模拟蜂窝系统中,要在通话进行过程中,进行控制信息的 传输,必须中断话音信息的传输(100ms),这就是所谓的“中断一猝发”的控制方式。 信道中断100ms,会使话音产生可以听得到的喀喇声。如果这种中断过于频繁,势必明 显地降低话音质量,因此,模拟蜂窝系统必须限制在通话过程中传输控制信息的容量。 与此不同,GSM蜂窝系统采用专用控制信道传输控制信息,除去FACCH外,不在通信过 程中中断话音信息,因而能保证话音的传输质量。其中FACCH虽然也采取“中断一猝发” 控制方式,但是只在特定场合下才使用,而且占用的时间短(18.5ms),其影响明显 减小。GSM蜂窝系统还采用信息处理技术,来估计并补偿这种因为插入FACCH而被删除 的话音。

BSIC

基站识别码 Base Station Identity Code
  包括PLMN色码和基站色码。用于区分不同运营者或同一运营者广播控制信道频率相同的不同小区。
  BSIC用於移动台识别相同载频的不同基站,特别用於区别在不同国家的边界地区采用相同载频且相临的基站,BSIC为一个6bit编码:BSIC=NCC(3bit)+BCC(3bit)
  NCC:PLMN色码,用来识别相临的PLMN网
  BCC:BTS色码,用来识别相同载频的不同的基站.
  BSIC的4个作用
  移动台收到SCH后,即认为已同步于该小区。但为了正确地译出下行公共信令信道上的信息,移动台还必须知道公共信令信道所采用的训练序列码(TSC)。按照GSM规范的规定,训练序列码有八种固定的格式,分别用序号0~7表示。每个小区的公共信令信道所采用的TSC序列号由该小区的BCC决定。因此BSIC的作用之一是通知移动台本小区公共信令信道所采用的训练序列号。
  由于BSIC参与了随机接入信道(RACH)的译码过程,因此它可以用来避免基站将移动台发往相邻小区的RACH误译为本小区的接入信道。
  当移动台在连接模式下(通话过程中),它必须根据BCCH上有关邻区表的规定,对邻区BCCH载频的电平进行测量并报告给基站。同时在上行的测量报告中对每一个频率点,移动台必须给出它所测量到的该载频的BSIC。当在某种特定的环境下,即某小区的邻区中包含两个或两个以上的小区采用相同的BCCH载频时,基站可以依靠BSIC来区分这些小区,从而避免错误的切换,甚至切换失败。
  移动台在连接模式下(通话过程中)必须测量邻区的信号,并将测量结果报告给网络。由于移动台每次发送的测量报告中只能包含六个邻区的内容,因此必须控制移动台仅报告与当前小区确实有切换关系的小区情况。BSIC中的高三位(即NCC)用于实现上述目的。网络运营者可以通过广播参数"允许的NCC"控制移动台只报告NCC在允许范围内的邻区情况。

2009年4月13日星期一

实战DeviceIoControl 之一:通过API访问设备驱动程序

Q 在NT/2000/XP中,我想用VC编写应用程序访问硬件设备,如获取磁盘参数、读写绝对扇区数据、测试光驱实际速度等,该从哪里入手呢?
A 在NT/2000/XP中,应用程序可以通过API函数DeviceIoControl来实现对设备的访问—获取信息,发送命令,交换数据等。利用该接口函数向指定的设备驱动发送正确的控制码及数据,然后分析它的响应,就可以达到我们的目的。
DeviceIoControl的函数原型为
BOOL DeviceIoControl(     HANDLE hDevice,              // 设备句柄     DWORD dwIoControlCode,       // 控制码     LPVOID lpInBuffer,           // 输入数据缓冲区指针     DWORD nInBufferSize,         // 输入数据缓冲区长度     LPVOID lpOutBuffer,          // 输出数据缓冲区指针     DWORD nOutBufferSize,        // 输出数据缓冲区长度     LPDWORD lpBytesReturned,     // 输出数据实际长度单元长度     LPOVERLAPPED lpOverlapped    // 重叠操作结构指针 ); 
设备句柄用来标识你所访问的设备。
发送不同的控制码,可以调用设备驱动程序的不同类型的功能。在头文件winioctl.h中,预定义的标准设备控制码,都以IOCTL或FSCTL开头。例如,IOCTL_DISK_GET_DRIVE_GEOMETRY是对物理驱动器取结构参数(介质类型、柱面数、每柱面磁道数、每磁道扇区数等)的控制码,FSCTL_LOCK_VOLUME是对逻辑驱动器的卷加锁的控制码。
输入输出数据缓冲区是否需要,是何种结构,以及占多少字节空间,完全由不同设备的不同操作类型决定。在头文件winioctl.h中,已经为标准设备预定义了一些输入输出数据结构。重叠操作结构指针设置为NULL,DeviceIoControl将进行阻塞调用;否则,应在编程时按异步操作设计。
Q 设备句柄是从哪里获得的?
A 设备句柄可以用API函数CreateFile获得。它的原型为
HANDLE CreateFile(     LPCTSTR lpFileName,                         // 文件名/设备路径     DWORD dwDesiredAccess,                      // 访问方式     DWORD dwShareMode,                          // 共享方式     LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全描述符指针     DWORD dwCreationDisposition,                // 创建方式     DWORD dwFlagsAndAttributes,                 // 文件属性及标志     HANDLE hTemplateFile                        // 模板文件的句柄 ); 
CreateFile这个函数用处很多,这里我们用它“打开”设备驱动程序,得到设备的句柄。操作完成后用CloseHandle关闭设备句柄。
与普通文件名有所不同,设备驱动的“文件名”(常称为“设备路径”)形式固定为“\\.\DeviceName”(注意在C程序中该字符串写法为“\\\\.\\DeviceName”),DeviceName必须与设备驱动程序内定义的设备名称一致。
一般地,调用CreateFile获得设备句柄时,访问方式参数设置为0或GENERIC_READ|GENERIC_WRITE,共享方式参数设置为FILE_SHARE_READ|FILE_SHARE_WRITE,创建方式参数设置为OPEN_EXISTING,其它参数设置为0或NULL。
Q 可是,我怎么知道设备名称是什么呢?
A 一些存储设备的名称是微软定义好的,不可能有什么变化。大体列出如下
软盘驱动器A:, B:
硬盘逻辑分区C:, D:, E:, ...
物理驱动器PHYSICALDRIVEx
CD-ROM, DVD/ROMCDROMx
磁带机TAPEx
其中,物理驱动器不包括软驱和光驱。逻辑驱动器可以是IDE/SCSI/PCMCIA/USB接口的硬盘分区(卷)、光驱、MO、CF卡等,甚至是虚拟盘。x=0,1,2 ……
其它的设备名称需通过驱动接口的GUID调用设备管理函数族取得,这里暂不讨论。
Q 请举一个简单的例子说明如何通过DeviceIoControl访问设备驱动程序。
A 这里有一个从MSDN上摘抄来的demo程序,演示在NT/2000/XP中如何通过DeviceIoControl获取硬盘的基本参数。
/* The code of interest is in the subroutine GetDriveGeometry. The    code in main shows how to interpret the results of the IOCTL call. */    #include  #include     BOOL GetDriveGeometry(DISK_GEOMETRY *pdg) {     HANDLE hDevice;               // handle to the drive to be examined     BOOL bResult;                 // results flag     DWORD junk;                   // discard results        hDevice = CreateFile("\\\\.\\PhysicalDrive0",  // drive to open                     0,                // no access to the drive                     FILE_SHARE_READ | // share mode                     FILE_SHARE_WRITE,                     NULL,             // default security attributes                     OPEN_EXISTING,    // disposition                     0,                // file attributes                     NULL);            // do not copy file attributes        if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive     {         return (FALSE);     }        bResult = DeviceIoControl(hDevice,     // device to be queried         IOCTL_DISK_GET_DRIVE_GEOMETRY,     // operation to perform                     NULL, 0,               // no input buffer                     pdg, sizeof(*pdg),     // output buffer                     &junk,                 // # bytes returned                     (LPOVERLAPPED) NULL);  // synchronous I/O        CloseHandle(hDevice);        return (bResult); }    int main(int argc, char *argv[]) {     DISK_GEOMETRY pdg;            // disk drive geometry structure     BOOL bResult;                 // generic results flag     ULONGLONG DiskSize;           // size of the drive, in bytes        bResult = GetDriveGeometry (&pdg);        if (bResult)     {         printf("Cylinders = %I64d\n", pdg.Cylinders);         printf("Tracks per cylinder = %ld\n", (ULONG) pdg.TracksPerCylinder);         printf("Sectors per track = %ld\n", (ULONG) pdg.SectorsPerTrack);         printf("Bytes per sector = %ld\n", (ULONG) pdg.BytesPerSector);            DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *             (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;         printf("Disk size = %I64d (Bytes) = %I64d (Mb)\n", DiskSize,             DiskSize / (1024 * 1024));     }     else     {         printf("GetDriveGeometry failed. Error %ld.\n", GetLastError());     }        return ((int)bResult); } 
Q 如果将设备名换成“A:”就可以取A盘参数,换成“CDROM0”就可以取CDROM参数,是这样吗?
A 这个问题暂不做回答。请动手试一下。
现在我们总结一下通过DeviceIoControl访问设备驱动程序的“三步曲”:首先用CreateFile取得设备句柄,然后用DeviceIoControl与设备进行I/O,最后别忘记用CloseHandle关闭设备句柄。

2009年4月9日星期四

在文件右键菜单添加项

修改右键菜单应该在注册表中,具体的说,是在HKEY_CLASSES_ROOT根键下(这里可是右键菜单中所有命令的根源哦!)。展开该根键,其下的子键主要有两种:扩展名键(.+扩展名)和类定义键(如图1)。一般地说,只要是在windows系统中已注册过的扩展名,在HKEY_CLASSES_ROOT下均有“·该扩展名”子键 ,记录该扩展名的一些信息,对某种特定类型的文件的右键菜单的修改,便是在该键或“扩展名file”键下的操作。

一、在所有的文件右键菜单中加入命令

如果你的系统上安装有Winzip、UltraEdit等,当你对任一文件点右键时,都会有“Add to zip”、“UltraEdit-32”等命令(当然,Winzip稍有不同,我将在后面讲到)。它的添加方法是:

1.打开“HKEY_CLASSES_ROOT\*”;
2.在其下新建“shell\命令\command”分支,再将command的键值设为执行该命令时所用的可执行程序的绝对路径,并在其后加“%1”即可。

例:在“HKEY_CLASSES_ROOT\*"下新建“shell\Open with SlickEdit 2009\command”子键,将command的键值设为“x:\xxxxx\SlickEdit 2009\win\vs.exe %1”,就会在右键菜单中出现“用写字板打开”的命令了。

说明:
1. 要删除该类命令,只需将“命令”子键删除即可;
2. 有的人或许会问他按我写的去做,但是得到的为何与我的有一些不同,这就是我的命令里有快捷键(N),只要在“Open with SlickEdit 2009”后加入“(&O)”即可。

二、在特定文件类型的右键菜单中加入命令

刚才说到了Winzip这个软件,对普通的文件类型,它的右键菜单中有“Add to zip”,但是对它所支持的压缩文件类型,如*.zip、*.cab、*.rar在其右键菜单中有“Open with Winzip”、“Extract to”、“Extract to folder”、“Create Self-Extractor(.EXE)” 等命令,对于自解压性安装文件(如OICQ99b),其右键菜单中有“Run with Winzip”命令。下面是特定文件类型的右键菜单的命令添加方法(以在mp3文件的右键菜单中加入Play with winamp为例):

1.打开“HKEY_CLASSES_ROOT\mp3_auto_file”主键;
2.在其下新建“shell\Play with Winamp(&P)\command”,将command的键值设为“C:\Program files\winamp\winamp.exe %1” 。

说明:当有多个软件可以播放mp3文件时,我们可以在右键菜单中添加多条命令,如加入“Play with Unreal”等命令,但是我们如何将某一条命令定义为默认操作(即右键菜单中的黑体命令)呢?

你一定会说,很简单的事情吗!将mouse移向一mp3文件,在按右键的同时按shift,在右键菜单中选“打开方式“便可更改,但是这是错误的,不信你试试看,这样只有在右键菜单中选“打开”时才会用你所选择的程序来打开它,否则,它仍旧一如继往。因为它的默认操作不是“打开“这条命令。真正的方法是将shell的默认键值改为你所想执行的命令,例如将shell的键值改为“Winamp”。

2009年4月8日星期三

QXDM-Messages View

HOW DO I OBTAIN THE DEFINITIONS OF EACH DEBUG OR EVENT MESSAGE?
The Messages view displays debug and event messages received by the mobile. (it can also be configured to display log packets and strings). These messages are not specific to QXDM, are used primarily by QUALCOMM for developing ASIC software, change frequently, and are not documented.

Debug Messages (labeled as Message Packets in QXDM) are software-specific printf strings created by the AMSS developer to help debug the AMSS itself. They are not documented beyond the source code itself. There are no QXDM user guides or addendums that define frequently used debug messages.

Event Reports are a debugging mechanism that summarizes activity by the software. The events are not implementation-specific or internal strings like debug messages, but are typically indicators of common, industry standard terms that are easier to understand and follow when compared to debug messages.

QXDM does not generate the messages that are displayed on the Messages view, which is why they are not documented in the QXDM user guide. QXDM only logs or displays the messages as they are provided by the mobile. The software in the test handset provides debug messages to QXDM as part of the MESSAGE RESPONSE MESSAGE (A Diagnostic command response), CMD_CODE(31), and Event Reports as part of the EVENT REPORT MESSAGE (CMD_CODE 96). QXDM does not need to be enhanced or changed to support debug messages for technologies in development. All such devices provide the debug text across the same transport described above, without the need to QXDM at all. Event Reports need a database update, as the Event ID and payload needs to be parsed for the Event Report to have meaning. Event Reports are not ASCII text strings like Debug Messages.

The debug messages consist of fixed text that is determined at compile time by the handset manufacturer. Most of the debug messages are inherited from the ASIC code that QUALCOMM provides to the handset manufactuer, while others are introduced by the handset manufacturer as they develop their product. The messages are used as a diagnostic aid to provide handset software developers with some insight into the behavior of the handset software program. The list of potential debug messages is very extensive, and are constantly changing from build to build. They are used for development purposes only, and will never be documented beyond the source code.

To find the definitions of any particular debug message that is generated from a commercial phone that uses the QUALCOMM chips, we have to refer to the handset manufacturer who modifies the debug messages according to their development needs. In most cases, this information is proprietary and of no real use to anyone else but the handset manufacturer's development teams. Our group does not have access to the manufacturer's source code files, so we cannot offer any additional information. ASIC licensees that have questions about the debug message definitions used in the distributed code can send their requests to "support.cdmatech@qualcomm.com". For debug messages from QCTest and Deployment Products, we can investigate each request for definitions (or, to solve the problem reported) on a case-by-case basis with a binary log sample and problem description provided.

To find the definitions of any particular Event Report, use the QXDM Database Editor, which is included with QXDM and shown in the "QXDM Professional" Windows program group. Select the ITEM/CATEGORY TABLES tab, then select the EVENTS sub-tab. Select or double-click on the Event ID you need a definition for, and the DESCRIPTION FIELD will display. To see enumerated list of variables, select the PARSE/DISPLAY TABLES tab and locate the same Event ID and double-click and press the [VIEW...] button. Then, press [VIEW ENUM...] to see the possible enum entries for that Event ID. This will tell you the possible values for the Event ID's payload.


HOW TO COLLECT A DEBUG MESSAGE AND EVENT REPORT LOG
  • Select FILTERED VIEW (F12)
  • Right click and choose CONFIG
  • Select MESSAGES PACKETS
  • Enable FILTERED/REGISTER ON TARGET FOR ITEMS
  • Select KNOWN MESSAGES
  • Select EVENT REPORTS
  • Enable FILTERED/REGISTER ON TARGET FOR ITEMS
  • Select KNOWN EVENTS
  • Use the FILE->NEW ITEMS to restart logging
  • Use the FILE->SAVE ITEMS to save the logging session

How QXDM Configures the Target for Debug Message Logging

The debug message mechanism in DIAG is extremely broad and covers many systems and subsystems. There are many generations of debug messages that have different filtering capabilities on target. This filtering allows the target to only send the debug messages at a particular level (LOW, MEDIUM, HIGH, ERROR or FATAL, which is coded in the software for each message) and in later versions of debug messages (Extended Debug Messages) have not only levels but subsystem IDs (SSIDs) that allow you to filter messages both level, subsystem or combinations of both). QXDM can control the target to send debug messages based on matching criteria. This configuration is sent by QXDM and obeyed by the target in real time as the debug messages are sent to QXDM for display. Filtering on the QXDM side is essentially the same thing as configuring the target to send according to the level\SSID settings you choose on the MESSAGES VIEW in QXDM.


ONLY ERROR MESSAGES ARE SEEN OR LOGGED
It is entirely possible that the handset manufacturer has only implemented debug messages of ERROR level. The other possibility is that you have filtered out everything lower than the ERROR level in QXDM's Mobile Messages screen. Do this:

  • Select FILTERED VIEW (F12)
  • Right click and choose CONFIG
  • Select MESSAGES PACKETS
  • Enable FILTERED/REGISTER ON TARGET FOR ITEMS
  • Select KNOWN MESSAGES
  • Use the FILE->NEW ITEMS to restart logging
  • Use the FILE->SAVE ITEMS to save the logging session

If you still get only ERROR level messages, then this is a phone software issue. The handset manufaturer has implemented only ERROR level debug messages.


MSG_LEVEL
Legacy Debug Messages have message levels that are set in the source code of the D\AMSS and are used as a maximum level the mobile must provide during a logging session. QXDM allows you to pick and choose for display pleasure only on the Mobile Messages screen, but the logging mechanism still takes the level into account, and the D\AMSS provides everything at the lowest level and above.

Think of them as a filtering mechanism.

The message levels are as follows...

  • NONE (This level disables debug messages entirely)
  • FATAL (This logs FATAL level messages only)
  • ERROR (This logs FATAL and ERROR level messages only)
  • HIGH (This logs FATAL, ERROR and HIGH level messages only)
  • MED (This logs FATAL, ERROR, HIGH and MED level messages only)
  • LOW (This logs FATAL, ERROR, HIGH, MED and LOW level messages)

If you set the message level to HIGH, then you have instructed the phone to only send debug messages that are tagged at compile-time as HIGH, ERROR or FATAL. If you change the message level to LOW, then this tells the phone to send *ALL* debug messages across the serial link (LOW, MED, HIGH, ERROR and FATAL). Again, QXDM can filter out the levels you only want to see on the Messages view, but that is not exactly how the logging mechanism works.

For example, say you have all levels visible on the Messages view, and your phone is constantly providing MED and HIGH level messages. You configure QXDM to display just MED messages. Then, you begin logging. Although you only saw MED level messages in QXDM, the mobile provided MED and above messages across the DIAG link, and all of those were logged. BUT, your configuration of QXDM only displayed the MED ones.

Legacy Debug Messages have been made obsolete by the Extended Debug Messages, which are filterable further by specific subsystem, which makes post-processing and real-time filtering even more powerful and further defined by category.


DROPPED MESSAGES
There is a field in the Message Response Message (which holds the debug messages from the mobile that are displayed on the Mobile Messages screen) called DROP_CNT. The DMSS\AMSS can keep track of how many Debug Messages are dropped between the current message and the previous one. You can see this number on the Mobile Messages screen's status bar. This value is also logged by QXDM in the binary log file. It is a 4-byte value, starting at the 5th byte of the payload.

If the DMSS\AMSS generates the debug messages to fast for the DIAG tool to log, the DMSS\AMSS uses this field to track how many newly arrived messages are dropped.

This counter has nothing to do with other log packets or diagnostic commands.

QXDM only displays the most recently received dropped messages count in the status bar of the Mobile Messages window. There is no flag or indicator on the Mobile Messages screen that indicates when the counter suddenly changes to a non-zero value for a particular message. Furthermore, the contents of the Mobile Messages displays does not have a column for the dropped messages counter, so you cannot pause and scroll back to see what the count was at any particular message's time stamp. However, this can be easily done with a post-processor.


What Does LEGACY Contain?
Legacy category contains all subsystems prior to the creation of SSIDs (Extended Message). It is kept in QXDM for backwards compatibility.


WHAT DOES "KEY PRESSED = (number)" MEAN?
The "Key pressed = 81" appears to be a message generated by the user interface key handler. The number 81 is the decimal ASCII code that represents the key that was pressed. For example, [1] = 49, [2] = 50, [3] = 51, etc. All keys are mapped to specific characters. The Message Response Message also provides the source code filename and line number for each Debug Message.


WHAT DOES "EMPTY PAGE" MEAN?
Empty pages are normal. In slotted paging mode, the mobile wakes up to inspect General Page Messages. Sometimes by reading a GPM, the mobile will know that there are going to be no pages for itself in this slot. That is when this message get printed out to the debug screen. The MORE_PAGES bit tells the mobile if there are more page messages in the same slot. The phone cannot go back to sleep unless it sees the MORE_PAGES = 0, or the slot ends. The empty page message should not be causing the mobile to lose CDMA.



Mobile Station Maintained List
The mobile software's internally maintained lists are typically exposed through the DIAG interface by way of Mobile Debug Messages on the MESSAGES view within QXDM. If the DMSS does not already support debug messages that display this information, or if the handset manufacturer has not implemented them, then it is not possible.
(Example, showing which PN's the mobile has put in it's ACCESS_HO_LIST)

2009年4月7日星期二

用AT命令拨打CS call

有关AT命令的标准协议参见:
3GPP 27007

1. "AT+CREG?" --查询网络注册状态(关于此命令说明见另一篇文章)
2. "AT+CBST"-- Select bearer service type (用途?)
3. "ATDXXXXX;" -- 拨号(XXXXX为号码,在命令最后有一分号)
(拨号之前注意语音功能是否被屏蔽)

关于手动搜索网络(+COPS)超时

发送AT命令+COPS=?进行手动搜网时,整个搜网过程要在2min之内完成,如果在2min之内无法完成,则此次搜索就会abort,+COPS命令返回+CME ERROR: operation not allowed(可用网络列表的长度为-1)

启动定时器代码位置在:
//rrccsp.c
void rrccsp_update_bplmn_srch_vars( wtow_bplmn_srch_status_type status, sys_network_selection_mode_e_type nw_sel_mode)
{
...
rrctmr_start_timer(RRCTMR_BPLMN_GUARD_SRCH_TIMER, RRCTMR_BPLMN_GUARD_SRCH_TIMER_IN_MS);
...
}

RRCTMR_BPLMN_GUARD_SRCH_TIMER定义在:
//rrctmr.h
typedef enum
{
RRCTMR_T_300_TIMER, /* T300 Timer from SIB 1 */
RRCTMR_T_308_TIMER, /* T308 Timer from SIB 1 */
RRCTMR_WAIT_TIME_TIMER, /* Wait Time Timer from RRC Connection Reject
Message */
RRCTMR_UE_TO_CAMP_ON_TIMER, /* Timer for UE to camp on, if not already */
RRCTMR_RRC_CON_DELAY_TIMER, /* Timer for UE to delay RRC Conn Release */
RRCTMR_RCE_L2ACK_TIMER, /* Timer to receive L2 ACK in acknowledged
mode transmission for RCE procedure */
RRCTMR_RCR_L2ACK_TIMER, /* Timer to receive L2 ACK in acknowledged
mode transmission for RCR procedure */
RRCTMR_T_304_TIMER, /* T304 Timer from SIB 1 */
RRCTMR_RSSI_BER_TIMER, /* Timer to periodically report RSSI & BER
to CM */
RRCTMR_SIB_WAIT_TIMER, /* Timer for maximum time to wait for SIBs
in a cell */
RRCTMR_T_302_TIMER, /* T302 timer for CELL UPDATE retransmission */
RRCTMR_T_305_TIMER, /* T305 timer for periodic CELL UPDATE */
RRCTMR_T_316_TIMER, /* T316 Timer for Out of Service Area in
CELL_PCH and URA_PCH state */
RRCTMR_T_317_TIMER, /* T317 Timer for Out of service Area in
CELL_FACH state */
RRCTMR_T_307_TIMER, /* T307 Timer is max time for UE to get into
In Service after T305 is expired */
RRCTMR_T_314_TIMER, /* T314 Re-establish timer */
RRCTMR_T_315_TIMER, /* T315 Re-establish timer */
RRCTMR_SIB7_EXP_TIMER, /* Timer for SIB7 Expiration */
RRCTMR_IGNORE_BCCH_MOD_TIMER, /* Timer to Ignore BCCH Modifcation Info IE
if RRC is already processing one */
RRCTMR_DCH_FACH_CELL_SELECTION_TIMER, /* Timer started during cell selection
going DCH->FACH
*/
#ifdef FEATURE_RRC_FREQ_REDIRECTION_THRU_RB_AND_CU
RRCTMR_FACH_TO_FACH_PCH_CELL_SELECTION_TIMER, /* Timer started during cell selection
going FACH->FACH/PCH
*/
#endif /* FEATURE_RRC_FREQ_REDIRECTION_THRU_RB_AND_CU */
RRCTMR_L1_DEADLOCK_DETECT_TIMER, /* Timer to detect L1 deadlocks */
RRCTMR_DELAY_ERR_FATAL_TIMER, /* Timer to delay ERR_FATAL */
RRCTMR_DCH_PCH_CELL_SELECTION_TIMER, /* Timer started during cell selection
going DCH->CELL_PCH or DCH->URA_PCH*/
RRCTMR_T_3174_TIMER, /* T3174 GTOW PCCO timer */
RRCTMR_FREQ_SCAN_TIMER, /* Timer indicating if FREQ_SCAN should be
initiated or not */
RRCTMR_T_OOS_TIMER, /* Timer indicating if UE can not select a cell
after OOS detection */
RRCTMR_PHY_CHAN_FAILURE_TIMER, /* Phy Chan Failure timer used when initiating Cell Selec when
we get a phy_chan_failure after a rrc conn setup */
RRCTMR_DEEP_SLEEP_NO_SVC_TIMER, /* Time duration for which no service should be
returned to NAS */
RRCTMR_BPLMN_SRCH_TIMER, /* Timer for background PLMN search from 2G->3G */
RRCTMR_BPLMN_FREQ_SCAN_TIMER, /* Timer indicating if FULL FREQ SCAN should be
initiated or not for a 2G->3G BPLMN srch request */
#ifdef FEATURE_MANUAL_SEARCH_FREQ_SCAN_SKIP_TIMER
RRCTMR_MANUAL_PLMN_FREQ_SCAN_TIMER, /* Timer indicating if FULL FREQ SCAN
should be done or not for a Manual PLMN search */
#endif
RRCTMR_FREQ_REDIRECT_WAIT_TIMER, /* Timer for inter frequency redirection */
RRCTMR_CONN_MODE_OOS_TIMER, /* Timer for OOS in Connected Mode */
RRCTMR_WTOW_BPLMN_DRX_SRCH_TIMER, /* Timer for 3G->3G BPLMN DRX tmr expiry*/
RRCTMR_BPLMN_GUARD_SRCH_TIMER /* Max Timer to complete 3G->3G, 2G BPLMN search */

#ifdef FEATURE_INACTIVITY_HANDLING

, RRCTMR_INACTIVITY_TIMER /* Timer for inactivity handling */

#endif /* FEATURE_INTACTIVITY_HANDLING */

#ifdef FEATURE_SIX_HRS_SIB_CLEAN_UP
,RRCTMR_SIXHR_SIB_UPDATE_TIMER /* Timer for six hr sib clean up*/
#endif

#ifdef FEATURE_UMTS_UNIFORM_OOS_HANDLING
, RRCTMR_UNIFORM_OOS_SEARCH_TIMER
#endif

#ifdef FEATURE_DEEP_SLEEP_REL6_OUT_OF_SERVICE_ENHANCEMENT
, RRCTMR_CONN_MODE_OOS_INITIAL_NO_DS_TIMER
, RRCTMR_CONN_MODE_OOS_DS_TIMER
#endif

,RRC_SIB_CHANGE_GUARD_TIMER /* Timer for sib change guard handling */
,RRC_BCCH_MODIFICATION_TIMER /* Timer for BCCH Modification timer handling */

#ifdef FEATURE_MODEM_MBMS
#error code not present
#endif

#ifdef FEATURE_GTOW_REDIRECTION_AFTER_CONN_RELEASE
#error code not present
#endif
}

RRCTMR_BPLMN_GUARD_SRCH_TIMER_IN_MS定义在:
//rrccspi.h
/* Maximum time allowed for completing background PLMN search */
#define RRCTMR_BPLMN_GUARD_SRCH_TIMER_IN_MS 120000UL //ms

RRCTMR_BPLMN_GUARD_SRCH_TIMER定时器的启动和终止:
rrccsp_update_bplmn_srch_vars
{
...
switch(status) {
case WTOW_SEARCH_START:
MSG_HIGH("WTOW: BPLMN srch vars init to start BPLMN search", 0, 0, 0);
...
rrctmr_start_timer(RRCTMR_BPLMN_GUARD_SRCH_TIMER, RRCTMR_BPLMN_GUARD_SRCH_TIMER_IN_MS);
rrc_csp_int_data.bplmn_guard_srch_tmr_expired = FALSE;
...
break;

...

case WTOW_SEARCH_STOP:
case WTOW_SEARCH_ABORT:
MSG_HIGH("WTOW: Aborting/Stopping BPLMN search", 0, 0, 0);
...
if (!rrc_csp_int_data.bplmn_srch_tmr_expired) {
rrctmr_stop_timer(RRCTMR_WTOW_BPLMN_DRX_SRCH_TIMER);
rrc_csp_int_data.bplmn_srch_tmr_expired = TRUE;
}
if (!rrc_csp_int_data.bplmn_guard_srch_tmr_expired) {
rrctmr_stop_timer(RRCTMR_BPLMN_GUARD_SRCH_TIMER);
rrc_csp_int_data.bplmn_guard_srch_tmr_expired = TRUE;
}
...
break;
...
}

在QXDM LOG中查找是否有此定义器超时发生,可以搜索:
expired timer:35
如下所示:
Day 0   00:12:11.504 [4A]       0x1FEB Extended Debug Message         
rrctmr.c        591     H       Expired timer:35           Drop count = 0